重构代码, 增加一些注释

This commit is contained in:
zhl 2021-02-22 17:53:48 +08:00
parent 3bdfeaec64
commit ff5cce11da
5 changed files with 450 additions and 423 deletions

View File

@ -1,84 +1,83 @@
import * as jetpack from "fs-jetpack"; import * as jetpack from 'fs-jetpack'
import {singleton} from "./Singleton"; import { GameEnv } from '../cfg/GameEnv'
import {GameEnv} from "../cfg/GameEnv"; import { BaseConst } from '../constants/BaseConst'
import {BaseConst} from "../constants/BaseConst"; import { error } from './Debug'
import {error} from "./Debug";
const $cfg = new Map(); const $cfg = new Map()
const jsonPath = 'config'; const jsonPath = 'config'
export var DataParser = (function (){ export var DataParser = (function () {
const parsers: { [index: string]: ConfigDataParser } = {}; const parsers: { [index: string]: ConfigDataParser } = {}
return { return {
regParser, regParser,
regCommonParser(key: string, CfgCreator: { new (): Cfg }, idkey = "id") { regCommonParser(key: string, CfgCreator: { new(): Cfg }, idkey = 'id') {
regParser(key, (data: any[]): any => { regParser(key, (data: any[]): any => {
if (!data) return; if (!data) return
let dict = new Map(); let dict = new Map()
for (let i = 0, len = data.length; i < len; i++) { for (let i = 0, len = data.length; i < len; i++) {
let obj = data[i]; let obj = data[i]
if (!obj[idkey]) { if (!obj[idkey]) {
error(`配置${key}的数据有误,唯一标识 ${idkey} 值为0或者没有${idkey}`); error(`配置${ key }的数据有误,唯一标识 ${ idkey } 值为0或者没有${ idkey }`)
continue; continue
} }
let to = new CfgCreator(); let to = new CfgCreator()
to.decode(obj); to.decode(obj)
if (dict.has(to.id)) { if (dict.has(to.id)) {
error(`配置${key}的数据有误,唯一标识 id 有重复值:${to.id}`) error(`配置${ key }的数据有误,唯一标识 id 有重复值:${ to.id }`)
process.abort(); process.abort()
} }
dict.set(to.id, to); dict.set(to.id, to)
} }
return dict; return dict
}); })
}, },
loadAll() { loadAll() {
let fileArr = jetpack.list(jsonPath); let fileArr = jetpack.list(jsonPath)
for (let f of fileArr) { for (let f of fileArr) {
let key = f.replace('_tbl.json', ''); let key = f.replace('_tbl.json', '')
let parser = parsers[key]; let parser = parsers[key]
let json = jetpack.read(`${jsonPath}/${f}`, 'json'); let json = jetpack.read(`${ jsonPath }/${ f }`, 'json')
if (parser && json){ if (parser && json) {
if (Array.isArray(json)) { if (Array.isArray(json)) {
let data = parser(json); let data = parser(json)
if (data) { // 支持一些void的情况 if (data) { // 支持一些void的情况
$cfg.set(key, data); $cfg.set(key, data)
}
} else {
$cfg.set(key, json);
}
}
} }
new GameEnv().init($cfg.get(BaseConst.COMPOUND)); } else {
Object.assign(global, { $cfg.set(key, json)
$cfg: $cfg }
}) }
}, }
new GameEnv().init($cfg.get(BaseConst.COMPOUND))
Object.assign(global, {
$cfg: $cfg
})
} }
/** }
*
* @param key /**
* @param parser *
*/ * @param key
function regParser(key: string, parser: ConfigDataParser) { * @param parser
parsers[key] = parser; */
} function regParser(key: string, parser: ConfigDataParser) {
})(); parsers[key] = parser
}
})()
/** /**
* *
*/ */
export interface ConfigDataParser { export interface ConfigDataParser {
(data: any): any; (data: any): any;
} }
export interface Cfg export interface Cfg {
{ /**
/** *
* * @param {*} data
* @param {*} data * @param {*} [local]
* @param {*} [local] */
*/ decode?: { (local?: any): void };
decode?: { (local?: any):void }; id?: number;
id?: number;
} }

515
src/global.d.ts vendored
View File

