2022-12-08 21:14:02 +08:00
|
|
|
import { ApiMsgEnum, EntityTypeEnum, IClientInput, IMsgClientSync, InputTypeEnum, IState, toFixed } from "../Common";
|
|
|
|
import { Connection } from "../Core";
|
|
|
|
import type Player from "./Player";
|
|
|
|
import PlayerManager from "./PlayerManager";
|
|
|
|
import RoomManager from "./RoomManager";
|
2022-12-01 22:26:41 +08:00
|
|
|
|
|
|
|
export default class Room {
|
2022-12-08 21:14:02 +08:00
|
|
|
id: number;
|
|
|
|
players: Set<Player> = new Set();
|
2022-12-04 22:10:30 +08:00
|
|
|
|
2022-12-08 21:14:02 +08:00
|
|
|
private lastTime?: number;
|
|
|
|
private timers: NodeJS.Timer[] = [];
|
|
|
|
private pendingInput: Array<IClientInput> = [];
|
|
|
|
private lastPlayerFrameIdMap: Map<number, number> = new Map();
|
2022-12-01 22:26:41 +08:00
|
|
|
|
|
|
|
constructor(rid: number) {
|
2022-12-08 21:14:02 +08:00
|
|
|
this.id = rid;
|
2022-12-01 22:26:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
join(uid: number) {
|
2022-12-08 21:14:02 +08:00
|
|
|
const player = PlayerManager.Instance.getPlayerById(uid);
|
2022-12-01 22:26:41 +08:00
|
|
|
if (player) {
|
2022-12-08 21:14:02 +08:00
|
|
|
player.rid = this.id;
|
|
|
|
this.players.add(player);
|
2022-12-01 22:26:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
leave(uid: number) {
|
2022-12-08 21:14:02 +08:00
|
|
|
const player = PlayerManager.Instance.getPlayerById(uid);
|
2022-12-01 22:26:41 +08:00
|
|
|
if (player) {
|
2022-12-08 21:14:02 +08:00
|
|
|
player.rid = -1;
|
|
|
|
player.connection.unlistenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this);
|
|
|
|
this.players.delete(player);
|
2022-12-01 22:26:41 +08:00
|
|
|
if (!this.players.size) {
|
2022-12-08 21:14:02 +08:00
|
|
|
RoomManager.Instance.closeRoom(this.id);
|
2022-12-01 22:26:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-07 22:24:46 +08:00
|
|
|
close() {
|
2022-12-08 21:14:02 +08:00
|
|
|
this.timers.forEach((t) => clearInterval(t));
|
2022-12-07 22:24:46 +08:00
|
|
|
for (const player of this.players) {
|
2022-12-08 21:14:02 +08:00
|
|
|
player.rid = -1;
|
|
|
|
player.connection.sendMsg(ApiMsgEnum.MsgGameEnd, {});
|
|
|
|
player.connection.unlistenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this);
|
2022-12-07 22:24:46 +08:00
|
|
|
}
|
2022-12-08 21:14:02 +08:00
|
|
|
this.players.clear();
|
2022-12-07 22:24:46 +08:00
|
|
|
}
|
|
|
|
|
2022-12-01 22:26:41 +08:00
|
|
|
sync() {
|
|
|
|
for (const player of this.players) {
|
2022-12-03 20:06:57 +08:00
|
|
|
player.connection.sendMsg(ApiMsgEnum.MsgRoom, {
|
2022-12-08 21:14:02 +08:00
|
|
|
room: RoomManager.Instance.getRoomView(this),
|
|
|
|
});
|
2022-12-03 20:06:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
start() {
|
|
|
|
const state: IState = {
|
2022-12-08 21:14:02 +08:00
|
|
|
actors: [...this.players].map((player, index) => ({
|
2022-12-03 20:06:57 +08:00
|
|
|
id: player.id,
|
|
|
|
nickname: player.nickname,
|
|
|
|
position: {
|
|
|
|
x: -150 + index * 300,
|
|
|
|
y: -150 + index * 300,
|
|
|
|
},
|
|
|
|
direction: {
|
|
|
|
x: 1,
|
2022-12-08 21:14:02 +08:00
|
|
|
y: 0,
|
2022-12-03 20:06:57 +08:00
|
|
|
},
|
|
|
|
hp: 100,
|
2022-12-08 21:14:02 +08:00
|
|
|
type: index === 0 ? EntityTypeEnum.Actor1 : EntityTypeEnum.Actor2,
|
|
|
|
weaponType: index === 0 ? EntityTypeEnum.Weapon1 : EntityTypeEnum.Weapon2,
|
|
|
|
bulletType: index === 0 ? EntityTypeEnum.Bullet1 : EntityTypeEnum.Bullet2,
|
2022-12-03 20:06:57 +08:00
|
|
|
})),
|
|
|
|
bullets: [],
|
2022-12-08 21:14:02 +08:00
|
|
|
nextBulletId: 1,
|
|
|
|
};
|
2022-12-03 20:06:57 +08:00
|
|
|
|
|
|
|
for (const player of this.players) {
|
|
|
|
player.connection.sendMsg(ApiMsgEnum.MsgGameStart, {
|
2022-12-08 21:14:02 +08:00
|
|
|
state,
|
|
|
|
});
|
|
|
|
player.connection.listenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this);
|
2022-12-03 20:06:57 +08:00
|
|
|
}
|
2022-12-06 23:10:03 +08:00
|
|
|
let t1 = setInterval(() => {
|
2022-12-08 21:14:02 +08:00
|
|
|
this.sendServerMsg();
|
|
|
|
}, 100);
|
2022-12-06 23:10:03 +08:00
|
|
|
let t2 = setInterval(() => {
|
2022-12-08 21:14:02 +08:00
|
|
|
this.timePast();
|
|
|
|
}, 16);
|
|
|
|
this.timers = [t1, t2];
|
2022-12-03 20:06:57 +08:00
|
|
|
}
|
|
|
|
|
2022-12-08 21:14:02 +08:00
|
|
|
getClientMsg(connection: Connection, { frameId, input }: IMsgClientSync) {
|
|
|
|
this.lastPlayerFrameIdMap.set(connection.playerId, frameId);
|
|
|
|
this.pendingInput.push(input);
|
2022-12-03 21:28:38 +08:00
|
|
|
}
|
|
|
|
|
2022-12-08 21:14:02 +08:00
|
|
|
sendServerMsg() {
|
|
|
|
const pendingInput = this.pendingInput;
|
|
|
|
this.pendingInput = [];
|
2022-12-04 22:10:30 +08:00
|
|
|
|
2022-12-03 21:28:38 +08:00
|
|
|
for (const player of this.players) {
|
2022-12-08 21:14:02 +08:00
|
|
|
player.connection.sendMsg(ApiMsgEnum.MsgServerSync, {
|
|
|
|
lastFrameId: this.lastPlayerFrameIdMap.get(player.id) ?? 0,
|
|
|
|
inputs: pendingInput,
|
|
|
|
});
|
2022-12-01 22:26:41 +08:00
|
|
|
}
|
|
|
|
}
|
2022-12-04 22:10:30 +08:00
|
|
|
|
|
|
|
timePast() {
|
|
|
|
let now = process.uptime();
|
2022-12-08 21:14:02 +08:00
|
|
|
const dt = now - (this.lastTime ?? now);
|
|
|
|
this.pendingInput.push({
|
2022-12-04 22:10:30 +08:00
|
|
|
type: InputTypeEnum.TimePast,
|
2022-12-08 21:14:02 +08:00
|
|
|
dt: toFixed(dt),
|
|
|
|
});
|
|
|
|
this.lastTime = now;
|
2022-12-04 22:10:30 +08:00
|
|
|
}
|
2022-12-01 22:26:41 +08:00
|
|
|
}
|