mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-16 21:34:01 +02:00
Disallow particle lifetime management in some contexts
Namely, in Create and ChangeType callbacks, which are themselves called by such lifetime management functions. Lifetime management includes explicit actions via partCreate and partKill, but also implicit ones such as changing the type property or changing x or y properties to values that move the particle beyond the edges and causes it to be killed.
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -129,6 +129,7 @@ public:
|
||||
|
||||
int textInputRefcount = 0;
|
||||
long unsigned int luaExecutionStart = 0;
|
||||
int monopartAccessPartID = -1;
|
||||
|
||||
private:
|
||||
std::vector<std::list<LuaSmartRef>> gameControllerEventHandlers; // must come after luaState
|
||||
@@ -154,6 +155,7 @@ public:
|
||||
void AssertInterfaceEvent();
|
||||
void AssertMutableSimEvent();
|
||||
void AssertMutableToolsEvent();
|
||||
void AssertMonopartAccessEvent(int partID);
|
||||
|
||||
friend class CommandInterface;
|
||||
};
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user