1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-24 13:47:46 +00:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Adam 2017-09-13 11:45:03 +09:00
commit 21a1837306
17 changed files with 558 additions and 358 deletions

View file

@ -11,7 +11,7 @@
<LobbyHost>127.0.0.1</LobbyHost> <LobbyHost>127.0.0.1</LobbyHost>
<!-- IP of the frontier server --> <!-- IP of the frontier server -->
<FrontierHost>127.0.0.1</FrontierHost> <FrontierHost>127.0.0.1</FrontierHost>
<!-- Secret used for server auth --> <!-- Secret used for server auth - you *must* change this for public servers -->
<ServerSecret>default</ServerSecret> <ServerSecret>default</ServerSecret>
<!-- Web server port --> <!-- Web server port -->
<HttpPort>80</HttpPort> <HttpPort>80</HttpPort>
@ -23,4 +23,9 @@
<Database>sapphire</Database> <Database>sapphire</Database>
</Mysql> </Mysql>
</General> </General>
<Parameters>
<!-- GM Rank for newly created characters - should be changed to 0 for public servers -->
<DefaultGMRank>255</DefaultGMRank>
</Parameters>
</Settings> </Settings>

View file

@ -18,7 +18,11 @@
</General> </General>
<Parameters> <Parameters>
<!-- Message players see upon logging in --> <!-- Messages players see upon logging in - These *must* be smaller than 307 characters -->
<MotD>&lt;&lt;&lt;Welcome to Sapphire&gt;&gt;&gt;</MotD> <MotDArray>
<MotD>&lt;&lt;&lt;Welcome to Sapphire&gt;&gt;&gt;</MotD>
<MotD>This is a very good server</MotD>
<MotD>You can change these messages by editing MotDArray in config/settings_zone.xml</MotD>
</MotdArray>
</Parameters> </Parameters>
</Settings> </Settings>

View file

@ -69,6 +69,7 @@ CREATE TABLE IF NOT EXISTS `charadetail` (
`PathId` int(10) DEFAULT NULL, `PathId` int(10) DEFAULT NULL,
`StepIndex` int(5) DEFAULT NULL, `StepIndex` int(5) DEFAULT NULL,
`ChocoboTaxiStandFlags` binary(8) DEFAULT NULL, `ChocoboTaxiStandFlags` binary(8) DEFAULT NULL,
`GMRank` int(3) DEFAULT '0',
`unlocks` binary(64) DEFAULT NULL, `unlocks` binary(64) DEFAULT NULL,
`CharacterId` int(20) NOT NULL DEFAULT '0', `CharacterId` int(20) NOT NULL DEFAULT '0',
`IS_DELETE` int(3) DEFAULT '0', `IS_DELETE` int(3) DEFAULT '0',

View file

@ -218,7 +218,7 @@ void Core::Network::GameConnection::enterWorld( FFXIVARR_PACKET_RAW& packet, uin
uint64_t lookupId = *reinterpret_cast< uint64_t* >( &packet.data[0] + 0x18 ); uint64_t lookupId = *reinterpret_cast< uint64_t* >( &packet.data[0] + 0x18 );
uint32_t logInCharId; uint32_t logInCharId = -1;
std::string logInCharName; std::string logInCharName;
auto charList = g_restConnector.getCharList( ( char * )m_pSession->getSessionId() ); auto charList = g_restConnector.getCharList( ( char * )m_pSession->getSessionId() );
for( uint32_t i = 0; i < charList.size(); i++ ) for( uint32_t i = 0; i < charList.size(); i++ )
@ -233,6 +233,8 @@ void Core::Network::GameConnection::enterWorld( FFXIVARR_PACKET_RAW& packet, uin
} }
} }
if( logInCharId == -1 )
return;
g_log.info( "[" + std::to_string( m_pSession->getAccountID() ) + "] Logging in as " + logInCharName + "(" + std::to_string( logInCharId ) + ")" ); g_log.info( "[" + std::to_string( m_pSession->getAccountID() ) + "] Logging in as " + logInCharName + "(" + std::to_string( logInCharId ) + ")" );

View file

