Add fixed core HUD and shared service window for T5 and T6
This commit is contained in:
@@ -44,7 +44,7 @@ function functions(source) {
|
||||
function engine(game) {
|
||||
const source = readFileSync(new URL(`${game}/scripts/tws_${game}_leaderboard.gsc`, root), 'utf8');
|
||||
const all = functions(source);
|
||||
const excluded = new Set(['lb_worker', 'lb_welcome', 'lb_get', 'lb_collect', 'lb_log', 'lb_show_hud', 'lb_hud_help_visible', 'lb_hud_end_game', 'lb_hud_destroy', 'lb_chat_listener', 'lb_request', 'lb_hud_disconnect']);
|
||||
const excluded = new Set(['lb_worker', 'lb_welcome', 'lb_get', 'lb_collect', 'lb_log', 'lb_chat_listener', 'lb_request']);
|
||||
const table = [];
|
||||
for (let i = 1; i < 256; i++) table[String.fromCharCode(i)] = i;
|
||||
const dvars = { mapname: game === 't5' ? 'zombie_theater' : 'zm_transit', ui_gametype: 'zstandard', ui_zm_mapstartlocation: 'town' };
|
||||
@@ -111,6 +111,42 @@ for (const game of ['t5', 't6']) {
|
||||
c.level.tws_lb_cache = undefined;
|
||||
assert.equal(queries.length, 0);
|
||||
});
|
||||
check(`${game} common owns the record service window`, () => {
|
||||
const commonPath = game === 't5' ? 'scripts\\sp\\tws_t5_common' : 'scripts\\zm\\tws_t6_common';
|
||||
assert(source.includes(`self ${commonPath}::show_record(snapshot);`));
|
||||
assert(!source.includes('lb_show_hud'));
|
||||
assert(!source.includes('lb_hud_'));
|
||||
assert(!source.includes('tws_help_elems'));
|
||||
assert(!source.includes('iPrintLnBold'));
|
||||
assert(!source.includes('make_text_elem'));
|
||||
assert(!source.includes('tws_t5_hud') && !source.includes('tws_t6_hud'));
|
||||
});
|
||||
check(`${game} manual missing/stale requests cancel welcome and reach the service`, () => {
|
||||
const calls = [];
|
||||
c.self = { notify: (event) => calls.push(['notify', event]) };
|
||||
c.recordService = (snapshot) => calls.push(['record', snapshot]);
|
||||
const request = all.get('lb_request')
|
||||
.replace(/\b(?:self|level) endon\([^;]*\);/g, '')
|
||||
.replace(/\bself notify\(/g, 'self.notify(')
|
||||
.replace(/\bself scripts\\(?:sp|zm)\\tws_t[56]_common::show_record\(/g, 'recordService(');
|
||||
vm.runInContext(request, c);
|
||||
for (const cached of [undefined, { saved_at: 1, round: 52, lines: ['Alice'] }]) {
|
||||
c.level.tws_lb_cache = cached;
|
||||
c.lb_request(false);
|
||||
assert.deepEqual(calls, []);
|
||||
c.lb_request(true);
|
||||
assert.deepEqual(calls, [['notify', 'tws_lb_requested'], ['record', undefined]]);
|
||||
calls.length = 0;
|
||||
}
|
||||
const snapshot = { saved_at: 1000000, round: 0, lines: [] };
|
||||
c.level.tws_lb_cache = snapshot;
|
||||
c.lb_request(false);
|
||||
assert.deepEqual(calls, [['record', snapshot]]);
|
||||
calls.length = 0;
|
||||
c.lb_request(true);
|
||||
assert.deepEqual(calls, [['notify', 'tws_lb_requested'], ['record', snapshot]]);
|
||||
c.level.tws_lb_cache = undefined;
|
||||
});
|
||||
check(`${game} unicode and URL encoding`, () => {
|
||||
assert.equal(c.lb_url_encode(bytes('t6:zm_transit:town /?&=#é')), 't6%3Azm_transit%3Atown%20%2F%3F%26%3D%23%C3%A9');
|
||||
assert.equal(text(c.lb_display_text(bytes('^1Alice\n^7 René 🧟'), 64)), 'Alice René 🧟');
|
||||
@@ -193,11 +229,33 @@ for (const game of ['t5', 't6']) {
|
||||
assert.equal(c.lb_refresh(), undefined);
|
||||
c.level.tws_lb_override = '';
|
||||
});
|
||||
check(`${game} all holders fit bounded messages`, () => {
|
||||
check(`${game} all holders fit bounded service rows`, () => {
|
||||
const names = Array.from({ length: 100 }, (_, i) => `Holder ${i}`);
|
||||
const lines = Array.from(c.lb_holder_lines(names));
|
||||
assert(lines.every((line) => line.length <= 100));
|
||||
assert(lines.every((line) => c.lb_holder_width(line) <= 16));
|
||||
assert.deepEqual(lines.join(', ').split(', '), names);
|
||||
assert.deepEqual(Array.from(c.lb_holder_lines([])), []);
|
||||
assert.deepEqual(Array.from(c.lb_holder_lines(['Alex', 'Sam', 'Jamie'])), ['Alex, Sam, Jamie']);
|
||||
});
|
||||
check(`${game} holder width counts glyphs and clips without breaking UTF-8`, () => {
|
||||
const samples = ['M'.repeat(64), 'é'.repeat(32), '🧟'.repeat(16), '玩家名字'.repeat(5),
|
||||
'abcdefghijklééé', '^1Alice\n^7 René 🧟', '^1\n\t'];
|
||||
for (const sample of samples) {
|
||||
const value = c.lb_holder_name(bytes(sample));
|
||||
assert(c.lb_holder_width(value) <= 16, sample);
|
||||
assert(c.lb_utf8_valid(value), sample);
|
||||
assert(!text(value).includes('\uFFFD'), sample);
|
||||
assert(!/[\x00-\x1f\x7f^]/.test(value), sample);
|
||||
assert(value.length > 0, sample);
|
||||
}
|
||||
assert.equal(c.lb_holder_name('M'.repeat(64)), 'M'.repeat(13) + '...');
|
||||
assert.equal(text(c.lb_holder_name(bytes('🧟'.repeat(16)))), '🧟'.repeat(6) + '...');
|
||||
assert.equal(c.lb_holder_name('^1\n\t'), 'Unknown player');
|
||||
assert.equal(c.lb_holder_width(bytes('René 🧟')), 8);
|
||||
const names = Array(100).fill(bytes('同じ名前'.repeat(5)));
|
||||
const rows = Array.from(c.lb_holder_lines(names));
|
||||
assert.equal(rows.length, names.length, 'identical long names still represent every holder');
|
||||
assert(rows.every((line) => c.lb_holder_width(line) <= 16 && c.lb_utf8_valid(line)));
|
||||
});
|
||||
if (game === 't6') {
|
||||
const variants = [
|
||||
|
||||
Reference in New Issue
Block a user