From eaef5b2205c05e016446800d62d4960275c46f99 Mon Sep 17 00:00:00 2001 From: Mk Date: Tue, 26 May 2026 19:05:24 +0000 Subject: [PATCH] fix: server-authoritative mob sync, seed sync, genColumn waits for seed --- game.js | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/game.js b/game.js index 51dabd5..c110f72 100644 --- a/game.js +++ b/game.js @@ -221,19 +221,22 @@ function customConfirm(msg, onYes) { console.log('Received world_state:', data); // Устанавливаем seed и перегенерируем мир если он изменился - if (data.seed !== undefined && data.seed !== worldSeed) { - const oldSeed = worldSeed; - worldSeed = data.seed; - console.log('World seed changed from', oldSeed, 'to', worldSeed); - - // Очищаем и перегенерируем мир с новым seed - generated.clear(); - grid.clear(); - blocks.length = 0; - placedBlocks = []; - removedBlocks = []; - console.log('World regenerated with new seed:', worldSeed); - } + if (data.seed !== undefined && data.seed !== worldSeed) { + const oldSeed = worldSeed; + worldSeed = data.seed; + console.log('World seed set from', oldSeed, 'to', worldSeed); + // Full regeneration with correct seed + grid.clear(); + blocks.length = 0; + placedBlocks = []; + removedBlocks = []; + generated.clear(); + for (let gx = spawnPoint.gx - 25; gx <= spawnPoint.gx + 25; gx++) { + genColumn(gx); + decorations(gx); + } + console.log('World regenerated with seed:', worldSeed); + } // Применяем блоки — сохраняем в serverOverrides для применения после genColumn if (data.blocks && Array.isArray(data.blocks)) { @@ -374,11 +377,19 @@ function customConfirm(msg, onYes) { }); socket.on('mob_positions', (arr) => { - // Client-authoritative: ignore server positions, mobAI handles physics locally. - // Only update HP/fuse/direction for consistency (e.g. if another client hurt the mob). for (const u of arr) { - const sm = serverMobs.get(u.id); - if (sm) { sm.hp = u.hp; sm.fuse = u.fuse != null ? u.fuse : sm.fuse; } + let sm = serverMobs.get(u.id); + if (!sm) { + sm = createMobFromServer({ id: u.id, kind: u.kind || 'zombie', x: u.x, y: u.y, + hp: u.hp || 1, maxHp: u.hp || 1, dir: u.dir || 1 }); + serverMobs.set(u.id, sm); + } + sm.x += (u.x - sm.x) * 0.3; + sm.y += (u.y - sm.y) * 0.3; + sm.dir = u.dir != null ? u.dir : sm.dir; + sm.hp = u.hp != null ? u.hp : sm.hp; + sm.fuse = u.fuse != null ? u.fuse : sm.fuse; + sm.grounded = !!u.grounded; } }); @@ -708,8 +719,8 @@ function customConfirm(msg, onYes) { }; // Seed мира для детерминированной генерации - // Инициализируем случайным seed, но он будет перезаписан сервером в мультиплеере - let worldSeed = Math.floor(Math.random() * 1000000); + // Seed: null in MP until server sends it; SP uses random seed + let worldSeed = isMultiplayer ? null : Math.floor(Math.random() * 1000000); // Отслеживание изменений мира (для оптимизированного сохранения) let placedBlocks = []; // [{gx, gy, t}] - блоки, установленные игроком @@ -3692,6 +3703,7 @@ registerProcessor('voice-playback', VoicePlaybackProcessor); function genColumn(gx) { if(generated.has(gx)) return; + if(worldSeed == null) return; // wait for server seed in multiplayer generated.add(gx); const sgy = surfaceGyAt(gx);