1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-25 14:07:46 +00:00

switch debugcommandhandler for scripted implementation

This commit is contained in:
Adam 2018-01-28 18:52:53 +11:00
parent 99300d746a
commit dde0a30fa3
28 changed files with 770 additions and 818 deletions

View file

@ -39,7 +39,7 @@ foreach(_scriptDir ${children})
endforeach()
add_library("script_${_name}" MODULE "${SCRIPT_FILES}" "${SCRIPT_INCLUDE_FILES}" "${_scriptDir}/ScriptLoader.cpp")
target_link_libraries("script_${_name}" sapphire_zone)
target_link_libraries("script_${_name}" sapphire_zone common xivdat ${Boost_LIBRARIES})
if(MSVC)
set_target_properties("script_${_name}" PROPERTIES
@ -53,6 +53,10 @@ foreach(_scriptDir ${children})
)
endif()
if(EXISTS "${_scriptDir}/PreInclude.h")
set(PreScriptIncludes "#include \"${_scriptDir}/PreInclude.h\"")
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.cpp.in" "${_scriptDir}/ScriptLoader.cpp")
add_custom_command(TARGET "script_${_name}" POST_BUILD
@ -63,5 +67,6 @@ foreach(_scriptDir ${children})
unset(ScriptIncludes)
unset(ScriptNames)
unset(PreScriptIncludes)
endif()
endforeach()

View file

@ -1,7 +1,5 @@
#include <vector>
class ScriptObject;
@PreScriptIncludes@
@ScriptIncludes@
const ScriptObject* ptrs[] =

View file

@ -0,0 +1,102 @@
#include <ScriptObject.h>
#include <common/Network/PacketDef/Zone/ServerZoneDef.h>
#include <common/Network/GamePacketNew.h>
#include <Actor/BattleNpc.h>
#include <Zone/Zone.h>
class Add : public DebugCommandScript
{
public:
Add() : DebugCommandScript( "add", "Executes ADD command", 1 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string &subCommand, const std::string &params )
{
if( subCommand == "status" )
{
int32_t id;
int32_t duration;
uint16_t param;
sscanf( params.c_str(), "%d %d %hu", &id, &duration, &param );
StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, player.getAsPlayer(), player.getAsPlayer(), duration, 3000 ) );
effect->setParam( param );
player.addStatusEffect( effect );
}
else if( subCommand == "title" )
{
uint32_t titleId;
sscanf( params.c_str(), "%u", &titleId );
player.addTitle( titleId );
player.sendNotice( "Added title (ID: " + std::to_string( titleId ) + ")" );
}
else if( subCommand == "spawn" )
{
int32_t model, name;
sscanf( params.c_str(), "%d %d", &model, &name );
Entity::BattleNpcPtr pBNpc( new Entity::BattleNpc( model, name, player.getPos() ) );
auto pZone = player.getCurrentZone();
pBNpc->setCurrentZone( pZone );
pZone->pushActor( pBNpc );
}
else if( subCommand == "op" )
{
// temporary research packet
int32_t opcode;
sscanf( params.c_str(), "%x", &opcode );
Network::Packets::GamePacketPtr pPe( new Network::Packets::GamePacket( opcode, 0x30, player.getId(), player.getId() ) );
player.queuePacket( pPe );
}
else if( subCommand == "actrl" )
{
// temporary research packet
int32_t opcode;
int32_t param1;
int32_t param2;
int32_t param3;
int32_t param4;
int32_t param5;
int32_t param6;
int32_t playerId;
sscanf( params.c_str(), "%x %x %x %x %x %x %x %x", &opcode, &param1, &param2, &param3, &param4, &param5, &param6, &playerId );
player.sendNotice( "Injecting ACTOR_CONTROL " + std::to_string( opcode ) );
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcActorControl143 > actorControl( playerId, player.getId() );
actorControl.data().category = opcode;
actorControl.data().param1 = param1;
actorControl.data().param2 = param2;
actorControl.data().param3 = param3;
actorControl.data().param4 = param4;
actorControl.data().param5 = param5;
actorControl.data().param6 = param6;
player.queuePacket( actorControl );
/*sscanf(params.c_str(), "%x %x %x %x %x %x %x", &opcode, &param1, &param2, &param3, &param4, &param5, &param6, &playerId);
Network::Packets::Server::ServerNoticePacket noticePacket( player, "Injecting ACTOR_CONTROL " + std::to_string( opcode ) );
player.queuePacket( noticePacket );
Network::Packets::Server::ActorControlPacket143 controlPacket( player, opcode,
param1, param2, param3, param4, param5, param6, playerId );
player.queuePacket( controlPacket );*/
}
else
{
player.sendUrgent( subCommand + " is not a valid ADD command." );
}
}
};

View file

@ -0,0 +1,31 @@
#include <ScriptObject.h>
#include <Zone/Zone.h>
class Get : public DebugCommandScript
{
public:
Get() : DebugCommandScript( "get", "Executes GET commands", 1 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string& subCommand, const std::string& params )
{
if( ( subCommand == "pos" ) )
{
int16_t map_id = m_objects->m_exd->m_zoneInfoMap[player.getCurrentZone()->getTerritoryId()].map_id;
player.sendNotice( "Pos:\n" +
std::to_string( player.getPos().x ) + "\n" +
std::to_string( player.getPos().y ) + "\n" +
std::to_string( player.getPos().z ) + "\n" +
std::to_string( player.getRotation() ) + "\nMapId: " +
std::to_string( map_id ) + "\nZoneID: " +
std::to_string(player.getCurrentZone()->getTerritoryId() ) + "\n" );
}
else
{
player.sendUrgent( subCommand + " is not a valid GET command." );
}
}
};

View file

@ -0,0 +1,23 @@
#include <ScriptObject.h>
#include <Script/NativeScriptManager.h>
class Help : public DebugCommandScript
{
public:
Help() : DebugCommandScript( "help", "Displays server build information", 0 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string& subCommand, const std::string& params )
{
player.sendDebug( "Available debug commands:" );
for( std::pair< uint32_t, ScriptObject* > s : m_objects->m_scriptMgr->getNativeScriptHandler().getScriptsOfType< DebugCommandScript >() )
{
auto script = dynamic_cast< DebugCommandScript* >( s.second );
if( player.getGmRank() >= script->getGmLevel() )
player.sendDebug( " - " + script->getCmd() + " - " + script->getHelpText() );
}
}
};

View file

@ -0,0 +1,21 @@
#include <ScriptObject.h>
#include <common/Network/PacketContainer.h>
#include <Session.h>
#include <Network/GameConnection.h>
#include <common/Network/CommonNetwork.h>
class InjectChatPacket : public DebugCommandScript
{
public:
InjectChatPacket() : DebugCommandScript( "injectc", "Injects a premade chat packet", 1 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string& subCommand, const std::string& params )
{
auto pSession = m_objects->m_zone->getSession( player.getId() );
if( pSession )
pSession->getChatConnection()->injectPacket( data.c_str() + 8, player );
}
};

View file

@ -0,0 +1,20 @@
#include <ScriptObject.h>
#include <common/Network/PacketContainer.h>
#include <Session.h>
#include <Network/GameConnection.h>
#include <common/Network/CommonNetwork.h>
class InjectPacket : public DebugCommandScript
{
public:
InjectPacket() : DebugCommandScript( "inject", "Injects a premade packet", 0 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string& subCommand, const std::string& params )
{
auto pSession = m_objects->m_zone->getSession( player.getId() );
if( pSession )
pSession->getZoneConnection()->injectPacket( data.c_str() + 7, player );
}
};

