Panel/docs/features/WORKSHOP_SYSTEM.md
2026-06-08 16:09:54 -05:00

10 KiB

Workshop System

Workspace reference: GSP-WORKSPACE.md

Current State

The current Workshop/content work is split across two module lines:

  • Panel/modules/steam_workshop - deprecated compatibility layer
  • Panel/modules/addonsmanager - the active Server Content Manager path

Important files:

  • Panel/modules/addonsmanager/module.php
  • Panel/modules/addonsmanager/user_addons.php
  • Panel/modules/addonsmanager/addons_manager.php
  • Panel/modules/addonsmanager/workshop_content.php
  • Panel/modules/addonsmanager/workshop_action.php
  • Panel/modules/addonsmanager/scripts/workshop/generic_steam_workshop_linux.sh
  • Panel/modules/addonsmanager/scripts/workshop/generic_steam_workshop_windows_cygwin.sh
  • Panel/modules/steam_workshop/module.php
  • Panel/modules/steam_workshop/agent_update_workshop.php

Current Implemented Behavior

Workshop is Panel-side orchestration. The active workflow lives in Server Content Manager and uses existing agent primitives only:

  • Panel writes manifests with validated numeric Workshop IDs.
  • Panel generates a per-job shell script under the server home.
  • The generated job script writes a temporary SteamCMD runscript and runs steamcmd +runscript <scriptfile>.
  • Panel invokes the job script through the existing authenticated agent exec RPC.
  • Agents do not need new Workshop-specific business logic.
  • Legacy agent RPCs from the old steam_workshop module remain compatibility-only and are not the primary path.

The active user workflow is now addonsmanager -> workshop_content.

Users can enter either:

  • a numeric Workshop item ID
  • a full Steam Workshop URL containing id=<number>

The Panel extracts and stores only numeric Workshop IDs. Invalid text is rejected before any manifest or shell command is built.

The Panel writes a manifest under the server home:

  • {SERVER_HOME}/gsp_server_content/workshop_manifest.json

The Panel writes a generated per-job script to:

  • {SERVER_HOME}/gsp_server_content/jobs/workshop/workshop_job_<timestamp>_<random>.sh

The agent executes the generated script with the manifest path by using the existing generic command execution path. Customers do not need to place scripts manually on the agent.

Script/job rules:

  1. Server Content Manager always generates the primary Workshop job script per action.
  2. Old XML/static script settings are logged as deprecated and ignored by the primary path.
  3. The default script filename must never be treated as a pre-existing agent path.
  4. The agent does not require generic_steam_workshop_linux.sh or generic_steam_workshop_windows_cygwin.sh to exist on disk.

The generated job script uses this SteamCMD runscript pattern:

@ShutdownOnFailedCommand 0
@NoPromptForPassword 1
force_install_dir <server_root>
login anonymous
workshop_download_item <workshop_app_id> <workshop_id> validate
quit

The manifest includes:

  • home_id
  • server/game path
  • workshop_app_id
  • Workshop item IDs
  • per-item target paths
  • install strategy
  • key-copy settings
  • content template metadata

Default install paths:

  • Generic Workshop installs default to {SERVER_ROOT}/workshop/{MOD_FOLDER}.
  • DayZ/Arma-style installs default to dayz_mod_folder or arma_mod_folder based on the game key/name/config file. Those strategies install to {SERVER_ROOT}/{MOD_FOLDER} so @<workshop_id> folders remain compatible with existing -mod= workflows.
  • DayZ/Arma key-copy behavior copies .bikey files into the server keys folder when found. Missing key files are logged but do not fail the install.

App ID rules:

  • workshop_app_id must come from a Server Content template, Steam Workshop profile, or game XML.
  • Game XML should declare Workshop support in the canonical workshop_support block.
  • Do not silently use the dedicated server Steam app ID as the Workshop app ID unless a legacy profile explicitly does so.
  • Arma 3 XML declares Workshop app ID 107410; its dedicated server Steam app ID remains 233780.

Canonical XML:

