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.

'; 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; case 'save_settings': sw_user_save_settings($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 were queued. Updates are processed automatically by the server agent.'); } function sw_user_save_settings($db, $home_id) { $ok = sw_save_server_settings($db, $home_id, array( 'update_mode' => $_POST['update_mode'] ?? 'manual', 'restart_behavior' => $_POST['restart_behavior'] ?? 'none', 'schedule_interval' => $_POST['schedule_interval'] ?? 'disabled', )); if ($ok) { sw_success('Workshop behavior settings saved.'); } else { sw_error('Failed to save settings.'); } } // ───────────────────────────────────────────────────────────────────────── // Render // ───────────────────────────────────────────────────────────────────────── function sw_user_render($db, $home_id, array $home, array $profile) { $mods = sw_get_server_mods($db, $home_id) ?: array(); $settings = sw_get_server_settings($db, $home_id); $queuedCount = 0; $failedCount = 0; $installedCount = 0; $latestUpdateAt = ''; $latestError = ''; foreach ($mods as $mod) { if (($mod['install_status'] ?? '') === 'queued') { $queuedCount++; } elseif (($mod['install_status'] ?? '') === 'failed') { $failedCount++; } elseif (($mod['install_status'] ?? '') === 'installed') { $installedCount++; } if (!empty($mod['last_updated_at']) && $mod['last_updated_at'] > $latestUpdateAt) { $latestUpdateAt = $mod['last_updated_at']; } if (($mod['install_status'] ?? '') === 'failed' && !empty($mod['last_error']) && $latestError === '') { $latestError = $mod['last_error']; } } $base_url = 'home.php?m=steam_workshop&p=user&home_id=' . $home_id; ?>

Server:   Game:   Workshop Profile:

Queue updates from this page. The server agent applies queued updates automatically.

Add Workshop Mod

Update Queue & Last Result

Enabled mods:   Queued:   Installed:   Failed:

Last update time:

Last error:

Workshop Behavior Settings

Installed Mods ()

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

$mod): ?> 70) ? (substr($mod['last_error'], 0, 67) . '...') : $mod['last_error']; } ?>
# Workshop ID Mod Name Folder Name Type Enabled Status Last Update Last Error Order Actions
Installed'; } elseif ($s === 'queued') { echo 'Queued'; } elseif ($s === 'failed') { echo 'Failed'; } elseif ($s === 'updating') { echo 'Updating'; } else { echo 'Not installed'; } ?>