Simplify game files to automatic T5 and T6 uploads

This commit is contained in:
2026-10-04 12:23:36 -04:00
parent 482e27e735
commit 68323c0baa
19 changed files with 588 additions and 232 deletions
+7 -5
View File
@@ -4,7 +4,7 @@ import { db } from '../db/index.js';
import { config, relDestForKind, serverDir } from '../config.js';
import { nativeInstance, nativeRequest, type NativeInstance } from '../backends/native.js';
import { getHost, getHostOperation, listHosts, nextHostPort, queueHostOperation, releaseHostPorts, requireReadyHost, reserveHostPort } from '../hosts/index.js';
import { getLibraryVersion, requireReadyLibrary } from '../game-files/index.js';
import { newestReadyLibrary, requireReadyLibrary } from '../game-files/index.js';
import { blueprintRecipe, captureRecipe, recipeForDeployment, summarizeRecipe, type LaunchRecipe } from '../fleet/launch-recipes.js';
import { getServerKey, saveServerKey } from '../fleet/server-keys.js';
import { activeBetaRemovalBlocker, getServer } from '../fleet/servers.js';
@@ -29,9 +29,11 @@ interface FilePlan { id: number; path: string; contentBase64: string | null; sha
export function nativeSelection(input: Record<string, unknown>, game: string): NativeSelection {
if (typeof input.hostId !== 'string' || !input.hostId) throw new Error('Select a ready host.');
if (typeof input.libraryId !== 'string' || !input.libraryId) throw new Error('Select a published game-file version.');
const version = getLibraryVersion(input.libraryId);
if (!version || version.game !== game || version.state !== 'ready') throw new Error('Choose a published game-file version for the selected game.');
const version = newestReadyLibrary(game);
if (!version) throw new Error(`Upload ${game.toUpperCase()} game files before launching a server.`);
if (input.libraryId !== undefined && input.libraryId !== '' && input.libraryId !== version.id) {
throw new Error(`The current ${game.toUpperCase()} game files changed. Refresh the launch preview.`);
}
const image = input.image === undefined || input.image === '' ? config.komodo.defaultImage : input.image;
if (typeof image !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9._/:@-]{0,499}$/.test(image)) throw new Error('Invalid runtime image.');
const host = requireReadyHost(input.hostId, { image, requiredBytes: 1024 ** 3 });
@@ -68,7 +70,7 @@ export function previewNativeCreation(input: Record<string, unknown>): LaunchPre
.run(id, expiresAt, name, port, JSON.stringify(recipe), blueprintName);
const checks: LaunchPreview['checks'] = [
{ label: 'Host readiness', state: 'pass', detail: `${getHost(selection.hostId)!.name}: connected, Docker ready, storage and runtime verified.` },
{ label: 'Game files', state: 'pass', detail: `Immutable library version ${selection.libraryId} is ready on the selected host.` },
{ label: 'Game files', state: 'pass', detail: `The latest ${recipe.game.toUpperCase()} game files are verified on the selected host.` },
{ label: 'Lobby', state: name ? 'pass' : 'blocked', detail: name ?? 'All lobby IDs for this map are reserved.' },
{ label: 'Host port', state: port ? 'pass' : 'blocked', detail: port ? `${selection.bindAddress}:${port} / UDP and TCP` : 'No available UDP/TCP port on this host.' },
{ label: 'Configuration', state: 'pass', detail: recipe.configSource }