View file

@ -0,0 +1,56 @@
#include <ScriptObject.h>
#include <common/Util/UtilMath.h>
#include <common/Network/PacketDef/Zone/ServerZoneDef.h>
#include <common/Network/GamePacketNew.h>
class Nudge : public DebugCommandScript
{
public:
Nudge() : DebugCommandScript( "nudge", "Nudge player in a direction", 1 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string& subCommand, const std::string& params )
{
// check if the command has parameters
std::string tmpCommand = std::string( data.c_str() + m_cmd.length() + 1 );
std::size_t spos = tmpCommand.find_first_of( " " );
auto& pos = player.getPos();
int32_t offset = 0;
char direction[20];
memset( direction, 0, 20 );
sscanf( tmpCommand.c_str(), "%d %s", &offset, direction );
if( direction[0] == 'u' || direction[0] == '+' )
{
pos.y += offset;
player.sendNotice( "nudge: Placing up " + std::to_string( offset ) + " yalms" );
}
else if( direction[0] == 'd' || direction[0] == '-' )
{
pos.y -= offset;
player.sendNotice( "nudge: Placing down " + std::to_string( offset ) + " yalms" );
}
else
{
float angle = player.getRotation() + ( PI / 2 );
pos.x -= offset * cos( angle );
pos.z += offset * sin( angle );
player.sendNotice( "nudge: Placing forward " + std::to_string( offset ) + " yalms" );
}
if( offset != 0 )
{
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcActorSetPos >
setActorPosPacket( player.getId() );
setActorPosPacket.data().x = player.getPos().x;
setActorPosPacket.data().y = player.getPos().y;
setActorPosPacket.data().z = player.getPos().z;
setActorPosPacket.data().r16 = Math::Util::floatToUInt16Rot( player.getRotation() );
player.queuePacket( setActorPosPacket );
}
}
};

View file

@ -0,0 +1,7 @@
#ifndef SAPPHIRE_PREINCLUDE_H
#define SAPPHIRE_PREINCLUDE_H
// fixes an issue where winsock is included before asio causing builds to fail
#include <boost/asio.hpp>
#endif //SAPPHIRE_PREINCLUDE_H

View file

@ -0,0 +1,29 @@
#include <ScriptObject.h>
#include <Session.h>
class Replay : public DebugCommandScript
{
public:
Replay() : DebugCommandScript( "replay", "Replays a saved capture", 1 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string& subCommand, const std::string& params )
{
if( subCommand == "start" )
{
auto pSession = m_objects->m_zone->getSession( player.getId() );
if( pSession )
pSession->startReplay( params );
}
else if( subCommand == "stop" )
{
auto pSession = m_objects->m_zone->getSession( player.getId() );
if( pSession )
pSession->stopReplay();
}
else
{
player.sendUrgent( subCommand + " is not a valid replay command." );
}
}
};

View file

@ -0,0 +1,86 @@
#include <ScriptObject.h>
#include <Script/NativeScriptManager.h>
#include <boost/format.hpp>
class Script : public DebugCommandScript
{
public:
Script() : DebugCommandScript( "script", "Script management commands", 0 )
{ }
virtual void run( Entity::Player& player, const std::string& args, const std::string& subCommand, const std::string& params )
{
if( subCommand == "unload" )
{
if ( subCommand == params )
player.sendDebug( "Command failed: requires name of script" );
else
if( m_objects->m_scriptMgr->getNativeScriptHandler().unloadScript( params ) )
player.sendDebug( "Unloaded script successfully." );
else
player.sendDebug( "Failed to unload script: " + params );
}
else if( subCommand == "find" || subCommand == "f" )
{
if( subCommand == params )
player.sendDebug( "Because reasons of filling chat with nonsense, please enter a search term" );
else
{
std::set< Core::Scripting::ScriptInfo* > scripts;
m_objects->m_scriptMgr->getNativeScriptHandler().findScripts( scripts, params );
if( !scripts.empty() )
{
player.sendDebug( "Found " + std::to_string( scripts.size() ) + " scripts" );
for( auto it = scripts.begin(); it != scripts.end(); ++it )
{
auto script = *it;
player.sendDebug( " - '" + script->library_name + "' loaded at @ 0x" +
boost::str( boost::format( "%|X|" ) % script->handle ) +
", num scripts: " + std::to_string( script->scripts.size() ) );
}
}
else
player.sendDebug( "No scripts found with search term: " + params );
}
}
else if( subCommand == "load" || subCommand == "l" )
{
if( subCommand == params )
player.sendDebug( "Command failed: requires relative path to script" );
else
{
if ( m_objects->m_scriptMgr->getNativeScriptHandler().loadScript( params ) )
player.sendDebug( "Loaded '" + params + "' successfully" );
else
player.sendDebug( "Failed to load '" + params + "'" );
}
}
else if( subCommand == "queuereload" || subCommand == "qrl" )
{
if( subCommand == params )
player.sendDebug( "Command failed: requires name of script to reload" );
else
{
m_objects->m_scriptMgr->getNativeScriptHandler().queueScriptReload( params );
player.sendDebug( "Queued script reload for script: " + params );
}
}
else if( subCommand == "build" || subCommand == "b" )
{
if( subCommand == params )
player.sendDebug( "Command failed: requires name of cmake target" );
else
{
}
}
else
{
player.sendDebug( "Unknown script subcommand: " + subCommand );
}
}
};

View file

@ -0,0 +1,17 @@
#include <ScriptObject.h>
#include <common/Version.h>
class ServerInfo : public DebugCommandScript
{
public:
ServerInfo() : DebugCommandScript( "serverinfo", "Displays server build information", 0 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string& subCommand, const std::string& params )
{
player.sendDebug( "Sapphire Zone " + Version::VERSION + "\nRev: " + Version::GIT_HASH );
player.sendDebug( "Compiled: " __DATE__ " " __TIME__ );
player.sendDebug( "Sessions: " + std::to_string( m_objects->m_zone->getSessionCount() ) );
}
};

View file

