Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to generate a WorldOption.sav file automatically in (mostly) bash #380

Conversation

sonroyaalmerol
Copy link
Contributor

@sonroyaalmerol sonroyaalmerol commented Feb 13, 2024

Context

  • A WorldOption.sav file is usually generated from a single player save and not a dedicated server. However, a dedicated server can still recognize the .sav file.
  • Some settings are limited in dedicated servers such as PVP and BaseCampWorkerMaxNum being locked at 15. Having an option to generate a WorldOption.sav file would allow these settings to be modified.
  • Currently, people are generating their WorldOption.sav files from this website. While this works, it would negate the purpose of having the settings as env vars in a Docker container as having the WorldOption.sav file would ignore the PalWorldSettings.ini file generated from those env vars. (Enable PVP or Set `BaseCampWorkerMaxNum` to 20 on a dedicated Server #293)

Choices

  • Unlike the previous PR (Add an option to generate a WorldOption.sav file automatically #337), this minimizes the Python code and removes the unnecessary parts for better maintainability. However, the script assumes that the generated PalWorldSettings.ini is always valid.
  • This script generates the WorldOption.sav file by:
    • Parsing configuration settings from a PalWorldSettings.ini file.
    • Converting the configuration settings into a JSON format suitable for palworld-save-tools.
    • Incorporating the generated JSON into the provided WorldOption.json.template.
    • Using an embedded Python script with palworld-save-tools to compress the JSON data into a WorldOption.sav file.
    • Writing the resulting .sav file to the appropriate directory within the game server's file structure.
  • The script would delete the existing WorldOption.sav file and generate a new one every boot to make sure it follows the current values of the Docker env vars.
  • GENERATE_WORLD_OPTION env var is added and is defaulted to false. Since the .sav file gets deleted every boot, having this env var to false would make sure that the PalWorldSettings.ini is used instead.

Test instructions

New server test:

  1. Started the container from scratch with default env vars and GENERATE_WORLD_OPTION=true. Check if it generates the .sav file (it shouldn't as the save folder does not exist at this point).
  2. Restart the container after the save folder has been initialized by the dedicated server.
  3. Check if it generates the .sav file.
  4. Test if it follows the default configurations.
  5. Modify env vars (ENABLE_PLAYER_TO_PLAYER_DAMAGE, IS_PVP, BASE_CAMP_WORKER_MAX_NUM, etc.)
  6. Restart the container and see if the changes persist.
  7. Modify env vars back to defaults.
  8. Restart the container and see if the changes persist.
  9. Set GENERATE_WORLD_OPTION to false.
  10. Restart the container if it reverts back to using PalWorldSettings.ini.

Existing server test:

  1. Started an existing container with BASE_CAMP_WORKER_MAX_NUM=20 (from the default 15) and GENERATE_WORLD_OPTION=true.
  2. Check if it generates the .sav file.
  3. Test if it follows the set configurations.
  4. Modify more env vars (ENABLE_PLAYER_TO_PLAYER_DAMAGE, IS_PVP, etc.)
  5. Restart the container and see if the changes persist.
  6. Modify env vars back to defaults.
  7. Restart the container and see if the changes persist.
  8. Set GENERATE_WORLD_OPTION to false.
  9. Restart the container if it reverts back to using PalWorldSettings.ini.

Checklist before requesting a review

  • I have performed a self-review of my code
  • I've added documentation about this change to the README.
  • I've not introduced breaking changes.

@sonroyaalmerol sonroyaalmerol marked this pull request as ready for review February 13, 2024 03:34
@gzukel
Copy link

gzukel commented Feb 13, 2024

We implemented this in our deployment of your stuff and we are seeing the following error:


***Using PalWorldSettings.ini to create WorldOption.sav***
Generating WorldOption.sav...
jq: invalid JSON text passed to --argjson
Use jq --help for help with command-line options,
or see the jq manpage, or online docs  at https://stedolan.github.io/jq
jq: invalid JSON text passed to --argjson
Use jq --help for help with command-line options,
or see the jq manpage, or online docs  at https://stedolan.github.io/jq
WorldOption Generator: Compressing WorldOption to .sav
Traceback (most recent call last):
  File "<string>", line 7, in <module>
  File "/usr/lib/python3.11/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)
WorldOption Generator: WorldOption.sav generation failed.
BACKUP_ENABLED=true
AUTO_UPDATE_ENABLED=true

well try to fix it as well but definitely seems like some of the jq stuff is failing causing a invalid json file that python can't open.

@sonroyaalmerol
Copy link
Contributor Author

Hi @gzukel, do you mind sharing the log with DEBUG env var set to true?

@gzukel
Copy link

gzukel commented Feb 13, 2024

xexport SERVER_NAME=\'${SERVER_NAME:-"Default Palworld Server"}\'
export SERVER_DESCRIPTION=\'${SERVER_DESCRIPTION:-""}\'
export ADMIN_PASSWORD=\'${ADMIN_PASSWORD:-""}\'
export SERVER_PASSWORD=\'${SERVER_PASSWORD:-""}\'
export PUBLIC_PORT=${PORT:-8211}
export PUBLIC_IP=\'${PUBLIC_IP:-""}\'
export RCON_ENABLED=${RCON_ENABLED:-False}
export RCON_PORT=${RCON_PORT:-25575}
export REGION=\'${REGION:-""}\'
export USEAUTH=${USEAUTH:-True}
export BAN_LIST_URL=\'${BAN_LIST_URL:-https://api.palworldgame.com/api/banlist.txt}\'

the double qoutes here was the issue, I changed to single qoutes and it fixed it.

Comment on lines +120 to +153
# Python script for converting JSON to .sav
convert_json_to_sav_python=$(
cat <<EOF
import sys
import json
from palworld_save_tools.gvas import GvasFile
from palworld_save_tools.palsav import compress_gvas_to_sav
from palworld_save_tools.paltypes import PALWORLD_CUSTOM_PROPERTIES

gvas_file = GvasFile.load(json.loads(sys.stdin.read()))
if ("Pal.PalWorldSaveGame" in gvas_file.header.save_game_class_name or "Pal.PalLocalWorldSaveGame" in gvas_file.header.save_game_class_name):
save_type = 0x32
else:
save_type = 0x31
sav_file = compress_gvas_to_sav(
gvas_file.write(PALWORLD_CUSTOM_PROPERTIES), save_type
)
sys.stdout.buffer.write(sav_file)
EOF
)

# Function to convert JSON to .sav
convert_json_to_sav() {
local json_data="$1"
local output_path="$2"

echo "WorldOption Generator: Compressing WorldOption to .sav"
if echo "$json_data" | python3 -c "$convert_json_to_sav_python" > "$output_path/WorldOption.sav"; then
echo "WorldOption Generator: Generated WorldOption.sav file to $output_path"
echo "Generating WorldOption.sav done!"
else
echo "WorldOption Generator: WorldOption.sav generation failed."
fi
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't include python code in this way.
Make a separate python file and call that.

@sonroyaalmerol
Copy link
Contributor Author

Closing PR due to its fragility and complexity. Will wait until I can think of a solution without adding an additional language to maintain before opening up another PR as we prefer to currently do things strictly in bash.

@sonroyaalmerol sonroyaalmerol deleted the generate-worldoptions-bash branch February 15, 2024 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants