Messerrunde auf dem eigenen Match-Server, danach derselbe Server fürs Match

Bei Seitenwahl per Messerrunde richtet die App den Match-Server in der Lobby als
Messer-Server ein (Passwort des Matches, Aufwärmphase ohne Ende). Spieler sehen die
Verbindungsdaten in der Lobby, der Organisator startet bzw. wiederholt die Runde.
Nach dem Veto wird derselbe Server fürs Match eingerichtet, die Messer-Einstellungen
werden zurückgenommen.
This commit is contained in:
mregosar committed 2026-11-01 18:25:07 +01:00
1 parent 2c57b8c170
commit 13320313ec
10 files changed
+220 -20

No files matched your search

+50
View File
@@ -713,3 +713,53 @@ test('Konsole: nur für Admins, Ausgabe kommt live, unbekannte Server 404', asyn
await close();
}
});
test('Messerrunde auf dem eigenen Match-Server: Verbindungsdaten in der Lobby, danach derselbe Server fürs Match', async () => {
const { app, call, close } = await setup();
try {
const created = await call('POST', '/matches', { body: { teamA: 'Alpha', teamB: 'Bravo', mode: 'wingman', format: 'bo1', vetoStart: 'knife' } });
const { id, organizerToken: org } = created.body;
const codes = (await call('GET', `/matches/${id}`, { token: org })).body.organizer.codes;
const tokens = {};
for (const [name, team] of [['a1', 'A'], ['a2', 'A'], ['b1', 'B'], ['b2', 'B']]) {
tokens[name] = (await call('POST', `/matches/${id}/join`, { body: { code: codes[team], nickname: name } })).body.playerToken;
}
// Vor dem Start: Aktionen gehen noch nicht
assert.equal((await call('POST', `/matches/${id}/server/knife-start`, { token: org })).status, 409);
await app.manager.poll();
await waitFor(() => app.manager.row(id).knife_phase === 'warmup', { label: 'Messerrunde eingerichtet' });
const player = (await call('GET', `/matches/${id}`, { token: tokens.b1 })).body;
assert.deepEqual(player.server.knife, { ready: true, phase: 'warmup' });
assert.equal(player.server.connect.password, app.manager.row(id).server_password, 'Spieler bekommen das Passwort des Matches');
const pub = (await call('GET', `/matches/${id}`)).body;
assert.equal(pub.server?.connect, undefined, 'öffentlich keine Verbindungsdaten');
// Nur der Organisator startet die Runde
assert.equal((await call('POST', `/matches/${id}/server/knife-start`, { token: tokens.a1 })).status, 403);
assert.equal((await call('POST', `/matches/${id}/server/knife-start`, { token: org })).status, 200);
assert.equal(app.manager.row(id).knife_phase, 'live');
assert.equal((await call('POST', `/matches/${id}/server/knife-reset`, { token: org })).status, 200);
assert.equal(app.manager.row(id).knife_phase, 'warmup');
// Nach dem Veto wird derselbe Server fürs Match eingerichtet, die Messer-Einstellungen werden zurückgenommen
const handle = app.manager.row(id).handle;
const plans = [];
const configure = app.adapter.configure.bind(app.adapter);
app.adapter.configure = async (h, plan) => { plans.push(plan); return configure(h, plan); };
for (const t of Object.values(tokens)) await call('POST', `/matches/${id}/ready`, { token: t, body: { ready: true } });
assert.equal((await call('POST', `/matches/${id}/veto/start`, { token: org, body: { firstTeam: 'A' } })).status, 200);
const snap = (await call('GET', `/matches/${id}`, { token: org })).body;
const capA = snap.teams.A.players.find((p) => p.isCaptain)?.nickname ?? 'a1';
const capB = snap.teams.B.players.find((p) => p.isCaptain)?.nickname ?? 'b1';
await playVeto(call, id, { A: tokens[capA], B: tokens[capB] });
await waitFor(() => app.manager.row(id).status === 'configured', { label: 'Match eingerichtet' });
const row = app.manager.row(id);
assert.equal(row.handle, handle, 'derselbe Server');
assert.equal(row.knife_at, null);
assert.ok(plans.at(-1).afterMapChange.includes('mp_give_player_c4 1'));
assert.equal((await call('GET', `/matches/${id}`, { token: tokens.b1 })).body.server.knife, undefined);
} finally {
await close();
}
});