From d92ea3ff21b8455e61e3a90cba7e66ae3080dcb2 Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 31 Jan 2022 19:09:03 -0800 Subject: [PATCH] Lua networking improvements More types can be sent over the network SyncTables are synchronized on client join --- build-windows-visual-studio/sm64ex.vcxproj | 1 + .../sm64ex.vcxproj.filters | 3 + src/pc/lua/smlua.c | 4 + src/pc/lua/smlua.h | 1 + src/pc/lua/smlua_sync_table.c | 169 +++++++++++++++--- src/pc/lua/smlua_sync_table.h | 1 + src/pc/network/network_player.c | 20 +++ src/pc/network/network_player.h | 4 + src/pc/network/packets/packet.c | 1 + src/pc/network/packets/packet.h | 10 +- src/pc/network/packets/packet_debug_sync.c | 3 + src/pc/network/packets/packet_join.c | 1 + .../network/packets/packet_lua_sync_table.c | 69 ++++++- 13 files changed, 256 insertions(+), 31 deletions(-) diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index 7c121a20..399f68ec 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj +++ b/build-windows-visual-studio/sm64ex.vcxproj @@ -553,6 +553,7 @@ + diff --git a/build-windows-visual-studio/sm64ex.vcxproj.filters b/build-windows-visual-studio/sm64ex.vcxproj.filters index c16d0da1..1947e076 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj.filters +++ b/build-windows-visual-studio/sm64ex.vcxproj.filters @@ -4869,6 +4869,9 @@ Source Files\src\pc\lua + + Source Files\src\pc\network\packets + diff --git a/src/pc/lua/smlua.c b/src/pc/lua/smlua.c index 69bc73ed..976021bc 100644 --- a/src/pc/lua/smlua.c +++ b/src/pc/lua/smlua.c @@ -2,6 +2,7 @@ #include "pc/mod_list.h" lua_State* gLuaState = NULL; +u8 gLuaInitializingScript = 0; static void smlua_exec_file(char* path) { lua_State* L = gLuaState; @@ -23,6 +24,7 @@ static void smlua_exec_str(char* str) { static void smlua_load_script(char* path, u16 remoteIndex) { lua_State* L = gLuaState; + gLuaInitializingScript = 1; if (luaL_loadfile(L, path) != LUA_OK) { LOG_LUA("Failed to load lua script '%s'.", path); puts(smlua_to_string(L, lua_gettop(L))); @@ -50,8 +52,10 @@ static void smlua_load_script(char* path, u16 remoteIndex) { LOG_LUA("Failed to execute lua script '%s'.", path); puts(smlua_to_string(L, lua_gettop(L))); smlua_dump_stack(); + gLuaInitializingScript = 0; return; } + gLuaInitializingScript = 0; } void smlua_init(void) { diff --git a/src/pc/lua/smlua.h b/src/pc/lua/smlua.h index 13a43ad0..cad6b1c6 100644 --- a/src/pc/lua/smlua.h +++ b/src/pc/lua/smlua.h @@ -30,6 +30,7 @@ #endif extern lua_State* gLuaState; +extern u8 gLuaInitializingScript; void smlua_init(void); void smlua_update(void); diff --git a/src/pc/lua/smlua_sync_table.c b/src/pc/lua/smlua_sync_table.c index 417b0836..0fb36182 100644 --- a/src/pc/lua/smlua_sync_table.c +++ b/src/pc/lua/smlua_sync_table.c @@ -1,53 +1,72 @@ #include "smlua.h" #include "pc/mod_list.h" #include "pc/network/network.h" +#include "pc/network/network_player.h" -static int smlua__set_sync_table_field(UNUSED lua_State* L) { +static u8 smlua_sync_table_send_field(u8 toLocalIndex, int stackIndex, bool alterSeq, bool push) { LUA_STACK_CHECK_BEGIN(); - if (!smlua_functions_valid_param_count(L, 3)) { return 0; } + lua_State* L = gLuaState; // get remoteIndex - u16 remoteIndex = smlua_get_integer_field(1, "_remoteIndex"); - if (!gSmLuaConvertSuccess) { return 0; } + u16 remoteIndex = smlua_get_integer_field(stackIndex + 1, "_remoteIndex"); + if (!gSmLuaConvertSuccess) { + LOG_LUA("smlua_sync_table_send_field on invalid remoteIndex: %u", remoteIndex); + if (push) { lua_pushinteger(L, 0); } + return 0; + } // get lst - enum LuaSyncTableType lst = smlua_get_integer_field(1, "_type"); + enum LuaSyncTableType lst = smlua_get_integer_field(stackIndex + 1, "_type"); if (!gSmLuaConvertSuccess) { return 0; } if (lst >= LST_MAX) { - LOG_LUA("_set_sync_table_field on invalid LST: %u", lst); - lua_pushinteger(L, 0); + LOG_LUA("smlua_sync_table_send_field on invalid LST: %u", lst); + if (push) { lua_pushinteger(L, 0); } return 0; } // get key - const char* key = smlua_to_string(L, 2); + const char* key = smlua_to_string(L, stackIndex + 2); if (!gSmLuaConvertSuccess) { return 0; } if (key == NULL || strlen(key) == 0 || strlen(key) > 64) { - LOG_LUA("_set_sync_table_field on invalid key: '%s'", (key == NULL) ? "" : key); - lua_pushinteger(L, 0); + LOG_LUA("smlua_sync_table_send_field on invalid key: '%s'", (key == NULL) ? "" : key); + if (push) { lua_pushinteger(L, 0); } return 0; } // get value union LSTNetworkUnion lUnion = { 0 }; enum LSTNetworkType lUnionType = LST_NETWORK_TYPE_MAX; - int valueType = lua_type(L, 3); + int valueType = lua_type(L, stackIndex + 3); if (valueType == LUA_TNUMBER) { - lUnion.integer = lua_tointeger(L, 3); + lUnion.integer = lua_tointeger(L, stackIndex + 3); lUnionType = LST_NETWORK_TYPE_INTEGER; if (lUnion.integer == 0) { - lUnion.number = lua_tonumber(L, 3); + lUnion.number = lua_tonumber(L, stackIndex + 3); lUnionType = LST_NETWORK_TYPE_NUMBER; } + + } else if (valueType == LUA_TBOOLEAN) { + lUnion.boolean = lua_toboolean(L, stackIndex + 3); + lUnionType = LST_NETWORK_TYPE_BOOLEAN; + } else if (valueType == LUA_TSTRING) { + lUnion.string = lua_tostring(L, stackIndex + 3); + lUnionType = LST_NETWORK_TYPE_STRING; + if (lUnion.string == NULL || strlen(lUnion.string) > 256) { + LOG_LUA("smlua_sync_table_send_field on invalid string value: '%s'", (lUnion.string == NULL) ? "" : lUnion.string); + if (push) { lua_pushinteger(L, 0); } + return 0; + } + } else if (valueType == LUA_TNIL) { + lUnionType = LST_NETWORK_TYPE_NIL; } else { - LOG_LUA("_set_sync_table_field on invalid type: '%d'", valueType); - lua_pushinteger(L, 0); + LOG_LUA("smlua_sync_table_send_field on invalid type: '%d'", valueType); + if (push) { lua_pushinteger(L, 0); } return 0; } // get seq table - lua_getfield(L, 1, "_seq"); + lua_getfield(L, stackIndex + 1, "_seq"); int seqT = lua_gettop(L); // get seq number @@ -56,21 +75,30 @@ static int smlua__set_sync_table_field(UNUSED lua_State* L) { lua_pop(L, 1); // set seq number - seq += MAX_PLAYERS + (MAX_PLAYERS - gNetworkPlayers[0].globalIndex); - smlua_push_number_field(seqT, (char*)key, seq); + if (!gLuaInitializingScript && alterSeq) { + seq += MAX_PLAYERS + (MAX_PLAYERS - gNetworkPlayers[0].globalIndex); + smlua_push_number_field(seqT, (char*)key, seq); + } lua_pop(L, 1); // get index - u16 index = smlua_get_integer_field(1, "_index"); - // TODO: translate to global index + u16 index = smlua_get_integer_field(stackIndex + 1, "_index"); + index = network_player_global_index_from_local(index); - network_send_lua_sync_table(seq, remoteIndex, lst, index, key, lUnionType, lUnion); + if (!gLuaInitializingScript && seq > 0) { + network_send_lua_sync_table(toLocalIndex, seq, remoteIndex, lst, index, key, lUnionType, lUnion); + } LUA_STACK_CHECK_END(); - lua_pushinteger(L, 1); + if (push) { lua_pushinteger(L, 1); } return 1; } +static int smlua__set_sync_table_field(UNUSED lua_State* L) { + if (!smlua_functions_valid_param_count(L, 3)) { return 0; } + return smlua_sync_table_send_field(0, 0, true, true); +} + void smlua_set_sync_table_field_from_network(u64 seq, u16 remoteIndex, u16 lst, u16 index, const char* key, u16 lUnionType, union LSTNetworkUnion lUnion) { LUA_STACK_CHECK_BEGIN(); lua_State* L = gLuaState; @@ -101,13 +129,13 @@ void smlua_set_sync_table_field_from_network(u64 seq, u16 remoteIndex, u16 lst, // sanity check lst if (lst >= LST_MAX) { - LOG_LUA("Received sync table field packet with an invalid LST: %u", lst); + LOG_ERROR("Received sync table field packet with an invalid LST: %u", lst); return; } // sanity check lUnionType if (lUnionType >= LST_NETWORK_TYPE_MAX) { - LOG_LUA("Received sync table field packet with an invalid lUnionType: %u", lUnionType); + LOG_ERROR("Received sync table field packet with an invalid lUnionType: %u", lUnionType); return; } @@ -124,9 +152,8 @@ void smlua_set_sync_table_field_from_network(u64 seq, u16 remoteIndex, u16 lst, case LST_PLAYER: syncTableSize = 2; lua_getfield(L, -1, "gPlayerSyncTable"); - lua_pushinteger(L, index); + lua_pushinteger(L, network_player_local_index_from_global(index)); lua_gettable(L, -2); - // TODO: translate to local index break; default: assert(false); } @@ -171,6 +198,21 @@ void smlua_set_sync_table_field_from_network(u64 seq, u16 remoteIndex, u16 lst, lua_pushnumber(L, lUnion.number); lua_rawset(L, t); break; + case LST_NETWORK_TYPE_BOOLEAN: + lua_pushstring(L, key); + lua_pushboolean(L, lUnion.boolean); + lua_rawset(L, t); + break; + case LST_NETWORK_TYPE_STRING: + lua_pushstring(L, key); + lua_pushstring(L, lUnion.string); + lua_rawset(L, t); + break; + case LST_NETWORK_TYPE_NIL: + lua_pushstring(L, key); + lua_pushnil(L); + lua_rawset(L, t); + break; default: SOFT_ASSERT(false); } @@ -256,3 +298,78 @@ void smlua_bind_sync_table(void) { smlua_bind_function(L, "_set_sync_table_field", smlua__set_sync_table_field); LUA_STACK_CHECK_END(); } + +//////////////////////////////////////////////// + + +static void smlua_sync_table_send_table(u8 toLocalIndex) { + LUA_STACK_CHECK_BEGIN(); + lua_State* L = gLuaState; + int tableIndex = lua_gettop(L); + + lua_getfield(L, -1, "_table"); + int internalIndex = lua_gettop(L); + + lua_pushnil(L); // first key + while (lua_next(L, internalIndex) != 0) { + // uses 'key' (at index -2) and 'value' (at index -1) + //LOG_INFO(" sending sync table field: %s", lua_tostring(L, -2)); + + lua_pushvalue(L, tableIndex); // insert sync table + lua_insert(L, -3); // re-order sync table + + smlua_sync_table_send_field(toLocalIndex, internalIndex, false, false); + + lua_remove(L, -3); // remove sync table + + lua_pop(L, 1); // removed value ; keeps 'key' for next iteration + } + + lua_pop(L, 1); // remove internal table + + LUA_STACK_CHECK_END(); +} + +static void smlua_sync_table_send_all_file(u8 toLocalIndex, const char* path) { + LUA_STACK_CHECK_BEGIN(); + lua_State* L = gLuaState; + + LOG_INFO("sending sync table for file %s to %u", path, toLocalIndex); + + lua_getfield(L, LUA_REGISTRYINDEX, path); // get the file's "global" table + + { + lua_getfield(L, -1, "gGlobalSyncTable"); + smlua_sync_table_send_table(toLocalIndex); + lua_pop(L, 1); // pop gGlobalSyncTable + } + + { + lua_getfield(L, -1, "gPlayerSyncTable"); + for (int i = 0; i < MAX_PLAYERS; i++) { + // get gPlayerSyncTable[i] + lua_pushinteger(L, i); + lua_gettable(L, -2); + + smlua_sync_table_send_table(toLocalIndex); + + lua_pop(L, 1); // pop gPlayerSyncTable[i] + } + lua_pop(L, 1); // pop gPlayerSyncTable + } + + lua_pop(L, 1); // pop file's "global" table + + LUA_STACK_CHECK_END(); +} + +void smlua_sync_table_send_all(u8 toLocalIndex) { + SOFT_ASSERT(gNetworkType == NT_SERVER); + LUA_STACK_CHECK_BEGIN(); + for (int i = 0; i < gModTableLocal.entryCount; i++) { + struct ModListEntry* entry = &gModTableLocal.entries[i]; + if (!entry->enabled) { continue; } + smlua_sync_table_send_all_file(toLocalIndex, entry->path); + } + LUA_STACK_CHECK_END(); +} diff --git a/src/pc/lua/smlua_sync_table.h b/src/pc/lua/smlua_sync_table.h index e0bb56cc..16a5dccc 100644 --- a/src/pc/lua/smlua_sync_table.h +++ b/src/pc/lua/smlua_sync_table.h @@ -12,5 +12,6 @@ union LSTNetworkUnion; void smlua_set_sync_table_field_from_network(u64 seq, u16 remoteIndex, u16 lst, u16 index, const char* key, u16 lUnionType, union LSTNetworkUnion lUnion); void smlua_sync_table_init_globals(char* path, u16 remoteIndex); void smlua_bind_sync_table(void); +void smlua_sync_table_send_all(u8 toLocalIndex); #endif \ No newline at end of file diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c index 86a48059..7293ecf5 100644 --- a/src/pc/network/network_player.c +++ b/src/pc/network/network_player.c @@ -41,6 +41,26 @@ u8 network_player_connected_count(void) { return count; } +u8 network_player_global_index_from_local(u8 localIndex) { + if (gNetworkType == NT_SERVER) { return localIndex; } + + if (gNetworkPlayerLocal == NULL) { return UNKNOWN_GLOBAL_INDEX; } + if (localIndex == 0) { return gNetworkPlayerLocal->globalIndex; } // me + if (localIndex == 1) { return 0; } // server + + return localIndex - ((localIndex <= gNetworkPlayerLocal->globalIndex) ? 1 : 0); +} + +u8 network_player_local_index_from_global(u8 globalIndex) { + if (gNetworkType == NT_SERVER) { return globalIndex; } + + if (gNetworkPlayerLocal == NULL) { return UNKNOWN_LOCAL_INDEX; } + if (gNetworkPlayerLocal->globalIndex == globalIndex) { return 0; } // me + if (globalIndex == 0) { return 1; } // server + + return globalIndex + ((globalIndex < gNetworkPlayerLocal->globalIndex) ? 1 : 0); +} + struct NetworkPlayer* network_player_from_global_index(u8 globalIndex) { for (int i = 0; i < MAX_PLAYERS; i++) { if (!gNetworkPlayers[i].connected) { continue; } diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index d731ffa6..5f000607 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -49,6 +49,10 @@ void network_player_init(void); void network_player_update_model(u8 localIndex); bool network_player_any_connected(void); u8 network_player_connected_count(void); + +u8 network_player_global_index_from_local(u8 localIndex); +u8 network_player_local_index_from_global(u8 globalIndex); + struct NetworkPlayer* network_player_from_global_index(u8 globalIndex); struct NetworkPlayer* get_network_player_from_level(s16 courseNum, s16 actNum, s16 levelNum); struct NetworkPlayer* get_network_player_from_area(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex); diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c index e1dcbd50..70b31321 100644 --- a/src/pc/network/packets/packet.c +++ b/src/pc/network/packets/packet.c @@ -83,6 +83,7 @@ void packet_process(struct Packet* p) { case PACKET_DOWNLOAD_REQUEST: network_receive_download_request(p); break; case PACKET_DOWNLOAD: network_receive_download(p); break; + case PACKET_LUA_SYNC_TABLE_REQUEST: network_receive_lua_sync_table_request(p); break; case PACKET_LUA_SYNC_TABLE: network_receive_lua_sync_table(p); break; case PACKET_NETWORK_PLAYERS_REQUEST: network_receive_network_players_request(p); break; diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h index c4472085..6cc0fa3b 100644 --- a/src/pc/network/packets/packet.h +++ b/src/pc/network/packets/packet.h @@ -59,6 +59,7 @@ enum PacketType { PACKET_DOWNLOAD_REQUEST, PACKET_DOWNLOAD, + PACKET_LUA_SYNC_TABLE_REQUEST, PACKET_LUA_SYNC_TABLE, PACKET_NETWORK_PLAYERS_REQUEST, @@ -106,11 +107,16 @@ enum KickReasonType { union LSTNetworkUnion { long long integer; double number; + u8 boolean; + const char* string; }; enum LSTNetworkType { LST_NETWORK_TYPE_INTEGER, LST_NETWORK_TYPE_NUMBER, + LST_NETWORK_TYPE_BOOLEAN, + LST_NETWORK_TYPE_STRING, + LST_NETWORK_TYPE_NIL, LST_NETWORK_TYPE_MAX }; @@ -319,7 +325,9 @@ void network_send_download(u16 clientIndex, u16 serverIndex, u64 offset); void network_receive_download(struct Packet* p); // packet_lua_sync_table.c -void network_send_lua_sync_table(u64 seq, u16 remoteIndex, u16 lst, u16 index, const char* key, enum LSTNetworkType lUnionType, union LSTNetworkUnion lUnion); +void network_send_lua_sync_table_request(void); +void network_receive_lua_sync_table_request(struct Packet* p); +void network_send_lua_sync_table(u8 toLocalIndex, u64 seq, u16 remoteIndex, u16 lst, u16 index, const char* key, enum LSTNetworkType lUnionType, union LSTNetworkUnion lUnion); void network_receive_lua_sync_table(struct Packet* p); #endif diff --git a/src/pc/network/packets/packet_debug_sync.c b/src/pc/network/packets/packet_debug_sync.c index 2c9506d0..9418e096 100644 --- a/src/pc/network/packets/packet_debug_sync.c +++ b/src/pc/network/packets/packet_debug_sync.c @@ -55,6 +55,9 @@ void network_receive_debug_sync(struct Packet* p) { } if (!hasMismatch) { return; } + extern s16 gCurrCourseNum; + if (gCurrCourseNum == 0) { return; } + LOG_INFO(" "); LOG_INFO("Sync Object Table Mismatch"); for (int i = 0; i < MAX_SYNC_OBJECTS; i++) { diff --git a/src/pc/network/packets/packet_join.c b/src/pc/network/packets/packet_join.c index 8f8c0412..dbf784f4 100644 --- a/src/pc/network/packets/packet_join.c +++ b/src/pc/network/packets/packet_join.c @@ -233,4 +233,5 @@ void network_receive_join(struct Packet* p) { smlua_init(); network_send_network_players_request(); + network_send_lua_sync_table_request(); } diff --git a/src/pc/network/packets/packet_lua_sync_table.c b/src/pc/network/packets/packet_lua_sync_table.c index c1c13340..21223fb4 100644 --- a/src/pc/network/packets/packet_lua_sync_table.c +++ b/src/pc/network/packets/packet_lua_sync_table.c @@ -3,7 +3,24 @@ #include "pc/lua/smlua.h" #include "pc/debuglog.h" -void network_send_lua_sync_table(u64 seq, u16 remoteIndex, u16 lst, u16 index, const char* key, enum LSTNetworkType lUnionType, union LSTNetworkUnion lUnion) { +static char sLuaStrValue[257] = { 0 }; + +void network_send_lua_sync_table_request(void) { + SOFT_ASSERT(gNetworkType == NT_CLIENT); + struct Packet p = { 0 }; + packet_init(&p, PACKET_LUA_SYNC_TABLE_REQUEST, true, PLMT_NONE); + network_send_to((gNetworkPlayerServer != NULL) ? gNetworkPlayerServer->localIndex : 0, &p); + LOG_INFO("sending lua sync table request"); +} + +void network_receive_lua_sync_table_request(struct Packet* p) { + SOFT_ASSERT(gNetworkType == NT_SERVER); + SOFT_ASSERT(p->localIndex < MAX_PLAYERS); + smlua_sync_table_send_all(p->localIndex); + LOG_INFO("received lua sync table request"); +} + +void network_send_lua_sync_table(u8 toLocalIndex, u64 seq, u16 remoteIndex, u16 lst, u16 index, const char* key, enum LSTNetworkType lUnionType, union LSTNetworkUnion lUnion) { u16 keyLength = strlen(key); struct Packet p = { 0 }; @@ -21,13 +38,31 @@ void network_send_lua_sync_table(u64 seq, u16 remoteIndex, u16 lst, u16 index, c case LST_NETWORK_TYPE_NUMBER: { f64 number = lUnion.number; packet_write(&p, &number, sizeof(f64)); - //LOG_INFO("sent lua_sync_table: %llu, %u, %u, %s, %u, %f", seq, remoteIndex, lst, key, lUnionType, number); + //LOG_INFO("tx lua_sync_table: %llu, %u, %u, %s, %u, %f", seq, remoteIndex, lst, key, lUnionType, number); break; } case LST_NETWORK_TYPE_INTEGER: { s64 integer = lUnion.integer; packet_write(&p, &integer, sizeof(s64)); - //LOG_INFO("sent lua_sync_table: %llu, %u, %u, %s, %u, %llu", seq, remoteIndex, lst, key, lUnionType, integer); + //LOG_INFO("tx lua_sync_table: %llu, %u, %u, %s, %u, %llu", seq, remoteIndex, lst, key, lUnionType, integer); + break; + } + case LST_NETWORK_TYPE_BOOLEAN: { + packet_write(&p, &lUnion.boolean, sizeof(u8)); + //LOG_INFO("tx lua_sync_table: %llu, %u, %u, %s, %u, %u", seq, remoteIndex, lst, key, lUnionType, lUnion.boolean); + break; + } + case LST_NETWORK_TYPE_STRING: { + snprintf(sLuaStrValue, 256, "%s", lUnion.string); + u16 valueLength = strlen(sLuaStrValue); + packet_write(&p, &valueLength, sizeof(u16)); + packet_write(&p, &sLuaStrValue, valueLength * sizeof(u8)); + //LOG_INFO("tx lua_sync_table: %llu, %u, %u, %s, %u, %s", seq, remoteIndex, lst, key, lUnionType, sLuaStrValue); + break; + } + case LST_NETWORK_TYPE_NIL: { + // no-op + //LOG_INFO("tx lua_sync_table: %llu, %u, %u, %s, %u, ", seq, remoteIndex, lst, key, lUnionType); break; } default: @@ -35,7 +70,11 @@ void network_send_lua_sync_table(u64 seq, u16 remoteIndex, u16 lst, u16 index, c return; } - network_send(&p); + if (toLocalIndex == 0 || toLocalIndex >= MAX_PLAYERS) { + network_send(&p); + } else { + network_send_to(toLocalIndex, &p); + } } void network_receive_lua_sync_table(struct Packet* p) { @@ -70,6 +109,28 @@ void network_receive_lua_sync_table(struct Packet* p) { packet_read(p, &lUnion.integer, sizeof(s64)); //LOG_INFO("rx lua_sync_table: %llu, %u, %u, %s, %u, %llu", seq, remoteIndex, lst, key, lUnionType, lUnion.integer); break; + case LST_NETWORK_TYPE_BOOLEAN: + packet_read(p, &lUnion.boolean, sizeof(u8)); + //LOG_INFO("rx lua_sync_table: %llu, %u, %u, %s, %u, %u", seq, remoteIndex, lst, key, lUnionType, lUnion.boolean); + break; + case LST_NETWORK_TYPE_STRING: { + u16 valueLength = 0; + packet_read(p, &valueLength, sizeof(u16)); + if (keyLength > 256) { + LOG_ERROR("received lua sync table with invalid value length: %d", keyLength); + return; + } + + packet_read(p, &sLuaStrValue, valueLength * sizeof(u8)); + sLuaStrValue[valueLength] = 0; + lUnion.string = sLuaStrValue; + //LOG_INFO("rx lua_sync_table: %llu, %u, %u, %s, %u, %s", seq, remoteIndex, lst, key, lUnionType, lUnion.string); + break; + } + case LST_NETWORK_TYPE_NIL: + // no-op + //LOG_INFO("rx lua_sync_table: %llu, %u, %u, %s, %u, ", seq, remoteIndex, lst, key, lUnionType); + break; default: LOG_ERROR("received lua sync table with invalid type: %d", lUnionType); return;