<workshop_support>
  <enabled>1</enabled>
  <provider>steam</provider>
  <steam_app_id>107410</steam_app_id>
  <workshop_app_id>107410</workshop_app_id>
  <download_method>steamcmd</download_method>
  <install_strategy>arma_mod_folder</install_strategy>
  <install_path>{SERVER_ROOT}/{MOD_FOLDER}</install_path>
  <startup_param_format>-mod={MOD_LIST}</startup_param_format>
  <mod_separator>;</mod_separator>
  <mod_prefix>@</mod_prefix>
  <copy_keys enabled="1">
    <source_pattern>{MOD_PATH}/keys/*.bikey</source_pattern>
    <target_path>{SERVER_ROOT}/keys</target_path>
  </copy_keys>
</workshop_support>

The Panel helper parser reads workshop_support first. Older direct tags are tolerated only as a compatibility fallback in helper code; they are not the canonical XML format.

Database State

server_content_workshop tracks:

  • content_id
  • home_id
  • workshop_app_id
  • workshop_item_id
  • title
  • install_path
  • install_strategy
  • enabled
  • load_order
  • update_policy
  • pending_action
  • install_state
  • last_installed_at
  • last_updated_at
  • last_error

Current install states used by Phase 1:

  • queued
  • installing
  • installed
  • downloaded
  • failed
  • removed

server_content_workshop_catalog tracks known/common Workshop items seen through Server Content Manager:

  • workshop_id
  • app_id
  • title
  • install_count
  • first_seen
  • last_installed
  • last_updated
  • published_date
  • tags
  • game_key
  • local_cache_path

The catalog is Panel-side and does not require Steam Web API metadata. Metadata can be added later.

What Exists Today

The current direction already supports:

  • content records in the Panel database
  • Workshop item IDs
  • installation metadata
  • install history tables
  • game compatibility fields
  • launch parameter additions
  • post-install behavior fields

Main Limitations

  • Workshop metadata is still incomplete.
  • Load order is tracked but not yet a full drag-and-drop or startup-param UX concept.
  • Enable/disable is exposed and stored but does not yet regenerate startup parameters.
  • update/remove are synchronous and should become background jobs.
  • caching and cleanup policy need product-level design, not just ad hoc scripts.
  • -mod= / -serverMod= generation still needs a safe structured implementation.

Scheduler Integration

Workshop updates use the existing cron / Scheduler system. No second Workshop scheduler should be created.

Supported scheduler action keys:

  • workshop_update
  • workshop_update_and_restart
  • workshop_download_only
  • workshop_install_pending_on_restart

Compatibility Server Content keys remain available:

  • server_content_check_workshop_updates
  • server_content_update_workshop
  • server_content_install_updates_next_restart
  • server_content_install_updates_and_restart

Per-item update policy values stored on server_content_workshop.update_policy:

  • manual
  • scheduled
  • update_now
  • update_and_restart
  • download_only
  • install_on_restart

Troubleshooting

Symptom Meaning Fix
Configured workshop script not found on agent host: generic_steam_workshop_windows_cygwin.sh Old Panel logic treated the default script filename as an agent path. Update the Panel. Current logic generates a per-job script under gsp_server_content/jobs/workshop/.
SteamCMD is missing on the agent host. The handler could not find SteamCMD at the configured path, STEAMCMD_PATH, or common locations. Install SteamCMD on the agent and/or set the SteamCMD path in the Workshop profile/template.
Workshop App ID is missing No template/profile/XML provided an app ID. Add workshop_app_id to the Server Content template or game XML.
Download succeeds but mod does not load Startup parameters are not yet regenerated from installed Workshop rows. Manually add the installed @... folders to the game startup params until Phase 2 startup integration is complete.

Use addonsmanager as the main future home for:

  • mods
  • add-ons
  • Workshop items
  • scripts
  • config packs
  • server content manifests
  • install history

Treat steam_workshop as a legacy bridge for migration only.

References Reviewed

  • reference/Module-Steam_Workshop is the local legacy OGP module. It confirms that the Panel historically owned Workshop state/configuration and used the agent for execution.
  • The uploaded steam-workshop-downloader reference was not present in this workspace, but its reviewed behavior is reflected in the active design: generate a SteamCMD runscript, call workshop_download_item <appid> <workshop_id> validate, copy or link the downloaded steamapps/workshop/content/<appid>/<workshop_id> folder into the server's mod location, optionally lowercase files for Linux, copy Arma/DayZ keys, and generate future -mod= data from installed items.

Panel-Agent Contract

Phase 1 does not use the legacy steam_workshop XML-RPC method for the primary user workflow. Instead:

  1. Panel parses customer input into numeric Workshop IDs.
  2. Panel writes {SERVER_HOME}/gsp_server_content/workshop_manifest.json.
  3. Panel writes a generated per-job script under {SERVER_HOME}/gsp_server_content/jobs/workshop/.
  4. The job script writes a temporary SteamCMD runscript.
  5. Panel invokes the job script through the existing authenticated agent exec RPC.
  6. The job writes workshop_install.log or workshop_install_windows.log under gsp_server_content.
  7. Panel updates server_content_workshop.install_state from queued/installing to installed/failed/removed.

Important manifest fields:

  • home_id
  • home_cfg_id
  • game_path
  • server_path
  • workshop_app_id
  • steam_app_id
  • items
  • item_details
  • install_strategy
  • target_path
  • extra.copy_keys
  • extra.keys_target_path

Generated Workshop jobs validate numeric item IDs, keep writes under the server home, use SteamCMD through a temporary runscript, copy files into the resolved target path, and copy .bikey files for DayZ/Arma strategies when enabled.

Bundled handler actions:

  • install - download with SteamCMD, copy/install into target path.
  • update - validate/download with SteamCMD, copy/install into target path.
  • check_updates - validate/download only; does not alter live mod folders.
  • download_only - download/cache only and leave install pending.
  • validate_files - SteamCMD validate/download only.
  • remove - move the installed target folder into gsp_server_content/workshop/removed/; this does not require SteamCMD.