diff --git a/scripts/native/CMakeLists.txt b/scripts/native/CMakeLists.txt index 3637a8a6..2fd7333e 100644 --- a/scripts/native/CMakeLists.txt +++ b/scripts/native/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.2) project(Sapphire_Script) 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/Server_Zone/") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/") - foreach(_sourcefile "${SCRIPT_FILES}") get_filename_component(_file "${_sourcefile}" NAME_WE) add_library("${_file}" MODULE "${_sourcefile}" "${SCRIPT_INCLUDE_FILES}") + message("adding library ${_file}") add_dependencies("${_file}" server_zone) set_target_properties("${_file}" PROPERTIES - CXX_STANDARD 14 - CXX_STANDARD_REQUIRED ON - CXX_EXTENSIONS ON - RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" - RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" - RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" - RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" - ) + CXX_STANDARD 14 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS ON + LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" + LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" + LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/compiledscripts/" + ) endforeach(_sourcefile "${SCRIPT_FILES}") \ No newline at end of file diff --git a/scripts/native/skill/AbilityScript3.cpp b/scripts/native/skill/AbilityScript3.cpp new file mode 100644 index 00000000..62b1b2d3 --- /dev/null +++ b/scripts/native/skill/AbilityScript3.cpp @@ -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 ) \ No newline at end of file diff --git a/scripts/native/statuseffect/StatusEffect50.cpp b/scripts/native/statuseffect/StatusEffect50.cpp index 4ecb90d6..478142d0 100644 --- a/scripts/native/statuseffect/StatusEffect50.cpp +++ b/scripts/native/statuseffect/StatusEffect50.cpp @@ -6,10 +6,11 @@ public: 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 ) \ No newline at end of file diff --git a/src/servers/Server_Zone/Script/NativeScript.cpp b/src/servers/Server_Zone/Script/NativeScript.cpp index 0181d82c..94861a66 100644 --- a/src/servers/Server_Zone/Script/NativeScript.cpp +++ b/src/servers/Server_Zone/Script/NativeScript.cpp @@ -11,9 +11,9 @@ namespace Core { 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 ) @@ -38,7 +38,7 @@ namespace Core { void NativeScript::removeAbilityScript( uint32_t abilityId ) { - m_abilityScripts.erase( abilityId ); + m_actionScripts.erase( abilityId ); } void NativeScript::removeQuestScript( uint32_t questId ) @@ -51,8 +51,39 @@ namespace Core { 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( ) diff --git a/src/servers/Server_Zone/Script/NativeScript.h b/src/servers/Server_Zone/Script/NativeScript.h index ae21e0fb..1b6197c1 100644 --- a/src/servers/Server_Zone/Script/NativeScript.h +++ b/src/servers/Server_Zone/Script/NativeScript.h @@ -10,6 +10,7 @@ #include #include "NativeScriptApi.h" +#include "ScriptLoader.h" namespace Core { namespace Scripting { @@ -18,16 +19,18 @@ namespace Core { { protected: 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, BattleNpcScript* > m_battleNpcScripts; std::unordered_map< uint32_t, ZoneScript* > m_zoneScripts; + ScriptLoader m_loader; + public: NativeScript( ); StatusEffectScript* getStatusEffectScript( uint32_t statusId ); - AbilityScript* getAbilityScript( uint32_t abilityId ); + ActionScript* getAbilityScript( uint32_t abilityId ); QuestScript* getQuestScript( uint32_t questId ); BattleNpcScript* getBattleNpcScript( uint32_t npcId ); ZoneScript* getZoneScript( uint32_t zoneId ); @@ -38,6 +41,8 @@ namespace Core { void removeBattleNpcScript( uint32_t npcId ); + void loadScript( std::string ); + void unloadScript( std::string ); void clearAllScripts(); }; diff --git a/src/servers/Server_Zone/Script/NativeScriptApi.h b/src/servers/Server_Zone/Script/NativeScriptApi.h index 45a4be9c..838bd027 100644 --- a/src/servers/Server_Zone/Script/NativeScriptApi.h +++ b/src/servers/Server_Zone/Script/NativeScriptApi.h @@ -60,24 +60,24 @@ public: }; -class AbilityScript : public ScriptObject +class ActionScript : public ScriptObject { protected: - const uint32_t m_abilityId; + const uint32_t m_actionId; public: - AbilityScript( std::string name, uint32_t abilityId ) : + ActionScript( std::string name, uint32_t abilityId ) : 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 onCastFinish(Core::Entity::Player player, Core::Entity::ActorPtr 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 onInterrupt( Core::Entity::Actor sourceActor/*, Core::Entity::Actor targetActor*/ ) { } }; @@ -132,6 +132,10 @@ public: m_zoneId( zoneId ) { } + const uint32_t getZoneId() + { + return m_zoneId; + } virtual void onZoneInit() { } virtual void onEnterZone( Core::Entity::Player pPlayer, uint32_t eventId, uint16_t param1, uint16_t param2 ) { } diff --git a/src/servers/Server_Zone/Script/ScriptLoader.cpp b/src/servers/Server_Zone/Script/ScriptLoader.cpp new file mode 100644 index 00000000..4ad8c285 --- /dev/null +++ b/src/servers/Server_Zone/Script/ScriptLoader.cpp @@ -0,0 +1,107 @@ +#include "ScriptLoader.h" + +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/src/servers/Server_Zone/Script/ScriptLoader.h b/src/servers/Server_Zone/Script/ScriptLoader.h new file mode 100644 index 00000000..cadc22e8 --- /dev/null +++ b/src/servers/Server_Zone/Script/ScriptLoader.h @@ -0,0 +1,44 @@ +#ifndef SAPPHIRE_SCRIPTLOADER_H +#define SAPPHIRE_SCRIPTLOADER_H + +#include +#include "NativeScriptApi.h" + +#ifdef _WIN32 +#include +#include + +typedef HMODULE ModuleHandle; +#else +#include +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