From 204f0d294c072c97dc5d73ada6757005f8761fef Mon Sep 17 00:00:00 2001 From: Joey Pollack Date: Mon, 21 Nov 2022 19:05:59 -0500 Subject: [PATCH] Refactors the World Scripting API into it's own class --- CMakeLists.txt | 1 + .../internal_scripts/components.wren | 8 +- .../internal_scripts/world_interface.wren | 11 +-- src/scripting/wren_state.h | 17 ++++ src/world/world.cpp | 56 +++++++---- src/world/world.h | 11 +-- src/world/world_api.cpp | 97 +++++++++++++++++++ src/world/world_api.h | 58 +++++++++++ 8 files changed, 212 insertions(+), 47 deletions(-) create mode 100644 src/world/world_api.cpp create mode 100644 src/world/world_api.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9740820..cb2370f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,7 @@ set(LUNARIUM_SRC "src/scripting/wren_script.cpp" "src/scripting/coreAPI.cpp" "src/world/world.cpp" +"src/world/world_api.cpp" "src/world/entity.cpp" ) diff --git a/src/scripting/internal_scripts/components.wren b/src/scripting/internal_scripts/components.wren index 044abda..1c7e825 100644 --- a/src/scripting/internal_scripts/components.wren +++ b/src/scripting/internal_scripts/components.wren @@ -6,14 +6,8 @@ * Description - The foreign classes for components ******************************************************************************/ -class Component { - EntityID { _EntityID } - EntityID=(value) { - _EntityID = value - } -} -foreign class VelocityComponent is Component { +foreign class VelocityComponent { // The parameter will be used on the C++ side to set the correct C++ component construct new(entity_id) { diff --git a/src/scripting/internal_scripts/world_interface.wren b/src/scripting/internal_scripts/world_interface.wren index f6c0939..3a2c2c6 100644 --- a/src/scripting/internal_scripts/world_interface.wren +++ b/src/scripting/internal_scripts/world_interface.wren @@ -6,15 +6,6 @@ * Description - The main interface for scripts to interact with the game world ******************************************************************************/ -class Component { - Tag { 1 } - Transform { 2 } - Velocity { 3 } - Camera { 4 } - BlockOut { 5 } - Script { 6 } -} - // Manages all of the EntityBehaviors class WorldInterface { @@ -55,7 +46,7 @@ class WorldInterface { // API ///////////////////////////////////////////////////////////////////// - //foreign static GetComponent(entity_id, component_id) + //foreign static GetVelocityComponent(entity_id) } diff --git a/src/scripting/wren_state.h b/src/scripting/wren_state.h index f02fefb..65b5ffe 100644 --- a/src/scripting/wren_state.h +++ b/src/scripting/wren_state.h @@ -43,6 +43,7 @@ namespace lunarium class WrenScript; typedef WrenForeignMethodFn ForeignMethod; + typedef WrenFinalizerFn Finalizer; class WrenState { @@ -61,6 +62,20 @@ namespace lunarium } }; + struct ForeignClassDesc + { + std::string Module; + std::string Class; + u32 ForeignDataSize; + + WrenForeignClassMethods FCM; + + bool operator==(const ForeignClassDesc& rhs) + { + return (Module == rhs.Module && Class == rhs.Class); + } + }; + public: ~WrenState(); @@ -85,6 +100,7 @@ public: static void WriteFN(WrenVM* vm, const char* text); static void ErrorFN(WrenVM* vm, WrenErrorType type, const char* module, int line, const char* message); static WrenForeignMethodFn BindForeignMethodFN(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature); + static WrenForeignClassMethods BindForeignClass(WrenVM* vm, const char* module, const char* className); @@ -92,6 +108,7 @@ public: static u32 mLogCat; WrenVM* mpVM; static std::vector mForeignMethods; + static std::vector mForeignClasses; }; } diff --git a/src/world/world.cpp b/src/world/world.cpp index 9e04804..9d16a46 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -10,6 +10,7 @@ ******************************************************************************/ #include "world.h" +#include "world_api.h" #include #include #include @@ -43,29 +44,34 @@ namespace lunarium void World::InitScriptState() { - mScriptState.Initialize().LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialize the world script state"); + // mScriptState.Initialize().LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialize the world script state"); - // Load the world interface script - mWorldInterface.SetModuleName("WorldInterface"); - std::string code = File::ReadTextFile("world_interface.wren"); // This will eventually move to internal data - mWorldInterface.SetScriptCode(code); + // // Register foreign methods + // mScriptState.RegisterForeignMethod({"WorldInterface", "WorldInterface", true, "GetComponent(_,_)", (WrenForeignMethodFn)&World::GetVelocityComponent}); - mScriptState.RunScript(&mWorldInterface); + // // Load the world interface script + // mWorldInterface.SetModuleName("WorldInterface"); + // std::string code = File::ReadTextFile("world_interface.wren"); // This will eventually move to internal data + // mWorldInterface.SetScriptCode(code); - // Get class and method handles - mWIHandle = mScriptState.GetWrenClassHandle("WorldInterface", "WorldInterface"); - mWIInitMethod = mScriptState.GetWrenMethodHandle("Init()"); - mWIDoOnLoadMethod = mScriptState.GetWrenMethodHandle("DoOnLoad()"); - mWIDoOnUnloadMethod = mScriptState.GetWrenMethodHandle("DoOnUnload()"); - mWIUpdateMethod = mScriptState.GetWrenMethodHandle("Update(_)"); + // mScriptState.RunScript(&mWorldInterface); - // Init the interface - mScriptState.CallWrenMethod(mWIInitMethod, mWIHandle, {}, "WorldInterface.Init()"); + // // Get class and method handles + // mWIHandle = mScriptState.GetWrenClassHandle("WorldInterface", "WorldInterface"); + // mWIInitMethod = mScriptState.GetWrenMethodHandle("Init()"); + // mWIDoOnLoadMethod = mScriptState.GetWrenMethodHandle("DoOnLoad()"); + // mWIDoOnUnloadMethod = mScriptState.GetWrenMethodHandle("DoOnUnload()"); + // mWIUpdateMethod = mScriptState.GetWrenMethodHandle("Update(_)"); + + // // Init the interface + // mScriptState.CallWrenMethod(mWIInitMethod, mWIHandle, {}, "WorldInterface.Init()"); } void World::OnLoad() { - InitScriptState(); + // InitScriptState(); + + WorldAPI::Initialize(this).LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialized the world scripting api"); // Load scripts from all ScriptComponents in the world auto group_scripts = mECSRegistry.view(); @@ -78,19 +84,24 @@ namespace lunarium editor::Script* pScript = (editor::Script*) editor::ContentManager::GetInstance().GetAsset(script_comp.ScriptID); WrenScript script(pScript->GetScriptFile().filename().string().c_str(), pScript->GetScript()); - mScriptState.RunScript(&script); + // mScriptState.RunScript(&script); + WorldAPI::RunScript(script); #endif } // Call OnLoad for each registered EntityBehavior class object - mScriptState.CallWrenMethod(mWIDoOnLoadMethod, mWIHandle, {}, "WorldInterface.DoOnLoad()"); + //mScriptState.CallWrenMethod(mWIDoOnLoadMethod, mWIHandle, {}, "WorldInterface.DoOnLoad()"); + WorldAPI::InvokeEvent(WorldAPI::Event::ON_LOAD); } void World::OnUnload() { // TODO: Call OnUnLoad for each registered EntityBehavior class object - mScriptState.CallWrenMethod(mWIDoOnUnloadMethod, mWIHandle, {}, "WorldInterface.DoOnUnload()"); - mScriptState.Shutdown(); + //mScriptState.CallWrenMethod(mWIDoOnUnloadMethod, mWIHandle, {}, "WorldInterface.DoOnUnload()"); + WorldAPI::InvokeEvent(WorldAPI::Event::ON_UNLOAD); + + //mScriptState.Shutdown(); + WorldAPI::Shutdown(); } void World::SetRunMode(RunMode mode) @@ -107,7 +118,8 @@ namespace lunarium { // Update all scripts // Call Update for each registered EntityBehavior class object - mScriptState.CallWrenMethod(mWIUpdateMethod, mWIHandle, { {WrenParamType::WPT_DOUBLE, (double)dt} }, "WorldInterface.Update(dt)"); + //mScriptState.CallWrenMethod(mWIUpdateMethod, mWIHandle, { {WrenParamType::WPT_DOUBLE, (double)dt} }, "WorldInterface.Update(dt)"); + WorldAPI::InvokeEvent(WorldAPI::Event::ON_UPDATE, dt); // Update Transforms for any enity with a velocity @@ -226,6 +238,8 @@ namespace lunarium return iter == mEntities.end(); } + + ///////////////////////////////////////////////////////////////////// // RUN MODE HELPERS ///////////////////////////////////////////////////////////////////// @@ -308,7 +322,7 @@ namespace lunarium mEntities.clear(); mEntitiesByUUID.clear(); - Deserialize(state.State); + Deserialize(state.State).LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to deserialize the world state"); } ///////////////////////////////////////////////////////////////////// diff --git a/src/world/world.h b/src/world/world.h index f448960..5bd66ba 100644 --- a/src/world/world.h +++ b/src/world/world.h @@ -107,13 +107,7 @@ namespace lunarium private: LUUID mUUID; std::string mName; - WrenState mScriptState; - WrenScript mWorldInterface; - WrenHandle* mWIHandle; - WrenHandle* mWIInitMethod; - WrenHandle* mWIDoOnLoadMethod; - WrenHandle* mWIDoOnUnloadMethod; - WrenHandle* mWIUpdateMethod; + // State critical Data entt::registry mECSRegistry; @@ -134,8 +128,7 @@ namespace lunarium // TEST STUFF //bool mGetAssetsFromEditor; // This is for testing until we get a proper asset manager - private: // SCRIPTING API - static void GetComponent(WrenVM* vm); + private: // HELPERS void InitScriptState(); diff --git a/src/world/world_api.cpp b/src/world/world_api.cpp new file mode 100644 index 0000000..d0264f5 --- /dev/null +++ b/src/world/world_api.cpp @@ -0,0 +1,97 @@ +/****************************************************************************** +* File - world_api.cpp +* Author - Joey Pollack +* Date - 2022/11/21 (y/m/d) +* Mod Date - 2022/11/21 (y/m/d) +* Description - The scripting api for the world interface +******************************************************************************/ + +#include "world_api.h" +#include "world.h" +#include +#include + +#include + +namespace lunarium +{ + WrenState WorldAPI::mScriptState; + World* WorldAPI::mpWorld = nullptr; + WorldAPI::ScriptEventHandles WorldAPI::mEventHandles; + + OpRes WorldAPI::Initialize(World* pWorld) + { + mpWorld = pWorld; + + mScriptState.Initialize().LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialize the world script state"); + + // Register foreign methods + mScriptState.RegisterForeignMethod({"WorldInterface", "WorldInterface", true, "GetComponent(_,_)", (WrenForeignMethodFn)&WorldAPI::GetVelocityComponent}); + + // Load the world interface script + WrenScript world_interface; + world_interface.SetModuleName("WorldInterface"); + std::string code = File::ReadTextFile("world_interface.wren"); // This will eventually move to internal data + world_interface.SetScriptCode(code); + + mScriptState.RunScript(&world_interface); + + // Get class and method handles + mEventHandles.mWIHandle = mScriptState.GetWrenClassHandle("WorldInterface", "WorldInterface"); + mEventHandles.mWIInitMethod = mScriptState.GetWrenMethodHandle("Init()"); + mEventHandles.mWIDoOnLoadMethod = mScriptState.GetWrenMethodHandle("DoOnLoad()"); + mEventHandles.mWIDoOnUnloadMethod = mScriptState.GetWrenMethodHandle("DoOnUnload()"); + mEventHandles.mWIUpdateMethod = mScriptState.GetWrenMethodHandle("Update(_)"); + + // Init the interface + mScriptState.CallWrenMethod(mEventHandles.mWIInitMethod, mEventHandles.mWIHandle, {}, "WorldInterface.Init()"); + + return OpRes::OK(); + } + + void WorldAPI::Shutdown() + { + mpWorld = nullptr; + } + + + void WorldAPI::RunScript(WrenScript& script) + { + mScriptState.RunScript(&script); + } + + void WorldAPI::InvokeEvent(Event e, ...) + { + switch (e) + { + case Event::ON_LOAD: mScriptState.CallWrenMethod(mEventHandles.mWIDoOnLoadMethod, mEventHandles.mWIHandle, {}, "WorldInterface.DoOnLoad()"); break; + case Event::ON_UNLOAD: mScriptState.CallWrenMethod(mEventHandles.mWIDoOnUnloadMethod, mEventHandles.mWIHandle, {}, "WorldInterface.DoOnUnload()"); break; + case Event::ON_UPDATE: + { + va_list args; + va_start(args, e); + double dt = va_arg(args, double); + + mScriptState.CallWrenMethod(mEventHandles.mWIUpdateMethod, mEventHandles.mWIHandle, { {WrenParamType::WPT_DOUBLE, (double)dt} }, "WorldInterface.Update(dt)" ); + + va_end(args); + } + break; + } + } + + ///////////////////////////////////////////////////////////////////// + // SCRIPT API + ///////////////////////////////////////////////////////////////////// + + void WorldAPI::GetVelocityComponent(WrenVM* vm) + { + std::string str_entity_id = wrenGetSlotString(vm, 1); + LUUID entity_id = std::stoull(str_entity_id); + + // More examples of creating foreign class instances + // https://github.com/wren-lang/wren/issues/1062 + + + } +} \ No newline at end of file diff --git a/src/world/world_api.h b/src/world/world_api.h new file mode 100644 index 0000000..a9d0893 --- /dev/null +++ b/src/world/world_api.h @@ -0,0 +1,58 @@ +/****************************************************************************** +* File - world_api.h +* Author - Joey Pollack +* Date - 2022/11/21 (y/m/d) +* Mod Date - 2022/11/21 (y/m/d) +* Description - The scripting api for the world interface +******************************************************************************/ + +#ifndef LUNARIUM_WORLD_API_H_ +#define LUNARIUM_WORLD_API_H_ + +#include +#include +#include +#include + +namespace lunarium +{ + class WorldAPI + { + friend class World; + + public: + struct ScriptEventHandles + { + WrenHandle* mWIHandle; + + WrenHandle* mWIInitMethod; + WrenHandle* mWIDoOnLoadMethod; + WrenHandle* mWIDoOnUnloadMethod; + WrenHandle* mWIUpdateMethod; + }; + + enum class Event + { + ON_LOAD, + ON_UNLOAD, + ON_UPDATE, + }; + + public: + static OpRes Initialize(World* pWorld); + static void Shutdown(); + + static void RunScript(WrenScript& script); + static void InvokeEvent(Event e, ...); + + private: // SCRIPTING API + static void GetVelocityComponent(WrenVM* vm); + + private: + static WrenState mScriptState; + static World* mpWorld; + static ScriptEventHandles mEventHandles; + }; +} + +#endif // LUNARIUM_WORLD_API_H_ \ No newline at end of file