@ -0,0 +1,148 @@
#include <ScriptObject.h>
#include <Session.h>
#include <common/Network/PacketContainer.h>
#include <Network/GameConnection.h>
#include <common/Network/PacketDef/Zone/ServerZoneDef.h>
#include <common/Network/GamePacketNew.h>
#include <servers/sapphire_zone/Network/PacketWrappers/InitUIPacket.h>
#include <cinttypes>
class Set : public DebugCommandScript
{
public:
Set() : DebugCommandScript( "set", "Executes SET commands", 1 )
{ }
virtual void run( Entity::Player& player, const std::string& data, const std::string& subCommand, const std::string& params )
{
player.sendDebug( subCommand );
player.sendDebug( params );
if( ( ( subCommand == "pos" ) || ( subCommand == "posr" ) ) && ( params != "" ) )
{
int32_t posX;
int32_t posY;
int32_t posZ;
sscanf( params.c_str(), "%d %d %d", &posX, &posY, &posZ );
if( ( posX == 0xcccccccc ) || ( posY == 0xcccccccc ) || ( posZ == 0xcccccccc ) )
{
player.sendUrgent( "Syntaxerror." );
return;
}
if( subCommand == "pos" )
player.setPosition( static_cast< float >( posX ),
static_cast< float >( posY ),
static_cast< float >( posZ ) );
else
player.setPosition( player.getPos().x + static_cast< float >( posX ),
player.getPos().y + static_cast< float >( posY ),
player.getPos().z + static_cast< float >( posZ ) );
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcActorSetPos >
setActorPosPacket( player.getId() );
setActorPosPacket.data().x = player.getPos().x;
setActorPosPacket.data().y = player.getPos().y;
setActorPosPacket.data().z = player.getPos().z;
player.queuePacket( setActorPosPacket );
}
else if( ( subCommand == "tele" ) && ( params != "" ) )
{
int32_t aetheryteId;
sscanf( params.c_str(), "%i", &aetheryteId );
player.teleport( aetheryteId );
}
else if( ( subCommand == "discovery" ) && ( params != "" ) )
{
int32_t map_id;
int32_t discover_id;
sscanf( params.c_str(), "%i %i", &map_id, &discover_id );
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcDiscovery > discoveryPacket( player.getId() );
discoveryPacket.data().map_id = map_id;
discoveryPacket.data().map_part_id = discover_id;
player.queuePacket( discoveryPacket );
}
// else if( ( subCommand == "discovery_pos" ) && ( params != "" ) )
// {
// int32_t map_id;
// int32_t discover_id;
// int32_t pos_id;
// sscanf( params.c_str(), "%i %i %i", &pos_id, &map_id, &discover_id );
//
// std::string query2 = "UPDATE IGNORE `discoveryinfo` SET `discover_id` = '" + std::to_string( discover_id ) +
// "' WHERE `discoveryinfo`.`id` = " + std::to_string( pos_id ) + ";";
//
// std::string query1 = "INSERT IGNORE INTO `discoveryinfo` (`id`, `map_id`, `discover_id`) VALUES ('" + std::to_string( pos_id ) +
// "', '" + std::to_string( map_id ) +
// "', '" + std::to_string( discover_id ) + "')";
//
// g_charaDb.execute( query1 );
// g_charaDb.execute( query2 );
//
// }
else if( subCommand == "discovery_reset" )
{
player.resetDiscovery();
player.queuePacket( Network::Packets::Server::InitUIPacket( player ) );
}
else if( subCommand == "classjob" )
{
int32_t id;
sscanf( params.c_str(), "%d", &id );
if( player.getLevelForClass( static_cast< Common::ClassJob > ( id ) ) == 0 )
{
player.setLevelForClass( 1, static_cast< Common::ClassJob > ( id ) );
player.setClassJob( static_cast< Common::ClassJob > ( id ) );
}
else
player.setClassJob( static_cast< Common::ClassJob > ( id ) );
}
else if ( subCommand == "cfpenalty" )
{
int32_t minutes;
sscanf( params.c_str(), "%d", &minutes );
player.setCFPenaltyMinutes( minutes );
}
else if ( subCommand == "eorzeatime" )
{
uint64_t timestamp;
sscanf( params.c_str(), "%" SCNu64, &timestamp );
player.setEorzeaTimeOffset( timestamp );
player.sendNotice( "Eorzea time offset: " + std::to_string( timestamp ) );
}
else if ( subCommand == "model" )
{
uint32_t slot;
uint32_t val;
sscanf( params.c_str(), "%d %d", &slot, &val );
player.setModelForSlot( static_cast< Inventory::EquipSlot >( slot ), val );
player.sendModel();
player.sendDebug( "Model updated" );
}
else if ( subCommand == "mount" )
{
int32_t id;
sscanf( params.c_str(), "%d", &id );
player.dismount();
player.mount( id );
}
else
{
player.sendUrgent( subCommand + " is not a valid SET command." );
}
}
};

View file

@ -1,64 +0,0 @@
#ifndef _GAMECOMMAND_H_
#define _GAMECOMMAND_H_
#include <common/Common.h>
#include "Actor/Player.h"
#include "Forwards.h"
namespace Core {
class DebugCommandHandler;
class DebugCommand
{
public:
using pFunc = void ( DebugCommandHandler::* )( char *, Entity::Player&, boost::shared_ptr< DebugCommand > );
// String for the command
std::string m_commandName;
// command callback
pFunc m_pFunc;
// helptext
std::string m_helpText;
// userlevel needed to execute the command
uint8_t m_gmLevel;
DebugCommand( const std::string& n, pFunc functionPtr, const std::string& hText, uint8_t uLevel )
{
m_commandName = n;
m_pFunc = functionPtr;
m_helpText = hText;
m_gmLevel = uLevel;
}
~DebugCommand()
{
}
const std::string& getName() const
{
return m_commandName;
}
const std::string& getHelpText() const
{
return m_helpText;
}
uint8_t getRequiredGmLevel() const
{
return m_gmLevel;
}
};
}
#endif

View file

