From 704ad00af88145722116cf8d302e743eea654653 Mon Sep 17 00:00:00 2001 From: noyciy7037 Date: Sun, 23 Apr 2023 12:40:54 +0900 Subject: [PATCH] Add card distribution function/extinction cards --- .vscode/launch.json | 20 ++++++++-- .vscode/tasks.json | 41 +++++++++++++++++++++ static/js/card-module.js | 23 ++++++++++++ static/js/cards.js | 3 +- static/js/game-client.js | 67 +++++++++++++++++++++++++++++++++- static/js/host-controller.js | 51 +++++++++++++++++++++----- static/js/player-controller.js | 18 +++++++++ static/js/websocket.js | 22 +---------- 8 files changed, 207 insertions(+), 38 deletions(-) create mode 100644 .vscode/tasks.json create mode 100644 static/js/card-module.js diff --git a/.vscode/launch.json b/.vscode/launch.json index 0ba4612..7082f75 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,12 +5,24 @@ "version": "0.2.0", "configurations": [ { - "type": "pwa-chrome", + "name": ".NET Core Launch (console)", + "type": "coreclr", "request": "launch", - "name": "Launch Chrome against localhost", - "runtimeExecutable": "C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe", + "preLaunchTask": "build", + "program": "${workspaceFolder}/ExtinctionOnline.Server/bin/Debug/net6.0/ExtinctionOnline.Server.dll", + "args": [], + "cwd": "${workspaceFolder}", + "stopAtEntry": false, + "console": "externalTerminal" + }, + { + "type": "chrome", + "request": "launch", + "name": "Launch ExtinctionOnlineClient", + "runtimeExecutable": "/usr/bin/brave", "url": "http://localhost:5500", - "webRoot": "${workspaceFolder}" + "webRoot": "${workspaceFolder}", + "sourceMaps": true } ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..19273c8 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/ExtinctionOnline.Server/ExtinctionOnline.Server.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/ExtinctionOnline.Server/ExtinctionOnline.Server.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/ExtinctionOnline.Server/ExtinctionOnline.Server.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/static/js/card-module.js b/static/js/card-module.js new file mode 100644 index 0000000..51f0bc2 --- /dev/null +++ b/static/js/card-module.js @@ -0,0 +1,23 @@ +"use strict"; +function discard(target, card) { + console.log("DIS!CAR!D!"); + postMessage({ type: "game", game: { command: "discard", target: target, card: card } }); +} + +function selectUser() { + +} + +function selectCard(count, target) { + +} + +onmessage = e => { + console.log(e); + switch (e.data.type) { + case "run": + let fun = new Function("target", "players", e.data.function); + fun(e.data.target, e.data.players); + break; + } +} \ No newline at end of file diff --git a/static/js/cards.js b/static/js/cards.js index 47bc0b4..97c09fb 100644 --- a/static/js/cards.js +++ b/static/js/cards.js @@ -78,7 +78,8 @@ const cardTypes = { extinction: { id: "extinction", prefix: "H", - count: 4 + count: 4, + onGet: "target.cards.forEach(it => {discard(target,it);});" }, annihilation: { id: "annihilation", diff --git a/static/js/game-client.js b/static/js/game-client.js index 5866f77..fe206b6 100644 --- a/static/js/game-client.js +++ b/static/js/game-client.js @@ -3,7 +3,18 @@ let clientId = null; let controller = null; let roomData = null; -const commands = { syncRoomData: "SyncRoomData", gameStart: "GameStart", addCard: "AddCard" }; +const commands = { + syncRoomData: "SyncRoomData", // args: ホストのPlayerID, [PlayerID...] + gameStart: "GameStart", // args: PlayerID(ターン順)... + addCard: "AddCard", // target: 追加するPlayerID; args: 追加するカードのID, カードのIndex + worker: "Worker", // +}; + +const side = { + host: "HOST", + player: "PLAYER", + both: "BOTH" +} function onSystemMessage(obj) { if (clientId === null) { @@ -31,6 +42,7 @@ function joinToRoom(id, name) { } }; socket.send(JSON.stringify(obj)); + EXOUtils.init(); } class Card { @@ -52,12 +64,23 @@ class Player { constructor(id) { this.clientId = id; } + + 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)); + } + } } class MessageBuilder { object; - constructor(to) { + constructor(to, trSide = side.player) { this.object = { from: clientId, roomData: roomData, @@ -66,6 +89,7 @@ class MessageBuilder { clientId: to }, body: { + side: trSide, commands: [] } }; @@ -88,4 +112,43 @@ 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; + } + break; + } + } } \ No newline at end of file diff --git a/static/js/host-controller.js b/static/js/host-controller.js index 72d8229..06fc652 100644 --- a/static/js/host-controller.js +++ b/static/js/host-controller.js @@ -4,15 +4,22 @@ const firstCardCount = 5; class HostController { playerController = null; deck = new Array(); + discarded = new Array(); players = new Map(); + turnOrder; + turn = -1; constructor() { this.playerController = new PlayerController(); } gameStart() { + // ターンを決定 + this.turnOrder = EXOUtils.shuffleArray([...this.players.keys()]); + + // ゲームを開始 let startMessage = new MessageBuilder().game(); - startMessage.addCommand(commands.gameStart).send(); + startMessage.addCommand(commands.gameStart, null, ...this.turnOrder).send(); // すべてのカードを生成 Object.keys(cardTypes).forEach(key => { @@ -21,14 +28,20 @@ class HostController { }); // 山札をシャッフル - let currentIndex = this.deck.length; - while (currentIndex) { - let j = Math.floor(Math.random() * currentIndex); - let t = this.deck[--currentIndex]; - this.deck[currentIndex] = this.deck[j]; - this.deck[j] = t; - } + EXOUtils.shuffleArray(this.deck); + this.distributionCards(); + } + + 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); + await new Promise(resolve => setTimeout(resolve, 700)); + } + } + /* // プレイヤーに5枚ずつ配布 for (const player of this.players) { // 本人通達用 @@ -40,14 +53,16 @@ class HostController { 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(); - } + }*/ } onGameMessage(message) { - this.playerController.onGameMessage(message); + if (message.body.side != side.host) + this.playerController.onGameMessage(message); } joinNewPlayer(obj) { @@ -56,4 +71,20 @@ class HostController { messageBuilder.addCommand(commands.syncRoomData, null, clientId, [...this.players.keys()]); messageBuilder.send(); } + + cardCommands = { + remove: (target, card, index, canRecycle) => { + const player = controller.players.get(target); + index = player.cards.findIndex(it => it.id == card.id); + card = player.cards[index]; + if (canRecycle) + this.discarded.push(...player.cards.splice(index, 1)); + else + this.cardCommands.backIntoDeck(card); + new MessageBuilder().game().addCommand(commands.worker, target, "remove", [target, card, index, canRecycle]).send(); + }, + backIntoDeck: (card) => { + this.deck.splice(Math.floor(Math.random() * (this.deck.length + 1)), 0, card); + }, + }; } \ No newline at end of file diff --git a/static/js/player-controller.js b/static/js/player-controller.js index 848da82..e307d67 100644 --- a/static/js/player-controller.js +++ b/static/js/player-controller.js @@ -2,6 +2,9 @@ class PlayerController { hostClientId; players = new Map(); + discarded = new Array(); + turnOrder; + turn = 0; constructor() { } @@ -16,15 +19,30 @@ class PlayerController { break; case commands.gameStart: if (message.from !== this.hostClientId) { socket.close(); return; } + this.turn = 0; + this.turnOrder = command.args; break; case commands.addCard: if (message.from !== this.hostClientId) { socket.close(); return; } if (command.target == clientId && command.args[0] == cardTypes.unknown.id) return; this.players.get(command.target).cards.push(new Card(cardTypes[command.args[0]], command.args[1])); break; + case commands.worker: + if (message.from !== this.hostClientId) { socket.close(); return; } + this.cardCommands[command.args[0]](...command.args[1]); + break; } }); } joinNewPlayer() { } + + cardCommands = { + remove: (target, card, index, canRecycle) => { + const player = this.players.get(target); + player.cards.splice(index, 1); + if (canRecycle) + this.discarded.push(new Card(cardTypes[card.cardType.id], card.idIndex)); + }, + }; } \ No newline at end of file diff --git a/static/js/websocket.js b/static/js/websocket.js index 9f9c435..07d58fa 100644 --- a/static/js/websocket.js +++ b/static/js/websocket.js @@ -16,24 +16,4 @@ socket.addEventListener('message', function (event) { } else if (obj.messageType == "GAME") { controller.onGameMessage(obj); } -}); - -/* -// ユーザのスクリプトを実行する -var funText = "\"use strict\";return \"TEST MESSAGE\";"; - -var workerFile = "\ -function testFunction(){" + funText + - "}\ -postMessage(testFunction());\ -onmessage = function(e){console.log(e);\ -}" - -var blob = new Blob([workerFile], { - type: "text/javascript" -}); - -var worker = new Worker(window.URL.createObjectURL(blob)); -worker.onmessage = function (e) { - console.log('Function result:', e.data); -}*/ \ No newline at end of file +}); \ No newline at end of file