Commit 4e1a921f authored by timel's avatar timel

feat: deck store

parent 80525c74
Pipeline #22923 failed with stages
in 12 minutes and 29 seconds
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
"cookies-ts": "^1.0.5", "cookies-ts": "^1.0.5",
"eventemitter3": "^5.0.1", "eventemitter3": "^5.0.1",
"google-protobuf": "^3.21.2", "google-protobuf": "^3.21.2",
"idb-keyval": "^6.2.1",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"react": "^18.2.0", "react": "^18.2.0",
"react-animated-numbers": "^0.16.0", "react-animated-numbers": "^0.16.0",
...@@ -11455,6 +11456,11 @@ ...@@ -11455,6 +11456,11 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/idb-keyval": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
"integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg=="
},
"node_modules/identity-obj-proxy": { "node_modules/identity-obj-proxy": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz",
...@@ -37258,6 +37264,11 @@ ...@@ -37258,6 +37264,11 @@
} }
} }
}, },
"idb-keyval": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
"integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg=="
},
"identity-obj-proxy": { "identity-obj-proxy": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz",
const DECKS: Record<string, { default: IDeck }> = import.meta.glob(
"/neos-assets/structure-decks/*.ydk",
{
eager: true,
}
);
export const DeckManager = _objToMap(
Object.keys(DECKS).map((key) => ({
...DECKS[key].default,
deckName:
key.split("/").pop()?.split(".").slice(0, -1).join(".") ?? "undefined",
}))
);
/*
* 返回卡组资源。
*
* @param deck- 卡组名称
* @returns 卡组数据
*
* @todo - 这里应该为萌卡实现卡组存储
* */
export async function fetchDeck(deck: string): Promise<IDeck> {
const res = DeckManager.get(deck);
if (!res) {
console.error(`Deck ${deck} doesn't exist.`);
}
return res ?? { deckName: "undefined", main: [], extra: [], side: [] };
}
function _objToMap(object: IDeck[]): Map<string, IDeck> {
const map: Map<string, IDeck> = new Map();
object.forEach((value) => map.set(value.deckName, value));
return map;
}
export interface IDeck {
deckName: string;
main: number[];
extra: number[];
side: number[];
}
export * from "./deckManager";
export * from "./cards"; export * from "./cards";
export * from "./cookies"; export * from "./cookies";
export * from "./deck";
export * from "./mycard"; export * from "./mycard";
export * from "./ocgcore/idl/ocgcore"; export * from "./ocgcore/idl/ocgcore";
export * from "./ocgcore/ocgHelper"; export * from "./ocgcore/ocgHelper";
......
import { proxy } from "valtio"; import { proxy } from "valtio";
import { NeosStore } from "./shared"; import { type NeosStore } from "./shared";
export interface User { export interface User {
id: string; id: string;
......
...@@ -3,7 +3,7 @@ import { proxy } from "valtio"; ...@@ -3,7 +3,7 @@ import { proxy } from "valtio";
import { CardMeta, ygopro } from "@/api"; import { CardMeta, ygopro } from "@/api";
import type { Interactivity } from "./matStore/types"; import type { Interactivity } from "./matStore/types";
import { NeosStore } from "./shared"; import { type NeosStore } from "./shared";
/** /**
* 场上某位置的状态 * 场上某位置的状态
......
import { proxy } from "valtio"; import { proxy } from "valtio";
import { NeosStore } from "./shared"; import { type NeosStore } from "./shared";
export interface ChatState extends NeosStore { export interface ChatState extends NeosStore {
message: string; message: string;
......
import { clear, createStore, del, set, values } from "idb-keyval";
import { proxy } from "valtio";
import { type NeosStore } from "./shared";
// 给玩家预设了几套卡组,一旦idb为空,就会给玩家添加这几套卡组
const PRESET_DECKS: Record<string, { default: Omit<IDeck, "deckName"> }> =
import.meta.glob("/neos-assets/structure-decks/*.ydk", {
eager: true,
});
const IDB_NAME = "decks";
const deckIdb = createStore(IDB_NAME, IDB_NAME);
interface IDeck {
deckName: string;
main: number[];
extra: number[];
side: number[];
}
export const deckStore = proxy({
decks: [] as IDeck[],
get(deckName: string) {
return deckStore.decks.find((deck) => deck.deckName === deckName);
},
async update(deckName: string, deck: IDeck): Promise<boolean> {
const index = deckStore.decks.findIndex(
(deck) => deck.deckName === deckName
);
if (index === -1) return false;
deckStore.decks[index] = deck;
await del(deckName, deckIdb); // 新的名字可能和旧的名字不一样,所以要删除旧的,再添加
await set(deck.deckName, deck, deckIdb);
return true;
},
async add(deck: IDeck): Promise<boolean> {
if (deckStore.decks.find((d) => d.deckName === deck.deckName)) return false;
deckStore.decks.push(deck);
await set(deck.deckName, deck, deckIdb);
return true;
},
async delete(deckName: string): Promise<boolean> {
const index = deckStore.decks.findIndex(
(deck) => deck.deckName === deckName
);
if (index === -1) return false;
deckStore.decks.splice(index, 1);
await del(deckName, deckIdb);
return true;
},
async initialize() {
deckStore.decks = await values<IDeck>(deckIdb);
if (!deckStore.decks.length) {
for (const key in PRESET_DECKS) {
const deck = PRESET_DECKS[key].default;
const deckName =
key.split("/").pop()?.split(".").slice(0, -1).join(".") ??
"undefined"; // 从路径解析文件名
await deckStore.add({ ...deck, deckName });
}
}
},
async reset() {
deckStore.decks = [];
await clear(deckIdb);
},
}) satisfies NeosStore;
export * from "./accountStore"; export * from "./accountStore";
export * from "./cardStore"; export * from "./cardStore";
export * from "./chatStore"; export * from "./chatStore";
export * from "./deckStore";
export * from "./matStore"; export * from "./matStore";
export * from "./placeStore"; export * from "./placeStore";
export * from "./replayStore"; export * from "./replayStore";
...@@ -8,21 +9,27 @@ export * from "./roomStore"; ...@@ -8,21 +9,27 @@ export * from "./roomStore";
import { devtools } from "valtio/utils"; import { devtools } from "valtio/utils";
import { useEnv } from "@/hook";
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 { deckStore } from "./deckStore";
import { matStore } from "./matStore"; import { matStore } from "./matStore";
import { placeStore } from "./placeStore"; import { placeStore } from "./placeStore";
import { replayStore } from "./replayStore"; import { replayStore } from "./replayStore";
import { roomStore } from "./roomStore"; import { roomStore } from "./roomStore";
devtools(chatStore, { name: "chat", enabled: true }); const { DEV } = useEnv();
devtools(matStore, { name: "mat", enabled: true });
devtools(cardStore, { name: "card", enabled: true }); devtools(chatStore, { name: "chat", enabled: DEV });
devtools(placeStore, { name: "place", enabled: true }); devtools(matStore, { name: "mat", enabled: DEV });
devtools(replayStore, { name: "replay", enabled: true }); devtools(cardStore, { name: "card", enabled: DEV });
devtools(accountStore, { name: "account", enabled: true }); devtools(placeStore, { name: "place", enabled: DEV });
devtools(roomStore, { name: "room", enabled: true }); devtools(replayStore, { name: "replay", enabled: DEV });
devtools(accountStore, { name: "account", enabled: DEV });
devtools(roomStore, { name: "room", enabled: DEV });
devtools(deckStore, { name: "deck", enabled: DEV });
// 重置所有`Store` // 重置所有`Store`
export const resetUniverse = () => { export const resetUniverse = () => {
......
...@@ -5,7 +5,7 @@ import { ygopro } from "@/api"; ...@@ -5,7 +5,7 @@ import { ygopro } from "@/api";
import { matStore } from "@/stores"; import { matStore } from "@/stores";
import type { Interactivity } from "./matStore/types"; import type { Interactivity } from "./matStore/types";
import { NeosStore } from "./shared"; import { type NeosStore } from "./shared";
export type PlaceInteractivity = export type PlaceInteractivity =
| Interactivity<{ | Interactivity<{
......
...@@ -2,7 +2,7 @@ import { proxy, ref } from "valtio"; ...@@ -2,7 +2,7 @@ import { proxy, ref } from "valtio";
import { YgoProPacket } from "@/api/ocgcore/ocgAdapter/packet"; import { YgoProPacket } from "@/api/ocgcore/ocgAdapter/packet";
import { NeosStore } from "./shared"; import { type NeosStore } from "./shared";
// 对局中每一次状态改变的记录 // 对局中每一次状态改变的记录
interface ReplaySpot { interface ReplaySpot {
......
...@@ -4,7 +4,7 @@ import { proxy } from "valtio"; ...@@ -4,7 +4,7 @@ import { proxy } from "valtio";
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import StocHsPlayerChange = ygopro.StocHsPlayerChange; import StocHsPlayerChange = ygopro.StocHsPlayerChange;
import SelfType = ygopro.StocTypeChange.SelfType; import SelfType = ygopro.StocTypeChange.SelfType;
import { NeosStore } from "./shared"; import { type NeosStore } from "./shared";
interface Player { interface Player {
name: string; // 玩家的昵称 name: string; // 玩家的昵称
......
...@@ -2,4 +2,5 @@ ...@@ -2,4 +2,5 @@
// 用于统一管理状态的初始化和重置 // 用于统一管理状态的初始化和重置
export interface NeosStore { export interface NeosStore {
reset(): void; reset(): void;
[key: string]: any;
} }
...@@ -4,14 +4,16 @@ import { useSnapshot } from "valtio"; ...@@ -4,14 +4,16 @@ import { useSnapshot } from "valtio";
import { CookieKeys, getCookie } from "@/api"; import { CookieKeys, getCookie } from "@/api";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { accountStore, type User } from "@/stores"; import { accountStore, deckStore, type User } from "@/stores";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export const loader: LoaderFunction = () => { export const loader: LoaderFunction = () => {
const user = getCookie<User>(CookieKeys.USER); const user = getCookie<User>(CookieKeys.USER);
if (user) accountStore.login(user); if (user) accountStore.login(user);
deckStore.initialize();
return null; return null;
}; };
......
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