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) {
const oldSeed = worldSeed;
worldSeed = data.seed;
console.log('World seed changed from', oldSeed, 'to', worldSeed);
// Очищаем и перегенерируем мир с новым seed
generated.clear();
console.log('World seed set from', oldSeed, 'to', worldSeed);
// Full regeneration with correct seed
grid.clear();
blocks.length = 0;
placedBlocks = [];
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
@ -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);