import { ApiMsgEnum, EntityTypeEnum, IClientInput, InputTypeEnum, IState, toFixed } from '../Common' import type Player from './Player' import PlayerManager from './PlayerManager' import RoomManager from './RoomManager' export default class Room { id: number players: Set = new Set() lastSyncTime?: number private inputs: Array = [] constructor(rid: number) { this.id = rid } join(uid: number) { const player = PlayerManager.Instance.getPlayerById(uid) if (player) { player.rid = this.id this.players.add(player) } } leave(uid: number) { const player = PlayerManager.Instance.getPlayerById(uid) if (player) { player.rid = -1 this.players.delete(player) if (!this.players.size) { RoomManager.Instance.closeRoom(this.id) } } } sync() { for (const player of this.players) { player.connection.sendMsg(ApiMsgEnum.MsgRoom, { room: RoomManager.Instance.getRoomView(this) }) } } start() { const state: IState = { players: [...this.players].map((player, index) => ({ id: player.id, nickname: player.nickname, position: { x: -150 + index * 300, y: -150 + index * 300, }, direction: { x: 1, y: 0 }, hp: 100, type: EntityTypeEnum.Actor1, weaponType: EntityTypeEnum.Weapon1, bulletType: EntityTypeEnum.Bullet1, })), bullets: [], nextBulletId: 1 } for (const player of this.players) { player.connection.sendMsg(ApiMsgEnum.MsgGameStart, { state }) } this.listenPlayer() setInterval(() => { this.syncInput() }, 100) setInterval(() => { this.timePast() }, 16) } listenPlayer() { for (const player of this.players) { player.connection.listenMsg(ApiMsgEnum.MsgClientSync, (input) => { this.inputs.push(input) }) } } syncInput() { const inputs = this.inputs this.inputs = [] for (const player of this.players) { player.connection.sendMsg(ApiMsgEnum.MsgServerSync, inputs) } } timePast() { let now = process.uptime(); const dt = now - (this.lastSyncTime ?? now) this.inputs.push({ type: InputTypeEnum.TimePast, dt: toFixed(dt) }) this.lastSyncTime = now; } }