diff --git a/apps/client/assets/Scripts/UI/PlayerManager.ts b/apps/client/assets/Scripts/UI/PlayerManager.ts index 3a8f6afced228b8c6a2e2abf5ff51ffa8c9ae09b..fe7f62768f753e0a5987990ff1b1cc3416f6f946 100644 --- a/apps/client/assets/Scripts/UI/PlayerManager.ts +++ b/apps/client/assets/Scripts/UI/PlayerManager.ts @@ -1,19 +1,20 @@ -import { _decorator, Component, Node, Label } from "cc"; -import DataManager from "../Global/DataManager"; -const { ccclass, property } = _decorator; +import { _decorator, Component, Node, Label } from "cc" +import { IPlayer } from "../Common" +import DataManager from "../Global/DataManager" +const { ccclass, property } = _decorator @ccclass("PlayerManager") export class PlayerManager extends Component { - init({ id, nickname, rid }: { id: number; nickname: string; rid: number }) { - const label = this.getComponent(Label); - let str = nickname; + init({ id, nickname, rid }: IPlayer) { + const label = this.getComponent(Label) + let str = nickname if (DataManager.Instance.myPlayerId === id) { - str += `(我)`; + str += `(我)` } - if (rid !== -1) { - str += `(房间${rid})`; + if (rid) { + str += `(房间${rid})` } - label.string = str; - this.node.active = true; + label.string = str + this.node.active = true } } diff --git a/apps/client/assets/Scripts/UI/RoomManager.ts b/apps/client/assets/Scripts/UI/RoomManager.ts index c9c2ebfa673bac7e12466e77e13770331b4fe26d..6596b8a99126e19d7e3646b190df99380fbfc810 100644 --- a/apps/client/assets/Scripts/UI/RoomManager.ts +++ b/apps/client/assets/Scripts/UI/RoomManager.ts @@ -1,19 +1,20 @@ -import { _decorator, Component, Node, Label } from "cc"; -import { EventEnum } from "../Enum"; -import EventManager from "../Global/EventManager"; -const { ccclass, property } = _decorator; +import { _decorator, Component, Node, Label } from "cc" +import { IRoom } from "../Common" +import { EventEnum } from "../Enum" +import EventManager from "../Global/EventManager" +const { ccclass, property } = _decorator @ccclass("RoomManager") export class RoomManager extends Component { - id: number; - init({ id, players }: { id: number; players: Array<{ id: number; nickname: string }> }) { - this.id = id; - const label = this.getComponent(Label); - label.string = `房间id:${id},当前人数:${players.length}`; - this.node.active = true; + id: number + init({ id, players }: IRoom) { + this.id = id + const label = this.getComponent(Label) + label.string = `房间id:${id},当前人数:${players.length}` + this.node.active = true } handleClick() { - EventManager.Instance.emit(EventEnum.RoomJoin, this.id); + EventManager.Instance.emit(EventEnum.RoomJoin, this.id) } } diff --git a/apps/server/src/Core/MyServer.ts b/apps/server/src/Core/MyServer.ts index 15707d5f774a133815848ef2f5fea2a458a0e840..0f77981001a5956ecc3fa64ee298ec200b165d6a 100644 --- a/apps/server/src/Core/MyServer.ts +++ b/apps/server/src/Core/MyServer.ts @@ -1,10 +1,10 @@ -import { EventEmitter } from "stream"; -import WebSocket, { WebSocketServer } from "ws"; -import { ApiMsgEnum } from "../Common"; -import { Connection, ConnectionEventEnum } from "./Connection"; +import { EventEmitter } from "stream" +import WebSocket, { WebSocketServer } from "ws" +import { ApiMsgEnum, IModel } from "../Common" +import { Connection, ConnectionEventEnum } from "./Connection" export interface IMyServerOptions { - port: number; + port: number } export enum MyServerEventEnum { @@ -13,51 +13,51 @@ export enum MyServerEventEnum { } export class MyServer extends EventEmitter { - wss?: WebSocketServer; - port: number; - connections: Set = new Set(); - apiMap: Map = new Map(); + wss?: WebSocketServer + port: number + connections: Set = new Set() + apiMap: Map = new Map() constructor({ port = 8080 }: Partial) { - super(); - this.port = port; + super() + this.port = port } start() { return new Promise((resolve, reject) => { - this.wss = new WebSocketServer({ port: this.port }); - this.wss.on("connection", this.handleConnect.bind(this)); + this.wss = new WebSocketServer({ port: this.port }) + this.wss.on("connection", this.handleConnect.bind(this)) this.wss.on("error", (e) => { - reject(e); - }); + reject(e) + }) this.wss.on("close", () => { - console.log("MyServer 服务关闭"); - }); + console.log("MyServer 服务关闭") + }) this.wss.on("listening", () => { - resolve(true); - }); - }); + resolve(true) + }) + }) } handleConnect(ws: WebSocket) { //初始化 - const connection = new Connection(this, ws); + const connection = new Connection(this, ws) //向外告知有人来了 - this.connections.add(connection); - this.emit(MyServerEventEnum.Connect, connection); + this.connections.add(connection) + this.emit(MyServerEventEnum.Connect, connection) //向外告知有人走了 connection.on(ConnectionEventEnum.Close, (code: number, reason: string) => { - this.connections.delete(connection); - this.emit(MyServerEventEnum.DisConnect, connection, code, reason); - }); + this.connections.delete(connection) + this.emit(MyServerEventEnum.DisConnect, connection, code, reason) + }) } - setApi(apiName: ApiMsgEnum, cb: Function) { - this.apiMap.set(apiName, cb); + setApi(name: T, cb: (connection: Connection, args: IModel["api"][T]["req"]) => IModel["api"][T]["res"]) { + this.apiMap.set(name, cb) } } diff --git a/apps/server/src/biz/Player.ts b/apps/server/src/biz/Player.ts index f375c38838fb67f868da2eec54e37c0b63fb988e..e10eca6a70641fab96e8fb2abfd31ba6c41da030 100644 --- a/apps/server/src/biz/Player.ts +++ b/apps/server/src/biz/Player.ts @@ -1,16 +1,14 @@ -import { Connection } from "../Core"; +import { Connection } from "../Core" export default class Player { - id: number; - nickname: string; - connection: Connection; - rid: number; + id: number + nickname: string + connection: Connection + rid: number constructor({ id, nickname, connection }: Pick) { - this.id = id; - this.nickname = nickname; - this.connection = connection; - this.connection.playerId = this.id; - this.rid = -1; + this.id = id + this.nickname = nickname + this.connection = connection } } diff --git a/apps/server/src/biz/PlayerManager.ts b/apps/server/src/biz/PlayerManager.ts index 137baff84a6d242d272e20002b548cf29b82b85b..7e716bd10fce0997a847905009020ed53302b6e3 100644 --- a/apps/server/src/biz/PlayerManager.ts +++ b/apps/server/src/biz/PlayerManager.ts @@ -1,55 +1,54 @@ -import Singleton from "../Base/Singleton"; -import { ApiMsgEnum, IApiPlayerJoinReq } from "../Common"; -import { Connection } from "../Core"; -import Player from "./Player"; -import RoomManager from "./RoomManager"; +import Singleton from "../Base/Singleton" +import { ApiMsgEnum, IApiPlayerJoinReq } from "../Common" +import { Connection } from "../Core" +import Player from "./Player" +import RoomManager from "./RoomManager" export default class PlayerManager extends Singleton { static get Instance() { - return super.GetInstance(); + return super.GetInstance() } - players: Set = new Set(); + players: Set = new Set() - private nextPlayerId = 1; - private idMapPlayer: Map = new Map(); + private nextPlayerId = 1 + private idMapPlayer: Map = new Map() createPlayer({ connection, nickname }: IApiPlayerJoinReq & { connection: Connection }) { - const player = new Player({ id: this.nextPlayerId++, connection, nickname }); - this.players.add(player); - this.idMapPlayer.set(player.id, player); - return player; + const player = new Player({ id: this.nextPlayerId++, connection, nickname }) + this.players.add(player) + this.idMapPlayer.set(player.id, player) + return player } removePlayer(uid: number) { - const player = this.idMapPlayer.get(uid); + const player = this.idMapPlayer.get(uid) if (player) { - const rid = player.rid; + const rid = player.rid if (rid !== undefined) { - RoomManager.Instance.leaveRoom(rid, uid); - RoomManager.Instance.syncRooms(); - RoomManager.Instance.syncRoom(rid); + RoomManager.Instance.leaveRoom(rid, uid) + RoomManager.Instance.syncRooms() + RoomManager.Instance.syncRoom(rid) } - this.players.delete(player); - this.idMapPlayer.delete(uid); - this.syncPlayers(); + this.players.delete(player) + this.idMapPlayer.delete(uid) } } getPlayerById(uid: number) { - return this.idMapPlayer.get(uid); + return this.idMapPlayer.get(uid) } syncPlayers() { for (const player of this.players) { - player.connection.sendMsg(ApiMsgEnum.MsgPlayerList, { list: this.getPlayersView() }); + player.connection.sendMsg(ApiMsgEnum.MsgPlayerList, { list: this.getPlayersView() }) } } getPlayersView(players: Set = this.players) { - return [...players].map((player) => this.getPlayerView(player)); + return [...players].map((player) => this.getPlayerView(player)) } getPlayerView({ id, nickname, rid }: Player) { - return { id, nickname, rid }; + return { id, nickname, rid } } } diff --git a/apps/server/src/biz/Room.ts b/apps/server/src/biz/Room.ts index 32d9bd359179934e1147c55059030a1e94e0df70..d341dcb2d3b2a66389f101e55765d547cfd6e945 100644 --- a/apps/server/src/biz/Room.ts +++ b/apps/server/src/biz/Room.ts @@ -1,57 +1,57 @@ -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"; +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" export default class Room { - id: number; - players: Set = new Set(); + id: number + players: Set = new Set() - private lastTime?: number; - private timers: NodeJS.Timer[] = []; - private pendingInput: Array = []; - private lastPlayerFrameIdMap: Map = new Map(); + private lastTime?: number + private timers: NodeJS.Timer[] = [] + private pendingInput: Array = [] + private lastPlayerFrameIdMap: Map = new Map() constructor(rid: number) { - this.id = rid; + this.id = rid } join(uid: number) { - const player = PlayerManager.Instance.getPlayerById(uid); + const player = PlayerManager.Instance.getPlayerById(uid) if (player) { - player.rid = this.id; - this.players.add(player); + player.rid = this.id + this.players.add(player) } } leave(uid: number) { - const player = PlayerManager.Instance.getPlayerById(uid); + const player = PlayerManager.Instance.getPlayerById(uid) if (player) { - player.rid = -1; - player.connection.unlistenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this); - this.players.delete(player); + player.rid = undefined + player.connection.unlistenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this) + this.players.delete(player) if (!this.players.size) { - RoomManager.Instance.closeRoom(this.id); + RoomManager.Instance.closeRoom(this.id) } } } close() { - this.timers.forEach((t) => clearInterval(t)); + this.timers.forEach((t) => clearInterval(t)) for (const player of this.players) { - player.rid = -1; - player.connection.sendMsg(ApiMsgEnum.MsgGameEnd, {}); - player.connection.unlistenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this); + player.rid = undefined + player.connection.sendMsg(ApiMsgEnum.MsgGameEnd, {}) + player.connection.unlistenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this) } - this.players.clear(); + this.players.clear() } sync() { for (const player of this.players) { player.connection.sendMsg(ApiMsgEnum.MsgRoom, { room: RoomManager.Instance.getRoomView(this), - }); + }) } } @@ -75,47 +75,47 @@ export default class Room { })), bullets: [], nextBulletId: 1, - }; + } for (const player of this.players) { player.connection.sendMsg(ApiMsgEnum.MsgGameStart, { state, - }); - player.connection.listenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this); + }) + player.connection.listenMsg(ApiMsgEnum.MsgClientSync, this.getClientMsg, this) } let t1 = setInterval(() => { - this.sendServerMsg(); - }, 100); + this.sendServerMsg() + }, 100) let t2 = setInterval(() => { - this.timePast(); - }, 16); - this.timers = [t1, t2]; + this.timePast() + }, 16) + this.timers = [t1, t2] } getClientMsg(connection: Connection, { frameId, input }: IMsgClientSync) { - this.lastPlayerFrameIdMap.set(connection.playerId, frameId); - this.pendingInput.push(input); + this.lastPlayerFrameIdMap.set(connection.playerId, frameId) + this.pendingInput.push(input) } sendServerMsg() { - const pendingInput = this.pendingInput; - this.pendingInput = []; + const pendingInput = this.pendingInput + this.pendingInput = [] for (const player of this.players) { player.connection.sendMsg(ApiMsgEnum.MsgServerSync, { lastFrameId: this.lastPlayerFrameIdMap.get(player.id) ?? 0, inputs: pendingInput, - }); + }) } } timePast() { - let now = process.uptime(); - const dt = now - (this.lastTime ?? now); + let now = process.uptime() + const dt = now - (this.lastTime ?? now) this.pendingInput.push({ type: InputTypeEnum.TimePast, dt: toFixed(dt), - }); - this.lastTime = now; + }) + this.lastTime = now } } diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 3e504b17bc5acf5c9d85692a747380d04f952aef..e9781f3084149f39c13c546c08dcd6fe3a378746 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -40,6 +40,7 @@ server.on(MyServerEventEnum.DisConnect, (connection: Connection) => { console.log(`${getTime()}走人|人数|${server.connections.size}`) if (connection.playerId) { PlayerManager.Instance.removePlayer(connection.playerId) + PlayerManager.Instance.syncPlayers() } }) @@ -50,6 +51,7 @@ server.setApi(ApiMsgEnum.ApiPlayerList, (connection: Connection, data: IApiPlaye server.setApi(ApiMsgEnum.ApiPlayerJoin, (connection: Connection, { nickname }: IApiPlayerJoinReq): IApiPlayerJoinRes => { const player = PlayerManager.Instance.createPlayer({ connection, nickname }) + connection.playerId = player.id PlayerManager.Instance.syncPlayers() return { player: PlayerManager.Instance.getPlayerView(player),