banner
MuElnova

NoxA

Becoming a random anime guy... Pwner@天枢Dubhe/天璇Merak | BUPT CyberSecurity | INTP-A
email
github
bilibili
steam
twitter

Analysis of the Archive Structure of the Mythical Creature Palu

How to Convert Local Archives to Server Archives in Palworld#

image

Before Reading#

Please make sure you have some hands-on ability. Based on the assumption that you can start the server, the following text will assume that the reader can use Python3 and the terminal.

Prerequisites#

  • Python3
  • MuelNova/Palworld-Save-Patcher
  • The archive to be converted, referred to as %SAVE% in the following text, should be similar to the following structure:
%SAVE%
├── LevelMeta.sav
├── Level.sav
├── LocalData.sav
├── Players
│   ├── 00000000000000000000000000000001.sav
│   ├── PLAYER_B_GUID.sav
│   └── PLAYER_C_GUID.sav
└── WorldOption.sav

Version Information (Timeliness)#

Modification Process#

Extracting Server Archives#

First, make sure your server is fully started and copy the %SAVE% folder to the server archive location.

The original host logs into the game, and there should be a need to create a new user. At this time, create a new user and perform some operations before exiting.

At this point, there should be a new file in the %SAVE%/Players folder. This GUID is specific to each STEAM user, and we use 0D000721000000000000000000000001.sav to represent it.

%SAVE%
├── LevelMeta.sav
├── Level.sav
├── LocalData.sav
├── Players
│   ├── 00000000000000000000000000000001.sav
│   ├── PLAYER_B_GUID.sav
│   ├── 0D000721000000000000000000000001.sav
│   └── PLAYER_C_GUID.sav
└── WorldOption.sav

At this point, 0d000721000000000000000000000001 is the GUID of the original host.

Close the server and make sure you have backed up the %SAVE% folder.

Running the Script#

git clone https://github.com/MuelNova/Palworld-Save-Patcher.git
cd Palworld-Save-Patcher
python script.py fix-host %SAVE% %GUID%
# Replace with your own
# python script.py fix-host /home/nova/test_pal 0d000721000000000000000000000000

Restart the Server#

At this point, the original host should already have something, but the name and guild no longer exist. You need to join a friend's server to fix this. This is also a small flaw (because these contents exist in BYTE and it is not convenient to modify using uesave).

Principle#

This part can be skipped by those who are not interested.

Analysis of Archive Files#

Under %applocaldadta%\Pal\Saved\SavedGame\<STEAM_ID>\<WORLD_ID>

LocalData.sav#

Saves the map, unrelated to the user. You can directly copy it to another archive to skip the mapping process.

Level.sav#

Key file, saves all resources, their owners, and map events.

Player/xxxxxx.sav#

Player file

.sav Files#

Currently, only the modification method is known, not the principle. You can refer to this gist: Converting PalWorld saves to JSON and back (github.com).

First, for a .sav file, it is not a standard UE .sav file header, but a file compressed with zlib (or double compressed).

[0:4] is the uncompressed size.

[4:8] is the compressed size.

[8:11] is a fixed magicNumber "PlZ".

[11] is a type, which can have the following values: 0x30, 0x31, 0x32. Among them, 0x30 is not used yet. 0x31 is zlib compressed once, and 0x32 is zlib compressed twice.

[12:] is the compressed data.

After decompression, it becomes a GVAS file, which can be directly converted to a json file using tools like trumank/uesave-rs: Rust library to read and write Unreal Engine save files (github.com).

image-20240122100541443

uesave to-json --input <GUID>.sav.gvas --output <GUID>.sav.json
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.