make next update interval a property on network update component instead of inheritable attribute on entities
This commit is contained in:
parent
c551f519ca
commit
29ba1c29d7
@ -16,6 +16,7 @@ export class BoundingBox extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public isCollidingWith(box: BoundingBox): boolean {
|
public isCollidingWith(box: BoundingBox): boolean {
|
||||||
|
// optimization; when neither rotates just check if they overlap
|
||||||
if (this.rotation == 0 && box.rotation == 0) {
|
if (this.rotation == 0 && box.rotation == 0) {
|
||||||
const thisTopLeft = this.getTopLeft();
|
const thisTopLeft = this.getTopLeft();
|
||||||
const thisBottomRight = this.getBottomRight();
|
const thisBottomRight = this.getBottomRight();
|
||||||
|
@ -1,7 +1,23 @@
|
|||||||
import { Component, ComponentNames } from '.';
|
import { Component, ComponentNames } from '.';
|
||||||
|
|
||||||
export class NetworkUpdateable extends Component {
|
export class NetworkUpdateable extends Component {
|
||||||
constructor() {
|
static DEFAULT_UPDATE_JITTER_MS = 30;
|
||||||
|
static DEFAULT_THRESHOLD_TIME_MS = 20;
|
||||||
|
|
||||||
|
public updateThreshold: number;
|
||||||
|
public jitter: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
updateThreshold = NetworkUpdateable.DEFAULT_THRESHOLD_TIME_MS,
|
||||||
|
jitter = NetworkUpdateable.DEFAULT_UPDATE_JITTER_MS
|
||||||
|
) {
|
||||||
super(ComponentNames.NetworkUpdateable);
|
super(ComponentNames.NetworkUpdateable);
|
||||||
|
|
||||||
|
this.updateThreshold = updateThreshold;
|
||||||
|
this.jitter = jitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNextUpdateTime() {
|
||||||
|
return Math.random() * this.jitter + this.updateThreshold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { EntityNames, Floor, Player } from '.';
|
import { EntityNames, Floor, Player } from '.';
|
||||||
import { type Component } from '../components';
|
import { type Component } from '../components';
|
||||||
|
|
||||||
const randomId = () =>
|
const randomId = () => (Math.random() * 1_000_000_000).toString();
|
||||||
(performance.now() + Math.random() * 10_000_000).toString();
|
|
||||||
|
|
||||||
export abstract class Entity {
|
export abstract class Entity {
|
||||||
public id: string;
|
public id: string;
|
||||||
@ -59,6 +58,4 @@ export abstract class Entity {
|
|||||||
public abstract setFrom(args: Record<string, any>): void;
|
public abstract setFrom(args: Record<string, any>): void;
|
||||||
|
|
||||||
public abstract serialize(): Record<string, any>;
|
public abstract serialize(): Record<string, any>;
|
||||||
|
|
||||||
public abstract getNextUpdateInterval(): number;
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ export class Floor extends Entity {
|
|||||||
|
|
||||||
this.addComponent(
|
this.addComponent(
|
||||||
new Sprite(
|
new Sprite(
|
||||||
IMAGES.get((Floor.spriteSpec?.states?.get(width) as SpriteSpec).sheet),
|
IMAGES.get(Floor.spriteSpec!.states!.get(width)!.sheet!)!,
|
||||||
{ x: 0, y: 0 },
|
{ x: 0, y: 0 },
|
||||||
{ width, height: Floor.spriteSpec.height },
|
{ width, height: Floor.spriteSpec.height },
|
||||||
Floor.spriteSpec.msPerFrame,
|
Floor.spriteSpec.msPerFrame,
|
||||||
@ -45,8 +45,4 @@ export class Floor extends Entity {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getNextUpdateInterval() {
|
|
||||||
return Math.random() * 500;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ export class Player extends Entity {
|
|||||||
const [leftSprite, rightSprite] = [Direction.LEFT, Direction.RIGHT].map(
|
const [leftSprite, rightSprite] = [Direction.LEFT, Direction.RIGHT].map(
|
||||||
(direction) =>
|
(direction) =>
|
||||||
new Sprite(
|
new Sprite(
|
||||||
IMAGES.get(Player.spriteSpec.states?.get(direction)?.sheet as string),
|
IMAGES.get(Player.spriteSpec.states!.get(direction)!.sheet!)!,
|
||||||
{ x: 0, y: 0 },
|
{ x: 0, y: 0 },
|
||||||
{ width: Player.spriteSpec.width, height: Player.spriteSpec.height },
|
{ width: Player.spriteSpec.width, height: Player.spriteSpec.height },
|
||||||
Player.spriteSpec.msPerFrame,
|
Player.spriteSpec.msPerFrame,
|
||||||
@ -102,8 +102,4 @@ export class Player extends Entity {
|
|||||||
new BoundingBox(center, boundingBox.dimension, boundingBox.rotation)
|
new BoundingBox(center, boundingBox.dimension, boundingBox.rotation)
|
||||||
].forEach((component) => this.addComponent(component));
|
].forEach((component) => this.addComponent(component));
|
||||||
}
|
}
|
||||||
|
|
||||||
public getNextUpdateInterval() {
|
|
||||||
return Math.random() * 30 + 50;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { System, SystemNames } from '.';
|
import { System, SystemNames } from '.';
|
||||||
import { Game } from '../Game';
|
import { Game } from '../Game';
|
||||||
import { ComponentNames } from '../components';
|
import { ComponentNames, NetworkUpdateable } from '../components';
|
||||||
import {
|
import {
|
||||||
type MessageQueueProvider,
|
type MessageQueueProvider,
|
||||||
type MessagePublisher,
|
type MessagePublisher,
|
||||||
@ -55,15 +55,20 @@ export class NetworkUpdate extends System {
|
|||||||
// 2. send entity updates
|
// 2. send entity updates
|
||||||
const updateMessages: EntityUpdateBody[] = [];
|
const updateMessages: EntityUpdateBody[] = [];
|
||||||
|
|
||||||
// todo: figure out if we can use the controllable component to determine if we should publish an update
|
|
||||||
game.forEachEntityWithComponent(
|
game.forEachEntityWithComponent(
|
||||||
ComponentNames.NetworkUpdateable,
|
ComponentNames.NetworkUpdateable,
|
||||||
(entity) => {
|
(entity) => {
|
||||||
|
const networkUpdateableComponent =
|
||||||
|
entity.getComponent<NetworkUpdateable>(
|
||||||
|
ComponentNames.NetworkUpdateable
|
||||||
|
);
|
||||||
|
const nextUpdateTime = networkUpdateableComponent.getNextUpdateTime();
|
||||||
|
|
||||||
const newHash = stringify(entity.serialize());
|
const newHash = stringify(entity.serialize());
|
||||||
let updateInfo: EntityUpdateInfo = this.entityUpdateInfo.get(
|
let updateInfo: EntityUpdateInfo = this.entityUpdateInfo.get(
|
||||||
entity.id
|
entity.id
|
||||||
) ?? {
|
) ?? {
|
||||||
timer: this.getNextUpdateTimeMs(),
|
timer: nextUpdateTime,
|
||||||
hash: newHash
|
hash: newHash
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,13 +76,11 @@ export class NetworkUpdate extends System {
|
|||||||
updateInfo.timer -= dt;
|
updateInfo.timer -= dt;
|
||||||
this.entityUpdateInfo.set(entity.id, updateInfo);
|
this.entityUpdateInfo.set(entity.id, updateInfo);
|
||||||
if (updateInfo.timer > 0) return;
|
if (updateInfo.timer > 0) return;
|
||||||
updateInfo.timer = entity.getNextUpdateInterval();
|
updateInfo.timer = nextUpdateTime;
|
||||||
this.entityUpdateInfo.set(entity.id, updateInfo);
|
this.entityUpdateInfo.set(entity.id, updateInfo);
|
||||||
|
|
||||||
// maybe update if hash is not consitent
|
// maybe update, if hash is not consistent
|
||||||
if (updateInfo.hash == newHash) {
|
if (updateInfo.hash == newHash) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateInfo.hash = newHash;
|
updateInfo.hash = newHash;
|
||||||
this.entityUpdateInfo.set(entity.id, updateInfo);
|
this.entityUpdateInfo.set(entity.id, updateInfo);
|
||||||
|
|
||||||
@ -102,7 +105,7 @@ export class NetworkUpdate extends System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getNextUpdateInterval(): number {
|
private getNextUpdateInterval() {
|
||||||
return Math.random() * 30;
|
return Math.random() * 30 + 20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,9 @@ export class GameServer {
|
|||||||
fetch: (req, srv) => this.fetchHandler(req, srv),
|
fetch: (req, srv) => this.fetchHandler(req, srv),
|
||||||
websocket: {
|
websocket: {
|
||||||
open: (ws) => this.openWebsocket(ws),
|
open: (ws) => this.openWebsocket(ws),
|
||||||
message: (ws, msg) => this.websocketMessage(ws, msg),
|
message: (ws, msg) => {
|
||||||
|
if (typeof msg === 'string') this.websocketMessage(ws, msg);
|
||||||
|
},
|
||||||
close: (ws) => this.closeWebsocket(ws)
|
close: (ws) => this.closeWebsocket(ws)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -54,21 +56,19 @@ export class GameServer {
|
|||||||
|
|
||||||
private websocketMessage(
|
private websocketMessage(
|
||||||
websocket: ServerWebSocket<SessionData>,
|
websocket: ServerWebSocket<SessionData>,
|
||||||
message: string | Uint8Array
|
message: string
|
||||||
) {
|
) {
|
||||||
if (typeof message == 'string') {
|
|
||||||
const receivedMessage = parse<ServerMessage>(message);
|
const receivedMessage = parse<ServerMessage>(message);
|
||||||
receivedMessage.sessionData = websocket.data;
|
receivedMessage.sessionData = websocket.data;
|
||||||
|
|
||||||
this.messageReceiver.addMessage(receivedMessage);
|
this.messageReceiver.addMessage(receivedMessage);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private closeWebsocket(websocket: ServerWebSocket<SessionData>) {
|
private closeWebsocket(websocket: ServerWebSocket<SessionData>) {
|
||||||
const { sessionId } = websocket.data;
|
const { sessionId } = websocket.data;
|
||||||
|
|
||||||
const sessionEntities =
|
const sessionEntities =
|
||||||
this.sessionManager.getSession(sessionId)!.controllableEntities;
|
this.sessionManager.getSession(sessionId)?.controllableEntities;
|
||||||
this.sessionManager.removeSession(sessionId);
|
this.sessionManager.removeSession(sessionId);
|
||||||
|
|
||||||
if (!sessionEntities) return;
|
if (!sessionEntities) return;
|
||||||
|
Loading…
Reference in New Issue
Block a user