Commit 4427068c authored by Chunchi Che's avatar Chunchi Che

support replay

parent 80d19636
Pipeline #22948 passed with stages
in 13 minutes and 37 seconds
......@@ -7,7 +7,7 @@ import { fetchCard, ygopro } from "@/api";
import { useConfig } from "@/config";
import { sleep } from "@/infra";
import { cardStore, CardType, matStore } from "@/stores";
import { replayStart } from "@/ui/Replay";
import { replayStart } from "@/ui/NewMatch/ReplayModal";
const TOKEN_SIZE = 13; // 每人场上最多就只可能有13个token
export default async (start: ygopro.StocGameMessage.MsgStart) => {
......
......@@ -17,7 +17,7 @@ import {
} from "./Message";
import { LifeBar, Mat, Menu } from "./PlayMat";
const NeosDuel = () => {
export const Component: React.FC = () => {
return (
<>
<SelectActionsModal />
......@@ -39,5 +39,4 @@ const NeosDuel = () => {
</>
);
};
export default NeosDuel;
Component.displayName = "NeosDuel";
......@@ -28,6 +28,7 @@ const _router = createBrowserRouter([
},
{
path: "/duel/:ip/:player/:passWd",
lazy: () => import("./Duel/Main"),
},
],
},
......
......@@ -6,7 +6,7 @@ import { proxy, useSnapshot } from "valtio";
import { useConfig } from "@/config";
import { accountStore, roomStore } from "@/stores";
import styles from "./Modal.module.scss";
import styles from "./MatchModal.module.scss";
import { init } from "./util";
const NeosConfig = useConfig();
const serverConfig = NeosConfig.servers;
......@@ -24,10 +24,10 @@ const defaultProps: Props = {
open: false,
};
export const localStore = proxy<Props>(defaultProps);
export const matchStore = proxy<Props>(defaultProps);
export const MatchModal: React.FC = ({}) => {
const { open } = useSnapshot(localStore);
const { open } = useSnapshot(matchStore);
const { user } = useSnapshot(accountStore);
const { joined } = useSnapshot(roomStore);
const [player, setPlayer] = useState(user?.name ?? defaultPlayer);
......@@ -71,7 +71,7 @@ export const MatchModal: React.FC = ({}) => {
<Modal
open={open}
title="请输入自定义房间信息"
onCancel={() => (localStore.open = false)}
onCancel={() => (matchStore.open = false)}
footer={
<Button onClick={handleSubmit} loading={confirmLoading}>
加入房间
......
import "../../styles/core.scss";
import { UploadOutlined } from "@ant-design/icons";
import { Button, message, Modal, Upload, UploadProps } from "antd";
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import rustInit from "rust-src";
import { proxy, useSnapshot } from "valtio";
import { initStrings } from "@/api";
import { useConfig } from "@/config";
import socketMiddleWare, { socketCmd } from "@/middleware/socket";
import sqliteMiddleWare, { sqliteCmd } from "@/middleware/sqlite";
import { matStore } from "@/stores";
import { init } from "./util";
const NeosConfig = useConfig();
const localStore = proxy({
open: false,
hasStart: false,
});
const ReplayModal: React.FC = () => {
const { hasStart } = useSnapshot(localStore);
export const ReplayModal: React.FC = () => {
const { open, hasStart } = useSnapshot(localStore);
const [replay, setReplay] = useState<null | ArrayBuffer>(null);
const [loading, setLoading] = useState(false);
const uploadProps: UploadProps = {
name: "replay",
onChange(info) {
......@@ -35,9 +33,32 @@ const ReplayModal: React.FC = () => {
};
const navigate = useNavigate();
const onSubmit = async () => {
if (replay === null) {
message.error("请先上传录像文件");
} else {
setLoading(true);
// 标记为回放模式
matStore.isReplay = true;
// 初始化额外卡组
// FIXME: 这样写应该不对,有空来修
window.myExtraDeckCodes = [];
await init({
ip: "",
player: "",
passWd: "",
replay: true,
replayData: replay,
});
}
};
useEffect(() => {
if (hasStart) {
setLoading(false);
// 跳转
navigate(`/duel/neos/replay/${NeosConfig.replayUrl}`);
}
......@@ -46,55 +67,16 @@ const ReplayModal: React.FC = () => {
return (
<Modal
title="选择回放"
open={true}
open={open}
maskClosable={false}
onOk={async () => {
if (replay === null) {
message.error("请先上传录像文件");
} else {
// 标记为回放模式
matStore.isReplay = true;
// 初始化wasm
const url =
import.meta.env.BASE_URL === "/"
? undefined
: new URL(
"rust_src_bg.wasm",
`${import.meta.env.BASE_URL}assets/`
);
await rustInit(url);
// 初始化额外卡组
// FIXME: 这样写应该不对,有空来修
window.myExtraDeckCodes = [];
// 初始化sqlite
await sqliteMiddleWare({
cmd: sqliteCmd.INIT,
initInfo: { dbUrl: NeosConfig.cardsDbUrl },
});
// 初始化文案
await initStrings();
// 连接回放websocket服务
socketMiddleWare({
cmd: socketCmd.CONNECT,
isReplay: true,
replayInfo: {
Url: NeosConfig.replayUrl,
data: replay,
},
});
}
}}
onCancel={() => {
// 断开websocket连接
socketMiddleWare({ cmd: socketCmd.DISCONNECT });
// 回到初始界面
navigate("/");
}}
confirmLoading={loading}
centered
footer={
<Button onClick={onSubmit} loading={loading}>
开始回放
</Button>
}
onCancel={() => (localStore.open = false)}
>
<Upload {...uploadProps}>
<Button icon={<UploadOutlined />}>点击上传录像文件</Button>
......@@ -103,8 +85,10 @@ const ReplayModal: React.FC = () => {
);
};
export const replayOpen = () => {
localStore.open = true;
};
export const replayStart = () => {
localStore.hasStart = true;
};
export default ReplayModal;
......@@ -7,7 +7,8 @@ import { accountStore, type User } from "@/stores";
import { Background, IconFont, Select } from "@/ui/Shared";
import styles from "./index.module.scss";
import { localStore, MatchModal } from "./Modal";
import { MatchModal, matchStore } from "./MatchModal";
import { ReplayModal, replayOpen } from "./ReplayModal";
export const loader: LoaderFunction = () => {
const sso = new URLSearchParams(location.search).get("sso");
......@@ -72,12 +73,13 @@ export const Component: React.FC = () => {
title="自定义房间"
desc="创建一个自定义的对战房间,便捷地与好友进行对战,甚至是举办一场竞技比赛。"
icon={<SettingFilled />}
onClick={() => (localStore.open = true)}
onClick={() => (matchStore.open = true)}
/>
<Mode
title="录像回放"
desc="自由查看进行过的决斗,回味那些精彩的逆转瞬间。"
icon={<IconFont type="icon-record" size={24} />}
onClick={replayOpen}
/>
<Mode
title="卡组编辑"
......@@ -88,6 +90,7 @@ export const Component: React.FC = () => {
</div>
</div>
<MatchModal />
<ReplayModal />
</>
);
};
......
......@@ -7,11 +7,13 @@ import sqliteMiddleWare, { sqliteCmd } from "@/middleware/sqlite";
const NeosConfig = useConfig();
// 进行进入房间前的一些初始化操作
// 进行进入房间/回放前的一些初始化操作
export const init = async (params: {
ip: string;
player: string;
passWd: string;
replay?: boolean;
replayData?: ArrayBuffer;
}) => {
// 初始化wasm
const url =
......@@ -29,9 +31,21 @@ export const init = async (params: {
// 初始化I18N文案
await initStrings();
// 页面第一次渲染时,通过socket中间件向ygopro服务端请求建立长连接
socketMiddleWare({
cmd: socketCmd.CONNECT,
initInfo: params,
});
if (params.replay && params.replayData) {
// 连接回放websocket服务
socketMiddleWare({
cmd: socketCmd.CONNECT,
isReplay: true,
replayInfo: {
Url: NeosConfig.replayUrl,
data: params.replayData,
},
});
} else {
// 通过socket中间件向ygopro服务端请求建立长连接
socketMiddleWare({
cmd: socketCmd.CONNECT,
initInfo: params,
});
}
};
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