mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-18 14:11:16 +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),
|
eventTraitInterfaceGraphics = UINT32_C(0x00000010),
|
||||||
eventTraitConstSim = UINT32_C(0x00000020),
|
eventTraitConstSim = UINT32_C(0x00000020),
|
||||||
eventTraitConstTools = UINT32_C(0x00000040),
|
eventTraitConstTools = UINT32_C(0x00000040),
|
||||||
|
eventTraitMonopartAccess = UINT32_C(0x00000080),
|
||||||
};
|
};
|
||||||
constexpr EventTraits operator |(EventTraits lhs, EventTraits rhs)
|
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, y);
|
||||||
lua_pushinteger(lsi->L, t);
|
lua_pushinteger(lsi->L, t);
|
||||||
lua_pushinteger(lsi->L, v);
|
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());
|
lsi->Log(CommandInterface::LogError, "In create func: " + LuaGetError());
|
||||||
lua_pop(lsi->L, 1);
|
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, y);
|
||||||
lua_pushinteger(lsi->L, from);
|
lua_pushinteger(lsi->L, from);
|
||||||
lua_pushinteger(lsi->L, to);
|
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());
|
lsi->Log(CommandInterface::LogError, "In change type: " + LuaGetError());
|
||||||
lua_pop(lsi->L, 1);
|
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;
|
auto *sim = lsi->sim;
|
||||||
if (property.Name == "type")
|
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));
|
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")
|
else if (property.Name == "x" || property.Name == "y")
|
||||||
{
|
{
|
||||||
|
lsi->AssertMonopartAccessEvent(-1);
|
||||||
float val = luaL_checknumber(L, 3);
|
float val = luaL_checknumber(L, 3);
|
||||||
float x = sim->parts[particleID].x;
|
float x = sim->parts[particleID].x;
|
||||||
float y = sim->parts[particleID].y;
|
float y = sim->parts[particleID].y;
|
||||||
@@ -332,6 +334,7 @@ void LuaSetParticleProperty(lua_State *L, int particleID, StructProperty propert
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
lsi->AssertMonopartAccessEvent(particleID);
|
||||||
LuaSetProperty(L, property, propertyAddress, 3);
|
LuaSetProperty(L, property, propertyAddress, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -917,3 +920,12 @@ void LuaScriptInterface::AssertMutableToolsEvent()
|
|||||||
luaL_error(L, "this functionality is restricted to mutable tool events");
|
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;
|
int textInputRefcount = 0;
|
||||||
long unsigned int luaExecutionStart = 0;
|
long unsigned int luaExecutionStart = 0;
|
||||||
|
int monopartAccessPartID = -1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::list<LuaSmartRef>> gameControllerEventHandlers; // must come after luaState
|
std::vector<std::list<LuaSmartRef>> gameControllerEventHandlers; // must come after luaState
|
||||||
@@ -154,6 +155,7 @@ public:
|
|||||||
void AssertInterfaceEvent();
|
void AssertInterfaceEvent();
|
||||||
void AssertMutableSimEvent();
|
void AssertMutableSimEvent();
|
||||||
void AssertMutableToolsEvent();
|
void AssertMutableToolsEvent();
|
||||||
|
void AssertMonopartAccessEvent(int partID);
|
||||||
|
|
||||||
friend class CommandInterface;
|
friend class CommandInterface;
|
||||||
};
|
};
|
||||||
|
@@ -312,7 +312,7 @@ static int partNeighbors(lua_State *L)
|
|||||||
static int partChangeType(lua_State *L)
|
static int partChangeType(lua_State *L)
|
||||||
{
|
{
|
||||||
auto *lsi = GetLSI();
|
auto *lsi = GetLSI();
|
||||||
lsi->AssertMutableSimEvent();
|
lsi->AssertMonopartAccessEvent(-1);
|
||||||
int partIndex = lua_tointeger(L, 1);
|
int partIndex = lua_tointeger(L, 1);
|
||||||
if(partIndex < 0 || partIndex >= NPART || !lsi->sim->parts[partIndex].type)
|
if(partIndex < 0 || partIndex >= NPART || !lsi->sim->parts[partIndex].type)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -323,7 +323,7 @@ static int partChangeType(lua_State *L)
|
|||||||
static int partCreate(lua_State *L)
|
static int partCreate(lua_State *L)
|
||||||
{
|
{
|
||||||
auto *lsi = GetLSI();
|
auto *lsi = GetLSI();
|
||||||
lsi->AssertMutableSimEvent();
|
lsi->AssertMonopartAccessEvent(-1);
|
||||||
int newID = lua_tointeger(L, 1);
|
int newID = lua_tointeger(L, 1);
|
||||||
if (newID >= NPART || newID < -3)
|
if (newID >= NPART || newID < -3)
|
||||||
{
|
{
|
||||||
@@ -386,6 +386,7 @@ static int partPosition(lua_State *L)
|
|||||||
{
|
{
|
||||||
if(argCount == 1)
|
if(argCount == 1)
|
||||||
{
|
{
|
||||||
|
lsi->AssertMonopartAccessEvent(-1);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
return 2;
|
return 2;
|
||||||
@@ -396,7 +397,7 @@ static int partPosition(lua_State *L)
|
|||||||
|
|
||||||
if (argCount == 3)
|
if (argCount == 3)
|
||||||
{
|
{
|
||||||
lsi->AssertMutableSimEvent();
|
lsi->AssertMonopartAccessEvent(-1);
|
||||||
float x = sim->parts[particleID].x;
|
float x = sim->parts[particleID].x;
|
||||||
float y = sim->parts[particleID].y;
|
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));
|
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)
|
if (argCount == 3)
|
||||||
{
|
{
|
||||||
lsi->AssertMutableSimEvent();
|
lsi->AssertMonopartAccessEvent(-1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
@@ -466,7 +467,6 @@ static int partProperty(lua_State *L)
|
|||||||
|
|
||||||
if (argCount == 3)
|
if (argCount == 3)
|
||||||
{
|
{
|
||||||
lsi->AssertMutableSimEvent();
|
|
||||||
LuaSetParticleProperty(L, particleID, *prop, propertyAddress, 3);
|
LuaSetParticleProperty(L, particleID, *prop, propertyAddress, 3);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -477,7 +477,7 @@ static int partProperty(lua_State *L)
|
|||||||
static int partKill(lua_State *L)
|
static int partKill(lua_State *L)
|
||||||
{
|
{
|
||||||
auto *lsi = GetLSI();
|
auto *lsi = GetLSI();
|
||||||
lsi->AssertMutableSimEvent();
|
lsi->AssertMonopartAccessEvent(-1);
|
||||||
if(lua_gettop(L)==2)
|
if(lua_gettop(L)==2)
|
||||||
lsi->sim->delete_part(lua_tointeger(L, 1), lua_tointeger(L, 2));
|
lsi->sim->delete_part(lua_tointeger(L, 1), lua_tointeger(L, 2));
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user