@ -1,299 +1,308 @@
import {IMsg} from "./message/IMsg"; import { IMsg } from './message/IMsg'
import {Client, Room} from "colyseus"; import { Client } from 'colyseus'
import {PetInfo, PetInfoMsg} from "./message/PetInfo"; import { PetInfo, PetInfoMsg } from './message/PetInfo'
import {BattleHandler} from "./rooms/logic/Handler/BattleHandler"; import { BattleHandler } from './rooms/logic/Handler/BattleHandler'
import {SkillInfoMsg} from "./message/SkillInfo"; import { SkillInfoMsg } from './message/SkillInfo'
import {PartResultMsg} from "./message/PartResult"; import { PartResultMsg } from './message/PartResult'
import {RemovePetMsg} from "./message/RemovePetMsg"; import { RemovePetMsg } from './message/RemovePetMsg'
import {Dispatcher} from "@colyseus/command"; import { Dispatcher } from '@colyseus/command'
import {Delayed} from "@gamestdio/timer/lib/Delayed"; import { Delayed } from '@gamestdio/timer/lib/Delayed'
import {Player} from "./rooms/schema/Player"; import { Player } from './rooms/schema/Player'
import {RobotClient} from "./robot/RobotClient"; import { RobotClient } from './robot/RobotClient'
export {}; export {}
declare global { declare global {
namespace NodeJS { namespace NodeJS {
interface Global { interface Global {
NODE_ENV: string NODE_ENV: string
ROOT_PATH: string ROOT_PATH: string
$cfg: any $cfg: any
isProd: boolean isProd: boolean
}
} }
}
} }
/** /**
* GeneralRoom * GeneralRoom
*/ */
declare module "colyseus" { declare module 'colyseus' {
interface Room { interface Room {
battleMan: BattleHandler; battleMan: BattleHandler;
dispatcher: Dispatcher; dispatcher: Dispatcher;
mainClock: Delayed; mainClock: Delayed;
robotCount: number; robotCount: number;
match: string | undefined ; match: string | undefined;
score: number; score: number;
/**
* sessionId获取client
* @param player id或者玩家的对象
*/
getClient(player: string | Player): Client;
/** /**
* room的client数量 * sessionId获取client
*/ * @param player id或者玩家的对象
clientCount(): number; */
// >>>>>>>>> Begin of extend send message <<<<<<<<<<<<< getClient(player: string | Player): Client;
/**
* 广
* @param data
* @param options
*/
bUserJoin(data?: any, options?: any): void;
/** /**
* 广 * room的client数量
* @param data */
*/ clientCount(): number;
bUserLeft(data?: any): void;
/** // >>>>>>>>> Begin of extend send message <<<<<<<<<<<<<
* /**
* @param client * 广
* @param data * @param data
*/ * @param options
sSelectHero(client: Client, data?: any):void; */
bUserJoin(data?: any, options?: any): void;
/** /**
* 广 * 广
* @param data * @param data
*/ */
bSelectHero(data?: any):void; bUserLeft(data?: any): void;
/** /**
* *
* @param client * @param client
* @param data * @param data
*/ */
sDrawCard(client: Client, data?: any):void; sSelectHero(client: Client, data?: any): void;
/**
* 广
* @param data
*/
bSelectHero(data?: any): void;
/**
*
* @param client
* @param data
*/
sDrawCard(client: Client, data?: any): void;
/** /**
* *
* @param data * @param data
*/ */
bAddPet(data?: PetInfoMsg): void; bAddPet(data?: PetInfoMsg): void;
/** /**
* *
* @param data * @param data
*/ */
bCastSkill(data?: SkillInfoMsg): void; bCastSkill(data?: SkillInfoMsg): void;
/** /**
* 广 * 广
* @param data * @param data
* @param options * @param options
*/ */
bStealCard(data?: any, options?: any):void; bStealCard(data?: any, options?: any): void;
/** /**
* *
* @param data * @param data
*/ */
sStealCard(data?: any):void; sStealCard(data?: any): void;
/** /**
* 广 * 广
* @param data * @param data
* @param options * @param options
*/ */
bDrawCard(data?: any, options?: any):void; bDrawCard(data?: any, options?: any): void;
/** /**
* 广 * 广
* @param data * @param data
* @param options * @param options
*/ */
bRemoveCard(data?: any, options?: any):void; bRemoveCard(data?: any, options?: any): void;
/** /**
* *
* @param data * @param data
* @param options * @param options
*/ */
bRemovePet(data?: RemovePetMsg, options?: any): void; bRemovePet(data?: RemovePetMsg, options?: any): void;
/**
* 广
* @param data
* @param options
*/
bPartResult(data?: PartResultMsg, options?: any): void;
/** /**
* 广 * 广
* @param data * @param data
* @param options * @param options
*/ */
bGameResult(data?: any, options?: any): void; bPartResult(data?: PartResultMsg, options?: any): void;
/** /**
* * 广
* @param client * @param data
* @param data * @param options
*/ */
sChangeCard(client: Client, data?: any):void; bGameResult(data?: any, options?: any): void;
/** /**
* *
* @param player * @param client
* @param data * @param data
*/ */
sNeedChangePet(player: string | Player, data?: any): void; sChangeCard(client: Client, data?: any): void;
/** /**
* *
* @param client * @param player
* @param data * @param data
*/ */
sMsgQueue(client: Client, data: IMsg[]): void; sNeedChangePet(player: string | Player, data?: any): void;
/**
*
* @param client
* @param data
*/
sMsgQueue(client: Client, data: IMsg[]): void;
/** /**
* 广 * 广
* : * :
* let datas:IMsg[] = []; * let datas:IMsg[] = [];
* datas.push({errcode: 0, type: '消息类型', data: {pid: 1}}); * datas.push({errcode: 0, type: '消息类型', data: {pid: 1}});
* this.room.bMsgQueue(datas); * this.room.bMsgQueue(datas);
* @param datas * @param datas
* @param options * @param options
*/ */
bMsgQueue(datas: IMsg[], options?: any): void; bMsgQueue(datas: IMsg[], options?: any): void;
send(client: Client, type: string, data?: any): void; send(client: Client, type: string, data?: any): void;
// >>>>>>>>> End of extend send message <<<<<<<<<<<<< // >>>>>>>>> End of extend send message <<<<<<<<<<<<<
// >>>>>>>>> Begin of extend functions <<<<<<<<<<<<< // >>>>>>>>> Begin of extend functions <<<<<<<<<<<<<
/** /**
* , 广 * , 广
* @param srcplayer * @param srcplayer
* @param dstplayer * @param dstplayer
* @param count * @param count
*/ */
drawCardFromPlayer(srcplayer: string, dstplayer: string, count: number) :number; drawCardFromPlayer(srcplayer: string, dstplayer: string, count: number): number;
/** /**
* , 广 * , 广
* @param dstplayer * @param dstplayer
* @param count * @param count
* @param fromplayer * @param fromplayer
*/ */
giveUpCard(dstplayer: string, count: number, fromplayer?: string): number; giveUpCard(dstplayer: string, count: number, fromplayer?: string): number;
/** /**
* , 广 * , 广
* @param dstplayer * @param dstplayer
* @param count , max_count至少一个不为0 * @param count , max_count至少一个不为0
* @param max_count , count和max_count都不为0, Math.min(count, (max_count - )) * @param max_count , count和max_count都不为0, Math.min(count, (max_count - ))
* @param source 0: 正常抽卡, 1: 技能, 2: gm命令抽的卡 * @param source 0: 正常抽卡, 1: 技能, 2: gm命令抽的卡
* @param fromplayer * @param fromplayer
* @param extData * @param extData
*/ */
addCard(dstplayer: string, count: number, max_count: number, source?: number, fromplayer?: string, extData?: {}): number; addCard(dstplayer: string, count: number, max_count: number, source?: number, fromplayer?: string, extData?: {}): number;
/** /**
* *
* @param dstplayer * @param dstplayer
* @param hp * @param hp
* @param reason * @param reason
* @param fromplayer * @param fromplayer
*/ */
updateHp(dstplayer: string, hp: number, reason?: string, fromplayer?: string): number; updateHp(dstplayer: string, hp: number, reason?: string, fromplayer?: string): number;
/** /**
* *
* @param datas * @param datas
* @param fromplayer * @param fromplayer
*/ */
updatePet(datas: PetInfo[], fromplayer?: string): void; updatePet(datas: PetInfo[], fromplayer?: string): void;
/**
* ,
* @param datas
* @param fromplayer
*/
updatePetStat(datas: PetInfo[], fromplayer?: string): void;
/** /**
* room.mainClock设定任务 * ,
* mainClock任何时候只有一个可执行的任务 * @param datas
* @param millisecond * @param fromplayer
* @param handler */
* @param name updatePetStat(datas: PetInfo[], fromplayer?: string): void;
*/
beginSchedule(millisecond: number, handler: Function, name: string): void;
/** /**
* room.mainClock的任务 * room.mainClock设定任务
* mainClock任何时候只有一个可执行的任务 * mainClock任何时候只有一个可执行的任务
* * @param millisecond
* @param name * @param handler
*/ * @param name
stopSchedule(name: string): number; */
/** beginSchedule(millisecond: number, handler: Function, name: string): void;
* room.mainClock增加n秒
* @param name
* @param millisecond
* @param reason
*/
addScheduleTime(millisecond: number, reason?: string, name?: string, ): void;
/** /**
* n张指定效果id的卡 * room.mainClock的任务
* @param effectId * mainClock任何时候只有一个可执行的任务
* @param count *
* @param player * @param name
* @param fromplayer */
*/ stopSchedule(name: string): number;
generateCard({player, count, effectId, fromplayer, options}
: {player: string | Player,
count: number,
effectId: number,
fromplayer?: string | Player,
options?: any}): number;
/**
*
* @param playerId
*/
addRobot(playerId?: string):void;
/** /**
* * room.mainClock增加n秒
* @param sessionId * @param name
*/ * @param millisecond
addAssistClient(sessionId: string): void; * @param reason
/** */
* session的辅助机器人 addScheduleTime(millisecond: number, reason?: string, name?: string): void;
* @param sessionId
*/
getAssistClient(sessionId: string): RobotClient;
/** /**
* * n张指定效果id的卡
* @param srcPlayer * @param effectId
*/ * @param count
getOppositePlayer(srcPlayer: string|Player): Player; * @param player
* @param fromplayer
*/
generateCard({ player, count, effectId, fromplayer, options }
: {
player: string | Player,
count: number,
effectId: number,
fromplayer?: string | Player,
options?: any
}): number;
/** /**
* index获取玩家 *
* @param {number} idx * @param playerId
* @return {Player} */
*/ addRobot(playerId?: string): void;
getPlayerByIdx(idx: number): Player;
} /**
*
* @param sessionId
*/
addAssistClient(sessionId: string): void;
/**
* session的辅助机器人
* @param sessionId
*/
getAssistClient(sessionId: string): RobotClient;
/**
*
* @param srcPlayer
*/
getOppositePlayer(srcPlayer: string | Player): Player;
/**
* index获取玩家
* @param {number} idx
* @return {Player}
*/
getPlayerByIdx(idx: number): Player;
}
} }