@ -270,6 +270,7 @@ namespace Core {
" unlocks, " " unlocks, "
" QuestTracking, " " QuestTracking, "
" Aetheryte, " " Aetheryte, "
" GMRank, "
" UPDATE_DATE ) " " UPDATE_DATE ) "
" VALUES (" + std::to_string( m_iD ) + ", " " VALUES (" + std::to_string( m_iD ) + ", "
+ std::to_string( m_guardianDeity ) + ", " + std::to_string( m_guardianDeity ) + ", "
@ -283,7 +284,8 @@ namespace Core {
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)questComplete, 200 ) ) + "'), " + "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)questComplete, 200 ) ) + "'), "
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)unlocks, 64 ) ) + "'), " + "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)unlocks, 64 ) ) + "'), "
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)questTracking, 10 ) ) + "'), " + "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)questTracking, 10 ) ) + "'), "
+ "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)aetherytes, 12 ) ) + "'), NOW());" ); + "UNHEX('" + std::string( Util::binaryToHexString( (uint8_t*)aetherytes, 12 ) ) + "'),"
+ std::to_string( m_gmRank ) + ", NOW());" );
g_database.execute( "INSERT INTO characlass (CharacterId, Lv_" + std::to_string( g_exdData.m_classJobInfoMap[m_class].exp_idx ) + ", UPDATE_DATE ) " g_database.execute( "INSERT INTO characlass (CharacterId, Lv_" + std::to_string( g_exdData.m_classJobInfoMap[m_class].exp_idx ) + ", UPDATE_DATE ) "

View file

@ -140,6 +140,16 @@ namespace Core {
m_tribe = tribe; m_tribe = tribe;
} }
uint8_t getGmRank()
{
return m_birthMonth;
}
void setGmRank( uint8_t rank )
{
m_gmRank = rank;
}
uint32_t m_modelEquip[10]; uint32_t m_modelEquip[10];
private: private:
@ -162,6 +172,8 @@ namespace Core {
std::map<uint8_t, uint16_t> m_classMap; std::map<uint8_t, uint16_t> m_classMap;
uint8_t m_look[26]; uint8_t m_look[26];
uint8_t m_gmRank;
char m_name[34]; char m_name[34];

View file

@ -113,7 +113,7 @@ bool Core::Network::SapphireAPI::createAccount( const std::string& username, con
} }
int Core::Network::SapphireAPI::createCharacter( const int& accountId, const std::string& name, const std::string& infoJson ) int Core::Network::SapphireAPI::createCharacter( const int& accountId, const std::string& name, const std::string& infoJson, const int& gmRank )
{ {
Core::PlayerMinimal newPlayer; Core::PlayerMinimal newPlayer;
@ -166,6 +166,7 @@ int Core::Network::SapphireAPI::createCharacter( const int& accountId, const std
newPlayer.setBirthDay( tmpVector2.at( 3 ), tmpVector2.at( 2 ) ); newPlayer.setBirthDay( tmpVector2.at( 3 ), tmpVector2.at( 2 ) );
newPlayer.setClass( tmpVector2.at( 4 ) ); newPlayer.setClass( tmpVector2.at( 4 ) );
newPlayer.setTribe( tmpVector2.at( 5 ) ); newPlayer.setTribe( tmpVector2.at( 5 ) );
newPlayer.setGmRank( gmRank );
newPlayer.saveAsNew(); newPlayer.saveAsNew();

View file

@ -27,7 +27,7 @@ namespace Core
bool createAccount( const std::string& username, const std::string& pass, std::string& sId ); bool createAccount( const std::string& username, const std::string& pass, std::string& sId );
int32_t createCharacter( const int& accountId, const std::string& name, const std::string& infoJson ); int32_t createCharacter( const int& accountId, const std::string& name, const std::string& infoJson, const int& gmRank );
void deleteCharacter( std::string name, uint32_t accountId ); void deleteCharacter( std::string name, uint32_t accountId );

View file

@ -331,7 +331,7 @@ int main(int argc, char* argv[])
} }
else else
{ {
int32_t charId = g_sapphireAPI.createCharacter( result, name, finalJson ); 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 ) + "\"}"; 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; *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string;

View file

@ -110,6 +110,16 @@ uint16_t Core::Entity::Player::getZoneId() const
return m_zoneId; return m_zoneId;
} }
uint8_t Core::Entity::Player::getGmRank() const
{
return m_gmRank;
}
void Core::Entity::Player::setGmRank( uint8_t rank )
{
m_gmRank = rank;
}
uint8_t Core::Entity::Player::getMode() const uint8_t Core::Entity::Player::getMode() const
{ {
return m_mode; return m_mode;
@ -780,11 +790,6 @@ void Core::Entity::Player::setLevelForClass( uint8_t level, Core::Common::ClassJ
setSyncFlag( PlayerSyncFlags::ExpLevel ); setSyncFlag( PlayerSyncFlags::ExpLevel );
} }
uint8_t Core::Entity::Player::getUserLevel() const
{
return m_userLevel;
}
void Core::Entity::Player::eventActionStart( uint32_t eventId, void Core::Entity::Player::eventActionStart( uint32_t eventId,
uint32_t action, uint32_t action,
ActionCallback finishCallback, ActionCallback finishCallback,

View file

@ -478,6 +478,9 @@ public:
uint16_t getZoneId() const; uint16_t getZoneId() const;
uint8_t getGmRank() const;
void setGmRank( uint8_t rank );
uint8_t getMode() const; uint8_t getMode() const;
void setMode( uint8_t mode ); void setMode( uint8_t mode );
@ -589,7 +592,7 @@ private:
boost::shared_ptr< Common::QuestActive > m_activeQuests[30]; boost::shared_ptr< Common::QuestActive > m_activeQuests[30];
int16_t m_questTracking[5]; int16_t m_questTracking[5];
uint8_t m_stateFlags[7]; uint8_t m_stateFlags[7];
uint8_t m_userLevel; uint8_t m_gmRank;
uint16_t zoneId; uint16_t zoneId;
bool m_bInCombat; bool m_bInCombat;

View file

@ -234,9 +234,9 @@ void Core::Entity::Player::eventFinish( uint32_t eventId, uint32_t freePlayer )
void Core::Entity::Player::onLogin() void Core::Entity::Player::onLogin()
{ {
; for( auto& child : g_serverZone.getConfig()->getChild( "Settings.Parameters.MotDArray" ) ) {
// TODO: Replace this with MoTD from config sendNotice( child.second.data() );
sendNotice( g_serverZone.getConfig()->getValue< std::string >( "Settings.Parameters.MotD", " <<<Welcome to Sapphire >>>" ) ); }
} }
void Core::Entity::Player::onZoneStart() void Core::Entity::Player::onZoneStart()

View file

@ -80,7 +80,8 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
"cd.GrandCompany, " "cd.GrandCompany, "
"cd.GrandCompanyRank, " "cd.GrandCompanyRank, "
"cd.CFPenaltyUntil, " "cd.CFPenaltyUntil, "
"cd.OpeningSequence " "cd.OpeningSequence, "
"cd.GMRank "
"FROM charabase AS c " "FROM charabase AS c "
" INNER JOIN charadetail AS cd " " INNER JOIN charadetail AS cd "
" ON c.CharacterId = cd.CharacterId " " ON c.CharacterId = cd.CharacterId "
@ -171,13 +172,13 @@ bool Core::Entity::Player::load( uint32_t charId, Core::SessionPtr pSession )
m_openingSequence = field[36].getUInt32(); m_openingSequence = field[36].getUInt32();
m_gmRank = field[37].getUInt8();
m_pCell = nullptr; m_pCell = nullptr;
if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() ) if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() )
g_log.error( "Player id " + char_id_str + " data corrupt!" ); g_log.error( "Player id " + char_id_str + " data corrupt!" );
m_userLevel = 1;
m_maxHp = getMaxHp(); m_maxHp = getMaxHp();
m_maxMp = getMaxMp(); m_maxMp = getMaxMp();

View file

@ -70,6 +70,12 @@ void Core::DebugCommandHandler::registerCommand( const std::string& n, Core::Deb
void Core::DebugCommandHandler::execCommand( char * data, Core::Entity::PlayerPtr pPlayer ) void Core::DebugCommandHandler::execCommand( char * data, Core::Entity::PlayerPtr pPlayer )
{ {
if( pPlayer->getGmRank() <= 0 )
{
pPlayer->sendUrgent( "You are not allowed to use debug commands." );
return;
}
// define callback pointer // define callback pointer
void ( DebugCommandHandler::*pf )( char *, Entity::PlayerPtr, boost::shared_ptr< DebugCommand > ); void ( DebugCommandHandler::*pf )( char *, Entity::PlayerPtr, boost::shared_ptr< DebugCommand > );

View file

@ -49,373 +49,384 @@ using namespace Core::Network::Packets::Server;
enum GmCommand enum GmCommand
{ {
Pos = 0x0000, Pos = 0x0000,
Lv = 0x0001, Lv = 0x0001,
Race = 0x0002, Race = 0x0002,
Tribe = 0x0003, Tribe = 0x0003,
Sex = 0x0004, Sex = 0x0004,
Time = 0x0005, Time = 0x0005,
Weather = 0x0006, Weather = 0x0006,
Call = 0x0007, Call = 0x0007,
Inspect = 0x0008, Inspect = 0x0008,
Speed = 0x0009, Speed = 0x0009,
Invis = 0x000D, Invis = 0x000D,
Raise = 0x0010, Raise = 0x0010,
Kill = 0x000E, Kill = 0x000E,
Icon = 0x0012, Icon = 0x0012,
Hp = 0x0064, Hp = 0x0064,
Mp = 0x0065, Mp = 0x0065,
Tp = 0x0066, Tp = 0x0066,
Gp = 0x0067, Gp = 0x0067,
Item = 0x00C8, Item = 0x00C8,
Gil = 0x00C9, Gil = 0x00C9,
Collect = 0x00CA, Collect = 0x00CA,
QuestAccept = 0x012C, QuestAccept = 0x012C,
QuestCancel = 0x012D, QuestCancel = 0x012D,
QuestComplete = 0x012E, QuestComplete = 0x012E,
QuestIncomplete = 0x012F, QuestIncomplete = 0x012F,
QuestSequence = 0x0130, QuestSequence = 0x0130,
QuestInspect = 0x0131, QuestInspect = 0x0131,
GC = 0x0154, GC = 0x0154,
GCRank = 0x0155, GCRank = 0x0155,
TeriInfo = 0x025D, TeriInfo = 0x025D,
Jump = 0x025E, Jump = 0x025E,
JumpNpc = 0x025F, JumpNpc = 0x025F,
}; };
void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPacket, void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPacket, Entity::PlayerPtr pPlayer )
Entity::PlayerPtr pPlayer )
{ {
uint32_t commandId = inPacket.getValAt< uint32_t >( 0x20 ); if( pPlayer->getGmRank() <= 0 )
uint32_t param1 = inPacket.getValAt< uint32_t >( 0x24 ); return;
uint32_t param2 = inPacket.getValAt< uint32_t >( 0x28 );
uint32_t param3 = inPacket.getValAt< uint32_t >( 0x38 );
g_log.debug( pPlayer->getName() + " used GM1 commandId: " + std::to_string( commandId ) + uint32_t commandId = inPacket.getValAt< uint32_t >( 0x20 );
", params: " + std::to_string( param1 ) + ", " + uint32_t param1 = inPacket.getValAt< uint32_t >( 0x24 );
std::to_string( param2 ) + ", " + std::to_string( param3 ) ); uint32_t param2 = inPacket.getValAt< uint32_t >( 0x28 );
uint32_t param3 = inPacket.getValAt< uint32_t >( 0x38 );
Core::Entity::ActorPtr targetActor; g_log.debug( pPlayer->getName() + " used GM1 commandId: " + std::to_string( commandId ) +
", params: " + std::to_string( param1 ) + ", " +
std::to_string( param2 ) + ", " + std::to_string( param3 ) );
Core::Entity::ActorPtr targetActor;
if( pPlayer->getId() == param3 ) if( pPlayer->getId() == param3 )
{ {
targetActor = pPlayer; targetActor = pPlayer;
} }
else { else {
auto inRange = pPlayer->getInRangeActors(); auto inRange = pPlayer->getInRangeActors();
for( auto actor : inRange ) for( auto actor : inRange )
{ {
if( actor->getId() == param3 ) if( actor->getId() == param3 )
targetActor = actor; targetActor = actor;
} }
} }
if( !targetActor ) if( !targetActor )
return; return;
auto targetPlayer = targetActor->getAsPlayer(); auto targetPlayer = targetActor->getAsPlayer();
switch( commandId ) switch( commandId )
{ {
case GmCommand::Kill: case GmCommand::Kill:
{ {
targetActor->takeDamage( 9999999 ); targetActor->takeDamage( 9999999 );
pPlayer->sendNotice( "Killed " + std::to_string( targetActor->getId() ) ); pPlayer->sendNotice( "Killed " + std::to_string( targetActor->getId() ) );
break; break;
} }
case GmCommand::QuestSequence: case GmCommand::QuestSequence:
{ {
targetPlayer->updateQuest( param1, param2 ); targetPlayer->updateQuest( param1, param2 );
break; break;
} }
case GmCommand::QuestComplete: case GmCommand::QuestComplete:
{ {
targetPlayer->finishQuest( param1 ); targetPlayer->finishQuest( param1 );
break; break;
} }
case GmCommand::QuestAccept: case GmCommand::QuestAccept:
{ {
targetPlayer->updateQuest( param1, 1 ); targetPlayer->updateQuest( param1, 1 );
break; break;
} }
case GmCommand::QuestCancel: case GmCommand::QuestCancel:
{ {
targetPlayer->removeQuest( param1 ); targetPlayer->removeQuest( param1 );
break; break;
} }
case GmCommand::QuestIncomplete: case GmCommand::QuestIncomplete:
{ {
targetPlayer->unfinishQuest( param1 ); targetPlayer->unfinishQuest( param1 );
break; break;
} }
case GmCommand::Speed: case GmCommand::Speed:
{ {
targetPlayer->queuePacket( ActorControlPacket143( pPlayer->getId(), Flee, param1 ) ); targetPlayer->queuePacket( ActorControlPacket143( pPlayer->getId(), Flee, param1 ) );
pPlayer->sendNotice( "Speed for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Speed for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
break; break;
} }
case GmCommand::Gil: case GmCommand::Gil:
{ {
targetPlayer->addCurrency( 1, param1 ); targetPlayer->addCurrency( 1, param1 );
pPlayer->sendNotice( "Added " + std::to_string( param1 ) + " Gil for " + targetPlayer->getName() ); pPlayer->sendNotice( "Added " + std::to_string( param1 ) + " Gil for " + targetPlayer->getName() );
break; break;
} }
case GmCommand::Lv: case GmCommand::Lv:
{ {
targetPlayer->setLevel( param1 ); targetPlayer->setLevel( param1 );
pPlayer->sendNotice( "Level for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Level for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
break; break;
} }
case GmCommand::Hp: case GmCommand::Hp:
{ {
targetPlayer->setHp( param1 ); targetPlayer->setHp( param1 );
pPlayer->sendNotice( "Hp for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Hp for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
break; break;
} }
case GmCommand::Mp: case GmCommand::Mp:
{ {
targetPlayer->setMp( param1 ); targetPlayer->setMp( param1 );
pPlayer->sendNotice( "Mp for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Mp for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
break; break;
} }
case GmCommand::Gp: case GmCommand::Gp:
{ {
targetPlayer->setHp( param1 ); targetPlayer->setHp( param1 );
pPlayer->sendNotice( "Gp for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Gp for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
break; break;
} }
case GmCommand::Sex: case GmCommand::Sex:
{ {
targetPlayer->setLookAt( CharaLook::Gender, param1 ); targetPlayer->setLookAt( CharaLook::Gender, param1 );
pPlayer->sendNotice( "Sex for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Sex for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
targetPlayer->spawn( targetPlayer ); targetPlayer->spawn( targetPlayer );
auto inRange = targetActor->getInRangeActors(); auto inRange = targetActor->getInRangeActors();
for( auto actor : inRange ) for( auto actor : inRange )
{ {
targetPlayer->despawn( actor->getAsPlayer() ); targetPlayer->despawn( actor->getAsPlayer() );
targetPlayer->spawn( actor->getAsPlayer() ); targetPlayer->spawn( actor->getAsPlayer() );
} }
break; break;
} }
case GmCommand::Race: case GmCommand::Race:
{ {
targetPlayer->setLookAt( CharaLook::Race, param1 ); targetPlayer->setLookAt( CharaLook::Race, param1 );
pPlayer->sendNotice( "Race for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Race for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
targetPlayer->spawn( targetPlayer ); targetPlayer->spawn( targetPlayer );
auto inRange = targetPlayer->getInRangeActors(); auto inRange = targetPlayer->getInRangeActors();
for( auto actor : inRange ) for( auto actor : inRange )
{ {
targetPlayer->despawn( actor->getAsPlayer() ); targetPlayer->despawn( actor->getAsPlayer() );
targetPlayer->spawn( actor->getAsPlayer() ); targetPlayer->spawn( actor->getAsPlayer() );
} }
break; break;
} }
case GmCommand::Tribe: case GmCommand::Tribe:
{ {
targetPlayer->setLookAt( CharaLook::Tribe, param1 ); targetPlayer->setLookAt( CharaLook::Tribe, param1 );
pPlayer->sendNotice( "Tribe for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Tribe for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
targetPlayer->spawn( targetPlayer ); targetPlayer->spawn( targetPlayer );
auto inRange = targetPlayer->getInRangeActors(); auto inRange = targetPlayer->getInRangeActors();
for( auto actor : inRange ) for( auto actor : inRange )
{ {
targetPlayer->despawn( actor->getAsPlayer() ); targetPlayer->despawn( actor->getAsPlayer() );
targetPlayer->spawn( actor->getAsPlayer() ); targetPlayer->spawn( actor->getAsPlayer() );
} }
break; break;
} }
case GmCommand::Item: case GmCommand::Item:
{ {
if( param2 < 1 || param2 > 99 ) if( param2 < 1 || param2 > 99 )
{ {
param2 = 1; param2 = 1;
} }
if( ( param1 == 0xcccccccc ) ) if( ( param1 == 0xcccccccc ) )
{ {
pPlayer->sendUrgent( "Syntaxerror." ); pPlayer->sendUrgent( "Syntaxerror." );
return; return;
} }
if( !targetPlayer->addItem( -1, param1, param2 ) ) if( !targetPlayer->addItem( -1, param1, param2 ) )
pPlayer->sendUrgent( "Item " + std::to_string( param1 ) + " not found..." ); pPlayer->sendUrgent( "Item " + std::to_string( param1 ) + " not found..." );
break; break;
} }
case GmCommand::Weather: case GmCommand::Weather:
{ {
targetPlayer->getCurrentZone()->setWeatherOverride( param1 ); targetPlayer->getCurrentZone()->setWeatherOverride( param1 );
pPlayer->sendNotice( "Weather in Zone \"" + targetPlayer->getCurrentZone()->getName() + "\" of " + pPlayer->sendNotice( "Weather in Zone \"" + targetPlayer->getCurrentZone()->getName() + "\" of " +
targetPlayer->getName() + " set in range." ); targetPlayer->getName() + " set in range." );
break; break;
} }
case GmCommand::TeriInfo: case GmCommand::TeriInfo:
{ {
pPlayer->sendNotice( "ZoneId: " + std::to_string( pPlayer->getZoneId() ) + "\nName: " + pPlayer->sendNotice( "ZoneId: " + std::to_string( pPlayer->getZoneId() ) + "\nName: " +
pPlayer->getCurrentZone()->getName() + "\nInternalName: " + pPlayer->getCurrentZone()->getName() + "\nInternalName: " +
pPlayer->getCurrentZone()->getInternalName() + "\nPopCount: " + pPlayer->getCurrentZone()->getInternalName() + "\nPopCount: " +
std::to_string( pPlayer->getCurrentZone()->getPopCount() ) + std::to_string( pPlayer->getCurrentZone()->getPopCount() ) +
"\nCurrentWeather:" + std::to_string( pPlayer->getCurrentZone()->getCurrentWeather() ) + "\nCurrentWeather:" + std::to_string( pPlayer->getCurrentZone()->getCurrentWeather() ) +
"\nNextWeather:" + std::to_string( pPlayer->getCurrentZone()->getNextWeather() ) ); "\nNextWeather:" + std::to_string( pPlayer->getCurrentZone()->getNextWeather() ) );
break; break;
} }
case GmCommand::Jump: case GmCommand::Jump:
{ {
auto inRange = pPlayer->getInRangeActors(); auto inRange = pPlayer->getInRangeActors();
for( auto actor : inRange ) for( auto actor : inRange )
{ {
pPlayer->changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z, pPlayer->changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z,
targetActor->getRotation() ); targetActor->getRotation() );
} }
pPlayer->sendNotice( "Jumping to " + targetPlayer->getName() + " in range." ); pPlayer->sendNotice( "Jumping to " + targetPlayer->getName() + " in range." );
break; break;
} }
case GmCommand::Collect: case GmCommand::Collect:
{ {
uint32_t gil = targetPlayer->getCurrency( 1 ); uint32_t gil = targetPlayer->getCurrency( 1 );
if( gil < param1 ) if( gil < param1 )
{ {
pPlayer->sendUrgent( "Player does not have enough Gil(" + std::to_string( gil ) + ")" ); pPlayer->sendUrgent( "Player does not have enough Gil(" + std::to_string( gil ) + ")" );
} }
else else
{ {
targetPlayer->removeCurrency( 1, param1 ); targetPlayer->removeCurrency( 1, param1 );
pPlayer->sendNotice( "Removed " + std::to_string( param1 ) + pPlayer->sendNotice( "Removed " + std::to_string( param1 ) +
" Gil from " + targetPlayer->getName() + " Gil from " + targetPlayer->getName() +
"(" + std::to_string( gil ) + " before)" ); "(" + std::to_string( gil ) + " before)" );
} }
break; break;
} }
case GmCommand::Icon: case GmCommand::Icon:
{ {
targetPlayer->setOnlineStatusMask( param1 ); targetPlayer->setOnlineStatusMask( param1 );
GamePacketNew< FFXIVIpcSetOnlineStatus, ServerZoneIpcType > statusPacket( targetPlayer->getId() ); GamePacketNew< FFXIVIpcSetOnlineStatus, ServerZoneIpcType > statusPacket( targetPlayer->getId() );
statusPacket.data().onlineStatusFlags = param1; statusPacket.data().onlineStatusFlags = param1;
queueOutPacket( statusPacket ); queueOutPacket( statusPacket );
GamePacketNew< FFXIVIpcSetSearchInfo, ServerZoneIpcType > searchInfoPacket( targetPlayer->getId() ); GamePacketNew< FFXIVIpcSetSearchInfo, ServerZoneIpcType > searchInfoPacket( targetPlayer->getId() );
searchInfoPacket.data().onlineStatusFlags = param1; searchInfoPacket.data().onlineStatusFlags = param1;
searchInfoPacket.data().selectRegion = targetPlayer->getSearchSelectRegion(); searchInfoPacket.data().selectRegion = targetPlayer->getSearchSelectRegion();
sprintf( searchInfoPacket.data().searchMessage, targetPlayer->getSearchMessage() ); sprintf( searchInfoPacket.data().searchMessage, targetPlayer->getSearchMessage() );
targetPlayer->queuePacket( searchInfoPacket ); targetPlayer->queuePacket( searchInfoPacket );
targetPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), SetStatusIcon, targetPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), SetStatusIcon,
static_cast< uint8_t >( pPlayer->getOnlineStatus() ) ), static_cast< uint8_t >( pPlayer->getOnlineStatus() ) ),
true ); true );
pPlayer->sendNotice( "Icon for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) ); pPlayer->sendNotice( "Icon for " + targetPlayer->getName() + " was set to " + std::to_string( param1 ) );
break; break;
} }
case GmCommand::GC: case GmCommand::GC:
{ {
targetPlayer->setGc( param1 ); targetPlayer->setGc( param1 );
pPlayer->sendNotice( "GC for " + targetPlayer->getName() + pPlayer->sendNotice( "GC for " + targetPlayer->getName() +
" was set to " + std::to_string( targetPlayer->getGc() ) ); " was set to " + std::to_string( targetPlayer->getGc() ) );
break; break;
} }
case GmCommand::GCRank: case GmCommand::GCRank:
{ {
targetPlayer->setGcRankAt( targetPlayer->getGc() - 1, param1 ); targetPlayer->setGcRankAt( targetPlayer->getGc() - 1, param1 );
pPlayer->sendNotice( "GC Rank for " + targetPlayer->getName() + pPlayer->sendNotice( "GC Rank for " + targetPlayer->getName() +
" for GC " + std::to_string( targetPlayer->getGc()) + " for GC " + std::to_string( targetPlayer->getGc() ) +
" was set to " + std::to_string( targetPlayer->getGcRankArray()[targetPlayer->getGc() - 1] ) ); " was set to " + std::to_string( targetPlayer->getGcRankArray()[targetPlayer->getGc() - 1] ) );
break; break;
} }
default: default:
pPlayer->sendUrgent( "GM1 Command not implemented: " + std::to_string( commandId ) ); pPlayer->sendUrgent( "GM1 Command not implemented: " + std::to_string( commandId ) );
break; break;
} }
pPlayer->setSyncFlag( Common::PlayerSyncFlags::All );
targetPlayer->setSyncFlag( Common::PlayerSyncFlags::All );
} }
void Core::Network::GameConnection::gm2Handler( const Packets::GamePacket& inPacket, void Core::Network::GameConnection::gm2Handler( const Packets::GamePacket& inPacket, Entity::PlayerPtr pPlayer )
Entity::PlayerPtr pPlayer )
{ {
uint32_t commandId = inPacket.getValAt< uint32_t >( 0x20 ); if( pPlayer->getGmRank() <= 0 )
std::string param1 = inPacket.getStringAt( 0x34 ); return;
g_log.debug( pPlayer->getName() + " used GM2 commandId: " + std::to_string( commandId ) + ", params: " + param1 ); uint32_t commandId = inPacket.getValAt< uint32_t >( 0x20 );
std::string param1 = inPacket.getStringAt( 0x34 );
auto targetSession = g_serverZone.getSession( param1 ); g_log.debug( pPlayer->getName() + " used GM2 commandId: " + std::to_string( commandId ) + ", params: " + param1 );
Core::Entity::ActorPtr targetActor;
if( targetSession != nullptr ) auto targetSession = g_serverZone.getSession( param1 );
{ Core::Entity::ActorPtr targetActor;
targetActor = targetSession->getPlayer();
}
else
{
if( param1 == "self" )
{
targetActor = pPlayer;
}
else
{
pPlayer->sendUrgent("Player " + param1 + " not found on this server.");
return;
}
}
if( !targetActor ) if( targetSession != nullptr )
return; {
auto targetPlayer = targetActor->getAsPlayer(); targetActor = targetSession->getPlayer();
}
else
{
if( param1 == "self" )
{
targetActor = pPlayer;
}
else
{
pPlayer->sendUrgent( "Player " + param1 + " not found on this server." );
return;
}
}
switch( commandId ) if( !targetActor )
{ return;
case GmCommand::Raise: auto targetPlayer = targetActor->getAsPlayer();
{
targetPlayer->resetHp();
targetPlayer->resetMp();
targetPlayer->setStatus( Entity::Actor::ActorStatus::Idle );
targetPlayer->setSyncFlag( Status );
targetPlayer->sendToInRangeSet( ActorControlPacket143( pPlayer->getId(), ZoneIn, 0x01, 0x01, 0, 113 ), true ); switch( commandId )
targetPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), SetStatus, {
static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle ) ), true ); case GmCommand::Raise:
pPlayer->sendNotice( "Raised " + targetPlayer->getName()); {
break; targetPlayer->resetHp();
} targetPlayer->resetMp();
case GmCommand::Jump: targetPlayer->setStatus( Entity::Actor::ActorStatus::Idle );
{ targetPlayer->setSyncFlag( Status );
if( targetPlayer->getZoneId() != pPlayer->getZoneId() )
{
pPlayer->setZone( targetPlayer->getZoneId() );
}
pPlayer->changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z,
targetActor->getRotation() );
pPlayer->sendNotice( "Jumping to " + targetPlayer->getName());
break;
}
case GmCommand::Call:
{
if( targetPlayer->getZoneId() != pPlayer->getZoneId() )
targetPlayer->setZone( pPlayer->getZoneId() );
targetPlayer->changePosition( pPlayer->getPos().x, pPlayer->getPos().y, pPlayer->getPos().z, targetPlayer->sendToInRangeSet( ActorControlPacket143( pPlayer->getId(), ZoneIn, 0x01, 0x01, 0, 113 ), true );
pPlayer->getRotation() ); targetPlayer->sendToInRangeSet( ActorControlPacket142( pPlayer->getId(), SetStatus,
pPlayer->sendNotice( "Calling " + targetPlayer->getName() ); static_cast< uint8_t >( Entity::Actor::ActorStatus::Idle ) ), true );
break; pPlayer->sendNotice( "Raised " + targetPlayer->getName() );
} break;
case GmCommand::Inspect: }
{ case GmCommand::Jump:
pPlayer->sendNotice( "Name: " + targetPlayer->getName() + {
"\nGil: " + std::to_string( targetPlayer->getCurrency( 1 ) ) + if( targetPlayer->getZoneId() != pPlayer->getZoneId() )
"\nZone: " + targetPlayer->getCurrentZone()->getName() + {
"(" + std::to_string( targetPlayer->getZoneId() ) + ")" + pPlayer->setZone( targetPlayer->getZoneId() );
"\nClass: " + std::to_string( targetPlayer->getClass() ) + }
"\nLevel: " + std::to_string( targetPlayer->getLevel() ) + pPlayer->changePosition( targetActor->getPos().x, targetActor->getPos().y, targetActor->getPos().z,
"\nExp: " + std::to_string( targetPlayer->getExp() ) + targetActor->getRotation() );
"\nSearchMessage: " + targetPlayer->getSearchMessage() + pPlayer->sendNotice( "Jumping to " + targetPlayer->getName() );
"\nPlayTime: " + std::to_string( targetPlayer->getPlayTime() ) ); break;
break; }
} case GmCommand::Call:
{
if( targetPlayer->getZoneId() != pPlayer->getZoneId() )
targetPlayer->setZone( pPlayer->getZoneId() );
targetPlayer->changePosition( pPlayer->getPos().x, pPlayer->getPos().y, pPlayer->getPos().z,
pPlayer->getRotation() );
pPlayer->sendNotice( "Calling " + targetPlayer->getName() );
break;
}
case GmCommand::Inspect:
{
pPlayer->sendNotice( "Name: " + targetPlayer->getName() +
"\nGil: " + std::to_string( targetPlayer->getCurrency( 1 ) ) +
"\nZone: " + targetPlayer->getCurrentZone()->getName() +
"(" + std::to_string( targetPlayer->getZoneId() ) + ")" +
"\nClass: " + std::to_string( targetPlayer->getClass() ) +
"\nLevel: " + std::to_string( targetPlayer->getLevel() ) +
"\nExp: " + std::to_string( targetPlayer->getExp() ) +
"\nSearchMessage: " + targetPlayer->getSearchMessage() +
"\nPlayTime: " + std::to_string( targetPlayer->getPlayTime() ) );
break;
}
default:
pPlayer->sendUrgent( "GM2 Command not implemented: " + std::to_string( commandId ) );
break;
}
pPlayer->setSyncFlag( Common::PlayerSyncFlags::All );
targetPlayer->setSyncFlag( Common::PlayerSyncFlags::All );
default:
pPlayer->sendUrgent( "GM2 Command not implemented: " + std::to_string( commandId ) );
break;
}
} }

