card_svr/src/robot/Robot.ts

233 lines
6.8 KiB
TypeScript

import {Client, Room} from "colyseus.js";
import {error, robotLog as log, robotLog as debug} from "../common/Debug";
import {GameStateConst} from "../constants/GameStateConst";
import {Player} from "../rooms/schema/Player";
import assistantUtil from "../utils/assistant.util";
import {delay, wait} from "../decorators/cfg";
export class Robot {
host: string;
roomId: string;
room: Room;
sessionId: string;
client: Client;
myTurn: boolean = false;
player: Player;
constructor(host: string, roomId: string) {
this.host = host;
this.roomId = roomId;
this.client = new Client(host);
}
async connect() {
try {
this.room = await this.client.joinById(this.roomId);
this.addListeners();
this.sessionId = this.room.sessionId;
this.setReady();
return this.room.sessionId;
} catch (err) {
error(`error join room ${this.host}, ${this.roomId}`)
}
}
async reConnect(sessionId: string) {
try {
this.room = await this.client.reconnect(this.roomId, sessionId);
this.addListeners();
this.sessionId = this.room.sessionId;
return this.room.sessionId;
} catch (err) {
error(`error reConnect room ${this.host}, ${this.roomId}, sessionId: ${sessionId}`);
}
}
addListeners() {
let self = this;
this.room.onMessage("*", (type, data) => {
debug("[ROBOT] received message:", type, "=>", data);
switch (type) {
case 'draw_card_s2c':
// if (data.player == self.sessionId) {
// self.cards = self.cards.concat(data.cards);
// }
break;
case 'player_ready_s2c':
break;
case 'eat_card_s2c':
if (data.errcode == 0 && data.player == self.sessionId) {
self.selectPet();
}
break;
}
});
this.room.onLeave(function () {
debug("[ROBOT] LEFT ROOM", arguments);
self.room.removeAllListeners();
self.room.leave();
});
/**
* 监听房间状态的变更, state含有当前房间游戏的所有公共信息, 任何值的更改都会触发该方法
* */
this.room.onStateChange(function (state) {
self.player = state.players.get(self.sessionId);
// self.players = state.players;
});
// 也可以监听state下某个特定值的变更, 比如下面是监听 当前轮的clientid
this.room.state.listen("currentTurn", (currentValue: string) => {
self.myTurn = currentValue === this.sessionId;
if (self.myTurn) {
self.discard();
}
});
this.room.state.listen("subTurn", (currentValue: string, previousValue: string) => {
// self.mySubTurn = currentValue === self.sessionId;
// if (self.mySubTurn) {
// setTimeout(self.giveup.bind(self), self.delay);
// }
});
// 监听游戏状态的改变
this.room.state.listen("gameState", (currentValue: number, previousValue: number) => {
switch (currentValue) {
case GameStateConst.DETERMINE_TURN:
// console.log('比大小阶段');
//TODO: 随机分牌比大小阶段, 需要
break;
case GameStateConst.CHANGE_HERO:
// console.log('英雄选择阶段');
self.selectHero();
break;
case GameStateConst.STATE_CHANGE_CARD:
// console.log('开局换卡阶段');
self.changeCard();
break;
case GameStateConst.STATE_BEGIN_EAT:
if (!self.myTurn) {
self.eatOrGiveUp();
}
break;
case GameStateConst.STATE_ROUND_RESULT:
console.log('结算轮');
break;
}
});
}
private reply(messageType: string, message: any) {
this.room.send(messageType, message);
}
// >>>>>>>>>>>>>>>>>> begin
/**
* 开局选择英雄
* @private
*/
@wait('pickHeroTime')
private async selectHero() {
let data = assistantUtil.randomHero();
this.reply('select_hero_c2s', data);
}
/**
* 开局准备
* @private
*/
@delay(2)
private async setReady() {
this.reply('play_ready_c2s', '');
}
/**
* 开局换牌
* @private
*/
@wait('cardChangeTime')
private async changeCard() {
let cardIds: number[] = [];
this.reply('change_card_c2s', {
cards: cardIds
});
}
/**
* 出牌
* @private
*/
@wait('maxDiscardTime')
private async discard() {
let self = this;
let cardArr = [...self.player.cards.values()];
let cards = assistantUtil.checkTriple(cardArr);
if (!cards) {
return;
}
let cardIds = cards.map(o => o.id);
self.reply('discard_card_c2s', {
cards: cardIds
});
}
/**
* 吃牌或者放弃
* @private
*/
@wait('maxEatTime')
private async eatOrGiveUp() {
let targetCard = [...this.room.state.cards.values()][0];
let cardArr = [...this.player.cards.values()];
let tmpCards = assistantUtil.checkTriple(cardArr, targetCard);
let next = this.giveup.bind(this);
if (tmpCards.length > 1 && targetCard.type === 1) {
let cardIds: number[] = [];
for (let card of tmpCards) {
if (card.id !== targetCard.id) {
cardIds.push(card.id);
}
}
next = this.eatCard.bind(this, cardIds, targetCard.id);
}
next.apply(this);
}
/**
* 吃牌
* @param cardIds
* @param target
* @private
*/
private eatCard(cardIds: number[], target: number) {
log(`${this.sessionId} 吃牌 ${cardIds} -> ${target}`);
this.reply('eat_card_c2s', {
cards: cardIds,
target
});
}
/**
* 放弃吃牌
* @private
*/
private giveup() {
this.reply('give_up_eat_c2s', {});
}
/**
* 选择一个法术或者一个随从
* @private
*/
@wait('playerActTime')
private async selectPet() {
let data = await assistantUtil.selectPet(this.player, this.room.state);
if (data) {
this.reply('select_pet_c2s', data);
}
}
}