@ -1,657 +0,0 @@
#include <boost/lexical_cast.hpp>
#include <common/Common.h>
#include <common/Version.h>
#include <common/Network/GamePacketNew.h>
#include <common/Network/CommonNetwork.h>
#include <common/Util/UtilMath.h>
#include <common/Network/PacketContainer.h>
#include <common/Logging/Logger.h>
#include <common/Exd/ExdData.h>
#include <common/Database/DatabaseDef.h>
#include "DebugCommand.h"
#include "DebugCommandHandler.h"
#include "Network/PacketWrappers/ServerNoticePacket.h"
#include "Network/PacketWrappers/ActorControlPacket142.h"
#include "Network/PacketWrappers/ActorControlPacket143.h"
#include "Network/PacketWrappers/InitUIPacket.h"
#include "Network/GameConnection.h"
#include "Script/ScriptManager.h"
#include "Script/NativeScriptManager.h"
#include "Actor/Player.h"
#include "Actor/BattleNpc.h"
#include "Zone/Zone.h"
#include "ServerZone.h"
#include "StatusEffect/StatusEffect.h"
#include "Session.h"
#include <boost/make_shared.hpp>
#include <boost/format.hpp>
#include <cinttypes>
extern Core::Scripting::ScriptManager g_scriptMgr;
extern Core::Data::ExdData g_exdData;
extern Core::Logger g_log;
extern Core::ServerZone g_serverZone;
// instanciate and initialize commands
Core::DebugCommandHandler::DebugCommandHandler()
{
// Push all commands onto the register map ( command name - function - description - required GM level )
registerCommand( "set", &DebugCommandHandler::set, "Executes SET commands.", 1 );
registerCommand( "get", &DebugCommandHandler::get, "Executes GET commands.", 1 );
registerCommand( "add", &DebugCommandHandler::add, "Executes ADD commands.", 1 );
registerCommand( "inject", &DebugCommandHandler::injectPacket, "Loads and injects a premade packet.", 1 );
registerCommand( "injectc", &DebugCommandHandler::injectChatPacket, "Loads and injects a premade chat packet.", 1 );
registerCommand( "replay", &DebugCommandHandler::replay, "Replays a saved capture folder.", 1 );
registerCommand( "nudge", &DebugCommandHandler::nudge, "Nudges you forward/up/down.", 1 );
registerCommand( "info", &DebugCommandHandler::serverInfo, "Show server info.", 0 );
registerCommand( "unlock", &DebugCommandHandler::unlockCharacter, "Unlock character.", 1 );
registerCommand( "help", &DebugCommandHandler::help, "Shows registered commands.", 0 );
registerCommand( "script", &DebugCommandHandler::script, "Server script utilities.", 1 );
}
// clear all loaded commands
Core::DebugCommandHandler::~DebugCommandHandler()
{
for( auto it = m_commandMap.begin(); it != m_commandMap.end(); ++it )
( *it ).second.reset();
}
// add a command set to the register map
void Core::DebugCommandHandler::registerCommand( const std::string& n, DebugCommand::pFunc functionPtr,
const std::string& hText, uint8_t uLevel )
{
m_commandMap[std::string( n )] = boost::make_shared< DebugCommand >( n, functionPtr, hText, uLevel );
}
// try to retrieve the command in question, execute if found
void Core::DebugCommandHandler::execCommand( char * data, Entity::Player& player )
{
// define callback pointer
void ( DebugCommandHandler::*pf )( char *, Entity::Player&, boost::shared_ptr< DebugCommand > );
std::string commandString;
// check if the command has parameters
std::string tmpCommand = std::string( data );
std::size_t pos = tmpCommand.find_first_of( " " );
if( pos != std::string::npos )
// command has parameters, grab the first part
commandString = tmpCommand.substr( 0, pos );
else
// no parameters, just get the command
commandString = tmpCommand;
// try to retrieve the command
auto it = m_commandMap.find( commandString );
if( it == m_commandMap.end() )
// no command found, do something... or not
player.sendUrgent( "Command not found." );
else
{
if( player.getGmRank() < it->second->getRequiredGmLevel() )
{
player.sendUrgent( "You are not allowed to use this command." );
return;
}
// command found, call the callback function and pass parameters if present.
pf = ( *it ).second->m_pFunc;
( this->*pf )( data, player, ( *it ).second );
return;
}
}
///////////////////////////////////////////////////////////////////////////////////////
// Definition of the commands
///////////////////////////////////////////////////////////////////////////////////////
void Core::DebugCommandHandler::help( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
player.sendDebug( "Registered debug commands:" );
for ( auto cmd : m_commandMap )
{
if ( player.getGmRank( ) >= cmd.second->m_gmLevel )
{
player.sendDebug( " - " + cmd.first + " - " + cmd.second->getHelpText( ) );
}
}
}
void Core::DebugCommandHandler::set( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
std::string subCommand = "";
std::string params = "";
// check if the command has parameters
std::string tmpCommand = std::string( data + command->getName().length() + 1 );
std::size_t pos = tmpCommand.find_first_of( " " );
if( pos != std::string::npos )
// command has parameters, grab the first part
subCommand = tmpCommand.substr( 0, pos );
else
// no subcommand given
subCommand = tmpCommand;
if( command->getName().length() + 1 + pos + 1 < strlen( data ) )
params = std::string( data + command->getName().length() + 1 + pos + 1 );
g_log.debug( "[" + std::to_string( player.getId() ) + "] " +
"subCommand " + subCommand + " params: " + params );
if( ( ( subCommand == "pos" ) || ( subCommand == "posr" ) ) && ( params != "" ) )
{
int32_t posX;
int32_t posY;
int32_t posZ;
sscanf( params.c_str(), "%d %d %d", &posX, &posY, &posZ );
if( ( posX == 0xcccccccc ) || ( posY == 0xcccccccc ) || ( posZ == 0xcccccccc ) )
{
player.sendUrgent( "Syntaxerror." );
return;
}
if( subCommand == "pos" )
player.setPosition( static_cast< float >( posX ),
static_cast< float >( posY ),
static_cast< float >( posZ ) );
else
player.setPosition( player.getPos().x + static_cast< float >( posX ),
player.getPos().y + static_cast< float >( posY ),
player.getPos().z + static_cast< float >( posZ ) );
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcActorSetPos >
setActorPosPacket( player.getId() );
setActorPosPacket.data().x = player.getPos().x;
setActorPosPacket.data().y = player.getPos().y;
setActorPosPacket.data().z = player.getPos().z;
player.queuePacket( setActorPosPacket );
}
else if( ( subCommand == "tele" ) && ( params != "" ) )
{
int32_t aetheryteId;
sscanf( params.c_str(), "%i", &aetheryteId );
player.teleport( aetheryteId );
}
else if( ( subCommand == "discovery" ) && ( params != "" ) )
{
int32_t map_id;
int32_t discover_id;
sscanf( params.c_str(), "%i %i", &map_id, &discover_id );
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcDiscovery > discoveryPacket( player.getId() );
discoveryPacket.data().map_id = map_id;
discoveryPacket.data().map_part_id = discover_id;
player.queuePacket( discoveryPacket );
}
else if( ( subCommand == "discovery_pos" ) && ( params != "" ) )
{
int32_t map_id;
int32_t discover_id;
int32_t pos_id;
sscanf( params.c_str(), "%i %i %i", &pos_id, &map_id, &discover_id );
std::string query2 = "UPDATE IGNORE `discoveryinfo` SET `discover_id` = '" + std::to_string( discover_id ) +
"' WHERE `discoveryinfo`.`id` = " + std::to_string( pos_id ) + ";";
std::string query1 = "INSERT IGNORE INTO `discoveryinfo` (`id`, `map_id`, `discover_id`) VALUES ('" + std::to_string( pos_id ) +
"', '" + std::to_string( map_id ) +
"', '" + std::to_string( discover_id ) + "')";
g_charaDb.execute( query1 );
g_charaDb.execute( query2 );
}
else if( subCommand == "discovery_reset" )
{
player.resetDiscovery();
player.queuePacket( Network::Packets::Server::InitUIPacket( player ) );
}
else if( subCommand == "classjob" )
{
int32_t id;
sscanf( params.c_str(), "%d", &id );
if( player.getLevelForClass( static_cast< Common::ClassJob > ( id ) ) == 0 )
{
player.setLevelForClass( 1, static_cast< Common::ClassJob > ( id ) );
player.setClassJob( static_cast< Common::ClassJob > ( id ) );
}
else
player.setClassJob( static_cast< Common::ClassJob > ( id ) );
}
else if ( subCommand == "cfpenalty" )
{
int32_t minutes;
sscanf( params.c_str(), "%d", &minutes );
player.setCFPenaltyMinutes( minutes );
}
else if ( subCommand == "eorzeatime" )
{
uint64_t timestamp;
sscanf( params.c_str(), "%" SCNu64, &timestamp );
player.setEorzeaTimeOffset( timestamp );
player.sendNotice( "Eorzea time offset: " + std::to_string( timestamp ) );
}
else if ( subCommand == "model" )
{
uint32_t slot;
uint32_t val;
sscanf( params.c_str(), "%d %d", &slot, &val );
player.setModelForSlot( static_cast< Inventory::EquipSlot >( slot ), val );
player.sendModel();
player.sendDebug( "Model updated" );
}
else if ( subCommand == "mount" )
{
int32_t id;
sscanf( params.c_str(), "%d", &id );
player.dismount();
player.mount( id );
}
else
{
player.sendUrgent( subCommand + " is not a valid SET command." );
}
}
void Core::DebugCommandHandler::add( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
std::string subCommand;
std::string params = "";
// check if the command has parameters
std::string tmpCommand = std::string( data + command->getName().length() + 1 );
std::size_t pos = tmpCommand.find_first_of( " " );
if( pos != std::string::npos )
// command has parameters, grab the first part
subCommand = tmpCommand.substr( 0, pos );
else
// no subcommand given
subCommand = tmpCommand;
if( command->getName().length() + 1 + pos + 1 < strlen( data ) )
params = std::string( data + command->getName().length() + 1 + pos + 1 );
g_log.debug( "[" + std::to_string( player.getId() ) + "] " +
"subCommand " + subCommand + " params: " + params );
if( subCommand == "status" )
{
int32_t id;
int32_t duration;
uint16_t param;
sscanf( params.c_str(), "%d %d %hu", &id, &duration, &param );
StatusEffect::StatusEffectPtr effect( new StatusEffect::StatusEffect( id, player.getAsPlayer(), player.getAsPlayer(), duration, 3000 ) );
effect->setParam( param );
player.addStatusEffect( effect );
}
else if( subCommand == "title" )
{
uint32_t titleId;
sscanf( params.c_str(), "%u", &titleId );
player.addTitle( titleId );
player.sendNotice( "Added title (ID: " + std::to_string( titleId ) + ")" );
}
else if( subCommand == "spawn" )
{
int32_t model, name;
sscanf( params.c_str(), "%d %d", &model, &name );
Entity::BattleNpcPtr pBNpc( new Entity::BattleNpc( model, name, player.getPos() ) );
auto pZone = player.getCurrentZone();
pBNpc->setCurrentZone( pZone );
pZone->pushActor( pBNpc );
}
else if( subCommand == "op" )
{
// temporary research packet
int32_t opcode;
sscanf( params.c_str(), "%x", &opcode );
Network::Packets::GamePacketPtr pPe( new Network::Packets::GamePacket( opcode, 0x30, player.getId(), player.getId() ) );
player.queuePacket( pPe );
}
else if( subCommand == "actrl" )
{
// temporary research packet
int32_t opcode;
int32_t param1;
int32_t param2;
int32_t param3;
int32_t param4;
int32_t param5;
int32_t param6;
int32_t playerId;
sscanf( params.c_str(), "%x %x %x %x %x %x %x %x", &opcode, &param1, &param2, &param3, &param4, &param5, &param6, &playerId );
player.sendNotice( "Injecting ACTOR_CONTROL " + std::to_string( opcode ) );
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcActorControl143 > actorControl( playerId, player.getId() );
actorControl.data().category = opcode;
actorControl.data().param1 = param1;
actorControl.data().param2 = param2;
actorControl.data().param3 = param3;
actorControl.data().param4 = param4;
actorControl.data().param5 = param5;
actorControl.data().param6 = param6;
player.queuePacket( actorControl );
/*sscanf(params.c_str(), "%x %x %x %x %x %x %x", &opcode, &param1, &param2, &param3, &param4, &param5, &param6, &playerId);
Network::Packets::Server::ServerNoticePacket noticePacket( player, "Injecting ACTOR_CONTROL " + std::to_string( opcode ) );
player.queuePacket( noticePacket );
Network::Packets::Server::ActorControlPacket143 controlPacket( player, opcode,
param1, param2, param3, param4, param5, param6, playerId );
player.queuePacket( controlPacket );*/
}
else
{
player.sendUrgent( subCommand + " is not a valid ADD command." );
}
}
void Core::DebugCommandHandler::get( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
std::string subCommand;
std::string params = "";
// check if the command has parameters
std::string tmpCommand = std::string( data + command->getName().length() + 1 );
std::size_t pos = tmpCommand.find_first_of( " " );
if( pos != std::string::npos )
// command has parameters, grab the first part
subCommand = tmpCommand.substr( 0, pos );
else
// no subcommand given
subCommand = tmpCommand;
if( command->getName().length() + 1 + pos + 1 < strlen( data ) )
params = std::string( data + command->getName().length() + 1 + pos + 1 );
g_log.debug( "[" + std::to_string( player.getId() ) + "] " +
"subCommand " + subCommand + " params: " + params );
if( ( subCommand == "pos" ) )
{
int16_t map_id = g_exdData.m_zoneInfoMap[player.getCurrentZone()->getTerritoryId()].map_id;
player.sendNotice( "Pos:\n" +
std::to_string( player.getPos().x ) + "\n" +
std::to_string( player.getPos().y ) + "\n" +
std::to_string( player.getPos().z ) + "\n" +
std::to_string( player.getRotation() ) + "\nMapId: " +
std::to_string( map_id ) + "\nZoneID: " +
std::to_string(player.getCurrentZone()->getTerritoryId() ) + "\n" );
}
else
{
player.sendUrgent( subCommand + " is not a valid GET command." );
}
}
void Core::DebugCommandHandler::injectPacket( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
auto pSession = g_serverZone.getSession( player.getId() );
if( pSession )
pSession->getZoneConnection()->injectPacket( data + 7, player );
}
void Core::DebugCommandHandler::injectChatPacket( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
auto pSession = g_serverZone.getSession( player.getId() );
if( pSession )
pSession->getChatConnection()->injectPacket( data + 8, player );
}
void Core::DebugCommandHandler::replay( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
std::string subCommand;
std::string params = "";
// check if the command has parameters
std::string tmpCommand = std::string( data + command->getName().length() + 1 );
std::size_t pos = tmpCommand.find_first_of( " " );
if( pos != std::string::npos )
// command has parameters, grab the first part
subCommand = tmpCommand.substr( 0, pos );
else
// no subcommand given
subCommand = tmpCommand;
if( command->getName().length() + 1 + pos + 1 < strlen( data ) )
params = std::string( data + command->getName().length() + 1 + pos + 1 );
g_log.debug( "[" + std::to_string( player.getId() ) + "] " +
"subCommand " + subCommand + " params: " + params );
if( subCommand == "start" )
{
auto pSession = g_serverZone.getSession( player.getId() );
if( pSession )
pSession->startReplay( params );
}
else if( subCommand == "stop" )
{
auto pSession = g_serverZone.getSession( player.getId() );
if( pSession )
pSession->stopReplay();
}
else
{
player.sendUrgent( subCommand + " is not a valid replay command." );
}
}
void Core::DebugCommandHandler::nudge( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
std::string subCommand;
// check if the command has parameters
std::string tmpCommand = std::string( data + command->getName().length() + 1 );
std::size_t spos = tmpCommand.find_first_of( " " );
auto& pos = player.getPos();
int32_t offset = 0;
char direction[20];
memset( direction, 0, 20 );
sscanf( tmpCommand.c_str(), "%d %s", &offset, direction );
if( direction[0] == 'u' || direction[0] == '+' )
{
pos.y += offset;
player.sendNotice( "nudge: Placing up " + std::to_string( offset ) + " yalms" );
}
else if( direction[0] == 'd' || direction[0] == '-' )
{
pos.y -= offset;
player.sendNotice( "nudge: Placing down " + std::to_string( offset ) + " yalms" );
}
else
{
float angle = player.getRotation() + ( PI / 2 );
pos.x -= offset * cos( angle );
pos.z += offset * sin( angle );
player.sendNotice( "nudge: Placing forward " + std::to_string( offset ) + " yalms" );
}
if( offset != 0 )
{
Network::Packets::ZoneChannelPacket< Network::Packets::Server::FFXIVIpcActorSetPos >
setActorPosPacket( player.getId() );
setActorPosPacket.data().x = player.getPos().x;
setActorPosPacket.data().y = player.getPos().y;
setActorPosPacket.data().z = player.getPos().z;
setActorPosPacket.data().r16 = Math::Util::floatToUInt16Rot( player.getRotation() );
player.queuePacket( setActorPosPacket );
}
}
void Core::DebugCommandHandler::serverInfo( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
player.sendDebug( "SapphireServer " + Version::VERSION + "\nRev: " + Version::GIT_HASH );
player.sendDebug( "Compiled: " __DATE__ " " __TIME__ );
player.sendDebug( "Sessions: " + std::to_string( g_serverZone.getSessionCount() ) );
}
void Core::DebugCommandHandler::unlockCharacter( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command )
{
player.unlock();
}
void Core::DebugCommandHandler::script( char* data, Entity::Player &player, boost::shared_ptr< DebugCommand > command )
{
std::string subCommand;
std::string params = "";
// check if the command has parameters
std::string tmpCommand = std::string( data + command->getName().length() + 1 );
std::size_t pos = tmpCommand.find_first_of( " " );
if( pos != std::string::npos )
// command has parameters, grab the first part
subCommand = tmpCommand.substr( 0, pos );
else
// no subcommand given
subCommand = tmpCommand;
// todo: fix params so it's empty if there's no params
if( command->getName().length() + 1 + pos + 1 < strlen( data ) )
params = std::string( data + command->getName().length() + 1 + pos + 1 );
g_log.debug( "[" + std::to_string( player.getId() ) + "] " +
"subCommand " + subCommand + " params: " + params );
if( subCommand == "unload" )
{
if ( subCommand == params )
player.sendDebug( "Command failed: requires name of script" );
else
if( g_scriptMgr.getNativeScriptHandler().unloadScript( params ) )
player.sendDebug( "Unloaded script successfully." );
else
player.sendDebug( "Failed to unload script: " + params );
}
else if( subCommand == "find" || subCommand == "f" )
{
if( subCommand == params )
player.sendDebug( "Because reasons of filling chat with nonsense, please enter a search term" );
else
{
std::set< Core::Scripting::ScriptInfo* > scripts;
g_scriptMgr.getNativeScriptHandler().findScripts( scripts, params );
if( !scripts.empty() )
{
player.sendDebug( "Found " + std::to_string( scripts.size() ) + " scripts" );
for( auto it = scripts.begin(); it != scripts.end(); ++it )
{
auto script = *it;
player.sendDebug( " - '" + script->library_name + "' loaded at @ 0x" +
boost::str( boost::format( "%|X|" ) % script->handle ) +
", num scripts: " + std::to_string( script->scripts.size() ) );
}
}
else
player.sendDebug( "No scripts found with search term: " + params );
}
}
else if( subCommand == "load" || subCommand == "l" )
{
if( subCommand == params )
player.sendDebug( "Command failed: requires relative path to script" );
else
{
if ( g_scriptMgr.getNativeScriptHandler().loadScript( params ) )
player.sendDebug( "Loaded '" + params + "' successfully" );
else
player.sendDebug( "Failed to load '" + params + "'" );
}
}
else if( subCommand == "queuereload" || subCommand == "qrl" )
{
if( subCommand == params )
player.sendDebug( "Command failed: requires name of script to reload" );
else
{
g_scriptMgr.getNativeScriptHandler().queueScriptReload( params );
player.sendDebug( "Queued script reload for script: " + params );
}
}
else if( subCommand == "build" || subCommand == "b" )
{
if( subCommand == params )
player.sendDebug( "Command failed: requires name of cmake target" );
else
{
}
}
else
{
player.sendDebug( "Unknown script subcommand: " + subCommand );
}
}

