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:
parent
076b2591d4
commit
a4453a378e
8 changed files with 236 additions and 30 deletions
|
@ -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,11 +7,10 @@ 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)
|
||||||
|
|
||||||
|
@ -19,9 +18,9 @@ foreach(_sourcefile "${SCRIPT_FILES}")
|
||||||
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}")
|
15
scripts/native/skill/AbilityScript3.cpp
Normal file
15
scripts/native/skill/AbilityScript3.cpp
Normal 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 )
|
|
@ -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 )
|
|
@ -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( )
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -60,23 +60,23 @@ 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 ) { }
|
||||||
|
|
107
src/servers/Server_Zone/Script/ScriptLoader.cpp
Normal file
107
src/servers/Server_Zone/Script/ScriptLoader.cpp
Normal 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;
|
||||||
|
}
|
44
src/servers/Server_Zone/Script/ScriptLoader.h
Normal file
44
src/servers/Server_Zone/Script/ScriptLoader.h
Normal 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
|
Loading…
Add table
Reference in a new issue