View File

@ -4,7 +4,6 @@ import cors from 'cors'
import { RedisPresence, Server } from 'colyseus' import { RedisPresence, Server } from 'colyseus'
import { monitor } from '@colyseus/monitor' import { monitor } from '@colyseus/monitor'
import rateLimit from 'express-rate-limit' import rateLimit from 'express-rate-limit'
// import socialRoutes from "@colyseus/social/express"
import { GeneralRoom } from './rooms/GeneralRoom' import { GeneralRoom } from './rooms/GeneralRoom'
import { initData } from './common/GConfig' import { initData } from './common/GConfig'
import { Config } from './cfg/Config' import { Config } from './cfg/Config'

View File

@ -2,7 +2,7 @@ import { Client, generateId, matchMaker, Room, ServerError } from 'colyseus'
import { BaseConst } from '../constants/BaseConst' import { BaseConst } from '../constants/BaseConst'
import { IncomingMessage } from 'http' import { IncomingMessage } from 'http'
import { checkMatchTicket } from '../common/WebApi' import { checkMatchTicket } from '../common/WebApi'
import { error, matchlog } from '../common/Debug' import { matchlog } from '../common/Debug'
import { retry } from 'colyseus/lib/Utils' import { retry } from 'colyseus/lib/Utils'
import { RoomListingData } from 'colyseus/lib/matchmaker/drivers/Driver' import { RoomListingData } from 'colyseus/lib/matchmaker/drivers/Driver'
@ -30,15 +30,12 @@ interface ClientStat {
export class RankedLobbyRoom extends Room { export class RankedLobbyRoom extends Room {
/** /**
* If `allowUnmatchedGroups` is true, players inside an unmatched group (that * true, maxWaitingTime,
* did not reached `numClientsToMatch`, and `maxWaitingTime` has been
* reached) will be matched together. Your room should fill the remaining
* spots with "bots" on this case.
*/ */
allowUnmatchedGroups: boolean = true allowUnmatchedGroups: boolean = true
/** /**
* Evaluate groups for each client at interval *
*/ */
evaluateGroupsInterval = 1000 evaluateGroupsInterval = 1000
@ -48,12 +45,12 @@ export class RankedLobbyRoom extends Room {
groups: MatchmakingGroup[] = [] groups: MatchmakingGroup[] = []
/** /**
* name of the room to create *
*/ */
roomToCreate = 'general_room' roomToCreate = 'general_room'
/** /**
* * , ,
*/ */
maxWaitingTime = 15 * 1000 maxWaitingTime = 15 * 1000
/** /**
@ -62,28 +59,34 @@ export class RankedLobbyRoom extends Room {
*/ */
groupAddOneTime = 10 * 1000 groupAddOneTime = 10 * 1000
/**
* after this time, try to fit this client with a not-so-compatible group
*/
maxWaitingTimeForPriority?: number = 10 * 1000
/** /**
* number of players on each match * number of players on each match
*/ */
numClientsToMatch = 4 numClientsToMatch = 4
// /**
// * after a group is ready, clients have this amount of milliseconds to confirm
// * connection to the created room
// */
// cancelConfirmationAfter = 5000;
/** /**
* rank and group cache per-player * rank and group cache per-player
*/ */
stats: ClientStat[] = [] stats: ClientStat[] = []
/**
*
* @type {number}
*/
rank_mpa = 0.2 rank_mpa = 0.2
/**
*
* @type {number}
*/
fair_ir = 1.2 fair_ir = 1.2
/**
*
* @type {number}
*/
step_ir = 1.3 step_ir = 1.3
/**
* id
* @type {string}
*/
matchid = '100001' matchid = '100001'
async onAuth(client: Client, options: any, request: IncomingMessage) { async onAuth(client: Client, options: any, request: IncomingMessage) {
@ -94,7 +97,7 @@ export class RankedLobbyRoom extends Room {
try { try {
await checkMatchTicket(accountid, this.matchid) await checkMatchTicket(accountid, this.matchid)
} catch (err) { } catch (err) {
let code = isNaN(err.message) ? 9: parseInt(err.message) let code = isNaN(err.message) ? 9 : parseInt(err.message)
throw new ServerError(code, 'not enough ticket') throw new ServerError(code, 'not enough ticket')
} }
return true return true
@ -410,7 +413,7 @@ export class RankedLobbyRoom extends Room {
Object.assign(options, matchData) Object.assign(options, matchData)
data.client.send('match_success', options) data.client.send('match_success', options)
const mdata = data.options const mdata = data.options
matchlog(`${mdata.accountid}:${mdata.score}:${mdata.rank}:${data.seat}:${client.waitingTime}`) matchlog(`${ mdata.accountid }:${ mdata.score }:${ mdata.rank }:${ data.seat }:${ client.waitingTime }`)
} }
})) }))

