Jump to content

Help editing map_p.bin on multiplayer

Recommended Posts

I'm hosting a small whitelisted PZ Server for just me and some friends.

While so far it's been a huge amount of fun with few issues, the occasional, multiplayer-specific issue has made me wish I could modify the data for my users' characters. For example one user was mobbed and infected due to latency making his client unresponsive.

After some digging I notice that the character data seems to be stored client-side in <USER_FOLDER>/Zomboid/Sandbox/<IP>_<USERNAME>/map_p.bin, and not on the server itself.

Having looked at the file in a hex editor it seems fairly easy to modify existing data. Changing the name or body parts is pretty trivial, but the problem I've run into is figure out which bit to flip or values to modify to be able to remove an infection.

I was wondering if any documentation exists for where that might be stored, or if someone with more coding experience than me might be able to figure it out and share the info?

Just to clarify, my goal here is correcting issues for my users that occurred as a result of Multiplayer bugs or limitations. I am very much against changing a save to undo something that was a user's own fault - if your stupidity kills you them then that's how it should be, but when an issue with the server is responsible for them losing items or a character then It's my responsibility to try and fix it.

Ultimately tools for that should be included for admins (and I know that build 25 is adding some fun admin stuff soon) but right now I'm just looking for a quick fix.

Share this post

Link to post
Share on other sites

No such documentation is available currently.


After a bit of digging I did find a bit of, albeit outdated, information that the maker a PZ singleplayer save editor had compiled and placed on github last summer. It's likely that the documentation is pretty outdated by now, but it was enough to get started.



With the help of a programming friend I tried to modify the player file with some success.


As far as we can make out each bodypart stores if it is infected or not (in a boolean). However removing the infection from there still leaves the symptoms in the player's stats as sickness and pain (in floats).



However for whatever reason the server seems to revert the character to being nauseous, and the symptoms resume, including all limbs being damaged. However the limbs don't revert to being flagged as having infection, and so It's likely that there is a value somewhere that we don't know about that that also determines if a character is infected.



If we can reliably figure out how to remove the infection I'll post some simple steps to follow.

Share this post

Link to post
Share on other sites

A final update:


We figured out that there was a 'time since infection' value that was re-applying the effects.


Interestingly enough, if you removed only the infection from the limb, then the timer stops counting. Your symptoms would remain static, but you wouldn't get any worse.


I think this actually has the potential to be a pretty neat mechanic: if you manage to remove the infection by some drastic means, like advanced medicine in a hospital or controlled amputation, then you will stop getting more sick, but you'll still have to live with the effects indefinitely.



In any case, after some deliberation we decided not to release the exact instructions on how to do this, since it does lend itself to abuse. To be clear, it's already very easy to reverse engineer the system, but I'd rather not encourage it. I am hoping that at some point the server will be authoritative over the player characters.

Share this post

Link to post
Share on other sites



I am having a similar issue, but my client crashed and when I reconnected, it was showing the "you died" sequence.  I'm looking through my map_p.bin file with HexEdit, and can't seem to find workable information.  I see item references, but no status references.  How did you guys go about editing the .bin to remove your status?

Here's an excerpt of what I'm working with:


Share this post

Link to post
Share on other sites

Stuck at having issues reading the PlayerTable (status) :\

Keep running into issues with parsing the name of the status.


This section:

(reference: https://github.com/lukezaa/PZEditor/blob/master/PZSaveInfo/PZSaveInfo/Documentation.txt#L118-L120)

(int (4 bytes)) PlayerTableLen - PlayerTable items count(array (? bytes)) PlayerTable - Player stats table{	(byte (1 byte)) Type - Type of object	Type 0:		(string (? bytes)) - Name		(string (? bytes)) - Value	Type 1:		(string (? bytes)) - Name		(double (8 bytes)) - Value}

I get an array of 10 statuses, but on the first status, it attempts to parse the name of the status and gets a byte length that is too long.  Pulling my hair out at this point :\


It seems the data architecture is slightly different than what is documented there, but I just can't figure it out..


(It's more of the puzzle to solve now, rather than worrying about fixing the bug)

Share this post

Link to post
Share on other sites

Made it through that section... Now stuck on parsing through the inventory table... I just can't seem to get the offset right...


This is the section of the documentation.  The .bin seems to be slightly different... ever so slightly...  I can't get the nested items (bags/containers) to filter through their contents..

(string (? bytes)) InvType - Invetory type(int (4 bytes)) InvExplored - ?? // this.bExplored = (input.getInt() == 1); //(int (4 bytes)) InvCount - Inventory items count(array (? bytes)) InvTable - Inventory{	(string (? bytes)) Item - Item	(int (4 bytes)) ItemUses - Item uses?	(byte (1 byte)) Control - Item table control byte	IF CONTROL == 1		(int (4 bytes)) ItemTableLen - ItemTable items count		(array (? bytes)) ItemTable - Item table		{				(byte (1 byte)) Type - Type of object			Type 0:				(string (? bytes)) - Name				(string (? bytes)) - Value			Type 1:				(string (? bytes)) - Name				(double (8 bytes)) - Value		}	ENDIF	(byte (1 byte)) Control - ??	IF CONTROL == 1		(float (4 bytes)) ItemUsedDelta - ??	ENDIF	(int (4 bytes)) ItemCondition - Item condition	(int (4 bytes)) ItemActive - Item active ?? // this.bExplored = (input.getInt() == 1); //}

Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...