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

refactor script api, base script loading impl

This commit is contained in:
GokuWeedLord 2017-12-10 15:31:48 +11:00
parent 076b2591d4
commit a4453a378e
8 changed files with 236 additions and 30 deletions

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 3.2)
project(Sapphire_Script) project(Sapphire_Script)
file(GLOB SCRIPT_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h") file(GLOB SCRIPT_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
@ -7,21 +7,20 @@ file(GLOB_RECURSE SCRIPT_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
include_directories("../../src/servers/") include_directories("../../src/servers/")
include_directories("../../src/servers/Server_Zone/") include_directories("../../src/servers/Server_Zone/")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/")
foreach(_sourcefile "${SCRIPT_FILES}") foreach(_sourcefile "${SCRIPT_FILES}")
get_filename_component(_file "${_sourcefile}" NAME_WE) get_filename_component(_file "${_sourcefile}" NAME_WE)
add_library("${_file}" MODULE "${_sourcefile}" "${SCRIPT_INCLUDE_FILES}") add_library("${_file}" MODULE "${_sourcefile}" "${SCRIPT_INCLUDE_FILES}")
message("adding library ${_file}")
add_dependencies("${_file}" server_zone) add_dependencies("${_file}" server_zone)
set_target_properties("${_file}" PROPERTIES set_target_properties("${_file}" PROPERTIES
CXX_STANDARD 14 CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON CXX_EXTENSIONS ON
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/"
RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/"
RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/"
) )
endforeach(_sourcefile "${SCRIPT_FILES}") endforeach(_sourcefile "${SCRIPT_FILES}")

View file

@ -0,0 +1,15 @@
//#include "../ScriptObject.h"
//
//class AbilityScript3 : public AbilityScript
//{
//public:
// AbilityScript3() : AbilityScript( "AbilityScript3", 3 )
// {}
//
// virtual void onCastFinish( Core::Entity::Player player, Core::Entity::ActorPtr targetActor )
// {
// player.addStatusEffectByIdIfNotExist( 50, 20000, player, 30 );
// }
//};
//
//EXPORT_ABILITYSCRIPT( AbilityScript3 )

View file

@ -6,10 +6,11 @@ public:
StatusEffect50() : StatusEffectScript( "StatusEffect50", 50 ) StatusEffect50() : StatusEffectScript( "StatusEffect50", 50 )
{} {}
virtual void onTick( Core::Entity::ActorPtr actor ) // virtual void onTick( Core::Entity::ActorPtr actor )
{ // {
// if( actor->isPlayer() )
} // actor->getAsPlayer()->sendDebug( "tick tock bitch" );
// }
}; };
EXPORT_STATUSEFFECTSCRIPT( StatusEffect50 ) EXPORT_STATUSEFFECTSCRIPT( StatusEffect50 )

View file

@ -11,9 +11,9 @@ namespace Core {
return m_statusEffectScripts.at( statusId ); return m_statusEffectScripts.at( statusId );
} }
AbilityScript* NativeScript::getAbilityScript( uint32_t abilityId ) ActionScript* NativeScript::getAbilityScript( uint32_t abilityId )
{ {
return m_abilityScripts.at( abilityId ); return m_actionScripts.at( abilityId );
} }
QuestScript* NativeScript::getQuestScript( uint32_t questId ) QuestScript* NativeScript::getQuestScript( uint32_t questId )
@ -38,7 +38,7 @@ namespace Core {
void NativeScript::removeAbilityScript( uint32_t abilityId ) void NativeScript::removeAbilityScript( uint32_t abilityId )
{ {
m_abilityScripts.erase( abilityId ); m_actionScripts.erase( abilityId );
} }
void NativeScript::removeQuestScript( uint32_t questId ) void NativeScript::removeQuestScript( uint32_t questId )
@ -51,8 +51,39 @@ namespace Core {
m_battleNpcScripts.erase( npcId ); m_battleNpcScripts.erase( npcId );
} }
void NativeScript::loadScript( std::string path )
{
// auto handle = m_loader.loadModule( path );
// if( handle )
// {
// // todo: this is shit
// if( auto script = m_loader.getScriptObject< StatusEffectScript >( handle ) )
// {
// m_statusEffectScripts.insert( std::make_pair( script->getEffectId(), script ) );
// }
// else if( auto script = m_loader.getScriptObject< ActionScript >( handle ) )
// {
// m_actionScripts.insert( std::make_pair( script->getActionId(), script ) );
// }
// else if( auto script = m_loader.getScriptObject< QuestScript >( handle ) )
// {
// m_questScripts.insert( std::make_pair( script->getQuestId(), script ) );
// }
// else if( auto script = m_loader.getScriptObject< BattleNpcScript >( handle ) )
// {
// m_battleNpcScripts.insert( std::make_pair( script->getNpcId(), script ) );
// }
// else if( auto script = m_loader.getScriptObject< ZoneScript >( handle ) )
// {
// m_zoneScripts.insert( std::make_pair( script->getZoneId(), script ) );
// }
// else
// {
// // unload anything which doesn't have a suitable export
// m_loader.unloadScript( handle );
// }
// }
}
boost::shared_ptr< NativeScript > create_script_engine( ) boost::shared_ptr< NativeScript > create_script_engine( )

