feat: config_games XML tag descriptions + jump link; support optional fields; steam_workshop remove adapter terminology
Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/7c776773-fa8f-4f5d-afec-ff62cf7b2bba Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
parent
e338eafb36
commit
e30c6ac25d
6 changed files with 237 additions and 52 deletions
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
require_once("server_config_parser.php");
|
||||
require_once(__DIR__ . "/xml_tag_descriptions.php");
|
||||
|
||||
/**
|
||||
* Safely convert any config value (string, NULL, or array from SimpleXML) to a
|
||||
|
|
@ -264,6 +265,14 @@ function config_games_print_editor_css()
|
|||
.xml-raw-section textarea{width:100%;min-height:300px;font-family:monospace;font-size:0.85rem;background:#0c0c0c;color:#eee;border:1px solid #3a3a3a;border-radius:4px;padding:8px}
|
||||
.xml-raw-warning{background:#2d2200;border:1px solid #7a5a00;border-radius:4px;padding:8px 12px;color:#f0c050;font-size:0.85rem;margin-bottom:6px}
|
||||
.xml-section-header{margin:20px 0 4px;font-size:0.8rem;color:#888;text-transform:uppercase;letter-spacing:0.1em;border-bottom:1px solid #2a2a2a;padding-bottom:4px}
|
||||
.xml-node__desc{font-size:0.82rem;color:#aaa;background:#0e0e0e;border-left:3px solid #2a4a7a;padding:6px 10px;margin:6px 0 8px;border-radius:0 4px 4px 0}
|
||||
.xml-node__options{margin:4px 0 4px 12px;padding:0;list-style:disc inside}
|
||||
.xml-node__options li{margin-bottom:2px}
|
||||
.xml-node__options code{color:#7eb3f0;background:rgba(30,100,200,0.12);padding:1px 4px;border-radius:3px}
|
||||
.xml-node__example{display:block;margin-top:4px;color:#888}
|
||||
.xml-node__example code{color:#a0d0a0;background:rgba(30,150,50,0.1);padding:1px 4px;border-radius:3px}
|
||||
.xml-jump-link{display:inline-block;margin-bottom:12px;padding:6px 14px;background:#1c6dd0;color:#fff;border-radius:4px;text-decoration:none;font-size:0.9rem}
|
||||
.xml-jump-link:hover{background:#1f7aec;text-decoration:none}
|
||||
</style>
|
||||
CSS;
|
||||
}
|
||||
|
|
@ -296,12 +305,34 @@ function config_games_render_node(SimpleXMLElement $node, array $ancestors, arra
|
|||
? "<span class='xml-node__badge xml-node__badge--required'>required</span>"
|
||||
: "<span class='xml-node__badge xml-node__badge--optional'>optional</span>";
|
||||
|
||||
// Look up per-tag description from the descriptions helper.
|
||||
$tagDescriptions = config_games_tag_descriptions();
|
||||
$tagDesc = $tagDescriptions[$name] ?? null;
|
||||
|
||||
$html = "<div class='{$nodeClass}'>";
|
||||
$actionId = 'node_action_' . substr(md5($safePath . $index), 0, 8);
|
||||
$html .= "<div class='xml-node__header'><div><div class='xml-node__title'>{$safeLabel}{$badge}</div><div class='xml-node__path'>{$displayPath}</div></div>";
|
||||
$html .= "<div class='xml-node__actions'><label for=\"{$actionId}\">Action</label>";
|
||||
$html .= "<select id=\"{$actionId}\" name=\"nodes[{$safeNodeKey}][action]\"><option value='keep'>Save Changes</option><option value='remove'>Remove Node</option></select>";
|
||||
$html .= "<button type='submit' name='save_xml' value='1' class='xml-node__apply'>Apply</button></div></div>";
|
||||
if ($tagDesc !== null) {
|
||||
$safeDesc = htmlspecialchars($tagDesc['desc'], ENT_QUOTES, 'UTF-8');
|
||||
$html .= "<div class='xml-node__desc'>{$safeDesc}";
|
||||
if (!empty($tagDesc['options'])) {
|
||||
$html .= "<ul class='xml-node__options'>";
|
||||
foreach ($tagDesc['options'] as $optVal => $optLabel) {
|
||||
$safeOptVal = htmlspecialchars((string)$optVal, ENT_QUOTES, 'UTF-8');
|
||||
$safeOptLabel = htmlspecialchars($optLabel, ENT_QUOTES, 'UTF-8');
|
||||
$html .= "<li><code>{$safeOptVal}</code> – {$safeOptLabel}</li>";
|
||||
}
|
||||
$html .= "</ul>";
|
||||
}
|
||||
if (!empty($tagDesc['example'])) {
|
||||
$safeExample = htmlspecialchars($tagDesc['example'], ENT_QUOTES, 'UTF-8');
|
||||
$html .= "<span class='xml-node__example'>Example: <code>{$safeExample}</code></span>";
|
||||
}
|
||||
$html .= "</div>";
|
||||
}
|
||||
$html .= "<div class='xml-node__body'>";
|
||||
$html .= "<input type='hidden' name=\"nodes[{$safeNodeKey}][path]\" value=\"{$safePath}\">";
|
||||
$html .= "<input type='hidden' name=\"nodes[{$safeNodeKey}][has_children]\" value=\"" . ($hasChildren ? '1' : '0') . "\">";
|
||||
|
|
@ -667,7 +698,8 @@ function exec_ogp_module() {
|
|||
</table>\n";
|
||||
|
||||
if ( isset($_GET['home_cfg_id']) )
|
||||
{
|
||||
{
|
||||
echo "<p><a class='xml-jump-link' href='#xml-editor-section'>↓ Jump to XML Editor</a></p>";
|
||||
$home_cfg_id = trim($_GET['home_cfg_id']);
|
||||
|
||||
$cfg_info = $db->getGameCfg($home_cfg_id);
|
||||
|
|
@ -721,6 +753,7 @@ function exec_ogp_module() {
|
|||
print_failure(get_lang_f("error_when_handling_file",$config_file));
|
||||
} else {
|
||||
$raw_xml_content = htmlspecialchars(file_get_contents($config_file), ENT_QUOTES, 'UTF-8');
|
||||
echo "<div id='xml-editor-section'>";
|
||||
echo "<form action='?m=config_games&home_cfg_id=".$home_cfg_id."' method='post'>";
|
||||
echo "<input type='hidden' name='home_cfg_id' value='".(int)$home_cfg_id."'>";
|
||||
echo "<button type='submit' name='save_xml' value='1' class='xml-global-save xml-global-save--top'>".get_lang('save')."</button>";
|
||||
|
|
@ -738,6 +771,7 @@ function exec_ogp_module() {
|
|||
echo "<div class='xml-actions' style='margin-top:8px'><button type='submit' name='save_xml' value='1' class='xml-global-save'>Save Raw XML</button></div>";
|
||||
echo "</div>";
|
||||
echo "</form>";
|
||||
echo "</div>"; // #xml-editor-section
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
155
modules/config_games/xml_tag_descriptions.php
Normal file
155
modules/config_games/xml_tag_descriptions.php
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
/*
|
||||
* OGP / GSP – Config Games XML tag descriptions
|
||||
*
|
||||
* Each entry maps an XML element name to an array with:
|
||||
* 'desc' – Short human-readable description of what the element does.
|
||||
* 'options' – (optional) array of allowed values with labels.
|
||||
* 'example' – (optional) A short illustrative value.
|
||||
*
|
||||
* Sourced from the OGP XML documentation and the schema in
|
||||
* modules/config_games/schema_server_config.xml.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return the description map for all known game-config XML tags.
|
||||
*
|
||||
* @return array<string, array{desc: string, options?: array<string,string>, example?: string}>
|
||||
*/
|
||||
function config_games_tag_descriptions(): array
|
||||
{
|
||||
return [
|
||||
'game_key' => [
|
||||
'desc' => 'Unique lowercase identifier for this game configuration. Used internally to link homes, mods, and Workshop profiles.',
|
||||
'example' => 'arma3_linux64',
|
||||
],
|
||||
'protocol' => [
|
||||
'desc' => 'Query protocol used to monitor server status.',
|
||||
'options' => [
|
||||
'lgsl' => 'LGSL – Lightweight Game Server Library',
|
||||
'gameq' => 'GameQ – PHP-based multi-protocol server query',
|
||||
'' => 'None (server is not queryable)',
|
||||
],
|
||||
],
|
||||
'lgsl_query_name' => [
|
||||
'desc' => 'LGSL type string identifying the game in the LGSL library (only used when protocol is "lgsl").',
|
||||
'example' => 'arma3',
|
||||
],
|
||||
'gameq_query_name' => [
|
||||
'desc' => 'GameQ protocol name identifying the game (only used when protocol is "gameq").',
|
||||
'example' => 'arma3',
|
||||
],
|
||||
'installer' => [
|
||||
'desc' => 'Installer/updater helper used to download and update game server files.',
|
||||
'options' => [
|
||||
'steam' => 'SteamCMD / HLDSUpdateTool',
|
||||
'steamcmd' => 'SteamCMD (explicit)',
|
||||
'' => 'None (manual installation)',
|
||||
],
|
||||
],
|
||||
'game_name' => [
|
||||
'desc' => 'Display name shown in the panel UI for this game.',
|
||||
'example' => 'Arma 3',
|
||||
],
|
||||
'server_exec_name' => [
|
||||
'desc' => 'Filename of the server executable (without path). The panel uses this to detect whether the server process is running.',
|
||||
'example' => 'arma3server_x64',
|
||||
],
|
||||
'query_port' => [
|
||||
'desc' => 'Port offset added to the main port to obtain the query port used for status monitoring.',
|
||||
'example' => '1',
|
||||
],
|
||||
'cli_template' => [
|
||||
'desc' => 'Command-line template used to launch the server. Supports placeholder tokens such as %ip%, %port%, %slots%.',
|
||||
'example' => '-ip=%ip% -port=%port% -maxPlayers=%slots%',
|
||||
],
|
||||
'cli_params' => [
|
||||
'desc' => 'Container for individual <param> child elements that define configurable launch parameters shown in the panel UI.',
|
||||
],
|
||||
'reserve_ports' => [
|
||||
'desc' => 'Additional sequential ports (beyond the main port) that must be reserved for this server instance.',
|
||||
'example' => '3',
|
||||
],
|
||||
'cli_allow_chars' => [
|
||||
'desc' => 'Extra characters that are safe to include in command-line parameter values (extends the default whitelist).',
|
||||
'example' => '@_-.',
|
||||
],
|
||||
'maps_location' => [
|
||||
'desc' => 'Path inside the server directory where map files are stored. The panel uses this to populate map-selection dropdowns.',
|
||||
'example' => 'Maps',
|
||||
],
|
||||
'map_list' => [
|
||||
'desc' => 'Hardcoded comma-separated list of map names when maps cannot be read from disk.',
|
||||
],
|
||||
'console_log' => [
|
||||
'desc' => 'Relative path to the server log file that the panel displays in the console viewer.',
|
||||
'example' => 'logs/console.log',
|
||||
],
|
||||
'exe_location' => [
|
||||
'desc' => 'Subdirectory within the server installation where the executable resides. Leave empty if the executable is at the root.',
|
||||
'example' => 'Binaries/Win64',
|
||||
],
|
||||
'max_user_amount' => [
|
||||
'desc' => 'Maximum player slots the panel will allow for this game type. Enforced in the panel UI when creating or editing a server.',
|
||||
'example' => '64',
|
||||
],
|
||||
'control_protocol' => [
|
||||
'desc' => 'Protocol used to send RCON/admin commands to the running server.',
|
||||
'options' => [
|
||||
'rcon' => 'RCON (remote console)',
|
||||
'rconhl' => 'Half-Life RCON',
|
||||
'' => 'None',
|
||||
],
|
||||
],
|
||||
'control_protocol_type' => [
|
||||
'desc' => 'Sub-type or variant that further qualifies the control protocol.',
|
||||
'example' => 'rcon_password',
|
||||
],
|
||||
'mods' => [
|
||||
'desc' => 'Container element for mod definitions. Child <mod> elements describe each variant of the server configuration.',
|
||||
],
|
||||
'replace_texts' => [
|
||||
'desc' => 'Container for text-replacement rules applied to config files on the server.',
|
||||
],
|
||||
'server_params' => [
|
||||
'desc' => 'Additional fixed parameters appended verbatim to the server launch command.',
|
||||
],
|
||||
'custom_fields' => [
|
||||
'desc' => 'Container for admin-defined extra fields displayed in the server control panel.',
|
||||
],
|
||||
'list_players_command' => [
|
||||
'desc' => 'RCON command sent to the server to retrieve the current player list.',
|
||||
'example' => 'players',
|
||||
],
|
||||
'player_info_regex' => [
|
||||
'desc' => 'Regular expression used to parse each line of the player-list response into name and other fields.',
|
||||
],
|
||||
'player_info' => [
|
||||
'desc' => 'Defines which capture groups from player_info_regex map to player attributes (name, score, ping, etc.).',
|
||||
],
|
||||
'player_commands' => [
|
||||
'desc' => 'Container for RCON commands that can be executed on individual players (kick, ban, etc.).',
|
||||
],
|
||||
'pre_install' => [
|
||||
'desc' => 'Shell/batch script executed on the agent BEFORE the game server files are installed or updated.',
|
||||
],
|
||||
'post_install' => [
|
||||
'desc' => 'Shell/batch script executed on the agent AFTER the game server files are installed or updated.',
|
||||
],
|
||||
'pre_start' => [
|
||||
'desc' => 'Shell/batch script executed on the agent BEFORE the game server process is started.',
|
||||
],
|
||||
'post_start' => [
|
||||
'desc' => 'Shell/batch script executed on the agent AFTER the game server process has started.',
|
||||
],
|
||||
'environment_variables' => [
|
||||
'desc' => 'Container for environment variables that are set in the server process environment at startup.',
|
||||
],
|
||||
'lock_files' => [
|
||||
'desc' => 'Files that should not be overwritten when updating the server. Paths are relative to the server installation directory.',
|
||||
],
|
||||
'configuration_files' => [
|
||||
'desc' => 'Container listing server configuration files that the panel can display and edit via the config-file editor.',
|
||||
],
|
||||
];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue