Prevent SaveRenderer from calling into Lua

Also clear SaveRenderer graphics cache along with the main Renderer's when needed, and revert to built-in element callbacks rather than nothing at all when assigning nil to a callback slot in Lua.
This commit is contained in:
Tamás Bálint Misius 2022-02-23 22:22:10 +01:00
parent bfe94618c6
commit df7bbd3b8e
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
7 changed files with 121 additions and 144 deletions

View File

@ -1295,43 +1295,7 @@ void Renderer::render_parts()
}
else if(!(colour_mode & COLOUR_BASC))
{
if (elements[t].Graphics)
{
#if !defined(RENDERER) && defined(LUACONSOLE)
if (lua_gr_func[t])
{
if (luacon_graphicsReplacement(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb, i))
{
graphicscache[t].isready = 1;
graphicscache[t].pixel_mode = pixel_mode;
graphicscache[t].cola = cola;
graphicscache[t].colr = colr;
graphicscache[t].colg = colg;
graphicscache[t].colb = colb;
graphicscache[t].firea = firea;
graphicscache[t].firer = firer;
graphicscache[t].fireg = fireg;
graphicscache[t].fireb = fireb;
}
}
else if ((*(elements[t].Graphics))(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb)) //That's a lot of args, a struct might be better
#else
if ((*(elements[t].Graphics))(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb)) //That's a lot of args, a struct might be better
#endif
{
graphicscache[t].isready = 1;
graphicscache[t].pixel_mode = pixel_mode;
graphicscache[t].cola = cola;
graphicscache[t].colr = colr;
graphicscache[t].colg = colg;
graphicscache[t].colb = colb;
graphicscache[t].firea = firea;
graphicscache[t].firer = firer;
graphicscache[t].fireg = fireg;
graphicscache[t].fireb = fireb;
}
}
else
if (!elements[t].Graphics || (*(elements[t].Graphics))(this, &(sim->parts[i]), nx, ny, &pixel_mode, &cola, &colr, &colg, &colb, &firea, &firer, &fireg, &fireb)) //That's a lot of args, a struct might be better
{
graphicscache[t].isready = 1;
graphicscache[t].pixel_mode = pixel_mode;

View File

@ -317,28 +317,6 @@ int luatpt_getelement(lua_State *l)
return 1;
}
int luacon_elementReplacement(UPDATE_FUNC_ARGS)
{
int retval = 0, callret;
if (lua_el_func[parts[i].type])
{
lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, lua_el_func[parts[i].type]);
lua_pushinteger(luacon_ci->l, i);
lua_pushinteger(luacon_ci->l, x);
lua_pushinteger(luacon_ci->l, y);
lua_pushinteger(luacon_ci->l, surround_space);
lua_pushinteger(luacon_ci->l, nt);
callret = lua_pcall(luacon_ci->l, 5, 1, 0);
if (callret)
luacon_ci->Log(CommandInterface::LogError, luacon_geterror());
if(lua_isboolean(luacon_ci->l, -1)){
retval = lua_toboolean(luacon_ci->l, -1);
}
lua_pop(luacon_ci->l, 1);
}
return retval;
}
int luatpt_element_func(lua_State *l)
{
if (lua_isfunction(l, 1))
@ -379,47 +357,6 @@ int luatpt_element_func(lua_State *l)
return 0;
}
int luacon_graphicsReplacement(GRAPHICS_FUNC_ARGS, int i)
{
int cache = 0, callret;
lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, lua_gr_func[cpart->type]);
lua_pushinteger(luacon_ci->l, i);
lua_pushinteger(luacon_ci->l, *colr);
lua_pushinteger(luacon_ci->l, *colg);
lua_pushinteger(luacon_ci->l, *colb);
callret = lua_pcall(luacon_ci->l, 4, 10, 0);
if (callret)
{
luacon_ci->Log(CommandInterface::LogError, luacon_geterror());
lua_pop(luacon_ci->l, 1);
}
else
{
bool valid = true;
for (int i = -10; i < 0; i++)
if (!lua_isnumber(luacon_ci->l, i) && !lua_isnil(luacon_ci->l, i))
{
valid = false;
break;
}
if (valid)
{
cache = luaL_optint(luacon_ci->l, -10, 0);
*pixel_mode = luaL_optint(luacon_ci->l, -9, *pixel_mode);
*cola = luaL_optint(luacon_ci->l, -8, *cola);
*colr = luaL_optint(luacon_ci->l, -7, *colr);
*colg = luaL_optint(luacon_ci->l, -6, *colg);
*colb = luaL_optint(luacon_ci->l, -5, *colb);
*firea = luaL_optint(luacon_ci->l, -4, *firea);
*firer = luaL_optint(luacon_ci->l, -3, *firer);
*fireg = luaL_optint(luacon_ci->l, -2, *fireg);
*fireb = luaL_optint(luacon_ci->l, -1, *fireb);
}
lua_pop(luacon_ci->l, 10);
}
return cache;
}
int luatpt_graphics_func(lua_State *l)
{
if(lua_isfunction(l, 1))

View File

@ -52,10 +52,8 @@ int luacon_transitionwrite(lua_State* l);
//tpt. api
int luatpt_getelement(lua_State *l);
int luacon_graphicsReplacement(GRAPHICS_FUNC_ARGS, int i);
int luatpt_graphics_func(lua_State *l);
int luacon_elementReplacement(UPDATE_FUNC_ARGS);
int luatpt_element_func(lua_State *l);
int luatpt_error(lua_State* l);

View File

@ -37,6 +37,7 @@
#include "simulation/GOLString.h"
#include "simulation/Simulation.h"
#include "simulation/ToolClasses.h"
#include "simulation/SaveRenderer.h"
#include "client/http/Request.h"
#include "gui/interface/Window.h"
@ -2866,6 +2867,7 @@ int LuaScriptInterface::elements_loadDefault(lua_State * l)
}
luacon_ci->custom_init_can_move();
std::fill(luacon_ren->graphicscache, luacon_ren->graphicscache+PT_NUM, gcache_item());
SaveRenderer::Ref().Flush(0, PT_NUM);
return 0;
}
@ -2945,7 +2947,96 @@ int LuaScriptInterface::elements_allocate(lua_State * l)
return 1;
}
void luaCreateWrapper(ELEMENT_CREATE_FUNC_ARGS)
static int luaUpdateWrapper(UPDATE_FUNC_ARGS)
{
if (lua_el_func[parts[i].type])
{
auto *builtinUpdate = GetElements()[parts[i].type].Update;
if (builtinUpdate && lua_el_mode[parts[i].type] == 1)
{
if (builtinUpdate(UPDATE_FUNC_SUBCALL_ARGS))
return 1;
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
}
int retval = 0, callret;
lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, lua_el_func[parts[i].type]);
lua_pushinteger(luacon_ci->l, i);
lua_pushinteger(luacon_ci->l, x);
lua_pushinteger(luacon_ci->l, y);
lua_pushinteger(luacon_ci->l, surround_space);
lua_pushinteger(luacon_ci->l, nt);
callret = lua_pcall(luacon_ci->l, 5, 1, 0);
if (callret)
luacon_ci->Log(CommandInterface::LogError, luacon_geterror());
if(lua_isboolean(luacon_ci->l, -1)){
retval = lua_toboolean(luacon_ci->l, -1);
}
lua_pop(luacon_ci->l, 1);
if (retval)
{
return 1;
}
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
if (builtinUpdate && lua_el_mode[parts[i].type] == 3)
{
if (builtinUpdate(UPDATE_FUNC_SUBCALL_ARGS))
return 1;
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
}
}
return 0;
}
static int luaGraphicsWrapper(GRAPHICS_FUNC_ARGS)
{
if (lua_gr_func[cpart->type])
{
int cache = 0, callret;
int i = cpart - ren->sim->parts; // pointer arithmetic be like
lua_rawgeti(luacon_ci->l, LUA_REGISTRYINDEX, lua_gr_func[cpart->type]);
lua_pushinteger(luacon_ci->l, i);
lua_pushinteger(luacon_ci->l, *colr);
lua_pushinteger(luacon_ci->l, *colg);
lua_pushinteger(luacon_ci->l, *colb);
callret = lua_pcall(luacon_ci->l, 4, 10, 0);
if (callret)
{
luacon_ci->Log(CommandInterface::LogError, luacon_geterror());
lua_pop(luacon_ci->l, 1);
}
else
{
bool valid = true;
for (int i = -10; i < 0; i++)
if (!lua_isnumber(luacon_ci->l, i) && !lua_isnil(luacon_ci->l, i))
{
valid = false;
break;
}
if (valid)
{
cache = luaL_optint(luacon_ci->l, -10, 0);
*pixel_mode = luaL_optint(luacon_ci->l, -9, *pixel_mode);
*cola = luaL_optint(luacon_ci->l, -8, *cola);
*colr = luaL_optint(luacon_ci->l, -7, *colr);
*colg = luaL_optint(luacon_ci->l, -6, *colg);
*colb = luaL_optint(luacon_ci->l, -5, *colb);
*firea = luaL_optint(luacon_ci->l, -4, *firea);
*firer = luaL_optint(luacon_ci->l, -3, *firer);
*fireg = luaL_optint(luacon_ci->l, -2, *fireg);
*fireb = luaL_optint(luacon_ci->l, -1, *fireb);
}
lua_pop(luacon_ci->l, 10);
}
return cache;
}
return 0;
}
static void luaCreateWrapper(ELEMENT_CREATE_FUNC_ARGS)
{
if (luaCreateHandlers[sim->parts[i].type])
{
@ -2963,7 +3054,7 @@ void luaCreateWrapper(ELEMENT_CREATE_FUNC_ARGS)
}
}
bool luaCreateAllowedWrapper(ELEMENT_CREATE_ALLOWED_FUNC_ARGS)
static bool luaCreateAllowedWrapper(ELEMENT_CREATE_ALLOWED_FUNC_ARGS)
{
bool ret = false;
if (luaCreateAllowedHandlers[t])
@ -2988,7 +3079,7 @@ bool luaCreateAllowedWrapper(ELEMENT_CREATE_ALLOWED_FUNC_ARGS)
return ret;
}
void luaChangeTypeWrapper(ELEMENT_CHANGETYPE_FUNC_ARGS)
static void luaChangeTypeWrapper(ELEMENT_CHANGETYPE_FUNC_ARGS)
{
if (luaChangeTypeHandlers[sim->parts[i].type])
{
@ -3058,12 +3149,13 @@ int LuaScriptInterface::elements_element(lua_State * l)
{
lua_el_func[id].Assign(l, -1);
lua_el_mode[id] = 1;
luacon_sim->elements[id].Update = luaUpdateWrapper;
}
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
{
lua_el_func[id].Clear();
lua_el_mode[id] = 0;
luacon_sim->elements[id].Update = nullptr;
luacon_sim->elements[id].Update = GetElements()[id].Update;
}
lua_pop(l, 1);
@ -3071,11 +3163,12 @@ int LuaScriptInterface::elements_element(lua_State * l)
if (lua_type(l, -1) == LUA_TFUNCTION)
{
lua_gr_func[id].Assign(l, -1);
luacon_sim->elements[id].Graphics = luaGraphicsWrapper;
}
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
{
lua_gr_func[id].Clear();
luacon_sim->elements[id].Graphics = nullptr;
luacon_sim->elements[id].Graphics = GetElements()[id].Graphics;
}
lua_pop(l, 1);
@ -3088,7 +3181,7 @@ int LuaScriptInterface::elements_element(lua_State * l)
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
{
luaCreateHandlers[id].Clear();
luacon_sim->elements[id].Create = nullptr;
luacon_sim->elements[id].Create = GetElements()[id].Create;
}
lua_pop(l, 1);
@ -3101,7 +3194,7 @@ int LuaScriptInterface::elements_element(lua_State * l)
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
{
luaCreateAllowedHandlers[id].Clear();
luacon_sim->elements[id].CreateAllowed = nullptr;
luacon_sim->elements[id].CreateAllowed = GetElements()[id].CreateAllowed;
}
lua_pop(l, 1);
@ -3114,7 +3207,7 @@ int LuaScriptInterface::elements_element(lua_State * l)
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
{
luaChangeTypeHandlers[id].Clear();
luacon_sim->elements[id].ChangeType = nullptr;
luacon_sim->elements[id].ChangeType = GetElements()[id].ChangeType;
}
lua_pop(l, 1);
@ -3127,7 +3220,7 @@ int LuaScriptInterface::elements_element(lua_State * l)
else if (lua_type(l, -1) == LUA_TBOOLEAN && !lua_toboolean(l, -1))
{
luaCtypeDrawHandlers[id].Clear();
luacon_sim->elements[id].CtypeDraw = nullptr;
luacon_sim->elements[id].CtypeDraw = GetElements()[id].CtypeDraw;
}
lua_pop(l, 1);
@ -3150,6 +3243,7 @@ int LuaScriptInterface::elements_element(lua_State * l)
luacon_model->BuildMenus();
luacon_ci->custom_init_can_move();
luacon_ren->graphicscache[id].isready = 0;
SaveRenderer::Ref().Flush(id, id + 1);
return 0;
}
@ -3217,6 +3311,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
luacon_model->BuildMenus();
luacon_ci->custom_init_can_move();
luacon_ren->graphicscache[id].isready = 0;
SaveRenderer::Ref().Flush(id, id + 1);
}
else if (propertyName == "Update")
{
@ -3237,12 +3332,13 @@ int LuaScriptInterface::elements_property(lua_State * l)
break;
}
lua_el_func[id].Assign(l, 3);
luacon_sim->elements[id].Update = luaUpdateWrapper;
}
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
{
lua_el_func[id].Clear();
lua_el_mode[id] = 0;
luacon_sim->elements[id].Update = NULL;
luacon_sim->elements[id].Update = GetElements()[id].Update;
}
}
else if (propertyName == "Graphics")
@ -3250,13 +3346,15 @@ int LuaScriptInterface::elements_property(lua_State * l)
if (lua_type(l, 3) == LUA_TFUNCTION)
{
lua_gr_func[id].Assign(l, 3);
luacon_sim->elements[id].Graphics = luaGraphicsWrapper;
}
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
{
lua_gr_func[id].Clear();
luacon_sim->elements[id].Graphics = NULL;
luacon_sim->elements[id].Graphics = GetElements()[id].Graphics;
}
luacon_ren->graphicscache[id].isready = 0;
SaveRenderer::Ref().Flush(id, id + 1);
}
else if (propertyName == "Create")
{
@ -3268,7 +3366,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
{
luaCreateHandlers[id].Clear();
luacon_sim->elements[id].Create = nullptr;
luacon_sim->elements[id].Create = GetElements()[id].Create;
}
}
else if (propertyName == "CreateAllowed")
@ -3281,7 +3379,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
{
luaCreateAllowedHandlers[id].Clear();
luacon_sim->elements[id].CreateAllowed = nullptr;
luacon_sim->elements[id].CreateAllowed = GetElements()[id].CreateAllowed;
}
}
else if (propertyName == "ChangeType")
@ -3294,7 +3392,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
{
luaChangeTypeHandlers[id].Clear();
luacon_sim->elements[id].ChangeType = nullptr;
luacon_sim->elements[id].ChangeType = GetElements()[id].ChangeType;
}
}
else if (propertyName == "CtypeDraw")
@ -3307,7 +3405,7 @@ int LuaScriptInterface::elements_property(lua_State * l)
else if (lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3))
{
luaCtypeDrawHandlers[id].Clear();
luacon_sim->elements[id].CtypeDraw = nullptr;
luacon_sim->elements[id].CtypeDraw = GetElements()[id].CtypeDraw;
}
}
else if (propertyName == "DefaultProperties")

