diff --git a/humanitz/README.md b/humanitz/README.md index 5efa0c27..d4d7cf94 100644 --- a/humanitz/README.md +++ b/humanitz/README.md @@ -1,30 +1,84 @@ # HumanitZ - ## [Documentation](https://store.steampowered.com/app/2728330/HZ_SERVER) +HumanitZ is a co-op, isometric, open world survival game in a world ended by the zombie outbreak. As one of the few human survivors, try to last as long as "humanly" possible. The past can't be changed, but you can make a difference today for the future of humanity. -HumanitZ is a co-op, isometric, open world survival game in a world ended by the zombie outbreak. As one of the few human survivors, try to last as long as “humanly” possible. The past can’t be changed, but you can make a difference today for the future of humanity. +## Install Notes -## Install notes +This egg provides comprehensive server configuration options for HumanitZ dedicated servers. All server settings can be configured through the Pterodactyl panel interface. -The current version of the server software is slightly buggy, and as of this writing has no proper documentation. +### Features +- Full server customization through environment variables +- RCON support for remote management +- Configurable difficulty settings for zombies, bandits, and animals +- Extensive loot rarity controls +- Weather system customization +- Building and decay mechanics +- Day/night cycle configuration +- Welcome message with color tag support -They include a `README.txt` file with the server software, that includes a description of most of the variables, but not more than that. This is only obtainable via the SteamCMD tool. +## Server Ports -## Installation/System Requirements +| Port | Default | Protocol | +|------------|---------|----------| +| Game Port | 7777 | UDP | +| Query Port | 27015 | UDP | +| RCON Port | 8888 | TCP | -Requires a 64-bit processor and operating system +**Note:** The game port can be customized to any available port. RCON is disabled by default and must be enabled in server settings. -## Server Ports +## Configuration + +### Boolean Values +All boolean settings use numeric values: +- `1` = Enabled/True +- `0` = Disabled/False + +### Key Settings + +#### Server Identity +- **Server Name**: Display name in the server browser +- **Server Password**: Optional password protection +- **Search ID**: Custom identifier for server grouping (changing hides server from default list) +- **Admin Password**: Use `/adminaccess ` in-game for admin privileges + +#### Difficulty Settings +Configure zombie, human bandit, and animal difficulty: +- **Health/Speed/Damage**: 0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare +- **Spawn Multipliers**: Adjust population (1=Default, 2=Double, 0.5=Half) +- **Respawn Timers**: Minutes until respawn (0=Disabled) + +#### Loot Configuration +- **Rarity Levels**: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant +- Categories: Food, Drink, Melee, Ranged, Ammo, Armor, Resources, Other +- **Loot Respawn**: Enable/disable with configurable timer (minutes) + +#### Survival Mechanics +- **PVP**: Player combat and item interaction +- **Perma Death**: Character loss on death +- **On Death Mode**: What items are lost (0=Nothing → 3=Everything) +- **Vital Drain**: Resource consumption rate (0=Slow, 1=Normal, 2=Fast) -Ports required to run the server in a table format. +#### World Settings +- **Day/Night Duration**: Real-time minutes for each cycle +- **Seasons**: Starting season and days per season +- **Weather Weights**: Customize spawn probability for each weather type +- **Time Freeze**: Pause time when server is empty -| Port | default | -|--------------|---------| -| Game Port | 7777 | -| Query Port | 27015 | +#### Building & Decay +- **Building Health**: Multiplier for player structures +- **Building Decay**: Real-life days until full decay (0=Disabled) +- **Territory Protection**: Prevent building in spawn point areas +- **Dismantle Options**: Allow players to remove their buildings/props -### Notes +#### Companion Animals +- **Dog Companions**: Enable/disable dog spawns +- **Recruit Dogs**: Allow food-based recruitment +- **Companion Stats**: Health and damage levels (0=Low, 1=Default, 2=High) -7777 is the default port, but any port can be used. +### Advanced Options +- **RCON**: Enable remote console for server management and ping display +- **AI Events**: Raid frequency (0=Disabled → 4=Insane) +- **Multiplayer Sleep**: Time advancement when all players sleep +- **Voice Chat**: In-game VoIP communication diff --git a/humanitz/egg-humanit-z.json b/humanitz/egg-humanit-z.json index 89ac486f..321c6cd5 100644 --- a/humanitz/egg-humanit-z.json +++ b/humanitz/egg-humanit-z.json @@ -1,552 +1,952 @@ { - "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", - "meta": { - "version": "PTDL_v2", - "update_url": null - }, - "exported_at": "2024-02-26T18:43:46+01:00", - "name": "HumanitZ", - "author": "engels74@marx.ps", - "description": "HumanitZ is a co-op, isometric, open world survival game in a world ended by the zombie outbreak. As one of the few human survivors, try to last as long as \u201chumanly\u201d possible. The past can\u2019t be changed, but you can make a difference today for the future of humanity.", - "features": null, - "docker_images": { - "ghcr.io\/ptero-eggs\/steamcmd:debian": "ghcr.io\/ptero-eggs\/steamcmd:debian" - }, - "file_denylist": [], - "startup": ".\/TSSGame\/Binaries\/Linux\/TSSGameServer-Linux-Shipping TSSGame -log -port={{SERVER_PORT}} -queryport={{QUERY_PORT}} -steamservername=\"{{SERVER_NAME}}\"", - "config": { - "files": "{\r\n \"TSSGame\/GameServerSettings.ini\": {\r\n \"parser\": \"ini\",\r\n \"find\": {\r\n \"[Host Settings].ServerName\": \"{{server.build.env.SERVER_NAME}}\",\r\n \"[Host Settings].Password\": \"{{server.build.env.PASSWORD}}\",\r\n \"[Host Settings].SaveName\": \"{{server.build.env.SAVE_NAME}}\",\r\n \"[Host Settings].AdminPass\": \"{{server.build.env.ADMIN_PASS}}\",\r\n \"[Host Settings].MaxPlayers\": \"{{server.build.env.MAX_PLAYERS}}\",\r\n \"[Host Settings].OnlyAllowedPlayers\": \"{{server.build.env.ONLY_ALLOWED_PLAYERS}}\",\r\n \"[World Settings].SaveIntervalSec\": \"{{server.build.env.SAVE_INTERVAL_SEC}}\",\r\n \"[World Settings].NoDeathFeedback\": \"{{server.build.env.NO_DEATH_FEEDBACK}}\",\r\n \"[World Settings].PermaDeath\": \"{{server.build.env.PERMA_DEATH}}\",\r\n \"[World Settings].OnDeath\": \"{{server.build.env.ON_DEATH}}\",\r\n \"[World Settings].PVP\": \"{{server.build.env.PVP}}\",\r\n \"[World Settings].ClearInfection\": \"{{server.build.env.CLEAR_INFECTION}}\",\r\n \"[World Settings].EagleEye\": \"{{server.build.env.EAGLE_EYE}}\",\r\n \"[World Settings].AirDrop\": \"{{server.build.env.AIR_DROP}}\",\r\n \"[World Settings].WeaponBreak\": \"{{server.build.env.WEAPON_BREAK}}\",\r\n \"[World Settings].MultiplayerSleep\": \"{{server.build.env.MULTIPLAYER_SLEEP}}\",\r\n \"[World Settings].LootRespawn\": \"{{server.build.env.LOOT_RESPAWN}}\",\r\n \"[World Settings].LootRespawnTimer\": \"{{server.build.env.LOOT_RESPAWN_TIMER}}\",\r\n \"[World Settings].PickupRespawnTimer\": \"{{server.build.env.PICKUP_RESPAWN_TIMER}}\",\r\n \"[World Settings].LootRarity\": \"{{server.build.env.LOOT_RARITY}}\",\r\n \"[World Settings].AirDropInterval\": \"{{server.build.env.AIR_DROP_INTERVAL}}\",\r\n \"[World Settings].ZombieDiffHealth\": \"{{server.build.env.ZOMBIE_DIFF_HEALTH}}\",\r\n \"[World Settings].ZombieDiffSpeed\": \"{{server.build.env.ZOMBIE_DIFF_SPEED}}\",\r\n \"[World Settings].ZombieDiffDamage\": \"{{server.build.env.ZOMBIE_DIFF_DAMAGE}}\",\r\n \"[World Settings].HumanDifficulty\": \"{{server.build.env.HUMAN_DIFFICULTY}}\",\r\n \"[World Settings].ZombieAmountMulti\": \"{{server.build.env.ZOMBIE_AMOUNT_MULTI}}\",\r\n \"[World Settings].HumanAmountMulti\": \"{{server.build.env.HUMAN_AMOUNT_MULTI}}\",\r\n \"[World Settings].ZombieDogMulti\": \"{{server.build.env.ZOMBIE_DOG_MULTI}}\",\r\n \"[World Settings].ZombieRespawnTimer\": \"{{server.build.env.ZOMBIE_RESPAWN_TIMER}}\",\r\n \"[World Settings].HumanRespawnTimer\": \"{{server.build.env.HUMAN_RESPAWN_TIMER}}\",\r\n \"[World Settings].AnimalRespawnTimer\": \"{{server.build.env.ANIMAL_RESPAWN_TIMER}}\",\r\n \"[World Settings].StartingSeason\": \"{{server.build.env.STARTING_SEASON}}\",\r\n \"[World Settings].DaysPerSeason\": \"{{server.build.env.DAYS_PER_SEASON}}\",\r\n \"[World Settings].DayDur\": \"{{server.build.env.DAY_DUR}}\",\r\n \"[World Settings].NightDur\": \"{{server.build.env.NIGHT_DUR}}\",\r\n \"[World Settings].VitalDrain\": \"{{server.build.env.VITAL_DRAIN}}\",\r\n \"[World Settings].DogEnabled\": \"{{server.build.env.DOG_ENABLED}}\",\r\n \"[World Settings].DogNum\": \"{{server.build.env.DOG_NUM}}\",\r\n \"[World Settings].RecruitDog\": \"{{server.build.env.RECRUIT_DOG}}\",\r\n \"[World Settings].BuildingHealth\": \"{{server.build.env.BUILDING_HEALTH}}\",\r\n \"[World Settings].CompanionHealth\": \"{{server.build.env.COMPANION_HEALTH}}\",\r\n \"[World Settings].CompanionDmg\": \"{{server.build.env.COMPANION_DMG}}\",\r\n \"[World Settings].AllowDismantle\": \"{{server.build.env.ALLOW_DISMANTLE}}\",\r\n \"[World Settings].AllowHouseDismantle\": \"{{server.build.env.ALLOW_HOUSE_DISMANTLE}}\",\r\n \"[World Settings].Territory\": \"{{server.build.env.TERRITORY}}\",\r\n \"[World Settings].Decay\": \"{{server.build.env.DECAY}}\",\r\n \"[World Settings].PickupCleanup\": \"{{server.build.env.PICKUP_CLEANUP}}\",\r\n \"[World Settings].FakeBuildingCleanup\": \"{{server.build.env.FAKE_BUILDING_CLEANUP}}\"\r\n }\r\n }\r\n}", - "startup": "{\r\n \"done\": \"LogKaiHelper: Session created!\"\r\n}", - "logs": "{}", - "stop": "^C" - }, - "scripts": { - "installation": { - "script": "#!\/bin\/bash\r\n# steamcmd Base Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n# Image to install with is 'ghcr.io\/ptero-eggs\/installers:debian'\r\n\r\n##\r\n#\r\n# Variables\r\n# STEAM_USER, STEAM_PASS, STEAM_AUTH - Steam user setup. If a user has 2fa enabled it will most likely fail due to timeout. Leave blank for anon install.\r\n# WINDOWS_INSTALL - if it's a windows server you want to install set to 1\r\n# SRCDS_APPID - steam app id found here - https:\/\/developer.valvesoftware.com\/wiki\/Dedicated_Servers_List\r\n# SRCDS_BETAID - beta branch of a steam app. Leave blank to install normal branch\r\n# SRCDS_BETAPASS - password for a beta branch should one be required during private or closed testing phases.. Leave blank for no password.\r\n# INSTALL_FLAGS - Any additional SteamCMD flags to pass during install.. Keep in mind that steamcmd auto update process in the docker image might overwrite or ignore these when it performs update on server boot.\r\n# AUTO_UPDATE - Adding this variable to the egg allows disabling or enabling automated updates on boot. Boolean value. 0 to disable and 1 to enable.\r\n#\r\n ##\r\n\r\n# Install packages. Default packages below are not required if using our existing install image thus speeding up the install process.\r\n#apt -y update\r\n#apt -y --no-install-recommends install curl lib32gcc-s1 ca-certificates\r\n\r\n## just in case someone removed the defaults.\r\nif [[ \"${STEAM_USER}\" == \"\" ]] || [[ \"${STEAM_PASS}\" == \"\" ]]; then\r\n echo -e \"steam user is not set.\\n\"\r\n echo -e \"Using anonymous user.\\n\"\r\n STEAM_USER=anonymous\r\n STEAM_PASS=\"\"\r\n STEAM_AUTH=\"\"\r\nelse\r\n echo -e \"user set to ${STEAM_USER}\"\r\nfi\r\n\r\n## download and install steamcmd\r\ncd \/tmp\r\nmkdir -p \/mnt\/server\/steamcmd\r\ncurl -sSL -o steamcmd.tar.gz https:\/\/steamcdn-a.akamaihd.net\/client\/installer\/steamcmd_linux.tar.gz\r\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\r\nmkdir -p \/mnt\/server\/steamapps # Fix steamcmd disk write error when this folder is missing\r\ncd \/mnt\/server\/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root \/mnt\r\nexport HOME=\/mnt\/server\r\n\r\n## install game using steamcmd\r\n.\/steamcmd.sh +force_install_dir \/mnt\/server +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} $( [[ \"${WINDOWS_INSTALL}\" == \"1\" ]] && printf %s '+@sSteamCmdForcePlatformType windows' ) +app_update ${SRCDS_APPID} $( [[ -z ${SRCDS_BETAID} ]] || printf %s \"-beta ${SRCDS_BETAID}\" ) $( [[ -z ${SRCDS_BETAPASS} ]] || printf %s \"-betapassword ${SRCDS_BETAPASS}\" ) ${INSTALL_FLAGS} validate +quit \r\n\r\n## set up 32 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk32\r\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so\r\n\r\n## set up 64 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk64\r\ncp -v linux64\/steamclient.so ..\/.steam\/sdk64\/steamclient.so\r\n\r\n## making server files executable\r\nchmod +x \/mnt\/server\/TSSGame\/Binaries\/Linux\/TSSGameServer-Linux-Shipping\r\n\r\n## install end\r\necho \"-----------------------------------------\"\r\necho \"Installation completed...\"\r\necho \"-----------------------------------------\"", - "container": "ghcr.io\/ptero-eggs\/installers:debian", - "entrypoint": "bash" - } - }, - "variables": [ - { - "name": "[REQUIRED] Steam App ID", - "description": "Steam App ID of HumanitZ Server", - "env_variable": "SRCDS_APPID", - "default_value": "2728330", - "user_viewable": false, - "user_editable": false, - "rules": "required|string|in:2728330", - "field_type": "text" - }, - { - "name": "Auto Update", - "description": "Enable automatic updates on boot", - "env_variable": "AUTO_UPDATE", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "[REQUIRED] Steam Beta Branch", - "description": "This ensures the script will grab the Linux version of the server", - "env_variable": "SRCDS_BETAID", - "default_value": "linuxbranch", - "user_viewable": false, - "user_editable": false, - "rules": "required|string|in:linuxbranch", - "field_type": "text" - }, - { - "name": "[REQUIRED] Steam Query Port", - "description": "Steam Query Port", - "env_variable": "QUERY_PORT", - "default_value": "27015", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Server Name", - "description": "Name of the server", - "env_variable": "SERVER_NAME", - "default_value": "HumanitZ [Dedicated]", - "user_viewable": true, - "user_editable": true, - "rules": "required|string", - "field_type": "text" - }, - { - "name": "Server Password", - "description": "Server password (if any)", - "env_variable": "PASSWORD", - "default_value": "", - "user_viewable": true, - "user_editable": true, - "rules": "nullable|string", - "field_type": "text" - }, - { - "name": "Save Name", - "description": "Name of the save-file for the server", - "env_variable": "SAVE_NAME", - "default_value": "DedicatedSaveMP", - "user_viewable": true, - "user_editable": true, - "rules": "required|string", - "field_type": "text" - }, - { - "name": "Admin Password", - "description": "Password for the admin", - "env_variable": "ADMIN_PASS", - "default_value": "", - "user_viewable": true, - "user_editable": true, - "rules": "nullable|string", - "field_type": "text" - }, - { - "name": "Max Players", - "description": "Maximum number of players allowed", - "env_variable": "MAX_PLAYERS", - "default_value": "16", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Only Allowed Players", - "description": "Restrict server to allowed players only", - "env_variable": "ONLY_ALLOWED_PLAYERS", - "default_value": "0", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Saving World Interval", - "description": "Save game every x seconds.", - "env_variable": "SAVE_INTERVAL_SEC", - "default_value": "300", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Permanent Death", - "description": "0=Off, 1=Individual perma-death, 2=All players experience perma-death", - "env_variable": "PERMA_DEATH", - "default_value": "0", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "On Death", - "description": "0=Only lose backpack, and weapon in hand, 1=Previous + pockets, and backpack, 2=All previous + Equipment", - "env_variable": "ON_DEATH", - "default_value": "2", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "PvP", - "description": "0\/1 Off\/On. Enable or disable Player vs Player.", - "env_variable": "PVP", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Clear Infection", - "description": "0=Respawning does not rid you of the infection, 1=You lose it upon respawning", - "env_variable": "CLEAR_INFECTION", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Eagle Eye", - "description": "1=Able to purchase the eagle eye skill, 0=You can't", - "env_variable": "EAGLE_EYE", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Air Drop", - "description": "1=Enabled, 0=Disabled. Controls whether air drops are enabled.", - "env_variable": "AIR_DROP", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Weapon Durability", - "description": "1=Weapons break when reaching 0% durability except crowbar, 0=Only improvised weapons break at 0% durability", - "env_variable": "WEAPON_BREAK", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Multiplayer Sleep", - "description": "1=Time passes if everyone performs the sleep emote at the same time, 0=Passing time is disabled", - "env_variable": "MULTIPLAYER_SLEEP", - "default_value": "0", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Building Health", - "description": "Health multiplier of player placed buildings. By default set to \"1\".", - "env_variable": "BUILDING_HEALTH", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Loot Respawn", - "description": "1=Loot does respawn, 0=Never respawn", - "env_variable": "LOOT_RESPAWN", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Loot Respawn Timer", - "description": "If loot respawns how long does it take in minutes", - "env_variable": "LOOT_RESPAWN_TIMER", - "default_value": "60", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Pickup Respawn Timer", - "description": "Time in minutes it takes to respawn pickups, 0 to disable.", - "env_variable": "PICKUP_RESPAWN_TIMER", - "default_value": "90", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Loot Rarity", - "description": "0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", - "env_variable": "LOOT_RARITY", - "default_value": "2", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Air Drop Interval", - "description": "Air drop every X day", - "env_variable": "AIR_DROP_INTERVAL", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Zombie Difficulty (Health)", - "description": "0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", - "env_variable": "ZOMBIE_DIFF_HEALTH", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Zombie Difficulty (Speed)", - "description": "0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", - "env_variable": "ZOMBIE_DIFF_SPEED", - "default_value": "2", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Zombie Difficulty (Damage)", - "description": "0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", - "env_variable": "ZOMBIE_DIFF_DAMAGE", - "default_value": "3", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Human Difficulty", - "description": "0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", - "env_variable": "HUMAN_DIFFICULTY", - "default_value": "3", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Zombie Amount Multiplier", - "description": "Zombie spawn count multiplier", - "env_variable": "ZOMBIE_AMOUNT_MULTI", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Human Amount Multiplier", - "description": "Hostile humans spawn count multiplier", - "env_variable": "HUMAN_AMOUNT_MULTI", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Zombie Dog Multiplier", - "description": "Zombie dog spawn count multiplier", - "env_variable": "ZOMBIE_DOG_MULTI", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Zombie Respawn Timer", - "description": "Time in minutes for zombies to respawn", - "env_variable": "ZOMBIE_RESPAWN_TIMER", - "default_value": "90", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Human Respawn Timer", - "description": "Time in minutes for hostile humans to respawn", - "env_variable": "HUMAN_RESPAWN_TIMER", - "default_value": "90", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Animal Respawn Timer", - "description": "Time in minutes for animals to respawn", - "env_variable": "ANIMAL_RESPAWN_TIMER", - "default_value": "90", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Starting Season", - "description": "0=Summer, 1=Autum, 2=Winter, 3=Spring", - "env_variable": "STARTING_SEASON", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Days Per Season", - "description": "How many days each season lasts", - "env_variable": "DAYS_PER_SEASON", - "default_value": "5", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Day Duration", - "description": "Day duration in minutes", - "env_variable": "DAY_DUR", - "default_value": "40", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Night Duration", - "description": "Night duration in minutes", - "env_variable": "NIGHT_DUR", - "default_value": "20", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Vital Drain", - "description": "How fast your vitals drain 0=Slow, 1=Normal, 2=Fast", - "env_variable": "VITAL_DRAIN", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Dog Companions Enabled", - "description": "Enable finding dog companions you can recruit", - "env_variable": "DOG_ENABLED", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Dog Companion Amount", - "description": "Number of companion dogs that could spawn randomly", - "env_variable": "DOG_NUM", - "default_value": "8", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Recruit Companion Dogs", - "description": "Allow players to recruit companion dog", - "env_variable": "RECRUIT_DOG", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Companion Health", - "description": "Dog companion health - 0=Low 1=Default 2=High", - "env_variable": "COMPANION_HEALTH", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Companion Damage", - "description": "Dog companion damage - 0=Low 1=Default 2=High", - "env_variable": "COMPANION_DMG", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "No Death Feedback", - "description": "0 to enable player died notification in chat - 1 to disable player died notification in chat.", - "env_variable": "NO_DEATH_FEEDBACK", - "default_value": "0", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Allow Dismantle", - "description": "1 = Enable players to dismantle their own buildings, 0 = Disable", - "env_variable": "ALLOW_DISMANTLE", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Allow House Dismantle", - "description": "1 = Players are able to dismantle house props, 0 = Disable", - "env_variable": "ALLOW_HOUSE_DISMANTLE", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Territory", - "description": "1 = Enabled. In PVE you are not allowed to build in someone's spawn point area. Only non recruit clan members can. 0 = Disable", - "env_variable": "TERRITORY", - "default_value": "1", - "user_viewable": true, - "user_editable": true, - "rules": "required|boolean", - "field_type": "text" - }, - { - "name": "Decay", - "description": "By default 3600, the crafted \"Spawn Point\" loses 1 durability every 1 hour. This is used to deal with territory build restrictions, so players have to repair their spawn point.", - "env_variable": "DECAY", - "default_value": "3600", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Pickup Cleanup", - "description": "How long in minutes it takes for dropped pickups to be destroyed (Pickups part of the world will not be considered), a value of 0 means no cleanup is done.", - "env_variable": "PICKUP_CLEANUP", - "default_value": "3000", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - }, - { - "name": "Fake Building Cleanup", - "description": "How long in minutes it takes for the white blueprint building to be destroyed, a value of 0 means no cleanup is done.", - "env_variable": "FAKE_BUILDING_CLEANUP", - "default_value": "3000", - "user_viewable": true, - "user_editable": true, - "rules": "required|numeric", - "field_type": "text" - } - ] + "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", + "meta": { + "version": "PTDL_v2", + "update_url": null + }, + "exported_at": "2026-02-28T23:29:46+01:00", + "name": "HumanitZ 1.02a", + "author": "game-tutos@icloud.com", + "description": "HumanitZ is a co-op, isometric, open world survival game in a world ended by the zombie outbreak. As one of the few human survivors, try to last as long as “humanly” possible. The past can’t be changed, but you can make a difference today for the future of humanity.", + "features": null, + "docker_images": { + "ghcr.io/ptero-eggs/steamcmd:debian": "ghcr.io/ptero-eggs/steamcmd:debian" + }, + "file_denylist": [], + "startup": "./HumanitZServer/Binaries/Linux/HumanitZServer-Linux-Shipping HumanitZServer -log -port={{SERVER_PORT}} -queryport={{QUERY_PORT}} -steamservername=\"{{SERVER_NAME}}\"", + "config": { + "files": "{\n \"HumanitZServer\\/GameServerSettings.ini\": {\n \"parser\": \"ini\",\n \"find\": {\n \"[Host Settings].ServerName\": \"{{server.build.env.SERVER_NAME}}\",\n \"[Host Settings].Password\": \"{{server.build.env.Password}}\",\n \"[Host Settings].SaveName\": \"{{server.build.env.SaveName}}\",\n \"[Host Settings].SearchID\": \"{{server.build.env.SearchID}}\",\n \"[Host Settings].AdminPass\": \"{{server.build.env.AdminPass}}\",\n \"[Host Settings].MaxPlayers\": \"{{server.build.env.MaxPlayers}}\",\n \"[Host Settings].ReserveSlots\": \"{{server.build.env.ReserveSlots}}\",\n \"[Host Settings].UseGlobalBanList\": \"{{server.build.env.UseGlobalBanList}}\",\n \"[Host Settings].RCONEnabled\": \"{{server.build.env.RCONEnabled}}\",\n \"[Host Settings].RConPort\": \"{{server.build.env.RConPort}}\",\n \"[Host Settings].RCONPass\": \"{{server.build.env.RCONPass}}\",\n \"[Host Settings].NoDeathFeedback\": \"{{server.build.env.NoDeathFeedback}}\",\n \"[Host Settings].NoJoinFeedback\": \"{{server.build.env.NoJoinFeedback}}\",\n \"[Host Settings].LimitedSpawns\": \"{{server.build.env.LimitedSpawns}}\",\n\n \"[World Settings].SaveIntervalSec\": \"{{server.build.env.SaveIntervalSec}}\",\n \"[World Settings].PermaDeath\": \"{{server.build.env.PermaDeath}}\",\n \"[World Settings].OnDeath\": \"{{server.build.env.OnDeath}}\",\n \"[World Settings].RespawnTimer\": \"{{server.build.env.RespawnTimer}}\",\n \"[World Settings].LogoutTimer\": \"{{server.build.env.LogoutTimer}}\",\n \"[World Settings].PVP\": \"{{server.build.env.PVP}}\",\n \"[World Settings].AirDrop\": \"{{server.build.env.AirDrop}}\",\n \"[World Settings].AirDropInterval\": \"{{server.build.env.AirDropInterval}}\",\n \"[World Settings].WeaponBreak\": \"{{server.build.env.WeaponBreak}}\",\n \"[World Settings].MaxOwnedCars\": \"{{server.build.env.MaxOwnedCars}}\",\n \"[World Settings].MultiplayerSleep\": \"{{server.build.env.MultiplayerSleep}}\",\n \"[World Settings].LootRespawn\": \"{{server.build.env.LootRespawn}}\",\n \"[World Settings].LootRespawnTimer\": \"{{server.build.env.LootRespawnTimer}}\",\n \"[World Settings].PickupRespawnTimer\": \"{{server.build.env.PickupRespawnTimer}}\",\n \"[World Settings].RarityFood\": \"{{server.build.env.RarityFood}}\",\n \"[World Settings].RarityDrink\": \"{{server.build.env.RarityDrink}}\",\n \"[World Settings].RarityMelee\": \"{{server.build.env.RarityMelee}}\",\n \"[World Settings].RarityRanged\": \"{{server.build.env.RarityRanged}}\",\n \"[World Settings].RarityAmmo\": \"{{server.build.env.RarityAmmo}}\",\n \"[World Settings].RarityArmor\": \"{{server.build.env.RarityArmor}}\",\n \"[World Settings].RarityResources\": \"{{server.build.env.RarityResources}}\",\n \"[World Settings].RarityOther\": \"{{server.build.env.RarityOther}}\",\n \"[World Settings].ZombieDiffHealth\": \"{{server.build.env.ZombieDiffHealth}}\",\n \"[World Settings].ZombieDiffSpeed\": \"{{server.build.env.ZombieDiffSpeed}}\",\n \"[World Settings].ZombieDiffDamage\": \"{{server.build.env.ZombieDiffDamage}}\",\n \"[World Settings].ZombieAmountMulti\": \"{{server.build.env.ZombieAmountMulti}}\",\n \"[World Settings].HumanAmountMulti\": \"{{server.build.env.HumanAmountMulti}}\",\n \"[World Settings].ZombieDogMulti\": \"{{server.build.env.ZombieDogMulti}}\",\n \"[World Settings].ZombieRespawnTimer\": \"{{server.build.env.ZombieRespawnTimer}}\",\n \"[World Settings].HumanRespawnTimer\": \"{{server.build.env.HumanRespawnTimer}}\",\n \"[World Settings].AnimalRespawnTimer\": \"{{server.build.env.AnimalRespawnTimer}}\",\n \"[World Settings].StartingSeason\": \"{{server.build.env.StartingSeason}}\",\n \"[World Settings].DaysPerSeason\": \"{{server.build.env.DaysPerSeason}}\",\n \"[World Settings].DayDur\": \"{{server.build.env.DayDur}}\",\n \"[World Settings].NightDur\": \"{{server.build.env.NightDur}}\",\n \"[World Settings].VitalDrain\": \"{{server.build.env.VitalDrain}}\",\n \"[World Settings].XpMultiplier\": \"{{server.build.env.XpMultiplier}}\",\n \"[World Settings].DogEnabled\": \"{{server.build.env.DogEnabled}}\",\n \"[World Settings].DogNum\": \"{{server.build.env.DogNum}}\",\n \"[World Settings].RecruitDog\": \"{{server.build.env.RecruitDog}}\",\n \"[World Settings].BuildingHealth\": \"{{server.build.env.BuildingHealth}}\",\n \"[World Settings].CompanionHealth\": \"{{server.build.env.CompanionHealth}}\",\n \"[World Settings].CompanionDmg\": \"{{server.build.env.CompanionDmg}}\",\n \"[World Settings].AllowDismantle\": \"{{server.build.env.AllowDismantle}}\",\n \"[World Settings].AllowHouseDismantle\": \"{{server.build.env.AllowHouseDismantle}}\",\n \"[World Settings].FreeBuild\": \"{{server.build.env.FreeBuild}}\",\n \"[World Settings].NoBuildZone\": \"{{server.build.env.NoBuildZone}}\",\n \"[World Settings].Territory\": \"{{server.build.env.Territory}}\",\n \"[World Settings].Decay\": \"{{server.build.env.Decay}}\",\n \"[World Settings].BuildingDecay\": \"{{server.build.env.BuildingDecay}}\",\n \"[World Settings].PickupCleanup\": \"{{server.build.env.PickupCleanup}}\",\n \"[World Settings].FakeBuildingCleanup\": \"{{server.build.env.FakeBuildingCleanup}}\",\n \"[World Settings].FoodDecay\": \"{{server.build.env.FoodDecay}}\",\n \"[World Settings].GenFuel\": \"{{server.build.env.GenFuel}}\",\n \"[World Settings].Sleep\": \"{{server.build.env.Sleep}}\",\n \"[World Settings].FreezeTime\": \"{{server.build.env.FreezeTime}}\",\n \"[World Settings].Seg0\": \"{{server.build.env.Seg0}}\",\n \"[World Settings].Seg1\": \"{{server.build.env.Seg1}}\",\n \"[World Settings].Seg2\": \"{{server.build.env.Seg2}}\",\n \"[World Settings].Voip\": \"{{server.build.env.Voip}}\",\n \"[World Settings].AIEvent\": \"{{server.build.env.AIEvent}}\",\n \"[World Settings].Weather_ClearSky\": \"{{server.build.env.Weather_ClearSky}}\",\n \"[World Settings].Weather_Cloudy\": \"{{server.build.env.Weather_Cloudy}}\",\n \"[World Settings].Weather_Foggy\": \"{{server.build.env.Weather_Foggy}}\",\n \"[World Settings].Weather_LightRain\": \"{{server.build.env.Weather_LightRain}}\",\n \"[World Settings].Weather_Rain\": \"{{server.build.env.Weather_Rain}}\",\n \"[World Settings].Weather_Thunderstorm\": \"{{server.build.env.Weather_Thunderstorm}}\",\n \"[World Settings].Weather_LightSnow\": \"{{server.build.env.Weather_LightSnow}}\",\n \"[World Settings].Weather_Snow\": \"{{server.build.env.Weather_Snow}}\",\n \"[World Settings].Weather_Blizzard\": \"{{server.build.env.Weather_Blizzard}}\"\n }\n }\n}", + "startup": "{\r\n \"done\": \"LogKaiHelper: Session created!\"\r\n}", + "logs": "{}", + "stop": "^C" + }, + "scripts": { + "installation": { + "script": "#!/bin/bash\r\n# steamcmd Base Installation Script\r\n#\r\n# Server Files: /mnt/server\r\n# Image to install with is 'ghcr.io/ptero-eggs/installers:debian'\r\n\r\n##\r\n#\r\n# Variables\r\n# STEAM_USER, STEAM_PASS, STEAM_AUTH - Steam user setup. If a user has 2fa enabled it will most likely fail due to timeout. Leave blank for anon install.\r\n# WINDOWS_INSTALL - if it's a windows server you want to install set to 1\r\n# SRCDS_APPID - steam app id found here - https://developer.valvesoftware.com/wiki/Dedicated_Servers_List\r\n# SRCDS_BETAID - beta branch of a steam app. Leave blank to install normal branch\r\n# SRCDS_BETAPASS - password for a beta branch should one be required during private or closed testing phases.. Leave blank for no password.\r\n# INSTALL_FLAGS - Any additional SteamCMD flags to pass during install.. Keep in mind that steamcmd auto update process in the docker image might overwrite or ignore these when it performs update on server boot.\r\n# AUTO_UPDATE - Adding this variable to the egg allows disabling or enabling automated updates on boot. Boolean value. 0 to disable and 1 to enable.\r\n#\r\n ##\r\n\r\n# Install packages. Default packages below are not required if using our existing install image thus speeding up the install process.\r\n#apt -y update\r\n#apt -y --no-install-recommends install curl lib32gcc-s1 ca-certificates\r\n\r\n## just in case someone removed the defaults.\r\nif [[ \"${STEAM_USER}\" == \"\" ]] || [[ \"${STEAM_PASS}\" == \"\" ]]; then\r\n echo -e \"steam user is not set.\\n\"\r\n echo -e \"Using anonymous user.\\n\"\r\n STEAM_USER=anonymous\r\n STEAM_PASS=\"\"\r\n STEAM_AUTH=\"\"\r\nelse\r\n echo -e \"user set to ${STEAM_USER}\"\r\nfi\r\n\r\n## download and install steamcmd\r\ncd /tmp\r\nmkdir -p /mnt/server/steamcmd\r\ncurl -sSL -o steamcmd.tar.gz https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz\r\ntar -xzvf steamcmd.tar.gz -C /mnt/server/steamcmd\r\nmkdir -p /mnt/server/steamapps # Fix steamcmd disk write error when this folder is missing\r\ncd /mnt/server/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root /mnt\r\nexport HOME=/mnt/server\r\n\r\n## install game using steamcmd\r\n./steamcmd.sh +force_install_dir /mnt/server +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} $( [[ \"${WINDOWS_INSTALL}\" == \"1\" ]] && printf %s '+@sSteamCmdForcePlatformType windows' ) +app_update ${SRCDS_APPID} $( [[ -z ${SRCDS_BETAID} ]] || printf %s \"-beta ${SRCDS_BETAID}\" ) $( [[ -z ${SRCDS_BETAPASS} ]] || printf %s \"-betapassword ${SRCDS_BETAPASS}\" ) ${INSTALL_FLAGS} validate +quit \r\n\r\n## set up 32 bit libraries\r\nmkdir -p /mnt/server/.steam/sdk32\r\ncp -v linux32/steamclient.so ../.steam/sdk32/steamclient.so\r\n\r\n## set up 64 bit libraries\r\nmkdir -p /mnt/server/.steam/sdk64\r\ncp -v linux64/steamclient.so ../.steam/sdk64/steamclient.so\r\n\r\n## making server files executable\r\nchmod +x /mnt/server/HumanitZServer/Binaries/Linux/HumanitZServer-Linux-Shipping\r\n\r\n## install end\r\necho \"-----------------------------------------\"\r\necho \"Installation completed...\"\r\necho \"-----------------------------------------\"", + "container": "ghcr.io/ptero-eggs/installers:debian", + "entrypoint": "bash" + } + }, + "variables": [ + { + "name": "[REQUIRED] Steam App ID", + "description": "Steam App ID of HumanitZ Server", + "env_variable": "SRCDS_APPID", + "default_value": "2728330", + "user_viewable": false, + "user_editable": false, + "rules": "required|string|in:2728330", + "field_type": "text" + }, + { + "name": "Auto Update", + "description": "Enable automatic updates on boot (1 = enabled, 0 = disabled)", + "env_variable": "AUTO_UPDATE", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "[REQUIRED] Steam Beta Branch", + "description": "This ensures the script will grab the Linux version of the server", + "env_variable": "SRCDS_BETAID", + "default_value": "linuxbranch", + "user_viewable": false, + "user_editable": false, + "rules": "required|string|in:linuxbranch", + "field_type": "text" + }, + { + "name": "[REQUIRED] Steam Query Port", + "description": "Port used by Steam to query server information", + "env_variable": "QUERY_PORT", + "default_value": "27015", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Server Name", + "description": "The display name of your server in the server browser", + "env_variable": "SERVER_NAME", + "default_value": "HumanitZ [Dedicated]", + "user_viewable": true, + "user_editable": true, + "rules": "required|string", + "field_type": "text" + }, + { + "name": "Server Password", + "description": "Password required to join the server (leave empty for no password)", + "env_variable": "Password", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string", + "field_type": "text" + }, + { + "name": "Save Name", + "description": "Name of the save file for this server, Avoid using the word \"Official\" in your server name or your server may not start or showup in the server list.", + "env_variable": "SaveName", + "default_value": "DedicatedSaveMP", + "user_viewable": true, + "user_editable": true, + "rules": "required|string", + "field_type": "text" + }, + { + "name": "Search ID", + "description": "Custom search identifier for grouping servers. Changing from default will hide server from standard server list", + "env_variable": "SearchID", + "default_value": "HumanitZ_Dedicated", + "user_viewable": true, + "user_editable": true, + "rules": "required|string", + "field_type": "text" + }, + { + "name": "Admin Password", + "description": "Password for admin access. Use /adminaccess in-game to gain admin privileges", + "env_variable": "AdminPass", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string", + "field_type": "text" + }, + { + "name": "Max Players", + "description": "Maximum number of players allowed on the server simultaneously", + "env_variable": "MaxPlayers", + "default_value": "16", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Reserve Slots", + "description": "Reserve slots for specific players listed in F_ReservedSlots.txt (0 = disabled)", + "env_variable": "ReserveSlots", + "default_value": "0", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Use Global Ban List", + "description": "Use the global ban list for banning known offenders (1 = enabled, 0 = disabled)", + "env_variable": "UseGlobalBanList", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "RCON Enabled", + "description": "Enable remote console for executing commands via RCON-compatible programs. Also displays server ping in browser (1 = enabled, 0 = disabled)", + "env_variable": "RCONEnabled", + "default_value": "0", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "RCON Port", + "description": "TCP port for RCON connections", + "env_variable": "RConPort", + "default_value": "8888", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "RCON Password", + "description": "Password required for RCON authentication", + "env_variable": "RCONPass", + "default_value": "", + "user_viewable": true, + "user_editable": true, + "rules": "nullable|string", + "field_type": "text" + }, + { + "name": "No Death Feedback", + "description": "Disable death notifications for players. Admins can still see them (1 = disabled/not visible, 0 = enabled)", + "env_variable": "NoDeathFeedback", + "default_value": "0", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "No Join Feedback", + "description": "Disable join/leave notifications for players. Admins can still see them (1 = disabled/not visible, 0 = enabled)", + "env_variable": "NoJoinFeedback", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Limited Spawns", + "description": "Restrict players to random coast spawns and spawn points only (1 = enabled, 0 = disabled)", + "env_variable": "LimitedSpawns", + "default_value": "0", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Save Interval Seconds", + "description": "Interval in seconds between automatic world saves (0 = disabled)", + "env_variable": "SaveIntervalSec", + "default_value": "300", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Perma Death", + "description": "Players lose their character permanently on death and must create a new one (1 = enabled, 0 = disabled)", + "env_variable": "PermaDeath", + "default_value": "0", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "On Death Mode", + "description": "What items are lost on death: 0=Nothing, 1=Backpack+Weapon, 2=Previous+Pockets, 3=Everything", + "env_variable": "OnDeath", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Respawn Timer", + "description": "Time in seconds before players can respawn after death", + "env_variable": "RespawnTimer", + "default_value": "15", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Logout Timer", + "description": "Time in seconds before player can log out while PVP is enabled (0 = disabled)", + "env_variable": "LogoutTimer", + "default_value": "30", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "PVP", + "description": "Enable player vs player combat and interaction with other players' items (cars, containers, etc.) (1 = enabled, 0 = disabled)", + "env_variable": "PVP", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Air Drop", + "description": "Enable air drop events on the server (1 = enabled, 0 = disabled)", + "env_variable": "AirDrop", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Air Drop Interval", + "description": "Number of in-game days between air drop events", + "env_variable": "AirDropInterval", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weapon Break", + "description": "Weapons break and are removed from inventory when durability reaches 0% (1 = enabled, 0 = disabled)", + "env_variable": "WeaponBreak", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Max Owned Cars", + "description": "Maximum number of cars a player can own. Unowned cars can be looted but not driven", + "env_variable": "MaxOwnedCars", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Multiplayer Sleep", + "description": "Allow time to pass when all players use the sleep emote simultaneously (1 = enabled, 0 = disabled)", + "env_variable": "MultiplayerSleep", + "default_value": "0", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Loot Respawn", + "description": "Enable loot respawning in the world (1 = enabled, 0 = disabled)", + "env_variable": "LootRespawn", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Loot Respawn Timer", + "description": "Time in minutes for loot containers to respawn (requires Loot Respawn enabled)", + "env_variable": "LootRespawnTimer", + "default_value": "60", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Pickup Respawn Timer", + "description": "Time in minutes for pickup items to respawn (requires Loot Respawn enabled)", + "env_variable": "PickupRespawnTimer", + "default_value": "90", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Rarity Food", + "description": "Food spawn rarity: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", + "env_variable": "RarityFood", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Rarity Drink", + "description": "Drink spawn rarity: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", + "env_variable": "RarityDrink", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Rarity Melee", + "description": "Melee weapon spawn rarity: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", + "env_variable": "RarityMelee", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Rarity Ranged", + "description": "Ranged weapon spawn rarity: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", + "env_variable": "RarityRanged", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Rarity Ammo", + "description": "Ammunition spawn rarity: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", + "env_variable": "RarityAmmo", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Rarity Armor", + "description": "Armor spawn rarity: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", + "env_variable": "RarityArmor", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Rarity Resources", + "description": "Resources spawn rarity: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", + "env_variable": "RarityResources", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Rarity Other", + "description": "Other items spawn rarity: 0=Scarce, 1=Low, 2=Default, 3=Plentiful, 4=Abundant", + "env_variable": "RarityOther", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "ZombieDiffHealth", + "description": "Zombie health difficulty: 0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", + "env_variable": "ZombieDiffHealth", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "ZombieDiffSpeed", + "description": "Zombie speed difficulty: 0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", + "env_variable": "ZombieDiffSpeed", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "ZombieDiffDamage", + "description": "Zombie damage difficulty: 0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", + "env_variable": "ZombieDiffDamage", + "default_value": "3", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "ZombieAmountMulti", + "description": "Zombie spawn multiplier (1=Default, 2=Double, 0.5=Half)", + "env_variable": "ZombieAmountMulti", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "HumanAmountMulti", + "description": "Human bandit spawn multiplier (1=Default, 2=Double, 0.5=Half)", + "env_variable": "HumanAmountMulti", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "ZombieDogMulti", + "description": "Zombie dog spawn multiplier, mainly appear at night (1=Default, 2=Double, 0.5=Half)", + "env_variable": "ZombieDogMulti", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "ZombieRespawnTimer", + "description": "Time in minutes for zombies to respawn (0 = disabled)", + "env_variable": "ZombieRespawnTimer", + "default_value": "90", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "HumanRespawnTimer", + "description": "Time in minutes for human bandits to respawn (0 = disabled)", + "env_variable": "HumanRespawnTimer", + "default_value": "90", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "HumanHealth", + "description": "Human bandit health difficulty: 0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", + "env_variable": "HumanHealth", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "HumanSpeed", + "description": "Human bandit speed difficulty: 0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", + "env_variable": "HumanSpeed", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "HumanDamage", + "description": "Human bandit damage difficulty: 0=Very Easy, 1=Easy, 2=Default, 3=Hard, 4=Very Hard, 5=Nightmare", + "env_variable": "HumanDamage", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "AnimalMulti", + "description": "Animal spawn multiplier (1=Default, 2=Double, 0.5=Half)", + "env_variable": "AnimalMulti", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "AnimalRespawnTimer", + "description": "Time in minutes for animals to respawn (0 = disabled)", + "env_variable": "AnimalRespawnTimer", + "default_value": "90", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "StartingSeason", + "description": "Initial season: 0=Summer, 1=Autumn, 2=Winter, 3=Spring", + "env_variable": "StartingSeason", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "DaysPerSeason", + "description": "Number of in-game days per season", + "env_variable": "DaysPerSeason", + "default_value": "5", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "DayDur", + "description": "Daytime duration in real-time minutes", + "env_variable": "DayDur", + "default_value": "40", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "NightDur", + "description": "Nighttime duration in real-time minutes", + "env_variable": "NightDur", + "default_value": "20", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "VitalDrain", + "description": "Vital stats drain rate: 0=Slow, 1=Normal, 2=Fast", + "env_variable": "VitalDrain", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "XP Multiplier", + "description": "Multiplier for player experience gain (1 = default, 2 = double, 0.5 = half)", + "env_variable": "XpMultiplier", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "DogEnabled", + "description": "Enable dog companions that can be found and recruited (1 = enabled, 0 = disabled)", + "env_variable": "DogEnabled", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "RecruitDog", + "description": "Allow players to recruit companion dogs by dropping food and claiming them (1 = enabled, 0 = disabled)", + "env_variable": "RecruitDog", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "DogNum", + "description": "Maximum number of companion dogs spawned in the world (respawn automatically)", + "env_variable": "DogNum", + "default_value": "8", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "BuildingHealth", + "description": "Health multiplier for player-placed buildings (1=Default, 2=Double)", + "env_variable": "BuildingHealth", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "CompanionHealth", + "description": "Dog companion health level: 0=Low, 1=Default, 2=High", + "env_variable": "CompanionHealth", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "CompanionDmg", + "description": "Dog companion damage level: 0=Low, 1=Default, 2=High", + "env_variable": "CompanionDmg", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "AllowDismantle", + "description": "Allow players to dismantle their own buildings (1 = enabled, 0 = disabled)", + "env_variable": "AllowDismantle", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "AllowHouseDismantle", + "description": "Allow players to dismantle house props (1 = enabled, 0 = disabled)", + "env_variable": "AllowHouseDismantle", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Free Build", + "description": "Experimental: when true, some buildables no longer require a foundation", + "env_variable": "FreeBuild", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "No Build Zone", + "description": "When true, players are not allowed to build in certain zones", + "env_variable": "NoBuildZone", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Territory", + "description": "Prevent building in spawn point areas. Clans: only non-recruit members can build (1 = enabled, 0 = disabled)", + "env_variable": "Territory", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Decay", + "description": "Number of real-life days for spawn points to decay from 100% to destroyed", + "env_variable": "Decay", + "default_value": "7", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "BuildingDecay", + "description": "Number of real-life days for player buildings to fully decay (0 = disabled)", + "env_variable": "BuildingDecay", + "default_value": "7", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "PickupCleanup", + "description": "Number of in-game days until dropped items are automatically destroyed", + "env_variable": "PickupCleanup", + "default_value": "6", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "FakeBuildingCleanup", + "description": "Time in minutes until blueprint buildings (white) are automatically destroyed", + "env_variable": "FakeBuildingCleanup", + "default_value": "3000", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "FoodDecay", + "description": "Food decay multiplier: 0=Disabled, 1=Default, 0.5=Half speed, 2=Double speed", + "env_variable": "FoodDecay", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "GenFuel", + "description": "Generator fuel consumption multiplier: 1=Default, 0.5=Half speed, 2=Double speed (range: 0.01-4)", + "env_variable": "GenFuel", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Sleep", + "description": "Enable sleep deprivation effects (1 = enabled, 0 = disabled)", + "env_variable": "Sleep", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "FreezeTime", + "description": "Pause time progression when server is empty (1 = enabled, 0 = disabled)", + "env_variable": "FreezeTime", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "Voip", + "description": "Enable voice chat (1 = enabled, 0 = disabled)", + "env_variable": "Voip", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean", + "field_type": "text" + }, + { + "name": "AIEvent", + "description": "AI raid event frequency (zombies/bandits attacking): 0=Disabled, 1=Low, 2=Default, 3=High, 4=Insane", + "env_variable": "AIEvent", + "default_value": "2", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_ClearSky", + "description": "Weather spawn weight for Clear Sky (season restrictions still apply)", + "env_variable": "Weather_ClearSky", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_Cloudy", + "description": "Weather spawn weight for Cloudy (season restrictions still apply)", + "env_variable": "Weather_Cloudy", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_Foggy", + "description": "Weather spawn weight for Fog (season restrictions still apply)", + "env_variable": "Weather_Foggy", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_LightRain", + "description": "Weather spawn weight for Light Rain (season restrictions still apply)", + "env_variable": "Weather_LightRain", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_Rain", + "description": "Weather spawn weight for Rain (season restrictions still apply)", + "env_variable": "Weather_Rain", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_Thunderstorm", + "description": "Weather spawn weight for Thunderstorm (season restrictions still apply)", + "env_variable": "Weather_Thunderstorm", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_LightSnow", + "description": "Weather spawn weight for Light Snow (season restrictions still apply)", + "env_variable": "Weather_LightSnow", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_Snow", + "description": "Weather spawn weight for Snow (season restrictions still apply)", + "env_variable": "Weather_Snow", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Weather_Blizzard", + "description": "Weather spawn weight for Blizzard (season restrictions still apply)", + "env_variable": "Weather_Blizzard", + "default_value": "1", + "user_viewable": true, + "user_editable": true, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Seg0", + "description": "Map is divided into 3 segments, objects that need to spawmn reasonabiliy far are put in Seg0 like houses.", + "env_variable": "Seg0", + "default_value": "8", + "user_viewable": false, + "user_editable": false, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Seg1", + "description": "Broken cars and other similar objects are put in Seg1.", + "env_variable": "Seg1", + "default_value": "12", + "user_viewable": false, + "user_editable": false, + "rules": "required|numeric", + "field_type": "text" + }, + { + "name": "Seg2", + "description": "Spawn distance performance segment.", + "env_variable": "Seg2", + "default_value": "20", + "user_viewable": false, + "user_editable": false, + "rules": "required|numeric", + "field_type": "text" + } + ] } \ No newline at end of file diff --git a/humanitz/rcon_probe.py b/humanitz/rcon_probe.py new file mode 100644 index 00000000..d5d56447 --- /dev/null +++ b/humanitz/rcon_probe.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python3 +import argparse +import random +import socket +import struct +import sys +import time +from dataclasses import dataclass +from typing import List + + +SERVERDATA_RESPONSE_VALUE = 0 +SERVERDATA_EXECCOMMAND = 2 +SERVERDATA_AUTH_RESPONSE = 2 +SERVERDATA_AUTH = 3 + + +@dataclass +class RconPacket: + request_id: int + packet_type: int + body: str + + +class RconClient: + def __init__(self, host: str, port: int, timeout: float, debug: bool = False): + self.host = host + self.port = port + self.timeout = timeout + self.debug = debug + self.sock: socket.socket | None = None + + def connect(self) -> None: + self.sock = socket.create_connection((self.host, self.port), timeout=self.timeout) + self.sock.settimeout(self.timeout) + if self.debug: + print(f"[DEBUG] Connected to {self.host}:{self.port}") + + def close(self) -> None: + if self.sock: + self.sock.close() + self.sock = None + + def _send_packet(self, request_id: int, packet_type: int, body: str) -> None: + if not self.sock: + raise RuntimeError("Socket is not connected") + + payload = body.encode("utf-8") + b"\x00\x00" + packet = struct.pack(" SEND id={request_id} type={packet_type} len={len(packet)} body={body!r}" + ) + print(f"[DEBUG] -> HEX {data.hex(' ')}") + + def _recv_packet(self) -> RconPacket: + if not self.sock: + raise RuntimeError("Socket is not connected") + + raw_size = self._recv_exact(4) + size = struct.unpack(" bytes: + if not self.sock: + raise RuntimeError("Socket is not connected") + + chunks: List[bytes] = [] + remaining = n + while remaining > 0: + chunk = self.sock.recv(remaining) + if not chunk: + raise ConnectionError("Connection closed by remote host") + chunks.append(chunk) + remaining -= len(chunk) + return b"".join(chunks) + + def authenticate(self, password: str) -> bool: + auth_id = random.randint(1, 2_000_000_000) + self._send_packet(auth_id, SERVERDATA_AUTH, password) + + deadline = time.time() + self.timeout + got_auth_response = False + + while time.time() < deadline: + try: + packet = self._recv_packet() + except socket.timeout: + break + + if packet.packet_type == SERVERDATA_AUTH_RESPONSE: + got_auth_response = True + if packet.request_id == -1: + return False + if packet.request_id == auth_id: + return True + + return got_auth_response + + def execute(self, command: str, settle_time: float, idle_timeout: float) -> list[RconPacket]: + command_id = random.randint(1, 2_000_000_000) + self._send_packet(command_id, SERVERDATA_EXECCOMMAND, command) + + packets: list[RconPacket] = [] + end_time = time.time() + max(settle_time, 0) + + while time.time() < end_time: + try: + packet = self._recv_packet() + packets.append(packet) + end_time = time.time() + idle_timeout + except socket.timeout: + break + except ConnectionError: + break + + return packets + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Low-level RCON probe for troubleshooting server/client protocol issues" + ) + parser.add_argument("--host", required=True, help="RCON host") + parser.add_argument("--port", required=True, type=int, help="RCON TCP port") + parser.add_argument("--password", required=True, help="RCON password") + parser.add_argument( + "--command", + action="append", + default=[], + help="Command to execute (use multiple --command for multiple commands)", + ) + parser.add_argument( + "--timeout", + type=float, + default=3.0, + help="Socket timeout in seconds (default: 3.0)", + ) + parser.add_argument( + "--settle-time", + type=float, + default=2.0, + help="Initial max wait for command responses in seconds (default: 2.0)", + ) + parser.add_argument( + "--idle-timeout", + type=float, + default=0.35, + help="Wait extension after each received packet in seconds (default: 0.35)", + ) + parser.add_argument( + "--debug", + action="store_true", + help="Print packet-level debug including hex bytes", + ) + + args = parser.parse_args() + + commands = args.command or ["info"] + + client = RconClient(args.host, args.port, args.timeout, debug=args.debug) + + try: + client.connect() + + authenticated = client.authenticate(args.password) + if not authenticated: + print("AUTH FAILED") + return 2 + + print("AUTH OK") + + for index, command in enumerate(commands, start=1): + print(f"\n=== COMMAND {index}: {command} ===") + packets = client.execute( + command=command, + settle_time=args.settle_time, + idle_timeout=args.idle_timeout, + ) + + if not packets: + print("No response packets received (empty/timed out).") + continue + + for i, packet in enumerate(packets, start=1): + printable_body = packet.body if packet.body else "" + print( + f"[{i}] id={packet.request_id} type={packet.packet_type} body={printable_body}" + ) + + except (TimeoutError, socket.timeout): + print("Timeout while connecting/reading packets") + return 3 + except Exception as exc: + print(f"ERROR: {exc}") + return 1 + finally: + client.close() + + return 0 + + +if __name__ == "__main__": + sys.exit(main())