Add: [Script] GSAsyncMode to set async mode of gamescript commands (#10913)
In asynchronous mode, don't wait for result of executed command, just fire-and-forget, and return estimated cost/result
This commit is contained in:
committed by
GitHub
parent
5821194ad1
commit
3effb8931c
@@ -82,6 +82,22 @@ ScriptObject::ActiveInstance::~ActiveInstance()
|
||||
return GetStorage()->mode_instance;
|
||||
}
|
||||
|
||||
/* static */ void ScriptObject::SetDoCommandAsyncMode(ScriptAsyncModeProc *proc, ScriptObject *instance)
|
||||
{
|
||||
GetStorage()->async_mode = proc;
|
||||
GetStorage()->async_mode_instance = instance;
|
||||
}
|
||||
|
||||
/* static */ ScriptAsyncModeProc *ScriptObject::GetDoCommandAsyncMode()
|
||||
{
|
||||
return GetStorage()->async_mode;
|
||||
}
|
||||
|
||||
/* static */ ScriptObject *ScriptObject::GetDoCommandAsyncModeInstance()
|
||||
{
|
||||
return GetStorage()->async_mode_instance;
|
||||
}
|
||||
|
||||
/* static */ void ScriptObject::SetLastCommand(const CommandDataBuffer &data, Commands cmd)
|
||||
{
|
||||
ScriptStorage *s = GetStorage();
|
||||
@@ -239,7 +255,7 @@ ScriptObject::ActiveInstance::~ActiveInstance()
|
||||
return ScriptObject::GetActiveInstance()->GetDoCommandCallback();
|
||||
}
|
||||
|
||||
std::tuple<bool, bool, bool> ScriptObject::DoCommandPrep()
|
||||
std::tuple<bool, bool, bool, bool> 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.");
|
||||
@@ -248,17 +264,20 @@ std::tuple<bool, bool, bool> ScriptObject::DoCommandPrep()
|
||||
/* Are we only interested in the estimate costs? */
|
||||
bool estimate_only = GetDoCommandMode() != nullptr && !GetDoCommandMode()();
|
||||
|
||||
/* Should the command be executed asynchronously? */
|
||||
bool asynchronous = GetDoCommandAsyncMode() != nullptr && GetDoCommandAsyncMode()();
|
||||
|
||||
bool networking = _networking && !_generating_world;
|
||||
|
||||
if (!ScriptCompanyMode::IsDeity() && !ScriptCompanyMode::IsValid()) {
|
||||
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY);
|
||||
return { true, estimate_only, networking };
|
||||
return { true, estimate_only, asynchronous, networking };
|
||||
}
|
||||
|
||||
return { false, estimate_only, networking };
|
||||
return { false, estimate_only, asynchronous, networking };
|
||||
}
|
||||
|
||||
bool ScriptObject::DoCommandProcessResult(const CommandCost &res, Script_SuspendCallbackProc *callback, bool estimate_only)
|
||||
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;
|
||||
@@ -282,8 +301,13 @@ bool ScriptObject::DoCommandProcessResult(const CommandCost &res, Script_Suspend
|
||||
SetLastCost(res.GetCost());
|
||||
SetLastCommandRes(true);
|
||||
|
||||
if (_generating_world) {
|
||||
if (_generating_world || asynchronous) {
|
||||
IncreaseDoCommandCosts(res.GetCost());
|
||||
if (!_generating_world) {
|
||||
/* Charge a nominal fee for asynchronously executed commands */
|
||||
Squirrel *engine = ScriptObject::GetActiveInstance()->engine;
|
||||
Squirrel::DecreaseOps(engine->GetVM(), 100);
|
||||
}
|
||||
if (callback != nullptr) {
|
||||
/* Insert return value into to stack and throw a control code that
|
||||
* the return value in the stack should be used. */
|
||||
|
||||
Reference in New Issue
Block a user