Commit 53342352 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'super-pre-release' into 'main'

Neos支持MC超先行服

See merge request mycard/Neos!338
parents 85be971f 57609714
{
"version":4960,
"servers":[
"version": 4960,
"servers": [{
"name": "koishi",
"ip": "koishi.momobako.com",
"port": "7211"
},
{
"name":"koishi",
"ip":"koishi.momobako.com",
"port":"7211"
"name": "mycard-athletic",
"ip": "tiramisu.moecube.com",
"port": "8912"
},
{
"name":"mycard-athletic",
"ip":"tiramisu.moecube.com",
"port":"8912"
"name": "pre-release",
"ip": "koishi.momobako.com",
"port": "889"
}
],
"assetsPath":"/neos-assets",
"cardImgUrl":"https://cdn02.moecube.com:444/images/ygopro-images-zh-CN",
"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",
"replayUrl":"replay.neos.moe",
"loginUrl":"https://accounts.moecube.com/signin",
"logoutUrl":"https://accounts.moecube.com/signout",
"profileUrl":"https://accounts.moecube.com/profiles",
"athleticWatchUrl":"wss://tiramisu.moecube.com:8923",
"entertainWatchUrl":"wss://tiramisu.moecube.com:7923",
"userApi":"https://sapi.moecube.com:444/accounts/users/{username}.json",
"streamInterval":20,
"startDelay":1000,
"ui":{
"hint":{
"maxCount":1
"assetsPath": "/neos-assets",
"releaseImgUrl": "https://cdn02.moecube.com:444/images/ygopro-images-zh-CN",
"preReleaseImgUrl": "https://cdn02.moecube.com:444/ygopro-super-pre/data/pics",
"releaseDbUrl": "https://cdn02.moecube.com:444/ygopro-database/zh-CN/cards.cdb",
"preReleaseDbUrl": "https://cdn02.moecube.com:444/ygopro-super-pre/data/test-release.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",
"replayUrl": "replay.neos.moe",
"loginUrl": "https://accounts.moecube.com/signin",
"logoutUrl": "https://accounts.moecube.com/signout",
"profileUrl": "https://accounts.moecube.com/profiles",
"athleticWatchUrl": "wss://tiramisu.moecube.com:8923",
"entertainWatchUrl": "wss://tiramisu.moecube.com:7923",
"userApi": "https://sapi.moecube.com:444/accounts/users/{username}.json",
"streamInterval": 20,
"startDelay": 1000,
"ui": {
"hint": {
"maxCount": 1
}
},
"unimplementedWhiteList":[
"unimplementedWhiteList": [
1,
6,
7,
......
{
"version":4960,
"servers":[
"version": 4960,
"servers": [{
"name": "koishi",
"ip": "koishi.momobako.com",
"port": "7211"
},
{
"name":"koishi",
"ip":"koishi.momobako.com",
"port":"7211"
"name": "mycard-athletic",
"ip": "tiramisu.moecube.com",
"port": "8912"
},
{
"name":"mycard-athletic",
"ip":"tiramisu.moecube.com",
"port":"8912"
"name": "pre-release",
"ip": "koishi.momobako.com",
"port": "889"
}
],
"assetsPath":"/neos-assets",
"cardImgUrl":"https://cdn02.moecube.com:444/images/ygopro-images-zh-CN",
"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",
"replayUrl":"replay.neos.moe",
"loginUrl":"https://accounts.moecube.com/signin",
"logoutUrl":"https://accounts.moecube.com/signout",
"profileUrl":"https://accounts.moecube.com/profiles",
"athleticWatchUrl":"wss://tiramisu.moecube.com:8923",
"entertainWatchUrl":"wss://tiramisu.moecube.com:7923",
"userApi":"https://sapi.moecube.com:444/accounts/users/{username}.json",
"streamInterval":20,
"startDelay":1000,
"ui":{
"hint":{
"maxCount":1
"assetsPath": "/neos-assets",
"releaseImgUrl": "https://cdn02.moecube.com:444/images/ygopro-images-zh-CN",
"preReleaseImgUrl": "https://cdn02.moecube.com:444/ygopro-super-pre/data/pics",
"releaseDbUrl": "https://cdn02.moecube.com:444/ygopro-database/zh-CN/cards.cdb",
"preReleaseDbUrl": "https://cdn02.moecube.com:444/ygopro-super-pre/data/test-release.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",
"replayUrl": "replay.neos.moe",
"loginUrl": "https://accounts.moecube.com/signin",
"logoutUrl": "https://accounts.moecube.com/signout",
"profileUrl": "https://accounts.moecube.com/profiles",
"athleticWatchUrl": "wss://tiramisu.moecube.com:8923",
"entertainWatchUrl": "wss://tiramisu.moecube.com:7923",
"userApi": "https://sapi.moecube.com:444/accounts/users/{username}.json",
"streamInterval": 20,
"startDelay": 1000,
"ui": {
"hint": {
"maxCount": 1
}
},
"unimplementedWhiteList":[
"unimplementedWhiteList": [
1,
6,
7,
......
......@@ -10,6 +10,7 @@ import initSqlJs, { Database } from "sql.js";
import { CardData, CardMeta, CardText } from "@/api/cards";
import { useConfig } from "@/config";
import { pfetch } from "@/infra";
import { isSuperReleaseCard } from "@/superPreRelease";
import { FtsParams, invokeFts } from "./fts";
......@@ -28,7 +29,8 @@ export interface sqliteAction<T extends sqliteCmd> {
cmd: T;
// 初始化DB需要业务方传入的数据
initInfo?: {
dbUrl: string;
releaseDbUrl: string;
preReleaseDbUrl: string;
progressCallback?: (progress: number) => void; // 用于获取读取进度
};
payload?: {
......@@ -42,7 +44,6 @@ export interface sqliteResult {
ftsResult?: CardMeta[];
}
let YGODB: Database | null = null;
const sqlPromise = initSqlJs({
locateFile: (file) => `${NeosConfig.assetsPath}/${file}`,
});
......@@ -53,17 +54,37 @@ export default function <T extends sqliteCmd>(
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失败
function helper<T extends sqliteCmd>(action: sqliteAction<T>) {
switch (action.cmd) {
case sqliteCmd.INIT: {
const info = action.initInfo;
if (info) {
const dataPromise = pfetch(info.dbUrl, {
const releasePromise = pfetch(info.releaseDbUrl, {
progressCallback: action.initInfo?.progressCallback,
}).then((res) => res.arrayBuffer()); // TODO: i18n
return Promise.all([sqlPromise, dataPromise]).then(([SQL, buffer]) => {
YGODB = new SQL.Database(new Uint8Array(buffer));
const preReleasePromise = pfetch(info.preReleaseDbUrl, {
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!");
});
} else {
......@@ -72,12 +93,21 @@ function helper<T extends sqliteCmd>(action: sqliteAction<T>) {
}
}
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 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 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 });
return {
......@@ -93,8 +123,22 @@ function helper<T extends sqliteCmd>(action: sqliteAction<T>) {
return {};
}
case sqliteCmd.FTS: {
if (YGODB && action.payload && action.payload.ftsParams) {
const metas = invokeFts(YGODB, action.payload.ftsParams);
if (
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 };
} 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";
import { sendSortCardResponse } from "@/api";
import { CardMeta } from "@/api/cards";
import { useConfig } from "@/config";
import { getCardImgUrl } from "@/ui/Shared";
import { NeosModal } from "./NeosModal";
const NeosConfig = useConfig();
interface SortOption {
meta: CardMeta;
response: number;
......@@ -118,7 +116,7 @@ const SortableItem = (props: { id: number; meta: CardMeta }) => {
cover={
<img
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";
import { useEnv } from "@/hook";
import sqliteMiddleWare, { sqliteCmd } from "@/middleware/sqlite";
import { accountStore, deckStore, initStore, type User } from "@/stores";
const { cardsDbUrl } = useConfig();
const { releaseDbUrl, preReleaseDbUrl } = useConfig();
const { BASE_URL } = useEnv();
/** 加载ygodb */
......@@ -23,7 +23,7 @@ export const initSqlite = async () => {
sqlite.progress = 0.01;
await sqliteMiddleWare({
cmd: sqliteCmd.INIT,
initInfo: { dbUrl: cardsDbUrl, progressCallback },
initInfo: { releaseDbUrl, preReleaseDbUrl, progressCallback },
});
sqlite.progress = 1;
}
......
......@@ -11,4 +11,8 @@
height: 3rem;
margin: 0.25rem;
}
.select {
margin: 0.25rem 0;
}
}
......@@ -5,12 +5,17 @@ import { proxy, useSnapshot } from "valtio";
import { useConfig } from "@/config";
import { accountStore, roomStore } from "@/stores";
import { Select } from "@/ui/Shared";
import styles from "./MatchModal.module.scss";
import { connectSrvpro } from "./util";
const NeosConfig = useConfig();
const serverConfig = NeosConfig.servers;
const KOISHI = "koishi";
const PRERELEASE = "pre-release";
const {
defaults: { defaultPlayer, defaultPassword },
automation: { isAiMode },
......@@ -33,17 +38,26 @@ export const MatchModal: React.FC = ({}) => {
const { joined, errorMsg } = useSnapshot(roomStore);
const [player, setPlayer] = useState(user?.name ?? defaultPlayer);
const [passwd, setPasswd] = useState(defaultPassword);
const [server, setServer] = useState(
`${serverConfig[0].ip}:${serverConfig[0].port}`,
);
const [serverId, setServerId] = useState(0);
const [confirmLoading, setConfirmLoading] = useState(false);
const navigate = useNavigate();
let handlePlayerChange = (event: ChangeEvent<HTMLInputElement>) => {
setPlayer(event.target.value);
};
let handleServerChange = (event: ChangeEvent<HTMLInputElement>) => {
setServer(event.target.value);
let handleServerChange = (value: any) => {
switch (value) {
case KOISHI: {
setServerId(0);
break;
}
case PRERELEASE: {
setServerId(2);
break;
}
default:
break;
}
};
let handlePasswdChange = (event: ChangeEvent<HTMLInputElement>) => {
setPasswd(event.target.value);
......@@ -51,7 +65,11 @@ export const MatchModal: React.FC = ({}) => {
const handleSubmit = async () => {
setConfirmLoading(true);
await connectSrvpro({ player, ip: server, passWd: passwd });
await connectSrvpro({
player,
ip: genServerAddress(serverId),
passWd: passwd,
});
};
useEffect(() => {
......@@ -91,6 +109,22 @@ export const MatchModal: React.FC = ({}) => {
centered
>
<div className={styles["inputs-container"]}>
<Select
className={styles.select}
title="服务器"
value={KOISHI}
options={[
{
value: KOISHI,
label: "Koishi服",
},
{
value: PRERELEASE,
label: "超先行服",
},
]}
onChange={handleServerChange}
/>
<Input
className={styles.input}
type="text"
......@@ -99,14 +133,6 @@ export const MatchModal: React.FC = ({}) => {
onChange={handlePlayerChange}
required
/>
<Input
className={styles.input}
type="text"
placeholder="服务器(IP+端口)"
value={server}
onChange={handleServerChange}
required
/>
<Input
className={styles.input}
type="text"
......@@ -119,3 +145,7 @@ export const MatchModal: React.FC = ({}) => {
</Modal>
);
};
const genServerAddress = (id: number) => {
return `${serverConfig[id].ip}:${serverConfig[id].port}`;
};
......@@ -26,7 +26,10 @@ export const connectSrvpro = async (params: {
// 初始化sqlite
await sqliteMiddleWare({
cmd: sqliteCmd.INIT,
initInfo: { dbUrl: NeosConfig.cardsDbUrl },
initInfo: {
releaseDbUrl: NeosConfig.releaseDbUrl,
preReleaseDbUrl: NeosConfig.preReleaseDbUrl,
},
});
// 初始化I18N文案
......
......@@ -2,6 +2,7 @@ import classNames from "classnames";
import { CSSProperties, useMemo } from "react";
import { useConfig } from "@/config";
import { isSuperReleaseCard } from "@/superPreRelease";
import styles from "./index.module.scss";
......@@ -60,5 +61,10 @@ export function getCardImgUrl(code: number, back = false) {
if (back || code === 0) {
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