View File

@ -1,83 +1,100 @@
import {Command} from "@colyseus/command"; import { Command } from '@colyseus/command'
import {CardGameState} from "../schema/CardGameState"; import { CardGameState } from '../schema/CardGameState'
import {Client} from "colyseus"; import { Client } from 'colyseus'
import {TurnEndCommand} from "./TurnEndCommand"; import { TurnEndCommand } from './TurnEndCommand'
import {GameEnv} from "../../cfg/GameEnv"; import { GameEnv } from '../../cfg/GameEnv'
import gameUtil from "../../utils/game.util"; import gameUtil from '../../utils/game.util'
/** /**
* *
*/ */
export class SelectPetCommand extends Command<CardGameState, {client: Client, export class SelectPetCommand extends Command<CardGameState, {
cardId: number, client: Client,
playerId: string, cardId: number,
pos: number, playerId: string,
effCards: number[], pos: number,
oldpos: number effCards: number[],
}> { oldpos: number
async execute({client, cardId, playerId, pos, effCards, oldpos} = this.payload) { }> {
let sessionId = client.sessionId; async execute({
let player = this.state.players.get(sessionId); client,
let ap = 0; cardId,
let moreAp = 0; playerId,
let count = 0; pos,
let targetCard; effCards,
let effectRate = this.room.battleMan.getTransEffCardRate(player); oldpos
// 检查效果卡, 并从玩家手牌中移除 } = this.payload) {
let eff_cnt = 0; // 效果卡数量 let sessionId = client.sessionId
let dbpt_cnt = 0; // 点数翻倍卡数量 let player = this.state.players.get(sessionId)
let transCount = 0; let ap = 0
for (let eCardId of effCards) { let moreAp = 0
if (!player.cards.has(eCardId + '')) { let count = 0
continue; let targetCard
} let effectRate = this.room.battleMan.getTransEffCardRate(player)
let card = player.cards.get(eCardId + '').clone(); // 检查效果卡, 并从玩家手牌中移除
player.cardQueue.push(card); let eff_cnt = 0 // 效果卡数量
if (card.type === 3) { let dbpt_cnt = 0 // 点数翻倍卡数量
dbpt_cnt ++; let transCount = 0
} else if (card.type === 2){ for (let eCardId of effCards) {
eff_cnt ++; if (!player.cards.has(eCardId + '')) {
} else { continue
transCount ++; }
} let card = player.cards.get(eCardId + '').clone()
} player.cardQueue.push(card)
gameUtil.deleteCardFromPlayer(player, effCards); if (card.type === 3) {
if (effectRate && transCount) { dbpt_cnt++
eff_cnt += (transCount / effectRate | 0); } else if (card.type === 2) {
} eff_cnt++
for (let card of this.state.cards.values()) { } else {
ap += card.number; transCount++
count ++; }
if (count === 3) {
moreAp += new GameEnv().baseAddScore;
} else if (count > 3) {
moreAp += new GameEnv().extraAddScore;
}
if (card.id == cardId) {
targetCard = card;
}
}
if (!targetCard) {
return;
}
//停止选随从计时, 并更新player.extraTime;
let elapsedTime = this.room.stopSchedule('select_pet');
if (elapsedTime >= 0) {
let count = elapsedTime - new GameEnv().playerActTime * 1000;
let newCount = player.extraTime - Math.min(count, 0);
player.extraTime = Math.max(newCount, 0);
}
let dstplayer = this.state.players.get(playerId);
let dstpet;
if (dstplayer && pos != undefined) {
dstpet = dstplayer.pets.get(pos+'');
}
let cardpoint = moreAp + ap;
let data = {srcplayer: player, card: targetCard.effect, cardpoint, eff_cnt, dstplayer, dstpet, dbpt_cnt, oldpos}
let time = this.room.battleMan.useCard(data);
await this.delay(time);
return [new TurnEndCommand()];
} }
gameUtil.deleteCardFromPlayer(player, effCards)
if (effectRate && transCount) {
eff_cnt += (transCount / effectRate | 0)
}
for (let card of this.state.cards.values()) {
ap += card.number
count++
if (count === 3) {
moreAp += new GameEnv().baseAddScore
} else if (count > 3) {
moreAp += new GameEnv().extraAddScore
}
if (card.id == cardId) {
targetCard = card
}
}
if (!targetCard) {
return
}
//停止选随从计时, 并更新player.extraTime;
let elapsedTime = this.room.stopSchedule('select_pet')
if (elapsedTime >= 0) {
let count = elapsedTime - new GameEnv().playerActTime * 1000
let newCount = player.extraTime - Math.min(count, 0)
player.extraTime = Math.max(newCount, 0)
}
let dstplayer = this.state.players.get(playerId)
let dstpet
if (dstplayer && pos != undefined) {
dstpet = dstplayer.pets.get(pos + '')
}
let cardpoint = moreAp + ap
let data = {
srcplayer: player,
card: targetCard.effect,
cardpoint,
eff_cnt,
dstplayer,
dstpet,
dbpt_cnt,
oldpos
}
let time = this.room.battleMan.useCard(data)
await this.delay(time)
return [new TurnEndCommand()]
}
} }