refactor
This commit is contained in:
parent
b7c95c5ca9
commit
c5acb09642
@ -8,7 +8,6 @@ export abstract class EntityManager extends Component {
|
|||||||
fsm: StateMachine
|
fsm: StateMachine
|
||||||
private _state: EntityStateEnum
|
private _state: EntityStateEnum
|
||||||
|
|
||||||
|
|
||||||
get state() {
|
get state() {
|
||||||
return this._state
|
return this._state
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { _decorator, Animation, Component } from 'cc'
|
import { _decorator, Animation, Component } from 'cc'
|
||||||
import { EntityTypeEnum, FsmParamTypeEnum } from '../Enum'
|
import { EntityTypeEnum } from '../Common'
|
||||||
|
import { FsmParamTypeEnum } from '../Enum'
|
||||||
const { ccclass } = _decorator
|
const { ccclass } = _decorator
|
||||||
import State from './State'
|
import State from './State'
|
||||||
import SubStateMachine from './SubStateMachine'
|
import SubStateMachine from './SubStateMachine'
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { _decorator, instantiate, ProgressBar, Label, Vec3, Tween, tween } from 'cc';
|
import { _decorator, instantiate, ProgressBar, Label, Vec3, Tween, tween, director } from 'cc';
|
||||||
import { EntityManager } from '../../Base/EntityManager';
|
import { EntityManager } from '../../Base/EntityManager';
|
||||||
import { ApiMsgEnum, EntityTypeEnum, IActor, InputTypeEnum, IVec2, toFixed } from '../../Common';
|
import { ApiMsgEnum, EntityTypeEnum, IActor, InputTypeEnum, IVec2, toFixed } from '../../Common';
|
||||||
import { EntityStateEnum } from '../../Enum';
|
import { EntityStateEnum, EventEnum, SceneEnum } from '../../Enum';
|
||||||
import DataManager from '../../Global/DataManager';
|
import DataManager from '../../Global/DataManager';
|
||||||
|
import EventManager from '../../Global/EventManager';
|
||||||
import NetworkManager from '../../Global/NetworkManager';
|
import NetworkManager from '../../Global/NetworkManager';
|
||||||
import { rad2Angle } from '../../Utils';
|
import { rad2Angle } from '../../Utils';
|
||||||
import { WeaponManager } from '../Weapon/WeaponManager';
|
import { WeaponManager } from '../Weapon/WeaponManager';
|
||||||
@ -30,6 +31,8 @@ export class ActorManager extends EntityManager implements IActor {
|
|||||||
private tw: Tween<any>
|
private tw: Tween<any>
|
||||||
private targetPos: Vec3
|
private targetPos: Vec3
|
||||||
|
|
||||||
|
private isDead = false
|
||||||
|
|
||||||
get isSelf() {
|
get isSelf() {
|
||||||
return DataManager.Instance.myPlayerId === this.id
|
return DataManager.Instance.myPlayerId === this.id
|
||||||
}
|
}
|
||||||
@ -60,11 +63,17 @@ export class ActorManager extends EntityManager implements IActor {
|
|||||||
this.node.active = false
|
this.node.active = false
|
||||||
}
|
}
|
||||||
|
|
||||||
tick(dt: number) {
|
async tick(dt: number) {
|
||||||
if (!this.isSelf) {
|
if (!this.isSelf) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.hp <= 0 && !this.isDead) {
|
||||||
|
EventManager.Instance.emit(EventEnum.GameEnd)
|
||||||
|
this.isDead = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (DataManager.Instance.jm.input.length()) {
|
if (DataManager.Instance.jm.input.length()) {
|
||||||
const { x, y } = DataManager.Instance.jm.input
|
const { x, y } = DataManager.Instance.jm.input
|
||||||
NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, {
|
NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, {
|
||||||
@ -87,6 +96,7 @@ export class ActorManager extends EntityManager implements IActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderHP(data: IActor) {
|
renderHP(data: IActor) {
|
||||||
|
this.hp = data.hp
|
||||||
this.hpBar.progress = data.hp / this.hpBar.totalLength
|
this.hpBar.progress = data.hp / this.hpBar.totalLength
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ export enum EventEnum {
|
|||||||
ExplosionBorn = 'ExplosionBorn',
|
ExplosionBorn = 'ExplosionBorn',
|
||||||
RoomJoin = 'RoomJoin',
|
RoomJoin = 'RoomJoin',
|
||||||
GameStart = 'GameStart',
|
GameStart = 'GameStart',
|
||||||
|
GameEnd = 'GameEnd',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PrefabPathEnum {
|
export enum PrefabPathEnum {
|
||||||
|
@ -16,25 +16,36 @@ const WEAPON_DAMAGE = 5
|
|||||||
const PLAYER_RADIUS = 50
|
const PLAYER_RADIUS = 50
|
||||||
const BULLET_RADIUS = 10
|
const BULLET_RADIUS = 10
|
||||||
|
|
||||||
|
const mapW = 960
|
||||||
|
const mapH = 640
|
||||||
|
|
||||||
export default class DataManager extends Singleton {
|
export default class DataManager extends Singleton {
|
||||||
static get Instance() {
|
static get Instance() {
|
||||||
return super.GetInstance<DataManager>()
|
return super.GetInstance<DataManager>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//登陆数据
|
||||||
|
myPlayerId = 1
|
||||||
|
|
||||||
|
//大厅数据
|
||||||
|
roomInfo: IRoom
|
||||||
|
|
||||||
|
//游戏数据
|
||||||
stage: Node
|
stage: Node
|
||||||
jm: JoyStickManager
|
jm: JoyStickManager
|
||||||
|
|
||||||
prefabMap: Map<string, Prefab> = new Map()
|
prefabMap: Map<string, Prefab> = new Map()
|
||||||
textureMap: Map<string, SpriteFrame[]> = new Map()
|
textureMap: Map<string, SpriteFrame[]> = new Map()
|
||||||
|
|
||||||
actorMap: Map<number, ActorManager> = new Map()
|
actorMap: Map<number, ActorManager> = new Map()
|
||||||
bulletMap: Map<number, BulletManager> = new Map()
|
bulletMap: Map<number, BulletManager> = new Map()
|
||||||
|
|
||||||
myPlayerId = 1
|
reset() {
|
||||||
roomInfo: IRoom
|
this.stage = null
|
||||||
mapSize = {
|
this.jm = null
|
||||||
x: 960,
|
this.actorMap.clear()
|
||||||
y: 640,
|
this.bulletMap.clear()
|
||||||
|
this.prefabMap.clear()
|
||||||
|
this.textureMap.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
state: IState = {
|
state: IState = {
|
||||||
@ -85,8 +96,8 @@ export default class DataManager extends Singleton {
|
|||||||
player.position.x += toFixed(x * PLAYER_SPEED * dt)
|
player.position.x += toFixed(x * PLAYER_SPEED * dt)
|
||||||
player.position.y += toFixed(y * PLAYER_SPEED * dt)
|
player.position.y += toFixed(y * PLAYER_SPEED * dt)
|
||||||
|
|
||||||
player.position.x = clamp(player.position.x, -this.mapSize.x / 2, this.mapSize.x / 2)
|
player.position.x = clamp(player.position.x, -mapW / 2, mapW / 2)
|
||||||
player.position.y = clamp(player.position.y, -this.mapSize.y / 2, this.mapSize.y / 2)
|
player.position.y = clamp(player.position.y, -mapH / 2, mapH / 2)
|
||||||
|
|
||||||
player.direction = { x, y }
|
player.direction = { x, y }
|
||||||
break
|
break
|
||||||
@ -124,7 +135,7 @@ export default class DataManager extends Singleton {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Math.abs(bullet.position.x) > this.mapSize.x / 2 || Math.abs(bullet.position.y) > this.mapSize.y / 2) {
|
if (Math.abs(bullet.position.x) > mapW / 2 || Math.abs(bullet.position.y) > mapH / 2) {
|
||||||
EventManager.Instance.emit(EventEnum.ExplosionBorn, bullet.id, {
|
EventManager.Instance.emit(EventEnum.ExplosionBorn, bullet.id, {
|
||||||
x: bullet.position.x,
|
x: bullet.position.x,
|
||||||
y: bullet.position.y,
|
y: bullet.position.y,
|
||||||
|
@ -2,7 +2,7 @@ import Singleton from '../Base/Singleton'
|
|||||||
import { EventEnum } from '../Enum';
|
import { EventEnum } from '../Enum';
|
||||||
|
|
||||||
interface IItem {
|
interface IItem {
|
||||||
func: Function;
|
cb: Function;
|
||||||
ctx: unknown;
|
ctx: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,25 +13,25 @@ export default class EventManager extends Singleton {
|
|||||||
|
|
||||||
private map: Map<EventEnum, Array<IItem>> = new Map();
|
private map: Map<EventEnum, Array<IItem>> = new Map();
|
||||||
|
|
||||||
on(event: EventEnum, func: Function, ctx?: unknown) {
|
on(event: EventEnum, cb: Function, ctx: unknown) {
|
||||||
if (this.map.has(event)) {
|
if (this.map.has(event)) {
|
||||||
this.map.get(event).push({ func, ctx });
|
this.map.get(event).push({ cb, ctx });
|
||||||
} else {
|
} else {
|
||||||
this.map.set(event, [{ func, ctx }]);
|
this.map.set(event, [{ cb, ctx }]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
off(event: EventEnum, func: Function, ctx?: unknown) {
|
off(event: EventEnum, cb: Function, ctx: unknown) {
|
||||||
if (this.map.has(event)) {
|
if (this.map.has(event)) {
|
||||||
const index = this.map.get(event).findIndex(i => func === i.func && i.ctx === ctx);
|
const index = this.map.get(event).findIndex(i => cb === i.cb && i.ctx === ctx);
|
||||||
index > -1 && this.map.get(event).splice(index, 1);
|
index > -1 && this.map.get(event).splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(event: EventEnum, ...params: unknown[]) {
|
emit(event: EventEnum, ...params: unknown[]) {
|
||||||
if (this.map.has(event)) {
|
if (this.map.has(event)) {
|
||||||
this.map.get(event).forEach(({ func, ctx }) => {
|
this.map.get(event).forEach(({ cb, ctx }) => {
|
||||||
ctx ? func.apply(ctx, params) : func(...params);
|
cb.apply(ctx, params)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import Singleton from '../Base/Singleton'
|
import Singleton from '../Base/Singleton'
|
||||||
import { ApiMsgEnum, IModel, strdecode, strencode } from '../Common';
|
import { ApiMsgEnum, IModel } from '../Common';
|
||||||
import { binaryEncode, binaryDecode } from '../Common/Binary';
|
import { binaryEncode, binaryDecode } from '../Common/Binary';
|
||||||
|
|
||||||
const TIMEOUT = 5000
|
const TIMEOUT = 5000
|
||||||
|
|
||||||
|
interface IItem {
|
||||||
|
cb: Function;
|
||||||
|
ctx: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ICallApiRet<T> {
|
export interface ICallApiRet<T> {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
error?: Error;
|
error?: Error;
|
||||||
@ -18,7 +23,7 @@ export default class NetworkManager extends Singleton {
|
|||||||
|
|
||||||
ws: WebSocket
|
ws: WebSocket
|
||||||
port = 8888
|
port = 8888
|
||||||
maps: Map<ApiMsgEnum, Function[]> = new Map()
|
maps: Map<ApiMsgEnum, Array<IItem>> = new Map()
|
||||||
isConnected = false
|
isConnected = false
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
@ -28,16 +33,17 @@ export default class NetworkManager extends Singleton {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.ws = new WebSocket(`ws://localhost:${this.port}`)
|
this.ws = new WebSocket(`ws://localhost:${this.port}`)
|
||||||
|
//onmessage接受的数据类型,只有在后端返回字节数组的时候才有效果
|
||||||
this.ws.binaryType = 'arraybuffer';
|
this.ws.binaryType = 'arraybuffer';
|
||||||
|
|
||||||
this.ws.onopen = () => {
|
this.ws.onopen = () => {
|
||||||
console.log("ws onopen")
|
|
||||||
this.isConnected = true
|
this.isConnected = true
|
||||||
resolve(true)
|
resolve(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ws.onerror = () => {
|
this.ws.onerror = (e) => {
|
||||||
this.isConnected = false
|
this.isConnected = false
|
||||||
|
console.log(e)
|
||||||
reject("ws onerror")
|
reject("ws onerror")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,12 +59,11 @@ export default class NetworkManager extends Singleton {
|
|||||||
try {
|
try {
|
||||||
if (this.maps.has(name) && this.maps.get(name).length) {
|
if (this.maps.has(name) && this.maps.get(name).length) {
|
||||||
console.log(json);
|
console.log(json);
|
||||||
this.maps.get(name).forEach(cb => cb(data))
|
this.maps.get(name).forEach(({ cb, ctx }) => cb.call(ctx, data))
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("this.maps.get(name).forEach(cb => cb(restData))", error)
|
console.log("onmessage:", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('解析失败,不是合法的JSON格式', error)
|
console.log('解析失败,不是合法的JSON格式', error)
|
||||||
}
|
}
|
||||||
@ -72,20 +77,19 @@ export default class NetworkManager extends Singleton {
|
|||||||
// 超时处理
|
// 超时处理
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
resolve({ success: false, error: new Error('timeout') })
|
resolve({ success: false, error: new Error('timeout') })
|
||||||
this.unlistenMsg(name, cb)
|
this.unlistenMsg(name as any, cb, null)
|
||||||
}, TIMEOUT)
|
}, TIMEOUT)
|
||||||
|
|
||||||
// 回调处理
|
// 回调处理
|
||||||
const cb = (res) => {
|
const cb = (res) => {
|
||||||
resolve(res)
|
resolve(res)
|
||||||
clearTimeout(timer)
|
clearTimeout(timer)
|
||||||
this.unlistenMsg(name, cb)
|
this.unlistenMsg(name as any, cb, null)
|
||||||
}
|
}
|
||||||
this.listenMsg(name as any, cb)
|
this.listenMsg(name as any, cb, null)
|
||||||
|
|
||||||
this.sendMsg(name as any, data)
|
this.sendMsg(name as any, data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
|
||||||
resolve({ success: false, error: error as Error })
|
resolve({ success: false, error: error as Error })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -98,18 +102,19 @@ export default class NetworkManager extends Singleton {
|
|||||||
this.ws.send(view.buffer)
|
this.ws.send(view.buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void) {
|
listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
|
||||||
if (this.maps.has(name)) {
|
if (this.maps.has(name)) {
|
||||||
this.maps.get(name).push(cb)
|
this.maps.get(name).push({ ctx, cb })
|
||||||
} else {
|
} else {
|
||||||
this.maps.set(name, [cb])
|
this.maps.set(name, [{ ctx, cb }])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unlistenMsg(name: ApiMsgEnum, cb: Function) {
|
unlistenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
|
||||||
if (this.maps.has(name)) {
|
if (this.maps.has(name)) {
|
||||||
const index = this.maps.get(name).indexOf(cb)
|
const items = this.maps.get(name)
|
||||||
index > -1 && this.maps.get(name).splice(index, 1)
|
const index = items.findIndex(i => cb === i.cb && i.ctx === ctx);
|
||||||
|
index > -1 && items.splice(index, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,11 @@ export default class ObjectPoolManager extends Singleton {
|
|||||||
return objectName + 'Pool'
|
return objectName + 'Pool'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.objectPool = null
|
||||||
|
this.map.clear()
|
||||||
|
}
|
||||||
|
|
||||||
get(objectName: EntityTypeEnum) {
|
get(objectName: EntityTypeEnum) {
|
||||||
if (this.objectPool === null) {
|
if (this.objectPool === null) {
|
||||||
this.objectPool = new Node("ObjectPool")
|
this.objectPool = new Node("ObjectPool")
|
||||||
|
@ -1,37 +1,52 @@
|
|||||||
import { _decorator, Component, Node, Prefab, instantiate, SpriteFrame } from 'cc';
|
import { _decorator, Component, Node, Prefab, instantiate, SpriteFrame, director } from 'cc';
|
||||||
import { ActorManager } from '../Entity/Actor/ActorManager';
|
import { ActorManager } from '../Entity/Actor/ActorManager';
|
||||||
import DataManager from '../Global/DataManager';
|
import DataManager from '../Global/DataManager';
|
||||||
import { JoyStickManager } from '../UI/JoyStickManager';
|
import { JoyStickManager } from '../UI/JoyStickManager';
|
||||||
import { ResourceManager } from '../Global/ResourceManager';
|
import { ResourceManager } from '../Global/ResourceManager';
|
||||||
import { PrefabPathEnum, TexturePathEnum } from '../Enum';
|
import { EventEnum, PrefabPathEnum, SceneEnum, TexturePathEnum } from '../Enum';
|
||||||
import NetworkManager from '../Global/NetworkManager';
|
import NetworkManager from '../Global/NetworkManager';
|
||||||
import ObjectPoolManager from '../Global/ObjectPoolManager';
|
import ObjectPoolManager from '../Global/ObjectPoolManager';
|
||||||
import { BulletManager } from '../Entity/Bullet/BulletManager';
|
import { BulletManager } from '../Entity/Bullet/BulletManager';
|
||||||
import { ApiMsgEnum, EntityTypeEnum, IMsgServerSync, InputTypeEnum } from '../Common';
|
import { ApiMsgEnum, EntityTypeEnum, IMsgServerSync, InputTypeEnum } from '../Common';
|
||||||
|
import EventManager from '../Global/EventManager';
|
||||||
|
|
||||||
const { ccclass } = _decorator;
|
const { ccclass } = _decorator;
|
||||||
|
|
||||||
@ccclass('BattleManager')
|
@ccclass('BattleManager')
|
||||||
export class BattleManager extends Component {
|
export class BattleManager extends Component {
|
||||||
stage: Node
|
private stage: Node
|
||||||
ui: Node
|
private ui: Node
|
||||||
isInited = false
|
private shouldUpdate = false
|
||||||
onLoad() {
|
|
||||||
this.stage = DataManager.Instance.stage = this.node.getChildByName("Stage")
|
|
||||||
this.ui = this.node.getChildByName("UI")
|
|
||||||
}
|
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
|
//清空
|
||||||
this.clearGame()
|
this.clearGame()
|
||||||
await this.loadRes()
|
|
||||||
this.initScene()
|
//资源加载和网络连接同步执行
|
||||||
await this.connectServer()
|
await Promise.all([this.loadRes(), this.connectServer()])
|
||||||
|
|
||||||
|
this.initGame()
|
||||||
|
|
||||||
// 在场景初始化完毕之前,卡主别的玩家,准备好以后再告知服务器,等所有玩家都准备好以后才开始,这里就不做了
|
// 在场景初始化完毕之前,卡主别的玩家,准备好以后再告知服务器,等所有玩家都准备好以后才开始,这里就不做了
|
||||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgServerSync, this.handleSync);
|
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgServerSync, this.handleSync, this);
|
||||||
this.isInited = true
|
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgGameEnd, this.leaveGame, this);
|
||||||
|
EventManager.Instance.on(EventEnum.GameEnd, this.handleGameEnd, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
clearGame() {
|
clearGame() {
|
||||||
|
//监听
|
||||||
|
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgServerSync, this.handleSync, this);
|
||||||
|
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgGameEnd, this.leaveGame, this);
|
||||||
|
EventManager.Instance.off(EventEnum.GameEnd, this.handleGameEnd, this)
|
||||||
|
|
||||||
|
//数据
|
||||||
|
this.shouldUpdate = false
|
||||||
|
ObjectPoolManager.Instance.reset()
|
||||||
|
DataManager.Instance.reset()
|
||||||
|
|
||||||
|
//节点
|
||||||
|
this.stage = DataManager.Instance.stage = this.node.getChildByName("Stage")
|
||||||
|
this.ui = this.node.getChildByName("UI")
|
||||||
this.stage.destroyAllChildren()
|
this.stage.destroyAllChildren()
|
||||||
this.ui.destroyAllChildren()
|
this.ui.destroyAllChildren()
|
||||||
}
|
}
|
||||||
@ -53,12 +68,6 @@ export class BattleManager extends Component {
|
|||||||
await Promise.all(list)
|
await Promise.all(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
async initScene() {
|
|
||||||
this.initJoyStick()
|
|
||||||
this.initShoot()
|
|
||||||
this.initMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
async connectServer() {
|
async connectServer() {
|
||||||
if (!await NetworkManager.Instance.connect().catch(() => false)) {
|
if (!await NetworkManager.Instance.connect().catch(() => false)) {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||||
@ -66,6 +75,26 @@ export class BattleManager extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leaveGame() {
|
||||||
|
this.clearGame()
|
||||||
|
director.loadScene(SceneEnum.Hall);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleGameEnd() {
|
||||||
|
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiGameEnd, { rid: DataManager.Instance.roomInfo.id })
|
||||||
|
if (!success) {
|
||||||
|
console.log(error)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async initGame() {
|
||||||
|
this.initJoyStick()
|
||||||
|
this.initShoot()
|
||||||
|
this.initMap()
|
||||||
|
this.shouldUpdate = true
|
||||||
|
}
|
||||||
|
|
||||||
initJoyStick() {
|
initJoyStick() {
|
||||||
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.JoyStick)
|
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.JoyStick)
|
||||||
const joySitck = instantiate(prefab)
|
const joySitck = instantiate(prefab)
|
||||||
@ -86,14 +115,8 @@ export class BattleManager extends Component {
|
|||||||
map.setParent(this.stage)
|
map.setParent(this.stage)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSync(inputs: IMsgServerSync) {
|
|
||||||
for (const input of inputs) {
|
|
||||||
DataManager.Instance.applyInput(input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update(dt: number) {
|
update(dt: number) {
|
||||||
if (!this.isInited) {
|
if (!this.shouldUpdate) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.render()
|
this.render()
|
||||||
@ -158,5 +181,12 @@ export class BattleManager extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSync(inputs: IMsgServerSync) {
|
||||||
|
for (const input of inputs) {
|
||||||
|
DataManager.Instance.applyInput(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,14 +25,14 @@ export class HallManager extends Component {
|
|||||||
onLoad() {
|
onLoad() {
|
||||||
director.preloadScene(SceneEnum.Room);
|
director.preloadScene(SceneEnum.Room);
|
||||||
EventManager.Instance.on(EventEnum.RoomJoin, this.joinRoom, this)
|
EventManager.Instance.on(EventEnum.RoomJoin, this.joinRoom, this)
|
||||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgPlayerList, this.renderPlayers);
|
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgPlayerList, this.renderPlayers, this);
|
||||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgRoomList, this.renderRooms);
|
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgRoomList, this.renderRooms, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy() {
|
onDestroy() {
|
||||||
EventManager.Instance.off(EventEnum.RoomJoin, this.joinRoom, this)
|
EventManager.Instance.off(EventEnum.RoomJoin, this.joinRoom, this)
|
||||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgPlayerList, this.renderPlayers);
|
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgPlayerList, this.renderPlayers, this);
|
||||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgRoomList, this.renderRooms);
|
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgRoomList, this.renderRooms, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { _decorator, Component, Node, Prefab, director, instantiate } from 'cc';
|
import { _decorator, Component, Node, Prefab, director, instantiate } from 'cc';
|
||||||
import { ApiMsgEnum, IMsgGameStart, IMsgRoom } from '../Common';
|
import { ApiMsgEnum, IMsgGameStart, IMsgRoom } from '../Common';
|
||||||
import { EventEnum, SceneEnum } from '../Enum';
|
import { SceneEnum } from '../Enum';
|
||||||
import DataManager from '../Global/DataManager';
|
import DataManager from '../Global/DataManager';
|
||||||
import EventManager from '../Global/EventManager';
|
|
||||||
import NetworkManager from '../Global/NetworkManager';
|
import NetworkManager from '../Global/NetworkManager';
|
||||||
import { PlayerManager } from '../UI/PlayerManager';
|
import { PlayerManager } from '../UI/PlayerManager';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
@ -17,13 +16,13 @@ export class RoomManager extends Component {
|
|||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
director.preloadScene(SceneEnum.Battle);
|
director.preloadScene(SceneEnum.Battle);
|
||||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgRoom, this.renderPlayers);
|
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgRoom, this.renderPlayers, this);
|
||||||
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgGameStart, this.startGame);
|
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgGameStart, this.handleGameStart, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy() {
|
onDestroy() {
|
||||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgRoom, this.renderPlayers);
|
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgRoom, this.renderPlayers, this);
|
||||||
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgGameStart, this.startGame);
|
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgGameStart, this.handleGameStart, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
@ -32,7 +31,7 @@ export class RoomManager extends Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPlayers = ({ room: { players: list } }: IMsgRoom) => {
|
renderPlayers({ room: { players: list } }: IMsgRoom) {
|
||||||
for (const item of this.playerContainer.children) {
|
for (const item of this.playerContainer.children) {
|
||||||
item.active = false
|
item.active = false
|
||||||
}
|
}
|
||||||
@ -67,13 +66,10 @@ export class RoomManager extends Component {
|
|||||||
console.log(error)
|
console.log(error)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// director.loadScene(SceneEnum.Battle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
startGame = ({ state }: IMsgGameStart) => {
|
handleGameStart({ state }: IMsgGameStart) {
|
||||||
DataManager.Instance.state = state
|
DataManager.Instance.state = state
|
||||||
|
|
||||||
director.loadScene(SceneEnum.Battle);
|
director.loadScene(SceneEnum.Battle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ export class RoomManager extends Component {
|
|||||||
init({ id, players }: { id: number, players: Array<{ id: number, nickname: string }> }) {
|
init({ id, players }: { id: number, players: Array<{ id: number, nickname: string }> }) {
|
||||||
this.id = id
|
this.id = id
|
||||||
const label = this.getComponent(Label)
|
const label = this.getComponent(Label)
|
||||||
label.string = `房间id:${id},当前人数:${players.length}`
|
label.string = `房间id:${id},当前人数:${players.length}`
|
||||||
this.node.active = true
|
this.node.active = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
import { IPlayer, IRoom } from "./Model"
|
export interface IPlayer {
|
||||||
|
id: number, nickname: string, rid: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRoom {
|
||||||
|
id: number, players: Array<IPlayer>
|
||||||
|
}
|
||||||
|
|
||||||
export interface IApiPlayerListReq {
|
export interface IApiPlayerListReq {
|
||||||
}
|
}
|
||||||
@ -47,3 +53,9 @@ export interface IApiGameStartReq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IApiGameStartRes { }
|
export interface IApiGameStartRes { }
|
||||||
|
|
||||||
|
export interface IApiGameEndReq {
|
||||||
|
rid: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApiGameEndRes { }
|
@ -22,10 +22,12 @@ export enum ApiMsgEnum {
|
|||||||
ApiRoomJoin,
|
ApiRoomJoin,
|
||||||
ApiRoomLeave,
|
ApiRoomLeave,
|
||||||
ApiGameStart,
|
ApiGameStart,
|
||||||
|
ApiGameEnd,
|
||||||
MsgPlayerList,
|
MsgPlayerList,
|
||||||
MsgRoomList,
|
MsgRoomList,
|
||||||
MsgRoom,
|
MsgRoom,
|
||||||
MsgGameStart,
|
MsgGameStart,
|
||||||
|
MsgGameEnd,
|
||||||
MsgClientSync,
|
MsgClientSync,
|
||||||
MsgServerSync,
|
MsgServerSync,
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,50 @@
|
|||||||
|
import { IApiGameEndReq, IApiGameStartReq, IApiGameStartRes, IApiPlayerJoinReq, IApiPlayerJoinRes, IApiPlayerListReq, IApiPlayerListRes, IApiRoomCreateReq, IApiRoomCreateRes, IApiRoomJoinReq, IApiRoomJoinRes, IApiRoomLeaveReq, IApiRoomLeaveRes, IApiRoomListReq, IApiRoomListRes, IApiGameEndRes } from './Api'
|
||||||
|
import { ApiMsgEnum } from './Enum'
|
||||||
|
import { IMsgClientSync, IMsgGameEnd, IMsgGameStart, IMsgPlayerList, IMsgRoom, IMsgRoomList, IMsgServerSync } from './Msg'
|
||||||
|
|
||||||
export interface IPlayer {
|
export interface IModel {
|
||||||
id: number, nickname: string, rid: number
|
api: {
|
||||||
}
|
[ApiMsgEnum.ApiPlayerJoin]: {
|
||||||
|
req: IApiPlayerJoinReq,
|
||||||
export interface IRoom {
|
res: IApiPlayerJoinRes,
|
||||||
id: number, players: Array<IPlayer>
|
}
|
||||||
|
[ApiMsgEnum.ApiPlayerList]: {
|
||||||
|
req: IApiPlayerListReq,
|
||||||
|
res: IApiPlayerListRes,
|
||||||
|
}
|
||||||
|
[ApiMsgEnum.ApiRoomList]: {
|
||||||
|
req: IApiRoomListReq,
|
||||||
|
res: IApiRoomListRes,
|
||||||
|
}
|
||||||
|
[ApiMsgEnum.ApiRoomCreate]: {
|
||||||
|
req: IApiRoomCreateReq,
|
||||||
|
res: IApiRoomCreateRes,
|
||||||
|
}
|
||||||
|
[ApiMsgEnum.ApiRoomJoin]: {
|
||||||
|
req: IApiRoomJoinReq,
|
||||||
|
res: IApiRoomJoinRes,
|
||||||
|
}
|
||||||
|
[ApiMsgEnum.ApiRoomLeave]: {
|
||||||
|
req: IApiRoomLeaveReq,
|
||||||
|
res: IApiRoomLeaveRes,
|
||||||
|
}
|
||||||
|
[ApiMsgEnum.ApiGameStart]: {
|
||||||
|
req: IApiGameStartReq,
|
||||||
|
res: IApiGameStartRes,
|
||||||
|
},
|
||||||
|
[ApiMsgEnum.ApiGameEnd]: {
|
||||||
|
req: IApiGameEndReq,
|
||||||
|
res: IApiGameEndRes,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
msg: {
|
||||||
|
[ApiMsgEnum.MsgPlayerList]: IMsgPlayerList
|
||||||
|
[ApiMsgEnum.MsgRoomList]: IMsgRoomList,
|
||||||
|
[ApiMsgEnum.MsgRoom]: IMsgRoom,
|
||||||
|
[ApiMsgEnum.MsgGameStart]: IMsgGameStart,
|
||||||
|
[ApiMsgEnum.MsgGameEnd]: IMsgGameEnd,
|
||||||
|
[ApiMsgEnum.MsgClientSync]: IMsgClientSync,
|
||||||
|
[ApiMsgEnum.MsgServerSync]: IMsgServerSync,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IPlayer, IRoom } from "./Model"
|
import { IPlayer, IRoom } from "./Api"
|
||||||
import { IClientInput, IState } from "./State"
|
import { IClientInput, IState } from "./State"
|
||||||
|
|
||||||
export interface IMsgPlayerList {
|
export interface IMsgPlayerList {
|
||||||
@ -22,6 +22,10 @@ export interface IMsgGameStart {
|
|||||||
state: IState
|
state: IState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IMsgGameEnd {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export type IMsgClientSync = IClientInput
|
export type IMsgClientSync = IClientInput
|
||||||
|
|
||||||
export type IMsgServerSync = Array<IClientInput>
|
export type IMsgServerSync = Array<IClientInput>
|
@ -7,36 +7,43 @@ export default class Room {
|
|||||||
id: number
|
id: number
|
||||||
players: Set<Player> = new Set()
|
players: Set<Player> = new Set()
|
||||||
lastSyncTime?: number
|
lastSyncTime?: number
|
||||||
timers: NodeJS.Timer[] = []
|
|
||||||
|
|
||||||
|
private timers: NodeJS.Timer[] = []
|
||||||
private inputs: Array<IClientInput> = []
|
private inputs: Array<IClientInput> = []
|
||||||
|
|
||||||
constructor(rid: number) {
|
constructor(rid: number) {
|
||||||
this.id = rid
|
this.id = rid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
join(uid: number) {
|
join(uid: number) {
|
||||||
const player = PlayerManager.Instance.getPlayerById(uid)
|
const player = PlayerManager.Instance.getPlayerById(uid)
|
||||||
if (player) {
|
if (player) {
|
||||||
player.rid = this.id
|
player.rid = this.id
|
||||||
this.players.add(player)
|
this.players.add(player)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
leave(uid: number) {
|
leave(uid: number) {
|
||||||
const player = PlayerManager.Instance.getPlayerById(uid)
|
const player = PlayerManager.Instance.getPlayerById(uid)
|
||||||
if (player) {
|
if (player) {
|
||||||
player.rid = -1
|
player.rid = -1
|
||||||
|
player.connection.unlistenMsg(ApiMsgEnum.MsgClientSync, this.getInput, this)
|
||||||
this.players.delete(player)
|
this.players.delete(player)
|
||||||
if (!this.players.size) {
|
if (!this.players.size) {
|
||||||
this.timers.forEach(t => clearInterval(t))
|
|
||||||
RoomManager.Instance.closeRoom(this.id)
|
RoomManager.Instance.closeRoom(this.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.timers.forEach(t => clearInterval(t))
|
||||||
|
for (const player of this.players) {
|
||||||
|
player.connection.sendMsg(ApiMsgEnum.MsgGameEnd, {})
|
||||||
|
player.connection.unlistenMsg(ApiMsgEnum.MsgClientSync, this.getInput, this)
|
||||||
|
}
|
||||||
|
this.players.clear()
|
||||||
|
}
|
||||||
|
|
||||||
sync() {
|
sync() {
|
||||||
for (const player of this.players) {
|
for (const player of this.players) {
|
||||||
player.connection.sendMsg(ApiMsgEnum.MsgRoom, {
|
player.connection.sendMsg(ApiMsgEnum.MsgRoom, {
|
||||||
@ -71,10 +78,10 @@ export default class Room {
|
|||||||
player.connection.sendMsg(ApiMsgEnum.MsgGameStart, {
|
player.connection.sendMsg(ApiMsgEnum.MsgGameStart, {
|
||||||
state
|
state
|
||||||
})
|
})
|
||||||
|
player.connection.listenMsg(ApiMsgEnum.MsgClientSync, this.getInput, this)
|
||||||
}
|
}
|
||||||
this.listenPlayer()
|
|
||||||
let t1 = setInterval(() => {
|
let t1 = setInterval(() => {
|
||||||
this.syncInput()
|
this.sendInput()
|
||||||
}, 100)
|
}, 100)
|
||||||
let t2 = setInterval(() => {
|
let t2 = setInterval(() => {
|
||||||
this.timePast()
|
this.timePast()
|
||||||
@ -82,19 +89,14 @@ export default class Room {
|
|||||||
this.timers = [t1, t2]
|
this.timers = [t1, t2]
|
||||||
}
|
}
|
||||||
|
|
||||||
listenPlayer() {
|
getInput(input: IClientInput) {
|
||||||
for (const player of this.players) {
|
this.inputs.push(input)
|
||||||
player.connection.listenMsg(ApiMsgEnum.MsgClientSync, (input) => {
|
|
||||||
this.inputs.push(input)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
syncInput() {
|
sendInput() {
|
||||||
const inputs = this.inputs
|
const inputs = this.inputs
|
||||||
this.inputs = []
|
this.inputs = []
|
||||||
|
|
||||||
|
|
||||||
for (const player of this.players) {
|
for (const player of this.players) {
|
||||||
player.connection.sendMsg(ApiMsgEnum.MsgServerSync, inputs)
|
player.connection.sendMsg(ApiMsgEnum.MsgServerSync, inputs)
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ export default class RoomManager extends Singleton {
|
|||||||
closeRoom(rid: number) {
|
closeRoom(rid: number) {
|
||||||
const room = this.getRoomById(rid)
|
const room = this.getRoomById(rid)
|
||||||
if (room) {
|
if (room) {
|
||||||
|
room.close()
|
||||||
this.rooms.delete(room)
|
this.rooms.delete(room)
|
||||||
this.idMapRoom.delete(rid)
|
this.idMapRoom.delete(rid)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
import { IApiGameStartReq, IApiGameStartRes, IApiPlayerJoinReq, IApiPlayerJoinRes, IApiPlayerListReq, IApiPlayerListRes, IApiRoomCreateReq, IApiRoomCreateRes, IApiRoomJoinReq, IApiRoomJoinRes, IApiRoomLeaveReq, IApiRoomLeaveRes, IApiRoomListReq, IApiRoomListRes } from './Api'
|
|
||||||
import { ApiMsgEnum } from './Enum'
|
|
||||||
import { IMsgClientSync, IMsgGameStart, IMsgPlayerList, IMsgRoom, IMsgRoomList, IMsgServerSync } from './Msg'
|
|
||||||
export * from './Api'
|
export * from './Api'
|
||||||
export * from './Msg'
|
export * from './Msg'
|
||||||
export * from './Enum'
|
export * from './Enum'
|
||||||
@ -9,44 +6,3 @@ export * from './State'
|
|||||||
export * from './Utils'
|
export * from './Utils'
|
||||||
export * from './Binary'
|
export * from './Binary'
|
||||||
|
|
||||||
export interface IModel {
|
|
||||||
api: {
|
|
||||||
[ApiMsgEnum.ApiPlayerJoin]: {
|
|
||||||
req: IApiPlayerJoinReq,
|
|
||||||
res: IApiPlayerJoinRes,
|
|
||||||
}
|
|
||||||
[ApiMsgEnum.ApiPlayerList]: {
|
|
||||||
req: IApiPlayerListReq,
|
|
||||||
res: IApiPlayerListRes,
|
|
||||||
}
|
|
||||||
[ApiMsgEnum.ApiRoomList]: {
|
|
||||||
req: IApiRoomListReq,
|
|
||||||
res: IApiRoomListRes,
|
|
||||||
}
|
|
||||||
[ApiMsgEnum.ApiRoomCreate]: {
|
|
||||||
req: IApiRoomCreateReq,
|
|
||||||
res: IApiRoomCreateRes,
|
|
||||||
}
|
|
||||||
[ApiMsgEnum.ApiRoomJoin]: {
|
|
||||||
req: IApiRoomJoinReq,
|
|
||||||
res: IApiRoomJoinRes,
|
|
||||||
}
|
|
||||||
[ApiMsgEnum.ApiRoomLeave]: {
|
|
||||||
req: IApiRoomLeaveReq,
|
|
||||||
res: IApiRoomLeaveRes,
|
|
||||||
}
|
|
||||||
[ApiMsgEnum.ApiGameStart]: {
|
|
||||||
req: IApiGameStartReq,
|
|
||||||
res: IApiGameStartRes,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
msg: {
|
|
||||||
[ApiMsgEnum.MsgPlayerList]: IMsgPlayerList
|
|
||||||
[ApiMsgEnum.MsgRoomList]: IMsgRoomList,
|
|
||||||
[ApiMsgEnum.MsgRoom]: IMsgRoom,
|
|
||||||
[ApiMsgEnum.MsgGameStart]: IMsgGameStart,
|
|
||||||
[ApiMsgEnum.MsgClientSync]: IMsgClientSync,
|
|
||||||
[ApiMsgEnum.MsgServerSync]: IMsgServerSync,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -9,10 +9,15 @@ export enum ConnectionEventEnum {
|
|||||||
Close = 'Close',
|
Close = 'Close',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IItem {
|
||||||
|
cb: Function;
|
||||||
|
ctx: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
export class Connection extends EventEmitter {
|
export class Connection extends EventEmitter {
|
||||||
server: MyServer
|
server: MyServer
|
||||||
ws: WebSocket
|
ws: WebSocket
|
||||||
msgMap: Map<ApiMsgEnum, Function[]> = new Map()
|
msgMap: Map<ApiMsgEnum, Array<IItem>> = new Map()
|
||||||
playerId?: number;
|
playerId?: number;
|
||||||
|
|
||||||
constructor(server: MyServer, ws: WebSocket) {
|
constructor(server: MyServer, ws: WebSocket) {
|
||||||
@ -34,7 +39,7 @@ export class Connection extends EventEmitter {
|
|||||||
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?.(this, data)
|
const res = cb.call(null, data)
|
||||||
this.sendMsg(name, {
|
this.sendMsg(name, {
|
||||||
success: true,
|
success: true,
|
||||||
res,
|
res,
|
||||||
@ -45,31 +50,34 @@ export class Connection extends EventEmitter {
|
|||||||
error: (error as Error)?.message,
|
error: (error as Error)?.message,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return
|
} else {
|
||||||
}
|
try {
|
||||||
|
if (this.msgMap.has(name)) {
|
||||||
if (this.msgMap.has(name)) {
|
this.msgMap.get(name)?.forEach(({ cb, ctx }) => cb.call(ctx, data))
|
||||||
this.msgMap.get(name)?.forEach(cb => cb(data))
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.log(`解析失败,${str}不是合法的JSON格式:`, error)
|
console.log(`解析失败,不是合法的JSON格式:`, error)
|
||||||
console.log(error)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void) {
|
listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
|
||||||
if (this.msgMap.has(name)) {
|
if (this.msgMap.has(name)) {
|
||||||
this.msgMap.get(name)?.push(cb)
|
this.msgMap.get(name)?.push({ cb, ctx })
|
||||||
} else {
|
} else {
|
||||||
this.msgMap.set(name, [cb])
|
this.msgMap.set(name, [{ cb, ctx }])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unlistenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void) {
|
unlistenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
|
||||||
if (this.msgMap.has(name)) {
|
if (this.msgMap.has(name)) {
|
||||||
const index = this.msgMap.get(name)?.indexOf(cb) || -1
|
const items = this.msgMap.get(name)
|
||||||
index > -1 && this.msgMap.get(name)?.splice(index, 1)
|
const index = items.findIndex(i => cb === i.cb && i.ctx === ctx);
|
||||||
|
index > -1 && items.splice(index, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +88,7 @@ export class Connection extends EventEmitter {
|
|||||||
})
|
})
|
||||||
const view = binaryEncode(name, data)
|
const view = binaryEncode(name, data)
|
||||||
const buffer = Buffer.from(view.buffer)
|
const buffer = Buffer.from(view.buffer)
|
||||||
console.log(`${getTime()}发送|字节数${buffer.length}|${this.playerId || -1}|${msg}`)
|
console.log(`${getTime()}发送|字节数${buffer.length}|${this.playerId || -1}|内存${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)}MB|${msg}`)
|
||||||
this.ws.send(buffer)
|
this.ws.send(buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ 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 { ApiMsgEnum, IApiGameStartReq, IApiGameStartRes, IApiPlayerJoinReq, IApiPlayerJoinRes, IApiPlayerListReq, IApiPlayerListRes, IApiRoomCreateReq, IApiRoomCreateRes, IApiRoomJoinReq, IApiRoomJoinRes, IApiRoomLeaveReq, IApiRoomLeaveRes, IApiRoomListReq, IApiRoomListRes, IModel } from './Common';
|
import { ApiMsgEnum, IApiGameEndReq, IApiGameEndRes, IApiGameStartReq, IApiGameStartRes, IApiPlayerJoinReq, IApiPlayerJoinRes, IApiPlayerListReq, IApiPlayerListRes, IApiRoomCreateReq, IApiRoomCreateRes, IApiRoomJoinReq, IApiRoomJoinRes, IApiRoomLeaveReq, IApiRoomLeaveRes, IApiRoomListReq, IApiRoomListRes, IModel } from './Common';
|
||||||
|
|
||||||
const server = new MyServer({ port: 8888 })
|
const server = new MyServer({ port: 8888 })
|
||||||
|
|
||||||
@ -31,7 +31,6 @@ server.setApi(ApiMsgEnum.ApiPlayerJoin, (connection: Connection, { nickname }: I
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
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() }
|
||||||
})
|
})
|
||||||
@ -114,6 +113,28 @@ server.setApi(ApiMsgEnum.ApiGameStart, (connection: Connection, data: IApiGameSt
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
server.setApi(ApiMsgEnum.ApiGameEnd, (connection: Connection, data: IApiGameEndReq): IApiGameEndRes => {
|
||||||
|
if (connection.playerId) {
|
||||||
|
const player = PlayerManager.Instance.getPlayerById(connection.playerId)
|
||||||
|
if (player) {
|
||||||
|
const rid = player.rid
|
||||||
|
if (rid) {
|
||||||
|
RoomManager.Instance.closeRoom(rid)
|
||||||
|
PlayerManager.Instance.syncPlayers()
|
||||||
|
RoomManager.Instance.syncRooms()
|
||||||
|
return {}
|
||||||
|
} else {
|
||||||
|
throw new Error("ApiGameEnd 玩家不在房间")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error("ApiGameEnd 玩家不存在")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error("ApiGameEnd 玩家未登录")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
// start!!
|
// start!!
|
||||||
server.start().then(() => {
|
server.start().then(() => {
|
||||||
symlinkCommon()
|
symlinkCommon()
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||||
/* Type Checking */
|
/* Type Checking */
|
||||||
"strict": true, /* Enable all strict type-checking options. */
|
// "strict": true, /* Enable all strict type-checking options. */
|
||||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||||
|
@ -5,5 +5,10 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"apps/*"
|
"apps/*"
|
||||||
]
|
],
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"lint:fix": "eslint . --fix",
|
||||||
|
"dev": "yarn workspace @game/server run dev"
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user