isAdmin($user_id); if (!$isAdmin) { echo "

Access Denied: Admin privileges required.

"; return; } // ------------------------------------------------------------------- // Check whether is_default_for_billing column exists. // It is added by db_version 8 migration; show a warning if missing. // ------------------------------------------------------------------- $colExists = false; $colCheck = $db->resultQuery( "SELECT COUNT(*) AS cnt FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '{$db_prefix}config_mods' AND COLUMN_NAME = 'is_default_for_billing'" ); if (!empty($colCheck[0]['cnt']) && intval($colCheck[0]['cnt']) > 0) { $colExists = true; } if (!$colExists) { echo "
" . "

Database migration required. " . "The is_default_for_billing column is not present in {$db_prefix}config_mods. " . "Please run the billing module update (Admin → Module Manager → Update) to apply db_version 8.

" . "
"; return; } // ------------------------------------------------------------------- // Handle POST: save default mod for a game (home_cfg_id) // ------------------------------------------------------------------- $saveMsg = ''; if (isset($_POST['save_default']) && isset($_POST['home_cfg_id'])) { $save_home_cfg_id = intval($_POST['home_cfg_id']); $save_mod_cfg_id = intval($_POST['mod_cfg_id'] ?? 0); // Clear all current defaults for this game first $db->query( "UPDATE `{$db_prefix}config_mods` SET is_default_for_billing = 0 WHERE home_cfg_id = " . $save_home_cfg_id ); if ($save_mod_cfg_id > 0) { // Set the selected mod as default (only if it belongs to this game) $updated = $db->query( "UPDATE `{$db_prefix}config_mods` SET is_default_for_billing = 1 WHERE mod_cfg_id = " . $save_mod_cfg_id . " AND home_cfg_id = " . $save_home_cfg_id ); $saveMsg = $updated ? "

Default mod/build updated for game config #{$save_home_cfg_id}.

" : "

Failed to update default — mod may not belong to this game.

"; } else { $saveMsg = "

Default cleared for game config #{$save_home_cfg_id}. Billing will use the service-specific mod or fail with an admin-visible error if none is set.

"; } } echo $saveMsg; echo "

Game Mod/Build Defaults for Billing

"; echo "

Mark one mod/build per game as the auto-install default used when billing provisions a new server. " . "This is used when a billing service does not specify its own mod (mod_cfg_id = 0).

"; echo "

Priority order during provisioning: " . "1) Service-specific mod_cfg_id → 2) is_default_for_billing here → " . "3) Single available mod (auto-selected) → 4) Fail with admin-visible error.

"; // ------------------------------------------------------------------- // Load all game configs that have at least one mod defined // ------------------------------------------------------------------- $games = $db->resultQuery( "SELECT ch.home_cfg_id, ch.home_name FROM `{$db_prefix}config_homes` ch WHERE EXISTS ( SELECT 1 FROM `{$db_prefix}config_mods` cm WHERE cm.home_cfg_id = ch.home_cfg_id ) ORDER BY ch.home_name ASC" ); if (empty($games)) { echo "

No game configurations with mods found. Add mods via Admin → Game Manager → Configure Games.

"; return; } echo ""; echo ""; foreach ((array)$games as $game) { $hcfgid = intval($game['home_cfg_id']); $gameName = htmlspecialchars($game['home_name'] ?? "Game #{$hcfgid}"); // Load mods for this game $mods = $db->resultQuery( "SELECT mod_cfg_id, mod_key, mod_name, is_default_for_billing FROM `{$db_prefix}config_mods` WHERE home_cfg_id = " . $hcfgid . " ORDER BY mod_name ASC" ); if (empty($mods)) { continue; } $currentDefault = null; foreach ($mods as $m) { if (!empty($m['is_default_for_billing'])) { $currentDefault = htmlspecialchars($m['mod_name'] . ' (mod_cfg_id=' . $m['mod_cfg_id'] . ')'); } } echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } echo "
Gamehome_cfg_idAvailable Mods/BuildsCurrent DefaultAction
{$gameName}{$hcfgid}"; $modNames = array_map(fn($m) => htmlspecialchars($m['mod_name']), $mods); echo implode('
', $modNames); echo "
"; echo $currentDefault ? "✓ " . $currentDefault . "" : "None"; echo ""; // Form to set default echo "
"; echo ""; echo ""; echo " "; echo ""; echo "
"; echo "
"; // ------------------------------------------------------------------- // Show billing_services with their current mod_cfg_id // ------------------------------------------------------------------- echo "
"; echo "

Billing Services — Mod/Build Override

"; echo "

Services below have an explicit mod_cfg_id set. This takes priority over the game default above. " . "Set to 0 to fall back to the game default.

"; $services = $db->resultQuery( "SELECT s.service_id, s.service_name, s.home_cfg_id, s.mod_cfg_id, ch.home_name AS game_name, cm.mod_name FROM `{$db_prefix}billing_services` s LEFT JOIN `{$db_prefix}config_homes` ch ON ch.home_cfg_id = s.home_cfg_id LEFT JOIN `{$db_prefix}config_mods` cm ON cm.mod_cfg_id = s.mod_cfg_id ORDER BY s.service_name ASC" ); if (empty($services)) { echo "

No billing services configured.

"; } else { echo ""; echo ""; foreach ((array)$services as $svc) { echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } echo "
ServiceGameCurrent mod_cfg_idMod Name
".htmlspecialchars($svc['service_name'] ?? '')." (#".intval($svc['service_id']).")".htmlspecialchars($svc['game_name'] ?? 'N/A')."".intval($svc['mod_cfg_id']).(intval($svc['mod_cfg_id']) === 0 ? " (use game default)" : "")."".htmlspecialchars($svc['mod_name'] ?? ($svc['mod_cfg_id'] == 0 ? '—' : 'mod not found'))."
"; echo "

To change a service's mod, edit it in Admin → Billing → Services.

"; } echo "
"; } ?>