"""Arma 3 process configuration: executables, ports, directory layout.""" class Arma3ProcessConfig: def get_allowed_executables(self) -> list[str]: return ["arma3server_x64.exe", "arma3server.exe"] def get_port_conventions(self, game_port: int) -> dict[str, int]: """ Arma 3 derives 3 additional ports from the game port. All 4 must be free when starting a server. rcon_port is separate (user-configurable, not auto-derived here). """ return { "game": game_port, "steam_query": game_port + 1, "von": game_port + 2, "steam_auth": game_port + 3, } def get_default_game_port(self) -> int: return 2302 def get_default_rcon_port(self, game_port: int) -> int | None: return game_port + 4 # e.g. 2306 for default game port def get_server_dir_layout(self) -> list[str]: """Subdirectories to create inside servers/{id}/.""" return ["server", "battleye", "mpmissions", "mods"] _DIR_READMES: dict[str, str] = { "server": ( "Arma 3 Server — Log Directory\n" "==============================\n\n" "Arma 3 writes RPT log files here (e.g. arma3server_2024-01-01_12-00-00.rpt).\n" "These are viewable in Languard's Logs tab.\n\n" "Do NOT place files here manually." ), "battleye": ( "BattlEye Anti-Cheat\n" "===================\n\n" "BattlEye configuration and GUID ban list files live here.\n" "Managed automatically by Arma 3 and Languard.\n\n" "Do NOT modify these files manually unless you know what you are doing." ), "mpmissions": ( "Mission Files\n" "=============\n\n" "Place Arma 3 mission files (.pbo) here to make them available for the server.\n" "Once placed here they will appear in Languard's Missions tab.\n\n" "Example: Wasteland_A3.Altis.pbo" ), "mods": ( "Mods\n" "====\n\n" "Place Arma 3 mod folders here. Each mod folder must start with '@'.\n\n" "Example layout:\n" " mods/\n" " @CBA_A3/\n" " addons/\n" " @ACE/\n" " addons/\n\n" "After placing mods here:\n" " 1. Go to the Mods tab in Languard.\n" " 2. Select the mods you want to enable.\n" " 3. Toggle 'Server-only' for mods that should use -serverMod= (e.g. task force radio server plugin).\n" " 4. Click 'Apply Selection'.\n" " 5. Restart the server for changes to take effect.\n\n" "Mods with a mod.cpp file will display their friendly name in the UI.\n" "Workshop mods with meta.cpp will show their Workshop ID." ), } def get_dir_readme(self, dir_name: str) -> str | None: return self._DIR_READMES.get(dir_name)