card_svr/src/rooms/commands/EatConfirmCommand.ts
2020-12-08 18:47:02 +08:00

109 lines
4.2 KiB
TypeScript

import {Command} from "@colyseus/command";
import {CardGameState} from "../schema/CardGameState";
import {GameStateConst} from "../../constants/GameStateConst";
import {singleton} from "../../common/Singleton";
import {GameEnv} from "../../cfg/GameEnv";
import {debugRoom} from "../../common/Debug";
import {TurnEndCommand} from "./TurnEndCommand";
import {Player} from "../schema/Player";
import arrUtil from "../../utils/array.util";
import {Card} from "../schema/Card";
/**
* 根据条件决定吃牌玩家, 并执行吃牌逻辑
*/
export class EatConfirmCommand extends Command<CardGameState, { timeUp: boolean }> {
execute({timeUp} = this.payload) {
let giveUpCount = 0;
const playerCount = this.room.maxClients - 1;
const sessionIds = [...this.state.players.keys()];
// 将当前轮玩家移至第一位
let pids = arrUtil.moveElement(sessionIds, -sessionIds.indexOf(this.state.currentTurn));
let tmpActionMap = this.state.tmpActionMap;
for (let [, val] of tmpActionMap) {
if (typeof val == 'number') {
giveUpCount++;
}
}
if (giveUpCount >= playerCount) {
// 所有人都放弃了, 则取消定时, 直接进入下一轮
if (this.room.mainClock?.active) {
this.room.mainClock.clear();
}
return [new TurnEndCommand()];
}
let player:Player;
let cards: string[] = [];
let isFirst = true;
// 所有死亡玩家已在吃牌开始的时候至为放弃, 所以这里可以不用考虑死亡玩家
for (let i = 1; i < pids.length; i ++) {
// 获取第一个不放弃的玩家
let pid = pids[i];
if (tmpActionMap.has(pid)) {
if (typeof tmpActionMap.get(pid) != 'number') {
player = this.state.players.get(pid);
cards = tmpActionMap.get(pid) as string[];
break;
}
} else {
isFirst = false;
}
}
/**
* 3 种情况直接进入选择随从轮
* 1. 下家出牌
* 2. tmpActionMap中数据等于 playerCount
* 3. timeUp
* 否则继续等待
*/
// 吃牌逻辑
if (player != null && (isFirst || timeUp)) {
// 如果有吃牌计时的话,停止吃牌计时
if (this.room.mainClock?.active) {
this.room.mainClock.clear();
}
for (let id of cards) {
this.state.cards.set(id + '', player.cards.get(id + ''));
player.cards.delete(id + '');
player.cardSet.delete(id + '');
}
let cardArr: Card[] = [...this.state.cards.values()];
this.state.gameState = GameStateConst.STATE_PICK_PET;
let time = singleton(GameEnv).playerActTime * 1000 + player.extraTime;
let self = this;
// 开启选随从计时, 计时结束后结束当前轮
this.room.mainClock = this.clock.setTimeout(function () {
player.extraTime = 0;
self.room.mainClock.clear();
debugRoom('选随从或者法术时间到, 自动出牌, 自动进入下一轮');
self.room.dispatcher.dispatch(new TurnEndCommand());
}, time);
let fromPlayer = this.state.players.get(this.state.currentTurn);
if (fromPlayer.id !== player.id) {
this.room.battleMan.onCardLinkOver(player, cardArr, fromPlayer);
} else {
this.room.battleMan.onCardLinkOver(player, cardArr);
}
// 成功后广播吃牌成功消息
this.room.broadcast('eat_card_s2c', {player: player.id, errocode: 0, errmsg: ''});
// 向其他玩家发送吃卡失败的消息
for (let [key, val] of tmpActionMap) {
if (typeof val != 'number' && key !== player.id) {
let client = this.room.getClient(key);
client.send('eat_card_s2c', {errcode: 9, errmsg: '吃卡失败'});
}
}
} else if (!player && timeUp) {
return [new TurnEndCommand()];
}
}
}