Hinweise im Ingame-Chat: Map, Seitenwahl, Serienstand, Match-Start, Map-Ende

Nach dem Laden einer Map schreibt die App per RCON say, welche Map gespielt wird, wer sie gewählt hat, wer als CT und T startet und den Serienstand. Die Hinweise wiederholen sich während der Aufwärmphase jede Minute (höchstens zehnmal). Beim Match-Start und am Map-Ende folgen Start-, Ergebnis- und Serienhinweise.
This commit is contained in:
mregosar committed 2026-11-01 21:19:13 +01:00
1 parent 7e17a33c3f
commit ece21db78a
4 files changed
+247

No files matched your search

+36
View File
@@ -831,3 +831,39 @@ test('Offene Lobbys werden nach LOBBY_MAX_HOURS samt Server gelöscht, laufende
await close();
}
});
test('Ingame-Chat: Hinweise nach dem Laden, beim Start und am Map-Ende', async () => {
const { app, call, close } = await setup();
try {
const said = [];
const send = app.adapter.sendCommands.bind(app.adapter);
app.adapter.sendCommands = async (h, commands) => {
said.push(...commands.filter((c) => c.startsWith('say ')).map((c) => c.slice(4)));
return send(h, commands);
};
const { id, org, tokens } = await readyWingmanMatch(call, 'bo3');
await call('POST', `/matches/${id}/veto/start`, { token: org });
const snap = (await call('GET', `/matches/${id}`, { token: org })).body;
const cap = (t) => tokens[snap.teams[t].players.find((p) => p.isCaptain).nickname];
await playVeto(call, id, { A: cap('A'), B: cap('B') });
await app.manager.poll();
await waitFor(() => app.manager.row(id).status === 'configured', { label: 'Map 1 eingerichtet' });
await waitFor(() => said.some((l) => l.startsWith('Map 1 von 3')), { label: 'Hinweis nach dem Laden' });
assert.ok(said.some((l) => / startet als CT, .* als T$/.test(l)), 'Seiten werden genannt');
assert.ok(said.includes('Serienstand: Alpha 0:0 Bravo'));
assert.equal((await call('POST', `/matches/${id}/server/warmup-end`, { token: org })).status, 200);
await waitFor(() => said.some((l) => l.startsWith('Match live!')), { label: 'Hinweis beim Start' });
const map = app.service.seriesMaps(id)[0].map;
const key = app.manager.row(id).config_key;
const body = ['Team playing "CT": Alpha', 'Team playing "TERRORIST": Bravo', 'World triggered "Match_Start" on "' + map + '"',
'Team "CT" triggered "SFUI_Notice_CTs_Win" (CT "1") (T "0")', 'World triggered "Round_End"',
`Game Over: scrimcomp2v2 ${map} score 1:0 after 1 min`].join('\n');
await fetch(`http://127.0.0.1:${app.server.address().port}/api/logs/${id}/${key}`, { method: 'POST', body });
await waitFor(() => said.some((l) => /^Map 1 \(.+\) geht an Alpha mit 1:0$/.test(l)), { label: 'Hinweis am Map-Ende' });
assert.ok(said.some((l) => l.startsWith('Nächste Map: ')));
} finally {
await close();
}
});
+45
View File
@@ -0,0 +1,45 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { chatText, mapEndLines, mapLoadedLines, matchStartLines, sayCommands } from '../src/servers/chatAnnouncements.js';
const teams = { A: 'Nordlicht', B: 'Hafenkante' };
test('Hinweise nach dem Laden: Map, Wahl, Seiten, Serienstand, Aufwärmphase', () => {
const lines = mapLoadedLines({
teams, total: 3, series: { A: 1, B: 0 },
map: { number: 2, mapName: 'Inferno', pickedBy: 'B', sideChosenBy: 'A', ctTeam: 'A' },
});
assert.deepEqual(lines, [
'Map 2 von 3: Inferno - gewählt von Hafenkante',
'Nordlicht hat die Seite gewählt: Nordlicht startet als CT, Hafenkante als T',
'Serienstand: Nordlicht 1:0 Hafenkante',
'Aufwärmphase - das Match startet, sobald der Organisator es freigibt',
]);
const bo1 = mapLoadedLines({ teams, total: 1, series: { A: 0, B: 0 }, map: { number: 1, mapName: 'Nuke', pickedBy: null, sideChosenBy: 'B', ctTeam: 'B' } });
assert.equal(bo1[0], 'Map: Nuke - Entscheidungsmap');
assert.ok(!bo1.some((l) => l.startsWith('Serienstand')), 'kein Serienstand im BO1');
});
test('Hinweise bei Match-Start und Map-Ende', () => {
assert.deepEqual(matchStartLines({ teams, ctTeam: 'B' }), ['Match live! Hafenkante (CT) gegen Nordlicht (T) - viel Glück, have fun']);
const next = mapEndLines({
teams, total: 3, decided: null, nextMapName: 'Inferno', autoAdvanceSeconds: 30, series: { A: 1, B: 0 },
map: { number: 1, mapName: 'Mirage', winner: 'A', score: { A: 13, B: 9 } },
});
assert.deepEqual(next, [
'Map 1 (Mirage) geht an Nordlicht mit 13:9',
'Serienstand: Nordlicht 1:0 Hafenkante',
'Nächste Map: Inferno, wird in 30 s geladen - bleibt auf dem Server',
]);
const won = mapEndLines({
teams, total: 3, decided: 'B', nextMapName: null, autoAdvanceSeconds: 30, series: { A: 0, B: 2 },
map: { number: 2, mapName: 'Nuke', winner: 'B', score: { A: 5, B: 13 } },
});
assert.equal(won[1], 'Hafenkante gewinnt die Serie 2:0 - danke fürs Spielen!');
});
test('Chattexte können keine weiteren Befehle anhängen', () => {
assert.equal(chatText('Team"; rcon_password x; say "'), 'Team rcon_password x say');
assert.deepEqual(sayCommands(['Hallo; quit', '', 'Stand 13:9']), ['say Hallo quit', 'say Stand 13:9']);
assert.ok(chatText('x'.repeat(300)).length <= 120);
});