View file

@ -1,52 +0,0 @@
#ifndef _GAMECOMMANDHANDLER_H_
#define _GAMECOMMANDHANDLER_H_
#include <map>
#include "DebugCommand.h"
#include <common/Common.h>
#include "Forwards.h"
namespace Core {
// handler for in game commands
class DebugCommandHandler
{
private:
// container mapping command string to command object
std::map< std::string, boost::shared_ptr< DebugCommand > > m_commandMap;
public:
DebugCommandHandler();
~DebugCommandHandler();
// register command to command map
void registerCommand( const std::string& n, DebugCommand::pFunc, const std::string& hText, uint8_t uLevel );
// execute command if registered
void execCommand( char * data, Entity::Player& player );
// help command
void help( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
// command handler callbacks
void set( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void get( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void add( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
//void debug( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void injectPacket( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void injectChatPacket( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void replay( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void nudge( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void serverInfo( char * data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void unlockCharacter( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
void script( char* data, Entity::Player& player, boost::shared_ptr< DebugCommand > command );
};
}
#endif

View file

@ -12,11 +12,9 @@
#include "Session.h"
#include "Zone/Zone.h"
#include "Network/PacketWrappers/InitUIPacket.h"
#include "DebugCommand/DebugCommandHandler.h"
#include "Actor/Player.h"
#include "Forwards.h"
extern Core::DebugCommandHandler g_gameCommandMgr;
extern Core::Logger g_log;
extern Core::ServerZone g_serverZone;

View file

@ -26,7 +26,6 @@
#include "Network/PacketWrappers/EventFinishPacket.h"
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
#include "DebugCommand/DebugCommandHandler.h"
#include "Actor/Player.h"
#include "Inventory/Inventory.h"
#include "Forwards.h"
@ -37,7 +36,6 @@
extern Core::Logger g_log;
extern Core::ServerZone g_serverZone;
extern Core::Data::ExdData g_exdData;
extern Core::DebugCommandHandler g_gameCommandMgr;
using namespace Core::Common;
using namespace Core::Network::Packets;

View file

@ -27,19 +27,19 @@
#include "Network/PacketWrappers/EventFinishPacket.h"
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
#include "DebugCommand/DebugCommandHandler.h"
#include "Actor/Player.h"
#include "Inventory/Inventory.h"
#include "Forwards.h"
#include "Event/EventHelper.h"
#include "Action/Action.h"
#include "Action/ActionTeleport.h"
#include "Script/ScriptManager.h"
extern Core::Logger g_log;
extern Core::ServerZone g_serverZone;
extern Core::TerritoryMgr g_territoryMgr;
extern Core::Data::ExdData g_exdData;
extern Core::DebugCommandHandler g_gameCommandMgr;
extern Core::Scripting::ScriptManager g_scriptMgr;
using namespace Core::Common;
using namespace Core::Network::Packets;
@ -127,6 +127,15 @@ void Core::Network::GameConnection::gm1Handler( const Packets::GamePacket& inPac
return;
auto targetPlayer = targetActor->getAsPlayer();
// auto script = g_scriptMgr.getNativeScriptHandler().getScript< GmCommandScript >( commandId );
// if( script )
// {
// script->gm1Handler( param1, param2, param3 );
// return;
// }
//
// player.sendUrgent( "GM1 Command not implemented: " + std::to_string( commandId ) );
switch( commandId )
{
case GmCommand::Lv:

View file

@ -19,7 +19,6 @@
#include "Network/PacketWrappers/ActorControlPacket143.h"
#include "Network/PacketWrappers/ActorControlPacket144.h"
#include "DebugCommand/DebugCommandHandler.h"
#include "Actor/Player.h"
#include "Inventory/Inventory.h"
#include "Forwards.h"
@ -27,7 +26,6 @@
extern Core::Logger g_log;
extern Core::ServerZone g_serverZone;
extern Core::Data::ExdData g_exdData;
extern Core::DebugCommandHandler g_gameCommandMgr;
using namespace Core::Common;
using namespace Core::Network::Packets;

View file

@ -29,7 +29,7 @@
#include "Network/PacketWrappers/EventFinishPacket.h"
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
#include "DebugCommand/DebugCommandHandler.h"
#include "Script/ScriptManager.h"
#include "Actor/Player.h"
#include "Inventory/Inventory.h"
#include "Forwards.h"
@ -42,7 +42,7 @@ extern Core::Logger g_log;
extern Core::ServerZone g_serverZone;
extern Core::TerritoryMgr g_territoryMgr;
extern Core::Data::ExdData g_exdData;
extern Core::DebugCommandHandler g_gameCommandMgr;
extern Core::Scripting::ScriptManager g_scriptMgr;
using namespace Core::Common;
using namespace Core::Network::Packets;
@ -493,7 +493,7 @@ void Core::Network::GameConnection::chatHandler( const Packets::GamePacket& inPa
if( chatString.at( 0 ) == '!' )
{
// execute game console command
g_gameCommandMgr.execCommand( const_cast< char * >( chatString.c_str() ) + 1, player );
g_scriptMgr.debugCommandHandler( chatString.substr( 1 ), player );
return;
}

View file

@ -19,8 +19,6 @@
#include "Network/PacketWrappers/PlayerStateFlagsPacket.h"
#include "DebugCommand/DebugCommandHandler.h"
#include "Actor/Player.h"
#include "Forwards.h"

View file

@ -1,13 +1,19 @@
#ifndef NATIVE_SCRIPT_API
#define NATIVE_SCRIPT_API
#include "ScriptManager.h"
#include <string>
#include <typeinfo>
#include <typeindex>
#include <utility>
#include <Actor/Actor.h>
#include <Actor/Player.h>
#include <StatusEffect/StatusEffect.h>
#include <common/Logging/Logger.h>
#include <ServerZone.h>
#include <common/Exd/ExdData.h>
#ifdef _MSC_VER
#define EXPORT __declspec( dllexport )
@ -21,16 +27,28 @@ using namespace Core;
#define EVENTSCRIPT_AETHERYTE_ID 0x50000
#define EVENTSCRIPT_AETHERNET_ID 0x50001
class SapphireObjects
{
public:
SapphireObjects() = default;
Core::Logger* m_logger;
Core::ServerZone* m_zone;
Core::Scripting::ScriptManager* m_scriptMgr;
Core::Data::ExdData* m_exd;
};
class ScriptObject
{
protected:
uint32_t m_id;
std::size_t m_type;
SapphireObjects* m_objects;
public:
ScriptObject( uint32_t id, std::size_t type ) :
ScriptObject( uint32_t id, const type_info& type ) :
m_id( id ),
m_type( type )
m_type( type.hash_code() )
{ }
virtual uint32_t getId() const
@ -38,18 +56,28 @@ public:
return m_id;
}
virtual void setId( const uint32_t id )
{
m_id = id;
}
virtual std::size_t getType() const
{
return m_type;
}
virtual void setObjects( SapphireObjects* ptr )
{
m_objects = ptr;
}
};
class StatusEffectScript : public ScriptObject
{
public:
StatusEffectScript( uint32_t effectId ) :
ScriptObject( effectId, typeid( StatusEffectScript ).hash_code() )
explicit StatusEffectScript( uint32_t effectId ) :
ScriptObject( effectId, typeid( StatusEffectScript ) )
{ }
virtual void onTick( Entity::Actor& actor ) { }
@ -66,8 +94,8 @@ public:
class ActionScript : public ScriptObject
{
public:
ActionScript( uint32_t abilityId ) :
ScriptObject( abilityId, typeid( ActionScript ).hash_code() )
explicit ActionScript( uint32_t abilityId ) :
ScriptObject( abilityId, typeid( ActionScript ) )
{ }
virtual void onStart( Entity::Actor& sourceActor, Entity::Actor& targetActor ) { }
@ -79,8 +107,8 @@ public:
class EventScript : public ScriptObject
{
public:
EventScript( uint32_t questId ) :
ScriptObject( questId, typeid( EventScript ).hash_code() )
explicit EventScript( uint32_t questId ) :
ScriptObject( questId, typeid( EventScript ) )
{ }
virtual void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) { }
@ -97,19 +125,63 @@ public:
class BattleNpcScript : public ScriptObject
{
public:
BattleNpcScript( uint32_t npcId ) :
ScriptObject( npcId, typeid( BattleNpcScript ).hash_code() )
explicit BattleNpcScript( uint32_t npcId ) :
ScriptObject( npcId, typeid( BattleNpcScript ) )
{ }
};
class ZoneScript : public ScriptObject
{
public:
ZoneScript( uint32_t zoneId ) :
ScriptObject( zoneId, typeid( ZoneScript ).hash_code() )
explicit ZoneScript( uint32_t zoneId ) :
ScriptObject( zoneId, typeid( ZoneScript ) )
{ }
virtual void onZoneInit() { }
};
class GmCommandScript : public ScriptObject
{
public:
explicit GmCommandScript( uint32_t cmdId ) :
ScriptObject( cmdId, typeid( GmCommandScript ) )
{ }
virtual void gm1Handler( uint32_t param1, uint32_t param2, uint32_t param3 ) { }
virtual void gm2Handler( const std::string& param1 ) { }
};
class DebugCommandScript : public ScriptObject
{
protected:
std::string m_cmd;
std::string m_helpText;
uint8_t m_gmLevel;
public:
explicit DebugCommandScript( const std::string& cmd, const std::string& helpText, uint8_t gmLevel) :
ScriptObject( 0, typeid( DebugCommandScript ) ),
m_cmd( cmd ),
m_helpText( helpText ),
m_gmLevel( gmLevel )
{ }
virtual const std::string& getCmd()
{
return m_cmd;
}
virtual const uint8_t getGmLevel()
{
return m_gmLevel;
}
virtual const std::string getHelpText()
{
return m_helpText;
}
virtual void run( Entity::Player& player, const std::string& args, const std::string& subCommand, const std::string& params ) { }
};
#endif

View file

@ -1,8 +1,30 @@
#include <ServerZone.h>
#include <common/Exd/ExdData.h>
#include "NativeScriptManager.h"
#include "ScriptManager.h"
extern Core::Scripting::ScriptManager g_scriptMgr;
extern Core::Data::ExdData g_exdData;
extern Core::Logger g_log;
extern Core::ServerZone g_serverZone;
namespace Core {
namespace Scripting {
NativeScriptManager::NativeScriptManager() :
m_objects( new SapphireObjects )
{
m_objects->m_logger = &g_log;
m_objects->m_zone = &g_serverZone;
m_objects->m_scriptMgr = &g_scriptMgr;
m_objects->m_exd = &g_exdData;
}
NativeScriptManager::~NativeScriptManager()
{
delete m_objects;
}
bool NativeScriptManager::loadScript( const std::string& path )
{
auto module = m_loader.loadModule( path );
@ -27,6 +49,11 @@ namespace Scripting {
auto script = scripts[i];
module->scripts.push_back( script );
script->setObjects( m_objects );
if( script->getId() == 0 )
script->setId( m_allocatedScriptIds[script->getType()]++ );
m_scripts[script->getType()][script->getId()] = script;
success = true;

View file

@ -20,15 +20,18 @@ namespace Scripting {
{
protected:
std::unordered_map< std::size_t, std::unordered_map< uint32_t, ScriptObject* > > m_scripts;
std::map< std::size_t, uint32_t > m_allocatedScriptIds;
ScriptLoader m_loader;
SapphireObjects* m_objects;
std::queue< std::string > m_scriptLoadQueue;
bool unloadScript( ScriptInfo* info );
public:
NativeScriptManager( ) = default;
NativeScriptManager();
~NativeScriptManager();
bool loadScript( const std::string& path );
bool unloadScript( const std::string& name );
@ -40,7 +43,7 @@ namespace Scripting {
const std::string getModuleExtension();
bool isModuleLoaded( const std::string& name );
template< typename T >
template< class T >
T* getScript( uint32_t scriptId )
{
auto type = typeid( T ).hash_code();
@ -51,6 +54,14 @@ namespace Scripting {
return dynamic_cast< T* >( script->second );
}
template< class T >
std::unordered_map< uint32_t, ScriptObject* >& getScriptsOfType()
{
auto type = typeid( T ).hash_code();
return m_scripts[type];
};
};

View file

@ -20,9 +20,6 @@
#include <boost/format.hpp>
#include <boost/foreach.hpp>
// enable the ambiguity fix for every platform to avoid #define nonsense
#define WIN_AMBIGUITY_FIX
#include <libraries/external/watchdog/Watchdog.h>
extern Core::Logger g_log;
@ -50,7 +47,8 @@ bool Core::Scripting::ScriptManager::init()
std::set< std::string > files;
loadDir( g_serverZone.getConfig()->getValue< std::string >( "Settings.General.Scripts.Path", "./compiledscripts/" ),
files, m_nativeScriptManager->getModuleExtension() );
files,
m_nativeScriptManager->getModuleExtension() );
uint32_t scriptsFound = 0;
uint32_t scriptsLoaded = 0;
@ -65,7 +63,7 @@ bool Core::Scripting::ScriptManager::init()
scriptsLoaded++;
}
g_log.info( "ScriptManager: Loaded " + std::to_string( scriptsLoaded ) + "/" + std::to_string( scriptsFound ) + " scripts successfully" );
g_log.info( "ScriptManager: Loaded " + std::to_string( scriptsLoaded ) + "/" + std::to_string( scriptsFound ) + " modules successfully" );
watchDirectories();
@ -89,17 +87,19 @@ void Core::Scripting::ScriptManager::watchDirectories()
return;
}
for( auto path : paths )
for( const auto& path : paths )
{
if( m_nativeScriptManager->isModuleLoaded( path.stem().string() ) )
{
g_log.debug( "Reloading changed script: " + path.stem().string() );
auto name = path.stem().string();
m_nativeScriptManager->queueScriptReload( path.stem( ).string( ));
if( m_nativeScriptManager->isModuleLoaded( name ) )
{
g_log.debug( "Reloading changed script: " + name );
m_nativeScriptManager->queueScriptReload( name );
}
else
{
g_log.debug( "Loading new script: " + path.stem().string() );
g_log.debug( "Loading new script: " + name );
m_nativeScriptManager->loadScript( path.string() );
}
@ -110,7 +110,7 @@ void Core::Scripting::ScriptManager::watchDirectories()
void Core::Scripting::ScriptManager::loadDir( const std::string& dirname, std::set<std::string> &files, const std::string& ext )
{
g_log.info( "ScriptEngine: loading scripts from " + dirname );
g_log.info( "ScriptManager: loading scripts from " + dirname );
boost::filesystem::path targetDir( dirname );
@ -342,6 +342,74 @@ bool Core::Scripting::ScriptManager::onZoneInit( ZonePtr pZone )
return false;
}
bool Core::Scripting::ScriptManager::gm1Handler( uint32_t cmdId, uint32_t param1, uint32_t param2, uint32_t param3 )
{
auto script = m_nativeScriptManager->getScript< GmCommandScript >( cmdId );
if( script )
{
script->gm1Handler( param1, param2, param3 );
return true;
}
return false;
}
bool Core::Scripting::ScriptManager::gm2Handler( uint32_t cmdId, const std::string& param1 )
{
auto script = m_nativeScriptManager->getScript< GmCommandScript >( cmdId );
if( script )
{
script->gm2Handler( param1 );
return true;
}
return false;
}
bool Core::Scripting::ScriptManager::debugCommandHandler( const std::string& cmd, Entity::Player& player )
{
std::string command, params, subCommand;
auto cmdPos = cmd.find_first_of( ' ' );
if( cmdPos != std::string::npos )
{
command = cmd.substr( 0, cmdPos );
params = cmd.substr( cmdPos + 1 );
auto p = params.find_first_of( ' ' );
if( p != std::string::npos )
{
subCommand = params.substr( 0, p );
params = params.substr( subCommand.length() + 1 );
}
else
subCommand = params;
}
else
command = cmd;
g_log.debug( "[" + std::to_string( player.getId() ) + "] " +
"subCommand: " + subCommand + " params: " + params );
for( std::pair< uint32_t, ScriptObject* > pair : m_nativeScriptManager->getScriptsOfType< DebugCommandScript >() )
{
if( pair.second == nullptr )
continue;
auto script = dynamic_cast< DebugCommandScript* >( pair.second );
if( player.getGmRank() >= script->getGmLevel() && script->getCmd() == command )
{
script->run( player, cmd, subCommand, params );
return true;
}
}
return false;
}
Scripting::NativeScriptManager& Core::Scripting::ScriptManager::getNativeScriptHandler()
{
return *m_nativeScriptManager;

View file

@ -59,6 +59,10 @@ namespace Core
bool onEventHandlerReturn( Entity::Player& player, uint32_t eventId, uint16_t subEvent, uint16_t param1, uint16_t param2, uint16_t param3 );
bool onEventHandlerTradeReturn( Entity::Player& player, uint32_t eventId, uint16_t subEvent, uint16_t param, uint32_t catalogId );
bool gm1Handler( uint32_t cmdId, uint32_t param1, uint32_t param2, uint32_t param3 );
bool gm2Handler( uint32_t cmdId, const std::string& param1 );
bool debugCommandHandler( const std::string& cmd, Entity::Player& player );
void loadDir( const std::string& dirname, std::set<std::string> &files, const std::string& ext );

View file

@ -24,7 +24,7 @@
#include "Zone/TerritoryMgr.h"
#include "DebugCommand/DebugCommandHandler.h"
#include "Actor/Player.h"
#include "Script/ScriptManager.h"
#include "Linkshell/LinkshellMgr.h"
@ -37,7 +37,6 @@
#include <common/Util/Util.h>
Core::Logger g_log;
Core::DebugCommandHandler g_gameCommandMgr;
Core::Scripting::ScriptManager g_scriptMgr;
Core::Data::ExdData g_exdData;
Core::Data::ExdDataGenerated g_exdDataGen;