From 3519dfa83a4b5d413ba1cda67404851d9473432a Mon Sep 17 00:00:00 2001 From: jacob1 Date: Sun, 1 Jan 2023 20:41:45 -0500 Subject: [PATCH] Fix pmap not being updated when setting x / y from Lua --- src/lua/LegacyLuaAPI.cpp | 119 ++++++++++++++++++--------------- src/lua/LuaScriptInterface.cpp | 51 +++++++++----- src/lua/LuaScriptInterface.h | 1 + src/simulation/Simulation.cpp | 49 ++++++++------ src/simulation/Simulation.h | 1 + 5 files changed, 132 insertions(+), 89 deletions(-) diff --git a/src/lua/LegacyLuaAPI.cpp b/src/lua/LegacyLuaAPI.cpp index fd7e271de..616f8988b 100644 --- a/src/lua/LegacyLuaAPI.cpp +++ b/src/lua/LegacyLuaAPI.cpp @@ -77,68 +77,70 @@ void initLegacyProps() #ifndef FFI int luacon_partread(lua_State* l) { - int tempinteger, i = cIndex; - float tempfloat; - ByteString key = tpt_lua_optByteString(l, 2, ""); - CommandInterface::FormatType format; - int offset = luacon_ci->GetPropertyOffset(key, format); - + int i = cIndex; if (i < 0 || i >= NPART) return luaL_error(l, "Out of range"); - if (offset == -1) - { - if (byteStringEqualsLiteral(key, "id")) - { - lua_pushnumber(l, i); - return 1; - } - return luaL_error(l, "Invalid property"); - } + if (!luacon_sim->parts[i].type) + return luaL_error(l, "Dead particle"); - switch(format) + auto &properties = Particle::GetProperties(); + auto prop = properties.end(); + + ByteString fieldName = tpt_lua_toByteString(l, 2); + if (fieldName == "id") { - case CommandInterface::FormatInt: - case CommandInterface::FormatElement: - tempinteger = *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)); - lua_pushnumber(l, tempinteger); - break; - case CommandInterface::FormatFloat: - tempfloat = *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)); - lua_pushnumber(l, tempfloat); - break; - default: - break; + lua_pushnumber(l, i); + return 1; } + for (auto &alias : Particle::GetPropertyAliases()) + { + if (fieldName == alias.from) + { + fieldName = alias.to; + } + } + prop = std::find_if(properties.begin(), properties.end(), [&fieldName](StructProperty const &p) { + return p.Name == fieldName; + }); + if (prop == properties.end()) + return luaL_error(l, "Invalid property"); + + //Calculate memory address of property + intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->parts[i]) + prop->Offset); + + LuaScriptInterface::LuaGetProperty(l, *prop, propertyAddress); return 1; } int luacon_partwrite(lua_State* l) { int i = cIndex; - ByteString key = tpt_lua_optByteString(l, 2, ""); - CommandInterface::FormatType format; - int offset = luacon_ci->GetPropertyOffset(key, format); - if (i < 0 || i >= NPART) return luaL_error(l, "Out of range"); if (!luacon_sim->parts[i].type) return luaL_error(l, "Dead particle"); - if (offset == -1) - return luaL_error(l, "Invalid property"); - switch(format) + auto &properties = Particle::GetProperties(); + auto prop = properties.end(); + + ByteString fieldName = tpt_lua_toByteString(l, 2); + for (auto &alias : Particle::GetPropertyAliases()) { - case CommandInterface::FormatInt: - *((int*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = luaL_optinteger(l, 3, 0); - break; - case CommandInterface::FormatFloat: - *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = luaL_optnumber(l, 3, 0); - break; - case CommandInterface::FormatElement: - luacon_sim->part_change_type(i, int(luacon_sim->parts[i].x + 0.5f), int(luacon_sim->parts[i].y + 0.5f), luaL_optinteger(l, 3, 0)); - default: - break; + if (fieldName == alias.from) + { + fieldName = alias.to; + } } + prop = std::find_if(properties.begin(), properties.end(), [&fieldName](StructProperty const &p) { + return p.Name == fieldName; + }); + if (prop == properties.end()) + return luaL_error(l, "Invalid property"); + + //Calculate memory address of property + intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->parts[i]) + prop->Offset); + + LuaScriptInterface::LuaSetParticleProperty(l, i, *prop, propertyAddress, 3); return 0; } @@ -254,15 +256,8 @@ int luacon_elementwrite(lua_State* l) return luaL_error(l, "Invalid index"); } - if (prop.Name == "type") // i.e. it's .type - { - luacon_sim->part_change_type(i, int(luacon_sim->parts[i].x+0.5f), int(luacon_sim->parts[i].y+0.5f), luaL_checkinteger(l, 3)); - } - else - { - intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset); - LuaScriptInterface::LuaSetProperty(l, prop, propertyAddress, 3); - } + intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->elements[i]) + prop.Offset); + LuaScriptInterface::LuaSetProperty(l, prop, propertyAddress, 3); luacon_model->BuildMenus(); luacon_sim->init_can_move(); @@ -575,6 +570,8 @@ int luatpt_set_property(lua_State* l) int offset = luacon_ci->GetPropertyOffset(prop, format); if (offset == -1) return luaL_error(l, "Invalid property '%s'", prop.c_str()); + bool isX = byteStringEqualsLiteral(prop, "x"); + bool isY = byteStringEqualsLiteral(prop, "y"); if (acount > 2) { @@ -639,6 +636,14 @@ int luatpt_set_property(lua_State* l) { if (format == CommandInterface::FormatElement) luacon_sim->part_change_type(i, nx, ny, t); + else if (isX || isY) + { + float x = luacon_sim->parts[i].x; + float y = luacon_sim->parts[i].y; + float nx = isX ? f : x; + float ny = isY ? f : y; + luacon_sim->move(i, (int)(x + 0.5f), (int)(y + 0.5f), nx, ny); + } else if(format == CommandInterface::FormatFloat) *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = f; else @@ -672,6 +677,14 @@ int luatpt_set_property(lua_State* l) if (format == CommandInterface::FormatElement) luacon_sim->part_change_type(i, int(luacon_sim->parts[i].x + 0.5f), int(luacon_sim->parts[i].y + 0.5f), t); + else if (isX || isY) + { + float x = luacon_sim->parts[i].x; + float y = luacon_sim->parts[i].y; + float nx = isX ? f : x; + float ny = isY ? f : y; + luacon_sim->move(i, (int)(x + 0.5f), (int)(y + 0.5f), nx, ny); + } else if (format == CommandInterface::FormatFloat) *((float*)(((unsigned char*)&luacon_sim->parts[i])+offset)) = f; else diff --git a/src/lua/LuaScriptInterface.cpp b/src/lua/LuaScriptInterface.cpp index 8d500d0b0..6a258d3d6 100644 --- a/src/lua/LuaScriptInterface.cpp +++ b/src/lua/LuaScriptInterface.cpp @@ -1161,7 +1161,7 @@ int LuaScriptInterface::simulation_partPosition(lua_State * l) { int particleID = lua_tointeger(l, 1); int argCount = lua_gettop(l); - if(particleID < 0 || particleID >= NPART || !luacon_sim->parts[particleID].type) + if (particleID < 0 || particleID >= NPART || !luacon_sim->parts[particleID].type) { if(argCount == 1) { @@ -1173,10 +1173,12 @@ int LuaScriptInterface::simulation_partPosition(lua_State * l) } } - if(argCount == 3) + if (argCount == 3) { - luacon_sim->parts[particleID].x = lua_tonumber(l, 2); - luacon_sim->parts[particleID].y = lua_tonumber(l, 3); + float x = luacon_sim->parts[particleID].x; + float y = luacon_sim->parts[particleID].y; + luacon_sim->move(particleID, (int)(x + 0.5f), (int)(y + 0.5f), lua_tonumber(l, 2), lua_tonumber(l, 3)); + return 0; } else @@ -1193,13 +1195,15 @@ int LuaScriptInterface::simulation_partProperty(lua_State * l) int particleID = luaL_checkinteger(l, 1); StructProperty property; - if(particleID < 0 || particleID >= NPART || !luacon_sim->parts[particleID].type) + if (particleID < 0 || particleID >= NPART || !luacon_sim->parts[particleID].type) { - if(argCount == 3) + if (argCount == 3) { lua_pushnil(l); return 1; - } else { + } + else + { return 0; } } @@ -1239,16 +1243,9 @@ int LuaScriptInterface::simulation_partProperty(lua_State * l) //Calculate memory address of property intptr_t propertyAddress = (intptr_t)(((unsigned char*)&luacon_sim->parts[particleID]) + prop->Offset); - if(argCount == 3) + if (argCount == 3) { - if (prop == properties.begin() + 0) // i.e. it's .type - { - luacon_sim->part_change_type(particleID, int(luacon_sim->parts[particleID].x+0.5f), int(luacon_sim->parts[particleID].y+0.5f), luaL_checkinteger(l, 3)); - } - else - { - LuaSetProperty(l, *prop, propertyAddress, 3); - } + LuaSetParticleProperty(l, particleID, *prop, propertyAddress, 3); return 0; } else @@ -3002,6 +2999,28 @@ void LuaScriptInterface::LuaSetProperty(lua_State* l, StructProperty property, i } } + +void LuaScriptInterface::LuaSetParticleProperty(lua_State* l, int particleID, StructProperty property, intptr_t propertyAddress, int stackPos) +{ + if (property.Name == "type") + { + luacon_sim->part_change_type(particleID, int(luacon_sim->parts[particleID].x+0.5f), int(luacon_sim->parts[particleID].y+0.5f), luaL_checkinteger(l, 3)); + } + else if (property.Name == "x" || property.Name == "y") + { + float val = luaL_checknumber(l, 3); + float x = luacon_sim->parts[particleID].x; + float y = luacon_sim->parts[particleID].y; + float nx = property.Name == "x" ? val : x; + float ny = property.Name == "y" ? val : y; + luacon_sim->move(particleID, (int)(x + 0.5f), (int)(y + 0.5f), nx, ny); + } + else + { + LuaSetProperty(l, property, propertyAddress, 3); + } +} + int LuaScriptInterface::elements_loadDefault(lua_State * l) { int args = lua_gettop(l); diff --git a/src/lua/LuaScriptInterface.h b/src/lua/LuaScriptInterface.h index d009c40ce..a0880900c 100644 --- a/src/lua/LuaScriptInterface.h +++ b/src/lua/LuaScriptInterface.h @@ -215,6 +215,7 @@ public: static void LuaGetProperty(lua_State* l, StructProperty property, intptr_t propertyAddress); static void LuaSetProperty(lua_State* l, StructProperty property, intptr_t propertyAddress, int stackPos); + static void LuaSetParticleProperty(lua_State* l, int particleID, StructProperty property, intptr_t propertyAddress, int stackPos); ui::Window * Window; lua_State *l; diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 6c38776b6..ea9a84262 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -2904,30 +2904,39 @@ int Simulation::do_move(int i, int x, int y, float nxf, float nyf) result = try_move(i, x, y, nx, ny); if (result) { - int t = parts[i].type; - parts[i].x = nxf; - parts[i].y = nyf; - if (ny!=y || nx!=x) - { - if (ID(pmap[y][x]) == i) - pmap[y][x] = 0; - if (ID(photons[y][x]) == i) - photons[y][x] = 0; - // kill_part if particle is out of bounds - if (nx < CELL || nx >= XRES - CELL || ny < CELL || ny >= YRES - CELL) - { - kill_part(i); - return -1; - } - if (elements[t].Properties & TYPE_ENERGY) - photons[ny][nx] = PMAP(i, t); - else if (t) - pmap[ny][nx] = PMAP(i, t); - } + if (!move(i, x, y, nxf, nyf)) + return -1; } return result; } +bool Simulation::move(int i, int x, int y, float nxf, float nyf) +{ + int nx = (int)(nxf+0.5f), ny = (int)(nyf+0.5f); + int t = parts[i].type; + parts[i].x = nxf; + parts[i].y = nyf; + if (ny != y || nx != x) + { + if (ID(pmap[y][x]) == i) + pmap[y][x] = 0; + if (ID(photons[y][x]) == i) + photons[y][x] = 0; + // kill_part if particle is out of bounds + if (nx < CELL || nx >= XRES - CELL || ny < CELL || ny >= YRES - CELL) + { + kill_part(i); + return false; + } + if (elements[t].Properties & TYPE_ENERGY) + photons[ny][nx] = PMAP(i, t); + else if (t) + pmap[ny][nx] = PMAP(i, t); + } + + return true; +} + void Simulation::photoelectric_effect(int nx, int ny)//create sparks from PHOT when hitting PSCN and NSCN { unsigned r = pmap[ny][nx]; diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index 7c9cad20f..cdac3a788 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -134,6 +134,7 @@ public: void photoelectric_effect(int nx, int ny); unsigned direction_to_map(float dx, float dy, int t); int do_move(int i, int x, int y, float nxf, float nyf); + bool move(int i, int x, int y, float nxf, float nyf); int try_move(int i, int x, int y, int nx, int ny); int eval_move(int pt, int nx, int ny, unsigned *rr); void init_can_move();