/apps/twnlua: ctx.udata preservation in reload, no export in .so, ignore /data/scripts/twnapi.lua

This commit is contained in:
veclavtalica
2025-02-15 22:19:14 +03:00
parent 29d163216c
commit 793bd850f6
6 changed files with 99 additions and 12 deletions

View File

@ -1,5 +1,6 @@
#include "twn_game_api.h"
/* TODO: actually move it back it its own file, it doesn't give any compilation benefits */
#define LUA_IMPL
#include "minilua.h"
@ -8,6 +9,8 @@
#include <SDL2/SDL.h>
#define UDATA_NESTING_LIMIT 128
/* generated by bindgen.py */
void bindgen_load_twn(lua_State *L);
@ -100,6 +103,47 @@ static void *custom_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
}
static void exchange_lua_states(lua_State *from, lua_State *to, int level, int index) {
if (level >= UDATA_NESTING_LIMIT) {
log_critical("ctx.udata nesting limit is reached (%u)", UDATA_NESTING_LIMIT);
return;
}
/* TODO: use arrays for optimized paths */
/* TODO: preallocate table records */
switch (lua_type(from, index)) {
case LUA_TTABLE:
lua_newtable(to);
lua_pushnil(from); /* first key */
while (lua_next(from, index - 1) != 0) {
/* 'key' at index -2 and 'value' at index -1 */
exchange_lua_states(from, to, level + 1, -2);
exchange_lua_states(from, to, level + 1, -1);
lua_settable(to, index - 2);
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(from, 1);
}
break;
case LUA_TNUMBER:
lua_pushnumber(to, lua_tonumber(from, index));
break;
case LUA_TBOOLEAN:
lua_pushboolean(to, lua_toboolean(from, index));
break;
case LUA_TSTRING:
lua_pushstring(to, lua_tostring(from, index));
break;
case LUA_TNIL:
lua_pushnil(to);
break;
default:
/* TODO: provide a path and type of it for better diagnostic */
log_warn("Unserializable udata found and is ignored");
break;
}
}
void game_tick(void) {
if (ctx.initialization_needed) {
if (!ctx.udata)
@ -108,13 +152,29 @@ void game_tick(void) {
State *state = ctx.udata;
/* let's init lua */
/* state existed already */
lua_State *new_state = luaL_newstate();
lua_setallocf(new_state, custom_alloc, NULL);
/* state existed already, copy its udata over */
if (state->L != NULL) {
lua_getglobal(state->L, "ctx");
lua_getfield(state->L, -1, "udata");
SDL_assert(!lua_isnoneornil(state->L, -1));
SDL_assert(!lua_isnoneornil(state->L, -2));
// SDL_TriggerBreakpoint();
if (!lua_isnoneornil(state->L, -1)) {
log_info("Exchanging lua states...");
lua_newtable(new_state);
exchange_lua_states(state->L, new_state, 0, -1);
lua_setfield(new_state, -2, "udata");
lua_setglobal(new_state, "ctx");
}
/* bye :) */
lua_close(state->L);
}
state->L = luaL_newstate();
lua_setallocf(state->L, custom_alloc, NULL);
state->L = new_state;
/* fakey version of luaL_openlibs() that excludes file i/o and os stuff */
{