This commit is contained in:
sli97 2022-12-13 13:44:53 +08:00
parent 6d37ab0468
commit 99d68b0ee7
2 changed files with 112 additions and 107 deletions

View File

@ -1,83 +1,82 @@
import WebSocket from "ws"; import WebSocket from "ws"
import { EventEmitter } from "stream"; import { EventEmitter } from "stream"
import { MyServer } from "./MyServer"; import { MyServer } from "./MyServer"
import { getTime, buffer2ArrayBuffer } from "../Utils"; import { getTime, buffer2ArrayBuffer } from "../Utils"
import { ApiMsgEnum, IModel } from "../Common"; import { ApiMsgEnum, IModel } from "../Common"
import { binaryEncode, binaryDecode } from "../Common/Binary"; import { binaryEncode, binaryDecode } from "../Common/Binary"
export enum ConnectionEventEnum { export enum ConnectionEventEnum {
Close = "Close", Close = "Close",
} }
interface IItem { interface IItem {
cb: Function; cb: Function
ctx: unknown; ctx: unknown
} }
export class Connection extends EventEmitter { export class Connection extends EventEmitter {
server: MyServer; server: MyServer
ws: WebSocket; ws: WebSocket
msgMap: Map<ApiMsgEnum, Array<IItem>> = new Map(); msgMap: Map<ApiMsgEnum, Array<IItem>> = new Map()
playerId?: number;
constructor(server: MyServer, ws: WebSocket) { constructor(server: MyServer, ws: WebSocket) {
super(); super()
this.server = server; this.server = server
this.ws = ws; this.ws = ws
this.ws.on("close", (code: number, reason: Buffer) => { this.ws.on("close", (code: number, reason: Buffer) => {
this.emit(ConnectionEventEnum.Close, code, reason.toString()); this.emit(ConnectionEventEnum.Close, code, reason.toString())
}); })
this.ws.on("message", (buffer: Buffer) => { this.ws.on("message", (buffer: Buffer) => {
// const str = buffer.toString() // const str = buffer.toString()
try { try {
const json = binaryDecode(buffer2ArrayBuffer(buffer)); const json = binaryDecode(buffer2ArrayBuffer(buffer))
const { name, data } = json; const { name, data } = json
// console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${str}`) // console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${str}`)
console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${JSON.stringify(json)}`); console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${JSON.stringify(json)}`)
if (this.server.apiMap.has(name)) { if (this.server.apiMap.has(name)) {
try { try {
const cb = this.server.apiMap.get(name); const cb = this.server.apiMap.get(name)
const res = cb.call(null, this, data); const res = cb.call(null, this, data)
this.sendMsg(name, { this.sendMsg(name, {
success: true, success: true,
res, res,
}); })
} catch (error) { } catch (error) {
this.sendMsg(name, { this.sendMsg(name, {
success: false, success: false,
error: (error as Error)?.message, error: (error as Error)?.message,
}); })
} }
} else { } else {
try { try {
if (this.msgMap.has(name)) { if (this.msgMap.has(name)) {
this.msgMap.get(name).forEach(({ cb, ctx }) => cb.call(ctx, this, data)); this.msgMap.get(name).forEach(({ cb, ctx }) => cb.call(ctx, this, data))
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error)
} }
} }
} catch (error) { } catch (error) {
console.log(`解析失败不是合法的JSON格式`, error); console.log(`解析失败不是合法的JSON格式`, error)
} }
}); })
} }
listenMsg<T extends keyof IModel["msg"]>(name: T, cb: (connection: Connection, arg: IModel["msg"][T]) => void, ctx: unknown) { listenMsg<T extends keyof IModel["msg"]>(name: T, cb: (connection: Connection, arg: IModel["msg"][T]) => void, ctx: unknown) {
if (this.msgMap.has(name)) { if (this.msgMap.has(name)) {
this.msgMap.get(name).push({ cb, ctx }); this.msgMap.get(name).push({ cb, ctx })
} else { } else {
this.msgMap.set(name, [{ cb, ctx }]); this.msgMap.set(name, [{ cb, ctx }])
} }
} }
unlistenMsg<T extends keyof IModel["msg"]>(name: T, cb: (connection: Connection, arg: IModel["msg"][T]) => void, ctx: unknown) { unlistenMsg<T extends keyof IModel["msg"]>(name: T, cb: (connection: Connection, arg: IModel["msg"][T]) => void, ctx: unknown) {
if (this.msgMap.has(name)) { if (this.msgMap.has(name)) {
const items = this.msgMap.get(name); const items = this.msgMap.get(name)
const index = items.findIndex((i) => cb === i.cb && i.ctx === ctx); const index = items.findIndex((i) => cb === i.cb && i.ctx === ctx)
index > -1 && items.splice(index, 1); index > -1 && items.splice(index, 1)
} }
} }
@ -85,14 +84,14 @@ export class Connection extends EventEmitter {
const msg = JSON.stringify({ const msg = JSON.stringify({
name, name,
data, data,
}); })
const view = binaryEncode(name, data); const view = binaryEncode(name, data)
const buffer = Buffer.from(view.buffer); const buffer = Buffer.from(view.buffer)
console.log( console.log(
`${getTime()}发送|字节数${buffer.length}|${this.playerId || -1}|内存${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed( `${getTime()}发送|字节数${buffer.length}|${this.playerId || -1}|内存${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(
2 2
)}MB|${msg}` )}MB|${msg}`
); )
this.ws.send(buffer); this.ws.send(buffer)
} }
} }

