Commit 80525c74 authored by Chunchi Che's avatar Chunchi Che

remove moraStore, joinStore, playerStore, Mora.tsx and WaitRoom.tsx

parent 318f12f9
Pipeline #22922 passed with stages
in 19 minutes and 42 seconds
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { playerStore } from "@/stores"; import { roomStore } from "@/stores";
type MsgSibylName = ygopro.StocGameMessage.MsgSibylName; type MsgSibylName = ygopro.StocGameMessage.MsgSibylName;
export default (sibylName: MsgSibylName) => { export default (sibylName: MsgSibylName) => {
playerStore.getMePlayer().name = sibylName.name_0; roomStore.getMePlayer().name = sibylName.name_0;
playerStore.getOpPlayer().name = sibylName.name_1; roomStore.getOpPlayer().name = sibylName.name_1;
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { playerStore } from "@/stores"; import { roomStore } from "@/stores";
// FIXME: player0 不一定是当前玩家 // TODO: 这里设置的player可能顺序会反
export default function handleDeckCount(pb: ygopro.YgoStocMsg) { export default function handleDeckCount(pb: ygopro.YgoStocMsg) {
const deckCount = pb.stoc_deck_count; const deckCount = pb.stoc_deck_count;
playerStore.player0.deckInfo = { roomStore.getMePlayer().deckInfo = {
mainCnt: deckCount.meMain, mainSize: deckCount.meMain,
extraCnt: deckCount.meExtra, extraSize: deckCount.meExtra,
sideCnt: deckCount.meSide, sideSize: deckCount.meSide,
}; };
playerStore.player1.deckInfo = { roomStore.getOpPlayer().deckInfo = {
mainCnt: deckCount.opMain, mainSize: deckCount.opMain,
extraCnt: deckCount.opExtra, extraSize: deckCount.opExtra,
sideCnt: deckCount.opSide, sideSize: deckCount.opSide,
}; };
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { moraStore } from "@/stores"; import { roomStore } from "@/stores";
export default function handleSelectHand(_: ygopro.YgoStocMsg) { export default function handleSelectHand(_: ygopro.YgoStocMsg) {
moraStore.selectHandAble = true; roomStore.selectHand = true;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { moraStore } from "@/stores"; import { roomStore } from "@/stores";
export default function handleSelectTp(_: ygopro.YgoStocMsg) { export default function handleSelectTp(_: ygopro.YgoStocMsg) {
moraStore.selectTpAble = true; roomStore.selectTp = true;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { moraStore } from "@/stores"; import { roomStore } from "@/stores";
export default function handleDuelStart(_pb: ygopro.YgoStocMsg) { export default function handleDuelStart(_pb: ygopro.YgoStocMsg) {
moraStore.duelStart = true; roomStore.moraStart = true;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { playerStore } from "@/stores"; import { roomStore } from "@/stores";
const READY_STATE = "ready";
const NO_READY_STATE = "not ready";
export default function handleHsPlayerChange(pb: ygopro.YgoStocMsg) { export default function handleHsPlayerChange(pb: ygopro.YgoStocMsg) {
const change = pb.stoc_hs_player_change; const change = pb.stoc_hs_player_change;
...@@ -17,36 +14,30 @@ export default function handleHsPlayerChange(pb: ygopro.YgoStocMsg) { ...@@ -17,36 +14,30 @@ export default function handleHsPlayerChange(pb: ygopro.YgoStocMsg) {
break; break;
} }
case ygopro.StocHsPlayerChange.State.MOVE: { case ygopro.StocHsPlayerChange.State.MOVE: {
// TODO: 这个分支可能有BUG,后面注意一下
console.log("Player " + change.pos + " moved to " + change.moved_pos); console.log("Player " + change.pos + " moved to " + change.moved_pos);
let _src = change.pos; const player = roomStore.players.splice(change.pos, 1);
let _dst = change.moved_pos; const insertIndex =
change.pos > change.moved_pos
console.log("Currently unsupport Move type of StocHsPlayerChange."); ? change.moved_pos
: change.moved_pos - 1;
// TODO roomStore.players.splice(insertIndex, 0, ...player);
break; break;
} }
case ygopro.StocHsPlayerChange.State.READY: { case ygopro.StocHsPlayerChange.State.READY:
playerStore[change.pos === 0 ? "player0" : "player1"].state =
READY_STATE;
break;
}
case ygopro.StocHsPlayerChange.State.NO_READY: { case ygopro.StocHsPlayerChange.State.NO_READY: {
playerStore[change.pos === 0 ? "player0" : "player1"].state = roomStore.players[change.pos].state = change.state;
NO_READY_STATE;
break; break;
} }
case ygopro.StocHsPlayerChange.State.LEAVE: { case ygopro.StocHsPlayerChange.State.LEAVE: {
playerStore[change.pos === 0 ? "player0" : "player1"] = {}; roomStore.players.splice(change.pos, 1);
break; break;
} }
case ygopro.StocHsPlayerChange.State.TO_OBSERVER: { case ygopro.StocHsPlayerChange.State.TO_OBSERVER: {
playerStore[change.pos === 0 ? "player0" : "player1"] = {}; // TODO: 有没有必要? roomStore.players.splice(change.pos, 1);
playerStore.observerCount += 1; roomStore.observerCount += 1;
break; break;
} }
default: { default: {
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { playerStore } from "@/stores"; import { roomStore } from "@/stores";
export default function handleHsPlayerEnter(pb: ygopro.YgoStocMsg) { export default function handleHsPlayerEnter(pb: ygopro.YgoStocMsg) {
const name = pb.stoc_hs_player_enter.name; const name = pb.stoc_hs_player_enter.name;
...@@ -8,6 +8,6 @@ export default function handleHsPlayerEnter(pb: ygopro.YgoStocMsg) { ...@@ -8,6 +8,6 @@ export default function handleHsPlayerEnter(pb: ygopro.YgoStocMsg) {
if (pos > 1) { if (pos > 1) {
console.log("Currently only supported 2v2 mode."); console.log("Currently only supported 2v2 mode.");
} else { } else {
playerStore[pos === 0 ? "player0" : "player1"].name = name; roomStore.players[pos].name = name;
} }
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { playerStore } from "@/stores"; import { roomStore } from "@/stores";
export default function handleHsWatchChange(pb: ygopro.YgoStocMsg) { export default function handleHsWatchChange(pb: ygopro.YgoStocMsg) {
const count = pb.stoc_hs_watch_change.count; const count = pb.stoc_hs_watch_change.count;
playerStore.observerCount = count; roomStore.observerCount = count;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { joinStore } from "@/stores"; import { roomStore } from "@/stores";
export default function handleJoinGame(pb: ygopro.YgoStocMsg) { export default function handleJoinGame(pb: ygopro.YgoStocMsg) {
const _msg = pb.stoc_join_game; const _msg = pb.stoc_join_game;
// TODO // TODO
joinStore.value = true; roomStore.joined = true;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { playerStore } from "@/stores"; import { roomStore } from "@/stores";
import SelfType = ygopro.StocTypeChange.SelfType;
const NO_READY_STATE = "not ready";
export default function handleTypeChange(pb: ygopro.YgoStocMsg) { export default function handleTypeChange(pb: ygopro.YgoStocMsg) {
const selfType = pb.stoc_type_change.self_type; const selfType = pb.stoc_type_change.self_type;
const assertHost = pb.stoc_type_change.is_host; const assertHost = pb.stoc_type_change.is_host;
playerStore.isHost = assertHost; roomStore.isHost = assertHost;
playerStore.selfType = selfType; roomStore.selfType = selfType;
if (assertHost) { if (assertHost) {
switch (selfType) { switch (selfType) {
case ygopro.StocTypeChange.SelfType.PLAYER1: { case SelfType.UNKNOWN:
playerStore.player0.isHost = true; case SelfType.OBSERVER: {
playerStore.player1.isHost = false; console.warn("<HandleTypeChange>selfType is UNKNOWN or OBSERVER");
playerStore.player0.state = NO_READY_STATE;
break;
}
case ygopro.StocTypeChange.SelfType.PLAYER2: {
playerStore.player0.isHost = false;
playerStore.player1.isHost = true;
playerStore.player1.state = NO_READY_STATE;
break; break;
} }
default: { default: {
roomStore.players[selfType - 1].state =
ygopro.StocHsPlayerChange.State.NO_READY;
break; break;
} }
} }
......
export * from "./accountStore"; export * from "./accountStore";
export * from "./cardStore"; export * from "./cardStore";
export * from "./chatStore"; export * from "./chatStore";
export * from "./joinStore";
export * from "./matStore"; export * from "./matStore";
export * from "./moraStore";
export * from "./placeStore"; export * from "./placeStore";
export * from "./playerStore";
export * from "./replayStore"; export * from "./replayStore";
export * from "./roomStore"; export * from "./roomStore";
...@@ -14,18 +11,12 @@ import { devtools } from "valtio/utils"; ...@@ -14,18 +11,12 @@ import { devtools } from "valtio/utils";
import { accountStore } from "./accountStore"; import { accountStore } from "./accountStore";
import { cardStore } from "./cardStore"; import { cardStore } from "./cardStore";
import { chatStore } from "./chatStore"; import { chatStore } from "./chatStore";
import { joinStore } from "./joinStore";
import { matStore } from "./matStore"; import { matStore } from "./matStore";
import { moraStore } from "./moraStore";
import { placeStore } from "./placeStore"; import { placeStore } from "./placeStore";
import { playerStore } from "./playerStore";
import { replayStore } from "./replayStore"; import { replayStore } from "./replayStore";
import { roomStore } from "./roomStore"; import { roomStore } from "./roomStore";
devtools(playerStore, { name: "player", enabled: true });
devtools(chatStore, { name: "chat", enabled: true }); devtools(chatStore, { name: "chat", enabled: true });
devtools(joinStore, { name: "join", enabled: true });
devtools(moraStore, { name: "mora", enabled: true });
devtools(matStore, { name: "mat", enabled: true }); devtools(matStore, { name: "mat", enabled: true });
devtools(cardStore, { name: "card", enabled: true }); devtools(cardStore, { name: "card", enabled: true });
devtools(placeStore, { name: "place", enabled: true }); devtools(placeStore, { name: "place", enabled: true });
...@@ -35,13 +26,10 @@ devtools(roomStore, { name: "room", enabled: true }); ...@@ -35,13 +26,10 @@ devtools(roomStore, { name: "room", enabled: true });
// 重置所有`Store` // 重置所有`Store`
export const resetUniverse = () => { export const resetUniverse = () => {
roomStore.reset();
cardStore.reset(); cardStore.reset();
chatStore.reset(); chatStore.reset();
joinStore.reset();
matStore.reset(); matStore.reset();
moraStore.reset();
placeStore.reset(); placeStore.reset();
playerStore.reset();
replayStore.reset(); replayStore.reset();
roomStore.reset();
}; };
import { proxy } from "valtio";
import { NeosStore } from "./shared";
export interface JoinState extends NeosStore {
value: boolean;
}
export const joinStore = proxy<JoinState>({
value: false,
reset() {
joinStore.value = false;
},
});
import { proxy } from "valtio";
import { NeosStore } from "./shared";
export interface MoraState extends NeosStore {
duelStart: boolean;
selectHandAble: boolean;
selectTpAble: boolean;
}
const initialState = {
duelStart: false,
selectHandAble: false,
selectTpAble: false,
};
export const moraStore = proxy<MoraState>({
...initialState,
reset() {
Object.keys(initialState).forEach((key) => {
// @ts-ignore
moraStore[key] = initialState[key];
});
},
});
/* eslint valtio/avoid-this-in-proxy: 0 */
import { cloneDeep } from "lodash-es";
import { proxy } from "valtio";
import { ygopro } from "@/api";
import SelfType = ygopro.StocTypeChange.SelfType;
import { NeosStore } from "./shared";
export interface Player {
name?: string;
state?: string;
isHost?: boolean;
deckInfo?: deckInfo;
}
export interface deckInfo {
mainCnt: number;
extraCnt: number;
sideCnt: number;
}
export interface PlayerState extends NeosStore {
player0: Player;
player1: Player;
observerCount: number;
isHost: boolean;
selfType: SelfType;
getMePlayer: () => Player;
getOpPlayer: () => Player;
}
const initialState = {
player0: {},
player1: {},
observerCount: 0,
isHost: false,
selfType: SelfType.UNKNOWN,
};
export const playerStore = proxy<PlayerState>({
...initialState,
getMePlayer() {
if (this.selfType === SelfType.PLAYER1) return this.player0;
return this.player1;
},
getOpPlayer() {
if (this.selfType === SelfType.PLAYER1) return this.player1;
return this.player0;
},
reset() {
const resetObj = cloneDeep(initialState);
Object.keys(resetObj).forEach((key) => {
// @ts-ignore
playerStore[key] = resetObj[key];
});
},
});
...@@ -3,7 +3,7 @@ import { proxy } from "valtio"; ...@@ -3,7 +3,7 @@ import { proxy } from "valtio";
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import StocHsPlayerChange = ygopro.StocHsPlayerChange; import StocHsPlayerChange = ygopro.StocHsPlayerChange;
import StocTypeChange = ygopro.StocTypeChange; import SelfType = ygopro.StocTypeChange.SelfType;
import { NeosStore } from "./shared"; import { NeosStore } from "./shared";
interface Player { interface Player {
...@@ -24,11 +24,20 @@ class RoomStore implements NeosStore { ...@@ -24,11 +24,20 @@ class RoomStore implements NeosStore {
players: Player[] = []; // 进入房间的玩家列表 players: Player[] = []; // 进入房间的玩家列表
observerCount: number = 0; // 观战者数量 observerCount: number = 0; // 观战者数量
isHost: boolean = false; // 当前玩家是否是房主 isHost: boolean = false; // 当前玩家是否是房主
selfType: StocTypeChange.SelfType = 0; // 当前玩家的类型 selfType: SelfType = 0; // 当前玩家的类型
moraStart: boolean = false; // 猜拳阶段是否开始 moraStart: boolean = false; // 猜拳阶段是否开始
selectHand: boolean = false; // 是否可以选择猜拳 selectHand: boolean = false; // 是否可以选择猜拳
selectTp: boolean = false; // 是否可以选边 selectTp: boolean = false; // 是否可以选边
getMePlayer() {
if (this.selfType == SelfType.PLAYER1) return this.players[0];
return this.players[1];
}
getOpPlayer() {
if (this.selfType == SelfType.PLAYER1) return this.players[1];
return this.players[0];
}
reset(): void { reset(): void {
this.joined = false; this.joined = false;
this.players = []; this.players = [];
......
...@@ -5,7 +5,7 @@ import AnimatedNumbers from "react-animated-numbers"; ...@@ -5,7 +5,7 @@ import AnimatedNumbers from "react-animated-numbers";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
import { useEnv } from "@/hook"; import { useEnv } from "@/hook";
import { matStore, playerStore } from "@/stores"; import { matStore, roomStore } from "@/stores";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
// 三个候选方案 // 三个候选方案
...@@ -15,7 +15,7 @@ import styles from "./index.module.scss"; ...@@ -15,7 +15,7 @@ import styles from "./index.module.scss";
export const LifeBar: React.FC = () => { export const LifeBar: React.FC = () => {
const snapInitInfo = useSnapshot(matStore.initInfo); const snapInitInfo = useSnapshot(matStore.initInfo);
const snapPlayer = useSnapshot(playerStore); const snapPlayer = useSnapshot(roomStore);
const { currentPlayer } = useSnapshot(matStore); const { currentPlayer } = useSnapshot(matStore);
const [meLife, setMeLife] = React.useState(0); const [meLife, setMeLife] = React.useState(0);
......
import {
ScissorOutlined,
SketchOutlined,
TableOutlined,
} from "@ant-design/icons";
import { Button, Modal } from "antd";
import React, { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useSnapshot } from "valtio";
import { sendHandResult, sendTpResult } from "@/api";
import { useConfig } from "@/config";
import { matStore, moraStore } from "@/stores";
const {
automation: { isAiMode, isAiFirst },
defaults: { defaultMora },
} = useConfig();
const Mora = () => {
const snapMora = useSnapshot(moraStore);
const snapMat = useSnapshot(matStore);
const meLife = snapMat.initInfo.me.life;
const selectHandAble = snapMora.selectHandAble;
const selectTpAble = snapMora.selectTpAble;
const navigate = useNavigate();
const { player, passWd, ip } = useParams<{
player?: string;
passWd?: string;
ip?: string;
}>();
const handleSelectMora = (selected: string) => {
sendHandResult(selected);
moraStore.selectHandAble = false;
};
const handleSelectTp = (isFirst: boolean) => {
sendTpResult(isFirst);
moraStore.selectTpAble = false;
};
useEffect(() => {
// 若对局已经开始,自动跳转
if (meLife > 0) {
navigate(`/duel/${player}/${encodeURIComponent(passWd ?? "")}/${ip}`);
}
}, [meLife]);
useEffect(() => {
if (isAiMode) {
handleSelectMora(defaultMora);
}
}, [selectHandAble]);
useEffect(() => {
if (isAiMode && !selectHandAble && selectTpAble) {
handleSelectTp(!isAiFirst);
}
}, [selectHandAble, selectTpAble]);
return (
<>
<Modal title="请选择猜拳" open={selectHandAble} footer={<></>}>
<Button
disabled={!selectHandAble}
onClick={() => {
handleSelectMora("scissors");
}}
icon={<ScissorOutlined />}
>
剪刀
</Button>
<Button
disabled={!selectHandAble}
onClick={() => {
handleSelectMora("rock");
}}
icon={<SketchOutlined />}
>
石头
</Button>
<Button
disabled={!selectHandAble}
onClick={() => {
handleSelectMora("paper");
}}
icon={<TableOutlined />}
>
</Button>
</Modal>
<Modal
title="请选择先攻/后攻"
open={!selectHandAble && selectTpAble}
footer={<></>}
>
<Button
disabled={!selectTpAble}
onClick={() => {
handleSelectTp(true);
}}
>
先攻
</Button>
<Button
disabled={!selectTpAble}
onClick={() => {
handleSelectTp(false);
}}
>
后攻
</Button>
</Modal>
</>
);
};
export default Mora;
import {
CheckCircleFilled,
LoginOutlined,
LogoutOutlined,
SendOutlined,
TagOutlined,
UploadOutlined,
UserOutlined,
} from "@ant-design/icons";
import type { UploadProps } from "antd";
import {
Avatar,
Button,
Checkbox,
message,
Modal,
notification,
Select,
Space,
Upload,
} from "antd";
import React, { useEffect, useState } from "react";
import { useLoaderData, useNavigate } from "react-router-dom";
import rustInit from "rust-src";
import { useSnapshot } from "valtio";
import YGOProDeck from "ygopro-deck-encode";
import { initStrings, sendHsReady, sendHsStart, sendUpdateDeck } from "@/api";
import { DeckManager, fetchDeck, type IDeck } from "@/api/deck";
import { useConfig } from "@/config";
import socketMiddleWare, { socketCmd } from "@/middleware/socket";
import sqliteMiddleWare, { sqliteCmd } from "@/middleware/sqlite";
import { chatStore, joinStore, moraStore, playerStore } from "@/stores";
const NeosConfig = useConfig();
const READY_STATE = "ready";
const {
defaults: { defaultDeck },
automation: { isAiMode },
} = useConfig();
interface Params {
player?: string;
passWd?: string;
ip?: string;
}
export const Loader = (params: Params) => params;
export const Component = () => {
const snapJoin = useSnapshot(joinStore);
const snapChat = useSnapshot(chatStore);
const snapMora = useSnapshot(moraStore);
const snapPlayer = useSnapshot(playerStore);
const [choseDeck, setChoseDeck] = useState<boolean>(false);
const { player, passWd, ip } = useLoaderData<Params>();
useEffect(() => {
if (ip && player && player.length != 0 && passWd && passWd.length != 0) {
const init = async () => {
// 初始化wasm
const url =
import.meta.env.BASE_URL === "/"
? undefined
: new URL("rust_src_bg.wasm", `${import.meta.env.BASE_URL}assets/`);
await rustInit(url);
// 初始化sqlite
await sqliteMiddleWare({
cmd: sqliteCmd.INIT,
initInfo: { dbUrl: NeosConfig.cardsDbUrl },
});
// 初始化文案
await initStrings();
// 页面第一次渲染时,通过socket中间件向ygopro服务端请求建立长连接
socketMiddleWare({
cmd: socketCmd.CONNECT,
initInfo: {
ip,
player,
passWd,
},
});
};
init();
}
}, []);
const [api, contextHolder] = notification.useNotification();
const joined = snapJoin.value;
const chat = snapChat.message;
const isHost = snapPlayer.isHost;
const player0 = snapPlayer.player0;
const player1 = snapPlayer.player1;
const duelStart = snapMora.duelStart;
// FIXME: 这些数据应该从`store`中获取
// TODO: 云卡组
const decks = [...DeckManager.keys()].map((deckName) => ({
value: deckName,
label: deckName,
}));
const [uploadState, setUploadState] = useState("");
const uploadProps: UploadProps = {
name: "file",
onChange(info) {
if (uploadState != "ERROR") {
info.file.status = "done";
}
},
beforeUpload(file, _) {
const reader = new FileReader();
reader.readAsText(file);
reader.onload = (e) => {
const ydk = e.target?.result as string;
const deck = YGOProDeck.fromYdkString(ydk);
if (
!(
deck.main.length === 0 &&
deck.extra.length === 0 &&
deck.side.length === 0
)
) {
// YDK解析成功
message.success(`${file.name}解析成功`);
onDeckReady({ deckName: file.name, ...deck });
} else {
message.error(`${file.name}解析失败`);
setUploadState("ERROR");
}
};
},
};
const onDeckReady = async (deck: IDeck) => {
sendUpdateDeck(deck);
setChoseDeck(true);
window.myExtraDeckCodes = [...deck.extra];
};
const handleChoseDeck = async (deckName: string) => {
const deck = await fetchDeck(deckName);
await onDeckReady(deck);
};
const handleChoseReady = () => {
sendHsReady();
};
const handleChoseStart = () => {
sendHsStart();
};
const navigate = useNavigate();
useEffect(() => {
if (joined) {
api.info({ message: "成功加入房间!", placement: "top" });
/** 如果是开发者模式下的人机对战,应该自动选择卡组,并自动准备和开始 */
const runAiMode = async () => {
await new Promise((resolve) => setTimeout(resolve, 500));
await handleChoseDeck(defaultDeck!);
handleChoseReady();
handleChoseStart();
};
(async () => {
if (isAiMode) {
await runAiMode();
}
})();
}
}, [joined]);
useEffect(() => {
if (chat != "") {
api.info({ message: "Chat", description: chat, placement: "bottom" });
}
}, [chat]);
useEffect(() => {
// 若当前玩家是房主并且对战双方都已准备完毕,跳转到猜拳页面;
// 否则停留在当前页面。
if (duelStart) {
navigate(`/mora/${player}/${encodeURIComponent(passWd ?? "")}/${ip}`);
}
}, [duelStart]);
return (
<>
<Modal
title="单局房间"
open={true}
maskClosable={false}
footer={
<>
<Space direction="vertical" size={10}>
<Space wrap size={10}>
<Avatar size={25} icon={<CheckCircleFilled />} />
<Button
disabled={!(choseDeck && joined)}
onClick={handleChoseReady}
>
决斗准备
</Button>
</Space>
<Space wrap size={10}>
<Avatar size={25} icon={<LoginOutlined />} />
<Button>到决斗者</Button>
</Space>
<Space wrap size={10}>
<Avatar size={25} icon={<LogoutOutlined />} />
<Button>到旁观者</Button>
</Space>
<Space wrap size={10}>
<Avatar size={25} icon={<SendOutlined />} />
<Button onClick={handleChoseStart} disabled={!isHost}>
开始游戏
</Button>
</Space>
</Space>
</>
}
onCancel={() => {
// 断开websocket🔗,
socketMiddleWare({ cmd: socketCmd.DISCONNECT });
// 回到初始界面
navigate("/");
}}
>
<Space direction="vertical" size={16}>
<Space wrap size={16}>
<Avatar size={30} icon={<UserOutlined />} />
<Checkbox
defaultChecked={false}
checked={player0.state === READY_STATE}
disabled
>
{player0.name}
</Checkbox>
{player0.isHost === true ? (
<Avatar size={30} icon={<TagOutlined />} />
) : (
<></>
)}
</Space>
<Space wrap size={16}>
<Avatar size={30} icon={<UserOutlined />} />
<Checkbox
defaultChecked={false}
checked={player1.state === READY_STATE}
disabled
>
{player1.name}
</Checkbox>
{player1.isHost === true ? (
<Avatar size={30} icon={<TagOutlined />} />
) : (
<></>
)}
</Space>
<Space wrap size={16}>
<Select
placeholder="请选择卡组"
onChange={handleChoseDeck}
options={decks}
style={{ width: 160 }}
/>
</Space>
<Space>
<Upload {...uploadProps}>
<Button icon={<UploadOutlined />}>
没有卡组?点击上传YDK文件
</Button>
</Upload>
</Space>
</Space>
</Modal>
{contextHolder}
</>
);
};
Component.displayName = "WaitRoom";
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment