DFHack / dfhack

Memory hacking library for Dwarf Fortress and a set of tools that use it
Other
1.88k stars 476 forks source link

findCivzonesAt() returns duplicate zone after world unload/load #2301

Closed Alex6544 closed 2 years ago

Alex6544 commented 2 years ago

I'm trying to use dfhack.buildings.findCivzonesAt in a lua script, and somehow I am getting two zones where there is supposed to be one. Also, I'm printing out the information and it's same id, type, pointer, everything. so I am thinking there might be a bug. The relevant piece of lua code is local civzones = dfhack.buildings.findCivzonesAt(guidm.getCursorPos()) if civzones then print("#civzones: ", #civzones) for x, y in pairs(civzones) do print("civzones", x, y, y.name, "id:", y.id, "type:", y.type) end end And the output is like

civzones: 2

civzones 1 <building_civzonest: 000001729D14C3B0> zone temple doren id: 4144 type: 9 civzones 2 <building_civzonest: 000001729D14C3B0> zone temple doren id: 4144 type: 9 And similar story for all zones I try

Oh, probably should add that it's 0.47.05-r6 from the PyLNP pack

myk002 commented 2 years ago

Looking at the code, it's not clear to me how this could happen. Since you said you're working in a script, I have to ask: you haven't changed any memory values directly in your game, have you? In particular, have you changed df.global.building_next_id? That might result in the same civzone being cached twice.

Alex6544 commented 2 years ago

In that save... honestly last few weeks tried so many things it's hard to say, although never touched any next_id things specifically. But I think I was able to reproduce a much cleaner case. This is what I just did: 1) move aside (rename) actual playthrough save 2) start anew, generate tiniest world, embark 3) immediately create zone, cursor over it, run this tiny simplified script: https://pastebin.com/diJSyCdW output is as expected

civzones: 1

civzones 1 <building_civzonest: 000001EFCC1A9740> zone 1 id: 1 type: 9 4) save -> main menu -> continue playing 5) try the script again - now I see this zone duplication problem

civzones: 2

civzones 1 <building_civzonest: 000001EFB66F3E60> zone 1 id: 1 type: 9 civzones 2 <building_civzonest: 000001EFB66F3E60> zone 1 id: 1 type: 9

Something save/load related?

myk002 commented 2 years ago

Thanks! I'll look into this. Actually, I think that gives me the answer. The cache is not properly cleared on world unload, so when you load a second time, it adds to the cache instead of replacing it. Thanks for helping me find that!

myk002 commented 2 years ago

After looking into this a bit more, the cause is slightly different from what I thought. we do clear our cache when a map is unloaded. The problem is just that we have a general buildings cache and a civzone-specific cache (they are separate because of the different qualities of civzones vs. "normal" buildings). The general buildings cache load was adding a duplicate copy of the civzone to the civzone cache. That's why you only get 2 items in the returned list, regardless of how many times you have saved/loaded the game.