xtreme8000 / CavEX

Project to recreate your favourite block game for the Wii (Beta 1.7.3)
GNU General Public License v3.0
258 stars 23 forks source link

Fix local player pointer randomly becoming corrupted after spawning an item #45

Open yyy257 opened 4 months ago

yyy257 commented 4 months ago

Client-side entitites are tracked with an M*LIB dictionary, and inserting a new entity can shuffle other entities around in memory, including the local player:

Elements in the dictionary are unordered. On insertion of a new element, contained objects may moved.

Therefore, insertion of a new entity can randomly make gstate.local_player point to garbage data, usually getting the player stuck at X=0, Y=0 and Z=0, sometimes ending in a segmentation fault.

To fix it, I added a variable separate from the entity dictionary which tracks the local player ID, allowing updating gstate.local_player after spawning a new entity. As long as the game is singleplayer, the local player ID is always 0, but the variable may be useful when multiplayer is added.

xtreme8000 commented 4 months ago

Good spot! I think the best solution here would be to only store struct entity* pointers in the dict, instead of the whole object.

yyy257 commented 4 months ago

I also think that's a good idea, so I implemented it in a commit. It might not be the best implementation, but it seems to work - I hope it will be useful. This could even save memory, as dictionaries may use a temp array relative to the dictionary's size while resizing.

To reproduce the bug, I dug a lot of blocks without picking them up until the player data became corrupted. I could also reliably trigger it with the code in my fork that drops all items upon death.