,
This commit is contained in:
parent
8f50ebdb97
commit
86e97df0dc
3 changed files with 414 additions and 35 deletions
|
|
@ -301,6 +301,7 @@ export class GameServer implements GameEvents {
|
|||
|
||||
private handlePhysics() {
|
||||
const frameStart = process.hrtime.bigint();
|
||||
const frameStartMs = performance.now();
|
||||
const delta = Number(frameStart - this.lastPhysicsBase) / 1e9;
|
||||
this.lastPhysicsBase = frameStart;
|
||||
|
||||
|
|
@ -348,8 +349,13 @@ export class GameServer implements GameEvents {
|
|||
this.players.step(scaledDelta);
|
||||
}
|
||||
|
||||
// Physics has only advanced to the start of this frame less whatever is still in the
|
||||
// accumulator. Timing anything off the send time instead would put up to one physics step
|
||||
// of noise on every interpolated position and on the client's replay anchor.
|
||||
const simulatedThroughMs = frameStartMs - this.physicsAccumulator * 1000;
|
||||
|
||||
const propertyUpdates = new Map<GameObject, PropertyUpdatesForObject | undefined>();
|
||||
this.players.stepCommunication(delta, (object) => {
|
||||
this.players.stepCommunication(delta, simulatedThroughMs, (object) => {
|
||||
if (!propertyUpdates.has(object)) {
|
||||
propertyUpdates.set(object, object.getPropertyUpdates());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,10 +82,11 @@ export class PlayerContainer {
|
|||
|
||||
public stepCommunication(
|
||||
deltaTimeInSeconds: number,
|
||||
simulatedThroughMs: number,
|
||||
propertyUpdatesOf: (object: GameObject) => PropertyUpdatesForObject | undefined,
|
||||
) {
|
||||
this._players.forEach((p) =>
|
||||
p.stepCommunications(deltaTimeInSeconds, propertyUpdatesOf),
|
||||
p.stepCommunications(deltaTimeInSeconds, simulatedThroughMs, propertyUpdatesOf),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ export class Player extends PlayerBase {
|
|||
|
||||
public stepCommunications(
|
||||
deltaTime: number,
|
||||
simulatedThroughMs: number,
|
||||
propertyUpdatesOf: (object: GameObject) => PropertyUpdatesForObject | undefined,
|
||||
) {
|
||||
const remoteCalls: Array<RemoteCallsForObject> = [];
|
||||
|
|
@ -180,15 +181,20 @@ export class Player extends PlayerBase {
|
|||
this.socket.emit(TransportEvents.Ping, this.pendingPingNonce);
|
||||
}
|
||||
|
||||
// Subtracted, not zeroed: zeroing would stretch every interval to the next physics frame.
|
||||
if ((this.timeSinceLastMessage += deltaTime) > settings.updateMessageInterval) {
|
||||
this.timeSinceLastMessage = 0;
|
||||
this.timeSinceLastMessage = Math.min(
|
||||
this.timeSinceLastMessage - settings.updateMessageInterval,
|
||||
settings.updateMessageInterval,
|
||||
);
|
||||
this.queueAnnouncement();
|
||||
this.queueSnapshot(propertyUpdatesOf);
|
||||
this.queueSnapshot(simulatedThroughMs, propertyUpdatesOf);
|
||||
this.sendQueuedCommandsToClient();
|
||||
}
|
||||
}
|
||||
|
||||
private queueSnapshot(
|
||||
simulatedThroughMs: number,
|
||||
propertyUpdatesOf: (object: GameObject) => PropertyUpdatesForObject | undefined,
|
||||
) {
|
||||
const { topLeft, size } = calculateViewArea(this.center, this.aspectRatio, 1.2);
|
||||
|
|
@ -227,7 +233,7 @@ export class Player extends PlayerBase {
|
|||
}
|
||||
}
|
||||
this.queueCommandSend(
|
||||
new PropertyUpdatesForObjects(propertyUpdates, performance.now() / 1000),
|
||||
new PropertyUpdatesForObjects(propertyUpdates, simulatedThroughMs / 1000),
|
||||
);
|
||||
|
||||
if (this.character) {
|
||||
|
|
@ -236,8 +242,10 @@ export class Player extends PlayerBase {
|
|||
this.lastInputClientTimeMs,
|
||||
this.character.movementSnapshot,
|
||||
this.lastLeapClientTimeMs,
|
||||
// Aged against the instant the pose is from, not the send time: the difference is
|
||||
// the un-simulated remainder, and it would land straight in the client's replay.
|
||||
this.lastInputReceiptMs > 0
|
||||
? Math.max(0, performance.now() - this.lastInputReceiptMs)
|
||||
? Math.max(0, simulatedThroughMs - this.lastInputReceiptMs)
|
||||
: 0,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue