diff --git a/src/gui/game/GameControllerEvents.h b/src/gui/game/GameControllerEvents.h index 3d530f553..ed4ce1af0 100644 --- a/src/gui/game/GameControllerEvents.h +++ b/src/gui/game/GameControllerEvents.h @@ -13,6 +13,7 @@ enum EventTraits : uint32_t eventTraitInterfaceGraphics = UINT32_C(0x00000010), eventTraitConstSim = UINT32_C(0x00000020), eventTraitConstTools = UINT32_C(0x00000040), + eventTraitMonopartAccess = UINT32_C(0x00000080), }; constexpr EventTraits operator |(EventTraits lhs, EventTraits rhs) { diff --git a/src/lua/LuaElements.cpp b/src/lua/LuaElements.cpp index c0578ec03..e88f1cc61 100644 --- a/src/lua/LuaElements.cpp +++ b/src/lua/LuaElements.cpp @@ -225,11 +225,13 @@ static void luaCreateWrapper(ELEMENT_CREATE_FUNC_ARGS) lua_pushinteger(lsi->L, y); lua_pushinteger(lsi->L, t); lua_pushinteger(lsi->L, v); - if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng)) + lsi->monopartAccessPartID = i; + if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng | eventTraitMonopartAccess)) { lsi->Log(CommandInterface::LogError, "In create func: " + LuaGetError()); lua_pop(lsi->L, 1); } + lsi->monopartAccessPartID = -1; } } @@ -283,11 +285,13 @@ static void luaChangeTypeWrapper(ELEMENT_CHANGETYPE_FUNC_ARGS) lua_pushinteger(lsi->L, y); lua_pushinteger(lsi->L, from); lua_pushinteger(lsi->L, to); - if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng)) + lsi->monopartAccessPartID = i; + if (tpt_lua_pcall(lsi->L, 5, 0, 0, eventTraitSimRng | eventTraitMonopartAccess)) { lsi->Log(CommandInterface::LogError, "In change type: " + LuaGetError()); lua_pop(lsi->L, 1); } + lsi->monopartAccessPartID = -1; } } diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index d922c01bc..f71967940 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -319,10 +319,12 @@ void LuaSetParticleProperty(lua_State *L, int particleID, StructProperty propert auto *sim = lsi->sim; if (property.Name == "type") { + lsi->AssertMonopartAccessEvent(-1); sim->part_change_type(particleID, int(sim->parts[particleID].x+0.5f), int(sim->parts[particleID].y+0.5f), luaL_checkinteger(L, 3)); } else if (property.Name == "x" || property.Name == "y") { + lsi->AssertMonopartAccessEvent(-1); float val = luaL_checknumber(L, 3); float x = sim->parts[particleID].x; float y = sim->parts[particleID].y; @@ -332,6 +334,7 @@ void LuaSetParticleProperty(lua_State *L, int particleID, StructProperty propert } else { + lsi->AssertMonopartAccessEvent(particleID); LuaSetProperty(L, property, propertyAddress, 3); } } @@ -917,3 +920,12 @@ void LuaScriptInterface::AssertMutableToolsEvent() luaL_error(L, "this functionality is restricted to mutable tool events"); } } + +void LuaScriptInterface::AssertMonopartAccessEvent(int partID) +{ + AssertMutableSimEvent(); + if ((eventTraits & eventTraitMonopartAccess) && monopartAccessPartID != partID) + { + luaL_error(L, "particle management is restricted to ID %i", monopartAccessPartID); + } +} diff --git a/src/lua/LuaScriptInterface.h b/src/lua/LuaScriptInterface.h index ce11bcb1e..9572f7bc2 100644 --- a/src/lua/LuaScriptInterface.h +++ b/src/lua/LuaScriptInterface.h @@ -129,6 +129,7 @@ public: int textInputRefcount = 0; long unsigned int luaExecutionStart = 0; + int monopartAccessPartID = -1; private: std::vector> gameControllerEventHandlers; // must come after luaState @@ -154,6 +155,7 @@ public: void AssertInterfaceEvent(); void AssertMutableSimEvent(); void AssertMutableToolsEvent(); + void AssertMonopartAccessEvent(int partID); friend class CommandInterface; }; diff --git a/src/lua/LuaSimulation.cpp b/src/lua/LuaSimulation.cpp index 9e6ac76b9..6293a4002 100644 --- a/src/lua/LuaSimulation.cpp +++ b/src/lua/LuaSimulation.cpp @@ -312,7 +312,7 @@ static int partNeighbors(lua_State *L) static int partChangeType(lua_State *L) { auto *lsi = GetLSI(); - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); int partIndex = lua_tointeger(L, 1); if(partIndex < 0 || partIndex >= NPART || !lsi->sim->parts[partIndex].type) return 0; @@ -323,7 +323,7 @@ static int partChangeType(lua_State *L) static int partCreate(lua_State *L) { auto *lsi = GetLSI(); - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); int newID = lua_tointeger(L, 1); if (newID >= NPART || newID < -3) { @@ -386,6 +386,7 @@ static int partPosition(lua_State *L) { if(argCount == 1) { + lsi->AssertMonopartAccessEvent(-1); lua_pushnil(L); lua_pushnil(L); return 2; @@ -396,7 +397,7 @@ static int partPosition(lua_State *L) if (argCount == 3) { - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); float x = sim->parts[particleID].x; float y = sim->parts[particleID].y; sim->move(particleID, (int)(x + 0.5f), (int)(y + 0.5f), lua_tonumber(L, 2), lua_tonumber(L, 3)); @@ -422,7 +423,7 @@ static int partProperty(lua_State *L) { if (argCount == 3) { - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); return 0; } lua_pushnil(L); @@ -466,7 +467,6 @@ static int partProperty(lua_State *L) if (argCount == 3) { - lsi->AssertMutableSimEvent(); LuaSetParticleProperty(L, particleID, *prop, propertyAddress, 3); return 0; } @@ -477,7 +477,7 @@ static int partProperty(lua_State *L) static int partKill(lua_State *L) { auto *lsi = GetLSI(); - lsi->AssertMutableSimEvent(); + lsi->AssertMonopartAccessEvent(-1); if(lua_gettop(L)==2) lsi->sim->delete_part(lua_tointeger(L, 1), lua_tointeger(L, 2)); else