Click PlayerProfile class on the left, looking through the code we found something interesting:
loadPlayerDataFromDisk
This function is super simple, we load a file from disk in path characters/<name>.fch
If you didn't read any binary file yet, don't worry i will explain this steps now:
Go to
C:\Users\<yourusername>\AppData\LocalLow\IronGate\ Valheim\characters
and you should see a file named <character_name>.fch
Open HXD and drop that file in there, you should get something like this:
Following the read file logic we read first 4 bytes, (those selected in blue), and store it in count (our data size).
We can check that this is correct if we put our cursor at the end of our 4 bytes, then we press CTRL + G and enter the first 4 bytes in reverse order.
In our example our data size is: 51 01 40 00 -> READ FROM RIGHT TO LEFT -> 00 40 01 51
This is due to endianess:
https://en.wikipedia.org/wiki/Endianness
I won't explain but basically you can read binary data in two ways, human way (from left to right) and machine way (from right to left)
Now following the code we should read 4 bytes again and read that data
We can see that last array of bytes has same length as count2 and its the end of the file, so we now have to know what those two are.
If we make a guess first data is player profile data and last 40 bytes is file checksum.
Moving on, we know that data contains player profile, so we need to edit our map data in order to reach our goal.
Time to go back to our loadPlayerFromDisk function
This could be a mess but trust me, it isnt a big deal. If you remember from previous step, first 4 bytes is data size, so we skip that bytes, now following this function we know that:
-> version type int (4 bytes)
-> x4 int values for player stats (16 bytes)
-> worldCount type int (4 bytes)
--- worldData Structure ---
->world_key type long (8 bytes)
-> have custom spawnpoint type byte (1 byte)
-> spawnPoint data (custom data value vector3 = x3 int values => 12 bytes)
-> haveLogout point (1 byte)
-> logoutVector (12 bytes)
-> haveDeathPoint (1 byte)
-> deathPointVector (12 bytes)
-> homePoint (12 bytes)
-> haveMapData (1 byte)
-> mapData --> (custom data value byteArray) -> size (4 bytes)
-> data (size bytes)
Now we know where our map data starts in our file, is time to do something with it, but first we need to know how this data is handled.
Remember our getMap data and set map data?, is time to use them.