View File

@ -1,7 +1,7 @@
import { Connection, MyServer, MyServerEventEnum } from "./Core"; import { Connection, MyServer, MyServerEventEnum } from "./Core"
import PlayerManager from "./Biz/PlayerManager"; import PlayerManager from "./Biz/PlayerManager"
import RoomManager from "./Biz/RoomManager"; import RoomManager from "./Biz/RoomManager"
import { getTime, symlinkCommon } from "./Utils"; import { getTime, symlinkCommon } from "./Utils"
import { import {
ApiMsgEnum, ApiMsgEnum,
IApiGameEndReq, IApiGameEndReq,
@ -21,145 +21,151 @@ import {
IApiRoomListReq, IApiRoomListReq,
IApiRoomListRes, IApiRoomListRes,
IModel, IModel,
} from "./Common"; } from "./Common"
const server = new MyServer({ port: 8888 }); declare module "./Core" {
interface Connection {
playerId?: number
}
}
const server = new MyServer({ port: 8888 })
// event // event
server.on(MyServerEventEnum.Connect, (connection: Connection) => { server.on(MyServerEventEnum.Connect, (connection: Connection) => {
console.log(`${getTime()}来人|人数|${server.connections.size}`); console.log(`${getTime()}来人|人数|${server.connections.size}`)
}); })
server.on(MyServerEventEnum.DisConnect, (connection: Connection) => { server.on(MyServerEventEnum.DisConnect, (connection: Connection) => {
console.log(`${getTime()}走人|人数|${server.connections.size}`); console.log(`${getTime()}走人|人数|${server.connections.size}`)
if (connection.playerId) { if (connection.playerId) {
PlayerManager.Instance.removePlayer(connection.playerId); PlayerManager.Instance.removePlayer(connection.playerId)
} }
}); })
// api // api
server.setApi(ApiMsgEnum.ApiPlayerList, (connection: Connection, data: IApiPlayerListReq): IApiPlayerListRes => { server.setApi(ApiMsgEnum.ApiPlayerList, (connection: Connection, data: IApiPlayerListReq): IApiPlayerListRes => {
return { list: PlayerManager.Instance.getPlayersView() }; return { list: PlayerManager.Instance.getPlayersView() }
}); })
server.setApi(ApiMsgEnum.ApiPlayerJoin, (connection: Connection, { nickname }: IApiPlayerJoinReq): IApiPlayerJoinRes => { server.setApi(ApiMsgEnum.ApiPlayerJoin, (connection: Connection, { nickname }: IApiPlayerJoinReq): IApiPlayerJoinRes => {
const player = PlayerManager.Instance.createPlayer({ connection, nickname }); const player = PlayerManager.Instance.createPlayer({ connection, nickname })
PlayerManager.Instance.syncPlayers(); PlayerManager.Instance.syncPlayers()
return { return {
player: PlayerManager.Instance.getPlayerView(player), player: PlayerManager.Instance.getPlayerView(player),
}; }
}); })
server.setApi(ApiMsgEnum.ApiRoomList, (connection: Connection, data: IApiRoomListReq): IApiRoomListRes => { server.setApi(ApiMsgEnum.ApiRoomList, (connection: Connection, data: IApiRoomListReq): IApiRoomListRes => {
return { list: RoomManager.Instance.getRoomsView() }; return { list: RoomManager.Instance.getRoomsView() }
}); })
server.setApi(ApiMsgEnum.ApiRoomCreate, (connection: Connection, data: IApiRoomCreateReq): IApiRoomCreateRes => { server.setApi(ApiMsgEnum.ApiRoomCreate, (connection: Connection, data: IApiRoomCreateReq): IApiRoomCreateRes => {
if (connection.playerId) { if (connection.playerId) {
const room = RoomManager.Instance.joinRoom(RoomManager.Instance.createRoom().id, connection.playerId); const room = RoomManager.Instance.joinRoom(RoomManager.Instance.createRoom().id, connection.playerId)
if (room) { if (room) {
RoomManager.Instance.syncRooms(); RoomManager.Instance.syncRooms()
PlayerManager.Instance.syncPlayers(); PlayerManager.Instance.syncPlayers()
return { return {
room: RoomManager.Instance.getRoomView(room), room: RoomManager.Instance.getRoomView(room),
}; }
} else { } else {
throw new Error("ApiRoomCreate room不存在"); throw new Error("ApiRoomCreate room不存在")
} }
} else { } else {
throw new Error("ApiRoomCreate 玩家未登录"); throw new Error("ApiRoomCreate 玩家未登录")
} }
}); })
server.setApi(ApiMsgEnum.ApiRoomJoin, (connection: Connection, data: IApiRoomJoinReq): IApiRoomJoinRes => { server.setApi(ApiMsgEnum.ApiRoomJoin, (connection: Connection, data: IApiRoomJoinReq): IApiRoomJoinRes => {
if (connection.playerId) { if (connection.playerId) {
const room = RoomManager.Instance.joinRoom(data.rid, connection.playerId); const room = RoomManager.Instance.joinRoom(data.rid, connection.playerId)
if (room) { if (room) {
RoomManager.Instance.syncRooms(); RoomManager.Instance.syncRooms()
PlayerManager.Instance.syncPlayers(); PlayerManager.Instance.syncPlayers()
RoomManager.Instance.syncRoom(room.id); RoomManager.Instance.syncRoom(room.id)
return { return {
room: RoomManager.Instance.getRoomView(room), room: RoomManager.Instance.getRoomView(room),
}; }
} else { } else {
throw new Error("ApiRoomJoin room不存在"); throw new Error("ApiRoomJoin room不存在")
} }
} else { } else {
throw new Error("ApiRoomJoin 玩家未登录"); throw new Error("ApiRoomJoin 玩家未登录")
} }
}); })
server.setApi(ApiMsgEnum.ApiRoomLeave, (connection: Connection, data: IApiRoomLeaveReq): IApiRoomLeaveRes => { server.setApi(ApiMsgEnum.ApiRoomLeave, (connection: Connection, data: IApiRoomLeaveReq): IApiRoomLeaveRes => {
if (connection.playerId) { if (connection.playerId) {
const player = PlayerManager.Instance.getPlayerById(connection.playerId); const player = PlayerManager.Instance.getPlayerById(connection.playerId)
if (player) { if (player) {
const rid = player.rid; const rid = player.rid
if (rid) { if (rid) {
RoomManager.Instance.leaveRoom(rid, player.id); RoomManager.Instance.leaveRoom(rid, player.id)
PlayerManager.Instance.syncPlayers(); PlayerManager.Instance.syncPlayers()
RoomManager.Instance.syncRooms(); RoomManager.Instance.syncRooms()
RoomManager.Instance.syncRoom(rid); RoomManager.Instance.syncRoom(rid)
return {}; return {}
} else { } else {
throw new Error("ApiRoomLeave 玩家不在房间"); throw new Error("ApiRoomLeave 玩家不在房间")
} }
} else { } else {
throw new Error("ApiRoomLeave 玩家不存在"); throw new Error("ApiRoomLeave 玩家不存在")
} }
} else { } else {
throw new Error("ApiRoomLeave 玩家未登录"); throw new Error("ApiRoomLeave 玩家未登录")
} }
}); })
server.setApi(ApiMsgEnum.ApiGameStart, (connection: Connection, data: IApiGameStartReq): IApiGameStartRes => { server.setApi(ApiMsgEnum.ApiGameStart, (connection: Connection, data: IApiGameStartReq): IApiGameStartRes => {
if (connection.playerId) { if (connection.playerId) {
const player = PlayerManager.Instance.getPlayerById(connection.playerId); const player = PlayerManager.Instance.getPlayerById(connection.playerId)
if (player) { if (player) {
const rid = player.rid; const rid = player.rid
if (rid) { if (rid) {
RoomManager.Instance.startRoom(rid); RoomManager.Instance.startRoom(rid)
PlayerManager.Instance.syncPlayers(); PlayerManager.Instance.syncPlayers()
RoomManager.Instance.syncRooms(); RoomManager.Instance.syncRooms()
return {}; return {}
} else { } else {
throw new Error("ApiRoomLeave 玩家不在房间"); throw new Error("ApiRoomLeave 玩家不在房间")
} }
} else { } else {
throw new Error("ApiRoomLeave 玩家不存在"); throw new Error("ApiRoomLeave 玩家不存在")
} }
} else { } else {
throw new Error("ApiRoomLeave 玩家未登录"); throw new Error("ApiRoomLeave 玩家未登录")
} }
}); })
server.setApi(ApiMsgEnum.ApiGameEnd, (connection: Connection, data: IApiGameEndReq): IApiGameEndRes => { server.setApi(ApiMsgEnum.ApiGameEnd, (connection: Connection, data: IApiGameEndReq): IApiGameEndRes => {
if (connection.playerId) { if (connection.playerId) {
const player = PlayerManager.Instance.getPlayerById(connection.playerId); const player = PlayerManager.Instance.getPlayerById(connection.playerId)
if (player) { if (player) {
const rid = player.rid; const rid = player.rid
if (rid) { if (rid) {
RoomManager.Instance.closeRoom(rid); RoomManager.Instance.closeRoom(rid)
PlayerManager.Instance.syncPlayers(); PlayerManager.Instance.syncPlayers()
RoomManager.Instance.syncRooms(); RoomManager.Instance.syncRooms()
return {}; return {}
} else { } else {
throw new Error("ApiGameEnd 玩家不在房间"); throw new Error("ApiGameEnd 玩家不在房间")
} }
} else { } else {
throw new Error("ApiGameEnd 玩家不存在"); throw new Error("ApiGameEnd 玩家不存在")
} }
} else { } else {
throw new Error("ApiGameEnd 玩家未登录"); throw new Error("ApiGameEnd 玩家未登录")
} }
}); })
// start!! // start!!
server server
.start() .start()
.then(() => { .then(() => {
symlinkCommon(); symlinkCommon()
console.log("服务启动!"); console.log("服务启动!")
}) })
.catch((e) => { .catch((e) => {
console.log("服务异常", e); console.log("服务异常", e)
}); })