Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

dumduel: fix input delivery — include handle in UDP input, WS fallback, no local position snap

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+30 -14
+14 -2
session-server/session.mjs
··· 2858 2858 if (parsed?.handle) duelManager.handlePing(parsed.handle, parsed.ts, id); 2859 2859 return; 2860 2860 } 2861 + if (msg.type === "duel:input") { 2862 + const parsed = typeof msg.content === "string" ? JSON.parse(msg.content) : msg.content; 2863 + if (parsed?.handle) duelManager.receiveInput(parsed.handle, parsed); 2864 + return; 2865 + } 2861 2866 2862 2867 everyone(JSON.stringify(msg)); // Relay any other message to every user. 2863 2868 } ··· 3608 3613 if (channel.webrtcConnection.state === "open") { 3609 3614 try { 3610 3615 const parsed = typeof data === "string" ? JSON.parse(data) : data; 3611 - const handle = clients[channel.id]?.handle; 3612 - if (handle) duelManager.receiveInput(handle, parsed); 3616 + // Resolve handle from channel identity OR from message payload 3617 + const handle = clients[channel.id]?.handle || parsed.handle; 3618 + if (handle) { 3619 + duelManager.receiveInput(handle, parsed); 3620 + // Also resolve UDP channel if not yet linked 3621 + if (!clients[channel.id]?.handle && parsed.handle) { 3622 + duelManager.resolveUdpChannel(parsed.handle, channel.id); 3623 + } 3624 + } 3613 3625 } catch (err) { 3614 3626 console.warn("duel:input error:", err); 3615 3627 }
+16 -12
system/public/aesthetic.computer/disks/dumduel.mjs
··· 67 67 68 68 const meServer = s.players?.find((p) => p.handle === myHandle); 69 69 if (meServer) { 70 - // Only correct position if delta is large (>5px) — otherwise let prediction run 71 - const dx = meServer.x - localX; 72 - const dy = meServer.y - localY; 73 - if (dx * dx + dy * dy > 25) { 70 + // On first snapshot or respawn, snap to server position 71 + if (snapCount === 1 || !meServer.alive) { 74 72 localX = meServer.x; 75 73 localY = meServer.y; 74 + localTargetX = meServer.targetX; 75 + localTargetY = meServer.targetY; 76 76 } 77 - 78 - // Always update target from server, then re-apply unacked inputs 79 - localTargetX = meServer.targetX; 80 - localTargetY = meServer.targetY; 81 - for (const inp of pendingInputs) { 82 - localTargetX = inp.targetX; 83 - localTargetY = inp.targetY; 77 + // Otherwise: never touch localX/Y — prediction is the display. 78 + // Only re-apply unacked inputs to target. 79 + if (pendingInputs.length === 0) { 80 + localTargetX = meServer.targetX; 81 + localTargetY = meServer.targetY; 84 82 } 85 83 86 84 ping = meServer.ping || 0; ··· 277 275 localTargetX = tx; 278 276 localTargetY = ty; 279 277 pendingInputs.push({ seq: inputSeq, targetX: tx, targetY: ty }); 280 - udpChannel?.send("duel:input", { seq: inputSeq, targetX: tx, targetY: ty }); 278 + const input = { seq: inputSeq, targetX: tx, targetY: ty, handle: myHandle }; 279 + // Send via UDP, fallback to WS 280 + if (udpChannel?.connected) { 281 + udpChannel.send("duel:input", input); 282 + } else { 283 + server?.send("duel:input", input); 284 + } 281 285 } 282 286 } 283 287 }