diff --git a/src/script/api/script_includes.hpp.in b/src/script/api/script_includes.hpp.in index e3136e49f3..7bb7092c74 100644 --- a/src/script/api/script_includes.hpp.in +++ b/src/script/api/script_includes.hpp.in @@ -11,22 +11,12 @@ ${SQUIRREL_INCLUDES} -static SQInteger ${APIUC}ObjectConstructor(HSQUIRRELVM vm) -{ - return sq_throwerror(vm, "This class is not instantiable"); -} - -static SQInteger ${APIUC}ObjectCloned(HSQUIRRELVM) -{ - throw Script_FatalError("This instance is not cloneable"); -} - void SQ${APIUC}_RegisterAll(Squirrel &engine) { DefSQClass SQ${APIUC}Object("${APIUC}Object"); SQ${APIUC}Object.PreRegister(engine); - SQ${APIUC}Object.DefSQAdvancedStaticMethod(engine, &${APIUC}ObjectConstructor, "constructor"); - SQ${APIUC}Object.DefSQAdvancedStaticMethod(engine, &${APIUC}ObjectCloned, "_cloned"); + SQ${APIUC}Object.DefSQAdvancedStaticMethod(engine, &ScriptObject::Constructor, "constructor"); + SQ${APIUC}Object.DefSQAdvancedStaticMethod(engine, &ScriptObject::_cloned, "_cloned"); SQ${APIUC}Object.PostRegister(engine); ${SQUIRREL_REGISTER} diff --git a/src/script/api/script_object.cpp b/src/script/api/script_object.cpp index f82852db5c..b656a95c09 100644 --- a/src/script/api/script_object.cpp +++ b/src/script/api/script_object.cpp @@ -22,6 +22,7 @@ #include "../script_fatalerror.hpp" #include "script_error.hpp" #include "../../debug.h" +#include "../squirrel_helper.hpp" #include "../../safeguards.h" @@ -259,7 +260,7 @@ ScriptObject::DisableDoCommandScope::DisableDoCommandScope() return ScriptObject::GetActiveInstance().GetDoCommandCallback(); } -std::tuple ScriptObject::DoCommandPrep() +/* static */ std::tuple ScriptObject::DoCommandPrep() { if (!ScriptObject::CanSuspend()) { throw Script_FatalError("You are not allowed to execute any DoCommand (even indirect) in your constructor, Save(), Load(), and any valuator."); @@ -281,7 +282,7 @@ std::tuple ScriptObject::DoCommandPrep() return { false, estimate_only, asynchronous, networking }; } -bool ScriptObject::DoCommandProcessResult(const CommandCost &res, Script_SuspendCallbackProc *callback, bool estimate_only, bool asynchronous) +/* static */ bool ScriptObject::DoCommandProcessResult(const CommandCost &res, Script_SuspendCallbackProc *callback, bool estimate_only, bool asynchronous) { /* Set the default callback to return a true/false result of the DoCommand */ if (callback == nullptr) callback = &ScriptInstance::DoCommandReturn; @@ -338,15 +339,33 @@ bool ScriptObject::DoCommandProcessResult(const CommandCost &res, Script_Suspend /* static */ ScriptObject::RandomizerArray ScriptObject::random_states; -Randomizer &ScriptObject::GetRandomizer(Owner owner) +/* static */ Randomizer &ScriptObject::GetRandomizer(Owner owner) { return ScriptObject::random_states[owner]; } -void ScriptObject::InitializeRandomizers() +/* static */ void ScriptObject::InitializeRandomizers() { Randomizer random = _random; for (Owner owner = OWNER_BEGIN; owner < OWNER_END; ++owner) { ScriptObject::GetRandomizer(owner).SetSeed(random.Next()); } } + +/* static */ SQInteger ScriptObject::Constructor(HSQUIRRELVM) +{ + throw Script_FatalError("This class is not instantiable"); +} + +/* static */ SQInteger ScriptObject::_cloned(HSQUIRRELVM vm) +{ + ScriptObject *original = static_cast(Squirrel::GetRealInstance(vm, 2, "Object")); + if (ScriptObject *clone = original->CloneObject(); clone != nullptr) { + clone->AddRef(); + sq_setinstanceup(vm, 1, clone); + sq_setreleasehook(vm, 1, SQConvert::DefSQDestructorCallback); + return 0; + } + + throw Script_FatalError("This instance is not cloneable"); +} diff --git a/src/script/api/script_object.hpp b/src/script/api/script_object.hpp index 710b0ce312..a0d6821e8a 100644 --- a/src/script/api/script_object.hpp +++ b/src/script/api/script_object.hpp @@ -105,6 +105,12 @@ protected: */ virtual bool LoadObject(HSQUIRRELVM) { return false; } + /** + * Clone an object. + * @return The clone if cloning this type is supported, nullptr otherwise. + */ + virtual ScriptObject *CloneObject() { return nullptr; } + public: /** * Store the latest result of a DoCommand per company. @@ -136,6 +142,16 @@ public: */ static void InitializeRandomizers(); + /** + * Used when trying to instanciate ScriptObject from squirrel. + */ + static SQInteger Constructor(HSQUIRRELVM); + + /** + * Used for 'clone' from squirrel. + */ + static SQInteger _cloned(HSQUIRRELVM); + protected: template struct ScriptDoCommandHelper;