Files
Cs2-Mapveto/server/src/servers/staticPoolAdapter.js
SPP UserandClaude Opus 5.5 104aa1a67b Backend: Match-Lobbys, Map-Veto, Echtzeit und CS2-Serveradapter
Express + Socket.IO + SQLite. Veto-Engine mit konfigurierbaren Map-Pools
und validierten Abläufen, rollenbasierte Berechtigungen, Server-Lebenszyklus
mit Demo-, Docker- und Static-Pool-Adapter (RCON), automatisches Herunterfahren.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:50:22 +01:00

57 lines
1.9 KiB
JavaScript

import { configureViaRcon, rconStatus } from './rconConfigure.js';
import { runRcon } from './rcon.js';
/**
* Nutzt bereits laufende, selbst betriebene CS2-Server (CS2_STATIC_SERVERS).
* "Start" bedeutet hier: einen freien Server aus dem Pool reservieren und per RCON prüfen.
* "Stopp" gibt ihn wieder frei und setzt ein zufälliges Serverpasswort, damit niemand
* mit alten Zugangsdaten auf dem Server bleibt. Der Prozess selbst wird nicht beendet.
*/
export class StaticPoolServerAdapter {
constructor({ servers }, { getUsedPorts }) {
this.name = 'static';
this.simulated = false;
this.servers = servers;
this.getUsedPorts = getUsedPorts;
if (!servers.length) throw new Error('SERVER_ADAPTER=static benötigt CS2_STATIC_SERVERS');
}
async start() {
const used = this.getUsedPorts();
const free = this.servers.find((s) => !used.has(`${s.host}:${s.port}`));
if (!free) throw new Error('Alle konfigurierten Server sind belegt');
return {
handle: { host: free.host, port: free.port, poolKey: `${free.host}:${free.port}`, rconPassword: free.rconPassword },
host: free.host,
port: free.port,
tvPort: free.tvPort,
};
}
target(handle) {
return { host: handle.host, port: handle.port, password: handle.rconPassword };
}
async status(handle) {
try {
const status = await rconStatus(this.target(handle));
return { state: 'running', playerCount: status.playerCount, map: status.map };
} catch (err) {
return { state: 'starting', message: `Server nicht erreichbar: ${err.message}` };
}
}
async configure(handle, plan) {
await configureViaRcon(this.target(handle), plan);
}
async sendCommands(handle, commands) {
return runRcon(this.target(handle), commands);
}
async stop(handle, { resetPassword } = {}) {
if (!resetPassword) return;
await runRcon(this.target(handle), [`sv_password "${resetPassword}"`, 'tv_stoprecord']).catch(() => {});
}
}