"use strict"; const firstCardCount = 5; class HostController { playerController = null; deck = new Array(); discards = new Array(); players = new Map(); turnOrder; turn = -1; latestWaitingId = 0; waitings = new Map(); constructor() { this.playerController = new PlayerController(); EXOUtils.init(); } async gameStart() { // ターンを決定 this.turnOrder = EXOUtils.shuffleArray([...this.players.keys()]); // ゲームを開始 let startMessage = new MessageBuilder().game(); startMessage.addCommand(commands.gameStart, null, ...this.turnOrder).send(); // すべてのカードを生成 Object.keys(cardTypes).forEach(key => { for (let i = 0; i < cardTypes[key].count; ++i) this.deck.push(new Card(cardTypes[key], i + 1)); }); // 山札をシャッフル EXOUtils.shuffleArray(this.deck); console.log([...this.deck]); await this.distributionCards(); this.nextTurn(); } async distributionCards() { for (let i = 0; i < firstCardCount; ++i) { for (const playerId of this.turnOrder) { await this.players.get(playerId).addCard(this.deck.splice(0, 1)[0]); await new Promise(resolve => setTimeout(resolve, 700)); } } } async nextTurn() { // ターンを進める ++this.turn; if (this.turnOrder.length <= this.turn) this.turn = 0; const turnPlayer = this.players.get(this.turnOrder[this.turn]); // カードを一枚引く await turnPlayer.addCard(this.deck.splice(0, 1)[0]); await new Promise(resolve => setTimeout(resolve, 700)); // 操作待ち this.cardCommands.selectCards((selectedBy, targetStockId, ...cardsIndex)=>{ const stock = this.cardCommands.getStock(targetStockId); stock[cardsIndex[0]].cardType.onGet; }, turnPlayer.clientId, turnPlayer.clientId, 1); //if (!this.waiting.has(turnPlayer.clientId)) this.waiting.set(turnPlayer.clientId, []); //this.waiting.get(turnPlayer.clientId).push(commands.useCard); } onGameMessage(message) { if (message.body.side === side.player || message.body.side === side.both) this.playerController.onGameMessage(message); if (message.body.side === side.host || message.body.side === side.both) message.body.commands.forEach(command => { switch (command.name) { case commands.waiting: if (!this.waitings.has(command.args[0])) return; const waiting = this.waitings.get(command.args[0]); if (message.from !== waiting.args[0]) return; waiting.onOperation(...waiting.args, ...command.args); break; } }); /* if (message.body.side !== side.host && message.body.side !== side.both) return; message.body.commands.forEach(command => { if (!this.waiting.get(message.from)?.includes(command.name)) return; switch (command.name) { case commands.useCard: break; } });*/ } joinNewPlayer(obj) { this.players.set(obj.from, new Player(obj.from)); let messageBuilder = new MessageBuilder().game(); messageBuilder.addCommand(commands.syncRoomData, null, clientId, [...this.players.keys()]); messageBuilder.send(); } cardCommands = { remove: (targetId, card, index, canRecycle) => { const player = this.players.get(targetId); index = player.cards.findIndex(it => it.id == card.id && it.cardType.id == card.cardType.id); card = player.cards[index]; if (canRecycle) this.discards.push(...player.cards.splice(index, 1)); else this.cardCommands.backIntoDeck(card); new MessageBuilder().game().addCommand(commands.worker, targetId, "remove", [targetId, { cardType: { id: card.cardType.id }, idIndex: card.idIndex }, index, canRecycle]).send(); }, backIntoDeck: (card) => { this.deck.splice(Math.floor(Math.random() * (this.deck.length + 1)), 0, card); }, selectCards: (callback, targetId, targetStockId, count) => { const waitingId = ++this.latestWaitingId; this.waitings.set(waitingId, { onOperation: this.clientOperations.useCards, targetId: targetId, args: [callback, targetId, targetStockId, count] }); new MessageBuilder(targetId).game().addCommand(commands.worker, targetId, "selectCards", [targetId, targetStockId, count, waitingId]).send(); }, getStock: (stockId) => { if (stockId === "DISCARDS") return this.discards; return this.players?.get(stockId).cards; }, }; clientOperations = { useCards: (callback, selectedBy, targetStockId, count, waitingId, ...cardsIndex) => { if (cardsIndex.length != Number(count)) { console.log("count missmatch"); return; } callback(selectedBy, targetStockId, ...cardsIndex); } }; } class EXOUtils { static worker; static init() { this.worker = new Worker("static/js/card-module.js"); this.worker.onmessage = this.#onMessage; } static shuffleArray(array) { let currentIndex = array.length; while (currentIndex) { let j = Math.floor(Math.random() * currentIndex); let t = array[--currentIndex]; array[currentIndex] = array[j]; array[j] = t; } return array; } static capsuleExecute(funText, target) { this.worker.postMessage({ type: "run", function: funText, target: target, players: controller.players }); } // Worker Commands static #onMessage(e) { switch (e.data.type) { case "game": switch (e.data.game.command) { case "discard": controller.cardCommands.remove(e.data.game.target.clientId, e.data.game.card, null, true); break; case "selectCards": controller.cardCommands.selectCards(e.data.game.target.clientId, e.data.game.card, null, true); break; } break; } } }