Trying to improve latency placing bombs while running
This commit is contained in:
parent
21f9807482
commit
e9306a2502
98
src/game.js
98
src/game.js
@ -127,6 +127,7 @@ const network = {
|
||||
inputStateAtClient: {
|
||||
dir: null,
|
||||
bomb: false,
|
||||
bombCell: null,
|
||||
},
|
||||
lastInputSentAt: 0,
|
||||
activeRoster: [],
|
||||
@ -712,7 +713,7 @@ function handleSocketMessage(raw) {
|
||||
if (!network.isHost || state.mode !== "multiplayer" || state.screen !== "game") {
|
||||
return;
|
||||
}
|
||||
network.remoteInputs.set(msg.playerId, msg.input || { dir: null, bomb: false });
|
||||
network.remoteInputs.set(msg.playerId, msg.input || { dir: null, bomb: false, bombCell: null });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -779,7 +780,7 @@ function leaveLobbyInternals() {
|
||||
network.activeRoster = [];
|
||||
state.notification.text = "";
|
||||
state.notification.expiresAt = 0;
|
||||
network.inputStateAtClient = { dir: null, bomb: false };
|
||||
network.inputStateAtClient = { dir: null, bomb: false, bombCell: null };
|
||||
network.lastInputSentAt = 0;
|
||||
network.hasReceivedSnapshot = false;
|
||||
}
|
||||
@ -975,22 +976,94 @@ function updateLobbyNetwork(dt) {
|
||||
}
|
||||
}
|
||||
|
||||
function sameBombCell(a, b) {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.x === b.x && a.y === b.y;
|
||||
}
|
||||
|
||||
function resolveBombDropCell(player, preferredCell = null) {
|
||||
const candidates = [];
|
||||
if (player.moveProgress < 1) {
|
||||
candidates.push({ x: player.moveFromX, y: player.moveFromY });
|
||||
if (player.moveToX !== player.moveFromX || player.moveToY !== player.moveFromY) {
|
||||
candidates.push({ x: player.moveToX, y: player.moveToY });
|
||||
}
|
||||
} else {
|
||||
candidates.push({ x: player.x, y: player.y });
|
||||
}
|
||||
|
||||
const canPlaceAt = (x, y) => {
|
||||
if (!inBounds(x, y)) {
|
||||
return false;
|
||||
}
|
||||
const tile = state.map[y]?.[x];
|
||||
if (!tile || tile.type !== "floor") {
|
||||
return false;
|
||||
}
|
||||
return !getBombAt(x, y);
|
||||
};
|
||||
|
||||
const isCandidateCell = (cell) =>
|
||||
candidates.some((candidate) => candidate.x === cell.x && candidate.y === cell.y);
|
||||
|
||||
if (preferredCell && Number.isInteger(preferredCell.x) && Number.isInteger(preferredCell.y)) {
|
||||
if (isCandidateCell(preferredCell) && canPlaceAt(preferredCell.x, preferredCell.y)) {
|
||||
return { x: preferredCell.x, y: preferredCell.y };
|
||||
}
|
||||
}
|
||||
|
||||
const primary =
|
||||
player.moveProgress < 1 && player.moveProgress >= 0.5
|
||||
? { x: player.moveToX, y: player.moveToY }
|
||||
: candidates[0];
|
||||
|
||||
if (primary && canPlaceAt(primary.x, primary.y)) {
|
||||
return { x: primary.x, y: primary.y };
|
||||
}
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (canPlaceAt(candidate.x, candidate.y)) {
|
||||
return { x: candidate.x, y: candidate.y };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function sendLocalMultiplayerInput(force = false) {
|
||||
if (state.mode !== "multiplayer" || state.screen !== "game" || network.isHost) {
|
||||
return;
|
||||
}
|
||||
const t = now();
|
||||
const localPlayer = state.players.find((player) => player.ownerId === network.clientId) || null;
|
||||
const nextInput = {
|
||||
dir: currentHumanDirection(),
|
||||
bomb: inputState.bombHeld,
|
||||
bombCell: null,
|
||||
};
|
||||
if (nextInput.bomb && localPlayer) {
|
||||
nextInput.bombCell = resolveBombDropCell(localPlayer);
|
||||
}
|
||||
|
||||
const changed =
|
||||
nextInput.dir !== network.inputStateAtClient.dir || nextInput.bomb !== network.inputStateAtClient.bomb;
|
||||
nextInput.dir !== network.inputStateAtClient.dir ||
|
||||
nextInput.bomb !== network.inputStateAtClient.bomb ||
|
||||
!sameBombCell(nextInput.bombCell, network.inputStateAtClient.bombCell);
|
||||
const dueHeartbeat = t - network.lastInputSentAt > 0.12;
|
||||
if (!changed && !force && !dueHeartbeat) {
|
||||
return;
|
||||
}
|
||||
network.inputStateAtClient = nextInput;
|
||||
|
||||
network.inputStateAtClient = {
|
||||
dir: nextInput.dir,
|
||||
bomb: nextInput.bomb,
|
||||
bombCell: nextInput.bombCell ? { ...nextInput.bombCell } : null,
|
||||
};
|
||||
network.lastInputSentAt = t;
|
||||
sendSocketMessage("player_input", { input: nextInput, ts: t });
|
||||
}
|
||||
@ -1032,18 +1105,20 @@ function queueDetonation(bombId) {
|
||||
state.pendingDetonations.push(bombId);
|
||||
}
|
||||
|
||||
function dropBomb(player) {
|
||||
function dropBomb(player, preferredCell = null) {
|
||||
if (!player.alive || player.bombsPlaced >= player.bombCapacity) {
|
||||
return false;
|
||||
}
|
||||
if (getBombAt(player.x, player.y)) {
|
||||
|
||||
const dropCell = resolveBombDropCell(player, preferredCell);
|
||||
if (!dropCell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bomb = {
|
||||
id: state.nextBombId,
|
||||
x: player.x,
|
||||
y: player.y,
|
||||
x: dropCell.x,
|
||||
y: dropCell.y,
|
||||
timer: CONFIG.bombFuse,
|
||||
range: player.flameRange,
|
||||
ownerId: player.id,
|
||||
@ -1329,7 +1404,7 @@ function occupiedTiles(player) {
|
||||
}
|
||||
|
||||
function getNetworkInput(ownerId) {
|
||||
return network.remoteInputs.get(ownerId) || { dir: null, bomb: false };
|
||||
return network.remoteInputs.get(ownerId) || { dir: null, bomb: false, bombCell: null };
|
||||
}
|
||||
|
||||
function getDesiredDirection(player) {
|
||||
@ -1371,8 +1446,9 @@ function updatePlayerMovement(player, dt) {
|
||||
player.renderY = player.y;
|
||||
}
|
||||
|
||||
const occupied = new Set(occupiedTiles(player));
|
||||
for (const bomb of state.bombs) {
|
||||
if (bomb.passThrough.has(player.id) && (player.x !== bomb.x || player.y !== bomb.y)) {
|
||||
if (bomb.passThrough.has(player.id) && !occupied.has(tileKey(bomb.x, bomb.y))) {
|
||||
bomb.passThrough.delete(player.id);
|
||||
}
|
||||
}
|
||||
@ -1585,7 +1661,7 @@ function updateGame(dt) {
|
||||
const remote = getNetworkInput(player.ownerId);
|
||||
const prevBomb = network.remoteBombPrev.get(player.ownerId) || false;
|
||||
if (remote.bomb && !prevBomb) {
|
||||
dropBomb(player);
|
||||
dropBomb(player, remote.bombCell || null);
|
||||
}
|
||||
network.remoteBombPrev.set(player.ownerId, remote.bomb);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user