From 44e80f88f85d9604f4ae5dcc56bb0bfc64006dba Mon Sep 17 00:00:00 2001 From: hispidence Date: Fri, 19 Aug 2022 22:42:16 +0100 Subject: [PATCH] Add mechanism for adding callbacks to be called before/after OnControlPhase --- TombEngine/Game/savegame.cpp | 28 ++++-- .../Scripting/Include/ScriptInterfaceGame.h | 3 + .../Scripting/Internal/ReservedScriptNames.h | 7 +- .../Internal/TEN/Logic/LogicHandler.cpp | 86 +++++++++++++++++++ .../Internal/TEN/Logic/LogicHandler.h | 36 +++----- .../Internal/TEN/Rotation/Rotation.cpp | 3 +- .../flatbuffers/ten_savegame_generated.h | 48 +++++++++-- .../Specific/savegame/schema/ten_savegame.fbs | 2 + 8 files changed, 175 insertions(+), 38 deletions(-) diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index a58985c66..377aab6bf 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -1026,16 +1026,9 @@ bool SaveGame::Save(int slot) alternatePendulumOffset = alternatePendulumInfo.Finish(); } - - std::vector> levelTableVec; - std::vector> levelStringVec2; - - //std::vector savedTables; - std::vector savedStrings; std::vector savedVars; g_GameScript->GetVariables(savedVars); - std::vector> varsVec; for (auto const& s : savedVars) @@ -1107,6 +1100,13 @@ bool SaveGame::Save(int slot) uvb.add_members(unionVec); auto unionVecOffset = uvb.Finish(); + std::vector callbackVecPreControl; + std::vector callbackVecPostControl; + g_GameScript->GetCallbackStrings(callbackVecPreControl, callbackVecPostControl); + + auto stringsCallbackPreControl = fbb.CreateVectorOfStrings(callbackVecPreControl); + auto stringsCallbackPostControl = fbb.CreateVectorOfStrings(callbackVecPostControl); + Save::SaveGameBuilder sgb{ fbb }; sgb.add_header(headerOffset); @@ -1150,6 +1150,8 @@ bool SaveGame::Save(int slot) } sgb.add_script_vars(unionVecOffset); + sgb.add_callbacks_pre_control(stringsCallbackPreControl); + sgb.add_callbacks_post_control(stringsCallbackPostControl); auto sg = sgb.Finish(); fbb.Finish(sg); @@ -1927,6 +1929,18 @@ bool SaveGame::Load(int slot) g_GameScript->SetVariables(loadedVars); + std::vector callbacksPreControlVec; + auto callbacksPreControlOffsetVec = s->callbacks_pre_control(); + for (auto const& s : *callbacksPreControlOffsetVec) + callbacksPreControlVec.push_back(s->str()); + + std::vector callbacksPostControlVec; + auto callbacksPostControlOffsetVec = s->callbacks_post_control(); + for (auto const& s : *callbacksPostControlOffsetVec) + callbacksPostControlVec.push_back(s->str()); + + g_GameScript->SetCallbackStrings(callbacksPreControlVec, callbacksPostControlVec); + return true; } diff --git a/TombEngine/Scripting/Include/ScriptInterfaceGame.h b/TombEngine/Scripting/Include/ScriptInterfaceGame.h index 33b7b3344..e49e5c80d 100644 --- a/TombEngine/Scripting/Include/ScriptInterfaceGame.h +++ b/TombEngine/Scripting/Include/ScriptInterfaceGame.h @@ -41,6 +41,9 @@ public: virtual void GetVariables(std::vector & vars) = 0; virtual void SetVariables(std::vector const& vars) = 0; + + virtual void GetCallbackStrings(std::vector & preControl, std::vector & postControl) const = 0; + virtual void SetCallbackStrings(std::vector const & preControl, std::vector const & postControl) = 0; }; extern ScriptInterfaceGame* g_GameScript; diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index ef99ae505..6ce0294ab 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -19,6 +19,7 @@ static constexpr char ScriptReserved_SoundSource[] = "SoundSource"; static constexpr char ScriptReserved_AIObject[] = "AIObject"; static constexpr char ScriptReserved_DisplayString[] = "DisplayString"; static constexpr char ScriptReserved_Vec3[] = "Vec3"; +static constexpr char ScriptReserved_Rotation[] = "Rotation"; // Member functions static constexpr char ScriptReserved_New[] = "New"; @@ -92,8 +93,6 @@ static constexpr char ScriptReserved_SetTitleScreenImagePath[] = "SetTitleScreen static constexpr char ScriptReserved_SetFarView[] = "SetFarView"; static constexpr char ScriptReserved_SetSettings[] = "SetSettings"; static constexpr char ScriptReserved_SetAnimations[] = "SetAnimations"; - -// Flow Functions static constexpr char ScriptReserved_SetStrings[] = "SetStrings"; static constexpr char ScriptReserved_GetString[] = "GetString"; static constexpr char ScriptReserved_SetLanguageNames[] = "SetLanguageNames"; @@ -129,6 +128,9 @@ static constexpr char ScriptReserved_ScreenToPercent[] = "ScreenToPercent"; static constexpr char ScriptReserved_PercentToScreen[] = "PercentToScreen"; static constexpr char ScriptReserved_HasLineOfSight[] = "HasLineOfSight"; +static constexpr char ScriptReserved_AddCallback[] = "AddCallback"; +static constexpr char ScriptReserved_RemoveCallback[] = "RemoveCallback"; + static constexpr char ScriptReserved_EmitParticle[] = "EmitParticle"; static constexpr char ScriptReserved_EmitLightningArc[] = "EmitLightningArc"; static constexpr char ScriptReserved_EmitShockwave[] = "EmitShockwave"; @@ -154,6 +156,7 @@ static constexpr char ScriptReserved_KeyClear[] = "KeyClear"; static constexpr char ScriptReserved_ObjID[] = "ObjID"; static constexpr char ScriptReserved_BlendID[] = "BlendID"; static constexpr char ScriptReserved_DisplayStringOption[] = "DisplayStringOption"; +static constexpr char ScriptReserved_CallbackPoint[] = "CallbackPoint"; static constexpr char ScriptReserved_LevelVars[] = "LevelVars"; static constexpr char ScriptReserved_GameVars[] = "GameVars"; diff --git a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp index 9057db93e..5590508f8 100644 --- a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp @@ -17,6 +17,18 @@ Saving data, triggering functions, and callbacks for level-specific scripts. @pragma nostrip */ +enum class CallbackPoint +{ + PreControl, + PostControl, +}; + +static const std::unordered_map kCallbackPoints +{ + {"PreControlPhase", CallbackPoint::PreControl}, + {"PostControlPhase", CallbackPoint::PostControl}, +}; + void SetVariable(sol::table tab, sol::object key, sol::object value) { switch (value.get_type()) @@ -63,6 +75,16 @@ sol::object GetVariable(sol::table tab, sol::object key) LogicHandler::LogicHandler(sol::state* lua, sol::table & parent) : m_handler{ lua } { m_handler.GetState()->set_function("print", &LogicHandler::LogPrint, this); + + sol::table table_logic{ m_handler.GetState()->lua_state(), sol::create }; + + parent.set(ScriptReserved_Logic, table_logic); + + table_logic.set_function(ScriptReserved_AddCallback, &LogicHandler::AddCallback, this); + table_logic.set_function(ScriptReserved_RemoveCallback, &LogicHandler::RemoveCallback, this); + + m_handler.MakeReadOnlyTable(table_logic, ScriptReserved_CallbackPoint, kCallbackPoints); + ResetScripts(true); } @@ -71,6 +93,33 @@ void LogicHandler::ResetGameTables() MakeSpecialTable(m_handler.GetState(), ScriptReserved_GameVars, &GetVariable, &SetVariable); } +void LogicHandler::AddCallback(CallbackPoint point, std::string const & name) +{ + switch(point) + { + case CallbackPoint::PreControl: + m_callbacksPreControl.insert(name); + break; + + case CallbackPoint::PostControl: + m_callbacksPostControl.insert(name); + break; + } +} + +void LogicHandler::RemoveCallback(CallbackPoint point, std::string const & name) +{ + switch(point) + { + case CallbackPoint::PreControl: + m_callbacksPreControl.erase(name); + break; + + case CallbackPoint::PostControl: + m_callbacksPostControl.erase(name); + break; + } +} void LogicHandler::ResetLevelTables() { @@ -121,6 +170,9 @@ void LogicHandler::ResetScripts(bool clearGameVars) { FreeLevelScripts(); + m_callbacksPreControl.clear(); + m_callbacksPostControl.clear(); + auto currentPackage = m_handler.GetState()->get("package"); auto currentLoaded = currentPackage.get("loaded"); @@ -347,6 +399,24 @@ void LogicHandler::GetVariables(std::vector & vars) populate(tab); } +void LogicHandler::GetCallbackStrings(std::vector& preControl, std::vector& postControl) const +{ + for (auto const& s : m_callbacksPreControl) + preControl.push_back(s); + + for (auto const& s : m_callbacksPostControl) + postControl.push_back(s); +} + +void LogicHandler::SetCallbackStrings(std::vector const & preControl, std::vector const & postControl) +{ + for (auto const& s : preControl) + m_callbacksPreControl.insert(s); + + for (auto const& s : postControl) + m_callbacksPostControl.insert(s); +} + template std::unique_ptr GetByName(std::string const & type, std::string const & name, mapType const & map) { @@ -428,9 +498,25 @@ void LogicHandler::OnLoad() void LogicHandler::OnControlPhase(float dt) { + sol::table levelFuncs = (*m_handler.GetState())[ScriptReserved_LevelFuncs]; + + auto tryCall = [dt, &levelFuncs](std::string const& name) + { + if (!levelFuncs[name].valid()) + ScriptAssertF(false, "Callback {} not valid", name); + else + levelFuncs[name].call(dt); + }; + + for (auto& name : m_callbacksPreControl) + tryCall(name); + lua_gc(m_handler.GetState()->lua_state(), LUA_GCCOLLECT, 0); if(m_onControlPhase.valid()) doCallback(m_onControlPhase, dt); + + for (auto& name : m_callbacksPostControl) + tryCall(name); } void LogicHandler::OnSave() diff --git a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h index db58965f6..498102f1c 100644 --- a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h @@ -5,28 +5,7 @@ #include #include "Strings/StringsHandler.h" -struct LuaFunction { - std::string Name; - std::string Code; - bool Executed; -}; - -struct GameScriptVector3 { - float x; - float y; - float z; -}; - -struct LuaVariable -{ - bool IsGlobal; - std::string Name; - int Type; - float FloatValue; - int IntValue; - std::string StringValue; - bool BoolValue; -}; +enum class CallbackPoint; class LogicHandler : public ScriptInterfaceGame { @@ -38,6 +17,9 @@ private: sol::protected_function m_onSave{}; sol::protected_function m_onEnd{}; + std::unordered_set m_callbacksPreControl; + std::unordered_set m_callbacksPostControl; + void ResetLevelTables(); void ResetGameTables(); LuaHandler m_handler; @@ -49,6 +31,10 @@ public: void LogPrint(sol::variadic_args va); bool SetLevelFunc(sol::table tab, std::string const& luaName, sol::object value); + + void AddCallback(CallbackPoint point, std::string const& name); + void RemoveCallback(CallbackPoint point, std::string const & name); + void ResetScripts(bool clearGameVars) override; sol::protected_function GetLevelFunc(sol::table tab, std::string const& luaName); @@ -59,13 +45,17 @@ public: void ExecuteFunction(std::string const& name, short idOne, short idTwo) override; void GetVariables(std::vector& vars) override; + void SetVariables(std::vector const& vars) override; void ResetVariables(); - void SetVariables(std::vector const& vars) override; + void SetCallbackStrings(std::vector const& preControl, std::vector const& postControl) override; + void GetCallbackStrings(std::vector& preControl, std::vector& postControl) const override; + void InitCallbacks() override; void OnStart() override; void OnLoad() override; void OnControlPhase(float dt) override; void OnSave() override; void OnEnd() override; + }; diff --git a/TombEngine/Scripting/Internal/TEN/Rotation/Rotation.cpp b/TombEngine/Scripting/Internal/TEN/Rotation/Rotation.cpp index 88f796cb4..479e9c9f1 100644 --- a/TombEngine/Scripting/Internal/TEN/Rotation/Rotation.cpp +++ b/TombEngine/Scripting/Internal/TEN/Rotation/Rotation.cpp @@ -1,5 +1,6 @@ #include "framework.h" #include "Rotation.h" +#include "ReservedScriptNames.h" #include "Specific/phd_global.h" /*** Represents a rotation. @@ -13,7 +14,7 @@ All values will be clamped to [-32768, 32767]. void Rotation::Register(sol::table & parent) { using ctors = sol::constructors; - parent.new_usertype("Rotation", + parent.new_usertype(ScriptReserved_Rotation, ctors(), sol::call_constructor, ctors(), sol::meta_function::to_string, &Rotation::ToString, diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h index a3ce470cc..9d157a5a0 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h @@ -5849,6 +5849,8 @@ struct SaveGameT : public flatbuffers::NativeTable { std::vector> volume_states{}; std::vector> call_counters{}; std::unique_ptr script_vars{}; + std::vector callbacks_pre_control{}; + std::vector callbacks_post_control{}; }; struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { @@ -5891,7 +5893,9 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_ALTERNATE_PENDULUM = 68, VT_VOLUME_STATES = 70, VT_CALL_COUNTERS = 72, - VT_SCRIPT_VARS = 74 + VT_SCRIPT_VARS = 74, + VT_CALLBACKS_PRE_CONTROL = 76, + VT_CALLBACKS_POST_CONTROL = 78 }; const TEN::Save::SaveGameHeader *header() const { return GetPointer(VT_HEADER); @@ -6001,6 +6005,12 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const TEN::Save::UnionVec *script_vars() const { return GetPointer(VT_SCRIPT_VARS); } + const flatbuffers::Vector> *callbacks_pre_control() const { + return GetPointer> *>(VT_CALLBACKS_PRE_CONTROL); + } + const flatbuffers::Vector> *callbacks_post_control() const { + return GetPointer> *>(VT_CALLBACKS_POST_CONTROL); + } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_HEADER) && @@ -6079,6 +6089,12 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { verifier.VerifyVectorOfTables(call_counters()) && VerifyOffset(verifier, VT_SCRIPT_VARS) && verifier.VerifyTable(script_vars()) && + VerifyOffset(verifier, VT_CALLBACKS_PRE_CONTROL) && + verifier.VerifyVector(callbacks_pre_control()) && + verifier.VerifyVectorOfStrings(callbacks_pre_control()) && + VerifyOffset(verifier, VT_CALLBACKS_POST_CONTROL) && + verifier.VerifyVector(callbacks_post_control()) && + verifier.VerifyVectorOfStrings(callbacks_post_control()) && verifier.EndTable(); } SaveGameT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -6198,6 +6214,12 @@ struct SaveGameBuilder { void add_script_vars(flatbuffers::Offset script_vars) { fbb_.AddOffset(SaveGame::VT_SCRIPT_VARS, script_vars); } + void add_callbacks_pre_control(flatbuffers::Offset>> callbacks_pre_control) { + fbb_.AddOffset(SaveGame::VT_CALLBACKS_PRE_CONTROL, callbacks_pre_control); + } + void add_callbacks_post_control(flatbuffers::Offset>> callbacks_post_control) { + fbb_.AddOffset(SaveGame::VT_CALLBACKS_POST_CONTROL, callbacks_post_control); + } explicit SaveGameBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -6246,10 +6268,14 @@ inline flatbuffers::Offset CreateSaveGame( flatbuffers::Offset alternate_pendulum = 0, flatbuffers::Offset>> volume_states = 0, flatbuffers::Offset>> call_counters = 0, - flatbuffers::Offset script_vars = 0) { + flatbuffers::Offset script_vars = 0, + flatbuffers::Offset>> callbacks_pre_control = 0, + flatbuffers::Offset>> callbacks_post_control = 0) { SaveGameBuilder builder_(_fbb); builder_.add_oneshot_position(oneshot_position); builder_.add_ambient_position(ambient_position); + builder_.add_callbacks_post_control(callbacks_post_control); + builder_.add_callbacks_pre_control(callbacks_pre_control); builder_.add_script_vars(script_vars); builder_.add_call_counters(call_counters); builder_.add_volume_states(volume_states); @@ -6329,7 +6355,9 @@ inline flatbuffers::Offset CreateSaveGameDirect( flatbuffers::Offset alternate_pendulum = 0, const std::vector> *volume_states = nullptr, const std::vector> *call_counters = nullptr, - flatbuffers::Offset script_vars = 0) { + flatbuffers::Offset script_vars = 0, + const std::vector> *callbacks_pre_control = nullptr, + const std::vector> *callbacks_post_control = nullptr) { auto items__ = items ? _fbb.CreateVector>(*items) : 0; auto room_items__ = room_items ? _fbb.CreateVector(*room_items) : 0; auto fxinfos__ = fxinfos ? _fbb.CreateVector>(*fxinfos) : 0; @@ -6349,6 +6377,8 @@ inline flatbuffers::Offset CreateSaveGameDirect( auto cd_flags__ = cd_flags ? _fbb.CreateVector(*cd_flags) : 0; auto volume_states__ = volume_states ? _fbb.CreateVector>(*volume_states) : 0; auto call_counters__ = call_counters ? _fbb.CreateVector>(*call_counters) : 0; + auto callbacks_pre_control__ = callbacks_pre_control ? _fbb.CreateVector>(*callbacks_pre_control) : 0; + auto callbacks_post_control__ = callbacks_post_control ? _fbb.CreateVector>(*callbacks_post_control) : 0; return TEN::Save::CreateSaveGame( _fbb, header, @@ -6386,7 +6416,9 @@ inline flatbuffers::Offset CreateSaveGameDirect( alternate_pendulum, volume_states__, call_counters__, - script_vars); + script_vars, + callbacks_pre_control__, + callbacks_post_control__); } flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); @@ -8117,6 +8149,8 @@ inline void SaveGame::UnPackTo(SaveGameT *_o, const flatbuffers::resolver_functi { auto _e = volume_states(); if (_e) { _o->volume_states.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->volume_states[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = call_counters(); if (_e) { _o->call_counters.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->call_counters[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = script_vars(); if (_e) _o->script_vars = std::unique_ptr(_e->UnPack(_resolver)); } + { auto _e = callbacks_pre_control(); if (_e) { _o->callbacks_pre_control.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->callbacks_pre_control[_i] = _e->Get(_i)->str(); } } } + { auto _e = callbacks_post_control(); if (_e) { _o->callbacks_post_control.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->callbacks_post_control[_i] = _e->Get(_i)->str(); } } } } inline flatbuffers::Offset SaveGame::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SaveGameT* _o, const flatbuffers::rehasher_function_t *_rehasher) { @@ -8163,6 +8197,8 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild auto _volume_states = _fbb.CreateVector> (_o->volume_states.size(), [](size_t i, _VectorArgs *__va) { return CreateVolumeState(*__va->__fbb, __va->__o->volume_states[i].get(), __va->__rehasher); }, &_va ); auto _call_counters = _fbb.CreateVector> (_o->call_counters.size(), [](size_t i, _VectorArgs *__va) { return CreateEventSetCallCounters(*__va->__fbb, __va->__o->call_counters[i].get(), __va->__rehasher); }, &_va ); auto _script_vars = _o->script_vars ? CreateUnionVec(_fbb, _o->script_vars.get(), _rehasher) : 0; + auto _callbacks_pre_control = _fbb.CreateVectorOfStrings(_o->callbacks_pre_control); + auto _callbacks_post_control = _fbb.CreateVectorOfStrings(_o->callbacks_post_control); return TEN::Save::CreateSaveGame( _fbb, _header, @@ -8200,7 +8236,9 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild _alternate_pendulum, _volume_states, _call_counters, - _script_vars); + _script_vars, + _callbacks_pre_control, + _callbacks_post_control); } inline bool VerifyVarUnion(flatbuffers::Verifier &verifier, const void *obj, VarUnion type) { diff --git a/TombEngine/Specific/savegame/schema/ten_savegame.fbs b/TombEngine/Specific/savegame/schema/ten_savegame.fbs index 2e1d13b31..f5f467269 100644 --- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs +++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs @@ -458,6 +458,8 @@ table SaveGame { volume_states: [VolumeState]; call_counters: [EventSetCallCounters]; script_vars: UnionVec; + callbacks_pre_control: [string]; + callbacks_post_control: [string]; } root_type TEN.Save.SaveGame;