重构代码

This commit is contained in:
zhl 2021-03-01 14:24:48 +08:00
parent a0c57268d2
commit 7dd2c82a50
2 changed files with 191 additions and 160 deletions

0
src/cfg/RoomOptions.ts Normal file
View File

View File

@ -1,194 +1,223 @@
import {Client, Room} from "colyseus"; import { Client, Room } from 'colyseus'
import {CardGameState} from "./schema/CardGameState"; import { CardGameState } from './schema/CardGameState'
import {OnJoinCommand} from "./commands/OnJoinCommand"; import { OnJoinCommand } from './commands/OnJoinCommand'
import {PlayReadyCommand} from "./commands/PlayReadyCommand"; import { PlayReadyCommand } from './commands/PlayReadyCommand'
import {Dispatcher} from "@colyseus/command"; import { Dispatcher } from '@colyseus/command'
import {DiscardCommand} from "./commands/DiscardCommand"; import { DiscardCommand } from './commands/DiscardCommand'
import {SelectPetCommand} from "./commands/SelectPetCommand"; import { SelectPetCommand } from './commands/SelectPetCommand'
import {ChangeCardCommand} from "./commands/ChangeCardCommand"; import { ChangeCardCommand } from './commands/ChangeCardCommand'
import {SelectHeroCommand} from "./commands/SelectHeroCommand"; import { SelectHeroCommand } from './commands/SelectHeroCommand'
import {EatCardCommand} from "./commands/EatCardCommand"; import { EatCardCommand } from './commands/EatCardCommand'
import {GiveUpCommand} from "./commands/GiveUpCommand"; import { GiveUpCommand } from './commands/GiveUpCommand'
import {BattleHandler} from "./logic/Handler/BattleHandler"; import { BattleHandler } from './logic/Handler/BattleHandler'
import {debugRoom, error, msgLog} from "../common/Debug"; import { debugRoom, error, msgLog } from '../common/Debug'
import {Delayed} from "@gamestdio/timer/lib/Delayed"; import { Delayed } from '@gamestdio/timer/lib/Delayed'
import {IncomingMessage} from "http"; import { IncomingMessage } from 'http'
import {PlayerStateConst} from "../constants/PlayerStateConst"; import { Player } from './schema/Player'
import {Player} from "./schema/Player"; import { GMCommand } from './commands/GMCommand'
import {GMCommand} from "./commands/GMCommand"; import { GameStateConst } from '../constants/GameStateConst'
import {GameStateConst} from "../constants/GameStateConst"; import { GameRestartCommand } from './commands/GameRestartCommand'
import {GameRestartCommand} from "./commands/GameRestartCommand"; import { RobotClient } from '../robot/RobotClient'
import {RobotClient} from "../robot/RobotClient"; import { ChangePetCommand } from './commands/ChangePetCommand'
import {ChangePetCommand} from "./commands/ChangePetCommand"; import { createRobot } from '../common/WebApi'
import {createRobot} from "../common/WebApi";
import { Service } from '../service/Service' import { Service } from '../service/Service'
export class GeneralRoom extends Room { export class GeneralRoom extends Room {
dispatcher = new Dispatcher(this); dispatcher = new Dispatcher(this)
maxClients = 4; maxClients = 4
score = 0; score = 0
battleMan = new BattleHandler(); battleMan = new BattleHandler()
// 用于游戏过程中各种计时器, 使用该计时器的前提是, 只针对当前操作玩家 // 用于游戏过程中各种计时器, 使用该计时器的前提是, 只针对当前操作玩家
gameClock: Map<string, Delayed> = new Map(); gameClock: Map<string, Delayed> = new Map()
assistMap: Map<String, RobotClient> = new Map(); assistMap: Map<String, RobotClient> = new Map()
match = ''; match = ''
robotCount = 0; robotCount = 0
async onAuth (client:Client, options: any, request: IncomingMessage) { async onAuth(client: Client, options: any, request: IncomingMessage) {
debugRoom(options); debugRoom(options)
// TODO: 验证用户信息 // TODO: 验证用户信息
// client.auth.accountId = options.accountId; // client.auth.accountId = options.accountId;
// client.auth.sessionId = options.sessionId; // client.auth.sessionId = options.sessionId;
return true; return true
} }
onCreate (options: any) {
let cs = new CardGameState(); onCreate(options: any) {
let cs = new CardGameState()
if (options.clients) { if (options.clients) {
this.maxClients = options.clients this.maxClients = options.clients
} }
this.setState(cs); this.setState(cs)
if (options.mode) { if (options.mode) {
this.state.mode = +options.mode; this.state.mode = +options.mode
} }
this.setPrivate(true); this.setPrivate(true)
if (options.count) { if (options.count) {
this.robotCount = Math.min(Math.max(0, options.count), this.maxClients - 1); this.robotCount = Math.min(Math.max(0, options.count), this.maxClients - 1)
} }
this.match = options.match; this.match = options.match
if (options.score) { if (options.score) {
this.score = options.score; this.score = options.score
} }
this.battleMan.init(cs, this); this.battleMan.init(cs, this)
this.clock.start(); this.clock.start()
this.state.gameState = GameStateConst.STATE_WAIT_JOIN; this.state.gameState = GameStateConst.STATE_WAIT_JOIN
this.onMessage("play_ready_c2s", (client, message) => { this.onMessage('play_ready_c2s', (client, message) => {
msgLog('play_ready from ', client.sessionId, JSON.stringify(message)); msgLog('play_ready from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new PlayReadyCommand(), {client}); this.dispatcher.dispatch(new PlayReadyCommand(), { client })
}); })
this.onMessage("change_card_c2s", (client, message) => { this.onMessage('change_card_c2s', (client, message) => {
msgLog('change_card from ', client.sessionId, JSON.stringify(message)); msgLog('change_card from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new ChangeCardCommand(), {client, cards: message.cards}); this.dispatcher.dispatch(new ChangeCardCommand(), {
}); client,
this.onMessage("discard_card_c2s", (client, message) => { cards: message.cards
msgLog('discard_card from ', client.sessionId, JSON.stringify(message)); })
this.dispatcher.dispatch(new DiscardCommand(), {client, cards: message.cards, target: message.target, dtype: 0}); })
}); this.onMessage('discard_card_c2s', (client, message) => {
this.onMessage("eat_card_c2s", (client, message) => { msgLog('discard_card from ', client.sessionId, JSON.stringify(message))
msgLog('eat_card from ', client.sessionId, JSON.stringify(message)); this.dispatcher.dispatch(new DiscardCommand(), {
this.dispatcher.dispatch(new EatCardCommand(), {client, cards: message.cards, target: message.target}); client,
}); cards: message.cards,
target: message.target,
dtype: 0
})
})
this.onMessage('eat_card_c2s', (client, message) => {
msgLog('eat_card from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new EatCardCommand(), {
client,
cards: message.cards,
target: message.target
})
})
this.onMessage("give_up_eat_c2s", (client, message) => { this.onMessage('give_up_eat_c2s', (client, message) => {
msgLog('give_up_take from ', client.sessionId, JSON.stringify(message)); msgLog('give_up_take from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new GiveUpCommand(), {client}); this.dispatcher.dispatch(new GiveUpCommand(), { client })
}); })
this.onMessage("select_pet_c2s", (client, message) => { this.onMessage('select_pet_c2s', (client, message) => {
msgLog('select_pet from ', client.sessionId, JSON.stringify(message)); msgLog('select_pet from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new SelectPetCommand(), {client, cardId: message.card, playerId: message.player, pos: message.pos, effCards: message.effCards, oldpos: message.oldPos }); this.dispatcher.dispatch(new SelectPetCommand(), {
}); client,
cardId: message.card,
playerId: message.player,
pos: message.pos,
effCards: message.effCards,
oldpos: message.oldPos
})
})
this.onMessage("select_hero_c2s", (client, message) => { this.onMessage('select_hero_c2s', (client, message) => {
msgLog('select_hero from ', client.sessionId, JSON.stringify(message)); msgLog('select_hero from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new SelectHeroCommand(), {client, heroId: message.heroId, cardGroup: message.cardgroup}); this.dispatcher.dispatch(new SelectHeroCommand(), {
}); client,
heroId: message.heroId,
cardGroup: message.cardgroup
})
})
this.onMessage("gm", (client, message) => { this.onMessage('gm', (client, message) => {
msgLog('gm command from ', client.sessionId, JSON.stringify(message)); msgLog('gm command from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new GMCommand(), {client, message}); this.dispatcher.dispatch(new GMCommand(), { client, message })
}); })
this.onMessage("restart_c2s", (client, message) => { this.onMessage('restart_c2s', (client, message) => {
msgLog('restart game from ', client.sessionId, JSON.stringify(message)); msgLog('restart game from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new GameRestartCommand(), {client}); this.dispatcher.dispatch(new GameRestartCommand(), { client })
}); })
this.onMessage("change_pet_c2s", (client, message) => { this.onMessage('change_pet_c2s', (client, message) => {
msgLog('change pet from ', client.sessionId, JSON.stringify(message)); msgLog('change pet from ', client.sessionId, JSON.stringify(message))
this.dispatcher.dispatch(new ChangePetCommand(), {client, pos: message.pos, petId: message.petId}); this.dispatcher.dispatch(new ChangePetCommand(), {
}); client,
pos: message.pos,
petId: message.petId
})
})
/** /**
* broadcast_c2s的消息, 广 * broadcast_c2s的消息, 广
*/ */
this.onMessage("broadcast_c2s", (client, message) => { this.onMessage('broadcast_c2s', (client, message) => {
msgLog('broadcast_c2s from ', client.sessionId, JSON.stringify(message)); msgLog('broadcast_c2s from ', client.sessionId, JSON.stringify(message))
this.broadcast("broadcast_s2c", message, {except: client}); this.broadcast('broadcast_s2c', message, { except: client })
}); })
this.onMessage("*", (client, type, message) => { this.onMessage('*', (client, type, message) => {
// //
// Triggers when any other type of message is sent, // Triggers when any other type of message is sent,
// excluding "action", which has its own specific handler defined above. // excluding "action", which has its own specific handler defined above.
// //
msgLog(client.sessionId, "sent", type, JSON.stringify(message)); msgLog(client.sessionId, 'sent', type, JSON.stringify(message))
}); })
} }
onJoin (client: Client, options: any) {
onJoin(client: Client, options: any) {
let data = { let data = {
client: client, client: client,
accountId: options.accountid, accountId: options.accountid,
seat: options.seat, seat: options.seat,
score: options.score, score: options.score
}; }
this.dispatcher.dispatch(new OnJoinCommand(), data); this.dispatcher.dispatch(new OnJoinCommand(), data)
} }
//TODO: 掉线逻辑 //TODO: 掉线逻辑
async onLeave (client: Client, consented: boolean) { async onLeave(client: Client, consented: boolean) {
if (this.state.gameState === GameStateConst.STATE_GAME_OVER || this.state.gameState === GameStateConst.STATE_WAIT_JOIN) { if (this.state.gameState === GameStateConst.STATE_GAME_OVER || this.state.gameState === GameStateConst.STATE_WAIT_JOIN) {
this.state.players.delete(client.sessionId); this.state.players.delete(client.sessionId)
if (this.assistMap.has(client.sessionId)) { if (this.assistMap.has(client.sessionId)) {
this.assistMap.get(client.sessionId).leave(); this.assistMap.get(client.sessionId).leave()
this.assistMap.delete(client.sessionId); this.assistMap.delete(client.sessionId)
} }
this.bUserLeft(client.sessionId); this.bUserLeft(client.sessionId)
} else { } else {
this.state.players.get(client.sessionId).online = false; this.state.players.get(client.sessionId).online = false
let assistClient = this.getAssistClient(client.sessionId); let assistClient = this.getAssistClient(client.sessionId)
assistClient.active = true; assistClient.active = true
try { try {
if (consented) { if (consented) {
throw new Error("consented leave"); throw new Error('consented leave')
} else { } else {
await this.allowReconnection(client, 10 * 60); await this.allowReconnection(client, 10 * 60)
debugRoom(`${client.sessionId} 重连`); debugRoom(`${ client.sessionId } 重连`)
assistClient.active = false; assistClient.active = false
this.state.players.get(client.sessionId).online = true; this.state.players.get(client.sessionId).online = true
} }
} catch (e) { } catch (e) {
debugRoom(`player realy level :${client.sessionId}, try add robot`); debugRoom(`player realy level :${ client.sessionId }, try add robot`)
// this.state.players.delete(client.sessionId); // this.state.players.delete(client.sessionId);
} }
} }
} }
onDispose() { onDispose() {
this.gameClock.clear(); this.gameClock.clear()
this.assistMap.clear(); this.assistMap.clear()
this.dispatcher.stop(); this.dispatcher.stop()
} }
getClient(player: string | Player): Client { getClient(player: string | Player): Client {
let result: Client; let result: Client
let sessionId; let sessionId
if (typeof player == 'string') { if (typeof player == 'string') {
sessionId = player; sessionId = player
result = this.clients.find(client => client.sessionId == player ); result = this.clients.find(client => client.sessionId == player)
} else { } else {
sessionId = player.id; sessionId = player.id
result = this.clients.find(client => client.sessionId == player.id ); result = this.clients.find(client => client.sessionId == player.id)
} }
if (!result) { if (!result) {
debugRoom(`无法获取id为: ${typeof player == 'string' ? player : player.id} 的客户端`); debugRoom(`无法获取id为: ${ typeof player == 'string' ? player : player.id } 的客户端`)
result = this.getAssistClient(sessionId); result = this.getAssistClient(sessionId)
debugRoom(`启用辅助机器人, 当前机器人状态: ${(result as RobotClient).active}`) debugRoom(`启用辅助机器人, 当前机器人状态: ${ (result as RobotClient).active }`)
} }
return result; return result
} }
clientCount(): number { clientCount(): number {
return this.clients.length; return this.clients.length
} }
/** /**
@ -199,17 +228,17 @@ export class GeneralRoom extends Room {
* @param name * @param name
*/ */
beginSchedule(millisecond: number, handler: Function, name: string): void { beginSchedule(millisecond: number, handler: Function, name: string): void {
debugRoom(`begin schedule: `, name, millisecond / 1000); debugRoom(`begin schedule: `, name, millisecond / 1000)
if (this.gameClock.has(name) && this.gameClock.get(name)?.active) { if (this.gameClock.has(name) && this.gameClock.get(name)?.active) {
error(`当前已存在进行中的gameClock: ${name}`); error(`当前已存在进行中的gameClock: ${ name }`)
this.gameClock.get(name).clear(); this.gameClock.get(name).clear()
this.gameClock.delete(name); this.gameClock.delete(name)
} }
let self = this; let self = this
let timeOverFun = function () { let timeOverFun = function () {
handler && handler(); handler && handler()
} }
this.gameClock.set(name, this.clock.setTimeout(timeOverFun, millisecond , name)); this.gameClock.set(name, this.clock.setTimeout(timeOverFun, millisecond, name))
} }
/** /**
@ -217,19 +246,19 @@ export class GeneralRoom extends Room {
* gameClock任何时候只有一个可执行的任务 * gameClock任何时候只有一个可执行的任务
*/ */
stopSchedule(name: string): number { stopSchedule(name: string): number {
debugRoom(`manual stop schedule: ${name}`); debugRoom(`manual stop schedule: ${ name }`)
if (!this.gameClock.has(name)) { if (!this.gameClock.has(name)) {
return -1; return -1
} else { } else {
let clock = this.gameClock.get(name) let clock = this.gameClock.get(name)
if (!clock.active) { if (!clock.active) {
this.gameClock.delete(name); this.gameClock.delete(name)
return -1; return -1
} else { } else {
let time = clock.elapsedTime; let time = clock.elapsedTime
clock.clear(); clock.clear()
this.gameClock.delete(name); this.gameClock.delete(name)
return time; return time
} }
} }
@ -242,25 +271,25 @@ export class GeneralRoom extends Room {
* @param reason * @param reason
*/ */
addScheduleTime(millisecond: number, reason?: string, name?: string): void { addScheduleTime(millisecond: number, reason?: string, name?: string): void {
let current; let current
let currentName = name; let currentName = name
if (!name) { if (!name) {
for (let [id, clock] of this.gameClock) { for (let [id, clock] of this.gameClock) {
if (clock.active) { if (clock.active) {
current = clock; current = clock
currentName = id; currentName = id
break; break
} }
} }
} else { } else {
if (this.gameClock.has(name)) { if (this.gameClock.has(name)) {
current = this.gameClock.get(name); current = this.gameClock.get(name)
} }
} }
debugRoom(`add schedule for ${currentName}, time: ${millisecond/1000}, reason: ${reason}`); debugRoom(`add schedule for ${ currentName }, time: ${ millisecond / 1000 }, reason: ${ reason }`)
if (current) { if (current) {
current.time += millisecond ; current.time += millisecond
debugRoom(`schedule for ${name} remain: ${(current.time - current.elapsedTime)/1000}`); debugRoom(`schedule for ${ name } remain: ${ (current.time - current.elapsedTime) / 1000 }`)
} }
} }
@ -271,42 +300,44 @@ export class GeneralRoom extends Room {
room: this.roomId, room: this.roomId,
sessionId: playerId sessionId: playerId
} }
await createRobot(data); await createRobot(data)
} }
addAssistClient(sessionId: string) { addAssistClient(sessionId: string) {
if (!this.assistMap.has(sessionId)) { if (!this.assistMap.has(sessionId)) {
let client = new RobotClient(sessionId, this.state, this['onMessageHandlers']); let client = new RobotClient(sessionId, this.state, this['onMessageHandlers'])
this.assistMap.set(sessionId, client); this.assistMap.set(sessionId, client)
} }
} }
getAssistClient(sessionId: string): RobotClient { getAssistClient(sessionId: string): RobotClient {
return this.assistMap.get(sessionId); return this.assistMap.get(sessionId)
} }
getPlayerByIdx(idx: number) { getPlayerByIdx(idx: number) {
for (let [, player] of this.state.players) { for (let [, player] of this.state.players) {
if (player.idx == idx) { if (player.idx == idx) {
return player; return player
} }
} }
} }
/** /**
* *
* @param srcPlayer * @param srcPlayer
*/ */
getOppositePlayer(srcPlayer: string | Player): Player { getOppositePlayer(srcPlayer: string | Player): Player {
let playerId; let playerId
if (typeof srcPlayer === 'string') { if (typeof srcPlayer === 'string') {
playerId = srcPlayer as string; playerId = srcPlayer as string
} else { } else {
playerId = srcPlayer.id; playerId = srcPlayer.id
} }
if (!this.state.players.has(playerId)) { if (!this.state.players.has(playerId)) {
return null; return null
} }
let idx = this.state.players.get(playerId).idx; let idx = this.state.players.get(playerId).idx
let opposIdx = ((this.maxClients / 2 | 0) + idx) % this.maxClients; let opposIdx = ((this.maxClients / 2 | 0) + idx) % this.maxClients
return this.getPlayerByIdx(opposIdx); return this.getPlayerByIdx(opposIdx)
} }
} }