CavEX icon indicating copy to clipboard operation
CavEX copied to clipboard

Fix local player pointer randomly becoming corrupted after spawning an item

Open yyy257 opened this issue 1 year ago • 2 comments

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.

yyy257 avatar May 29 '24 07:05 yyy257

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

xtreme8000 avatar May 29 '24 10:05 xtreme8000

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.

yyy257 avatar May 29 '24 12:05 yyy257