/apps/twnlua: ctx.udata preservation in reload, no export in .so, ignore /data/scripts/twnapi.lua
This commit is contained in:
		
							
								
								
									
										1
									
								
								apps/twnlua/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								apps/twnlua/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1 +1,2 @@
 | 
			
		||||
luabind.c
 | 
			
		||||
data/scripts/twnapi.lua
 | 
			
		||||
 
 | 
			
		||||
@@ -151,15 +151,12 @@ for typename, typedesc in used_converters.items():
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
print('\n'.join(storages))
 | 
			
		||||
print("extern void bindgen_init(void);\n")
 | 
			
		||||
print("void bindgen_init(void) {\n" + '\n'.join(initializers) + "\n}\n")
 | 
			
		||||
print('\n'.join(converters))
 | 
			
		||||
print('\n'.join(bindings))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
loader = "extern void bindgen_load_%s(lua_State *L);\n" % api["name"]
 | 
			
		||||
loader += "void bindgen_load_%s(lua_State *L) {\n" % api["name"]
 | 
			
		||||
loader += "    bindgen_init();\n"
 | 
			
		||||
for procedure, procedure_desc in api["procedures"].items():
 | 
			
		||||
    loader += "    lua_pushcfunction(L, binding_%s);\n" % procedure
 | 
			
		||||
    loader += "    lua_setglobal(L, \"%s\");\n" % procedure
 | 
			
		||||
 
 | 
			
		||||
@@ -4,16 +4,39 @@ offset = { x = 0, y = 0 }
 | 
			
		||||
angle = 0
 | 
			
		||||
 | 
			
		||||
function game_tick()
 | 
			
		||||
    if ctx.udata == nil then
 | 
			
		||||
        ctx.udata = {
 | 
			
		||||
            frame_count = 0,
 | 
			
		||||
            nest = {
 | 
			
		||||
                frame_count = 0,
 | 
			
		||||
            },
 | 
			
		||||
            arr = { [0] = 0 },
 | 
			
		||||
        }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    draw_text {
 | 
			
		||||
        string = tostring(ctx.udata.frame_count),
 | 
			
		||||
        position = { x = 0, y = 0 },
 | 
			
		||||
        font = "/fonts/kenney-pixel.ttf",
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    draw_text {
 | 
			
		||||
        string = tostring(ctx.udata.nest.frame_count),
 | 
			
		||||
        position = { x = 0, y = 14 },
 | 
			
		||||
        font = "/fonts/kenney-pixel.ttf",
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    draw_text {
 | 
			
		||||
        string = tostring(ctx.udata.arr[0]),
 | 
			
		||||
        position = { x = 0, y = 28 },
 | 
			
		||||
        font = "/fonts/kenney-pixel.ttf",
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    input_action {
 | 
			
		||||
        name = "press",
 | 
			
		||||
        control = "A"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    draw_rectangle {
 | 
			
		||||
        rect = { x = 0, y = 0, w = 640, h = 360 },
 | 
			
		||||
        color = { r = 127, g = 0, b = 127, a = 255 },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    draw_sprite {
 | 
			
		||||
        texture = "/assets/title.png",
 | 
			
		||||
        rect = {
 | 
			
		||||
@@ -32,6 +55,10 @@ function game_tick()
 | 
			
		||||
        }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    ctx.udata.frame_count = ctx.udata.frame_count + 1
 | 
			
		||||
    ctx.udata.nest.frame_count = ctx.udata.nest.frame_count + 1
 | 
			
		||||
    ctx.udata.arr[0] = ctx.udata.arr[0] + 1
 | 
			
		||||
 | 
			
		||||
    offset.x = ORIGIN.x + (math.cos(angle) * RADIUS)
 | 
			
		||||
    offset.y = ORIGIN.y + (math.sin(angle) * RADIUS)
 | 
			
		||||
    angle = angle + 0.1
 | 
			
		||||
 
 | 
			
		||||
@@ -6,5 +6,6 @@ dev_id = "somebody"
 | 
			
		||||
 | 
			
		||||
[game]
 | 
			
		||||
resolution = [ 640, 360 ]
 | 
			
		||||
background_color = [ 127, 0, 127, 255 ]
 | 
			
		||||
 | 
			
		||||
[engine]
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -383,7 +383,8 @@ extern "C" {
 | 
			
		||||
 | 
			
		||||
#else				/* }{ */
 | 
			
		||||
 | 
			
		||||
#define LUA_API		extern
 | 
			
		||||
/* TWN: Don't export anything, there's no need. */
 | 
			
		||||
#define LUA_API		LUAI_FUNC
 | 
			
		||||
 | 
			
		||||
#endif				/* } */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user