feat(steam_workshop): production rewrite with full admin profile page and server settings
- module.php: bump db_version to 2; full v2 schema in install_queries[0]; ALTER TABLE migration in install_queries[2] adding 11 new profile columns plus server_workshop_settings table
- WorkshopRepository: expand saveProfile() with all new fields (steam_app_id, steamcmd_login_mode, steamcmd_path, mod_separator, copy_keys, key paths, pre/post scripts, validation_notes); add nullOrStr helper; add server settings CRUD (getServerSettings, saveServerSettings, recordUpdateResult, setUpdateQueued, listQueuedUpdateHomes); update insertOrUpdateMod with custom_folder; update listAllEnabledMods to select new columns
- WorkshopProfileController: full extractProfileData() with all new fields; validateProfileData with folder template check
- views/admin/profile_form.php: full rewrite – all required fields (steam_app_id, workshop_app_id, login mode, SteamCMD path, OS, cache path, install path, folder naming dropdown, launch params, mod separator, copy method, copy keys with JS show/hide, key paths, pre/per-mod/post bash scripts with DayZ example, validation notes, config file template)
- views/admin/profiles.php: updated list view columns (App IDs, Login, Method)
- WorkshopInstaller.php: full rewrite with %var% template support (+ legacy {var} compat); buildTemplateVars() resolves all 14 variables; pre/post script execution; triggerSteamCmdDownload uses new profile fields; copyKeys helper
- WorkshopModController: add save_settings and queue_update POST actions; handleModsPage loads serverSettings + allProfiles
- views/user_workshop_mods.php: full rewrite – server settings form (enable, profile selector, update mode, restart behavior), update status grid (status/error/time/success time), queue update button, mod table with custom_folder column and toggle/order auto-submit
- lang/en_US.php: ~80 new string keys for all v2 fields
- steam_workshop.css: new v2 styles (3-col grid, script textarea, status grid, server settings card, badges)"
Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/e7f0d80d-f775-4794-adbd-cf48b55bc9c1
Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
parent
199b398543
commit
69f415ad86
10 changed files with 1334 additions and 312 deletions
|
|
@ -4,21 +4,28 @@ declare(strict_types=1);
|
|||
/** @var array|null $profile existing row when editing, null when creating */
|
||||
/** @var int $profileId */
|
||||
|
||||
$isEdit = $profileId > 0 && $profile !== null;
|
||||
$heading = $isEdit
|
||||
$isEdit = $profileId > 0 && $profile !== null;
|
||||
$heading = $isEdit
|
||||
? sprintf($lang['config_heading_edit'] ?? 'Edit Workshop Configuration: %s', htmlspecialchars($profile['game_name'] ?? ''))
|
||||
: ($lang['config_heading_create'] ?? 'Add Workshop Game Configuration');
|
||||
|
||||
$v = static function (string $key, array $profile, string $default = ''): string {
|
||||
return htmlspecialchars((string)($profile[$key] ?? $default), ENT_QUOTES);
|
||||
/** Helper: return html-safe value from profile array (or default). */
|
||||
$v = static function (string $key, array $p, string $default = ''): string {
|
||||
return htmlspecialchars((string)($p[$key] ?? $default), ENT_QUOTES);
|
||||
};
|
||||
|
||||
$osList = ['linux' => 'Linux', 'windows' => 'Windows'];
|
||||
$currentOs = array_filter(explode(',', (string)($profile['supported_os'] ?? 'linux')));
|
||||
$methodList = ['rsync' => 'rsync (Linux)', 'robocopy' => 'robocopy (Windows)', 'custom_script' => 'Custom script'];
|
||||
$curMethod = (string)($profile['copy_method'] ?? 'rsync');
|
||||
$osList = ['linux' => 'Linux', 'windows' => 'Windows'];
|
||||
$currentOs = array_filter(explode(',', (string)($profile['supported_os'] ?? 'linux')));
|
||||
$folderFormats = ['@%mod_name%' => '@%mod_name% (mod title)', '@%workshop_id%' => '@%workshop_id% (numeric ID)', 'custom' => 'Custom template'];
|
||||
$curFolderFormat = (string)($profile['folder_naming_format'] ?? '@%workshop_id%');
|
||||
$separatorList = ['semicolon' => 'Semicolon ( ; )', 'comma' => 'Comma ( , )', 'space' => 'Space ( )'];
|
||||
$curSeparator = (string)($profile['mod_separator'] ?? 'semicolon');
|
||||
$copyMethods = ['rsync' => 'rsync (Linux/Unix)', 'copy' => 'cp / basic copy', 'symlink' => 'Symlink'];
|
||||
$curCopyMethod = (string)($profile['copy_method'] ?? 'rsync');
|
||||
$loginModes = ['anonymous' => 'Anonymous (recommended for free mods)', 'account' => 'Configured account (paid games)'];
|
||||
$curLoginMode = (string)($profile['steamcmd_login_mode'] ?? 'anonymous');
|
||||
|
||||
$tplVarNote = $lang['profile_template_vars'] ?? 'Available: {home_id} {agent_id} {workshop_app_id} {mod_id} {mod_title} {mod_folder} {steamcmd_path} {server_path} {install_path} {cache_path}';
|
||||
$tplVarNote = $lang['profile_template_vars'] ?? 'Variables: %home_id% %server_path% %steam_app_id% %workshop_app_id% %workshop_id% %mod_name% %install_name% %download_path% %source_path% %target_path% %keys_source_path% %keys_target_path% %steamcmd_path%';
|
||||
?>
|
||||
<div class="sw-admin sw-profile-form">
|
||||
<h3><?php echo $heading; ?></h3>
|
||||
|
|
@ -26,36 +33,84 @@ $tplVarNote = $lang['profile_template_vars'] ?? 'Available: {home_id} {agent_id
|
|||
|
||||
<div class="sw-info-box">
|
||||
<strong><?php echo htmlspecialchars($lang['config_steamcmd_heading'] ?? 'How mods are downloaded'); ?></strong>
|
||||
<p><?php echo htmlspecialchars($lang['config_steamcmd_note'] ?? 'Workshop mods are downloaded using SteamCMD: +workshop_download_item <App ID> <Mod ID>. The cache path below is where SteamCMD stores downloaded content on the agent. The install path is where the mod files are copied into the game server directory.'); ?></p>
|
||||
<p><?php echo htmlspecialchars($lang['config_steamcmd_note'] ?? 'Workshop mods are downloaded using SteamCMD: +workshop_download_item <App ID> <Mod ID>. Configure the paths and scripts below to control how mods are installed for servers of this game type.'); ?></p>
|
||||
<p><strong><?php echo htmlspecialchars($lang['profile_template_vars_heading'] ?? 'Template variables:'); ?></strong><br>
|
||||
<code><?php echo htmlspecialchars($tplVarNote); ?></code></p>
|
||||
</div>
|
||||
|
||||
<form method="post" action="?m=steam_workshop&p=workshop_admin" class="sw-form">
|
||||
<input type="hidden" name="sw_action" value="profile_save">
|
||||
<input type="hidden" name="profile_id" value="<?php echo $profileId; ?>">
|
||||
|
||||
<!-- Basic info -->
|
||||
<!-- Basic identification -->
|
||||
<fieldset>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_basic'] ?? 'Basic info'); ?></legend>
|
||||
<div class="sw-form__grid">
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_basic'] ?? 'Basic identification'); ?></legend>
|
||||
<div class="sw-form__grid sw-form__grid--3col">
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['label_game_key'] ?? 'Game key'); ?> <em>*</em>
|
||||
<small><?php echo htmlspecialchars($lang['config_hint_game_key'] ?? 'Short identifier matching the game XML key, e.g. arma3_linux'); ?></small>
|
||||
<small><?php echo htmlspecialchars($lang['config_hint_game_key'] ?? 'Short identifier matching the game XML key, e.g. dayz_linux'); ?></small>
|
||||
<input type="text" name="game_key" value="<?php echo $v('game_key', $profile ?? []); ?>"
|
||||
pattern="[A-Za-z0-9_\-.]+" required maxlength="100"
|
||||
<?php echo $isEdit ? 'readonly' : ''; ?>>
|
||||
</label>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_game_name'] ?? 'Game name'); ?> <em>*</em>
|
||||
<?php echo htmlspecialchars($lang['profile_label_game_name'] ?? 'Game display name'); ?> <em>*</em>
|
||||
<input type="text" name="game_name" value="<?php echo $v('game_name', $profile ?? []); ?>"
|
||||
required maxlength="255">
|
||||
</label>
|
||||
<label class="sw-checkbox" style="align-self:end;padding-bottom:0.75rem;">
|
||||
<input type="checkbox" name="enabled" value="1"
|
||||
<?php echo ($profile['enabled'] ?? 1) ? 'checked' : ''; ?>>
|
||||
<span><?php echo htmlspecialchars($lang['config_label_enabled'] ?? 'Profile enabled'); ?></span>
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- Steam / SteamCMD settings -->
|
||||
<fieldset>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_steam'] ?? 'Steam & SteamCMD settings'); ?></legend>
|
||||
<div class="sw-form__grid sw-form__grid--3col">
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['config_label_app_id'] ?? 'Steam App ID'); ?> <em>*</em>
|
||||
<small><?php echo htmlspecialchars($lang['config_hint_app_id'] ?? 'The Steam App ID used with +workshop_download_item, e.g. 107410 for Arma 3'); ?></small>
|
||||
<?php echo htmlspecialchars($lang['profile_label_steam_app_id'] ?? 'Steam App ID'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_steam_app_id'] ?? 'The Steam game App ID (e.g. 221100 for DayZ). Used when Steam login is required.'); ?></small>
|
||||
<input type="text" name="steam_app_id"
|
||||
value="<?php echo $v('steam_app_id', $profile ?? []); ?>"
|
||||
pattern="[0-9]*" maxlength="32">
|
||||
</label>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['config_label_app_id'] ?? 'Workshop App ID'); ?> <em>*</em>
|
||||
<small><?php echo htmlspecialchars($lang['config_hint_app_id'] ?? 'The App ID used with +workshop_download_item, e.g. 221100 for DayZ'); ?></small>
|
||||
<input type="text" name="workshop_app_id"
|
||||
value="<?php echo $v('workshop_app_id', $profile ?? []); ?>"
|
||||
pattern="[0-9]+" required maxlength="32">
|
||||
</label>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_steamcmd_path'] ?? 'SteamCMD path on agent'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_steamcmd_path'] ?? 'Full path to steamcmd.sh on the remote agent. Leave blank to use the agent default (/home/gameserver/steamcmd/steamcmd.sh).'); ?></small>
|
||||
<input type="text" name="steamcmd_path"
|
||||
value="<?php echo $v('steamcmd_path', $profile ?? []); ?>"
|
||||
placeholder="/home/gameserver/steamcmd/steamcmd.sh" maxlength="512">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="sw-form__grid sw-form__grid--2col">
|
||||
<label class="sw-checkbox">
|
||||
<input type="checkbox" name="steam_login_required" value="1"
|
||||
id="sw-login-required"
|
||||
<?php echo !empty($profile['steam_login_required']) ? 'checked' : ''; ?>>
|
||||
<span><?php echo htmlspecialchars($lang['profile_label_steam_login_required'] ?? 'Steam login required (game is not free / requires ownership)'); ?></span>
|
||||
</label>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_steamcmd_login_mode'] ?? 'SteamCMD login mode'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_steamcmd_login_mode'] ?? 'Use anonymous for free Workshop mods. Use configured account for games requiring ownership.'); ?></small>
|
||||
<select name="steamcmd_login_mode">
|
||||
<?php foreach ($loginModes as $mVal => $mLabel): ?>
|
||||
<option value="<?php echo $mVal; ?>" <?php echo $curLoginMode === $mVal ? 'selected' : ''; ?>>
|
||||
<?php echo htmlspecialchars($mLabel); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<fieldset class="sw-form__os-group">
|
||||
|
|
@ -70,81 +125,180 @@ $tplVarNote = $lang['profile_template_vars'] ?? 'Available: {home_id} {agent_id
|
|||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
<!-- Paths / templates -->
|
||||
<!-- Download & install paths -->
|
||||
<fieldset>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_paths'] ?? 'Paths & templates'); ?></legend>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_paths'] ?? 'Download & install paths'); ?></legend>
|
||||
<small class="sw-hint"><?php echo htmlspecialchars($tplVarNote); ?></small>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_cache_path'] ?? 'SteamCMD cache path template'); ?> <em>*</em>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_cache_path'] ?? 'Where SteamCMD downloads mods on the agent. E.g. {steamcmd_path}/steamapps/workshop/content/{workshop_app_id}/{mod_id}'); ?></small>
|
||||
<?php echo htmlspecialchars($lang['profile_label_cache_path'] ?? 'Workshop download/cache path'); ?> <em>*</em>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_cache_path'] ?? 'Where SteamCMD stores downloaded mod content on the agent. E.g. /home/gameserver/steamcmd/steamapps/workshop/content/%workshop_app_id%/%workshop_id%'); ?></small>
|
||||
<input type="text" name="cache_path_template"
|
||||
value="<?php echo $v('cache_path_template', $profile ?? []); ?>" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_install_path'] ?? 'Server install path template'); ?> <em>*</em>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_install_path'] ?? 'Where mod files are placed inside the game server directory. E.g. {server_path}/mods/{mod_folder}'); ?></small>
|
||||
<?php echo htmlspecialchars($lang['profile_label_install_path'] ?? 'Server mod install root'); ?> <em>*</em>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_install_path'] ?? 'Base directory inside the server where mods are installed. E.g. %server_path%/mods/%install_name%'); ?></small>
|
||||
<input type="text" name="install_path_template"
|
||||
value="<?php echo $v('install_path_template', $profile ?? []); ?>" required>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_folder_name'] ?? 'Mod folder name template'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_folder_name'] ?? 'Folder name for each mod inside the install path. Default: @{mod_id}'); ?></small>
|
||||
<input type="text" name="folder_name_template"
|
||||
value="<?php echo $v('folder_name_template', $profile ?? [], '@{mod_id}'); ?>">
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<!-- Copy method -->
|
||||
<!-- Mod folder naming -->
|
||||
<fieldset>
|
||||
<legend><?php echo htmlspecialchars($lang['config_section_copy'] ?? 'Copy / sync method'); ?></legend>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_folder'] ?? 'Mod folder naming'); ?></legend>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_copy_method'] ?? 'Method used to copy mod files from SteamCMD cache to the server'); ?>
|
||||
<select name="copy_method">
|
||||
<?php foreach ($methodList as $mVal => $mLabel): ?>
|
||||
<option value="<?php echo $mVal; ?>" <?php echo $curMethod === $mVal ? 'selected' : ''; ?>>
|
||||
<?php echo htmlspecialchars($mLabel); ?>
|
||||
<?php echo htmlspecialchars($lang['profile_label_folder_format'] ?? 'Folder naming format'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_folder_format'] ?? 'How each mod folder is named inside the install root.'); ?></small>
|
||||
<select name="folder_naming_format" id="sw-folder-format">
|
||||
<?php foreach ($folderFormats as $fVal => $fLabel): ?>
|
||||
<option value="<?php echo $fVal; ?>" <?php echo $curFolderFormat === $fVal ? 'selected' : ''; ?>>
|
||||
<?php echo htmlspecialchars($fLabel); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_install_script'] ?? 'Custom install script (optional, admin-defined)'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_install_script'] ?? 'Only used when copy method is custom_script. Template variables are replaced before execution.'); ?></small>
|
||||
<textarea name="install_script" rows="4"><?php echo $v('install_script', $profile ?? []); ?></textarea>
|
||||
</label>
|
||||
<div id="sw-custom-folder-wrap" <?php echo $curFolderFormat !== 'custom' ? 'style="display:none"' : ''; ?>>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_folder_name'] ?? 'Custom folder name template'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_folder_name'] ?? 'Use %workshop_id% or %mod_name%. E.g. @%workshop_id%'); ?></small>
|
||||
<input type="text" name="folder_name_template"
|
||||
value="<?php echo $v('folder_name_template', $profile ?? [], '@%workshop_id%'); ?>">
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- Config / launch params -->
|
||||
<!-- Launch parameters -->
|
||||
<fieldset>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_config'] ?? 'Config & launch parameters'); ?></legend>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_launch'] ?? 'Launch parameters'); ?></legend>
|
||||
<div class="sw-form__grid sw-form__grid--2col">
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_mod_launch_param'] ?? 'Mod launch parameter format'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_mod_launch_param'] ?? 'How the full mod list is passed to the server start command. E.g. -mod=%mods%'); ?></small>
|
||||
<input type="text" name="mod_launch_param"
|
||||
value="<?php echo $v('mod_launch_param', $profile ?? []); ?>"
|
||||
placeholder="-mod=%mods%" maxlength="512">
|
||||
</label>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_mod_separator'] ?? 'Mod separator'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_mod_separator'] ?? 'Character used to join multiple mod folder names in the launch parameter.'); ?></small>
|
||||
<select name="mod_separator">
|
||||
<?php foreach ($separatorList as $sVal => $sLabel): ?>
|
||||
<option value="<?php echo $sVal; ?>" <?php echo $curSeparator === $sVal ? 'selected' : ''; ?>>
|
||||
<?php echo htmlspecialchars($sLabel); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_config_tpl'] ?? 'Config file template (optional)'); ?>
|
||||
<textarea name="config_file_template" rows="4"><?php echo $v('config_file_template', $profile ?? []); ?></textarea>
|
||||
</label>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_launch_tpl'] ?? 'Launch parameter template (optional)'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['config_hint_launch_tpl'] ?? 'Extra launch parameters added when this game has Workshop mods enabled. E.g. -mod=@{mod_id}'); ?></small>
|
||||
<?php echo htmlspecialchars($lang['profile_label_launch_tpl'] ?? 'Full launch parameter template (optional)'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['config_hint_launch_tpl'] ?? 'Complete launch parameter string appended to server start. Each mod folder name is joined with the separator above.'); ?></small>
|
||||
<input type="text" name="launch_param_template"
|
||||
value="<?php echo $v('launch_param_template', $profile ?? []); ?>">
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<!-- Flags -->
|
||||
<!-- Copy / sync method -->
|
||||
<fieldset>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_flags'] ?? 'Flags'); ?></legend>
|
||||
<legend><?php echo htmlspecialchars($lang['config_section_copy'] ?? 'Copy / sync method'); ?></legend>
|
||||
<div class="sw-form__grid sw-form__grid--2col">
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_copy_method'] ?? 'Copy method'); ?>
|
||||
<select name="copy_method">
|
||||
<?php foreach ($copyMethods as $mVal => $mLabel): ?>
|
||||
<option value="<?php echo $mVal; ?>" <?php echo $curCopyMethod === $mVal ? 'selected' : ''; ?>>
|
||||
<?php echo htmlspecialchars($mLabel); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
<label class="sw-checkbox" style="align-self:end;padding-bottom:0.5rem;">
|
||||
<input type="checkbox" name="copy_keys" value="1"
|
||||
id="sw-copy-keys"
|
||||
<?php echo !empty($profile['copy_keys']) ? 'checked' : ''; ?>>
|
||||
<span><?php echo htmlspecialchars($lang['profile_label_copy_keys'] ?? 'Copy mod keys (*.bikey) to server keys directory'); ?></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div id="sw-key-paths-wrap" <?php echo empty($profile['copy_keys']) ? 'style="display:none"' : ''; ?>>
|
||||
<div class="sw-form__grid sw-form__grid--2col">
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_key_source'] ?? 'Key source path'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_key_source'] ?? 'Path inside the mod cache where key files live. E.g. %source_path%/keys'); ?></small>
|
||||
<input type="text" name="key_source_path"
|
||||
value="<?php echo $v('key_source_path', $profile ?? []); ?>"
|
||||
placeholder="%source_path%/keys">
|
||||
</label>
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_key_dest'] ?? 'Key destination path'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_key_dest'] ?? 'Where keys are copied on the server. E.g. %server_path%/keys'); ?></small>
|
||||
<input type="text" name="key_dest_path"
|
||||
value="<?php echo $v('key_dest_path', $profile ?? []); ?>"
|
||||
placeholder="%server_path%/keys">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- Bash scripts -->
|
||||
<fieldset>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_scripts'] ?? 'Bash scripts'); ?></legend>
|
||||
<div class="sw-info-box sw-info-box--compact">
|
||||
<strong><?php echo htmlspecialchars($lang['profile_scripts_order'] ?? 'Execution order:'); ?></strong>
|
||||
1. <?php echo htmlspecialchars($lang['profile_label_pre_script'] ?? 'Pre-update script'); ?> →
|
||||
2. <?php echo htmlspecialchars($lang['profile_label_install_script'] ?? 'Per-mod install script'); ?> (<?php echo htmlspecialchars($lang['profile_scripts_per_mod'] ?? 'repeated for each mod'); ?>) →
|
||||
3. <?php echo htmlspecialchars($lang['profile_label_post_script'] ?? 'Post-update script'); ?>
|
||||
</div>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_pre_script'] ?? 'Pre-update bash script'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_pre_script'] ?? 'Runs once before any mod is downloaded/installed. Variables: %home_id% %server_path% %workshop_app_id%'); ?></small>
|
||||
<textarea name="pre_update_script" rows="4" class="sw-script-textarea"><?php echo $v('pre_update_script', $profile ?? []); ?></textarea>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_install_script'] ?? 'Per-mod install bash script'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_install_script'] ?? 'Runs once for each mod. All template variables listed above are available.'); ?></small>
|
||||
<details class="sw-example-block">
|
||||
<summary><?php echo htmlspecialchars($lang['profile_script_example_toggle'] ?? 'Show DayZ-style example'); ?></summary>
|
||||
<pre class="sw-code-pre">mkdir -p "%target_path%"
|
||||
rsync -a --delete "%source_path%/" "%target_path%/"
|
||||
if [ -d "%source_path%/keys" ]; then
|
||||
mkdir -p "%keys_target_path%"
|
||||
cp -f "%source_path%/keys/"*.bikey "%keys_target_path%/" 2>/dev/null || true
|
||||
fi</pre>
|
||||
</details>
|
||||
<textarea name="install_script" rows="8" class="sw-script-textarea"><?php echo $v('install_script', $profile ?? []); ?></textarea>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_post_script'] ?? 'Post-update bash script'); ?>
|
||||
<small><?php echo htmlspecialchars($lang['profile_hint_post_script'] ?? 'Runs once after all mods have been installed. Variables: %home_id% %server_path% %workshop_app_id%'); ?></small>
|
||||
<textarea name="post_update_script" rows="4" class="sw-script-textarea"><?php echo $v('post_update_script', $profile ?? []); ?></textarea>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<!-- Options & validation -->
|
||||
<fieldset>
|
||||
<legend><?php echo htmlspecialchars($lang['profile_section_flags'] ?? 'Options & validation'); ?></legend>
|
||||
<label class="sw-checkbox">
|
||||
<input type="checkbox" name="requires_restart" value="1"
|
||||
<?php echo !empty($profile['requires_restart']) ? 'checked' : ''; ?>>
|
||||
<span><?php echo htmlspecialchars($lang['profile_label_requires_restart'] ?? 'Server restart required after mod install or update'); ?></span>
|
||||
</label>
|
||||
<label class="sw-checkbox">
|
||||
<input type="checkbox" name="enabled" value="1"
|
||||
<?php echo ($profile['enabled'] ?? 1) ? 'checked' : ''; ?>>
|
||||
<span><?php echo htmlspecialchars($lang['config_label_enabled'] ?? 'Configuration enabled (allows servers to use Workshop mods for this game)'); ?></span>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_validation_notes'] ?? 'Validation notes / help text (shown to server owners)'); ?>
|
||||
<textarea name="validation_notes" rows="3"><?php echo $v('validation_notes', $profile ?? []); ?></textarea>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<?php echo htmlspecialchars($lang['profile_label_config_tpl'] ?? 'Config file template (optional)'); ?>
|
||||
<textarea name="config_file_template" rows="3"><?php echo $v('config_file_template', $profile ?? []); ?></textarea>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
|
|
@ -158,3 +312,25 @@ $tplVarNote = $lang['profile_template_vars'] ?? 'Available: {home_id} {agent_id
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Show/hide custom folder template field
|
||||
const formatSel = document.getElementById('sw-folder-format');
|
||||
const customWrap = document.getElementById('sw-custom-folder-wrap');
|
||||
if (formatSel && customWrap) {
|
||||
formatSel.addEventListener('change', function () {
|
||||
customWrap.style.display = this.value === 'custom' ? '' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
// Show/hide key path fields
|
||||
const copyKeysChk = document.getElementById('sw-copy-keys');
|
||||
const keyPathsWrap = document.getElementById('sw-key-paths-wrap');
|
||||
if (copyKeysChk && keyPathsWrap) {
|
||||
copyKeysChk.addEventListener('change', function () {
|
||||
keyPathsWrap.style.display = this.checked ? '' : 'none';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ declare(strict_types=1);
|
|||
<tr>
|
||||
<th><?php echo htmlspecialchars($lang['profile_col_game'] ?? 'Game'); ?></th>
|
||||
<th><?php echo htmlspecialchars($lang['profile_col_key'] ?? 'Game Key'); ?></th>
|
||||
<th>App ID</th>
|
||||
<th>OS</th>
|
||||
<th><?php echo htmlspecialchars($lang['profile_col_app_ids'] ?? 'App IDs'); ?></th>
|
||||
<th><?php echo htmlspecialchars($lang['profile_col_login'] ?? 'Login'); ?></th>
|
||||
<th><?php echo htmlspecialchars($lang['profile_col_method'] ?? 'Install Method'); ?></th>
|
||||
<th><?php echo htmlspecialchars($lang['profile_col_restart'] ?? 'Restart?'); ?></th>
|
||||
<th><?php echo htmlspecialchars($lang['profile_col_status'] ?? 'Status'); ?></th>
|
||||
|
|
@ -33,8 +33,16 @@ declare(strict_types=1);
|
|||
<tr>
|
||||
<td><?php echo htmlspecialchars($profile['game_name']); ?></td>
|
||||
<td><code><?php echo htmlspecialchars($profile['game_key']); ?></code></td>
|
||||
<td><?php echo htmlspecialchars($profile['workshop_app_id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($profile['supported_os']); ?></td>
|
||||
<td>
|
||||
<small><?php echo htmlspecialchars($lang['profile_col_steam'] ?? 'Steam'); ?>:</small> <?php echo htmlspecialchars($profile['steam_app_id'] !== '' ? $profile['steam_app_id'] : '—'); ?><br>
|
||||
<small><?php echo htmlspecialchars($lang['profile_col_workshop'] ?? 'Workshop'); ?>:</small> <?php echo htmlspecialchars($profile['workshop_app_id']); ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo htmlspecialchars($profile['steamcmd_login_mode'] ?? 'anonymous'); ?>
|
||||
<?php if (!empty($profile['steam_login_required'])): ?>
|
||||
<span class="sw-badge sw-badge--warning"><?php echo htmlspecialchars($lang['profile_badge_login_required'] ?? 'Login req.'); ?></span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?php echo htmlspecialchars($profile['copy_method']); ?></td>
|
||||
<td><?php echo $profile['requires_restart'] ? '✔' : '✘'; ?></td>
|
||||
<td>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue