edit(wip)
This commit is contained in:
parent
8136e91a0f
commit
55a828c9d2
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
@ -16,13 +16,11 @@
|
||||
"console": "externalTerminal"
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
"type": "firefox",
|
||||
"request": "launch",
|
||||
"name": "Launch ExtinctionOnlineClient",
|
||||
"runtimeExecutable": "/usr/bin/brave",
|
||||
"url": "http://localhost:5500",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"sourceMaps": true
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 noyciy7037
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,25 +1,50 @@
|
||||
"use strict";
|
||||
const AsyncFunction = async function () {}.constructor;
|
||||
const AsyncFunction = async function () { }.constructor;
|
||||
class Operation {
|
||||
static #operations = new Map();
|
||||
static #id = 0;
|
||||
static get nextId() {
|
||||
return ++Operation.#id;
|
||||
}
|
||||
static addOperation(id, callback) {
|
||||
Operation.#operations.set(id, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function discard(target, card) {
|
||||
console.log("DIS!CAR!D!");
|
||||
postMessage({ type: "game", game: { command: "discard", target: target, card: card } });
|
||||
}
|
||||
|
||||
function selectUser() {
|
||||
/*
|
||||
function selectUser(from, callback) {
|
||||
const opeId = Operation.nextId;
|
||||
postMessage({ type: "game", game: { command: "selectUser", from: from, id: opeId } });
|
||||
Operation.addOperation(opeId, callback);
|
||||
}*/
|
||||
|
||||
function selectCards(count, target, targetStockId, callback) {/*todo*/
|
||||
const opeId = Operation.nextId;
|
||||
postMessage({ type: "game", game: { command: "selectCards", target: target, count: count, targetStockId: targetStockId, id: opeId } });
|
||||
Operation.addOperation(opeId, callback);
|
||||
}
|
||||
|
||||
function selectCard(count, target) {
|
||||
|
||||
function getCard(target, cardId) {
|
||||
return target.cards.find(it => it.cardType.id == cardId);
|
||||
}
|
||||
|
||||
onmessage = e => {
|
||||
async function wait(time) {
|
||||
await new Promise(resolve => {
|
||||
setTimeout(resolve, time);
|
||||
});
|
||||
}
|
||||
|
||||
onmessage = async e => {
|
||||
console.log(e);
|
||||
switch (e.data.type) {
|
||||
case "run":
|
||||
let fun = new AsyncFunction("target", "players", e.data.function);
|
||||
fun(e.data.target, e.data.players);
|
||||
await fun(e.data.target, e.data.players);
|
||||
break;
|
||||
}
|
||||
}
|
@ -43,7 +43,8 @@ const cardTypes = {
|
||||
rob: {
|
||||
id: "rob",
|
||||
prefix: "J",
|
||||
count: 4
|
||||
count: 4,
|
||||
onUse: ""
|
||||
},
|
||||
robKill: {
|
||||
id: "robKill",
|
||||
@ -79,13 +80,13 @@ const cardTypes = {
|
||||
id: "extinction",
|
||||
prefix: "H",
|
||||
count: 4,
|
||||
onGet: "target.cards.forEach(it => {discard(target,it);});"
|
||||
onGet: "await wait(700);const lose = getCard(target,\"lose\");if(lose)discard(target,lose);else target.cards.forEach(it => {discard(target,it);});await wait(700);"
|
||||
},
|
||||
annihilation: {
|
||||
id: "annihilation",
|
||||
prefix: "I",
|
||||
count: 1,
|
||||
onGet: "players.forEach(player => {if(player.cards.length <= 5)player.cards.forEach(card => {discard(player,card);})});"
|
||||
onGet: "await wait(700);players.forEach(player => {if(player.cards.length <= 5)player.cards.forEach(card => {discard(player,card);})});await wait(700);"
|
||||
},
|
||||
drop: {
|
||||
id: "drop",
|
||||
@ -110,6 +111,7 @@ const cardTypes = {
|
||||
lose: {
|
||||
id: "lose",
|
||||
prefix: "T",
|
||||
count: 1
|
||||
count: 1,
|
||||
onGet: "console.log(\"LOSE!!!\");"
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ const commands = {
|
||||
gameStart: "GameStart", // args: PlayerID(ターン順)...
|
||||
addCard: "AddCard", // target: 追加するPlayerID; args: 追加するカードのID, カードのIndex
|
||||
worker: "Worker", //
|
||||
waiting: "Waiting",//
|
||||
};
|
||||
|
||||
const side = {
|
||||
@ -42,7 +43,6 @@ function joinToRoom(id, name) {
|
||||
}
|
||||
};
|
||||
socket.send(JSON.stringify(obj));
|
||||
EXOUtils.init();
|
||||
}
|
||||
|
||||
class Card {
|
||||
@ -65,14 +65,13 @@ class Player {
|
||||
this.clientId = id;
|
||||
}
|
||||
|
||||
// Side: Host
|
||||
async addCard(card) {
|
||||
this.cards.push(card);
|
||||
new MessageBuilder(this.clientId).game().addCommand(commands.addCard, this.clientId, card.cardType.id, card.idIndex).send();
|
||||
new MessageBuilder().game().addCommand(commands.addCard, this.clientId, cardTypes.unknown.id, -1).send();
|
||||
if (card.cardType.onGet) {
|
||||
await new Promise(resolve => setTimeout(resolve, 700));
|
||||
EXOUtils.capsuleExecute(card.cardType.onGet, this);
|
||||
await new Promise(resolve => setTimeout(resolve, 700));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,47 +110,6 @@ class MessageBuilder {
|
||||
|
||||
send() {
|
||||
socket.send(JSON.stringify(this.object));
|
||||
}
|
||||
}
|
||||
|
||||
class EXOUtils {
|
||||
static worker;
|
||||
|
||||
static init() {
|
||||
if (controller instanceof HostController) {
|
||||
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, players) {
|
||||
this.worker.postMessage({ type: "run", function: funText, target: target, players: 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 "selectCard":
|
||||
controller.cardCommands.selectCard(e.data.game.target.clientId, e.data.game.card, null, true);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.object = null;
|
||||
}
|
||||
}
|
@ -4,15 +4,16 @@ const firstCardCount = 5;
|
||||
class HostController {
|
||||
playerController = null;
|
||||
deck = new Array();
|
||||
discarded = new Array();
|
||||
discards = new Array();
|
||||
players = new Map();
|
||||
turnOrder;
|
||||
turn = -1;
|
||||
latestWaitingId = 0;
|
||||
waiting = new Map();
|
||||
waitings = new Map();
|
||||
|
||||
constructor() {
|
||||
this.playerController = new PlayerController();
|
||||
EXOUtils.init();
|
||||
}
|
||||
|
||||
async gameStart() {
|
||||
@ -32,54 +33,64 @@ class HostController {
|
||||
// 山札をシャッフル
|
||||
EXOUtils.shuffleArray(this.deck);
|
||||
|
||||
console.log([...this.deck]);
|
||||
|
||||
await this.distributionCards();
|
||||
this.nextTurn();
|
||||
}
|
||||
|
||||
async distributionCards() {
|
||||
for (let i = 0; i < firstCardCount; ++i) {
|
||||
for (const player of this.players) {
|
||||
await player[1].addCard(this.deck[0]);
|
||||
this.deck.splice(0, 1);
|
||||
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));
|
||||
}
|
||||
}
|
||||
/*
|
||||
// プレイヤーに5枚ずつ配布
|
||||
for (const player of this.players) {
|
||||
// 本人通達用
|
||||
let messageBuilder = new MessageBuilder(player[0]).game();
|
||||
// 他人通達用
|
||||
let messageBuilderForRoom = new MessageBuilder().game();
|
||||
for (let j = 0; j < firstCardCount; ++j) {
|
||||
player[1].cards.push(this.deck[0]);
|
||||
messageBuilder.addCommand(commands.addCard, player[0], this.deck[0].cardType.id, this.deck[0].idIndex);
|
||||
messageBuilderForRoom.addCommand(commands.addCard, player[0], cardTypes.unknown.id, -1)
|
||||
this.deck.splice(0, 1);
|
||||
|
||||
}
|
||||
messageBuilder.send();
|
||||
messageBuilderForRoom.send();
|
||||
}*/
|
||||
}
|
||||
|
||||
async nextTurn() {
|
||||
// ターンを進める
|
||||
++this.turn;
|
||||
if (this.turnOrder.length >= this.turn) this.turn = 0;
|
||||
if (this.turnOrder.length <= this.turn) this.turn = 0;
|
||||
|
||||
const turnPlayer = players[this.turnOrder[this.turn]];
|
||||
const turnPlayer = this.players.get(this.turnOrder[this.turn]);
|
||||
// カードを一枚引く
|
||||
await turnPlayer.addCard(this.deck[0]);
|
||||
this.deck.splice(0, 1);
|
||||
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.host)
|
||||
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) {
|
||||
@ -89,29 +100,75 @@ class HostController {
|
||||
messageBuilder.send();
|
||||
}
|
||||
|
||||
clientOperations = {
|
||||
selectedCards: () => { }
|
||||
}
|
||||
|
||||
cardCommands = {
|
||||
remove: (target, card, index, canRecycle) => {
|
||||
const player = controller.players.get(target);
|
||||
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.discarded.push(...player.cards.splice(index, 1));
|
||||
this.discards.push(...player.cards.splice(index, 1));
|
||||
else
|
||||
this.cardCommands.backIntoDeck(card);
|
||||
new MessageBuilder().game().addCommand(commands.worker, target, "remove", [target, { cardType: { id: card.cardType.id }, idIndex: card.idIndex }, index, canRecycle]).send();
|
||||
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);
|
||||
},
|
||||
selectCard: (target, count, waitingId) => {
|
||||
const player = controller.players.get(target);
|
||||
waitingId = ++this.latestWaitingId;
|
||||
this.waiting.set(waitingId, this.clientOperations.selectedCards);
|
||||
new MessageBuilder(target).game().addCommand(commands.worker, target, "selectCard", [target, count, waitingId]).send();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -38,11 +38,18 @@ class PlayerController {
|
||||
joinNewPlayer() { }
|
||||
|
||||
cardCommands = {
|
||||
remove: (target, card, index, canRecycle) => {
|
||||
const player = this.players.get(target);
|
||||
remove: (targetId, card, index, canRecycle) => {
|
||||
const player = this.players.get(targetId);
|
||||
player.cards.splice(index, 1);
|
||||
if (canRecycle)
|
||||
this.discarded.push(new Card(cardTypes[card.cardType.id], card.idIndex));
|
||||
},
|
||||
selectCards: (targetId, targetStockId, count, waitingId) => {
|
||||
/* TODO */
|
||||
console.log(`selectCards,from: ${targetStockId}, count: ${count}, waitingId: ${waitingId}`);
|
||||
},
|
||||
selectedCards: (waitingId, targetStockId, ...cardsIndex) => {
|
||||
new MessageBuilder(this.hostClientId, side.host).game().addCommand(commands.waiting, clientId, "selectedCards", [waitingId, ...cardsIndex]).send();
|
||||
},
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user