Steam Workshop – Mod Manager'; $home_id = isset($_REQUEST['home_id']) ? (int)$_REQUEST['home_id'] : 0; if (!$home_id) { sw_error('No server selected. Please access this page from your game server manager.'); return; } // Ownership check if (!sw_user_owns_home($db, (int)$_SESSION['user_id'], $home_id)) { sw_error('Access denied. You do not own this server.'); return; } // Load server info $home = sw_get_home_info($db, $home_id); if (!$home) { sw_error('Server not found.'); return; } // Find matching Workshop profile $profile = sw_get_profile_for_home($db, $home_id); if (!$profile) { echo '

Steam Workshop is not enabled for this game type (' . sw_h($home['game_name']) . ').

'; echo '

An administrator must enable Workshop support for this game under ' . 'Steam Workshop › Admin.

'; return; } $action = $_POST['action'] ?? ($_GET['action'] ?? ''); // ── POST handlers ───────────────────────────────────────────────── if ($_SERVER['REQUEST_METHOD'] === 'POST') { switch ($action) { case 'add_mod': sw_user_add_mod($db, $home_id, $profile); break; case 'save_mod': sw_user_save_mod($db, $home_id); break; case 'delete_mod': sw_user_delete_mod($db, $home_id); break; case 'toggle_mod': sw_user_toggle_mod($db, $home_id); break; case 'move_up': case 'move_down': sw_user_reorder_mod($db, $home_id, $action); break; case 'queue_update': sw_user_queue_update($db, $home_id); break; } } // ── Render page ─────────────────────────────────────────────────── sw_user_render($db, $home_id, $home, $profile); } // ───────────────────────────────────────────────────────────────────────── // POST action handlers // ───────────────────────────────────────────────────────────────────────── function sw_user_add_mod($db, $home_id, array $profile) { $workshop_id = trim($_POST['workshop_id'] ?? ''); if (!preg_match('/^\d{1,20}$/', $workshop_id)) { sw_error('Invalid Workshop ID – must be a numeric Steam Workshop item ID.'); return; } // Prevent duplicates $safe_wid = $db->realEscapeSingle($workshop_id); $exists = $db->resultQuery( "SELECT id FROM " . sw_table('steam_workshop_server_mods') . " WHERE `home_id` = $home_id AND `workshop_id` = '$safe_wid' LIMIT 1" ); if ($exists) { sw_error("Workshop ID $workshop_id is already in the list."); return; } // Determine next sort_order $last = $db->resultQuery( "SELECT MAX(`sort_order`) AS m FROM " . sw_table('steam_workshop_server_mods') . " WHERE `home_id` = $home_id" ); $sort = ($last && isset($last[0]['m'])) ? ((int)$last[0]['m'] + 1) : 0; $mod_name = $db->realEscapeSingle(trim($_POST['mod_name'] ?? '')); $mod_type = (($_POST['mod_type'] ?? 'client') === 'server') ? 'server' : 'client'; $profile_id = (int)$profile['id']; // Auto-generate folder name from naming format template $folder_name = sw_apply_template( $profile['folder_naming_format'], array( 'MOD_NAME' => !empty($mod_name) ? $mod_name : $workshop_id, 'WORKSHOP_ID' => $workshop_id, 'WORKSHOP_APP_ID'=> $profile['workshop_app_id'], ) ); $safe_fname = $db->realEscapeSingle($folder_name); $safe_mname = $mod_name; // already escaped above via realEscapeSingle $ok = $db->query( "INSERT INTO " . sw_table('steam_workshop_server_mods') . " (`home_id`, `profile_id`, `workshop_id`, `mod_name`, `folder_name`, `mod_type`, `sort_order`, `enabled`, `install_status`, `created_at`) VALUES ($home_id, $profile_id, '$safe_wid', '$safe_mname', '$safe_fname', '$mod_type', $sort, 1, '', NOW())" ); if ($ok) { sw_success("Workshop mod $workshop_id added."); } else { sw_error('Failed to add mod.'); } } function sw_user_save_mod($db, $home_id) { $mod_id = (int)($_POST['mod_id'] ?? 0); if (!$mod_id) { return; } $mod = sw_get_mod_by_id($db, $mod_id); if (!$mod || (int)$mod['home_id'] !== $home_id) { sw_error('Mod not found or access denied.'); return; } $mod_name = $db->realEscapeSingle(trim($_POST['mod_name'] ?? '')); $folder_name = $db->realEscapeSingle(trim($_POST['folder_name'] ?? '')); $mod_type = (($_POST['mod_type'] ?? 'client') === 'server') ? 'server' : 'client'; if (empty($folder_name)) { sw_error('Folder name cannot be empty.'); return; } $ok = $db->query( "UPDATE " . sw_table('steam_workshop_server_mods') . " SET `mod_name` = '$mod_name', `folder_name` = '$folder_name', `mod_type` = '$mod_type', `updated_at` = NOW() WHERE `id` = $mod_id AND `home_id` = $home_id LIMIT 1" ); if ($ok) { sw_success('Mod updated.'); } else { sw_error('Failed to update mod.'); } } function sw_user_delete_mod($db, $home_id) { $mod_id = (int)($_POST['mod_id'] ?? 0); if (!$mod_id) { return; } $mod = sw_get_mod_by_id($db, $mod_id); if (!$mod || (int)$mod['home_id'] !== $home_id) { sw_error('Mod not found or access denied.'); return; } $db->query( "DELETE FROM " . sw_table('steam_workshop_server_mods') . " WHERE `id` = $mod_id AND `home_id` = $home_id LIMIT 1" ); sw_success('Mod removed from list.'); } function sw_user_toggle_mod($db, $home_id) { $mod_id = (int)($_POST['mod_id'] ?? 0); if (!$mod_id) { return; } $mod = sw_get_mod_by_id($db, $mod_id); if (!$mod || (int)$mod['home_id'] !== $home_id) { sw_error('Mod not found or access denied.'); return; } $new_state = $mod['enabled'] ? 0 : 1; $db->query( "UPDATE " . sw_table('steam_workshop_server_mods') . " SET `enabled` = $new_state, `updated_at` = NOW() WHERE `id` = $mod_id AND `home_id` = $home_id LIMIT 1" ); } function sw_user_reorder_mod($db, $home_id, $direction) { $mod_id = (int)($_POST['mod_id'] ?? 0); if (!$mod_id) { return; } $mod = sw_get_mod_by_id($db, $mod_id); if (!$mod || (int)$mod['home_id'] !== $home_id) { return; } $mods = sw_get_server_mods($db, $home_id); if (!$mods) { return; } // Normalise sort_order to 0-based sequential integers $sorted = array_values($mods); foreach ($sorted as $idx => $m) { $db->query( "UPDATE " . sw_table('steam_workshop_server_mods') . " SET `sort_order` = $idx WHERE `id` = " . (int)$m['id'] . " AND `home_id` = $home_id LIMIT 1" ); } // Find the position of the target mod $pos = -1; foreach ($sorted as $idx => $m) { if ((int)$m['id'] === $mod_id) { $pos = $idx; break; } } if ($pos < 0) { return; } if ($direction === 'move_up' && $pos > 0) { $swap_pos = $pos - 1; } elseif ($direction === 'move_down' && $pos < (count($sorted) - 1)) { $swap_pos = $pos + 1; } else { return; // already at boundary } $swap_id = (int)$sorted[$swap_pos]['id']; // Swap sort_order values $db->query( "UPDATE " . sw_table('steam_workshop_server_mods') . " SET `sort_order` = $swap_pos WHERE `id` = $mod_id AND `home_id` = $home_id LIMIT 1" ); $db->query( "UPDATE " . sw_table('steam_workshop_server_mods') . " SET `sort_order` = $pos WHERE `id` = $swap_id AND `home_id` = $home_id LIMIT 1" ); } function sw_user_queue_update($db, $home_id) { // Mark all enabled mods as 'queued' so the agent picks them up. $db->query( "UPDATE " . sw_table('steam_workshop_server_mods') . " SET `install_status` = 'queued', `updated_at` = NOW() WHERE `home_id` = $home_id AND `enabled` = 1" ); sw_success('All enabled mods queued for update. Run the agent to process downloads.'); } // ───────────────────────────────────────────────────────────────────────── // Render // ───────────────────────────────────────────────────────────────────────── function sw_user_render($db, $home_id, array $home, array $profile) { $mods = sw_get_server_mods($db, $home_id) ?: array(); // Generate launch params from enabled mods $enabled_mods = array_filter($mods, function ($m) { return !empty($m['enabled']); }); $params = sw_generate_launch_params(array_values($enabled_mods), $profile); $base_url = 'home.php?m=steam_workshop&p=user&home_id=' . $home_id; ?>

Server:    Game:    Workshop Profile:

Add Workshop Mod


Installed Mods ()

No mods added yet. Use the form above to add Workshop IDs.

$mod): ?>
# Workshop ID Mod Name Folder Name Type Enabled Status Order Actions
Installed'; } elseif ($s === 'queued') { echo 'Queued'; } elseif ($s === 'failed') { echo 'Failed'; } elseif ($s === 'updating') { echo 'Updating'; } else { echo 'Not installed'; } ?>

Generated Launch Parameters

Based on the enabled mods above (sorted by order). Copy these into your server startup command.

No enabled mods – launch parameters will be empty.

Client mods (-mod=):

Server-side mods (-serverMod=):

Combined:


Install / Update Mods

Clicking Queue Update marks all enabled mods as queued. Then run the agent on the game server host (where SteamCMD and the game files are located) to download and install the mods. Adjust the path to the panel's modules/steam_workshop/agent_update_workshop.php for your server:

php /path/to/panel/modules/steam_workshop/agent_update_workshop.php --home-id=