From d7524f48a1cda393626d42aea52bfa9946b0ddc5 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Sun, 27 Sep 2026 18:43:28 -0700 Subject: [PATCH] fix oskiewar fairy caption crash and retry rate-limited shirt edits --- apple/aesel/Sources/ContentView.swift | 16 +++++++++++++--- xbox/live/oskiewar.js | 2 +- xbox/live/tests/pool-playground.test.mjs | 13 +++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/apple/aesel/Sources/ContentView.swift b/apple/aesel/Sources/ContentView.swift index 7040ab3dbe..a7f2a35cb8 100644 --- a/apple/aesel/Sources/ContentView.swift +++ b/apple/aesel/Sources/ContentView.swift @@ -1010,18 +1010,23 @@ private struct CurtainAccountButtonStyle: ButtonStyle { private final class OskiewarAttachment: ObservableObject { @Published var status = "" @Published var editStatus = "" + private var intent = 0 + private var starRequested = false func setIntent(_ value: Int) { + intent = value guard let socket else { return } Task { try? await socket.send(.string("{\"type\":\"oskiewar:flags\",\"content\":{\"aeselIntent\":\(value)}}")) } } func applyStar() { guard let socket, status.hasPrefix("Connected") else { editStatus = "Connect to a game first"; return } + starRequested = true; intent = 2 Task { do { - try await socket.send(.string("{\"type\":\"oskiewar:flags\",\"content\":{\"aeselIntent\":2}}")) - try await socket.send(.string("{\"type\":\"oskiewar:flags\",\"content\":{\"shirtSymbol\":2}}")) + try await socket.send(.string("{\"type\":\"oskiewar:flags\",\"content\":{\"aeselIntent\":2,\"shirtSymbol\":2}}")) editStatus = "Star sent to game" try await Task.sleep(nanoseconds: 3_000_000_000) + guard self.socket === socket else { return } + intent = 0 try await socket.send(.string("{\"type\":\"oskiewar:flags\",\"content\":{\"aeselIntent\":0}}")) } catch { editStatus = "Could not send star" } } @@ -1033,6 +1038,7 @@ private final class OskiewarAttachment: ObservableObject { func disconnect() { receiver?.cancel(); heartbeat?.cancel() + intent = 0; starRequested = false socket?.cancel(with: .goingAway, reason: nil) socket = nil; receiver = nil; heartbeat = nil; room = ""; status = "Oskiewar disconnected" } @@ -1065,7 +1071,11 @@ private final class OskiewarAttachment: ObservableObject { do { while !Task.isCancelled { pulse = (pulse + 1) % 64 - try await task.send(.string("{\"type\":\"oskiewar:flags\",\"content\":{\"aeselPulse\":\(pulse)}}")) + guard let self, self.socket === task else { return } + var flags: [String: Int] = ["aeselPulse": pulse, "aeselIntent": self.intent] + if self.starRequested { flags["shirtSymbol"] = 2 } + let data = try JSONSerialization.data(withJSONObject: ["type": "oskiewar:flags", "content": flags]) + try await task.send(.string(String(decoding: data, as: UTF8.self))) try await Task.sleep(nanoseconds: 1_000_000_000) } } catch { if !Task.isCancelled { self?.status = "Oskiewar connection lost" } } diff --git a/xbox/live/oskiewar.js b/xbox/live/oskiewar.js index b1461b08ae..acf3282932 100644 --- a/xbox/live/oskiewar.js +++ b/xbox/live/oskiewar.js @@ -4059,7 +4059,7 @@ function drawAeselFairy(t){ if(label){ const p=cameraDoll.project(c),saved=triangleDepth,size=18,w=handleWidth(label,size); if(Number.isFinite(p.x)&&Number.isFinite(p.y)){ - const x=Math.max(24,Math.min(viewWidth()-w-24,p.x-w/2)),y=Math.max(32,Math.min(viewHeight()-48,p.y-42)); + const x=Math.max(24,Math.min(viewWidth()-w-24,p.x-w/2)),y=Math.max(32,Math.min(viewHeight-48,p.y-42)); triangleDepth=-1.49;screenRect(x-8,y-5,w+16,30,[31,24,41]);typeWrite(label,x,y,size,255,231,180);triangleDepth=saved; } } diff --git a/xbox/live/tests/pool-playground.test.mjs b/xbox/live/tests/pool-playground.test.mjs index 86fed722d2..35b948a5f2 100644 --- a/xbox/live/tests/pool-playground.test.mjs +++ b/xbox/live/tests/pool-playground.test.mjs @@ -335,3 +335,16 @@ test('native polling delivers star edits once and drains the queue',()=>{ a.netDrainHostInbox();assert.equal(polls,2);assert.equal(globalThis.__oskiewarNetInbox.length,0); }finally{delete globalThis.oskiewarNetPoll;delete globalThis.__oskiewarNetInbox;delete globalThis.__oskiewarRenderFlags;} }); + +test('live star edits render their fairy captions without stopping the frame',()=>{ + const a=playground(),p=a.players[0];p.skin='pastel'; + a.cameraDoll.snap({position:{x:p.x+300,y:p.y-130,z:40},target:{x:p.x,y:p.y-130,z:0},width:1650,perspective:1}); + try{ + for(const intent of [2,1,0]){ + globalThis.__oskiewarNetInbox=[{kind:'render-flags',flags:{shirtSymbol:2,aeselPulse:intent+1,aeselIntent:intent}}]; + a.netDrainHostInbox(); + assert.doesNotThrow(()=>a.drawRunner(p,0)); + assert.doesNotThrow(()=>a.drawAeselFairy(0),`intent ${intent} renders`); + } + }finally{delete globalThis.__oskiewarNetInbox;delete globalThis.__oskiewarRenderFlags;} +}); -- 2.51.2