Files
BarotraumaModServer/scripts/autogen_config.py

146 lines
4.3 KiB
Python
Executable File

#!/usr/bin/env python3
"""Generate config_player.xml from SERVER.xml mod list preserving load order."""
import os
import sys
import xml.etree.ElementTree as ET
MODLIST_PATH = "/mnt/nvme/B/SteamLibrary/steamapps/common/Barotrauma/ModLists/SERVER.xml"
LOCALMODS_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "LocalMods")
OUTPUT = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config_player.xml")
WORKSHOP_DIR = "/mnt/nvme/B/SteamLibrary/steamapps/workshop/content/602960"
def log_ok(msg: str, indent: int = 0):
prefix = " " * indent + "\033[92m✓\033[0m"
print(f"{prefix} {msg}")
def log_info(msg: str, indent: int = 0):
prefix = " " * indent + ""
print(f"{prefix} {msg}")
def log_warn(msg: str, indent: int = 0):
prefix = " " * indent + "\033[93m⚠\033[0m"
print(f"{prefix} {msg}")
def log_err(msg: str, indent: int = 0):
prefix = " " * indent + "\033[91m✗\033[0m"
print(f"{prefix} {msg}", file=sys.stderr)
def get_workshop_name(mod_id: str) -> str | None:
fl_path = os.path.join(WORKSHOP_DIR, mod_id, "filelist.xml")
if os.path.isfile(fl_path):
try:
return ET.parse(fl_path).getroot().get("name")
except Exception:
return None
return None
def find_mod_folder(name: str) -> str | None:
name_lower = name.lower()
if not os.path.isdir(LOCALMODS_DIR):
return None
for d in os.listdir(LOCALMODS_DIR):
if d.lower() == name_lower:
return d
return None
def resolve_mod_path(name: str, mod_id: str | None = None) -> str:
folder = find_mod_folder(name)
if folder and os.path.isfile(os.path.join(LOCALMODS_DIR, folder, "filelist.xml")):
return f"LocalMods/{folder}/filelist.xml"
if mod_id:
workshop_name = get_workshop_name(mod_id)
if workshop_name:
folder = find_mod_folder(workshop_name)
if folder and os.path.isfile(os.path.join(LOCALMODS_DIR, folder, "filelist.xml")):
return f"LocalMods/{folder}/filelist.xml"
return f"LocalMods/{name}/filelist.xml"
def main():
print()
print("╔══════════════════════════════════════════╗")
print("║ Autogen Config from SERVER.xml order ║")
print("╚══════════════════════════════════════════╝")
print()
if not os.path.isfile(MODLIST_PATH):
log_err(f"Mod list not found: {MODLIST_PATH}")
sys.exit(1)
log_info(f"Reading: {MODLIST_PATH}")
try:
tree = ET.parse(MODLIST_PATH)
root = tree.getroot()
except Exception as e:
log_err(f"Parse error: {e}")
sys.exit(1)
entries = list(root)
log_info(f"Total entries in mod list: {len(entries)}")
print()
resolved = []
missing = []
for el in entries:
tag = el.tag
if tag == "Vanilla":
continue
name = el.get("name", "").strip()
mod_id = el.get("id", "").strip() if tag == "Workshop" else None
if not name:
continue
path = resolve_mod_path(name, mod_id)
resolved.append(path)
full_path = os.path.join(os.path.dirname(OUTPUT), path)
if os.path.isfile(full_path):
log_ok(f"{name}", indent=1)
else:
missing.append(name)
log_warn(f"{name} — filelist.xml not found, adding anyway", indent=1)
print()
log_info(f"Mods resolved: {len([r for r in resolved if r])}")
if missing:
log_warn(f"Missing from LocalMods: {len(missing)}")
for m in missing:
log_info(f" {m}", indent=1)
print()
log_info("Generating config_player.xml...")
barotrauma = ET.Element("Barotrauma")
cps = ET.SubElement(barotrauma, "contentpackages")
ET.SubElement(cps, "corepackage", path="Content/ContentPackages/Vanilla.xml")
reg = ET.SubElement(cps, "regularpackages")
for r in resolved:
ET.SubElement(reg, "package", path=r)
ET.indent(barotrauma)
xml_str = ET.tostring(barotrauma, encoding="unicode", xml_declaration=True)
with open(OUTPUT, "w") as f:
f.write(xml_str)
log_ok(f"Written {OUTPUT}")
print()
if __name__ == "__main__":
main()