So, let’s get started. Your algorithm should generate the world using a seed, as this is the only way to ensure that your world can be saved adequately. From here, we can immediately conclude that you need a function that can determine whether a block is located at a specific point in your world’s matrix without physically loading the world, using only the seed.
Additionally, the person above mentioned that you should serialize the data {id: number,position: {num,num,num}
I would like to point out that I would not make the position relative to world coordinates, but relative to your coordinates (for example, the second block on X has a position of X 2, not pos*size
Of course, you shouldn’t store the size of your blocks…
But now let’s get to the “fun” part. Ideally, when saving, you should go through each chunk in which the player was and save only the added/broken blocks, and of course the Seed itself, when loading, you load the Seed, and then go through the saved blocks → you load the supplied ones based on positions and ids, you remove the removed ones accordingly (first delete it, then save it)
Okay, to be honest, this is not “ideal,” but it is “exactly how it should be done,” otherwise your world will be measured in hundreds rather than tens of megabytes.
So, in the end, you get an incredibly huge table of objects when you save it. You should definitely use JsonEncode to convert it to a string. I think a player will place/break about 6,000 blocks in one session, and they will also perform many additional actions that will affect the weight, so I can multiply the final weight by three.
local a = { id=123,pos={100,100,100}} -- 30 bytes
local b = game.HttpService:JSONEncode(a)
local bytesOfUSave = string.len(b) * 6000 * 3 -- 30bytes * 6000times * 3multy
print(bytesOfUSave/1024/1024) -- 0.5 megabytes
So, in the end, you’ll be saving more than just blocks (oh, how much a chest filled with items weighs!), so it’s safe to assume that a single datastore (4mb) won’t be enough for even 3-4 sessions. That’s why people came up with text compression. You should look for the best combination
So when you’ve found the best combination of algorithms, I think you’ve compressed everything enough, but I’ll still write down what else can be done.
- Technically, the “id” key itself adds 1 extra byte of weight. Write i and all that changes is the name of the key, and the weight decreases by 1 byte. Do the same with pos → p and get rid of two more bytes (you can use indexes, but it’s less convenient).
- group changes by chunks for convenience (16x16x256)
- deleted obj is not “deleted” its just air so its not “deleted” its is is 0
- instead of pos = 1,2,3 u can do posId = x + zchunkSizeX + ychunkSizeX*chunkSizeZ (encode to one number using hash and store with a single number)
- Lazy loading