View File

@ -33,6 +33,12 @@ SaveRenderer::SaveRenderer(){
#endif
}
void SaveRenderer::Flush(int begin, int end)
{
std::lock_guard<std::mutex> gx(renderMutex);
std::fill(ren->graphicscache + begin, ren->graphicscache + end, gcache_item());
}
VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire, Renderer *renderModeSource)
{
std::lock_guard<std::mutex> gx(renderMutex);

View File

@ -22,6 +22,7 @@ public:
SaveRenderer();
VideoBuffer * Render(GameSave * save, bool decorations = true, bool fire = true, Renderer *renderModeSource = nullptr);
VideoBuffer * Render(unsigned char * saveData, int saveDataSize, bool decorations = true, bool fire = true);
void Flush(int begin, int end);
virtual ~SaveRenderer();
private:

View File

@ -4092,40 +4092,13 @@ void Simulation::UpdateParticles(int start, int end)
}
//call the particle update function, if there is one
#if !defined(RENDERER) && defined(LUACONSOLE)
if (lua_el_mode[parts[i].type] == 3)
{
if (luacon_elementReplacement(this, i, x, y, surround_space, nt, parts, pmap) || t != parts[i].type)
continue;
// Need to update variables, in case they've been changed by Lua
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
}
if (elements[t].Update && lua_el_mode[t] != 2)
#else
if (elements[t].Update)
#endif
{
if ((*(elements[t].Update))(this, i, x, y, surround_space, nt, parts, pmap))
continue;
else if (t==PT_WARP)
{
// Warp does some movement in its update func, update variables to avoid incorrect data in pmap
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
}
}
#if !defined(RENDERER) && defined(LUACONSOLE)
if (lua_el_mode[parts[i].type] && lua_el_mode[parts[i].type] != 3)
{
if (luacon_elementReplacement(this, i, x, y, surround_space, nt, parts, pmap) || t != parts[i].type)
continue;
// Need to update variables, in case they've been changed by Lua
x = (int)(parts[i].x+0.5f);
y = (int)(parts[i].y+0.5f);
}
#endif
if(legacy_enable)//if heat sim is off
Element::legacyUpdate(this, i,x,y,surround_space,nt, parts, pmap);