Add card distribution function/extinction cards

This commit is contained in:
noyciy7037 2023-04-23 12:40:54 +09:00
parent b6b0e71739
commit 704ad00af8
Signed by: noyciy7037
GPG Key ID: 46A54FA18BBA58FF
8 changed files with 207 additions and 38 deletions

20
.vscode/launch.json vendored
View File

@ -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
}
]
}

41
.vscode/tasks.json vendored Normal file
View File

@ -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"
}
]
}

23
static/js/card-module.js Normal file
View File

@ -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;
}
}

View File

@ -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",

View File

@ -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;
}
}
}

View File

@ -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);
},
};
}

View File

@ -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));
},
};
}

View File

@ -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);
}*/
});