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"] [submodule "neos-protobuf"]
path = neos-protobuf path = neos-protobuf
url = git@git.mycard.moe:mycard/neos-protobuf.git 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 @@ ...@@ -21,6 +21,7 @@
"@types/react": "^18.0.17", "@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@types/react-redux": "^7.1.24", "@types/react-redux": "^7.1.24",
"@types/sql.js": "^1.4.4",
"antd": "^5.0.7", "antd": "^5.0.7",
"axios": "^0.27.2", "axios": "^0.27.2",
"google-protobuf": "^3.21.0", "google-protobuf": "^3.21.0",
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
"react-router-dom": "^6.4.0", "react-router-dom": "^6.4.0",
"react-scripts": "^2.1.3", "react-scripts": "^2.1.3",
"socket.io-client": "^4.5.1", "socket.io-client": "^4.5.1",
"sql.js": "^1.8.0",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"devDependencies": { "devDependencies": {
...@@ -2850,6 +2852,11 @@ ...@@ -2850,6 +2852,11 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz",
"integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" "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": { "node_modules/@types/google-protobuf": {
"version": "3.15.6", "version": "3.15.6",
"resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.6.tgz", "resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.6.tgz",
...@@ -2935,6 +2942,15 @@ ...@@ -2935,6 +2942,15 @@
"integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==", "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
"dev": true "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": { "node_modules/@types/tapable": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz",
...@@ -23527,6 +23543,11 @@ ...@@ -23527,6 +23543,11 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" "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": { "node_modules/sshpk": {
"version": "1.17.0", "version": "1.17.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
...@@ -28593,6 +28614,11 @@ ...@@ -28593,6 +28614,11 @@
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz",
"integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" "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": { "@types/google-protobuf": {
"version": "3.15.6", "version": "3.15.6",
"resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.6.tgz", "resolved": "https://registry.npmjs.org/@types/google-protobuf/-/google-protobuf-3.15.6.tgz",
...@@ -28678,6 +28704,15 @@ ...@@ -28678,6 +28704,15 @@
"integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==", "integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
"dev": true "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": { "@types/tapable": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.2.tgz",
...@@ -44718,6 +44753,11 @@ ...@@ -44718,6 +44753,11 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" "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": { "sshpk": {
"version": "1.17.0", "version": "1.17.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
import axios from "axios"; import axios from "axios";
import sqliteMiddleWare, { sqliteCmd } from "../middleware/sqlite";
export interface CardMeta { export interface CardMeta {
id: number; id: number;
data: { data: {
ot?: number; ot?: number;
setcode?: number; setcode?: number;
type_?: number; type?: number;
atk?: number; atk?: number;
def?: number; def?: number;
level?: number; level?: number;
...@@ -42,7 +43,15 @@ export interface CardMeta { ...@@ -42,7 +43,15 @@ export interface CardMeta {
* @returns 卡片数据 * @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); const res = await axios.get<CardMeta>("http://localhost:3030/cards/" + id);
return res.data; 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< ...@@ -80,7 +80,7 @@ export function createAsyncMetaThunk(name: string): AsyncThunk<
}) => { }) => {
const code = param.code; const code = param.code;
const meta = await fetchCard(code); const meta = await fetchCard(code, true);
const response = { const response = {
controler: param.controler, controler: param.controler,
sequence: param.sequence, sequence: param.sequence,
...@@ -110,7 +110,7 @@ export function createAsyncRepeatedMetaThunk( ...@@ -110,7 +110,7 @@ export function createAsyncRepeatedMetaThunk(
if (id == 0) { if (id == 0) {
return { id, data: {}, text: {} }; return { id, data: {}, text: {} };
} else { } else {
return await fetchCard(id); return await fetchCard(id, true);
} }
}) })
); );
......
...@@ -29,7 +29,7 @@ export const fetchSelectPlaceHintMeta = createAsyncThunk( ...@@ -29,7 +29,7 @@ export const fetchSelectPlaceHintMeta = createAsyncThunk(
const player = param[0]; const player = param[0];
const hintData = param[1]; 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]; const response: [number, string] = [player, hintMeta];
return response; return response;
......
...@@ -58,7 +58,7 @@ export const fetchCheckCardMeta = createAsyncThunk( ...@@ -58,7 +58,7 @@ export const fetchCheckCardMeta = createAsyncThunk(
tagName: string; tagName: string;
option: { code: number; response: number; effectDescCode?: number }; 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 const effectDesc = param.option.effectDescCode
? getCardStr(meta, param.option.effectDescCode & 0xf) ? getCardStr(meta, param.option.effectDescCode & 0xf)
: undefined; : undefined;
......
...@@ -59,7 +59,7 @@ export const fetchCheckCardMetasV2 = createAsyncThunk( ...@@ -59,7 +59,7 @@ export const fetchCheckCardMetasV2 = createAsyncThunk(
}) => { }) => {
const metas = await Promise.all( const metas = await Promise.all(
param.options.map(async (option) => { param.options.map(async (option) => {
return await fetchCard(option.code); return await fetchCard(option.code, true);
}) })
); );
const response = { const response = {
......
...@@ -23,7 +23,7 @@ export const resetOptionModalImpl: CaseReducer<DuelState> = (state) => { ...@@ -23,7 +23,7 @@ export const resetOptionModalImpl: CaseReducer<DuelState> = (state) => {
export const fetchOptionMeta = createAsyncThunk( export const fetchOptionMeta = createAsyncThunk(
"duel/fetchOptionMeta", "duel/fetchOptionMeta",
async (param: { code: number; response: number }) => { 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 msg = getCardStr(meta, param.code & 0xf) || "[?]";
const response = { msg, response: param.response }; const response = { msg, response: param.response };
......
...@@ -32,7 +32,7 @@ export const fetchYesNoMeta = createAsyncThunk( ...@@ -32,7 +32,7 @@ export const fetchYesNoMeta = createAsyncThunk(
) => string; ) => string;
}) => { }) => {
const desc = await fetchStrings("!system", param.descCode); const desc = await fetchStrings("!system", param.descCode);
const meta = await fetchCard(param.code); const meta = await fetchCard(param.code, true);
// TODO: 国际化文案 // TODO: 国际化文案
return param.textGenerator(desc, meta, param.location); return param.textGenerator(desc, meta, param.location);
......
...@@ -21,6 +21,7 @@ import { ...@@ -21,6 +21,7 @@ import {
sendHsStart, sendHsStart,
} from "../api/ocgcore/ocgHelper"; } from "../api/ocgcore/ocgHelper";
import socketMiddleWare, { socketCmd } from "../middleware/socket"; import socketMiddleWare, { socketCmd } from "../middleware/socket";
import sqliteMiddleWare, { sqliteCmd } from "../middleware/sqlite";
import { Button } from "antd"; import { Button } from "antd";
const READY_STATE = "ready"; const READY_STATE = "ready";
...@@ -47,6 +48,12 @@ export default function WaitRoom() { ...@@ -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); const joined = useAppSelector(selectJoined);
......
ygopro-database @ 97dc1a6b
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