Prepare alpha 11 with online diagnostics
This commit is contained in:
1 parent
d53467baf2
commit
4d9e6d9185
14 files changed
+550
-77
No files matched your search
@@ -49,6 +49,20 @@ assert.strictEqual(JSON.parse(context.rpcInviteFriend(inviteCtx, {}, inviteNk, J
|
||||
assert.strictEqual(sentInvites.length, 1, "A rate-limited invitation must not send another notification.");
|
||||
assert.strictEqual(JSON.parse(context.rpcInviteFriend({ userId: friendId }, {}, inviteNk, JSON.stringify({ friend_id: hostId, room_code: "ABC123" }))).accepted, false, "Only the private room host may invite.");
|
||||
assert.strictEqual(JSON.parse(context.rpcInviteFriend(inviteCtx, {}, { ...inviteNk, friendsList: () => ({ friends: [] }) }, JSON.stringify({ friend_id: friendId, room_code: "ABC123" }))).accepted, false, "Only mutual friends may be invited.");
|
||||
const nameLookupNk = {
|
||||
sqlQuery(_query, params) {
|
||||
assert.strictEqual(params[0], "Emporex2", "Player search must use parameter binding.");
|
||||
return [{ id: friendId, display_name: "Emporex2" }];
|
||||
}
|
||||
};
|
||||
assert.deepStrictEqual(JSON.parse(context.rpcFindPlayerByName(inviteCtx, {}, nameLookupNk, JSON.stringify({ display_name: "Emporex2" }))),
|
||||
{ found: true, user_id: friendId, display_name: "Emporex2" });
|
||||
assert.strictEqual(JSON.parse(context.rpcFindPlayerByName(inviteCtx, {},
|
||||
{ sqlQuery: () => [{ id: friendId, display_name: "Same" }, { id: "third", display_name: "Same" }] },
|
||||
JSON.stringify({ display_name: "Same" }))).error, "ambiguous", "Duplicate display names must not invite the wrong account.");
|
||||
assert.strictEqual(JSON.parse(context.rpcFindPlayerByName(inviteCtx, {},
|
||||
{ sqlQuery: () => [{ id: hostId, display_name: "Self" }] },
|
||||
JSON.stringify({ display_name: "Self" }))).error, "not_found");
|
||||
const flakState = {
|
||||
towers: [{ id: 20, type: 6, x: 800, y: 200, owner: 0, level: 1, cooldown: 0 }],
|
||||
enemies: [
|
||||
@@ -344,4 +358,58 @@ state = context.matchJoin({}, logger, nk, dispatcher, 33, state, [presenceB]).st
|
||||
assert.strictEqual(state.pausedForReconnect, false);
|
||||
assert.strictEqual(state.slots["pilot-b"], 1);
|
||||
|
||||
const bossState = context.initialState({ difficulty: 1 });
|
||||
bossState.wave = 5;
|
||||
bossState.waveSchedule = [{ type: 5, boss: true }];
|
||||
const originalRandom = context.Math.random;
|
||||
context.Math.random = () => 0;
|
||||
context.spawnEnemy(bossState);
|
||||
context.Math.random = originalRandom;
|
||||
assert.ok(bossState.enemies[0].shield, "The first boss shield test needs a shielded ship.");
|
||||
assert.strictEqual(bossState.enemies[0].max_shield_hp, bossState.enemies[0].max_hp * 0.275,
|
||||
"Wave-five mothership shields must be half their former strength.");
|
||||
const laterBossState = context.initialState({ difficulty: 1 });
|
||||
laterBossState.wave = 10;
|
||||
laterBossState.waveSchedule = [{ type: 8, boss: true }];
|
||||
context.Math.random = () => 0;
|
||||
context.spawnEnemy(laterBossState);
|
||||
context.Math.random = originalRandom;
|
||||
assert.strictEqual(laterBossState.enemies[0].max_shield_hp, laterBossState.enemies[0].max_hp * 0.55,
|
||||
"Later bosses retain their original shield balance.");
|
||||
|
||||
const diagnosticStore = new Map();
|
||||
const diagnosticNk = {
|
||||
sha256Hash(value) { return crypto.createHash("sha256").update(value).digest("hex"); },
|
||||
storageRead(ops) { return ops.map(op => diagnosticStore.get(`${op.collection}:${op.userId}:${op.key}`)).filter(Boolean); },
|
||||
storageWrite(ops) { for (const op of ops) diagnosticStore.set(`${op.collection}:${op.userId}:${op.key}`, { key: op.key, value: op.value }); },
|
||||
storageList(userId, collection) {
|
||||
return { objects: [...diagnosticStore.entries()].filter(([key]) => key.startsWith(`${collection}:${userId}:`)).map(([, object]) => object), cursor: "" };
|
||||
},
|
||||
storageDelete(ops) { for (const op of ops) diagnosticStore.delete(`${op.collection}:${op.userId}:${op.key}`); }
|
||||
};
|
||||
const diagnosticMatchId = "sample-match.123";
|
||||
let diagState = context.initialState({ difficulty: 1 });
|
||||
diagState = context.matchJoin({ matchId: diagnosticMatchId }, logger, diagnosticNk, dispatcher, 1, diagState,
|
||||
[{ userId: hostId, username: "Host" }, { userId: friendId, username: "Guest" }]).state;
|
||||
const report = { match_id: diagnosticMatchId, version: "0.26", records: [
|
||||
{ event: "window", utc: "2026-10-10T13:00:00", snapshots: 90, gap_p95_ms: 103, player_name: "must_not_store" },
|
||||
{ event: "end", utc: "2026-10-10T13:00:01", reason: "left_match" }
|
||||
] };
|
||||
const firstReport = JSON.parse(context.rpcSubmitOnlineDiagnostics({ userId: hostId }, logger, diagnosticNk, JSON.stringify(report)));
|
||||
const secondReport = JSON.parse(context.rpcSubmitOnlineDiagnostics({ userId: friendId }, logger, diagnosticNk, JSON.stringify(report)));
|
||||
assert.strictEqual(firstReport.round_id, secondReport.round_id, "Both players need one shared round ID.");
|
||||
assert.strictEqual(firstReport.slot, 0);
|
||||
assert.strictEqual(secondReport.slot, 1);
|
||||
assert.strictEqual(JSON.parse(context.rpcSubmitOnlineDiagnostics({ userId: "stranger" }, logger, diagnosticNk, JSON.stringify(report))).error,
|
||||
"not_participant", "A third account cannot attach data to the round.");
|
||||
const listedReports = JSON.parse(context.rpcListOnlineDiagnostics({}, logger, diagnosticNk, "{}")).reports;
|
||||
assert.strictEqual(listedReports.length, 2);
|
||||
assert.ok(!JSON.stringify(listedReports).includes("must_not_store"), "The server must discard arbitrary client strings.");
|
||||
const pairReports = JSON.parse(context.rpcListOnlineDiagnostics({}, logger, diagnosticNk,
|
||||
JSON.stringify({ round_id: firstReport.round_id }))).reports;
|
||||
assert.strictEqual(pairReports.length, 2);
|
||||
assert.strictEqual(pairReports[0].round_id, pairReports[1].round_id);
|
||||
assert.ok(!JSON.stringify(pairReports).includes("must_not_store"), "Detailed reports must also omit unapproved strings.");
|
||||
assert.throws(() => context.rpcListOnlineDiagnostics({ userId: hostId }, logger, diagnosticNk, "{}"), /server-to-server/);
|
||||
|
||||
console.log("VOID_BASTION_SERVER_SIM_OK");
|
||||
Reference in new issue
Block a user