What do you mean exacly with that? I dont understand what you mean. Can you explain a bit more?
If you want to change the random generation later, its going to be almost impossible to make sure that everyone’s existing items stay the same. The only way I can think of doing it is keeping every old generator version’s code and including which version was used with every item. I don’t think that’s worth the memory saving.
What the other commenters are talking about is encoding your data as text and then (optionally) running it through a text compression algorithm to save storage.
Your idea of deterministically generating the data from a seed is totally sound and could save a lot of storage, assuming you have lots of generated data. Someone pointed out one potential pitfall with this: if you change the code that generates things, players’ saved items will change too!
You can create an RNG with a specific seed using the new-ish Random class: Random | Roblox Creator Documentation
So if you have a sword generator, you can use it like this:
function generateSword(seed)
local r = Random.new(seed)
local sword = {
seed = seed,
power = r:NextNumber(5, 20)
... many more properties
}
return sword, seed
end
local r = Random.new()
function givePlayerSomeSwords(player)
for _ = 1, 3 do
local sword, seed = generateSword(r:NextInteger())
--store in the players' runtime inventory
end
end
function loadPlayerInventory(player)
local compressedInventory = getPlayerCompressedInventory(player)
local inventory = {swords={}}--reconstruct runtime inventory from compressed data
for _, seed in ipairs(compressedInventory.swords)
table.insert(inventory.swords, generateSword(seed))
end
return inventory
end
function savePlayerInventory(player)
local inventory = getPlayerInventory(player)
local compressedInventory = {swords={}}
for _, item in ipairs(inventory.swords)
table.insert(compressedInventory.swords, item.seed)
end
return compressedInventory
end
Thanks, i’ll check when i open my PC
It might take a while. But how can i convert my data into text? Using tostring()? Or how should i do that?
I am Working on that TextCompressen modulescript but for some reason it doen’t work. I have no idea why, can you send the modulescript and how to enable it.
Apperantly this does not work
Module:
script:
error:
What the heck is happening
Modulescript code entirely
local Module = {}
function Module.GetCode(text)
local dictionary, length = {}, 0
for i = 32, 127 do
if i ~= 34 and i ~= 92 then
local c = string.char(i)
dictionary[c], dictionary[length] = length, c
length = length + 1
end
end
local escapemap = {}
for i = 1, 34 do
i = ({34, 92, 127})[i-31] or i
local c, e = string.char(i), string.char(i + 31)
escapemap[c], escapemap[e] = e, c
end
local function escape(s)
return (s:gsub("[%c\"\\]", function(c)
return "\127"..escapemap[c]
end))
end
local function unescape(s)
return (s:gsub("\127(.)", function(c)
return escapemap[c]
end))
end
local function copy(t)
local new = {}
for k, v in pairs(t) do
new[k] = v
end
return new
end
local function tobase93(n)
local value = ""
repeat
local remainder = n%93
value = dictionary[remainder]..value
n = (n - remainder)/93
until n == 0
return value
end
local function tobase10(value)
local n = 0
for i = 1, #value do
n = n + 93^(i-1)*dictionary[value:sub(-i, -i)]
end
return n
end
local function compress(text)
local dictionary = copy(dictionary)
local key, sequence, size = "", {}, #dictionary
local width, spans, span = 1, {}, 0
local function listkey(key)
local value = tobase93(dictionary[key])
if #value > width then
width, span, spans[width] = #value, 0, span
end
sequence[#sequence+1] = (" "):rep(width - #value)..value
span = span + 1
end
text = escape(text)
for i = 1, #text do
local c = text:sub(i, i)
local new = key..c
if dictionary[new] then
key = new
else
listkey(key)
key, size = c, size+1
dictionary[new], dictionary[size] = size, new
end
end
listkey(key)
spans[width] = span
return table.concat(spans, ",").."|"..table.concat(sequence)
end
local function decompress(text)
local dictionary = copy(dictionary)
local sequence, spans, content = {}, text:match("(.-)|(.*)")
local groups, start = {}, 1
for span in spans:gmatch("%d+") do
local width = #groups+1
groups[width] = content:sub(start, start + span*width - 1)
start = start + span*width
end
local previous;
for width = 1, #groups do
for value in groups[width]:gmatch(('.'):rep(width)) do
local entry = dictionary[tobase10(value)]
if previous then
if entry then
sequence[#sequence+1] = entry
dictionary[#dictionary+1] = previous..entry:sub(1, 1)
else
entry = previous..previous:sub(1, 1)
sequence[#sequence+1] = entry
dictionary[#dictionary+1] = entry
end
else
sequence[1] = entry
end
previous = entry
end
end
return unescape(table.concat(sequence))
end
return {compress = compress, decompress = decompress}
end
return Module
What am i doing wrong?
You’re lacking require().
Why would you optimize the data if it makes such little difference?
Data limit for a single data store value is 4MB meaning you can store 4,000,000 standard characters per value.
Let’s say a JSON encoded table for a single tool is so huge that it takes 1,000 bytes.
Then, you’ll still be able to store almost 4,000 tools.
Unless you necessarily need such extreme quantities, I wouldn’t recommend overcomplicating the task.
Yeah, but i am going to use this method to save more data, like maps, etc…
And i like optimized stuff (;
I basicly like spending way too much time on things to just improve it slightly.
What you are doing in generate sword, is sending the seed again back, so it can be used again. But is there a way, you can get a seed, depending on the stats in the table? So you can turn every single table into a seed, and then return it into a table (or string)?
Also you forgot typing do after the for loop.
for _, item in ipairs(inventory.swords) do -- you forgot to type the "do"
So you’re basically making it harder for yourself to operate the data because you like having it optimized when it’s not significant?
yes, and to learn new things in lua, such as the httpsservice and storing data in seeds.
And how seeds work and how i can use them.
What you’re looking for is modular arithmetic. If all of the max values are the same (I.e. NameID can be max 100, Damage can be max 100, Range can be max 100) You can do this:
Ideally you would encode and decode the output with base93.
But if the maximum values are different you can’t do this.
Please note that you probably shouldn’t/can’t use this for everything. For example vector3’s don’t have a max. And if you set the max value too high (E.G. 10000000) it’d be boatloads of times worse than just plain ol’ text encoding.
This is probably what you’re looking for, but not what you should use.
If thats not what i should use, do you have some different ways if storing data?
Yes, please look at my first reply.
But didn’t you just say “but not what you should use”? I don’t exacly know what you mean?
Look at the linked post. It should be very obvious.
I am not entirely sure how this works. I’ve read most of it but if i understanded it correctly its like remooving the variables and puttng them in a order (example), so the first 2 characters will be the id, the 3th to 4th will be the damage, etc…?
Whatever you use will have to be a reversible function mapping a table to a string and back, which means you will just end up recreating JSONEncode, which is also that. If you really need to save memory you could also JSONEncode and then do text compression on top of that, but you will need a compression algorithm that also outputs a string (as opposed to binary), so why bother.
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.