diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py
index 0ff729ee5..6cd662b67 100644
--- a/autogen/convert_functions.py
+++ b/autogen/convert_functions.py
@@ -159,6 +159,8 @@ manual_index_documentation = """
- [define_custom_obj_fields](#define_custom_obj_fields)
- [network_init_object](#network_init_object)
- [network_send_object](#network_send_object)
+ - [network_send_to](#network_send_to)
+ - [network_send](#network_send)
@@ -236,6 +238,55 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
+## [network_send_to](#network_send_to)
+
+Sends a packet to a particular player (using their local index) containing whatever data you want.
+
+`dataTable` can only contain strings, integers, numbers, booleans, and nil
+
+The `reliable` field will ensure that the packet arrives, but should be used sparingly and only when missing a packet would cause a desync.
+
+### Lua Example
+`network_send_to(localPlayerIndex, reliable, { data1 = 'hello', data2 = 10})`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| localPlayerIndex | `integer` |
+| reliable | `bool` |
+| dataTable | `table` |
+
+### C Prototype
+`N/A`
+
+[:arrow_up_small:](#)
+
+
+
+## [network_send](#network_send)
+
+Sends a packet to all players containing whatever data you want.
+
+`dataTable` can only contain strings, integers, numbers, booleans, and nil
+
+The `reliable` field will ensure that the packet arrives, but should be used sparingly and only when missing a packet would cause a desync.
+
+### Lua Example
+`network_send(reliable, { data1 = 'hello', data2 = 10})`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| reliable | `bool` |
+| dataTable | `table` |
+
+### C Prototype
+`N/A`
+
+[:arrow_up_small:](#)
+
+
+
"""
############################################################################
diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua
index 701ff3dcb..94ab707c6 100644
--- a/autogen/lua_definitions/constants.lua
+++ b/autogen/lua_definitions/constants.lua
@@ -7852,7 +7852,10 @@ HOOK_ON_OBJECT_RENDER = 19
HOOK_ON_DEATH = 20
--- @type LuaHookedEventType
-HOOK_MAX = 21
+HOOK_ON_PACKET_RECEIVE = 21
+
+--- @type LuaHookedEventType
+HOOK_MAX = 22
--- @class ModelExtendedId
diff --git a/autogen/lua_definitions/manual.lua b/autogen/lua_definitions/manual.lua
index dc6e94b3e..da0707344 100644
--- a/autogen/lua_definitions/manual.lua
+++ b/autogen/lua_definitions/manual.lua
@@ -120,3 +120,17 @@ function network_send_object(object, reliable)
-- ...
end
+--- @param reliable boolean
+--- @param dataTable table
+--- @return nil
+function network_send(reliable, dataTable)
+ -- ...
+end
+
+--- @param toLocalIndex integer
+--- @param reliable boolean
+--- @param dataTable table
+--- @return nil
+function network_send_to(toLocalIndex, reliable, dataTable)
+ -- ...
+end
diff --git a/docs/lua/constants.md b/docs/lua/constants.md
index 0532526c7..da4624be1 100644
--- a/docs/lua/constants.md
+++ b/docs/lua/constants.md
@@ -2755,7 +2755,8 @@
| HOOK_ON_SET_CAMERA_MODE | 18 |
| HOOK_ON_OBJECT_RENDER | 19 |
| HOOK_ON_DEATH | 20 |
-| HOOK_MAX | 21 |
+| HOOK_ON_PACKET_RECEIVE | 21 |
+| HOOK_MAX | 22 |
[:arrow_up_small:](#)
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index 584fede32..e38466f67 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -6,6 +6,8 @@
- [define_custom_obj_fields](#define_custom_obj_fields)
- [network_init_object](#network_init_object)
- [network_send_object](#network_send_object)
+ - [network_send_to](#network_send_to)
+ - [network_send](#network_send)
@@ -1500,6 +1502,55 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
+## [network_send_to](#network_send_to)
+
+Sends a packet to a particular player (using their local index) containing whatever data you want.
+
+`dataTable` can only contain strings, integers, numbers, booleans, and nil
+
+The `reliable` field will ensure that the packet arrives, but should be used sparingly and only when missing a packet would cause a desync.
+
+### Lua Example
+`network_send_to(localPlayerIndex, reliable, { data1 = 'hello', data2 = 10})`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| localPlayerIndex | `integer` |
+| reliable | `bool` |
+| dataTable | `table` |
+
+### C Prototype
+`N/A`
+
+[:arrow_up_small:](#)
+
+
+
+## [network_send](#network_send)
+
+Sends a packet to all players containing whatever data you want.
+
+`dataTable` can only contain strings, integers, numbers, booleans, and nil
+
+The `reliable` field will ensure that the packet arrives, but should be used sparingly and only when missing a packet would cause a desync.
+
+### Lua Example
+`network_send(reliable, { data1 = 'hello', data2 = 10})`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| reliable | `bool` |
+| dataTable | `table` |
+
+### C Prototype
+`N/A`
+
+[:arrow_up_small:](#)
+
+
+
---
# functions from behavior_actions.h
diff --git a/docs/lua/hooks.md b/docs/lua/hooks.md
index 070213277..c3d47d9f8 100644
--- a/docs/lua/hooks.md
+++ b/docs/lua/hooks.md
@@ -105,8 +105,9 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
| HOOK_ON_PAUSE_EXIT | Called when the local player exits through the pause screen, return `false` to prevent the exit | `boolean` usedExitToCastle |
| HOOK_GET_STAR_COLLECTION_DIALOG | Called when the local player collects a star, return a [DialogId](constants.md#enum-DialogId) to show a message | None |
| HOOK_ON_SET_CAMERA_MODE | Called when the camera mode gets set, return `false` to prevent the camera mode from being set | [Camera](structs.md#Camera), `integer` mode, `integer` frames |
-| HOOK_ON_OBJECT_RENDER | Called right before an object is rendered. **Note:** You must set the `hookRender` field of the object to a non-zero value | [Object](structs.md#Object) |
-| HOOK_ON_DEATH | Called when the local player dies, return `false` to prevent normal death sequence | [MarioState](structs.md#MarioState) |
+| HOOK_ON_OBJECT_RENDER | Called right before an object is rendered. **Note:** You must set the `hookRender` field of the object to a non-zero value | [Object](structs.md#Object) renderedObj |
+| HOOK_ON_DEATH | Called when the local player dies, return `false` to prevent normal death sequence | [MarioState](structs.md#MarioState) localMario |
+| HOOK_ON_PACKET_RECEIVE | Called when the mod receives a packet that used `network_send()` or `network_send_to()` | `table` dataTable |
### Parameters
diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c
index 330865deb..0590b3010 100644
--- a/src/pc/lua/smlua_constants_autogen.c
+++ b/src/pc/lua/smlua_constants_autogen.c
@@ -2798,7 +2798,8 @@ char gSmluaConstants[] = ""
"HOOK_ON_SET_CAMERA_MODE = 18\n"
"HOOK_ON_OBJECT_RENDER = 19\n"
"HOOK_ON_DEATH = 20\n"
-"HOOK_MAX = 21\n"
+"HOOK_ON_PACKET_RECEIVE = 21\n"
+"HOOK_MAX = 22\n"
"E_MODEL_NONE = 0\n"
"E_MODEL_MARIO = 1\n"
"E_MODEL_SMOKE = 2\n"
diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c
index 12d4b061c..3c2e1bf76 100644
--- a/src/pc/lua/smlua_functions.c
+++ b/src/pc/lua/smlua_functions.c
@@ -176,6 +176,16 @@ int smlua_func_network_send_object(lua_State* L) {
return 1;
}
+int smlua_func_network_send(lua_State* L) {
+ if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
+ network_send_lua_custom(true);
+}
+
+int smlua_func_network_send_to(lua_State* L) {
+ if (!smlua_functions_valid_param_count(L, 3)) { return 0; }
+ network_send_lua_custom(false);
+}
+
//////////
// bind //
//////////
@@ -191,4 +201,6 @@ void smlua_bind_functions(void) {
smlua_bind_function(L, "network_init_object", smlua_func_network_init_object);
smlua_bind_function(L, "network_send_object", smlua_func_network_send_object);
smlua_bind_function(L, "reset_level", smlua_func_reset_level);
+ smlua_bind_function(L, "network_send", smlua_func_network_send);
+ smlua_bind_function(L, "network_send_to", smlua_func_network_send_to);
}
diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c
index 6d06ea0db..2b3a4ea28 100644
--- a/src/pc/lua/smlua_hooks.c
+++ b/src/pc/lua/smlua_hooks.c
@@ -1,4 +1,5 @@
#include "smlua.h"
+#include "pc/mods/mod.h"
#include "src/game/object_list_processor.h"
#include "pc/djui/djui_chat_message.h"
#include "pc/crash_handler.h"
@@ -454,6 +455,27 @@ void smlua_call_event_hooks_set_camera_mode_params(enum LuaHookedEventType hookT
}
}
+void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int modIndex, int valueIndex) {
+ lua_State* L = gLuaState;
+ if (L == NULL) { return; }
+ struct LuaHookedEvent* hook = &sHookedEvents[hookType];
+ for (int i = 0; i < hook->count; i++) {
+ if (hook->mod[i]->index != modIndex) { continue; }
+ // push the callback onto the stack
+ lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
+
+ // push value
+ lua_pushvalue(L, valueIndex);
+
+ // call the callback
+ if (0 != smlua_call_hook(L, 1, 0, 0, hook->mod[i])) {
+ LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
+ smlua_logline();
+ continue;
+ }
+ }
+}
+
////////////////////
// hooked actions //
////////////////////
diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h
index b0804df8b..e7f25c40f 100644
--- a/src/pc/lua/smlua_hooks.h
+++ b/src/pc/lua/smlua_hooks.h
@@ -29,6 +29,7 @@ enum LuaHookedEventType {
HOOK_ON_SET_CAMERA_MODE,
HOOK_ON_OBJECT_RENDER,
HOOK_ON_DEATH,
+ HOOK_ON_PACKET_RECEIVE,
HOOK_MAX,
};
@@ -54,6 +55,7 @@ static char* LuaHookedEventTypeName[] = {
"HOOK_ON_SET_CAMERA_MODE",
"HOOK_ON_OBJECT_RENDER",
"HOOK_ON_DEATH",
+ "HOOK_ON_PACKET_RECEIVE",
"HOOK_MAX"
};
@@ -70,6 +72,7 @@ void smlua_call_event_hooks_interact_params(enum LuaHookedEventType hookType, st
void smlua_call_event_hooks_object_param(enum LuaHookedEventType hookType, struct Object* obj);
bool smlua_call_event_hooks_ret_int(enum LuaHookedEventType hookType, s32* returnValue);
void smlua_call_event_hooks_set_camera_mode_params(enum LuaHookedEventType hookType, struct Camera *c, s16 mode, s16 frames, bool* returnValue);
+void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int modIndex, int valueIndex);
enum BehaviorId smlua_get_original_behavior_id(const BehaviorScript* behavior);
const BehaviorScript* smlua_override_behavior(const BehaviorScript* behavior);
diff --git a/src/pc/lua/smlua_utils.c b/src/pc/lua/smlua_utils.c
index 8db9df131..630d820a9 100644
--- a/src/pc/lua/smlua_utils.c
+++ b/src/pc/lua/smlua_utils.c
@@ -260,6 +260,94 @@ struct LSTNetworkType smlua_to_lnt(lua_State* L, int index) {
///////////////////////////////////////////////////////////////////////////////////////////
+bool packet_write_lnt(struct Packet* p, struct LSTNetworkType* lnt) {
+ u8 lntType = lnt->type;
+ packet_write(p, &lntType, sizeof(u8));
+
+ switch (lnt->type) {
+ case LST_NETWORK_TYPE_NUMBER: {
+ f64 number = lnt->value.number;
+ packet_write(p, &number, sizeof(f64));
+ return true;
+ }
+
+ case LST_NETWORK_TYPE_INTEGER: {
+ s64 integer = lnt->value.integer;
+ packet_write(p, &integer, sizeof(s64));
+ return true;
+ }
+
+ case LST_NETWORK_TYPE_BOOLEAN: {
+ packet_write(p, &lnt->value.boolean, sizeof(u8));
+ return true;
+ }
+
+ case LST_NETWORK_TYPE_STRING: {
+ u16 valueLength = strlen(lnt->value.string);
+ if (valueLength < 1 || valueLength > 256) {
+ LOG_ERROR("attempted to send lua variable with invalid string length: %u", valueLength);
+ return false;
+ }
+ packet_write(p, &valueLength, sizeof(u16));
+ packet_write(p, lnt->value.string, valueLength * sizeof(u8));
+ return true;
+ }
+
+ case LST_NETWORK_TYPE_NIL: {
+ // no-op
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ LOG_ERROR("attempted to send lua variable with invalid lnt type: %d", lnt->type);
+ return false;
+}
+
+bool packet_read_lnt(struct Packet* p, struct LSTNetworkType* lnt) {
+ packet_read(p, &lnt->type, sizeof(u8));
+
+ switch (lnt->type) {
+ case LST_NETWORK_TYPE_NUMBER:
+ packet_read(p, &lnt->value.number, sizeof(f64));
+ return true;
+
+ case LST_NETWORK_TYPE_INTEGER:
+ packet_read(p, &lnt->value.integer, sizeof(s64));
+ return true;
+
+ case LST_NETWORK_TYPE_BOOLEAN:
+ packet_read(p, &lnt->value.boolean, sizeof(u8));
+ return true;
+
+ case LST_NETWORK_TYPE_STRING: {
+ u16 valueLength = 0;
+ packet_read(p, &valueLength, sizeof(u16));
+ if (valueLength < 1 || valueLength > 256) {
+ LOG_ERROR("received lua variable with invalid value length: %d", valueLength);
+ return false;
+ }
+ lnt->value.string = calloc(valueLength + 1, sizeof(char));
+ packet_read(p, lnt->value.string, valueLength * sizeof(u8));
+ return true;
+ }
+
+ case LST_NETWORK_TYPE_NIL:
+ // no-op
+ return true;
+
+ default:
+ break;
+ }
+
+ LOG_ERROR("received lua variable with invalid type: %d", lnt->type);
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
void smlua_push_object(lua_State* L, u16 lot, void* p) {
if (p == NULL) {
lua_pushnil(L);
diff --git a/src/pc/lua/smlua_utils.h b/src/pc/lua/smlua_utils.h
index 136fe5c90..f8adf1570 100644
--- a/src/pc/lua/smlua_utils.h
+++ b/src/pc/lua/smlua_utils.h
@@ -3,6 +3,8 @@
extern u8 gSmLuaConvertSuccess;
typedef int LuaFunction;
+struct Packet;
+struct LSTNetworkType;
f32* smlua_get_vec3f_from_buffer(void);
s16* smlua_get_vec3s_from_buffer(void);
@@ -19,6 +21,9 @@ void* smlua_to_cobject(lua_State* L, int index, u16 lot);
void* smlua_to_cpointer(lua_State* L, int index, u16 lvt);
struct LSTNetworkType smlua_to_lnt(lua_State* L, int index);
+bool packet_write_lnt(struct Packet* p, struct LSTNetworkType* lnt);
+bool packet_read_lnt(struct Packet* p, struct LSTNetworkType* lnt);
+
void smlua_push_object(lua_State* L, u16 lot, void* p);
void smlua_push_pointer(lua_State* L, u16 lvt, void* p);
void smlua_push_integer_field(int index, char* name, lua_Integer val);
diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c
index 84b1efc89..293dabc04 100644
--- a/src/pc/network/packets/packet.c
+++ b/src/pc/network/packets/packet.c
@@ -92,7 +92,9 @@ void packet_process(struct Packet* p) {
case PACKET_NETWORK_PLAYERS_REQUEST: network_receive_network_players_request(p); break;
- case PACKET_REQUEST_FAILED: network_receive_request_failed(p); break;
+ case PACKET_REQUEST_FAILED: network_receive_request_failed(p); break;
+
+ case PACKET_LUA_CUSTOM: network_receive_lua_custom(p); break;
// custom
case PACKET_CUSTOM: network_receive_custom(p); break;
diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h
index a8097b5b5..04c8a30fd 100644
--- a/src/pc/network/packets/packet.h
+++ b/src/pc/network/packets/packet.h
@@ -69,6 +69,8 @@ enum PacketType {
PACKET_REQUEST_FAILED,
+ PACKET_LUA_CUSTOM,
+
///
PACKET_CUSTOM = 255,
};
@@ -353,4 +355,8 @@ void network_receive_lua_sync_table(struct Packet* p);
void network_send_request_failed(struct NetworkPlayer* toNp, u8 requestType);
void network_receive_request_failed(struct Packet* p);
+// packet_lua_custom.c
+void network_send_lua_custom(bool broadcast);
+void network_receive_lua_custom(struct Packet* p);
+
#endif
diff --git a/src/pc/network/packets/packet_lua_custom.c b/src/pc/network/packets/packet_lua_custom.c
new file mode 100644
index 000000000..9eff14cfa
--- /dev/null
+++ b/src/pc/network/packets/packet_lua_custom.c
@@ -0,0 +1,125 @@
+#include
+#include "../network.h"
+#include "pc/mods/mod.h"
+#include "pc/lua/smlua.h"
+#include "pc/lua/smlua_utils.h"
+#include "pc/debuglog.h"
+
+void network_send_lua_custom(bool broadcast) {
+ LOG_INFO("Sending lua custom packet");
+ lua_State* L = gLuaState;
+ u16 zero = 0;
+ s32 paramIndex = 1;
+
+ // figure out mod index
+ if (gLuaActiveMod == NULL) {
+ LOG_LUA("Could not figure out the current active mod!");
+ smlua_logline();
+ return;
+ }
+ u16 modIndex = gLuaActiveMod->index;
+
+ // get local index
+ s32 toLocalIndex = 0;
+ if (!broadcast) {
+ s32 toLocalIndex = smlua_to_integer(L, paramIndex++);
+ if (toLocalIndex <= 0 || toLocalIndex >= MAX_PLAYERS) {
+ LOG_LUA("Tried to send packet to invalid local index: %d", toLocalIndex)
+ smlua_logline();
+ return;
+ }
+ if (!gSmLuaConvertSuccess) { return; }
+ }
+
+ // get reliability
+ bool reliability = smlua_to_boolean(L, paramIndex++);
+ if (!gSmLuaConvertSuccess) { return; }
+
+ // write packet header
+ struct Packet p = { 0 };
+ packet_init(&p, PACKET_LUA_CUSTOM, reliability, PLMT_NONE);
+ packet_write(&p, &modIndex, sizeof(u16));
+ u8* keyCount = &p.buffer[p.cursor];
+ packet_write(&p, &zero, sizeof(u8));
+
+ // make sure value passed in is a table
+ s32 tableIndex = paramIndex;
+ if (lua_type(L, tableIndex) != LUA_TTABLE) {
+ LOG_LUA("Tried to send a packet with a non-table");
+ smlua_logline();
+ return;
+ }
+
+ // iterate table
+ s32 iterateIndex = lua_gettop(L);
+ lua_pushnil(L); // first key
+ while (lua_next(L, iterateIndex) != 0) {
+ // convert and write key
+ struct LSTNetworkType lntKey = smlua_to_lnt(L, -2);
+ if (!gSmLuaConvertSuccess) {
+ LOG_LUA("Failed to convert key to LNT (tx)");
+ smlua_logline();
+ return;
+ }
+ if (!packet_write_lnt(&p, &lntKey)) {
+ return;
+ }
+
+ // convert and write value
+ struct LSTNetworkType lntValue = smlua_to_lnt(L, -1);
+ if (!gSmLuaConvertSuccess) {
+ LOG_LUA("Failed to convert value to LNT (tx)");
+ smlua_logline();
+ return;
+ }
+ if (!packet_write_lnt(&p, &lntValue)) {
+ return;
+ }
+
+ // increment key count
+ *keyCount = *keyCount + 1;
+ lua_pop(L, 1); // pop value
+ }
+ lua_pop(L, 1); // pop key
+
+ // send packet
+ if (broadcast) {
+ network_send(&p);
+ } else {
+ network_send_to(toLocalIndex, &p);
+ }
+}
+
+void network_receive_lua_custom(struct Packet* p) {
+ LOG_INFO("Receiving lua custom packet");
+ lua_State* L = gLuaState;
+ u16 modIndex = 0;
+ u8 keyCount = 0;
+ packet_read(p, &modIndex, sizeof(u16));
+ packet_read(p, &keyCount, sizeof(u8));
+
+ lua_newtable(L);
+ s32 tableIndex = lua_gettop(L);
+ for(u16 i = 0; i < keyCount; i++) {
+ struct LSTNetworkType lntKey = { 0 };
+ if (!packet_read_lnt(p, &lntKey)) {
+ LOG_LUA("Failed to convert key to LNT (rx)");
+ smlua_logline();
+ return;
+ }
+ smlua_push_lnt(&lntKey);
+
+ struct LSTNetworkType lntValue = { 0 };
+ if (!packet_read_lnt(p, &lntValue)) {
+ LOG_LUA("Failed to convert value to LNT (rx)");
+ smlua_logline();
+ return;
+ }
+ smlua_push_lnt(&lntValue);
+
+ lua_settable(L, -3);
+ }
+
+ smlua_call_event_hooks_value_param(HOOK_ON_PACKET_RECEIVE, modIndex, tableIndex);
+ lua_pop(L, 1); // pop table
+}
diff --git a/src/pc/network/packets/packet_lua_sync_table.c b/src/pc/network/packets/packet_lua_sync_table.c
index 9c478f584..fd950129d 100644
--- a/src/pc/network/packets/packet_lua_sync_table.c
+++ b/src/pc/network/packets/packet_lua_sync_table.c
@@ -20,96 +20,6 @@ void network_receive_lua_sync_table_request(struct Packet* p) {
LOG_INFO("received lua sync table request");
}
-/////////////////////////////////////////////////////////////
-
-static bool packet_write_lnt(struct Packet* p, struct LSTNetworkType* lnt) {
- u8 lntType = lnt->type;
- packet_write(p, &lntType, sizeof(u8));
-
- switch (lnt->type) {
- case LST_NETWORK_TYPE_NUMBER: {
- f64 number = lnt->value.number;
- packet_write(p, &number, sizeof(f64));
- return true;
- }
-
- case LST_NETWORK_TYPE_INTEGER: {
- s64 integer = lnt->value.integer;
- packet_write(p, &integer, sizeof(s64));
- return true;
- }
-
- case LST_NETWORK_TYPE_BOOLEAN: {
- packet_write(p, &lnt->value.boolean, sizeof(u8));
- return true;
- }
-
- case LST_NETWORK_TYPE_STRING: {
- u16 valueLength = strlen(lnt->value.string);
- if (valueLength < 1 || valueLength > 256) {
- LOG_ERROR("attempted to send lua sync table with invalid string length: %u", valueLength);
- return false;
- }
- packet_write(p, &valueLength, sizeof(u16));
- packet_write(p, lnt->value.string, valueLength * sizeof(u8));
- return true;
- }
-
- case LST_NETWORK_TYPE_NIL: {
- // no-op
- return true;
- }
-
- default:
- break;
- }
-
- LOG_ERROR("attempted to send lua sync table with invalid lnt type: %d", lnt->type);
- return false;
-}
-
-static bool packet_read_lnt(struct Packet* p, struct LSTNetworkType* lnt) {
- packet_read(p, &lnt->type, sizeof(u8));
-
- switch (lnt->type) {
- case LST_NETWORK_TYPE_NUMBER:
- packet_read(p, &lnt->value.number, sizeof(f64));
- return true;
-
- case LST_NETWORK_TYPE_INTEGER:
- packet_read(p, &lnt->value.integer, sizeof(s64));
- return true;
-
- case LST_NETWORK_TYPE_BOOLEAN:
- packet_read(p, &lnt->value.boolean, sizeof(u8));
- return true;
-
- case LST_NETWORK_TYPE_STRING: {
- u16 valueLength = 0;
- packet_read(p, &valueLength, sizeof(u16));
- if (valueLength < 1 || valueLength > 256) {
- LOG_ERROR("received lua sync table with invalid value length: %d", valueLength);
- return false;
- }
- lnt->value.string = calloc(valueLength + 1, sizeof(char));
- packet_read(p, lnt->value.string, valueLength * sizeof(u8));
- return true;
- }
-
- case LST_NETWORK_TYPE_NIL:
- // no-op
- return true;
-
- default:
- break;
- }
-
- LOG_ERROR("received lua sync table with invalid type: %d", lnt->type);
- return false;
-}
-
-/////////////////////////////////////////////////////////////
-
void network_send_lua_sync_table(u8 toLocalIndex, u64 seq, u16 modRemoteIndex, u16 lntKeyCount, struct LSTNetworkType* lntKeys, struct LSTNetworkType* lntValue) {
if (gLuaState == NULL) { return; }