Let's figure out how Items work! #3
Replies: 10 comments 23 replies
-
My Wild Guess: There could be an intermediate index mapping each chunk ID to a list of "pages", for example chunk 35 -> [2, 5, 33] would tell you that the 2nd, 5th, and 33rd "page" of 24-byte records all belong to chunk 35. If this is true, you would only gain insight into this mechanism when a new page is required, so maybe the key to figuring this out is filling up a few chunks with as many items as possible. Another interesting test would be to place items that span across chunks. |
Beta Was this translation helpful? Give feedback.
-
Above is what I know about how items are stored in a DQB2 STGDAT file. If anyone knows more than me, please share and maybe we can finally crack this mystery! (@turtle-insect @Sapphire645 @Mugafo and anyone else) |
Beta Was this translation helpful? Give feedback.
-
Just a little update. |
Beta Was this translation helpful? Give feedback.
-
https://drive.google.com/file/d/162ZJDUgTHHUrmA572a-jrbKEhWCqAJKS/view?usp=drive_link Found this region of memory. Looks like it gets updated whenever an item is placed. |
Beta Was this translation helpful? Give feedback.
-
Hey, been awhile since I've been able to work on this, busy busy and a cat puked on my computer frying it awhile back so I lost some item code I had at the time that I never committed to my tile editor. I had gotten to essentially the same point of what you've found on items. As the screen vid Sapphire645 posted shows, items also place values in the block data area, these handle special checks for being able to place other blocks/items in that spot (though it doesn't appear to be the only check) and you can do neat things with that like deleting the item, but leaving the block data behind and create custom shadows etc. From what I can remember, there was also a size setting in the bytes somewhere, as some items have a small, normal, and large setting that could be used by editing it. I remember playing around with the clock item having the different sizes down next to each other on the map. With the positioning data you can make items overlap and you can cause weird glitches with some of the other bytes. I remember making a pot indestructible when hit but would spit out 3 pots to pick up (liking tying into the block properties for the type of soil that would drop 3 seeds). I'd need to get back into it, my assembly knowledge isn't very good, so I was having trouble at the time trying to figure out what all was happening when an item was placed. |
Beta Was this translation helpful? Give feedback.
-
Small progress update: As turtle-insect demonstrated, there are 2 relevant ranges of memory:
The 4-byte record contains:
The key idea is that if you load and immediately save your file (without adding or destroying anything) then the resulting save file will Edit: For reference, here is an example of how fragmentation can occur:
So it appears to be something like an indexed ring buffer, where new items are always added to the end, but I don't really know. For now I plan on requiring the user to use the game to defragment the item records if they want to manipulate them. But I may not be able to resume this work for a while because I am rethinking my entire project and going to try using a relational database as the foundation. |
Beta Was this translation helpful? Give feedback.
-
I've just learned that the debug build has a feature that will automatically build blueprints. And I do (mostly) understand how items are represented in blueprints. This means if I want to do large-scale item and block manipulation, I can just generate blueprints (well up to 4 at a time I guess) and use the autobuild to quickly complete them! Of course, I'd still like to be able to directly manipulate items in the STGDAT file, but until that time this might be the perfect workaround, pending some testing... |
Beta Was this translation helpful? Give feedback.
-
We really need to get this whole thing cracked... To start, all items's data is stored at this location 0x24E7D1 right? |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
I've just had another wild guess about the 24-byte data structure. Consider that autosave probably works something like this: A background thread simply copies the main memory directly into a separate buffer to be zipped and saved to disk. While this is happening, the main thread does not pause. So the main thread might be in the middle of destroying or adding an item while the autosave copies the data. If this is true, the mystery bytes may implement something like a "checksum" [1] so that no matter what the autosave happened to capture, there is a sensible/consistent way to interpret the data when it is loaded. For example, maybe when an item is destroyed the very first byte written invalidates the checksum. And when an item is added the very last byte written validates the checksum. So when autosave data is loaded, if the checksum is invalid it can safely be interpreted as "there's no item here." [1] I put "checksum" in quotes because I don't know what to call it. The pattern is much more regular than any checksum I've seen. Maybe it's more analogous to a "commit protocol" or something. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
When you place a tree, at least two things happen in the STGDAT file:
But how does the game know which 24-byte records belong to which chunks? Since the xyz coordinate is within the chunk, it must come from somewhere else.
Details of the 24B Record
The LSByte of the total number of 24B records is stored at 0024 E7CD. The 24B records begin near 0024 E???. It seems there is space reserved for up to 0xC8000 total records, meaning the records would end at (start + 24 * 0xC8000).
I'm not actually sure where one record ends and the next one starts, but it looks like the records align at 0029 5C01 (±24i). Assuming this alignment is correct, the contents of the record are:
xxxiiiii
wherexxx
is the lowest 3 bits of the 5-bit X coordinate (within the chunk, 0 <= X <= 31)iiiii
is the higher bits of the Item IDyyyyyyxx
whereyyyyyy
is the lowest 6 bits of the Y coordinate (0 <= Y <= 95)xx
is the highest 2 bits of the 5-bit X coordinate (within the chunk, 0 <= X <= 31)ddzzzzzy
wheredd
is the compass direction (NSEW)zzzzz
is the 5-bit Z coordinate (within the chunk, 0 <= Z <= 31)y
is the highest bit of the Y coordinate (when set, Y >= 64)Bytes 0-7 and 16-23 seem similar, and appear to be related to the internals of the data structure.
Beta Was this translation helpful? Give feedback.
All reactions