2022-11-13 21:30:01 +09:00
|
|
|
"use strict";
|
2022-11-04 22:05:08 +09:00
|
|
|
const firstCardCount = 5;
|
|
|
|
|
|
|
|
class HostController {
|
|
|
|
playerController = null;
|
|
|
|
deck = new Array();
|
2025-08-31 18:28:13 +09:00
|
|
|
discards = new Array();
|
2022-11-13 21:30:01 +09:00
|
|
|
players = new Map();
|
2023-04-23 12:40:54 +09:00
|
|
|
turnOrder;
|
|
|
|
turn = -1;
|
2023-06-10 00:06:54 +09:00
|
|
|
latestWaitingId = 0;
|
2025-08-31 18:28:13 +09:00
|
|
|
waitings = new Map();
|
2022-11-04 22:05:08 +09:00
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.playerController = new PlayerController();
|
2025-08-31 18:28:13 +09:00
|
|
|
EXOUtils.init();
|
2022-11-04 22:05:08 +09:00
|
|
|
}
|
|
|
|
|
2023-06-10 00:06:54 +09:00
|
|
|
async gameStart() {
|
2023-04-23 12:40:54 +09:00
|
|
|
// ターンを決定
|
|
|
|
this.turnOrder = EXOUtils.shuffleArray([...this.players.keys()]);
|
|
|
|
|
|
|
|
// ゲームを開始
|
2022-11-13 21:30:01 +09:00
|
|
|
let startMessage = new MessageBuilder().game();
|
2023-04-23 12:40:54 +09:00
|
|
|
startMessage.addCommand(commands.gameStart, null, ...this.turnOrder).send();
|
2022-11-13 21:30:01 +09:00
|
|
|
|
|
|
|
// すべてのカードを生成
|
2022-11-04 22:05:08 +09:00
|
|
|
Object.keys(cardTypes).forEach(key => {
|
|
|
|
for (let i = 0; i < cardTypes[key].count; ++i)
|
|
|
|
this.deck.push(new Card(cardTypes[key], i + 1));
|
|
|
|
});
|
2022-11-13 21:30:01 +09:00
|
|
|
|
2022-11-04 22:05:08 +09:00
|
|
|
// 山札をシャッフル
|
2023-04-23 12:40:54 +09:00
|
|
|
EXOUtils.shuffleArray(this.deck);
|
2022-11-13 21:30:01 +09:00
|
|
|
|
2025-08-31 18:28:13 +09:00
|
|
|
console.log([...this.deck]);
|
|
|
|
|
2023-06-10 00:06:54 +09:00
|
|
|
await this.distributionCards();
|
|
|
|
this.nextTurn();
|
2023-04-23 12:40:54 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
async distributionCards() {
|
|
|
|
for (let i = 0; i < firstCardCount; ++i) {
|
2025-08-31 18:28:13 +09:00
|
|
|
for (const playerId of this.turnOrder) {
|
|
|
|
await this.players.get(playerId).addCard(this.deck.splice(0, 1)[0]);
|
2023-04-23 12:40:54 +09:00
|
|
|
await new Promise(resolve => setTimeout(resolve, 700));
|
|
|
|
}
|
|
|
|
}
|
2022-11-04 22:05:08 +09:00
|
|
|
}
|
|
|
|
|
2023-06-10 00:06:54 +09:00
|
|
|
async nextTurn() {
|
|
|
|
// ターンを進める
|
|
|
|
++this.turn;
|
2025-08-31 18:28:13 +09:00
|
|
|
if (this.turnOrder.length <= this.turn) this.turn = 0;
|
2023-06-10 00:06:54 +09:00
|
|
|
|
2025-08-31 18:28:13 +09:00
|
|
|
const turnPlayer = this.players.get(this.turnOrder[this.turn]);
|
2023-06-10 00:06:54 +09:00
|
|
|
// カードを一枚引く
|
2025-08-31 18:28:13 +09:00
|
|
|
await turnPlayer.addCard(this.deck.splice(0, 1)[0]);
|
2023-06-10 00:06:54 +09:00
|
|
|
await new Promise(resolve => setTimeout(resolve, 700));
|
|
|
|
|
|
|
|
// 操作待ち
|
2025-08-31 18:28:13 +09:00
|
|
|
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);
|
2023-06-10 00:06:54 +09:00
|
|
|
}
|
|
|
|
|
2022-11-04 22:05:08 +09:00
|
|
|
onGameMessage(message) {
|
2025-08-31 18:28:13 +09:00
|
|
|
if (message.body.side === side.player || message.body.side === side.both)
|
2023-04-23 12:40:54 +09:00
|
|
|
this.playerController.onGameMessage(message);
|
2025-08-31 18:28:13 +09:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
});*/
|
2022-11-04 22:05:08 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
joinNewPlayer(obj) {
|
2022-11-13 21:30:01 +09:00
|
|
|
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();
|
2022-11-04 22:05:08 +09:00
|
|
|
}
|
2023-04-23 12:40:54 +09:00
|
|
|
|
|
|
|
cardCommands = {
|
2025-08-31 18:28:13 +09:00
|
|
|
remove: (targetId, card, index, canRecycle) => {
|
|
|
|
const player = this.players.get(targetId);
|
2023-06-10 00:06:54 +09:00
|
|
|
index = player.cards.findIndex(it => it.id == card.id && it.cardType.id == card.cardType.id);
|
2023-04-23 12:40:54 +09:00
|
|
|
card = player.cards[index];
|
|
|
|
if (canRecycle)
|
2025-08-31 18:28:13 +09:00
|
|
|
this.discards.push(...player.cards.splice(index, 1));
|
2023-04-23 12:40:54 +09:00
|
|
|
else
|
|
|
|
this.cardCommands.backIntoDeck(card);
|
2025-08-31 18:28:13 +09:00
|
|
|
new MessageBuilder().game().addCommand(commands.worker, targetId, "remove", [targetId, { cardType: { id: card.cardType.id }, idIndex: card.idIndex }, index, canRecycle]).send();
|
2023-04-23 12:40:54 +09:00
|
|
|
},
|
|
|
|
backIntoDeck: (card) => {
|
|
|
|
this.deck.splice(Math.floor(Math.random() * (this.deck.length + 1)), 0, card);
|
|
|
|
},
|
2025-08-31 18:28:13 +09:00
|
|
|
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();
|
2023-06-10 00:06:54 +09:00
|
|
|
},
|
2025-08-31 18:28:13 +09:00
|
|
|
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);
|
|
|
|
}
|
2023-04-23 12:40:54 +09:00
|
|
|
};
|
2025-08-31 18:28:13 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2022-11-04 22:05:08 +09:00
|
|
|
}
|