Commit 57609714 authored by Chunchi Che's avatar Chunchi Che

Neos支持MC超先行服

parent 85be971f
{ {
"version":4960, "version": 4960,
"servers":[ "servers": [{
{ "name": "koishi",
"name":"koishi", "ip": "koishi.momobako.com",
"ip":"koishi.momobako.com", "port": "7211"
"port":"7211" },
}, {
{ "name": "mycard-athletic",
"name":"mycard-athletic", "ip": "tiramisu.moecube.com",
"ip":"tiramisu.moecube.com", "port": "8912"
"port":"8912" },
} {
], "name": "pre-release",
"assetsPath":"/neos-assets", "ip": "koishi.momobako.com",
"cardImgUrl":"https://cdn02.moecube.com:444/images/ygopro-images-zh-CN", "port": "889"
"cardsDbUrl":"https://cdn02.moecube.com:444/ygopro-database/zh-CN/cards.cdb", }
"stringsUrl":"https://cdn02.moecube.com:444/ygopro-database/zh-CN/strings.conf", ],
"lflistUrl":"https://cdn02.moecube.com:444/ygopro-database/zh-CN/lflist.conf", "assetsPath": "/neos-assets",
"replayUrl":"replay.neos.moe", "releaseImgUrl": "https://cdn02.moecube.com:444/images/ygopro-images-zh-CN",
"loginUrl":"https://accounts.moecube.com/signin", "preReleaseImgUrl": "https://cdn02.moecube.com:444/ygopro-super-pre/data/pics",
"logoutUrl":"https://accounts.moecube.com/signout", "releaseDbUrl": "https://cdn02.moecube.com:444/ygopro-database/zh-CN/cards.cdb",
"profileUrl":"https://accounts.moecube.com/profiles", "preReleaseDbUrl": "https://cdn02.moecube.com:444/ygopro-super-pre/data/test-release.cdb",
"athleticWatchUrl":"wss://tiramisu.moecube.com:8923", "stringsUrl": "https://cdn02.moecube.com:444/ygopro-database/zh-CN/strings.conf",
"entertainWatchUrl":"wss://tiramisu.moecube.com:7923", "lflistUrl": "https://cdn02.moecube.com:444/ygopro-database/zh-CN/lflist.conf",
"userApi":"https://sapi.moecube.com:444/accounts/users/{username}.json", "replayUrl": "replay.neos.moe",
"streamInterval":20, "loginUrl": "https://accounts.moecube.com/signin",
"startDelay":1000, "logoutUrl": "https://accounts.moecube.com/signout",
"ui":{ "profileUrl": "https://accounts.moecube.com/profiles",
"hint":{ "athleticWatchUrl": "wss://tiramisu.moecube.com:8923",
"maxCount":1 "entertainWatchUrl": "wss://tiramisu.moecube.com:7923",
} "userApi": "https://sapi.moecube.com:444/accounts/users/{username}.json",
}, "streamInterval": 20,
"unimplementedWhiteList":[ "startDelay": 1000,
1, "ui": {
6, "hint": {
7, "maxCount": 1
34, }
54, },
55, "unimplementedWhiteList": [
56, 1,
60, 6,
61, 7,
62, 34,
63, 54,
64, 55,
65, 56,
70, 60,
71, 61,
72, 62,
73, 63,
74, 64,
75, 65,
76, 70,
80, 71,
81, 72,
83, 73,
93, 74,
95, 75,
96, 76,
97, 80,
101, 81,
102, 83,
110, 93,
111, 95,
112, 96,
113, 97,
114, 101,
120, 102,
121, 110,
122, 111,
123, 112,
130, 113,
131, 114,
132, 120,
133, 121,
160, 122,
161, 123,
163, 130,
164, 131,
165, 132,
170, 133,
180, 160,
230, 161,
231, 163,
236 164,
] 165,
170,
180,
230,
231,
236
]
} }
{ {
"version":4960, "version": 4960,
"servers":[ "servers": [{
{ "name": "koishi",
"name":"koishi", "ip": "koishi.momobako.com",
"ip":"koishi.momobako.com", "port": "7211"
"port":"7211" },
}, {
{ "name": "mycard-athletic",
"name":"mycard-athletic", "ip": "tiramisu.moecube.com",
"ip":"tiramisu.moecube.com", "port": "8912"
"port":"8912" },
} {
], "name": "pre-release",
"assetsPath":"/neos-assets", "ip": "koishi.momobako.com",
"cardImgUrl":"https://cdn02.moecube.com:444/images/ygopro-images-zh-CN", "port": "889"
"cardsDbUrl":"https://cdn02.moecube.com:444/ygopro-database/zh-CN/cards.cdb", }
"stringsUrl":"https://cdn02.moecube.com:444/ygopro-database/zh-CN/strings.conf", ],
"lflistUrl":"https://cdn02.moecube.com:444/ygopro-database/zh-CN/lflist.conf", "assetsPath": "/neos-assets",
"replayUrl":"replay.neos.moe", "releaseImgUrl": "https://cdn02.moecube.com:444/images/ygopro-images-zh-CN",
"loginUrl":"https://accounts.moecube.com/signin", "preReleaseImgUrl": "https://cdn02.moecube.com:444/ygopro-super-pre/data/pics",
"logoutUrl":"https://accounts.moecube.com/signout", "releaseDbUrl": "https://cdn02.moecube.com:444/ygopro-database/zh-CN/cards.cdb",
"profileUrl":"https://accounts.moecube.com/profiles", "preReleaseDbUrl": "https://cdn02.moecube.com:444/ygopro-super-pre/data/test-release.cdb",
"athleticWatchUrl":"wss://tiramisu.moecube.com:8923", "stringsUrl": "https://cdn02.moecube.com:444/ygopro-database/zh-CN/strings.conf",
"entertainWatchUrl":"wss://tiramisu.moecube.com:7923", "lflistUrl": "https://cdn02.moecube.com:444/ygopro-database/zh-CN/lflist.conf",
"userApi":"https://sapi.moecube.com:444/accounts/users/{username}.json", "replayUrl": "replay.neos.moe",
"streamInterval":20, "loginUrl": "https://accounts.moecube.com/signin",
"startDelay":1000, "logoutUrl": "https://accounts.moecube.com/signout",
"ui":{ "profileUrl": "https://accounts.moecube.com/profiles",
"hint":{ "athleticWatchUrl": "wss://tiramisu.moecube.com:8923",
"maxCount":1 "entertainWatchUrl": "wss://tiramisu.moecube.com:7923",
} "userApi": "https://sapi.moecube.com:444/accounts/users/{username}.json",
}, "streamInterval": 20,
"unimplementedWhiteList":[ "startDelay": 1000,
1, "ui": {
6, "hint": {
7, "maxCount": 1
34, }
54, },
55, "unimplementedWhiteList": [
56, 1,
60, 6,
61, 7,
62, 34,
63, 54,
64, 55,
65, 56,
70, 60,
71, 61,
72, 62,
73, 63,
74, 64,
75, 65,
76, 70,
80, 71,
81, 72,
83, 73,
93, 74,
95, 75,
96, 76,
97, 80,
101, 81,
102, 83,
110, 93,
111, 95,
112, 96,
113, 97,
114, 101,
120, 102,
121, 110,
122, 111,
123, 112,
130, 113,
131, 114,
132, 120,
133, 121,
160, 122,
161, 123,
163, 130,
164, 131,
165, 132,
170, 133,
180, 160,
230, 161,
231, 163,
236 164,
] 165,
170,
180,
230,
231,
236
]
} }
...@@ -10,6 +10,7 @@ import initSqlJs, { Database } from "sql.js"; ...@@ -10,6 +10,7 @@ import initSqlJs, { Database } from "sql.js";
import { CardData, CardMeta, CardText } from "@/api/cards"; import { CardData, CardMeta, CardText } from "@/api/cards";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { pfetch } from "@/infra"; import { pfetch } from "@/infra";
import { isSuperReleaseCard } from "@/superPreRelease";
import { FtsParams, invokeFts } from "./fts"; import { FtsParams, invokeFts } from "./fts";
...@@ -28,7 +29,8 @@ export interface sqliteAction<T extends sqliteCmd> { ...@@ -28,7 +29,8 @@ export interface sqliteAction<T extends sqliteCmd> {
cmd: T; cmd: T;
// 初始化DB需要业务方传入的数据 // 初始化DB需要业务方传入的数据
initInfo?: { initInfo?: {
dbUrl: string; releaseDbUrl: string;
preReleaseDbUrl: string;
progressCallback?: (progress: number) => void; // 用于获取读取进度 progressCallback?: (progress: number) => void; // 用于获取读取进度
}; };
payload?: { payload?: {
...@@ -42,7 +44,6 @@ export interface sqliteResult { ...@@ -42,7 +44,6 @@ export interface sqliteResult {
ftsResult?: CardMeta[]; ftsResult?: CardMeta[];
} }
let YGODB: Database | null = null;
const sqlPromise = initSqlJs({ const sqlPromise = initSqlJs({
locateFile: (file) => `${NeosConfig.assetsPath}/${file}`, locateFile: (file) => `${NeosConfig.assetsPath}/${file}`,
}); });
...@@ -53,17 +54,37 @@ export default function <T extends sqliteCmd>( ...@@ -53,17 +54,37 @@ export default function <T extends sqliteCmd>(
return helper(action) as any; return helper(action) as any;
} }
// TODO: may defining a class be better?
interface YgoDbs {
release: Database | null;
preRelease: Database | null;
}
let YGODBS: YgoDbs = { release: null, preRelease: null };
// FIXME: 应该有个返回值,告诉业务方本次请求的结果,比如初始化DB失败 // FIXME: 应该有个返回值,告诉业务方本次请求的结果,比如初始化DB失败
function helper<T extends sqliteCmd>(action: sqliteAction<T>) { function helper<T extends sqliteCmd>(action: sqliteAction<T>) {
switch (action.cmd) { switch (action.cmd) {
case sqliteCmd.INIT: { case sqliteCmd.INIT: {
const info = action.initInfo; const info = action.initInfo;
if (info) { if (info) {
const dataPromise = pfetch(info.dbUrl, { const releasePromise = pfetch(info.releaseDbUrl, {
progressCallback: action.initInfo?.progressCallback, progressCallback: action.initInfo?.progressCallback,
}).then((res) => res.arrayBuffer()); // TODO: i18n }).then((res) => res.arrayBuffer()); // TODO: i18n
return Promise.all([sqlPromise, dataPromise]).then(([SQL, buffer]) => { const preReleasePromise = pfetch(info.preReleaseDbUrl, {
YGODB = new SQL.Database(new Uint8Array(buffer)); progressCallback: action.initInfo?.progressCallback,
}).then((res) => res.arrayBuffer());
return Promise.all([
sqlPromise,
releasePromise,
preReleasePromise,
]).then(([SQL, releaseBuffer, preReleaseBuffer]) => {
YGODBS.release = new SQL.Database(new Uint8Array(releaseBuffer));
YGODBS.preRelease = new SQL.Database(
new Uint8Array(preReleaseBuffer),
);
console.log("YGODB inited!"); console.log("YGODB inited!");
}); });
} else { } else {
...@@ -72,12 +93,21 @@ function helper<T extends sqliteCmd>(action: sqliteAction<T>) { ...@@ -72,12 +93,21 @@ function helper<T extends sqliteCmd>(action: sqliteAction<T>) {
} }
} }
case sqliteCmd.SELECT: { case sqliteCmd.SELECT: {
if (YGODB && action.payload && action.payload.id) { if (
YGODBS.release &&
YGODBS.preRelease &&
action.payload &&
action.payload.id
) {
const code = action.payload.id; const code = action.payload.id;
const dataStmt = YGODB.prepare("SELECT * FROM datas WHERE ID = $id"); const db = isSuperReleaseCard(code)
? YGODBS.preRelease
: YGODBS.release;
const dataStmt = db.prepare("SELECT * FROM datas WHERE ID = $id");
const dataResult = dataStmt.getAsObject({ $id: code }); const dataResult = dataStmt.getAsObject({ $id: code });
const textStmt = YGODB.prepare("SELECT * FROM texts WHERE ID = $id"); const textStmt = db.prepare("SELECT * FROM texts WHERE ID = $id");
const textResult = textStmt.getAsObject({ $id: code }); const textResult = textStmt.getAsObject({ $id: code });
return { return {
...@@ -93,8 +123,22 @@ function helper<T extends sqliteCmd>(action: sqliteAction<T>) { ...@@ -93,8 +123,22 @@ function helper<T extends sqliteCmd>(action: sqliteAction<T>) {
return {}; return {};
} }
case sqliteCmd.FTS: { case sqliteCmd.FTS: {
if (YGODB && action.payload && action.payload.ftsParams) { if (
const metas = invokeFts(YGODB, action.payload.ftsParams); YGODBS.release &&
YGODBS.preRelease &&
action.payload &&
action.payload.ftsParams
) {
const releaseMetas = invokeFts(
YGODBS.release,
action.payload.ftsParams,
);
const preReleaseMetas = invokeFts(
YGODBS.preRelease,
action.payload.ftsParams,
);
const metas = releaseMetas.concat(preReleaseMetas);
return { ftsResult: metas }; return { ftsResult: metas };
} else { } else {
......
import SuperReleaseData from "../../super-pre-release.json";
export function isSuperReleaseCard(code: number): boolean {
return SuperReleaseData.find((id) => id === code) !== undefined;
}
...@@ -22,12 +22,10 @@ import { proxy, useSnapshot } from "valtio"; ...@@ -22,12 +22,10 @@ import { proxy, useSnapshot } from "valtio";
import { sendSortCardResponse } from "@/api"; import { sendSortCardResponse } from "@/api";
import { CardMeta } from "@/api/cards"; import { CardMeta } from "@/api/cards";
import { useConfig } from "@/config"; import { getCardImgUrl } from "@/ui/Shared";
import { NeosModal } from "./NeosModal"; import { NeosModal } from "./NeosModal";
const NeosConfig = useConfig();
interface SortOption { interface SortOption {
meta: CardMeta; meta: CardMeta;
response: number; response: number;
...@@ -118,7 +116,7 @@ const SortableItem = (props: { id: number; meta: CardMeta }) => { ...@@ -118,7 +116,7 @@ const SortableItem = (props: { id: number; meta: CardMeta }) => {
cover={ cover={
<img <img
alt={props.meta.id.toString()} alt={props.meta.id.toString()}
src={`${NeosConfig.cardImgUrl}/${props.meta.id}.jpg`} src={getCardImgUrl(props.meta.id)}
/> />
} }
/> />
......
...@@ -11,7 +11,7 @@ import { useConfig } from "@/config"; ...@@ -11,7 +11,7 @@ import { useConfig } from "@/config";
import { useEnv } from "@/hook"; import { useEnv } from "@/hook";
import sqliteMiddleWare, { sqliteCmd } from "@/middleware/sqlite"; import sqliteMiddleWare, { sqliteCmd } from "@/middleware/sqlite";
import { accountStore, deckStore, initStore, type User } from "@/stores"; import { accountStore, deckStore, initStore, type User } from "@/stores";
const { cardsDbUrl } = useConfig(); const { releaseDbUrl, preReleaseDbUrl } = useConfig();
const { BASE_URL } = useEnv(); const { BASE_URL } = useEnv();
/** 加载ygodb */ /** 加载ygodb */
...@@ -23,7 +23,7 @@ export const initSqlite = async () => { ...@@ -23,7 +23,7 @@ export const initSqlite = async () => {
sqlite.progress = 0.01; sqlite.progress = 0.01;
await sqliteMiddleWare({ await sqliteMiddleWare({
cmd: sqliteCmd.INIT, cmd: sqliteCmd.INIT,
initInfo: { dbUrl: cardsDbUrl, progressCallback }, initInfo: { releaseDbUrl, preReleaseDbUrl, progressCallback },
}); });
sqlite.progress = 1; sqlite.progress = 1;
} }
......
...@@ -11,4 +11,8 @@ ...@@ -11,4 +11,8 @@
height: 3rem; height: 3rem;
margin: 0.25rem; margin: 0.25rem;
} }
.select {
margin: 0.25rem 0;
}
} }
...@@ -5,12 +5,17 @@ import { proxy, useSnapshot } from "valtio"; ...@@ -5,12 +5,17 @@ import { proxy, useSnapshot } from "valtio";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { accountStore, roomStore } from "@/stores"; import { accountStore, roomStore } from "@/stores";
import { Select } from "@/ui/Shared";
import styles from "./MatchModal.module.scss"; import styles from "./MatchModal.module.scss";
import { connectSrvpro } from "./util"; import { connectSrvpro } from "./util";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
const serverConfig = NeosConfig.servers; const serverConfig = NeosConfig.servers;
const KOISHI = "koishi";
const PRERELEASE = "pre-release";
const { const {
defaults: { defaultPlayer, defaultPassword }, defaults: { defaultPlayer, defaultPassword },
automation: { isAiMode }, automation: { isAiMode },
...@@ -33,17 +38,26 @@ export const MatchModal: React.FC = ({}) => { ...@@ -33,17 +38,26 @@ export const MatchModal: React.FC = ({}) => {
const { joined, errorMsg } = useSnapshot(roomStore); const { joined, errorMsg } = useSnapshot(roomStore);
const [player, setPlayer] = useState(user?.name ?? defaultPlayer); const [player, setPlayer] = useState(user?.name ?? defaultPlayer);
const [passwd, setPasswd] = useState(defaultPassword); const [passwd, setPasswd] = useState(defaultPassword);
const [server, setServer] = useState( const [serverId, setServerId] = useState(0);
`${serverConfig[0].ip}:${serverConfig[0].port}`,
);
const [confirmLoading, setConfirmLoading] = useState(false); const [confirmLoading, setConfirmLoading] = useState(false);
const navigate = useNavigate(); const navigate = useNavigate();
let handlePlayerChange = (event: ChangeEvent<HTMLInputElement>) => { let handlePlayerChange = (event: ChangeEvent<HTMLInputElement>) => {
setPlayer(event.target.value); setPlayer(event.target.value);
}; };
let handleServerChange = (event: ChangeEvent<HTMLInputElement>) => { let handleServerChange = (value: any) => {
setServer(event.target.value); switch (value) {
case KOISHI: {
setServerId(0);
break;
}
case PRERELEASE: {
setServerId(2);
break;
}
default:
break;
}
}; };
let handlePasswdChange = (event: ChangeEvent<HTMLInputElement>) => { let handlePasswdChange = (event: ChangeEvent<HTMLInputElement>) => {
setPasswd(event.target.value); setPasswd(event.target.value);
...@@ -51,7 +65,11 @@ export const MatchModal: React.FC = ({}) => { ...@@ -51,7 +65,11 @@ export const MatchModal: React.FC = ({}) => {
const handleSubmit = async () => { const handleSubmit = async () => {
setConfirmLoading(true); setConfirmLoading(true);
await connectSrvpro({ player, ip: server, passWd: passwd }); await connectSrvpro({
player,
ip: genServerAddress(serverId),
passWd: passwd,
});
}; };
useEffect(() => { useEffect(() => {
...@@ -91,6 +109,22 @@ export const MatchModal: React.FC = ({}) => { ...@@ -91,6 +109,22 @@ export const MatchModal: React.FC = ({}) => {
centered centered
> >
<div className={styles["inputs-container"]}> <div className={styles["inputs-container"]}>
<Select
className={styles.select}
title="服务器"
value={KOISHI}
options={[
{
value: KOISHI,
label: "Koishi服",
},
{
value: PRERELEASE,
label: "超先行服",
},
]}
onChange={handleServerChange}
/>
<Input <Input
className={styles.input} className={styles.input}
type="text" type="text"
...@@ -99,14 +133,6 @@ export const MatchModal: React.FC = ({}) => { ...@@ -99,14 +133,6 @@ export const MatchModal: React.FC = ({}) => {
onChange={handlePlayerChange} onChange={handlePlayerChange}
required required
/> />
<Input
className={styles.input}
type="text"
placeholder="服务器(IP+端口)"
value={server}
onChange={handleServerChange}
required
/>
<Input <Input
className={styles.input} className={styles.input}
type="text" type="text"
...@@ -119,3 +145,7 @@ export const MatchModal: React.FC = ({}) => { ...@@ -119,3 +145,7 @@ export const MatchModal: React.FC = ({}) => {
</Modal> </Modal>
); );
}; };
const genServerAddress = (id: number) => {
return `${serverConfig[id].ip}:${serverConfig[id].port}`;
};
...@@ -26,7 +26,10 @@ export const connectSrvpro = async (params: { ...@@ -26,7 +26,10 @@ export const connectSrvpro = async (params: {
// 初始化sqlite // 初始化sqlite
await sqliteMiddleWare({ await sqliteMiddleWare({
cmd: sqliteCmd.INIT, cmd: sqliteCmd.INIT,
initInfo: { dbUrl: NeosConfig.cardsDbUrl }, initInfo: {
releaseDbUrl: NeosConfig.releaseDbUrl,
preReleaseDbUrl: NeosConfig.preReleaseDbUrl,
},
}); });
// 初始化I18N文案 // 初始化I18N文案
......
...@@ -2,6 +2,7 @@ import classNames from "classnames"; ...@@ -2,6 +2,7 @@ import classNames from "classnames";
import { CSSProperties, useMemo } from "react"; import { CSSProperties, useMemo } from "react";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { isSuperReleaseCard } from "@/superPreRelease";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
...@@ -60,5 +61,10 @@ export function getCardImgUrl(code: number, back = false) { ...@@ -60,5 +61,10 @@ export function getCardImgUrl(code: number, back = false) {
if (back || code === 0) { if (back || code === 0) {
return `${ASSETS_BASE}/card_back.jpg`; return `${ASSETS_BASE}/card_back.jpg`;
} }
return `${NeosConfig.cardImgUrl}/${code}.jpg`;
if (isSuperReleaseCard(code)) {
return `${NeosConfig.preReleaseImgUrl}/${code}.jpg`;
} else {
return `${NeosConfig.releaseImgUrl}/${code}.jpg`;
}
} }
[
100219001,
100219002,
100200251,
101205000,
101205001,
101205002,
101205003,
101205004,
101205005,
101205006,
101205033,
101205053,
101205054,
101205055,
101205068,
101205069,
101203081,
101203082,
101203083,
101203084,
101203085,
101203086,
101203087,
101203088,
101203089,
101203090,
101203091,
101203092,
101203093,
101203094,
101203095,
101203096,
100216001
]
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