Skip to content

Commit

Permalink
Automatically detect save directory (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
bostrt committed Feb 12, 2024
1 parent 4112688 commit 594f9eb
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 2 deletions.
49 changes: 49 additions & 0 deletions src/palworld_exporter/collectors/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from glob import glob
import logging
import os
import re

server_name_re = re.compile(r'^DedicatedServerName=(?P<name>.*?)$')

def find_server_name(filename: str) -> str | None:
with open(filename, 'r') as f:
for l in f.readlines():
m = server_name_re.search(l)
if m:
return m.group("name")


def find_save_directory(starting_dir: str) -> str:
# First, look for a single Level.sav
level_sav_search = os.path.join(starting_dir, "**/Level.sav")
result = glob(level_sav_search, recursive=True)
if len(result) == 1:
# Found a single result so let's use it
save_path = os.path.dirname(result[0])
logging.info(f"Found save directory: {save_path}")
return save_path
elif len(result) == 0:
logging.warning("No Level.sav found")
elif len(result) > 1:
logging.warning("Multiple Level.sav found")

logging.warning("Searching GameUserSettings.ini for save directory")

# Second, try using the GameUserSettings.ini to figure out the right
game_settings_search = os.path.join(starting_dir, "**/GameUserSettings.ini")
result = glob(game_settings_search, recursive=True)
if len(result) == 1:
# Found settings so identify the save directory name
server_name = find_server_name(result[0])
if server_name:
save_path_search = os.path.join(starting_dir, f"**/{server_name}")
save_path = glob(save_path_search, recursive=True)
if len(save_path) == 1:
logging.info(f"Found save directory: {save_path}")
return save_path[0]
else:
raise ValueError("Error automatically finding save directory")
elif len(result) == 0:
raise FileNotFoundError("No GameUserSettings.ini found")
elif len(result) > 1:
raise ValueError("Multiple GameUserSettings.ini found. Please use more specific directory.")
11 changes: 9 additions & 2 deletions src/palworld_exporter/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from palworld_exporter.collectors.rcon_collector import (RCONCollector,
RCONContext)
from palworld_exporter.collectors.save_meta_collector import SaveFileCollector
from palworld_exporter.collectors.util import find_save_directory

# Unregister default/built-in Python collectors
# https://prometheus.github.io/client_python/collector/#disabling-default-collector-metrics
Expand Down Expand Up @@ -40,10 +41,16 @@ def main(rcon_host: str,
level=log_level)

# Register all the collectors
if save_directory:
try:
actual_save_dir = find_save_directory(save_directory)
REGISTRY.register(SaveFileCollector(actual_save_dir))
except Exception as e:
logging.error(e)
return

rcon_ctx = RCONContext(rcon_host, rcon_port, rcon_password)
REGISTRY.register(RCONCollector(rcon_ctx, ignore_logging_in))
if save_directory:
REGISTRY.register(SaveFileCollector(save_directory))
start_http_server(port=listen_port, addr=listen_address)

logging.info(f'Listening on {listen_address}:{listen_port}')
Expand Down
51 changes: 51 additions & 0 deletions src/test/collectors/test_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import pytest
from pyfakefs.fake_filesystem_unittest import TestCase

from palworld_exporter.collectors.util import find_save_directory


class UtilTestCase(TestCase):
def setUp(self):
self.setUpPyfakefs()

def test_valid_direct_path(self):
dir = "/Pal/Saved/SaveGames/0/F0951AC10BED42C6B0EA92ACABB01E95"
self.fs.create_dir(dir)
self.fs.create_file(f"{dir}/Level.sav")

found = find_save_directory(dir)
assert found == dir

def test_valid_indirect_path(self):
dir = "/Pal/Saved/SaveGames/0/F0951AC10BED42C6B0EA92ACABB01E95"
self.fs.create_dir(dir)
self.fs.create_file(f"{dir}/Level.sav")

found = find_save_directory("/Pal")
assert found == dir

def test_valid_has_settings_ini(self):
dir = "/Pal"
save_dir = "/Pal/Saved/SaveGames/0/2FAAC44DFD3E4DA18C418EE1F577A560"
self.fs.create_dir(save_dir)
self.fs.create_file("/Pal/Saved/Config/LinuxServer/GameUserSettings.ini", contents="""
[/Script/Pal.PalGameLocalSettings]
AudioSettings=(Master=0.500000,BGM=1.000000,SE=1.000000,PalVoice=1.000000,HumanVoice=1.000000,Ambient=1.000000,UI=1.000000)
GraphicsLevel=None
DefaultGraphicsLevel=None
bRunedBenchMark=False
bHasAppliedUserSetting=False
DedicatedServerName=2FAAC44DFD3E4DA18C418EE1F577A560
""")

found = find_save_directory(dir)
assert save_dir == found



def test_invalid_no_settings_ini(self):
dir = "/empty/directory"
self.fs.create_dir(dir)

with pytest.raises(FileNotFoundError):
find_save_directory(dir)

0 comments on commit 594f9eb

Please sign in to comment.