I’m currently working on a game that saves a significant amount of data to the DataStore. Any attempt at reducing the amount of data you transfer back and forth to the DataStore will be beneficial to your users, and thus, you - mobile users will be especially grateful.
Let’s take a look at the differences in the byte sizes of the JSON encoded strings you might save:
Output:
Memory sizes of colour JSON:
JSON [1] with '{"col":"FF960A"}' cost: 16 bytes
JSON [2] with '{"col":16750090}' cost: 16 bytes
JSON [3] with '{"col":250150010}' cost: 17 bytes
JSON [4] with '{"col":"250,150,10"}' cost: 20 bytes
JSON [5] with '{"col":[255,150,10]}' cost: 20 bytes
JSON [6] with '{"col":[1,0.588235318660736083984375,0.0392156876623630523681640625]}' cost: 69 bytes
Hex [FF960A] can be coverted back to Col -> 255, 150, 10
Int [16750090] can be coverted back to Col -> 255, 150, 10
Int->Hex: FF960A | Hex->Int 16750090
Code:
-- set up our env
local http = game:GetService('HttpService')
local memory = require(script.mem)
local rgbhex = require(script.rgbhexint)
for i, v in next, rgbhex do
getfenv()[i] = v
end
-- collect our strings to compare
local colour = Color3.fromRGB(255, 150, 10)
local strings = {
http:JSONEncode {col = {colour.r, colour.g, colour.b}}; -- What if we save it as an array without keys?
http:JSONEncode {col = rgbFromCol(colour)}; -- What if we save it as an array from 0 - 255?
http:JSONEncode {col = '250,150,10'}; -- What if we save it as a string with a delim?
http:JSONEncode {col = 250150010}; -- We know each rgb will be 0 - 255, so what if we save it as a 9 digit number?
http:JSONEncode {col = rgb2int(colour)}; -- As an int?
http:JSONEncode {col = rgb2hex(colour)}; -- As a hex code?
}
-- sort in order of bytesize & print info
table.sort(strings, function (a, b)
return memory:getSize(a) < memory:getSize(b)
end)
print 'Memory sizes of colour JSON:'
table.foreach(strings, function (i, json)
print(
('\tJSON [%d] with \'%s\' cost: %s bytes'):format(i, json, memory:getSize(json))
)
end)
-- demonstrate hex conversion
local hex = rgb2hex(colour)
print(
('\rHex [%s] can be coverted back to Col ->'):format(hex),
table.concat(rgbFromCol(hex2rgb(hex)), ', ')
)
-- demonstrate int conversion
local int = rgb2int(colour)
print(
('Int [%s] can be coverted back to Col ->'):format(int),
table.concat(rgbFromCol(int2rgb(int)), ', ')
)
-- demonstrate hex-int conversions
print(
('Int->Hex: %s\t|\tHex->Int %s'):format(int2hex(int), hex2int(int2hex(int)))
)
As you can see, saving the colour as an int/hex has saved us 53 bytes! This might seem inconsequential but if you’re saving masses of data (e.g. games like Bloxburg) you’re going to be reducing the size of your JSON packets significantly.
Here’s a placefile with the scripts:colourdata.rbxl (20.1 KB)
and here’s the relevant code for conversions:
local module = { }
-- helper
function module.rgbFromCol(rgb)
if typeof(rgb) ~= 'Color3' then
return warn 'Color3 object not passed'
end
if rgb.r > 1 then
return {rgb.r, rgb.g, rgb.b}
else
return {math.floor(rgb.r*255), math.floor(rgb.g*255), math.floor(rgb.b*255)}
end
end
-- hex
function module.rgb2hex(rgb)
rgb = typeof(rgb) == 'table' and rgb or (typeof(rgb) == 'Color3' and module.rgbFromCol(rgb) or nil)
if rgb then
local hex = ''
for _, v in next, rgb do
local h = ''
while (v > 0) do
local i = math.fmod(v, 16) + 1
v = math.floor(v / 16)
h = ('0123456789ABCDEF'):sub(i, i) .. h
end
h = #h == 0 and '00' or (#h == 1 and '0' .. h or h)
hex = hex .. h
end
return hex
end
end
function module.hex2rgb(hex)
return Color3.fromRGB(tonumber('0x' .. hex:sub(1, 2)), tonumber('0x' .. hex:sub(3, 4)), tonumber('0x' .. hex:sub(5, 6)))
end
function module.hex2int(hex)
return tonumber(hex, 16)
end
-- int
function module.rgb2int(rgb)
rgb = typeof(rgb) == 'table' and rgb or (typeof(rgb) == 'Color3' and module.rgbFromCol(rgb) or nil)
return rgb[1]*256^2 + rgb[2]*256 + rgb[3]
end
function module.int2rgb(int)
return Color3.fromRGB(
math.floor(int/256^2) % 256,
math.floor(int/256) % 256,
math.floor(int) % 256
)
end
function module.int2hex(int)
local hex = ('%x'):format(int * 256):upper()
return hex:sub(1, #hex - 2)
end
return module