Here’s a quick primer for string.pack
for people who think “how can this possibly be of any use to me”.
Let’s say you want to transmit the character state over the wire. A character has position (where they are), walk direction (where are they going) and health.
Position requires three numbers but they can be 32-bit floating point because that’s as much precision as Vector3 gives you anyhow.
Direction requires three numbers but they are from -1…1 and you don’t need to be as precise.
Health requires one number that’s 0-100.
Let’s pack this!
Create a format string that describes the message, with each component using a format specification per Lua documentation (Lua 5.3 Reference Manual). Just ignore the aligment and endianness options and focus on types:
local characterStateFormat = "fffbbbB"
How many bytes will the packed message take? Let’s ask string.packsize
:
> print(string.packsize(characterStateFormat))
16
Nice, 16 bytes! That’s pretty compact, you can send a lot of these if you want to.
Then let’s pack the data! We’re going to store direction as a byte -127…127, and health as a 0…100 byte (using unsigned byte for clarity, no difference in this case):
local characterState = string.pack(characterStateFormat,
posx, posy, posz, dirx * 127, diry * 127, dirz * 127, health)
For astute readers: yes this is losing ~0.5 bits per directional component because of imprecise rounding; if you want to you can correct it with math.round, e.g. math.round(dirx * 127)
Then let’s unpack the data on the other side! (after sending the string across the wire through a remote event):
local posx, posy, posz, dirx, diry, dirz, health =
string.unpack(characterStateFormat, characterState)
dirx /= 127
diry /= 127
dirz /= 127
Note that direction that you reconstruct will have a bit of an error (usually not a big problem) and health will drop the fractional parts, but considering we just used 4 bytes to store both of these it’s not that big of a deal.