C Data is a simple wrapper for LuaJIT FFI's cast to C String. This is primarily used to serialize Lua tables into network-transferable data.
It is worth noting that if you encode an incomplete table (missing a key) then when you decode the packet, it will have the missing key with a value of 0.
local cdata = require "cdata"
local packets = {}
-- all structs get a type field so we don't lose our minds.
function add_struct(name, fields, map)
local struct = string.format("typedef struct { uint8_t type; %s } %s;", fields, name)
cdata:new_struct(name, struct)
-- the packet_type struct isn't a real packet, so don't index it.
if map then
map.name = name
table.insert(packets, map)
packets[name] = #packets
end
end
-- Slightly special, I guess.
add_struct("packet_type", "")
add_struct(
"player_whois", [[
uint16_t id;
]], {
"id",
}
)
add_struct(
"player_create", [[
uint16_t id;
uint8_t flags;
float position_x, position_y, position_z;
float orientation_x, orientation_y, orientation_z;
unsigned char name[64];
]], {
"id",
"flags",
"position_x", "position_y", "position_z",
"orientation_x", "orientation_y", "orientation_z",
"name",
}
)
add_struct(
"player_update", [[
uint16_t id;
float position_x, position_y, position_z;
float orientation_x, orientation_y, orientation_z;
]], {
"id",
"position_x", "position_y", "position_z",
"orientation_x", "orientation_y", "orientation_z",
}
)
add_struct(
"player_action", [[
uint16_t id;
uint16_t action;
]], {
"id",
"action",
}
)
local player = self.players[1]
local data = {
type = packets["player_update"],
id = player.id,
position_x = player.position.x,
position_y = player.position.y,
position_z = player.position.z,
orientation_x = player.orientation.x,
orientation_y = player.orientation.y,
orientation_z = player.orientation.z,
}
local struct = cdata:set_struct("player_update", data)
local encoded = cdata:encode(struct)
-- We assume we have a variable named data that we received from the network
local header = cdata:decode("packet_type", data)
local map = packets[header.type]
if not map then
error(string.format("Invalid packet type (%s) received!", header.type))
return
end
local decoded = cdata:decode(map.name, data)