fix: server-authoritative mob sync, seed sync, genColumn waits for seed

This commit is contained in:
Mk 2026-05-26 19:05:24 +00:00
parent a5f9ac841f
commit eaef5b2205
1 changed files with 31 additions and 19 deletions

34
game.js
View File

@ -224,15 +224,18 @@ function customConfirm(msg, onYes) {
if (data.seed !== undefined && data.seed !== worldSeed) { if (data.seed !== undefined && data.seed !== worldSeed) {
const oldSeed = worldSeed; const oldSeed = worldSeed;
worldSeed = data.seed; worldSeed = data.seed;
console.log('World seed changed from', oldSeed, 'to', worldSeed); console.log('World seed set from', oldSeed, 'to', worldSeed);
// Full regeneration with correct seed
// Очищаем и перегенерируем мир с новым seed
generated.clear();
grid.clear(); grid.clear();
blocks.length = 0; blocks.length = 0;
placedBlocks = []; placedBlocks = [];
removedBlocks = []; removedBlocks = [];
console.log('World regenerated with new seed:', worldSeed); 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 // Применяем блоки — сохраняем в serverOverrides для применения после genColumn
@ -374,11 +377,19 @@ function customConfirm(msg, onYes) {
}); });
socket.on('mob_positions', (arr) => { 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) { for (const u of arr) {
const sm = serverMobs.get(u.id); let sm = serverMobs.get(u.id);
if (sm) { sm.hp = u.hp; sm.fuse = u.fuse != null ? u.fuse : sm.fuse; } 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 мира для детерминированной генерации
// Инициализируем случайным seed, но он будет перезаписан сервером в мультиплеере // Seed: null in MP until server sends it; SP uses random seed
let worldSeed = Math.floor(Math.random() * 1000000); let worldSeed = isMultiplayer ? null : Math.floor(Math.random() * 1000000);
// Отслеживание изменений мира (для оптимизированного сохранения) // Отслеживание изменений мира (для оптимизированного сохранения)
let placedBlocks = []; // [{gx, gy, t}] - блоки, установленные игроком let placedBlocks = []; // [{gx, gy, t}] - блоки, установленные игроком
@ -3692,6 +3703,7 @@ registerProcessor('voice-playback', VoicePlaybackProcessor);
function genColumn(gx) { function genColumn(gx) {
if(generated.has(gx)) return; if(generated.has(gx)) return;
if(worldSeed == null) return; // wait for server seed in multiplayer
generated.add(gx); generated.add(gx);
const sgy = surfaceGyAt(gx); const sgy = surfaceGyAt(gx);