Commit b8eca8c7 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/migrate/sql.js' into 'main'

Feat/migrate/sql.js

See merge request mycard/Neos!88
parents c598f38d 8287645a
Pipeline #19737 passed with stages
in 4 minutes and 42 seconds
[submodule "neos-protobuf"]
path = neos-protobuf
url = git@git.mycard.moe:mycard/neos-protobuf.git
[submodule "ygopro-database"]
path = ygopro-database
url = git@git.mycard.moe:mycard/ygopro-database.git
......@@ -21,6 +21,7 @@
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@types/react-redux": "^7.1.24",
"@types/sql.js": "^1.4.4",
"antd": "^5.0.7",
"axios": "^0.27.2",
"google-protobuf": "^3.21.0",
......@@ -31,6 +32,7 @@
"react-router-dom": "^6.4.0",
"react-scripts": "^2.1.3",
"socket.io-client": "^4.5.1",
"sql.js": "^1.8.0",
"web-vitals": "^2.1.4"
},
"devDependencies": {
......@@ -2850,6 +2852,11 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz",
"integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig=="
},
"node_modules/@types/emscripten": {
"version": "1.39.6",
"resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz",
"integrity": "sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg=="
},
"node_modules/@types/google-protobuf": {
"version": "3.15.6",
"resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.6.tgz",
......@@ -2935,6 +2942,15 @@
"integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
"dev": true
},
"node_modules/@types/sql.js": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/@types/sql.js/-/sql.js-1.4.4.tgz",
"integrity": "sha512-6EWU2wfiBtzgTy18WQoXZAGTreBjhZcBCfD8CDvyI1Nj0a4KNDDt41IYeAZ40cRUdfqWHb7VGx7t6nK0yBOI5A==",
"dependencies": {
"@types/emscripten": "*",
"@types/node": "*"
}
},
"node_modules/@types/tapable": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz",
......@@ -23527,6 +23543,11 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"node_modules/sql.js": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.8.0.tgz",
"integrity": "sha512-3HD8pSkZL+5YvYUI8nlvNILs61ALqq34xgmF+BHpqxe68yZIJ1H+sIVIODvni25+CcxHUxDyrTJUL0lE/m7afw=="
},
"node_modules/sshpk": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
......@@ -28593,6 +28614,11 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz",
"integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig=="
},
"@types/emscripten": {
"version": "1.39.6",
"resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz",
"integrity": "sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg=="
},
"@types/google-protobuf": {
"version": "3.15.6",
"resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.6.tgz",
......@@ -28678,6 +28704,15 @@
"integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
"dev": true
},
"@types/sql.js": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/@types/sql.js/-/sql.js-1.4.4.tgz",
"integrity": "sha512-6EWU2wfiBtzgTy18WQoXZAGTreBjhZcBCfD8CDvyI1Nj0a4KNDDt41IYeAZ40cRUdfqWHb7VGx7t6nK0yBOI5A==",
"requires": {
"@types/emscripten": "*",
"@types/node": "*"
}
},
"@types/tapable": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz",
......@@ -44718,6 +44753,11 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"sql.js": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.8.0.tgz",
"integrity": "sha512-3HD8pSkZL+5YvYUI8nlvNILs61ALqq34xgmF+BHpqxe68yZIJ1H+sIVIODvni25+CcxHUxDyrTJUL0lE/m7afw=="
},
"sshpk": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
import axios from "axios";
import sqliteMiddleWare, { sqliteCmd } from "../middleware/sqlite";
export interface CardMeta {
id: number;
data: {
ot?: number;
setcode?: number;
type_?: number;
type?: number;
atk?: number;
def?: number;
level?: number;
......@@ -42,7 +43,15 @@ export interface CardMeta {
* @returns 卡片数据
*
* */
export async function fetchCard(id: number): Promise<CardMeta> {
export async function fetchCard(
id: number,
local?: boolean
): Promise<CardMeta> {
if (local) {
return await sqliteMiddleWare({ cmd: sqliteCmd.SELECT, payload: id }).then(
(res) => (res ? res : { id, data: {}, text: {} })
);
}
const res = await axios.get<CardMeta>("http://localhost:3030/cards/" + id);
return res.data;
......
/*
* Sqlite中间件
*
* 用于获取卡牌数据
*
* */
import initSqlJs, { Database } from "sql.js";
import { CardMeta } from "../api/cards";
export enum sqliteCmd {
// 初始化
INIT,
// 读取操作
SELECT,
}
export interface sqliteAction {
cmd: sqliteCmd;
// 初始化DB需要业务方传入的数据
initInfo?: {
dbUrl: string;
};
// 需要读取卡牌数据的ID
payload?: number;
}
let YGODB: Database | null = null;
const sqlPromise = initSqlJs({
locateFile: (file) => `/node_modules/sql.js/dist/${file}`,
});
// FIXME: 应该有个返回值,告诉业务方本次请求的结果,比如初始化DB失败
export default async function (action: sqliteAction) {
switch (action.cmd) {
case sqliteCmd.INIT: {
const info = action.initInfo;
if (info) {
const dataPromise = fetch(info.dbUrl).then((res) => res.arrayBuffer()); // TODO: i18n
const [SQL, buffer] = await Promise.all([sqlPromise, dataPromise]);
YGODB = new SQL.Database(new Uint8Array(buffer));
console.info("YGODB inited!");
} else {
console.warn("init YGODB action without initInfo");
}
break;
}
case sqliteCmd.SELECT: {
if (YGODB && action.payload) {
const code = action.payload;
const dataStmt = YGODB.prepare("SELECT * from datas WHERE ID = $id");
const dataResult = dataStmt.getAsObject({ $id: code });
const textStmt = YGODB.prepare("SELECT * from texts WHERE ID = $id");
const textResult = textStmt.getAsObject({ $id: code });
return constructCardMeta(code, dataResult, textResult);
} else {
console.warn("ygo db not init!");
}
break;
}
default: {
console.warn(`Unhandled sqlite command: ${action.cmd}`);
break;
}
}
}
function constructCardMeta(
id: number,
data: initSqlJs.ParamsObject,
text: initSqlJs.ParamsObject
): CardMeta {
return {
id,
data,
text,
};
}
......@@ -80,7 +80,7 @@ export function createAsyncMetaThunk(name: string): AsyncThunk<
}) => {
const code = param.code;
const meta = await fetchCard(code);
const meta = await fetchCard(code, true);
const response = {
controler: param.controler,
sequence: param.sequence,
......@@ -110,7 +110,7 @@ export function createAsyncRepeatedMetaThunk(
if (id == 0) {
return { id, data: {}, text: {} };
} else {
return await fetchCard(id);
return await fetchCard(id, true);
}
})
);
......
......@@ -29,7 +29,7 @@ export const fetchSelectPlaceHintMeta = createAsyncThunk(
const player = param[0];
const hintData = param[1];
const hintMeta = (await fetchCard(hintData)).text.name || "[?]";
const hintMeta = (await fetchCard(hintData, true)).text.name || "[?]";
const response: [number, string] = [player, hintMeta];
return response;
......
......@@ -58,7 +58,7 @@ export const fetchCheckCardMeta = createAsyncThunk(
tagName: string;
option: { code: number; response: number; effectDescCode?: number };
}) => {
const meta = await fetchCard(param.option.code);
const meta = await fetchCard(param.option.code, true);
const effectDesc = param.option.effectDescCode
? getCardStr(meta, param.option.effectDescCode & 0xf)
: undefined;
......
......@@ -59,7 +59,7 @@ export const fetchCheckCardMetasV2 = createAsyncThunk(
}) => {
const metas = await Promise.all(
param.options.map(async (option) => {
return await fetchCard(option.code);
return await fetchCard(option.code, true);
})
);
const response = {
......
......@@ -23,7 +23,7 @@ export const resetOptionModalImpl: CaseReducer<DuelState> = (state) => {
export const fetchOptionMeta = createAsyncThunk(
"duel/fetchOptionMeta",
async (param: { code: number; response: number }) => {
const meta = await fetchCard(param.code >> 4);
const meta = await fetchCard(param.code >> 4, true);
const msg = getCardStr(meta, param.code & 0xf) || "[?]";
const response = { msg, response: param.response };
......
......@@ -32,7 +32,7 @@ export const fetchYesNoMeta = createAsyncThunk(
) => string;
}) => {
const desc = await fetchStrings("!system", param.descCode);
const meta = await fetchCard(param.code);
const meta = await fetchCard(param.code, true);
// TODO: 国际化文案
return param.textGenerator(desc, meta, param.location);
......
......@@ -21,6 +21,7 @@ import {
sendHsStart,
} from "../api/ocgcore/ocgHelper";
import socketMiddleWare, { socketCmd } from "../middleware/socket";
import sqliteMiddleWare, { sqliteCmd } from "../middleware/sqlite";
import { Button } from "antd";
const READY_STATE = "ready";
......@@ -47,6 +48,12 @@ export default function WaitRoom() {
},
});
}
// 初始化sqlite
sqliteMiddleWare({
cmd: sqliteCmd.INIT,
initInfo: { dbUrl: "/ygopro-database/locales/zh-CN/cards.cdb" },
});
}, []);
const joined = useAppSelector(selectJoined);
......
Subproject commit 97dc1a6bbb51d55a2cabb1524ea2aa39521cd26e
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