So I am planning on making a game that would require saving many values (CFrames, colours, vector3’s…), so I’m looking into sort of packing the values as much as I can, and I want to learn from this, not be spoonfed.
Anyway, for saving colours, I found one method that seems to work fine, and that’s by plugging the R, G, and B values into this formula:
65536 * r + 256 * g + b
This returns a number between 0 and 16777215, being black and white respectively.
What I’m unsure of is whether this is actually efficient in saving datastore space since I could be potentially using up to 8 characters when a hex code has 6. That being said, is it efficient to solely rely on the integer method, or is it more efficient to rely on hex codes? Or should I dynamically rely on one or the other depending on the length of the integer (if length of the int is smaller than 6, rely on integer method, else use hex)?
That is true but that isn’t very efficient when it comes to optimizing in order to not exceed the 4M character limit. If I were to serialize a Color3 to a string for example, it would be 9 characters, being RRRGGGBBB. The special thing about hex codes and the integer method I mentioned in the OP, is that the max lengths are 6 and 8 respectively, which might not seem like it’s reducing much but it definitely does add up.
You could probably compress the number into multiple strings using string.char and backwards with string.byte. It has 256 possible characters, although I don’t think anything beyond 128 in string.char is possible on a datastore so we get half of the characters, and I don’t think char 0 also works for datastores so that leaves us with 127 characters. It is still alot of numbers to fit into one character.
This is my attempt
local color = Color3.new(math.random(),math.random(),math.random()) -- Random color
local hex = tonumber("0x"..color:ToHex()) -- turn to number
local function compress(number)
local s = ""
repeat s ..= string.char(number%127+1)
number = math.floor(number/127)
until number <= 0
return s
end
local function decompress(s)
local n = 0
for i, v in ipairs(string.split(s,"")) do
n += 127^(i-1)*(string.byte(v)-1)
end
return n
end
local compressed = compress(hex)
local decompressed = decompress(compressed)
print(decompressed == hex, #compressed) -- is decompressed equal to original number; and how many characters
It turns the color values into a number, then compresses it using string.char. This shrinks the color values down to 4 characters. If 256 characters was possible, it would shrink it down to 3 characters which is amazing. Anyways, I’m too lazy to turn the number back into colors but I think you can do it.
Edit: this looks more like a compressor for numbers rather than colors, but it still does its job.
Edit2: this compressor doesn’t like big numbers. Numbers above 2^54 (from my tests) sometimes get inaccuracies about ~25.6%, and some specific numbers will decide to throw an error
I did some debugging, and apparently very large numbers have weird behavior with arithmetic. How is the remainder more than the divisor? The last two digits is 51 how is it 00?