multiplayer fixes: trajectory dedupe by seq, reset client carve state on terrain resync, traceId backfill
This commit is contained in:
1 parent
21b383edd8
commit
69b494d054
3 files changed
+12
-4
No files matched your search
+8
-2
@@ -804,7 +804,9 @@ function applyWorld(snap) {
|
|||||||
projectiles = snap.projectiles || [];
|
projectiles = snap.projectiles || [];
|
||||||
explosions = (snap.explosions || []).map(e => ({...e, osc: NOOP_OSC}));
|
explosions = (snap.explosions || []).map(e => ({...e, osc: NOOP_OSC}));
|
||||||
if (networkMode && !netIsHost()) {
|
if (networkMode && !netIsHost()) {
|
||||||
const incoming = snap.trajectories || [];
|
let lastSeq = 0;
|
||||||
|
for (const t of trajectories) if (t.seq > lastSeq) lastSeq = t.seq;
|
||||||
|
const incoming = (snap.trajectories || []).filter(t => t.seq > lastSeq);
|
||||||
trajectories = [...trajectories, ...incoming].slice(-600);
|
trajectories = [...trajectories, ...incoming].slice(-600);
|
||||||
} else {
|
} else {
|
||||||
trajectories = snap.trajectories || [];
|
trajectories = snap.trajectories || [];
|
||||||
@@ -922,6 +924,9 @@ function interpolateWorld() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyTerrain(grid) {
|
function applyTerrain(grid) {
|
||||||
|
carveQueue.length = 0;
|
||||||
|
seenClientExplosions.clear();
|
||||||
|
clientCollapseState = null;
|
||||||
decodeTerrain(terrain, grid);
|
decodeTerrain(terrain, grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -962,7 +967,7 @@ function broadcastWorld() {
|
|||||||
napalmParticles: napalmParticles.map(p => ({x: p.x, y: p.y})),
|
napalmParticles: napalmParticles.map(p => ({x: p.x, y: p.y})),
|
||||||
fireCells: fireCells.map(f => ({x: f.x, y: f.y, timeLeft: f.timeLeft})),
|
fireCells: fireCells.map(f => ({x: f.x, y: f.y, timeLeft: f.timeLeft})),
|
||||||
smokeParticles: smokeParticles.map(s => ({x: s.x, y: s.y, vx: s.vx, vy: s.vy, alpha: s.alpha, lifetime: s.lifetime})),
|
smokeParticles: smokeParticles.map(s => ({x: s.x, y: s.y, vx: s.vx, vy: s.vy, alpha: s.alpha, lifetime: s.lifetime})),
|
||||||
trajectories: trajectories.slice(-300).filter((_, i) => i % 3 === 0).map(t => ({x: t.x, y: t.y, a: t.a, c: t.c, traceId: t.traceId})),
|
trajectories: trajectories.slice(-300).filter((_, i) => i % 3 === 0).map(t => ({x: t.x, y: t.y, a: t.a, c: t.c, traceId: t.traceId, seq: t.seq})),
|
||||||
};
|
};
|
||||||
netBroadcast({type: HOST_MSG.WORLD, snap});
|
netBroadcast({type: HOST_MSG.WORLD, snap});
|
||||||
}
|
}
|
||||||
@@ -1585,6 +1590,7 @@ function update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (state === 'shoot') {
|
else if (state === 'shoot') {
|
||||||
|
for (const p of projectiles) if (!p.traceId) p.traceId = nextTraceId++;
|
||||||
for (let i=projectiles.length-1; i>=0; i--) {
|
for (let i=projectiles.length-1; i>=0; i--) {
|
||||||
const projectile = projectiles[i];
|
const projectile = projectiles[i];
|
||||||
const projectileType = PROJECTILE_TYPES[projectile.type];
|
const projectileType = PROJECTILE_TYPES[projectile.type];
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,7 @@ import {audio, createOsc} from './sound.js?v=26';
|
|||||||
import {isTerrain, landHeight} from './terrain.js?v=26';
|
import {isTerrain, landHeight} from './terrain.js?v=26';
|
||||||
import {EXPLOSION_TYPES} from './weapons.js?v=26';
|
import {EXPLOSION_TYPES} from './weapons.js?v=26';
|
||||||
|
|
||||||
|
let trajectorySeq = 1;
|
||||||
|
|
||||||
export const PROJECTILE_TYPES = {
|
export const PROJECTILE_TYPES = {
|
||||||
normal: {
|
normal: {
|
||||||
@@ -109,7 +110,7 @@ export const PROJECTILE_TYPES = {
|
|||||||
|
|
||||||
trajectory
|
trajectory
|
||||||
.slice(0, trajectory.length-1)
|
.slice(0, trajectory.length-1)
|
||||||
.map(x => ({...x, a:255, traceId: projectile.traceId}))
|
.map(x => ({...x, a:255, traceId: projectile.traceId, seq: trajectorySeq++}))
|
||||||
.forEach(x => trajectories.push(x));
|
.forEach(x => trajectories.push(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +270,7 @@ export const PROJECTILE_TYPES = {
|
|||||||
|
|
||||||
trajectory
|
trajectory
|
||||||
.slice(0, trajectory.length-1)
|
.slice(0, trajectory.length-1)
|
||||||
.map(x => ({...x, a:255, traceId: projectile.traceId}))
|
.map(x => ({...x, a:255, traceId: projectile.traceId, seq: trajectorySeq++}))
|
||||||
.forEach(x => trajectories.push(x));
|
.forEach(x => trajectories.push(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ export function encodeTerrain(ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function decodeTerrain(ctx, grid) {
|
export function decodeTerrain(ctx, grid) {
|
||||||
|
if (!grid || !grid.tops || !grid.colors || !Array.isArray(grid.palette)) return;
|
||||||
const {width, height} = ctx.canvas;
|
const {width, height} = ctx.canvas;
|
||||||
const paletteRgb = grid.palette.map(hexToRgb);
|
const paletteRgb = grid.palette.map(hexToRgb);
|
||||||
const tops = new Uint16Array(fromBase64(grid.tops).buffer);
|
const tops = new Uint16Array(fromBase64(grid.tops).buffer);
|
||||||
|
|||||||
Reference in new issue
Block a user