code wiki / _hdl_build / nx_pets_mp_relay_gate.nx
nx_pets_mp_relay_gate.nx source
↩ module page · 113 lines · 5674 B
1// nx_pets_mp_relay_gate.nx -- proves multiplayer pixelmon player-state transport:
2// the sovereign player-state codec (nx_pets_netstate) carried over the sovereign
3// server-relay (nx_room_relay) = no WebRTC/STUN/TURN/WebSocket. Each player POSTs a
4// packed snapshot; another player reads the roster, fetches that peer's frame, unpacks
5// it -> its decoded position/species. This is the exact transport MP-R1/R2 build on.
6// 1) round-trip: A & B in a room -> A sees B in roster + decodes B's pos/species
7// (B's z is NEGATIVE -> exercises sign-extended i32 decode)
8// 2) room isolation (neg-control): a peer in another room never appears
9// 3) staleness: peers past TTL drop from the roster
10// 4) bad-magic reject (neg-control): ps_unpack on garbage returns 0, no fabricated data
11// 5) anti-tautology: A's decoded state != B's decoded state (real per-peer frames)
12// Built nx_cc_sovereign -> nxasm_x86 (no gcc, no .sh).
13// license_tier: ORIGINAL
14import "nx_syscalls.nx"
15import "nx_gate_emit_lib.nx"
16import "nx_room_relay.nx"
17import "nx_pets_netstate.nx"
18import "nx_gate_verdict.nx"
19
20func setf(f: *i64, x: i64, y: i64, z: i64, yaw: i64, pitch: i64, sp: i64, caught: i64, act: i64, anim: i64, flags: i64) -> i64 {
21 f[0]=x; f[1]=y; f[2]=z; f[3]=yaw; f[4]=pitch
22 f[5]=sp; f[6]=caught; f[7]=act; f[8]=anim; f[9]=flags
23 return 0
24}
25
26func main() -> i64 {
27 g_puts("nx_pets_mp_relay gate (sovereign multiplayer pixelmon state transport)\n" as *u8)
28 var pass: i64 = 0; var total: i64 = 0
29
30 let N: i64 = 8
31 let SB: i64 = 64 // 28-byte frame fits with room to grow
32 let st: *i64 = sys_mmap((2 + 5*N) * 8) as *i64
33 let arena: *u8 = sys_mmap(N * SB)
34 rr_init(st, N, SB)
35
36 let ROOM_GAME: i64 = 0x7E70
37 let ROOM_OTHER: i64 = 0x9999
38 let PA: i64 = 100
39 let PB: i64 = 101
40 let PC: i64 = 200
41
42 // pack + post player A (peer 100) and player B (peer 101) into ROOM_GAME
43 let fa: *i64 = sys_mmap(10*8) as *i64
44 let fb: *i64 = sys_mmap(10*8) as *i64
45 let pa: *u8 = sys_mmap(SB)
46 let pb: *u8 = sys_mmap(SB)
47 setf(fa, 10, 4, 20, 128, 0-13, 2, 3, 1, 0, 1) // A: z=+20
48 setf(fb, 30, 5, 0-7, 900, 0, 1, 5, 2, 1, 0) // B: z=-7 (negative -> sign test)
49 let la: i64 = ps_pack(pa, fa)
50 let lb: i64 = ps_pack(pb, fb)
51 rr_post(st, arena, ROOM_GAME, PA, 1000, 1, pa, la)
52 rr_post(st, arena, ROOM_GAME, PB, 1000, 1, pb, lb)
53
54 // 1) ROUND-TRIP: from A's view, roster -> [101]; fetch B's frame, unpack, check pos/species
55 let out: *i64 = sys_mmap(N * 8) as *i64
56 let dec: *i64 = sys_mmap(10*8) as *i64
57 var c1: i64 = rr_roster(st, ROOM_GAME, PA, 1000, 8000, out)
58 var r1: i64 = 1
59 if c1 != 1 { r1 = 0 }
60 if out[0] != PB { r1 = 0 }
61 let sB: i64 = rr_live(st, ROOM_GAME, PB, 1000, 8000)
62 if sB < 0 { r1 = 0 } else {
63 let ok: i64 = ps_unpack((arena + sB*SB) as *u8, rr_flen(st, sB), dec)
64 if ok != 1 { r1 = 0 }
65 if dec[0] != 30 { r1 = 0 } // x
66 if dec[2] != (0-7){ r1 = 0 } // z (negative, sign-extended)
67 if dec[5] != 1 { r1 = 0 } // species_held
68 if dec[6] != 5 { r1 = 0 } // caught_count
69 if dec[7] != 2 { r1 = 0 } // action
70 }
71 pass = pass + g_check("round-trip: A decodes B's pos/species over the relay" as *u8, r1); total=total+1
72
73 // 2) ROOM ISOLATION (neg-control): peer 200 in ROOM_OTHER never appears in A's roster
74 let pc: *u8 = sys_mmap(SB)
75 let fc: *i64 = sys_mmap(10*8) as *i64
76 setf(fc, 99, 9, 99, 0, 0, 3, 1, 0, 0, 0)
77 rr_post(st, arena, ROOM_OTHER, PC, 1000, 1, pc, ps_pack(pc, fc))
78 let c2: i64 = rr_roster(st, ROOM_GAME, PA, 1000, 8000, out)
79 pass = pass + g_check("room isolation: other-room peer absent (still 1)" as *u8, c2 == 1); total=total+1
80
81 // 3) STALENESS: advance now past TTL -> roster empties
82 let c3: i64 = rr_roster(st, ROOM_GAME, PA, 20000, 8000, out)
83 pass = pass + g_check("stale peers (past TTL) drop from roster" as *u8, c3 == 0); total=total+1
84
85 // 4) BAD-MAGIC REJECT (neg-control): garbage frame -> unpack returns 0, no data
86 let bad: *u8 = sys_mmap(SB)
87 var k: i64 = 0; while k < SB { bad[k] = 0xFF as u8; k=k+1 }
88 let rbad: i64 = ps_unpack(bad, 28, dec)
89 pass = pass + g_check("bad-magic frame rejected (unpack=0)" as *u8, rbad == 0); total=total+1
90
91 // 5) ANTI-TAUTOLOGY: A's own decoded state differs from B's (real per-peer frames)
92 rr_post(st, arena, ROOM_GAME, PA, 21000, 2, pa, la) // refresh A so it's live again
93 let sA2: i64 = rr_live(st, ROOM_GAME, PA, 21000, 8000)
94 var r5: i64 = 1
95 let decA: *i64 = sys_mmap(10*8) as *i64
96 if sA2 < 0 { r5 = 0 } else {
97 ps_unpack((arena + sA2*SB) as *u8, rr_flen(st, sA2), decA)
98 if decA[0] != 10 { r5 = 0 } // A.x == 10
99 if decA[0] == dec[0] { r5 = 0 } // A.x (10) != B.x (30) -> not a constant
100 }
101 pass = pass + g_check("anti-tautology: A.x=10 distinct from B.x=30" as *u8, r5); total=total+1
102
103 g_puts("---- pets-mp-relay gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
104 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
105 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
106 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
107 let ctr__dry: *i64 = gv_ctr()
108 ctr__dry[0] = pass
109 ctr__dry[1] = total
110 let rc__dry: i64 = gv_verdict("PETS-MP-RELAY-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
111 sys_exit(rc__dry)
112 return rc__dry
113}