Commit fff94394 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'optimize/ui/card' into 'main'

Optimize/ui/card

See merge request mycard/Neos!128
parents 8e3c4dc3 113f72b5
Pipeline #20604 passed with stages
in 7 minutes and 46 seconds
......@@ -13,16 +13,6 @@ export async function initStrings() {
}
}
export async function fetchStrings(
region: string,
id: number,
local?: boolean
): Promise<string> {
if (local) {
return localStorage.getItem(`${region}_${id}`) || "";
}
return (
await axios.get<string>(`http://localhost:3030/strings/${region}_${id}`)
).data;
export function fetchStrings(region: string, id: number): string {
return localStorage.getItem(`${region}_${id}`) || "";
}
//! 一些Neos中基础的数据结构
// 类型
const TYPE_MONSTER = 0x1; //
const TYPE_SPELL = 0x2; //
const TYPE_TRAP = 0x4; //
const TYPE_NORMAL = 0x10; //
const TYPE_EFFECT = 0x20; //
const TYPE_FUSION = 0x40; //
const TYPE_RITUAL = 0x80; //
const TYPE_TRAPMONSTER = 0x100; //
const TYPE_SPIRIT = 0x200; //
const TYPE_UNION = 0x400; //
const TYPE_DUAL = 0x800; //
const TYPE_TUNER = 0x1000; //
const TYPE_SYNCHRO = 0x2000; //
const TYPE_TOKEN = 0x4000; //
const TYPE_QUICKPLAY = 0x10000; //
const TYPE_CONTINUOUS = 0x20000; //
const TYPE_EQUIP = 0x40000; //
const TYPE_FIELD = 0x80000; //
const TYPE_COUNTER = 0x100000; //
const TYPE_FLIP = 0x200000; //
const TYPE_TOON = 0x400000; //
const TYPE_XYZ = 0x800000; //
const TYPE_PENDULUM = 0x1000000; //
const TYPE_SPSUMMON = 0x2000000; //
const TYPE_LINK = 0x4000000; //
/*
* 在做卡牌信息展示的时候,发现`CardMeta`里面的数据和`strings.conf`配置文件
* 里面的code是不对应的,这里定义一个哈希表来管理其中的映射关系。
*
* metaCode -> stringCode
* */
export const Type2StringCodeMap: Map<number, number> = new Map([
[TYPE_MONSTER, 1050],
[TYPE_SPELL, 1051],
[TYPE_TRAP, 1052],
[TYPE_NORMAL, 1054],
[TYPE_EFFECT, 1055],
[TYPE_FUSION, 1056],
[TYPE_RITUAL, 1057],
[TYPE_TRAPMONSTER, 1058],
[TYPE_SPIRIT, 1059],
[TYPE_UNION, 1060],
[TYPE_DUAL, 1061],
[TYPE_TUNER, 1062],
[TYPE_SYNCHRO, 1063],
[TYPE_TOKEN, 1064],
[TYPE_QUICKPLAY, 1066],
[TYPE_CONTINUOUS, 1067],
[TYPE_EQUIP, 1068],
[TYPE_FIELD, 1069],
[TYPE_COUNTER, 1070],
[TYPE_FLIP, 1071],
[TYPE_TOON, 1072],
[TYPE_XYZ, 1073],
[TYPE_PENDULUM, 1074],
[TYPE_SPSUMMON, 1075],
[TYPE_LINK, 1076],
]);
/*
* ygopro将卡牌类型按位运算进行了编码,这里将编码信息提出出来*/
export function extraCardTypes(typeCode: number): number[] {
return [
TYPE_MONSTER,
TYPE_SPELL,
TYPE_TRAP,
TYPE_NORMAL,
TYPE_EFFECT,
TYPE_FUSION,
TYPE_RITUAL,
TYPE_TRAPMONSTER,
TYPE_SPIRIT,
TYPE_UNION,
TYPE_DUAL,
TYPE_TUNER,
TYPE_SYNCHRO,
TYPE_TOKEN,
TYPE_QUICKPLAY,
TYPE_CONTINUOUS,
TYPE_EQUIP,
TYPE_FIELD,
TYPE_COUNTER,
TYPE_FLIP,
TYPE_TOON,
TYPE_XYZ,
TYPE_PENDULUM,
TYPE_SPSUMMON,
TYPE_LINK,
].filter((target) => (target & typeCode) > 0);
}
// 属性
// const ATTRIBUTE_ALL = 0x7f; //
const ATTRIBUTE_EARTH = 0x01; //
const ATTRIBUTE_WATER = 0x02; //
const ATTRIBUTE_FIRE = 0x04; //
const ATTRIBUTE_WIND = 0x08; //
const ATTRIBUTE_LIGHT = 0x10; //
const ATTRIBUTE_DARK = 0x20; //
const ATTRIBUTE_DEVINE = 0x40; //
export const Attribute2StringCodeMap: Map<number, number> = new Map([
[ATTRIBUTE_EARTH, 1010],
[ATTRIBUTE_WATER, 1011],
[ATTRIBUTE_FIRE, 1012],
[ATTRIBUTE_WIND, 1013],
[ATTRIBUTE_LIGHT, 1014],
[ATTRIBUTE_DARK, 1015],
[ATTRIBUTE_DEVINE, 1016],
]);
// 种族
const RACE_WARRIOR = 0x1; //
const RACE_SPELLCASTER = 0x2; //
const RACE_FAIRY = 0x4; //
const RACE_FIEND = 0x8; //
const RACE_ZOMBIE = 0x10; //
const RACE_MACHINE = 0x20; //
const RACE_AQUA = 0x40; //
const RACE_PYRO = 0x80; //
const RACE_ROCK = 0x100; //
const RACE_WINDBEAST = 0x200; //
const RACE_PLANT = 0x400; //
const RACE_INSECT = 0x800; //
const RACE_THUNDER = 0x1000; //
const RACE_DRAGON = 0x2000; //
const RACE_BEAST = 0x4000; //
const RACE_BEASTWARRIOR = 0x8000; //
const RACE_DINOSAUR = 0x10000; //
const RACE_FISH = 0x20000; //
const RACE_SEASERPENT = 0x40000; //
const RACE_REPTILE = 0x80000; //
const RACE_PSYCHO = 0x100000; //
const RACE_DEVINE = 0x200000; //
const RACE_CREATORGOD = 0x400000; //
const RACE_WYRM = 0x800000; //
const RACE_CYBERSE = 0x1000000; //
export const Race2StringCodeMap: Map<number, number> = new Map([
[RACE_WARRIOR, 1020],
[RACE_SPELLCASTER, 1021],
[RACE_FAIRY, 1022],
[RACE_FIEND, 1023],
[RACE_ZOMBIE, 1024],
[RACE_MACHINE, 1025],
[RACE_AQUA, 1026],
[RACE_PYRO, 1027],
[RACE_ROCK, 1028],
[RACE_WINDBEAST, 1029],
[RACE_PLANT, 1030],
[RACE_INSECT, 1031],
[RACE_THUNDER, 1032],
[RACE_DRAGON, 1033],
[RACE_BEAST, 1034],
[RACE_BEASTWARRIOR, 1035],
[RACE_DINOSAUR, 1036],
[RACE_FISH, 1037],
[RACE_SEASERPENT, 1038],
[RACE_REPTILE, 1039],
[RACE_PSYCHO, 1040],
[RACE_DEVINE, 1041],
[RACE_CREATORGOD, 1042],
[RACE_WYRM, 1043],
[RACE_CYBERSE, 1044],
]);
......@@ -16,7 +16,7 @@ export const fetchCommonHintMeta = createAsyncThunk(
const player = param[0];
const hintData = param[1];
const hintMeta = await fetchStrings("!system", hintData, true);
const hintMeta = fetchStrings("!system", hintData);
const response: [number, string] = [player, hintMeta];
return response;
......
......@@ -31,7 +31,7 @@ export const fetchYesNoMeta = createAsyncThunk(
cardLocation: ygopro.CardLocation
) => string;
}) => {
const desc = await fetchStrings("!system", param.descCode, true);
const desc = fetchStrings("!system", param.descCode);
const meta = await fetchCard(param.code, true);
// TODO: 国际化文案
......
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";
......@@ -12,10 +12,17 @@ import {
} from "../../reducers/duel/mod";
import { Modal, Card, Button, Row, Col } from "antd";
import { sendSelectIdleCmdResponse } from "../../api/ocgcore/ocgHelper";
import Icon from "@ant-design/icons";
import Icon, { StarOutlined } from "@ant-design/icons";
import NeosConfig from "../../../neos.config.json";
import { ReactComponent as BattleSvg } from "../../../neos-assets/battle-axe.svg";
import { ReactComponent as DefenceSvg } from "../../../neos-assets/checked-shield.svg";
import {
extraCardTypes,
Type2StringCodeMap,
Attribute2StringCodeMap,
Race2StringCodeMap,
} from "../../common";
import { fetchStrings } from "../../api/strings";
const { Meta } = Card;
const CARD_WIDTH = 240;
......@@ -25,6 +32,10 @@ const CardModal = () => {
const isOpen = useAppSelector(selectCardModalIsOpen);
const meta = useAppSelector(selectCardModalMeta);
const name = meta?.text.name;
const types = meta?.data.type;
const race = meta?.data.race;
const attribute = meta?.data.attribute;
const level = meta?.data.level;
const desc = meta?.text.desc;
const atk = meta?.data.atk;
const def = meta?.data.def;
......@@ -45,30 +56,17 @@ const CardModal = () => {
cover={<img alt={name} src={imgUrl} />}
>
<Meta title={name} />
<p>{desc}</p>
<p>
<Row gutter={8}>
{atk ? (
<Col>
<Icon component={BattleSvg} />
<a>{atk}</a>
</Col>
) : (
<></>
)}
<Col>
<div>/</div>
</Col>
{def ? (
<Col>
<Icon component={DefenceSvg} />
<a>{def}</a>
</Col>
) : (
<></>
)}
</Row>
<AttLine
types={extraCardTypes(types || 0)}
race={race}
attribute={attribute}
/>
</p>
<p>
<AtkLine level={level} atk={atk} def={def} />
</p>
<p>{desc}</p>
</Card>
{interactivies.map((interactive, idx) => {
return (
......@@ -89,4 +87,58 @@ const CardModal = () => {
);
};
const AtkLine = (props: { level?: number; atk?: number; def?: number }) => (
<Row gutter={8}>
{props.level ? (
<Col>
<StarOutlined />
{props.level}
</Col>
) : (
<></>
)}
{props.atk ? (
<Col>
<Icon component={BattleSvg} />
<a>{props.atk}</a>
</Col>
) : (
<></>
)}
<Col>/</Col>
{props.def ? (
<Col>
<Icon component={DefenceSvg} />
<a>{props.def}</a>
</Col>
) : (
<></>
)}
</Row>
);
const AttLine = (props: {
types: number[];
race?: number;
attribute?: number;
}) => {
const race = props.race
? fetchStrings("!system", Race2StringCodeMap.get(props.race) || 0)
: undefined;
const attribute = props.attribute
? fetchStrings("!system", Attribute2StringCodeMap.get(props.attribute) || 0)
: undefined;
const types = props.types
.map((t) => fetchStrings("!system", Type2StringCodeMap.get(t) || 0))
.join("|");
return (
<Row gutter={8}>
<Col>{`[${types}]`}</Col>
{race ? <Col>{race}</Col> : <></>}
<Col>/</Col>
{attribute ? <Col>{attribute}</Col> : <></>}
</Row>
);
};
export default CardModal;
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