diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a2964aca..9f3f22ab 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -22,7 +22,7 @@ When making a PR, please make sure that it follows our style guidelines and good
### Coding style
-Indentations are Allman-style based, 4-space, no tabs.
+Indentations are Allman-style based, 3-space, no tabs.
Space between arguments in function calls, as well as for types.
Example (shortened from ActionHandler.cpp):
@@ -30,34 +30,34 @@ Example (shortened from ActionHandler.cpp):
```cpp
switch( commandId )
{
- case 0x01: // Toggle sheathe
- {
- if ( param11 == 1 )
- pPlayer->setStance( Entity::Actor::Stance::Active );
- else
- {
- pPlayer->setStance( Entity::Actor::Stance::Passive );
- pPlayer->setAutoattack( false );
- }
+ case 0x01: // Toggle sheathe
+ {
+ if ( param11 == 1 )
+ pPlayer->setStance( Entity::Actor::Stance::Active );
+ else
+ {
+ pPlayer->setStance( Entity::Actor::Stance::Passive );
+ pPlayer->setAutoattack( false );
+ }
- pPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), 0, param11, 1 ) );
+ pPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), 0, param11, 1 ) );
- break;
- }
- case 0x03: // Change target
- {
- uint64_t targetId = inPacket.getValAt< uint64_t >( 0x24 );
- pPlayer->changeTarget( targetId );
- break;
- }
- default:
- {
- break;
- }
+ break;
+ }
+ case 0x03: // Change target
+ {
+ uint64_t targetId = inPacket.getValAt< uint64_t >( 0x24 );
+ pPlayer->changeTarget( targetId );
+ break;
+ }
+ default:
+ {
+ break;
+ }
}
```
### Feature implementation
Please make sure edge cases have been tested, behavior is aligned with retail and (if applicable) your queries make sense.
-Any changes to the SQL base should be noted (and reflected in the update.sql file in rootDirectory/sql).
\ No newline at end of file
+Any changes to the SQL base should be noted (and reflected in the update.sql file in rootDirectory/sql).
diff --git a/bin/config/settings_rest.xml b/bin/config/settings_rest.xml
index af0c2fb9..ddadaf67 100644
--- a/bin/config/settings_rest.xml
+++ b/bin/config/settings_rest.xml
@@ -3,15 +3,16 @@
54994
54998
-
+
127.0.0.1
C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv
+
127.0.0.1
-
+
127.0.0.1
-
+
default
80
@@ -28,4 +29,4 @@
255
-
\ No newline at end of file
+
diff --git a/sql/charainfo.sql b/sql/charainfo.sql
index d6570722..4a03dd4a 100644
--- a/sql/charainfo.sql
+++ b/sql/charainfo.sql
@@ -64,7 +64,6 @@ CREATE TABLE `charainfo` (
`HowTo` binary(33) DEFAULT NULL,
`Minions` binary(33) DEFAULT NULL,
`Mounts` binary(13) DEFAULT NULL,
- `Orchestrion` binary(38) DEFAULT NULL,
`EquippedMannequin` int(5) DEFAULT '0',
`ConfigFlags` smallint(5) NOT NULL DEFAULT '0',
`QuestCompleteFlags` binary(200) DEFAULT NULL,
@@ -76,7 +75,7 @@ CREATE TABLE `charainfo` (
`GMRank` int(3) DEFAULT '0',
`Unlocks` binary(64) DEFAULT NULL,
`CFPenaltyUntil` int(11) DEFAULT NULL,
- `UPDATE_DATE` datetime DEFAULT NULL,
+ `UPDATE_DATE` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`CharacterId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/sql/import.bat b/sql/import.bat
index 73359eae..3f9de0e9 100644
--- a/sql/import.bat
+++ b/sql/import.bat
@@ -32,13 +32,13 @@ FOR %%X IN (*.sql) DO (
REM handle update.sql last
) ELSE (
ECHO Importing %%X
- %PATH_MYSQL% %DBNAME% -h %DBADDRESS% -u %USER% < %%X
+ %PATH_MYSQL% %DBNAME% -h %DBADDRESS% -u %USER% %PASSWORD% < %%X
)
)
IF EXIST "update.sql" (
ECHO Importing update.sql
- %PATH_MYSQL% %DBNAME% -h %DBADDRESS% -u %USER% < update.sql
+ %PATH_MYSQL% %DBNAME% -h %DBADDRESS% -u %USER% %PASSWORD% < update.sql
)
ECHO Finished!
diff --git a/sql/update.sql b/sql/update.sql
index 4cd029d7..a2a9c38e 100644
--- a/sql/update.sql
+++ b/sql/update.sql
@@ -38,4 +38,7 @@ ALTER TABLE infolinkshell
MODIFY COLUMN UPDATE_DATE DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
ALTER TABLE uniqueiddata
-MODIFY COLUMN UPDATE_DATE DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
\ No newline at end of file
+MODIFY COLUMN UPDATE_DATE DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
+
+ALTER TABLE charainfo
+ADD `Orchestrion` binary(38) DEFAULT NULL AFTER `Mounts`;
diff --git a/src/servers/Server_Common/Network/GamePacket.h b/src/servers/Server_Common/Network/GamePacket.h
index d98f0316..6fcc584e 100644
--- a/src/servers/Server_Common/Network/GamePacket.h
+++ b/src/servers/Server_Common/Network/GamePacket.h
@@ -45,31 +45,37 @@ public:
template
T getValAt( uint16_t pos ) const
{
- assert(m_segHdr.size > pos);
+ assert( m_segHdr.size > pos );
return *reinterpret_cast< const T* >( &m_dataBuf[0] + pos );
}
void setBytesAt( uint16_t offset, uint8_t * bytes, uint16_t length )
{
- assert(m_segHdr.size > offset);
+ assert( m_segHdr.size > offset );
memcpy( reinterpret_cast< uint8_t* >( &m_dataBuf[0] + offset ), bytes, length );
}
const char * getStringAt( uint16_t pos ) const
{
- assert(m_segHdr.size > pos);
+ assert( m_segHdr.size > pos );
return reinterpret_cast< const char* >( &m_dataBuf[0] + pos );
}
void setStringAt( uint16_t pos, const std::string& str )
{
- assert(m_segHdr.size > pos);
+ assert( m_segHdr.size > pos );
memcpy( reinterpret_cast< uint8_t* >( &m_dataBuf[0] + pos ), str.c_str(), str.length() );
}
- uint8_t * getData()
+ const uint8_t * getData() const
{
- return reinterpret_cast< uint8_t* >( &m_dataBuf[0] );
+ return reinterpret_cast< const uint8_t* >( &m_dataBuf[0] );
+ }
+
+ const uint8_t * getDataAt(uint16_t pos) const
+ {
+ assert( m_segHdr.size > pos );
+ return reinterpret_cast< const uint8_t* >( &m_dataBuf[0] + pos );
}
void setHeader( uint16_t size, uint16_t type, uint32_t id1, uint32_t id2, uint16_t subType, uint32_t unknown = 0xFED2E000 );
diff --git a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h
index 29373409..6df1e762 100644
--- a/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h
+++ b/src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h
@@ -815,7 +815,7 @@ struct FFXIVIpcPlayerStats : FFXIVIpcBasePacket
uint32_t unknown;
uint32_t unknown_1;
uint32_t unknown_2;
- uint32_t parry;
+ uint32_t tenacity;
uint32_t attack;
uint32_t defense;
uint32_t accuracy;
@@ -837,7 +837,11 @@ struct FFXIVIpcPlayerStats : FFXIVIpcBasePacket
uint32_t skillSpeed;
uint32_t spellSpeed1;
uint32_t spellSpeedMod;
- uint32_t unknown_6[5];
+ uint32_t unknown_6;
+ uint32_t craftsmanship;
+ uint32_t control;
+ uint32_t gathering;
+ uint32_t perception;
uint32_t resistanceSlow;
uint32_t resistanceSilence;
uint32_t resistanceBlind;
@@ -846,7 +850,7 @@ struct FFXIVIpcPlayerStats : FFXIVIpcBasePacket
uint32_t resistanceSleep;
uint32_t resistanceBind;
uint32_t resistanceHeavy;
- uint32_t unknown_7[9];
+ uint32_t unknown_7[9]; // possibly level sync stats.
};
/**
@@ -881,10 +885,11 @@ struct FFXIVIpcPlayerStateFlags : FFXIVIpcBasePacket
struct FFXIVIpcPlayerClassInfo : FFXIVIpcBasePacket
{
uint16_t classId;
- uint16_t unknown;
- uint16_t level;
- uint16_t level1;
- uint8_t unknownFields[48];
+ uint8_t unknown;
+ uint8_t isSpecialist;
+ uint16_t level; // Locks actions, equipment, prob more
+ uint16_t level1; // Locks roles, prob more
+ uint32_t roleActions[10];
};
/**
diff --git a/src/servers/Server_REST/SapphireAPI.cpp b/src/servers/Server_REST/SapphireAPI.cpp
index d3181696..5fbc108e 100644
--- a/src/servers/Server_REST/SapphireAPI.cpp
+++ b/src/servers/Server_REST/SapphireAPI.cpp
@@ -200,7 +200,7 @@ void Core::Network::SapphireAPI::deleteCharacter( std::string name, uint32_t acc
g_charaDb.execute( "DELETE FROM charaitemcrystal WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charaiteminventory WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
g_charaDb.execute( "DELETE FROM charaitemgearset WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
- g_charaDb.execute( "DELETE FROM charaquest WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
+ g_charaDb.execute( "DELETE FROM charaquestnew WHERE CharacterId LIKE '" + std::to_string( id ) + "';" );
}
std::vector< Core::PlayerMinimal > Core::Network::SapphireAPI::getCharList( uint32_t accountId )
diff --git a/src/servers/Server_REST/main.cpp b/src/servers/Server_REST/main.cpp
index 8108836d..88500536 100644
--- a/src/servers/Server_REST/main.cpp
+++ b/src/servers/Server_REST/main.cpp
@@ -169,6 +169,575 @@ bool loadSettings( int32_t argc, char* argv[] )
return true;
}
+using ContentType = enum
+{
+ NONE,
+ TEXT_PLAIN,
+ JSON,
+ XML,
+};
+
+std::string buildHttpResponse( uint16_t rCode, const std::string& content = "", ContentType type = NONE )
+{
+ std::string result{""};
+ std::string httpHead{"HTTP/1.1 "};
+ std::string contentHeader{"Content-Length: "};
+ std::string contentTypeHeader{"Content-Type: "};
+
+ switch( type )
+ {
+ case NONE:
+ contentTypeHeader = "";
+ break;
+ case TEXT_PLAIN:
+ contentTypeHeader += "text/plain\r\n";
+ break;
+ case JSON:
+ contentTypeHeader += "application/json\r\n";
+ break;
+ case XML:
+ contentTypeHeader += "text/xml\r\n";
+ break;
+
+ }
+
+ switch( rCode )
+ {
+ case 200:
+ result += httpHead + "200 OK\r\n";
+ if( content.size() > 0 )
+ {
+ result += contentTypeHeader;
+ result += contentHeader + std::to_string( content.size() ) + "\r\n";
+ }
+ break;
+ case 400:
+ case 401:
+ case 402:
+ case 403:
+ result += httpHead + std::to_string( rCode ) + "\r\n";
+ if( content.size() > 0 )
+ {
+ result += contentTypeHeader;
+ result += contentHeader + std::to_string( content.size() ) + "\r\n";
+ }
+ break;
+ case 500:
+ result += httpHead + "500 Internal Server Error\r\n";
+ break;
+ default:
+ result += httpHead + std::to_string( rCode ) + "\r\n";
+
+
+
+
+ }
+ result += "\r\n";
+ if( content.size() > 0 )
+ result += content;
+
+ return result;
+}
+
+void getZoneName( shared_ptr response, shared_ptr request )
+{
+ string number = request->path_match[1];
+ auto it = g_exdData.m_zoneInfoMap.find( atoi( number.c_str() ) );
+ std::string responseStr = "Not found!";
+ if( it != g_exdData.m_zoneInfoMap.end() )
+ responseStr = it->second.zone_name + ", " + it->second.zone_str;
+ *response << buildHttpResponse( 200, responseStr );
+}
+
+void createAccount( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+
+ std::string pass = pt.get( "pass" );
+ std::string user = pt.get( "username" );
+ // reloadConfig();
+
+ std::string sId;
+ if( g_sapphireAPI.createAccount( user, pass, sId ) )
+ {
+ std::string json_string = "{\"sId\":\"" + sId +
+ "\", \"lobbyHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.LobbyHost" ) +
+ "\", \"frontierHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.FrontierHost" ) + "\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ else
+ *response << buildHttpResponse( 400 );
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+}
+
+void login( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+
+ std::string pass = pt.get( "pass" );
+ std::string user = pt.get( "username" );
+
+ std::string sId;
+
+ // reloadConfig();
+ if( g_sapphireAPI.login( user, pass, sId ) )
+ {
+ std::string json_string = "{\"sId\":\"" + sId +
+ "\", \"lobbyHost\":\"" + m_pConfig->getValue< std::string >("Settings.General.LobbyHost") +
+ "\", \"frontierHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.FrontierHost" ) + "\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ else
+ *response << buildHttpResponse( 400 );
+
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+
+}
+
+void deleteCharacter( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+ std::string sId = pt.get( "sId" );
+ std::string secret = pt.get( "secret" );
+ std::string name = pt.get( "name" );
+
+ // reloadConfig();
+
+ int32_t accountId = g_sapphireAPI.checkSession( sId );
+
+ if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret )
+ {
+ std::string json_string = "{\"result\":\"invalid_secret\"}";
+ *response << buildHttpResponse( 403, json_string, JSON );
+ }
+ else
+ {
+ g_sapphireAPI.deleteCharacter( name, accountId );
+ std::string json_string = "{\"result\":\"success\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+
+}
+
+void createCharacter( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+ std::string sId = pt.get( "sId" );
+ std::string secret = pt.get( "secret" );
+ std::string name = pt.get( "name" );
+ std::string infoJson = pt.get( "infoJson" );
+
+ std::string finalJson = Core::Util::base64_decode( infoJson );
+
+ // reloadConfig();
+
+ int32_t result = g_sapphireAPI.checkSession( sId );
+
+ if( result != -1 )
+ {
+ if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret )
+ {
+ std::string json_string = "{\"result\":\"invalid_secret\"}";
+ *response << buildHttpResponse( 403, json_string, JSON );
+ }
+ else
+ {
+ int32_t charId = g_sapphireAPI.createCharacter( result, name, finalJson, m_pConfig->getValue< uint8_t >( "Settings.Parameters.DefaultGMRank", 255 ) );
+
+ std::string json_string = "{\"result\":\"" + std::to_string( charId ) + "\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ else
+ {
+ std::string json_string = "{\"result\":\"invalid\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+
+}
+
+void insertSession( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+ std::string sId = pt.get( "sId" );
+ uint32_t accountId = pt.get( "accountId" );
+ std::string secret = pt.get( "secret" );
+ // reloadConfig();
+ if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret )
+ {
+ std::string json_string = "{\"result\":\"invalid_secret\"}";
+ *response << buildHttpResponse( 403, json_string, JSON );
+ }
+ else
+ {
+ g_sapphireAPI.insertSession( accountId, sId );
+ std::string json_string = "{\"result\":\"success\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+}
+
+void checkNameTaken( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+
+ std::string name = pt.get( "name" );
+ std::string secret = pt.get( "secret" );
+
+ // reloadConfig();
+
+ if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret )
+ {
+ std::string json_string = "{\"result\":\"invalid_secret\"}";
+ *response << buildHttpResponse( 403, json_string, JSON );
+ }
+ else
+ {
+ std::string json_string;
+ if( !g_sapphireAPI.checkNameTaken( name ) )
+ json_string = "{\"result\":\"false\"}";
+ else
+ json_string = "{\"result\":\"true\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+}
+
+void checkSession( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+ std::string sId = pt.get( "sId" );
+ std::string secret = pt.get( "secret" );
+ int32_t result = g_sapphireAPI.checkSession( sId );
+
+ // reloadConfig();
+
+ if( result != -1 )
+ {
+ if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret )
+ {
+ std::string json_string = "{\"result\":\"invalid_secret\"}";
+ *response << buildHttpResponse( 403, json_string, JSON );
+ }
+ else
+ {
+ std::string json_string = "{\"result\":\"" + std::to_string( result ) + "\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ else
+ {
+ std::string json_string = "{\"result\":\"invalid\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+
+}
+
+void getNextCharId( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+ std::string secret = pt.get( "secret" );
+
+ // reloadConfig();
+
+ if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret )
+ {
+ std::string json_string = "{\"result\":\"invalid_secret\"}";
+ *response << buildHttpResponse( 403, json_string, JSON );
+ }
+ else
+ {
+ std::string json_string = "{\"result\":\"" + std::to_string( g_sapphireAPI.getNextCharId() ) + "\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+
+}
+
+void getNextContentId( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+ std::string secret = pt.get( "secret" );
+
+ // reloadConfig();
+
+ if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret )
+ {
+ std::string json_string = "{\"result\":\"invalid_secret\"}";
+ *response << buildHttpResponse( 403, json_string, JSON );
+ }
+ else
+ {
+ std::string json_string = "{\"result\":\"" + std::to_string( g_sapphireAPI.getNextContentId() ) + "\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+
+}
+
+void getCharacterList( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ using namespace boost::property_tree;
+ ptree pt;
+ read_json( request->content, pt );
+ std::string sId = pt.get( "sId" );
+ std::string secret = pt.get( "secret" );
+
+ // reloadConfig();
+
+ int32_t result = g_sapphireAPI.checkSession( sId );
+
+ if( result != -1 )
+ {
+ if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret )
+ {
+ std::string json_string = "{\"result\":\"invalid_secret\"}";
+ *response << buildHttpResponse( 403, json_string, JSON );
+ }
+ else
+ {
+ auto charList = g_sapphireAPI.getCharList( result );
+ using boost::property_tree::ptree;
+ ptree pt;
+ ptree char_tree;
+
+ for( auto entry : charList )
+ {
+ ptree tree_entry;
+ tree_entry.put( "name", std::string( entry.getName() ) );
+ tree_entry.put( "charId", std::to_string( entry.getId() ) );
+ tree_entry.put( "contentId", std::to_string( entry.getContentId() ) );
+ tree_entry.put( "infoJson", std::string( entry.getInfoJson() ) );
+ char_tree.push_back( std::make_pair( "", tree_entry ) );
+ }
+
+ pt.add_child( "charArray", char_tree );
+ pt.put( "result", "success" );
+ std::ostringstream oss;
+ write_json( oss, pt );
+ std::string responseStr = oss.str();
+ *response << buildHttpResponse( 200, responseStr, JSON );
+ }
+ }
+ else
+ {
+ std::string json_string = "{\"result\":\"invalid\"}";
+ *response << buildHttpResponse( 200, json_string, JSON );
+ }
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+}
+
+void get_init( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ auto web_root_path = boost::filesystem::canonical( "web" );
+ auto path = boost::filesystem::canonical( web_root_path / "news.xml" );
+ //Check if path is within web_root_path
+ if( distance( web_root_path.begin(), web_root_path.end() ) > distance( path.begin(), path.end() ) ||
+ !std::equal( web_root_path.begin(), web_root_path.end(), path.begin() ) )
+ throw invalid_argument( "path must be within root path" );
+ if( !( boost::filesystem::exists( path ) && boost::filesystem::is_regular_file( path ) ) )
+ throw invalid_argument( "file does not exist" );
+
+ auto ifs = make_shared();
+ ifs->open( path.string(), ifstream::in | ios::binary | ios::ate );
+
+ if( *ifs )
+ {
+ auto length = ifs->tellg();
+ ifs->seekg( 0, ios::beg );
+
+ *response << "HTTP/1.1 200 OK\r\n" << "Content-Length: " << length << "\r\n\r\n";
+ default_resource_send( server, response, ifs );
+ }
+ else
+ throw invalid_argument( "could not read file" );
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+}
+
+void get_headline_all( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ auto web_root_path = boost::filesystem::canonical( "web" );
+ auto path = boost::filesystem::canonical( web_root_path / "headlines.xml" );
+ //Check if path is within web_root_path
+ if( distance( web_root_path.begin(), web_root_path.end() ) > distance( path.begin(), path.end() ) ||
+ !std::equal( web_root_path.begin(), web_root_path.end(), path.begin() ) )
+ throw invalid_argument( "path must be within root path" );
+ if( !( boost::filesystem::exists( path ) && boost::filesystem::is_regular_file( path ) ) )
+ throw invalid_argument( "file does not exist" );
+
+ auto ifs = make_shared();
+ ifs->open( path.string(), ifstream::in | ios::binary | ios::ate );
+
+ if( *ifs )
+ {
+ auto length = ifs->tellg();
+ ifs->seekg( 0, ios::beg );
+ *response << "HTTP/1.1 200 OK\r\n" << "Content-Length: " << length << "\r\n\r\n";
+ default_resource_send( server, response, ifs );
+ }
+ else
+ throw invalid_argument( "could not read file" );
+ }
+ catch( exception& e )
+ {
+ *response << buildHttpResponse( 500 );
+ g_log.error( e.what() );
+ }
+}
+
+void defaultGet( shared_ptr response, shared_ptr request )
+{
+ print_request_info( request );
+ try
+ {
+ auto web_root_path = boost::filesystem::canonical( "web" );
+ auto path = boost::filesystem::canonical( web_root_path / request->path );
+ //Check if path is within web_root_path
+ if( distance( web_root_path.begin(), web_root_path.end() ) > distance( path.begin(), path.end() ) ||
+ !std::equal( web_root_path.begin(), web_root_path.end(), path.begin() ) )
+ throw invalid_argument( "path must be within root path" );
+ if( boost::filesystem::is_directory( path ) )
+ path /= "index.html";
+ if( !( boost::filesystem::exists( path ) && boost::filesystem::is_regular_file( path ) ) )
+ throw invalid_argument( "file does not exist" );
+
+ auto ifs = make_shared();
+ ifs->open( path.string(), ifstream::in | ios::binary | ios::ate );
+
+ if( *ifs )
+ {
+ auto length = ifs->tellg();
+ ifs->seekg( 0, ios::beg );
+
+ *response << "HTTP/1.1 200 OK\r\n" << "Content-Length: " << length << "\r\n\r\n";
+ default_resource_send( server, response, ifs );
+ }
+ else
+ throw invalid_argument( "could not read file" );
+ }
+ catch( const exception & )
+ {
+ string content = "Path not found: " + request->path;
+ *response << buildHttpResponse( 400, content );
+ }
+}
+
int main( int argc, char* argv[] )
{
g_log.setLogPath( "log\\SapphireAPI" );
@@ -180,550 +749,33 @@ int main( int argc, char* argv[] )
g_log.info( "Compiled: " __DATE__ " " __TIME__ );
g_log.info( "===========================================================" );
- if (!loadSettings(argc, argv))
- {
+ if( !loadSettings( argc, argv ) )
throw std::exception();
- }
g_exdData.loadZoneInfo();
g_exdData.loadClassJobInfo();
server.config.port = stoi( m_pConfig->getValue< std::string >( "Settings.General.HttpPort", "80" ) );
- g_log.info( "Starting REST server at port " + m_pConfig->getValue< std::string >( "Settings.General.HttpPort", "80" ) + "..." );
-
- server.resource["^/ZoneName/([0-9]+)$"]["GET"] = [&]( shared_ptr response, shared_ptr request ) {
- string number = request->path_match[1];
- auto it = g_exdData.m_zoneInfoMap.find( atoi( number.c_str() ) );
- std::string responseStr = "Not found!";
- if( it != g_exdData.m_zoneInfoMap.end() )
- {
- responseStr = it->second.zone_name + ", " + it->second.zone_str;
- }
- *response << "HTTP/1.1 200 OK\r\nContent-Length: " << responseStr.length() << "\r\n\r\n" << responseStr;
- };
-
-
- /* Create account */
- server.resource["^/sapphire-api/lobby/createAccount"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- std::string responseStr = "HTTP/1.1 400\r\n\r\n";
- try
- {
-
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string pass = pt.get( "pass" );
- std::string user = pt.get( "username" );
-
- // reloadConfig();
-
- std::string sId;
- if( g_sapphireAPI.createAccount( user, pass, sId ) )
- {
- std::string json_string = "{\"sId\":\"" + sId + "\", \"lobbyHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.LobbyHost" ) + "\", \"frontierHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.FrontierHost" ) + "\"}";
- *response << "HTTP/1.1 200 OK\r\n "
- << "Content-Type: application/json\r\n"
- << "Content-Length: " << json_string.length() << "\r\n\r\n"
- << json_string;
- }
- else
- *response << "HTTP/1.1 400\r\n\r\n";
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
- *response << "HTTP/1.1 200 OK\r\nContent-Length: " << responseStr.length() << "\r\nContent-Type: text/xml\r\n\r\n" << responseStr;
- };
-
-
- server.resource["^/sapphire-api/lobby/login"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string pass = pt.get( "pass" );
- std::string user = pt.get( "username" );
-
- std::string sId;
-
- // reloadConfig();
-
- if( g_sapphireAPI.login( user, pass, sId ) )
- {
- std::string json_string = "{\"sId\":\"" + sId + "\", \"lobbyHost\":\"" + m_pConfig->getValue< std::string >("Settings.General.LobbyHost") + "\", \"frontierHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.FrontierHost" ) + "\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- *response << "HTTP/1.1 400\r\n\r\n";
-
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^/sapphire-api/lobby/deleteCharacter"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string sId = pt.get( "sId" );
- std::string secret = pt.get( "secret" );
- std::string name = pt.get( "name" );
-
- // reloadConfig();
-
- int32_t accountId = g_sapphireAPI.checkSession( sId );
-
- if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) {
- std::string json_string = "{\"result\":\"invalid_secret\"}";
- *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- {
- g_sapphireAPI.deleteCharacter( name, accountId );
- std::string json_string = "{\"result\":\"success\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^/sapphire-api/lobby/createCharacter"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string sId = pt.get( "sId" );
- std::string secret = pt.get( "secret" );
- std::string name = pt.get( "name" );
- std::string infoJson = pt.get( "infoJson" );
-
- std::string finalJson = Core::Util::base64_decode( infoJson );
-
- // reloadConfig();
-
- int32_t result = g_sapphireAPI.checkSession( sId );
-
- if( result != -1 )
- {
- if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) {
- std::string json_string = "{\"result\":\"invalid_secret\"}";
- *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- {
- int32_t charId = g_sapphireAPI.createCharacter( result, name, finalJson, m_pConfig->getValue< uint8_t >( "Settings.Parameters.DefaultGMRank", 255 ) );
-
- std::string json_string = "{\"result\":\"" + std::to_string( charId ) + "\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- else
- {
- std::string json_string = "{\"result\":\"invalid\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^/sapphire-api/lobby/insertSession"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string sId = pt.get( "sId" );
- uint32_t accountId = pt.get( "accountId" );
- std::string secret = pt.get( "secret" );
-
- // reloadConfig();
-
- if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) {
- std::string json_string = "{\"result\":\"invalid_secret\"}";
- *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- {
- g_sapphireAPI.insertSession( accountId, sId );
- std::string json_string = "{\"result\":\"success\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^/sapphire-api/lobby/checkNameTaken"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string name = pt.get( "name" );
- std::string secret = pt.get( "secret" );
-
- // reloadConfig();
-
- if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) {
- std::string json_string = "{\"result\":\"invalid_secret\"}";
- *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- {
- std::string json_string;
- if( !g_sapphireAPI.checkNameTaken( name ) )
- json_string = "{\"result\":\"false\"}";
- else
- json_string = "{\"result\":\"true\"}";
-
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^/sapphire-api/lobby/checkSession"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string sId = pt.get( "sId" );
- std::string secret = pt.get( "secret" );
-
- int32_t result = g_sapphireAPI.checkSession( sId );
-
- // reloadConfig();
-
- if( result != -1 )
- {
- if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) {
- std::string json_string = "{\"result\":\"invalid_secret\"}";
- *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- {
- std::string json_string = "{\"result\":\"" + std::to_string( result ) + "\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- else
- {
- std::string json_string = "{\"result\":\"invalid\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^/sapphire-api/lobby/getNextCharId"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string secret = pt.get( "secret" );
-
- // reloadConfig();
-
- if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) {
- std::string json_string = "{\"result\":\"invalid_secret\"}";
- *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- {
- std::string json_string = "{\"result\":\"" + std::to_string( g_sapphireAPI.getNextCharId() ) + "\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^/sapphire-api/lobby/getNextContentId"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string secret = pt.get( "secret" );
-
- // reloadConfig();
-
- if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) {
- std::string json_string = "{\"result\":\"invalid_secret\"}";
- *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- {
- std::string json_string = "{\"result\":\"" + std::to_string( g_sapphireAPI.getNextContentId() ) + "\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^/sapphire-api/lobby/getCharacterList"]["POST"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- using namespace boost::property_tree;
- ptree pt;
- read_json( request->content, pt );
-
- std::string sId = pt.get( "sId" );
- std::string secret = pt.get( "secret" );
-
- // reloadConfig();
-
- int32_t result = g_sapphireAPI.checkSession( sId );
-
- if( result != -1 )
- {
-
- if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) {
- std::string json_string = "{\"result\":\"invalid_secret\"}";
- *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- else
- {
- auto charList = g_sapphireAPI.getCharList( result );
- using boost::property_tree::ptree;
- ptree pt;
- ptree char_tree;
-
- for( auto entry : charList )
- {
- ptree tree_entry;
- tree_entry.put( "name", std::string( entry.getName() ) );
- tree_entry.put( "charId", std::to_string( entry.getId() ) );
- tree_entry.put( "contentId", std::to_string( entry.getContentId() ) );
- tree_entry.put( "infoJson", std::string( entry.getInfoJson() ) );
- char_tree.push_back( std::make_pair( "", tree_entry ) );
- }
-
- pt.add_child( "charArray", char_tree );
- pt.put( "result", "success" );
- std::ostringstream oss;
- write_json( oss, pt );
- std::string responseStr = oss.str();
- *response << "HTTP/1.1 200\r\nContent-Length: " << responseStr.length() << "\r\n\r\n" << responseStr;
- }
- }
- else
- {
- std::string json_string = "{\"result\":\"invalid\"}";
- *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;
- }
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^(/frontier-api/ffxivsupport/view/get_init)(.*)"]["GET"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- auto web_root_path = boost::filesystem::canonical( "web" );
- auto path = boost::filesystem::canonical( web_root_path / "news.xml" );
- //Check if path is within web_root_path
- if( distance( web_root_path.begin(), web_root_path.end() ) > distance( path.begin(), path.end() ) ||
- !std::equal( web_root_path.begin(), web_root_path.end(), path.begin() ) )
- throw invalid_argument( "path must be within root path" );
- if( !( boost::filesystem::exists( path ) && boost::filesystem::is_regular_file( path ) ) )
- throw invalid_argument( "file does not exist" );
-
- std::string cache_control, etag;
-
- // Uncomment the following line to enable Cache-Control
- // cache_control="Cache-Control: max-age=86400\r\n";
-
- auto ifs = make_shared();
- ifs->open( path.string(), ifstream::in | ios::binary | ios::ate );
-
- if( *ifs )
- {
- auto length = ifs->tellg();
- ifs->seekg( 0, ios::beg );
-
- *response << "HTTP/1.1 200 OK\r\n" << cache_control << etag << "Content-Length: " << length << "\r\n\r\n";
- default_resource_send( server, response, ifs );
- }
- else
- throw invalid_argument( "could not read file" );
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- server.resource["^(/frontier-api/ffxivsupport/information/get_headline_all)(.*)"]["GET"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- auto web_root_path = boost::filesystem::canonical( "web" );
- auto path = boost::filesystem::canonical( web_root_path / "headlines.xml" );
- //Check if path is within web_root_path
- if( distance( web_root_path.begin(), web_root_path.end() ) > distance( path.begin(), path.end() ) ||
- !std::equal( web_root_path.begin(), web_root_path.end(), path.begin() ) )
- throw invalid_argument( "path must be within root path" );
- if( !( boost::filesystem::exists( path ) && boost::filesystem::is_regular_file( path ) ) )
- throw invalid_argument( "file does not exist" );
-
- std::string cache_control, etag;
-
- // Uncomment the following line to enable Cache-Control
- // cache_control="Cache-Control: max-age=86400\r\n";
-
- auto ifs = make_shared();
- ifs->open( path.string(), ifstream::in | ios::binary | ios::ate );
-
- if( *ifs )
- {
- auto length = ifs->tellg();
- ifs->seekg( 0, ios::beg );
-
- *response << "HTTP/1.1 200 OK\r\n" << cache_control << etag << "Content-Length: " << length << "\r\n\r\n";
- default_resource_send( server, response, ifs );
- }
- else
- throw invalid_argument( "could not read file" );
- }
- catch( exception& e )
- {
- *response << "HTTP/1.1 500\r\n\r\n";
- g_log.error( e.what() );
- }
-
- };
-
- //Default GET-example. If no other matches, this anonymous function will be called.
- //Will respond with content in the web/-directory, and its subdirectories.
- //Default file: index.html
- //Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
- server.default_resource["GET"] = [&]( shared_ptr response, shared_ptr request ) {
- print_request_info( request );
-
- try
- {
- auto web_root_path = boost::filesystem::canonical( "web" );
- auto path = boost::filesystem::canonical( web_root_path / request->path );
- //Check if path is within web_root_path
- if( distance( web_root_path.begin(), web_root_path.end() ) > distance( path.begin(), path.end() ) ||
- !std::equal( web_root_path.begin(), web_root_path.end(), path.begin() ) )
- throw invalid_argument( "path must be within root path" );
- if( boost::filesystem::is_directory( path ) )
- path /= "index.html";
- if( !( boost::filesystem::exists( path ) && boost::filesystem::is_regular_file( path ) ) )
- throw invalid_argument( "file does not exist" );
-
- std::string cache_control, etag;
-
- // Uncomment the following line to enable Cache-Control
- // cache_control="Cache-Control: max-age=86400\r\n";
-
- auto ifs = make_shared();
- ifs->open( path.string(), ifstream::in | ios::binary | ios::ate );
-
- if( *ifs )
- {
- auto length = ifs->tellg();
- ifs->seekg( 0, ios::beg );
-
- *response << "HTTP/1.1 200 OK\r\n" << cache_control << etag << "Content-Length: " << length << "\r\n\r\n";
- default_resource_send( server, response, ifs );
- }
- else
- throw invalid_argument( "could not read file" );
- }
- catch( const exception & )
- {
- string content = "Path not found: " + request->path;
- *response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
- }
- };
-
- thread server_thread( [&]() {
+ g_log.info( "Starting API server at port " + m_pConfig->getValue< std::string >( "Settings.General.HttpPort", "80" ) + "..." );
+
+ server.resource["^/ZoneName/([0-9]+)$"]["GET"] = &getZoneName;
+ server.resource["^/sapphire-api/lobby/createAccount"]["POST"] = &createAccount;
+ server.resource["^/sapphire-api/lobby/login"]["POST"] = &login;
+ server.resource["^/sapphire-api/lobby/deleteCharacter"]["POST"] = &deleteCharacter;
+ server.resource["^/sapphire-api/lobby/createCharacter"]["POST"] = &createCharacter;
+ server.resource["^/sapphire-api/lobby/insertSession"]["POST"] = &insertSession;
+ server.resource["^/sapphire-api/lobby/checkNameTaken"]["POST"] = &checkNameTaken;
+ server.resource["^/sapphire-api/lobby/checkSession"]["POST"] = &checkSession;
+ server.resource["^/sapphire-api/lobby/getNextCharId"]["POST"] = &getNextCharId;
+ server.resource["^/sapphire-api/lobby/getNextContentId"]["POST"] = &getNextContentId;
+ server.resource["^/sapphire-api/lobby/getCharacterList"]["POST"] = &getCharacterList;
+ server.resource["^(/frontier-api/ffxivsupport/view/get_init)(.*)"]["GET"] = &get_init;
+ server.resource["^(/frontier-api/ffxivsupport/information/get_headline_all)(.*)"]["GET"] = &get_headline_all;
+
+ server.default_resource["GET"] = &defaultGet;
+
+ thread server_thread( [&]()
+ {
//Start server
server.start();
} );
@@ -732,8 +784,6 @@ int main( int argc, char* argv[] )
this_thread::sleep_for( chrono::seconds( 1 ) );
server_thread.join();
- g_log.info( "Started REST server at port " + std::to_string( server.config.port ) );
-
return 0;
}
diff --git a/src/servers/Server_Zone/Action/Action.cpp b/src/servers/Server_Zone/Action/Action.cpp
index 21e09e0a..1405f45a 100644
--- a/src/servers/Server_Zone/Action/Action.cpp
+++ b/src/servers/Server_Zone/Action/Action.cpp
@@ -1,6 +1,6 @@
#include "Action.h"
-#include
+#include
Core::Action::Action::Action()
diff --git a/src/servers/Server_Zone/Action/Action.h b/src/servers/Server_Zone/Action/Action.h
index 9e0e79b6..3c270180 100644
--- a/src/servers/Server_Zone/Action/Action.h
+++ b/src/servers/Server_Zone/Action/Action.h
@@ -1,8 +1,8 @@
#ifndef _ACTION_H_
#define _ACTION_H_
-#include
-#include "src/servers/Server_Zone/Forwards.h"
+#include
+#include "../Forwards.h"
namespace Core { namespace Action {
@@ -57,4 +57,4 @@ namespace Core { namespace Action {
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/servers/Server_Zone/Action/ActionCast.cpp b/src/servers/Server_Zone/Action/ActionCast.cpp
index b9fcbcd2..7fc79ea3 100644
--- a/src/servers/Server_Zone/Action/ActionCast.cpp
+++ b/src/servers/Server_Zone/Action/ActionCast.cpp
@@ -1,16 +1,16 @@
#include "ActionCast.h"
-#include
-#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
+#include
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket144.h"
-#include "src/servers/Server_Zone/Actor/Player.h"
-#include "src/servers/Server_Zone/Script/ScriptManager.h"
+#include "Network/PacketWrappers/ActorControlPacket142.h"
+#include "Network/PacketWrappers/ActorControlPacket143.h"
+#include "Network/PacketWrappers/ActorControlPacket144.h"
+#include "Actor/Player.h"
+#include "Script/ScriptManager.h"
using namespace Core::Common;
using namespace Core::Network;
@@ -52,7 +52,8 @@ void Core::Action::ActionCast::onStart()
castPacket.data().action_id = m_id;
castPacket.data().skillType = Common::SkillType::Normal;
castPacket.data().unknown_1 = m_id;
- castPacket.data().cast_time = static_cast< float >( m_castTime / 1000 ); // This is used for the cast bar above the target bar of the caster.
+ // This is used for the cast bar above the target bar of the caster.
+ castPacket.data().cast_time = static_cast< float >( m_castTime / 1000 );
castPacket.data().target_id = m_pTarget->getId();
m_pSource->sendToInRangeSet( castPacket, true );
@@ -73,10 +74,10 @@ void Core::Action::ActionCast::onFinish()
pPlayer->sendStateFlags();
/*auto control = ActorControlPacket143( m_pTarget->getId(), ActorControlType::Unk7,
- 0x219, m_id, m_id, m_id, m_id );
+ 0x219, m_id, m_id, m_id, m_id );
m_pSource->sendToInRangeSet( control, true );*/
- g_scriptMgr.onCastFinish( pPlayer, m_pTarget, m_id );
+ g_scriptMgr.onCastFinish( *pPlayer, m_pTarget, m_id );
}
void Core::Action::ActionCast::onInterrupt()
@@ -89,7 +90,7 @@ void Core::Action::ActionCast::onInterrupt()
m_pSource->getAsPlayer()->sendStateFlags();
auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt,
- 0x219, 1, m_id, 0 );
+ 0x219, 1, m_id, 0 );
// Note: When cast interrupt from taking too much damage, set the last value to 1. This enables the cast interrupt effect. Example:
// auto control = ActorControlPacket142( m_pSource->getId(), ActorControlType::CastInterrupt, 0x219, 1, m_id, 0 );
diff --git a/src/servers/Server_Zone/Action/ActionCast.h b/src/servers/Server_Zone/Action/ActionCast.h
index 897ad7c1..b656b391 100644
--- a/src/servers/Server_Zone/Action/ActionCast.h
+++ b/src/servers/Server_Zone/Action/ActionCast.h
@@ -1,10 +1,11 @@
#ifndef _ACTIONCAST_H_
#define _ACTIONCAST_H_
-#include "src/servers/Server_Zone/Forwards.h"
+#include "../Forwards.h"
#include "Action.h"
-namespace Core { namespace Action {
+namespace Core {
+namespace Action {
class ActionCast : public Action
{
@@ -25,4 +26,4 @@ namespace Core { namespace Action {
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/servers/Server_Zone/Action/ActionCollision.cpp b/src/servers/Server_Zone/Action/ActionCollision.cpp
index bfae7a60..6eb11182 100644
--- a/src/servers/Server_Zone/Action/ActionCollision.cpp
+++ b/src/servers/Server_Zone/Action/ActionCollision.cpp
@@ -1,10 +1,11 @@
-#include
-#include
-#include
+#include
+#include
+#include
#include "ActionCollision.h"
-#include
-#include
+#include "Actor/Actor.h"
+#include "Actor/Player.h"
+
#include
#include
@@ -16,7 +17,7 @@ using namespace Core::Common;
bool ActionCollision::isActorApplicable( ActorPtr actorPtr, TargetFilter targetFilter )
{
bool actorApplicable = false;
- switch ( targetFilter )
+ switch( targetFilter )
{
case TargetFilter::All:
{
@@ -57,14 +58,14 @@ std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXI
{
std::set< ActorPtr > actorsCollided;
- switch ( static_cast< ActionCollisionType >( actionInfo->aoe_type ) )
+ switch( static_cast< ActionCollisionType >( actionInfo->aoe_type ) )
{
case ActionCollisionType::None:
case ActionCollisionType::SingleTarget:
{
// This is actually needed. There is "splash damage" in actions marked as single target.
// Notice how we're using aoe_width. How collision works for SingleTarget is unknown as of now.
- for ( auto pActor : actorsInRange )
+ for( auto pActor : actorsInRange )
{
// Make sure actor exists. If it doesn't we done goofed.
assert( pActor );
@@ -84,7 +85,7 @@ std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXI
}
case ActionCollisionType::Circle:
{
- for ( auto pActor : actorsInRange )
+ for( auto pActor : actorsInRange )
{
assert( pActor );
@@ -92,15 +93,13 @@ std::set< Core::Entity::ActorPtr > ActionCollision::getActorsHitFromAction( FFXI
continue;
if ( radiusCollision( pActor->getPos(), aoePosition, actionInfo->aoe_range ) )
- {
actorsCollided.insert( pActor );
- }
}
break;
}
case ActionCollisionType::Box:
{
- for ( auto pActor : actorsInRange )
+ for( auto pActor : actorsInRange )
{
assert( pActor );
@@ -137,4 +136,4 @@ bool ActionCollision::boxCollision( FFXIVARR_POSITION3 actorPosition, FFXIVARR_P
actorPosition.x > aoePosition.x &&
actorPosition.y < aoePosition.y + height &&
actorPosition.y > aoePosition.y;
-}
\ No newline at end of file
+}
diff --git a/src/servers/Server_Zone/Action/ActionCollision.h b/src/servers/Server_Zone/Action/ActionCollision.h
index 05ec923e..db3f7120 100644
--- a/src/servers/Server_Zone/Action/ActionCollision.h
+++ b/src/servers/Server_Zone/Action/ActionCollision.h
@@ -1,43 +1,43 @@
#ifndef _ACTIONCOLLISION_H
#define _ACTIONCOLLISION_H
-#include
+#include
-#include
+#include "Actor/Actor.h"
#include "Action.h"
namespace Core {
- namespace Entity {
+namespace Entity {
- enum class TargetFilter
- {
- All, // All actors in the AoE are applicable for collision
- Players, // Only players
- Allies, // Only allies (players, ally NPCs)
- Party, // Only party members
- Enemies // Only enemies
- };
+ enum class TargetFilter
+ {
+ All, // All actors in the AoE are applicable for collision
+ Players, // Only players
+ Allies, // Only allies (players, ally NPCs)
+ Party, // Only party members
+ Enemies // Only enemies
+ };
- class ActionCollision
- {
- public:
+ class ActionCollision
+ {
+ public:
- static bool isActorApplicable( ActorPtr actorPtr, TargetFilter targetFilter );
- static std::set< ActorPtr > getActorsHitFromAction( Common::FFXIVARR_POSITION3 aoePosition,
- std::set< ActorPtr > actorsInRange,
- boost::shared_ptr< Data::ActionInfo > actionInfo,
- TargetFilter targetFilter );
-
- private:
- static bool radiusCollision( Common::FFXIVARR_POSITION3 actorPosition, Common::FFXIVARR_POSITION3 aoePosition,
- uint16_t radius );
+ static bool isActorApplicable( ActorPtr actorPtr, TargetFilter targetFilter );
+ static std::set< ActorPtr > getActorsHitFromAction( Common::FFXIVARR_POSITION3 aoePosition,
+ std::set< ActorPtr > actorsInRange,
+ boost::shared_ptr< Data::ActionInfo > actionInfo,
+ TargetFilter targetFilter );
- static bool boxCollision( Common::FFXIVARR_POSITION3 actorPosition, Common::FFXIVARR_POSITION3 aoePosition,
- uint16_t width, uint16_t height );
-
- };
+ private:
+ static bool radiusCollision( Common::FFXIVARR_POSITION3 actorPosition, Common::FFXIVARR_POSITION3 aoePosition,
+ uint16_t radius );
- }
+ static bool boxCollision( Common::FFXIVARR_POSITION3 actorPosition, Common::FFXIVARR_POSITION3 aoePosition,
+ uint16_t width, uint16_t height );
+
+ };
+
+}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/servers/Server_Zone/Action/ActionMount.cpp b/src/servers/Server_Zone/Action/ActionMount.cpp
index 26c7cddd..b45b460f 100644
--- a/src/servers/Server_Zone/Action/ActionMount.cpp
+++ b/src/servers/Server_Zone/Action/ActionMount.cpp
@@ -1,16 +1,16 @@
#include "ActionMount.h"
-#include
-#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
+#include
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket144.h"
-#include "src/servers/Server_Zone/Actor/Player.h"
-#include "src/servers/Server_Zone/Script/ScriptManager.h"
+#include "Network/PacketWrappers/ActorControlPacket142.h"
+#include "Network/PacketWrappers/ActorControlPacket143.h"
+#include "Network/PacketWrappers/ActorControlPacket144.h"
+#include "Actor/Player.h"
+#include "Script/ScriptManager.h"
using namespace Core::Common;
using namespace Core::Network;
@@ -23,7 +23,7 @@ extern Core::Scripting::ScriptManager g_scriptMgr;
Core::Action::ActionMount::ActionMount()
{
- m_handleActionType = Common::HandleActionType::Event;
+ m_handleActionType = HandleActionType::Event;
}
Core::Action::ActionMount::ActionMount( Entity::ActorPtr pActor, uint16_t mountId )
@@ -75,19 +75,20 @@ void Core::Action::ActionMount::onFinish()
pPlayer->unsetStateFlag( PlayerStateFlag::Casting );
pPlayer->sendStateFlags();
- ZoneChannelPacket< FFXIVIpcEffect > effectPacket(pPlayer->getId());
+ ZoneChannelPacket< FFXIVIpcEffect > effectPacket( pPlayer->getId() );
effectPacket.data().targetId = pPlayer->getId();
effectPacket.data().actionAnimationId = m_id;
- effectPacket.data().unknown_62 = 13; // Affects displaying action name next to number in floating text
+ // Affects displaying action name next to number in floating text
+ effectPacket.data().unknown_62 = 13;
effectPacket.data().actionTextId = 4;
effectPacket.data().numEffects = 1;
- effectPacket.data().rotation = Math::Util::floatToUInt16Rot(pPlayer->getRotation());
+ effectPacket.data().rotation = Math::Util::floatToUInt16Rot( pPlayer->getRotation() );
effectPacket.data().effectTarget = INVALID_GAME_OBJECT_ID;
effectPacket.data().effects[0].effectType = ActionEffectType::Mount;
effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::CritDamage;
effectPacket.data().effects[0].value = m_id;
- pPlayer->sendToInRangeSet(effectPacket, true);
+ pPlayer->sendToInRangeSet( effectPacket, true );
pPlayer->mount( m_id );
}
diff --git a/src/servers/Server_Zone/Action/ActionMount.h b/src/servers/Server_Zone/Action/ActionMount.h
index 6c970869..ba32817d 100644
--- a/src/servers/Server_Zone/Action/ActionMount.h
+++ b/src/servers/Server_Zone/Action/ActionMount.h
@@ -1,10 +1,11 @@
#ifndef _ACTIONMOUNT_H_
#define _ACTIONMOUNT_H_
-#include "src/servers/Server_Zone/Forwards.h"
+#include "../Forwards.h"
#include "Action.h"
-namespace Core { namespace Action {
+namespace Core {
+namespace Action {
class ActionMount : public Action
{
@@ -25,4 +26,4 @@ namespace Core { namespace Action {
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/servers/Server_Zone/Action/ActionTeleport.cpp b/src/servers/Server_Zone/Action/ActionTeleport.cpp
index 37ebbfbd..c201b0cc 100644
--- a/src/servers/Server_Zone/Action/ActionTeleport.cpp
+++ b/src/servers/Server_Zone/Action/ActionTeleport.cpp
@@ -1,12 +1,12 @@
#include "ActionTeleport.h"
-#include
-#include
-#include
+#include
+#include
+#include
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
-#include "src/servers/Server_Zone/Actor/Player.h"
+#include "Network/PacketWrappers/ActorControlPacket142.h"
+#include "Network/PacketWrappers/ActorControlPacket143.h"
+#include "Actor/Player.h"
using namespace Core::Common;
using namespace Core::Network;
@@ -18,7 +18,7 @@ extern Core::Logger g_log;
Core::Action::ActionTeleport::ActionTeleport()
{
- m_handleActionType = Common::HandleActionType::Event;
+ m_handleActionType = HandleActionType::Event;
}
Core::Action::ActionTeleport::ActionTeleport( Entity::ActorPtr pActor, uint16_t targetZone, uint16_t cost )
@@ -81,7 +81,7 @@ void Core::Action::ActionTeleport::onFinish()
//auto control = Network::Packets::Server::ActorControlPacket142( m_pSource->getId(), Common::ActorControlType::TeleportDone );
//m_pSource->sendToInRangeSet( control, false );
- pPlayer->setZoningType( Common::ZoneingType::Teleport );
+ pPlayer->setZoningType( ZoneingType::Teleport );
ZoneChannelPacket< FFXIVIpcEffect > effectPacket( pPlayer->getId() );
effectPacket.data().targetId = pPlayer->getId();
@@ -90,7 +90,7 @@ void Core::Action::ActionTeleport::onFinish()
effectPacket.data().actionTextId = 5;
effectPacket.data().unknown_5 = 1;
effectPacket.data().numEffects = 1;
- effectPacket.data().rotation = static_cast< uint16_t >( 0x8000 * ( (pPlayer->getRotation() + 3.1415926) ) / 3.1415926 );
+ effectPacket.data().rotation = static_cast< uint16_t >( 0x8000 * ( ( pPlayer->getRotation() + 3.1415926 ) ) / 3.1415926 );
effectPacket.data().effectTarget = pPlayer->getId();
pPlayer->sendToInRangeSet( effectPacket, true );
diff --git a/src/servers/Server_Zone/Action/ActionTeleport.h b/src/servers/Server_Zone/Action/ActionTeleport.h
index 8cb83ec1..480090eb 100644
--- a/src/servers/Server_Zone/Action/ActionTeleport.h
+++ b/src/servers/Server_Zone/Action/ActionTeleport.h
@@ -1,10 +1,11 @@
#ifndef _ACTIONTELEPORT_H_
#define _ACTIONTELEPORT_H_
-#include "src/servers/Server_Zone/Forwards.h"
+#include "../Forwards.h"
#include "Action.h"
-namespace Core { namespace Action {
+namespace Core {
+namespace Action {
class ActionTeleport : public Action
{
@@ -27,4 +28,4 @@ namespace Core { namespace Action {
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/servers/Server_Zone/Action/EventAction.cpp b/src/servers/Server_Zone/Action/EventAction.cpp
index 00116ed4..5e6a9cf3 100644
--- a/src/servers/Server_Zone/Action/EventAction.cpp
+++ b/src/servers/Server_Zone/Action/EventAction.cpp
@@ -1,12 +1,12 @@
-#include
-#include
-#include
+#include
+#include
+#include
#include "EventAction.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
-#include "src/servers/Server_Zone/Actor/Player.h"
-#include "src/servers/Server_Zone/Event/Event.h"
+#include "Network/PacketWrappers/ActorControlPacket142.h"
+#include "Network/PacketWrappers/ActorControlPacket143.h"
+#include "Server_Zone/Actor/Player.h"
+#include "Server_Zone/Event/Event.h"
extern Core::Logger g_log;
extern Core::Data::ExdData g_exdData;
@@ -18,7 +18,7 @@ using namespace Core::Network::Packets::Server;
Core::Action::EventAction::EventAction()
{
- m_handleActionType = Common::HandleActionType::Event;
+ m_handleActionType = HandleActionType::Event;
}
Core::Action::EventAction::EventAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action,
@@ -75,7 +75,6 @@ void Core::Action::EventAction::onFinish()
m_onActionFinishClb( *m_pSource->getAsPlayer(), m_eventId, m_additional );
auto control = ActorControlPacket142( m_pSource->getId(), Common::ActorControlType::CastStart, 0, m_id );
-
if( !pEvent->hasPlayedScene() )
m_pSource->getAsPlayer()->eventFinish( m_eventId, 1 );
diff --git a/src/servers/Server_Zone/Action/EventAction.h b/src/servers/Server_Zone/Action/EventAction.h
index 038d9c99..6f8e5614 100644
--- a/src/servers/Server_Zone/Action/EventAction.h
+++ b/src/servers/Server_Zone/Action/EventAction.h
@@ -1,12 +1,13 @@
#ifndef _EVENTACTION_H_
#define _EVENTACTION_H_
-#include
+#include
-#include "src/servers/Server_Zone/Forwards.h"
-#include "src/servers/Server_Zone/Action/Action.h"
+#include "../Forwards.h"
+#include "Action.h"
-namespace Core { namespace Action {
+namespace Core {
+namespace Action {
class EventAction : public Action
{
@@ -34,4 +35,4 @@ namespace Core { namespace Action {
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/servers/Server_Zone/Action/EventItemAction.cpp b/src/servers/Server_Zone/Action/EventItemAction.cpp
index 567f689c..6c85b183 100644
--- a/src/servers/Server_Zone/Action/EventItemAction.cpp
+++ b/src/servers/Server_Zone/Action/EventItemAction.cpp
@@ -1,14 +1,14 @@
#include "EventItemAction.h"
-#include
-#include
-#include
+#include
+#include
+#include
#include
-#include "src/servers/Server_Zone/Actor/Player.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
+#include "Actor/Player.h"
+#include "Network/PacketWrappers/ActorControlPacket142.h"
+#include "Network/PacketWrappers/ActorControlPacket143.h"
extern Core::Logger g_log;
@@ -19,7 +19,7 @@ using namespace Core::Network::Packets::Server;
Core::Action::EventItemAction::EventItemAction()
{
- m_handleActionType = Common::HandleActionType::Event;
+ m_handleActionType = HandleActionType::Event;
}
Core::Action::EventItemAction::EventItemAction( Entity::ActorPtr pActor, uint32_t eventId, uint16_t action,
diff --git a/src/servers/Server_Zone/Action/EventItemAction.h b/src/servers/Server_Zone/Action/EventItemAction.h
index 71bc5e89..bd9eee9d 100644
--- a/src/servers/Server_Zone/Action/EventItemAction.h
+++ b/src/servers/Server_Zone/Action/EventItemAction.h
@@ -1,10 +1,11 @@
#ifndef _EVENTITEMACTION_H_
#define _EVENTITEMACTION_H_
-#include "src/servers/Server_Zone/Forwards.h"
-#include "src/servers/Server_Zone/Action/Action.h"
+#include "../Forwards.h"
+#include "Action.h"
-namespace Core { namespace Action {
+namespace Core {
+namespace Action {
class EventItemAction : public Action
{
@@ -32,4 +33,4 @@ namespace Core { namespace Action {
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/servers/Server_Zone/Actor/Actor.cpp b/src/servers/Server_Zone/Actor/Actor.cpp
index a137618c..3439fef7 100644
--- a/src/servers/Server_Zone/Actor/Actor.cpp
+++ b/src/servers/Server_Zone/Actor/Actor.cpp
@@ -1,26 +1,25 @@
-#include
-#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
+#include
-#include "src/servers/Server_Zone/Forwards.h"
-#include "src/servers/Server_Zone/Action/Action.h"
+#include "Forwards.h"
+#include "Action/Action.h"
-#include "src/servers/Server_Zone/Zone/Zone.h"
+#include "Zone/Zone.h"
-#include "src/servers/Server_Zone/Network/GameConnection.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket142.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket143.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/ActorControlPacket144.h"
-#include "src/servers/Server_Zone/Network/PacketWrappers/UpdateHpMpTpPacket.h"
+#include "Network/GameConnection.h"
+#include "Network/PacketWrappers/ActorControlPacket142.h"
+#include "Network/PacketWrappers/ActorControlPacket143.h"
+#include "Network/PacketWrappers/ActorControlPacket144.h"
+#include "Network/PacketWrappers/UpdateHpMpTpPacket.h"
-#include "src/servers/Server_Zone/StatusEffect/StatusEffectContainer.h"
-#include "src/servers/Server_Zone/StatusEffect/StatusEffect.h"
-#include "src/servers/Server_Zone/Action/ActionCollision.h"
-#include "src/servers/Server_Zone/ServerZone.h"
-#include "src/servers/Server_Zone/Session.h"
-#include "src/servers/Server_Zone/Math/CalcBattle.h"
+#include "StatusEffect/StatusEffect.h"
+#include "Action/ActionCollision.h"
+#include "ServerZone.h"
+#include "Session.h"
+#include "Math/CalcBattle.h"
#include "Actor.h"
#include "Player.h"
@@ -33,6 +32,11 @@ using namespace Core::Network::Packets::Server;
Core::Entity::Actor::Actor()
{
+ // initialize the free slot queue
+ for( uint8_t i = 0; i < MAX_STATUS_EFFECTS; i++ )
+ {
+ m_statusEffectFreeSlotQueue.push( i );
+ }
}
Core::Entity::Actor::~Actor()
@@ -660,7 +664,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
uint64_t param2, Entity::Actor& pTarget )
{
- if ( isPlayer() )
+ if( isPlayer() )
{
getAsPlayer()->sendDebug( std::to_string( pTarget.getId() ) );
getAsPlayer()->sendDebug( "Handle script skill type: " + std::to_string( type ) );
@@ -682,7 +686,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
effectPacket.data().effectTarget = pTarget.getId();
// Todo: for each actor, calculate how much damage the calculated value should deal to them - 2-step damage calc. we only have 1-step
- switch ( type )
+ switch( type )
{
case ActionEffectType::Damage:
@@ -692,7 +696,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalDamage;
effectPacket.data().effects[0].unknown_3 = 7;
- if ( !actionInfoPtr->is_aoe )
+ if( !actionInfoPtr->is_aoe )
{
// If action on this specific target is valid...
if ( isPlayer() && !ActionCollision::isActorApplicable( pTarget.shared_from_this(), TargetFilter::Enemies ) )
@@ -700,11 +704,11 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
sendToInRangeSet( effectPacket, true );
- pTarget.takeDamage( static_cast< uint32_t >( param1 ) );
-
if ( pTarget.isAlive() )
pTarget.onActionHostile( shared_from_this() );
-
+
+ pTarget.takeDamage( static_cast< uint32_t >( param1 ) );
+
}
else
{
@@ -712,7 +716,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
auto actorsCollided = ActionCollision::getActorsHitFromAction( pTarget.getPos(), getInRangeActors( true ),
actionInfoPtr, TargetFilter::Enemies );
- for ( const auto& pHitActor : actorsCollided )
+ for( const auto& pHitActor : actorsCollided )
{
effectPacket.data().targetId = pHitActor->getId();
effectPacket.data().effectTarget = pHitActor->getId();
@@ -720,17 +724,17 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
// todo: send to range of what? ourselves? when mob script hits this is going to be lacking
sendToInRangeSet( effectPacket, true );
- pHitActor->takeDamage( static_cast< uint32_t >( param1 ) );
if( pHitActor->isAlive() )
pHitActor->onActionHostile( shared_from_this() );
+ pHitActor->takeDamage( static_cast< uint32_t >( param1 ) );
+
// Debug
if ( isPlayer() )
{
- if ( pHitActor->isPlayer() ) {
+ if ( pHitActor->isPlayer() )
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) + " (" + pHitActor->getName() + ")" );
- }
else
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) );
}
@@ -748,9 +752,9 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
effectPacket.data().effects[0].effectType = ActionEffectType::Heal;
effectPacket.data().effects[0].hitSeverity = ActionHitSeverityType::NormalHeal;
- if ( !actionInfoPtr->is_aoe )
+ if( !actionInfoPtr->is_aoe )
{
- if ( isPlayer() && !ActionCollision::isActorApplicable( pTarget.shared_from_this(), TargetFilter::Allies ) )
+ if( isPlayer() && !ActionCollision::isActorApplicable( pTarget.shared_from_this(), TargetFilter::Allies ) )
break;
sendToInRangeSet( effectPacket, true );
@@ -764,7 +768,7 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
auto actorsCollided = ActionCollision::getActorsHitFromAction( pTarget.getPos(), getInRangeActors( true ),
actionInfoPtr, TargetFilter::Allies );
- for ( auto pHitActor : actorsCollided )
+ for( auto pHitActor : actorsCollided )
{
effectPacket.data().targetId = pTarget.getId();
effectPacket.data().effectTarget = pHitActor->getId();
@@ -773,11 +777,10 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
pHitActor->heal( calculatedHeal );
// Debug
- if ( isPlayer() )
+ if( isPlayer() )
{
- if ( pHitActor->isPlayer() ) {
+ if( pHitActor->isPlayer() )
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) + " (" + pHitActor->getName() + ")" );
- }
else
getAsPlayer()->sendDebug( "AoE hit actor " + std::to_string( pHitActor->getId() ) );
}
@@ -794,7 +797,30 @@ void Core::Entity::Actor::handleScriptSkill( uint32_t type, uint16_t actionId, u
/*! \param StatusEffectPtr to be applied to the actor */
void Core::Entity::Actor::addStatusEffect( StatusEffect::StatusEffectPtr pEffect )
{
- m_pStatusEffectContainer->addStatusEffect( pEffect );
+ int8_t nextSlot = getStatusEffectFreeSlot();
+ // if there is no slot left, do not add the effect
+ if( nextSlot == -1 )
+ return;
+
+ pEffect->applyStatus();
+ m_statusEffectMap[nextSlot] = pEffect;
+
+ ZoneChannelPacket< Server::FFXIVIpcAddStatusEffect > statusEffectAdd( getId() );
+ statusEffectAdd.data().actor_id = pEffect->getTargetActorId();
+ statusEffectAdd.data().actor_id1 = pEffect->getSrcActorId();
+ statusEffectAdd.data().current_hp = getHp();
+ statusEffectAdd.data().current_mp = getMp();
+ statusEffectAdd.data().current_tp = getTp();
+ statusEffectAdd.data().duration = static_cast< float >( pEffect->getDuration() ) / 1000;
+ statusEffectAdd.data().effect_id = pEffect->getId();
+ statusEffectAdd.data().effect_index = nextSlot;
+ statusEffectAdd.data().max_hp = getMaxHp();
+ statusEffectAdd.data().max_mp = getMaxMp();
+ statusEffectAdd.data().max_something = 1;
+ //statusEffectAdd.data().unknown2 = 28;
+ statusEffectAdd.data().param = pEffect->getParam();
+
+ sendToInRangeSet( statusEffectAdd, isPlayer() );
}
/*! \param StatusEffectPtr to be applied to the actor */
@@ -809,22 +835,173 @@ void Core::Entity::Actor::addStatusEffectById( uint32_t id, int32_t duration, En
/*! \param StatusEffectPtr to be applied to the actor */
void Core::Entity::Actor::addStatusEffectByIdIfNotExist( uint32_t id, int32_t duration, Entity::Actor& pSource, uint16_t param )
{
- if( !m_pStatusEffectContainer->hasStatusEffect( id ) )
+ if( hasStatusEffect( id ) )
+ return;
+
+ StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, pSource.shared_from_this(),
+ shared_from_this(), duration, 3000 ) );
+ effect->setParam( param );
+ addStatusEffect( effect );
+
+}
+
+float Core::Entity::Actor::getRotation() const
+{
+ return m_rot;
+}
+
+void Core::Entity::Actor::setRotation( float rot )
+{
+ m_rot = rot;
+}
+
+int8_t Core::Entity::Actor::getStatusEffectFreeSlot()
+{
+ int8_t freeEffectSlot = -1;
+
+ if( m_statusEffectFreeSlotQueue.empty() )
+ return freeEffectSlot;
+
+ freeEffectSlot = m_statusEffectFreeSlotQueue.front();
+ m_statusEffectFreeSlotQueue.pop();
+
+ return freeEffectSlot;
+}
+
+void Core::Entity::Actor::statusEffectFreeSlot( uint8_t slotId )
+{
+ m_statusEffectFreeSlotQueue.push( slotId );
+}
+
+void Core::Entity::Actor::removeSingleStatusEffectById( uint32_t id )
+{
+ for( auto effectIt : m_statusEffectMap )
{
- StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, pSource.shared_from_this(),
- shared_from_this(), duration, 3000 ) );
- effect->setParam( param );
- addStatusEffect( effect );
+ if( effectIt.second->getId() == id )
+ {
+ removeStatusEffect( effectIt.first );
+ break;
+ }
}
}
-/*! \param Status that should be removed, based on its ID. */
-void Core::Entity::Actor::removeSingleStatusEffectFromId( uint32_t id )
+void Core::Entity::Actor::removeStatusEffect( uint8_t effectSlotId )
{
- m_pStatusEffectContainer->removeSingleStatusEffectFromId( id );
+ auto pEffectIt = m_statusEffectMap.find( effectSlotId );
+ if( pEffectIt == m_statusEffectMap.end() )
+ return;
+
+ statusEffectFreeSlot( effectSlotId );
+
+ auto pEffect = pEffectIt->second;
+ pEffect->removeStatus();
+
+ sendToInRangeSet( ActorControlPacket142( getId(), StatusEffectLose, pEffect->getId() ), isPlayer() );
+
+ m_statusEffectMap.erase( effectSlotId );
+
+ sendStatusEffectUpdate();
}
-Core::StatusEffect::StatusEffectContainerPtr Core::Entity::Actor::getStatusEffectContainer() const
+std::map< uint8_t, Core::StatusEffect::StatusEffectPtr > Core::Entity::Actor::getStatusEffectMap() const
{
- return m_pStatusEffectContainer;
-}
\ No newline at end of file
+ return m_statusEffectMap;
+}
+
+void Core::Entity::Actor::sendStatusEffectUpdate()
+{
+ uint64_t currentTimeMs = Util::getTimeMs();
+
+ ZoneChannelPacket< Server::FFXIVIpcStatusEffectList > statusEffectList( getId() );
+
+ statusEffectList.data().current_hp = getHp();
+ statusEffectList.data().current_mp = getMp();
+ statusEffectList.data().currentTp = getTp();
+ statusEffectList.data().max_hp = getMaxHp();
+ statusEffectList.data().max_mp = getMaxMp();
+ uint8_t slot = 0;
+ for( auto effectIt : m_statusEffectMap )
+ {
+ float timeLeft = static_cast< float >( effectIt.second->getDuration() -
+ ( currentTimeMs - effectIt.second->getStartTimeMs() ) ) / 1000;
+ statusEffectList.data().effect[slot].duration = timeLeft;
+ statusEffectList.data().effect[slot].effect_id = effectIt.second->getId();
+ statusEffectList.data().effect[slot].sourceActorId = effectIt.second->getSrcActorId();
+ slot++;
+ }
+
+ sendToInRangeSet( statusEffectList, isPlayer() );
+
+}
+
+void Core::Entity::Actor::updateStatusEffects()
+{
+ uint64_t currentTimeMs = Util::getTimeMs();
+
+ uint32_t thisTickDmg = 0;
+ uint32_t thisTickHeal = 0;
+
+ for( auto effectIt : m_statusEffectMap )
+ {
+ uint8_t effectIndex = effectIt.first;
+ auto effect = effectIt.second;
+
+ uint64_t lastTick = effect->getLastTickMs();
+ uint64_t startTime = effect->getStartTimeMs();
+ uint32_t duration = effect->getDuration();
+ uint32_t tickRate = effect->getTickRate();
+
+ if( ( currentTimeMs - startTime ) > duration )
+ {
+ // remove status effect
+ removeStatusEffect( effectIndex );
+ // break because removing invalidates iterators
+ break;
+ }
+
+ if( ( currentTimeMs - lastTick ) > tickRate )
+ {
+ effect->setLastTick( currentTimeMs );
+ effect->onTick();
+
+ auto thisEffect = effect->getTickEffect();
+
+ switch( thisEffect.first )
+ {
+
+ case 1:
+ {
+ thisTickDmg += thisEffect.second;
+ break;
+ }
+
+ case 2:
+ {
+ thisTickHeal += thisEffect.second;
+ break;
+ }
+
+ }
+ }
+
+ }
+
+ if( thisTickDmg != 0 )
+ {
+ takeDamage( thisTickDmg );
+ sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Damage ), thisTickDmg ) );
+ }
+
+ if( thisTickHeal != 0 )
+ {
+ heal( thisTickDmg );
+ sendToInRangeSet( ActorControlPacket142( getId(), HPFloatingText, 0, static_cast< uint8_t >( ActionEffectType::Heal ), thisTickHeal ) );
+ }
+}
+
+bool Core::Entity::Actor::hasStatusEffect( uint32_t id )
+{
+ if( m_statusEffectMap.find( id ) != m_statusEffectMap.end() )
+ return true;
+ return false;
+}
diff --git a/src/servers/Server_Zone/Actor/Actor.h b/src/servers/Server_Zone/Actor/Actor.h
index 83baaf39..35547b01 100644
--- a/src/servers/Server_Zone/Actor/Actor.h
+++ b/src/servers/Server_Zone/Actor/Actor.h
@@ -1,12 +1,13 @@
#ifndef _ACTOR_H_
#define _ACTOR_H_
-#include
+#include
#include
-#include "src/servers/Server_Zone/Forwards.h"
+#include "Forwards.h"
#include
#include