Add scripting API for custom execution context

This allows a script to create its own execution context so that it can
control when a coroutine is valid to play based on custom data.

Also adds a function which causes a coroutine to end in an error.
This commit is contained in:
asarium committed 2020-08-11 09:38:39 +02:00
1 parent b419d3fac5
commit 8fcb05bfd0
10 files changed
+447 -505

No files matched your search

@@ -0,0 +1,34 @@
#include "CombinedExecutionContext.h"
namespace executor {
CombinedExecutionContext::CombinedExecutionContext(SCP_vector<std::shared_ptr<IExecutionContext>> contexts)
: m_contexts(std::move(contexts))
{
}
IExecutionContext::State CombinedExecutionContext::determineContextState() const
{
bool suspended_context = false;
bool invalid_context = false;
for (const auto& context : m_contexts) {
const auto state = context->determineContextState();
if (state == IExecutionContext::State::Suspended) {
suspended_context = true;
} else if (state == IExecutionContext::State::Invalid) {
invalid_context = true;
}
}
// If there is an invalid context then the combined state is invalid
// If there is not but there is a suspended one, then the state is suspended
if (invalid_context) {
return IExecutionContext::State::Invalid;
} else if (suspended_context) {
return IExecutionContext::State::Suspended;
} else {
return IExecutionContext::State::Valid;
}
}
CombinedExecutionContext::~CombinedExecutionContext() = default;
} // namespace executor
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include "IExecutionContext.h"
#include "gamesequence/gamesequence.h"
#include "utils/event.h"
namespace executor {
class CombinedExecutionContext : public IExecutionContext {
public:
CombinedExecutionContext(SCP_vector<std::shared_ptr<IExecutionContext>> contexts);
~CombinedExecutionContext() override;
State determineContextState() const override;
private:
SCP_vector<std::shared_ptr<IExecutionContext>> m_contexts;
};
} // namespace executor
@@ -0,0 +1,50 @@
#include "LuaExecutionContext.h"
#include "scripting/ade_args.h"
#include "scripting/api/objs/enums.h"
namespace scripting {
namespace api {
LuaExecutionContext::LuaExecutionContext(luacpp::LuaFunction contextFunction)
: m_contextFunction(std::move(contextFunction))
{
}
LuaExecutionContext::~LuaExecutionContext() = default;
executor::IExecutionContext::State LuaExecutionContext::determineContextState() const
{
auto L = m_contextFunction.getLuaState();
const auto returnVal = m_contextFunction.call(L);
if (returnVal.size() != 1) {
LuaError(L, "Need exactly one return value for Lua execution context function!");
return executor::IExecutionContext::State::Invalid;
}
const auto currentTop = lua_gettop(L);
returnVal[0].pushValue(L);
enum_h enumValue;
internal::Ade_get_args_lfunction = true;
internal::Ade_get_args_skip = currentTop;
if (!ade_get_args(L, "o", l_Enum.Get(&enumValue))) {
lua_settop(L, currentTop);
return executor::IExecutionContext::State::Invalid;
}
lua_settop(L, currentTop);
switch (enumValue.index) {
case LE_CONTEXT_INVALID:
return executor::IExecutionContext::State::Invalid;
case LE_CONTEXT_SUSPENDED:
return executor::IExecutionContext::State::Suspended;
case LE_CONTEXT_VALID:
return executor::IExecutionContext::State::Valid;
default:
LuaError(L, "Got invalid enum value %s from Lua context function.", enumValue.getName().c_str());
return executor::IExecutionContext::State::Invalid;
}
}
} // namespace api
} // namespace scripting
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "executor/IExecutionContext.h"
#include "gamesequence/gamesequence.h"
#include "scripting/lua/LuaFunction.h"
#include "utils/event.h"
namespace scripting {
namespace api {
class LuaExecutionContext : public executor::IExecutionContext {
public:
LuaExecutionContext(luacpp::LuaFunction contextFunction);
~LuaExecutionContext() override;
State determineContextState() const override;
private:
luacpp::LuaFunction m_contextFunction;
};
} // namespace api
} // namespace scripting
+112 -10
View File
@@ -1,9 +1,12 @@
#include "async.h"
#include "executor/CombinedExecutionContext.h"
#include "executor/GameStateExecutionContext.h"
#include "executor/global_executors.h"
#include "scripting/api/LuaCoroutineRunner.h"
#include "scripting/api/LuaExecutionContext.h"
#include "scripting/api/objs/execution_context.h"
#include "scripting/api/objs/executor.h"
#include "scripting/api/objs/promise.h"
#include "scripting/lua/LuaThread.h"
@@ -169,7 +172,8 @@ ADE_FUNC(errored,
ADE_FUNC(run,
l_Async,
"function() => any body",
"function() => any body, [executor executeOn = nil, boolean|execution_context captureContext = true /* Captures "
"game state context by default */]",
"Runs an asynchronous function. Inside this function you can use async.await to suspend the function until a "
"promise resolves.",
"promise",
@@ -177,9 +181,24 @@ ADE_FUNC(run,
{
luacpp::LuaFunction body;
executor_h executor;
bool captureContext = true;
if (!ade_get_args(L, "u|ob", &body, l_Executor.Get(&executor), &captureContext)) {
return ADE_RETURN_NIL;
std::shared_ptr<executor::IExecutionContext> context;
if (lua_type(L, 3) == LUA_TUSERDATA) {
execution_context_h* ctx = nullptr;
if (!ade_get_args(L, "u|oo", &body, l_Executor.Get(&executor), l_ExecutionContext.GetPtr(&ctx))) {
return ADE_RETURN_NIL;
}
if (ctx != nullptr) {
context = ctx->getExecutionContext();
}
} else {
bool captureContext = true;
if (!ade_get_args(L, "u|ob", &body, l_Executor.Get(&executor), &captureContext)) {
return ADE_RETURN_NIL;
}
if (executor.isValid() && captureContext) {
context = executor::GameStateExecutionContext::captureContext();
}
}
auto coroutine = luacpp::LuaThread::create(L, body);
@@ -188,14 +207,9 @@ ADE_FUNC(run,
return true;
});
std::shared_ptr<executor::IExecutionContext> exeContext;
if (executor.isValid() && captureContext) {
exeContext = executor::GameStateExecutionContext::captureContext();
}
return ade_set_args(L,
"o",
l_Promise.Set(runAsyncCoroutine(std::move(coroutine), executor.getExecutor(), std::move(exeContext))));
l_Promise.Set(runAsyncCoroutine(std::move(coroutine), executor.getExecutor(), std::move(context))));
}
ADE_FUNC(await,
@@ -273,5 +287,93 @@ ADE_FUNC(yield,
l_Promise.Set(LuaPromise(std::make_shared<yield_resolve_context>(executor::currentExecutor()))));
}
ADE_FUNC(error,
l_Async,
"...",
"Causes the currently running coroutine to fail with an error with the specified values.",
nullptr,
"Does not return")
{
// error cannot be used on the main thread since there is nothing that will wait for the promise
if (lua_pushthread(L)) {
// We are the main thread
lua_pop(L, 1);
LuaError(L, "Tried to cause a coroutine error on the main thread! That is not supported.");
return ADE_RETURN_NIL;
}
lua_pop(L, 1);
auto nargs = lua_gettop(L);
luacpp::LuaValueList values;
values.reserve(nargs);
for (int i = 1; i <= nargs; ++i) {
luacpp::LuaValue val;
val.setReference(luacpp::UniqueLuaReference::create(L, i));
values.push_back(val);
}
// Push an errored promise on the stack and then yield the coroutine. The awaiter will get this promise and stop
// execution.
ade_set_args(L, "o", l_Promise.Set(LuaPromise::errored(values)));
return lua_yield(L, 1);
}
//**********SUBLIBRARY: async/context
ADE_LIB_DERIV(l_Async_Context, "context", nullptr, "Support library for creating execution contexts.", l_Async);
ADE_FUNC(captureGameState,
l_Async_Context,
nullptr,
"Captures the current game state as an execution context",
"execution_context",
"The execution context or invalid handle on error")
{
return ade_set_args(L,
"o",
l_ExecutionContext.Set(execution_context_h(executor::GameStateExecutionContext::captureContext())));
}
ADE_FUNC(createLuaState,
l_Async_Context,
"function() => enumeration",
"Creates an execution state by storing the passed function and calling that when the state is required.",
"execution_context",
"The execution context or invalid handle on error")
{
luacpp::LuaFunction body;
if (!ade_get_args(L, "u", &body)) {
return ade_set_args(L, "o", l_ExecutionContext.Set(execution_context_h(nullptr)));
}
return ade_set_args(L,
"o",
l_ExecutionContext.Set(execution_context_h(std::make_shared<LuaExecutionContext>(std::move(body)))));
}
ADE_FUNC(combineContexts,
l_Async_Context,
"execution_context... contexts",
"Combines several execution contexts into a single one by only return a valid state if all contexts are valid.",
"execution_context",
"The execution context or invalid handle on error")
{
SCP_vector<std::shared_ptr<executor::IExecutionContext>> contexts;
for (int i = 0; i < lua_gettop(L); ++i) {
execution_context_h* ctx;
internal::Ade_get_args_skip = i;
if (!ade_get_args(L, "o", l_ExecutionContext.GetPtr(&ctx))) {
return ade_set_args(L, "o", l_ExecutionContext.Set(execution_context_h(nullptr)));
}
contexts.emplace_back(ctx->getExecutionContext());
}
return ade_set_args(L,
"o",
l_ExecutionContext.Set(
execution_context_h(std::make_shared<executor::CombinedExecutionContext>(std::move(contexts)))));
}
} // namespace api
} // namespace scripting
+103 -494
View File
@@ -13,494 +13,95 @@ namespace api {
//or after. Don't forget to increment NEXT INDEX after you're done.
//=====================================
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// clang-format off
flag_def_list Enumerations[] = {
{
"ALPHABLEND_FILTER",
LE_ALPHABLEND_FILTER,
0
},
{
"ALPHABLEND_NONE",
LE_ALPHABLEND_NONE,
0
},
{
"CFILE_TYPE_NORMAL",
LE_CFILE_TYPE_NORMAL,
0
},
{
"CFILE_TYPE_MEMORY_MAPPED",
LE_CFILE_TYPE_MEMORY_MAPPED,
0
},
{
"MOUSE_LEFT_BUTTON",
LE_MOUSE_LEFT_BUTTON,
0
},
{
"MOUSE_RIGHT_BUTTON",
LE_MOUSE_RIGHT_BUTTON,
0
},
{
"MOUSE_MIDDLE_BUTTON",
LE_MOUSE_MIDDLE_BUTTON,
0
},
{
"ORDER_ATTACK",
LE_ORDER_ATTACK,
0
},
{
"ORDER_ATTACK_ANY",
LE_ORDER_ATTACK_ANY,
0
},
{
"ORDER_DEPART",
LE_ORDER_DEPART,
0
},
{
"ORDER_DISABLE",
LE_ORDER_DISABLE,
0
},
{
"ORDER_DISARM",
LE_ORDER_DISARM,
0
},
{
"ORDER_DOCK",
LE_ORDER_DOCK,
0
},
{
"ORDER_EVADE",
LE_ORDER_EVADE,
0
},
{
"ORDER_FLY_TO",
LE_ORDER_FLY_TO,
0
},
{
"ORDER_FORM_ON_WING",
LE_ORDER_FORM_ON_WING,
0
},
{
"ORDER_GUARD",
LE_ORDER_GUARD,
0
},
{
"ORDER_IGNORE_SHIP",
LE_ORDER_IGNORE,
0
},
{
"ORDER_KEEP_SAFE_DISTANCE",
LE_ORDER_KEEP_SAFE_DISTANCE,
0
},
{
"ORDER_PLAY_DEAD",
LE_ORDER_PLAY_DEAD,
0
},
{
"ORDER_PLAY_DEAD_PERSISTENT",
LE_ORDER_PLAY_DEAD_PERSISTENT,
0
},
{
"ORDER_REARM",
LE_ORDER_REARM,
0
},
{
"ORDER_STAY_NEAR",
LE_ORDER_STAY_NEAR,
0
},
{
"ORDER_STAY_STILL",
LE_ORDER_STAY_STILL,
0
},
{
"ORDER_UNDOCK",
LE_ORDER_UNDOCK,
0
},
{
"ORDER_WAYPOINTS",
LE_ORDER_WAYPOINTS,
0
},
{
"ORDER_WAYPOINTS_ONCE",
LE_ORDER_WAYPOINTS_ONCE,
0
},
{
"ORDER_ATTACK_WING",
LE_ORDER_ATTACK_WING,
0
},
{
"ORDER_GUARD_WING",
LE_ORDER_GUARD_WING,
0
},
{
"ORDER_ATTACK_SHIP_CLASS",
LE_ORDER_ATTACK_SHIP_CLASS,
0
},
{
"PARTICLE_DEBUG",
LE_PARTICLE_DEBUG,
0
},
{
"PARTICLE_BITMAP",
LE_PARTICLE_BITMAP,
0
},
{
"PARTICLE_FIRE",
LE_PARTICLE_FIRE,
0
},
{
"PARTICLE_SMOKE",
LE_PARTICLE_SMOKE,
0
},
{
"PARTICLE_SMOKE2",
LE_PARTICLE_SMOKE2,
0
},
{
"PARTICLE_PERSISTENT_BITMAP",
LE_PARTICLE_PERSISTENT_BITMAP,
0
},
{
"SEXPVAR_CAMPAIGN_PERSISTENT",
LE_SEXPVAR_CAMPAIGN_PERSISTENT,
0
},
{
"SEXPVAR_NOT_PERSISTENT",
LE_SEXPVAR_NOT_PERSISTENT,
0
},
{
"SEXPVAR_PLAYER_PERSISTENT",
LE_SEXPVAR_PLAYER_PERSISTENT,
0
},
{
"SEXPVAR_TYPE_NUMBER",
LE_SEXPVAR_TYPE_NUMBER,
0
},
{
"SEXPVAR_TYPE_STRING",
LE_SEXPVAR_TYPE_STRING,
0
},
{
"TEXTURE_STATIC",
LE_TEXTURE_STATIC,
0
},
{
"TEXTURE_DYNAMIC",
LE_TEXTURE_DYNAMIC,
0
},
{
"LOCK",
LE_LOCK,
0
},
{
"UNLOCK",
LE_UNLOCK,
0
},
{
"NONE",
LE_NONE,
0
},
{
"SHIELD_FRONT",
LE_SHIELD_FRONT,
0
},
{
"SHIELD_LEFT",
LE_SHIELD_LEFT,
0
},
{
"SHIELD_RIGHT",
LE_SHIELD_RIGHT,
0
},
{
"SHIELD_BACK",
LE_SHIELD_BACK,
0
},
{
"MISSION_REPEAT",
LE_MISSION_REPEAT,
0
},
{
"NORMAL_CONTROLS",
LE_NORMAL_CONTROLS,
0
},
{
"LUA_STEERING_CONTROLS",
LE_LUA_STEERING_CONTROLS,
0
},
{
"LUA_FULL_CONTROLS",
LE_LUA_FULL_CONTROLS,
0
},
{
"NORMAL_BUTTON_CONTROLS",
LE_NORMAL_BUTTON_CONTROLS,
0
},
{
"LUA_ADDITIVE_BUTTON_CONTROL",
LE_LUA_ADDITIVE_BUTTON_CONTROL,
0
},
{
"LUA_OVERRIDE_BUTTON_CONTROL",
LE_LUA_OVERRIDE_BUTTON_CONTROL,
0
},
{
"VM_INTERNAL",
LE_VM_INTERNAL,
0
},
{
"VM_EXTERNAL",
LE_VM_EXTERNAL,
0
},
{
"VM_TRACK",
LE_VM_TRACK,
0
},
{
"VM_DEAD_VIEW",
LE_VM_DEAD_VIEW,
0
},
{
"VM_CHASE",
LE_VM_CHASE,
0
},
{
"VM_OTHER_SHIP",
LE_VM_OTHER_SHIP,
0
},
{
"VM_EXTERNAL_CAMERA_LOCKED",
LE_VM_EXTERNAL_CAMERA_LOCKED,
0
},
{
"VM_CAMERA_LOCKED",
LE_VM_CAMERA_LOCKED,
0
},
{
"VM_WARP_CHASE",
LE_VM_WARP_CHASE,
0
},
{
"VM_PADLOCK_UP",
LE_VM_PADLOCK_UP,
0
},
{
"VM_PADLOCK_REAR",
LE_VM_PADLOCK_REAR,
0
},
{
"VM_PADLOCK_LEFT",
LE_VM_PADLOCK_LEFT,
0
},
{
"VM_PADLOCK_RIGHT",
LE_VM_PADLOCK_RIGHT,
0
},
{
"VM_WARPIN_ANCHOR",
LE_VM_WARPIN_ANCHOR,
0
},
{
"VM_TOPDOWN",
LE_VM_TOPDOWN,
0
},
{
"VM_FREECAMERA",
LE_VM_FREECAMERA,
0
},
{
"VM_CENTERING",
LE_VM_CENTERING,
0
},
{
"MESSAGE_PRIORITY_LOW",
LE_MESSAGE_PRIORITY_LOW,
0
},
{
"MESSAGE_PRIORITY_NORMAL",
LE_MESSAGE_PRIORITY_NORMAL,
0
},
{
"MESSAGE_PRIORITY_HIGH",
LE_MESSAGE_PRIORITY_HIGH,
0
},
{
"OPTION_TYPE_SELECTION",
LE_OPTION_TYPE_SELECTION,
0
},
{
"OPTION_TYPE_RANGE",
LE_OPTION_TYPE_RANGE,
0
},
{
"AUDIOSTREAM_EVENTMUSIC",
LE_ASF_EVENTMUSIC,
0
},
{
"AUDIOSTREAM_MENUMUSIC",
LE_ASF_MENUMUSIC,
0
},
{
"AUDIOSTREAM_VOICE",
LE_ASF_VOICE,
0
},
{"ALPHABLEND_FILTER", LE_ALPHABLEND_FILTER, 0},
{"ALPHABLEND_NONE", LE_ALPHABLEND_NONE, 0},
{"CFILE_TYPE_NORMAL", LE_CFILE_TYPE_NORMAL, 0},
{"CFILE_TYPE_MEMORY_MAPPED", LE_CFILE_TYPE_MEMORY_MAPPED, 0},
{"MOUSE_LEFT_BUTTON", LE_MOUSE_LEFT_BUTTON, 0},
{"MOUSE_RIGHT_BUTTON", LE_MOUSE_RIGHT_BUTTON, 0},
{"MOUSE_MIDDLE_BUTTON", LE_MOUSE_MIDDLE_BUTTON, 0},
{"ORDER_ATTACK", LE_ORDER_ATTACK, 0},
{"ORDER_ATTACK_ANY", LE_ORDER_ATTACK_ANY, 0},
{"ORDER_DEPART", LE_ORDER_DEPART, 0},
{"ORDER_DISABLE", LE_ORDER_DISABLE, 0},
{"ORDER_DISARM", LE_ORDER_DISARM, 0},
{"ORDER_DOCK", LE_ORDER_DOCK, 0},
{"ORDER_EVADE", LE_ORDER_EVADE, 0},
{"ORDER_FLY_TO", LE_ORDER_FLY_TO, 0},
{"ORDER_FORM_ON_WING", LE_ORDER_FORM_ON_WING, 0},
{"ORDER_GUARD", LE_ORDER_GUARD, 0},
{"ORDER_IGNORE_SHIP", LE_ORDER_IGNORE, 0},
{"ORDER_KEEP_SAFE_DISTANCE", LE_ORDER_KEEP_SAFE_DISTANCE, 0},
{"ORDER_PLAY_DEAD", LE_ORDER_PLAY_DEAD, 0},
{"ORDER_PLAY_DEAD_PERSISTENT", LE_ORDER_PLAY_DEAD_PERSISTENT, 0},
{"ORDER_REARM", LE_ORDER_REARM, 0},
{"ORDER_STAY_NEAR", LE_ORDER_STAY_NEAR, 0},
{"ORDER_STAY_STILL", LE_ORDER_STAY_STILL, 0},
{"ORDER_UNDOCK", LE_ORDER_UNDOCK, 0},
{"ORDER_WAYPOINTS", LE_ORDER_WAYPOINTS, 0},
{"ORDER_WAYPOINTS_ONCE", LE_ORDER_WAYPOINTS_ONCE, 0},
{"ORDER_ATTACK_WING", LE_ORDER_ATTACK_WING, 0},
{"ORDER_GUARD_WING", LE_ORDER_GUARD_WING, 0},
{"ORDER_ATTACK_SHIP_CLASS", LE_ORDER_ATTACK_SHIP_CLASS, 0},
{"PARTICLE_DEBUG", LE_PARTICLE_DEBUG, 0},
{"PARTICLE_BITMAP", LE_PARTICLE_BITMAP, 0},
{"PARTICLE_FIRE", LE_PARTICLE_FIRE, 0},
{"PARTICLE_SMOKE", LE_PARTICLE_SMOKE, 0},
{"PARTICLE_SMOKE2", LE_PARTICLE_SMOKE2, 0},
{"PARTICLE_PERSISTENT_BITMAP", LE_PARTICLE_PERSISTENT_BITMAP, 0},
{"SEXPVAR_CAMPAIGN_PERSISTENT", LE_SEXPVAR_CAMPAIGN_PERSISTENT, 0},
{"SEXPVAR_NOT_PERSISTENT", LE_SEXPVAR_NOT_PERSISTENT, 0},
{"SEXPVAR_PLAYER_PERSISTENT", LE_SEXPVAR_PLAYER_PERSISTENT, 0},
{"SEXPVAR_TYPE_NUMBER", LE_SEXPVAR_TYPE_NUMBER, 0},
{"SEXPVAR_TYPE_STRING", LE_SEXPVAR_TYPE_STRING, 0},
{"TEXTURE_STATIC", LE_TEXTURE_STATIC, 0},
{"TEXTURE_DYNAMIC", LE_TEXTURE_DYNAMIC, 0},
{"LOCK", LE_LOCK, 0},
{"UNLOCK", LE_UNLOCK, 0},
{"NONE", LE_NONE, 0},
{"SHIELD_FRONT", LE_SHIELD_FRONT, 0},
{"SHIELD_LEFT", LE_SHIELD_LEFT, 0},
{"SHIELD_RIGHT", LE_SHIELD_RIGHT, 0},
{"SHIELD_BACK", LE_SHIELD_BACK, 0},
{"MISSION_REPEAT", LE_MISSION_REPEAT, 0},
{"NORMAL_CONTROLS", LE_NORMAL_CONTROLS, 0},
{"LUA_STEERING_CONTROLS", LE_LUA_STEERING_CONTROLS, 0},
{"LUA_FULL_CONTROLS", LE_LUA_FULL_CONTROLS, 0},
{"NORMAL_BUTTON_CONTROLS", LE_NORMAL_BUTTON_CONTROLS, 0},
{"LUA_ADDITIVE_BUTTON_CONTROL", LE_LUA_ADDITIVE_BUTTON_CONTROL, 0},
{"LUA_OVERRIDE_BUTTON_CONTROL", LE_LUA_OVERRIDE_BUTTON_CONTROL, 0},
{"VM_INTERNAL", LE_VM_INTERNAL, 0},
{"VM_EXTERNAL", LE_VM_EXTERNAL, 0},
{"VM_TRACK", LE_VM_TRACK, 0},
{"VM_DEAD_VIEW", LE_VM_DEAD_VIEW, 0},
{"VM_CHASE", LE_VM_CHASE, 0},
{"VM_OTHER_SHIP", LE_VM_OTHER_SHIP, 0},
{"VM_EXTERNAL_CAMERA_LOCKED", LE_VM_EXTERNAL_CAMERA_LOCKED, 0},
{"VM_CAMERA_LOCKED", LE_VM_CAMERA_LOCKED, 0},
{"VM_WARP_CHASE", LE_VM_WARP_CHASE, 0},
{"VM_PADLOCK_UP", LE_VM_PADLOCK_UP, 0},
{"VM_PADLOCK_REAR", LE_VM_PADLOCK_REAR, 0},
{"VM_PADLOCK_LEFT", LE_VM_PADLOCK_LEFT, 0},
{"VM_PADLOCK_RIGHT", LE_VM_PADLOCK_RIGHT, 0},
{"VM_WARPIN_ANCHOR", LE_VM_WARPIN_ANCHOR, 0},
{"VM_TOPDOWN", LE_VM_TOPDOWN, 0},
{"VM_FREECAMERA", LE_VM_FREECAMERA, 0},
{"VM_CENTERING", LE_VM_CENTERING, 0},
{"MESSAGE_PRIORITY_LOW", LE_MESSAGE_PRIORITY_LOW, 0},
{"MESSAGE_PRIORITY_NORMAL", LE_MESSAGE_PRIORITY_NORMAL, 0},
{"MESSAGE_PRIORITY_HIGH", LE_MESSAGE_PRIORITY_HIGH, 0},
{"OPTION_TYPE_SELECTION", LE_OPTION_TYPE_SELECTION, 0},
{"OPTION_TYPE_RANGE", LE_OPTION_TYPE_RANGE, 0},
{"AUDIOSTREAM_EVENTMUSIC", LE_ASF_EVENTMUSIC, 0},
{"AUDIOSTREAM_MENUMUSIC", LE_ASF_MENUMUSIC, 0},
{"AUDIOSTREAM_VOICE", LE_ASF_VOICE, 0},
{"CONTEXT_VALID", LE_CONTEXT_VALID, 0},
{"CONTEXT_SUSPENDED", LE_CONTEXT_SUSPENDED, 0},
{"CONTEXT_INVALID", LE_CONTEXT_INVALID, 0},
};
// clang-format on
//DO NOT FORGET to increment NEXT INDEX: !!!!!!!!!!!!!
@@ -511,10 +112,21 @@ enum_h::enum_h() {
index = -1;
is_constant = false;
}
enum_h::enum_h(int n_index) {
enum_h::enum_h(int n_index)
{
index = n_index;
is_constant = false;
}
SCP_string enum_h::getName() const
{
for (size_t i = 0; i < Num_enumerations; i++) {
if (Enumerations[i].def == index) {
return Enumerations[i].name;
}
}
return SCP_string();
}
bool enum_h::IsValid() const { return (index > -1 && index < ENUM_NEXT_INDEX); }
ADE_OBJ(l_Enum, enum_h, "enumeration", "Enumeration object");
@@ -552,14 +164,11 @@ ADE_FUNC(__tostring,
return ade_set_args(L, "s", "<INVALID>");
}
uint i;
for (i = 0; i < Num_enumerations; i++) {
if (Enumerations[i].def == e->index) {
return ade_set_args(L, "s", Enumerations[i].name);
}
const auto name = e->getName();
if (name.empty()) {
return ade_set_args(L, "s", "<INVALID>");
}
return ade_set_args(L, "s", "<INVALID>");
return ade_set_args(L, "s", name);
}
ADE_FUNC(__eq,
+6 -1
View File
@@ -92,8 +92,11 @@ const int32_t LE_OPTION_TYPE_RANGE = 79;
const int32_t LE_ASF_EVENTMUSIC = 80;
const int32_t LE_ASF_MENUMUSIC = 81;
const int32_t LE_ASF_VOICE = 82;
const int32_t LE_CONTEXT_VALID = 83;
const int32_t LE_CONTEXT_SUSPENDED = 84;
const int32_t LE_CONTEXT_INVALID = 85;
const int ENUM_NEXT_INDEX = 83; // <<<<<<<<<<<<<<<<<<<<<<
const int ENUM_NEXT_INDEX = 86; // <<<<<<<<<<<<<<<<<<<<<<
extern flag_def_list Enumerations[];
extern size_t Num_enumerations;
@@ -105,6 +108,8 @@ struct enum_h {
explicit enum_h(int n_index);
SCP_string getName() const;
bool IsValid() const;
};
@@ -0,0 +1,67 @@
#include "execution_context.h"
#include "enums.h"
namespace scripting {
namespace api {
execution_context_h::execution_context_h(std::shared_ptr<executor::IExecutionContext> executionContext)
: m_executionContext(std::move(executionContext))
{
}
const std::shared_ptr<executor::IExecutionContext>& execution_context_h::getExecutionContext() const
{
return m_executionContext;
}
bool execution_context_h::isValid() const { return m_executionContext != nullptr; }
ADE_OBJ(l_ExecutionContext,
execution_context_h,
"execution_context",
"An execution context for asynchonous operations");
ADE_FUNC(determineState,
l_ExecutionContext,
nullptr,
"Determines the current state of the context.",
"enum",
"One of the CONTEXT_ enumerations")
{
execution_context_h* context = nullptr;
if (!ade_get_args(L, "o", l_ExecutionContext.GetPtr(&context))) {
return ADE_RETURN_FALSE;
}
if (!context->isValid()) {
return ade_set_args(L, "o", l_Enum.Set(enum_h(LE_CONTEXT_INVALID)));
}
const auto state = context->getExecutionContext()->determineContextState();
switch (state) {
case executor::IExecutionContext::State::Valid:
return ade_set_args(L, "o", l_Enum.Set(enum_h(LE_CONTEXT_VALID)));
case executor::IExecutionContext::State::Suspended:
return ade_set_args(L, "o", l_Enum.Set(enum_h(LE_CONTEXT_SUSPENDED)));
case executor::IExecutionContext::State::Invalid:
default:
return ade_set_args(L, "o", l_Enum.Set(enum_h(LE_CONTEXT_INVALID)));
}
}
ADE_FUNC(isValid,
l_ExecutionContext,
nullptr,
"Determines if the handle is valid",
"boolean",
"true if valid, false otherwise")
{
execution_context_h* context = nullptr;
if (!ade_get_args(L, "o", l_ExecutionContext.GetPtr(&context))) {
return ADE_RETURN_FALSE;
}
return ade_set_args(L, "b", context != nullptr && context->isValid());
}
} // namespace api
} // namespace scripting
@@ -0,0 +1,25 @@
#pragma once
#include "executor/IExecutionContext.h"
#include "scripting/ade_api.h"
namespace scripting {
namespace api {
class execution_context_h {
public:
execution_context_h(std::shared_ptr<executor::IExecutionContext> executionContext);
const std::shared_ptr<executor::IExecutionContext>& getExecutionContext() const;
bool isValid() const;
private:
std::shared_ptr<executor::IExecutionContext> m_executionContext;
};
DECLARE_ADE_OBJ(l_ExecutionContext, execution_context_h);
} // namespace api
} // namespace scripting
+6
View File
@@ -262,6 +262,8 @@ add_file_folder("ExceptionHandler"
# Executor files
add_file_folder("Executor"
executor/CombinedExecutionContext.cpp
executor/CombinedExecutionContext.h
executor/Executor.cpp
executor/Executor.h
executor/GameStateExecutionContext.cpp
@@ -1091,6 +1093,8 @@ add_file_folder("Scripting\\\\Api"
scripting/api/LuaCoroutineRunner.h
scripting/api/LuaEventCallback.cpp
scripting/api/LuaEventCallback.h
scripting/api/LuaExecutionContext.cpp
scripting/api/LuaExecutionContext.h
scripting/api/LuaPromise.cpp
scripting/api/LuaPromise.h
)
@@ -1157,6 +1161,8 @@ add_file_folder("Scripting\\\\Api\\\\Objs"
scripting/api/objs/enums.h
scripting/api/objs/event.cpp
scripting/api/objs/event.h
scripting/api/objs/execution_context.cpp
scripting/api/objs/execution_context.h
scripting/api/objs/executor.cpp
scripting/api/objs/executor.h
scripting/api/objs/eye.cpp