View file

@ -45,7 +45,7 @@ namespace Server {
m_data.tPCurr = pPlayer->getTp(); m_data.tPCurr = pPlayer->getTp();
m_data.hPMax = pPlayer->getMaxHp(); m_data.hPMax = pPlayer->getMaxHp();
m_data.mPMax = pPlayer->getMaxMp(); m_data.mPMax = pPlayer->getMaxMp();
m_data.gmRank = 0xff; m_data.gmRank = pPlayer->getGmRank();
//m_data.tPMax = 3000; //m_data.tPMax = 3000;
m_data.level = pPlayer->getLevel(); m_data.level = pPlayer->getLevel();
memcpy( m_data.look, pPlayer->getLookArray(), 26 ); memcpy( m_data.look, pPlayer->getLookArray(), 26 );

View file

@ -0,0 +1,147 @@
-- init global variable
g_dump = io.open(os.date("dump_%Y-%m-%d-%H-%M-%S.txt"), "a")
g_dump:write("ptr, name\n")
g_count = 0
-- relative virtual address(rva) to register_whatever function
-- this assume ffxiv sb benchmark
-- YOU MUST EDIT THIS TO RIGHT VALUE TO WORK
-- check http://imgur.com/a/nJCef for disasm
g_addr = {}
-- signature: 4053 4881EC60010000 488B??????????4833C4 4889842450010000 C70100000000 488BD9 4585C0 7514
g_addr.load_master = 0x166140 -- looks like below function is called from this
-- signature: 48895C2408 48896C2410 4889742418 57 4883EC40 498BD9 498BF8 488BF2 488BE9 4D85C9 740A
-- rva on benchmark was at 0x1624B0 and it's now located at 0x1663E0 (offseted by 0x3F30)
g_addr.load1 = 0x1663E0 -- mostly loads gfx stuff but does calc in it?
-- these were just calculated from load1 offset (didn't tested)
g_addr.load2 = 0x162410 + 0x3F30 -- mostly loads gfx stuff
g_addr.load3 = 0x1626B0 + 0x3F30 -- mostly loads exd data
g_addr.load4 = 0x162540 + 0x3F30 -- from this on found it because there are next to each other
g_addr.load5 = 0x162360 + 0x3F30 -- umm, vfx?
g_loadseen = {}
g_xiv = {}
g_xiv.proc_name = "ffxiv_dx11.exe"
g_xiv.path = "C:\\Users\\Mino\\Desktop\\FFXIV-SB\\game\\" .. g_xiv.proc_name
-- because I don't want to login and out every single try
g_xiv.arg = "SYS.Language=1 SYS.Fps=0 SYS.MainAdapter=\"AMD_Radeon_HD_7800_Series(\\\\.\\DISPLAY1)\" SYS.ScreenMode=0 SYS.ScreenWidth=1280 SYS.ScreenHeight=720 SYS.FullScreenWidth=1280 SYS.FullScreenHeight=720 SYS.Gamma=50 SYS.IsSoundAlways=0 SYS.SoundMaster=100 SYS.SoundBgm=100 SYS.SoundSe=100 SYS.SoundVoice=100 SYS.SoundSystem=100 SYS.SoundEnv=100 SYS.IsSndMaster=0 SYS.IsSndBgm=0 SYS.IsSndSe=0 SYS.IsSndVoice=0 SYS.IsSndSystem=0 SYS.IsSndEnv=0 SYS.WaterWet_DX11=1 SYS.OcclusionCulling_DX11=1 SYS.LodType_DX11=1 SYS.ReflectionType_DX11=0 SYS.AntiAliasing_DX11=0 SYS.TranslucentQuality_DX11=0 SYS.GrassQuality_DX11=2 SYS.ShadowLOD_DX11=1 SYS.ShadowVisibilityTypeSelf_DX11=1 SYS.ShadowVisibilityTypeOther_DX11=0 SYS.ShadowTextureSizeType_DX11=1 SYS.ShadowCascadeCountType_DX11=2 SYS.ShadowSoftShadowType_DX11=1 SYS.PhysicsTypeSelf_DX11=2 SYS.PhysicsTypeOther_DX11=2 SYS.TextureFilterQuality_DX11=2 SYS.TextureAnisotropicQuality_DX11=0 SYS.Vignetting_DX11=1 SYS.RadialBlur_DX11=1 SYS.SSAO_DX11=1 SYS.Glare_DX11=2 SYS.DepthOfField_DX11=1 SYS.ParallaxOcclusion_DX11=0 SYS.Tessellation_DX11=0 SYS.GlareRepresentation_DX11=0"
g_mode = "attach"
function init()
-- attach debugger
if g_mode == "create" then
print(string.format("Launching ffxiv.exe w/ arg %s", g_xiv.arg))
createProcess(g_xiv.path, g_xiv.arg, true, true)
elseif g_mode == "attach" then
print("Looking for ffxiv.exe..")
while not openProcess("ffxiv.exe") do sleep(1) end
print("Attaching...")
debugProcess()
while not getAddress(g_xiv.proc_name) do sleep(1) end
print("Module loaded")
else
print("Unsupported mode!")
return
end
for k, v in pairs(g_addr) do
-- k = name
-- v = rva
print(string.format("Attaching %s breakpoint on 0x%X", k, v))
debug_setBreakpoint(get_va(v))
end
print("Now waiting for breakpoints..")
end
function debugger_onBreakpoint()
if RIP == get_va(g_addr.load1) then
-- dump_message("1>>")
dump_addr(R8)
elseif RIP == get_va(g_addr.load2) then
-- dump_message("2>>")
dump_addr(R8)
elseif RIP == get_va(g_addr.load3) then
-- dump_message("3>>")
dump_addr(RCX)
elseif RIP == get_va(g_addr.load4) then
-- dump_message("4>>")
dump_addr(RCX)
elseif RIP == get_va(g_addr.load5) then
-- dump_message("5>>")
dump_addr(RDX)
elseif RIP == get_va(g_addr.load_master) then
-- dump_message("master>>")
dump_addr(RDX)
else
-- user bp, update gui on ce, but who gives a shit?
-- continue execution anyway
debug_continueFromBreakpoint("co_run")
return 0
end
-- something is missing on the text file because it takes ageeeeeeeeees to write to file
-- let just wait it
-- continue execution
debug_continueFromBreakpoint("co_run")
--return 0 -- update gui
return 1
end
function dump_addr(addr)
local vfspath = readString(addr, 256)
if not g_loadseen[vfspath] then
g_loadseen[vfspath] = true -- set seen flag
local message = string.format("%X, %s", addr, vfspath)
dump_line(message)
end
end
function dump_line(message)
dump_message(message .. "\n")
end
function dump_message(message)
g_dump:write(message)
g_dump:flush()
print(message)
end
-- mod_base + rva = va
function get_va(rva)
return getAddress(g_xiv.proc_name) + rva
end
-- rva = va - mod_base
function get_rva(va)
return va - getAddress(g_xiv.proc_name)
end
-- check mod_base <= va <= mod_base + mod_size
function is_mmod_addr(va)
local mod_base = getAddress(g_xiv.proc_name)
local mod_size = getModuleSize(g_xiv.proc_name)
if mod_base <= va and va <= mod_base + mod_size then
return true
end
return false
end
function split(str)
local result = {}
for token in string.gmatch(str..",", "([^,]+),%s*") do
table.insert(result, all_trim(token))
end
return result
end
init()