View file

@ -10,6 +10,7 @@
#include <Server_Common/Crypt/md5.h> #include <Server_Common/Crypt/md5.h>
#include "NativeScriptApi.h" #include "NativeScriptApi.h"
#include "ScriptLoader.h"
namespace Core { namespace Core {
namespace Scripting { namespace Scripting {
@ -18,16 +19,18 @@ namespace Core {
{ {
protected: protected:
std::unordered_map< uint32_t, StatusEffectScript* > m_statusEffectScripts; std::unordered_map< uint32_t, StatusEffectScript* > m_statusEffectScripts;
std::unordered_map< uint32_t, AbilityScript* > m_abilityScripts; std::unordered_map< uint32_t, ActionScript* > m_actionScripts;
std::unordered_map< uint32_t, QuestScript* > m_questScripts; std::unordered_map< uint32_t, QuestScript* > m_questScripts;
std::unordered_map< uint32_t, BattleNpcScript* > m_battleNpcScripts; std::unordered_map< uint32_t, BattleNpcScript* > m_battleNpcScripts;
std::unordered_map< uint32_t, ZoneScript* > m_zoneScripts; std::unordered_map< uint32_t, ZoneScript* > m_zoneScripts;
ScriptLoader m_loader;
public: public:
NativeScript( ); NativeScript( );
StatusEffectScript* getStatusEffectScript( uint32_t statusId ); StatusEffectScript* getStatusEffectScript( uint32_t statusId );
AbilityScript* getAbilityScript( uint32_t abilityId ); ActionScript* getAbilityScript( uint32_t abilityId );
QuestScript* getQuestScript( uint32_t questId ); QuestScript* getQuestScript( uint32_t questId );
BattleNpcScript* getBattleNpcScript( uint32_t npcId ); BattleNpcScript* getBattleNpcScript( uint32_t npcId );
ZoneScript* getZoneScript( uint32_t zoneId ); ZoneScript* getZoneScript( uint32_t zoneId );
@ -38,6 +41,8 @@ namespace Core {
void removeBattleNpcScript( uint32_t npcId ); void removeBattleNpcScript( uint32_t npcId );
void loadScript( std::string );
void unloadScript( std::string );
void clearAllScripts(); void clearAllScripts();
}; };

View file

@ -60,24 +60,24 @@ public:
}; };
class AbilityScript : public ScriptObject class ActionScript : public ScriptObject
{ {
protected: protected:
const uint32_t m_abilityId; const uint32_t m_actionId;
public: public:
AbilityScript( std::string name, uint32_t abilityId ) : ActionScript( std::string name, uint32_t abilityId ) :
ScriptObject( name ), ScriptObject( name ),
m_abilityId( abilityId ) m_actionId( abilityId )
{ } { }
const uint32_t GetAbilityId( ) const uint32_t getActionId()
{ {
return m_abilityId; return m_actionId;
} }
virtual void onStart( Core::Entity::Actor sourceActor, Core::Entity::Actor targetActor ) { } virtual void onStart( Core::Entity::Actor sourceActor, Core::Entity::ActorPtr targetActor ) { }
virtual void onCastFinish(Core::Entity::Player player, Core::Entity::ActorPtr targetActor) { } virtual void onCastFinish( Core::Entity::Player player, Core::Entity::ActorPtr targetActor ) { }
virtual void onInterrupt( Core::Entity::Actor sourceActor/*, Core::Entity::Actor targetActor*/ ) { } virtual void onInterrupt( Core::Entity::Actor sourceActor/*, Core::Entity::Actor targetActor*/ ) { }
}; };
@ -132,6 +132,10 @@ public:
m_zoneId( zoneId ) m_zoneId( zoneId )
{ } { }
const uint32_t getZoneId()
{
return m_zoneId;
}
virtual void onZoneInit() { } virtual void onZoneInit() { }
virtual void onEnterZone( Core::Entity::Player pPlayer, uint32_t eventId, uint16_t param1, uint16_t param2 ) { } virtual void onEnterZone( Core::Entity::Player pPlayer, uint32_t eventId, uint16_t param1, uint16_t param2 ) { }

View file

@ -0,0 +1,107 @@
#include "ScriptLoader.h"
#include <Server_Common/Logging/Logger.h>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
extern Core::Logger g_log;
const std::string Core::Scripting::ScriptLoader::getModuleExtension()
{
#ifdef _WIN32
return ".dll";
#elif __APPLE__
return ".dylib";
#else
return ".so";
#endif
}
bool Core::Scripting::ScriptLoader::unloadModule( ModuleHandle handle )
{
#ifdef _WIN32
bool success = FreeLibrary( handle ) != 0;
#else
bool success = dlclose( handle ) == 0;
#endif
if( !success )
{
g_log.fatal( "Failed to unload module @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) );
return false;
}
g_log.debug( "Unloaded module @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) );
return true;
}
ModuleHandle Core::Scripting::ScriptLoader::loadModule( std::string path )
{
#ifdef _WIN32
ModuleHandle handle = LoadLibrary( path.c_str() );
#else
ModuleHandle handle = dlopen( path.c_str(), RTLD_LAZY );
#endif
if( !handle )
{
g_log.error( "Failed to load module from: " + path );
return NULL;
}
g_log.info( "Loaded module from '" + path + "' @ 0x" + boost::str( boost::format( "%|08X|" ) % handle ) );
boost::filesystem::path f( path );
m_moduleMap.insert( std::make_pair( f.stem().string(), handle ) );
return handle;
}
template< typename T >
T* Core::Scripting::ScriptLoader::getScriptObject( ModuleHandle handle )
{
typedef T* (*getScriptObjectType)();
auto fn = boost::str( boost::format( "get%1%" ) % typeid( T ).name() );
g_log.info( "getting symbol: " + fn );
#ifdef _WIN32
getScriptObjectType func = reinterpret_cast< getScriptObjectType >( GetProcAddress( handle, fn.c_str() ) );
#else
getScriptObjectType func = reinterpret_cast< getScriptObjectType >( dlsym( handle, fn.c_str() ) );
#endif
if( func )
return func();
else
return nullptr;
}
bool Core::Scripting::ScriptLoader::unloadScript( std::string name )
{
auto moduleHandle = m_moduleMap.at( name );
if( moduleHandle )
{
return unloadModule( moduleHandle );
}
g_log.info( "Module '" + name + "' is not loaded" );
return false;
}
bool Core::Scripting::ScriptLoader::unloadScript( ModuleHandle handle )
{
for( auto it = m_moduleMap.begin(); it != m_moduleMap.end(); ++it )
{
if( it->second == handle )
{
m_moduleMap.erase( it );
return unloadModule( handle );
}
}
return false;
}

View file

@ -0,0 +1,44 @@
#ifndef SAPPHIRE_SCRIPTLOADER_H
#define SAPPHIRE_SCRIPTLOADER_H
#include <string>
#include "NativeScriptApi.h"
#ifdef _WIN32
#include <windows.h>
#include <unordered_map>
typedef HMODULE ModuleHandle;
#else
#include <dlfcn.h>
typedef void* ModuleHandle;
#endif
namespace Core {
namespace Scripting {
class ScriptLoader {
protected:
std::unordered_map< std::string, ModuleHandle > m_moduleMap;
bool unloadModule( ModuleHandle );
public:
ScriptLoader() = default;
const std::string getModuleExtension();
ModuleHandle loadModule( std::string );
bool unloadScript( std::string );
bool unloadScript( ModuleHandle );
template< typename T >
T* getScriptObject( ModuleHandle );
};
}
}
#endif //SAPPHIRE_SCRIPTLOADER_H