Commit 00bbfcce authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/announce' into 'main'

Feat/announce

See merge request mycard/Neos!208
parents 255aa6df e14b2781
Pipeline #21831 passed with stages
in 13 minutes and 8 seconds
Subproject commit 48be6a827024995962fc479db1ec69bde38a72f6 Subproject commit ee85cb1d1f71ad6b44f1daf1877b63fa2ac1991f
This diff is collapsed.
...@@ -57,3 +57,7 @@ export const MSG_REMOVE_COUNTER = 102; ...@@ -57,3 +57,7 @@ export const MSG_REMOVE_COUNTER = 102;
export const MSG_SELECT_COUNTER = 22; export const MSG_SELECT_COUNTER = 22;
export const MSG_SORT_CARD = 25; export const MSG_SORT_CARD = 25;
export const MSG_ATTACK = 110; export const MSG_ATTACK = 110;
export const MSG_ANNOUNCE_RACE = 140;
export const MSG_ANNOUNCE_ATTRIB = 141;
export const MSG_ANNOUNCE_CARD = 142;
export const MSG_ANNOUNCE_NUMBER = 143;
import { BufferReader } from "rust-src";
import { ygopro } from "@/api/ocgcore/idl/ocgcore";
import MsgAnnounce = ygopro.StocGameMessage.MsgAnnounce;
/*
* Announce Attribute
*
* @param - TODO
* @usage - 声明属性
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data);
const player = reader.readUint8();
const min = reader.readUint8();
const avaiable = reader.readUint32();
const options = [];
for (let i = 0; i < 7; i++) {
if ((avaiable & (1 << i)) > 0) {
options.push(
new MsgAnnounce.Option({
code: i,
response: 1 << i,
})
);
}
}
return new MsgAnnounce({
player,
announce_type: MsgAnnounce.AnnounceType.Attribute,
min,
options,
});
};
import { BufferReader } from "rust-src";
import { ygopro } from "@/api/ocgcore/idl/ocgcore";
import MsgAnnounce = ygopro.StocGameMessage.MsgAnnounce;
/*
* Announce Card
*
* @param - TODO
* @usage - 声明卡片
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data);
const player = reader.readUint8();
const count = reader.readUint8();
const options = [];
for (let i = 0; i < count; i++) {
const code = reader.readUint32();
options.push(
new MsgAnnounce.Option({
code,
response: code,
})
);
}
return new MsgAnnounce({
player,
announce_type: MsgAnnounce.AnnounceType.Card,
options,
});
};
import { BufferReader } from "rust-src";
import { ygopro } from "@/api/ocgcore/idl/ocgcore";
import MsgAnnounce = ygopro.StocGameMessage.MsgAnnounce;
/*
* Announce Number
*
* @param - TODO
* @usage - 声明数字
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data);
const player = reader.readUint8();
const count = reader.readUint8();
const options = [];
for (let i = 0; i < count; i++) {
const num = reader.readUint32();
options.push(
new MsgAnnounce.Option({
code: num,
response: i,
})
);
}
return new MsgAnnounce({
player,
announce_type: MsgAnnounce.AnnounceType.Number,
options,
});
};
import { BufferReader } from "rust-src";
import { ygopro } from "@/api/ocgcore/idl/ocgcore";
import MsgAnnounce = ygopro.StocGameMessage.MsgAnnounce;
/*
* Announce Race
*
* @param - TODO
* @usage - 声明种族
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data);
const player = reader.readUint8();
const min = reader.readUint8();
const avaiable = reader.readUint32();
const options = [];
for (let i = 0; i < 25; i++) {
if ((avaiable & (1 << i)) > 0) {
options.push(
new MsgAnnounce.Option({
code: i,
response: 1 << i,
})
);
}
}
return new MsgAnnounce({
player,
announce_type: MsgAnnounce.AnnounceType.RACE,
min,
options,
});
};
...@@ -7,6 +7,10 @@ import { ygopro } from "../../../idl/ocgcore"; ...@@ -7,6 +7,10 @@ import { ygopro } from "../../../idl/ocgcore";
import { StocAdapter, YgoProPacket } from "../../packet"; import { StocAdapter, YgoProPacket } from "../../packet";
import * as GAME_MSG from "../../protoDecl"; import * as GAME_MSG from "../../protoDecl";
import MsgAddCounter from "./addCounter"; import MsgAddCounter from "./addCounter";
import MsgAnnounceAttribute from "./announceAttrib";
import MsgAnnounceCard from "./announceCard";
import MsgAnnounceNumber from "./announceNumber";
import MsgAnnounceRace from "./announceRace";
import MsgAttack from "./attack"; import MsgAttack from "./attack";
import MsgDamage from "./damage"; import MsgDamage from "./damage";
import MsgDrawAdapter from "./draw"; import MsgDrawAdapter from "./draw";
...@@ -196,6 +200,26 @@ export default class GameMsgAdapter implements StocAdapter { ...@@ -196,6 +200,26 @@ export default class GameMsgAdapter implements StocAdapter {
break; break;
} }
case GAME_MSG.MSG_ANNOUNCE_RACE: {
gameMsg.announce = MsgAnnounceRace(gameData);
break;
}
case GAME_MSG.MSG_ANNOUNCE_ATTRIB: {
gameMsg.announce = MsgAnnounceAttribute(gameData);
break;
}
case GAME_MSG.MSG_ANNOUNCE_CARD: {
gameMsg.announce = MsgAnnounceCard(gameData);
break;
}
case GAME_MSG.MSG_ANNOUNCE_NUMBER: {
gameMsg.announce = MsgAnnounceNumber(gameData);
break;
}
default: { default: {
gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({ gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({
command: func, command: func,
......
import { fetchCard, fetchStrings, ygopro } from "@/api";
import { messageStore } from "@/stores";
import MsgAnnounce = ygopro.StocGameMessage.MsgAnnounce;
const { announceModal } = messageStore;
export default async (announce: MsgAnnounce) => {
const type_ = announce.announce_type;
let min = announce.min;
if (
type_ == MsgAnnounce.AnnounceType.Card ||
type_ == MsgAnnounce.AnnounceType.Number
) {
min = 1;
}
announceModal.min = min;
switch (type_) {
case MsgAnnounce.AnnounceType.RACE: {
announceModal.title = fetchStrings("!system", 563);
announceModal.options = announce.options.map((option) => ({
info: fetchStrings("!system", 1200 + option.code),
response: option.response,
}));
announceModal.isOpen = true;
break;
}
case MsgAnnounce.AnnounceType.Attribute: {
announceModal.title = fetchStrings("!system", 562);
announceModal.options = announce.options.map((option) => ({
info: fetchStrings("!system", 1010 + option.code),
response: option.response,
}));
announceModal.isOpen = true;
break;
}
case MsgAnnounce.AnnounceType.Card: {
announceModal.title = fetchStrings("!system", 564);
announceModal.options = await Promise.all(
announce.options.map(async (option) => ({
info: await fetchCard(option.code).then(
(meta) => meta.text.name ?? "[?]"
),
response: option.response,
}))
);
announceModal.isOpen = true;
break;
}
case MsgAnnounce.AnnounceType.Number: {
announceModal.title = fetchStrings("!system", 565);
announceModal.options = announce.options.map((option) => ({
info: option.code.toString(),
response: option.response,
}));
announceModal.isOpen = true;
break;
}
default: {
console.warn(`Unknown announce_type = ${type_}`);
}
}
};
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { matStore } from "@/stores"; import { matStore } from "@/stores";
import onAnnounce from "./announce";
import onMsgAttack from "./attack"; import onMsgAttack from "./attack";
import onMsgAttackDisable from "./attackDisable"; import onMsgAttackDisable from "./attackDisable";
import onMsgChainEnd from "./chainEnd"; import onMsgChainEnd from "./chainEnd";
...@@ -270,6 +271,11 @@ export default async function handleGameMsg(pb: ygopro.YgoStocMsg) { ...@@ -270,6 +271,11 @@ export default async function handleGameMsg(pb: ygopro.YgoStocMsg) {
break; break;
} }
case "announce": {
await onAnnounce(msg.announce);
break;
}
case "unimplemented": { case "unimplemented": {
onUnimplemented(msg.unimplemented); onUnimplemented(msg.unimplemented);
......
...@@ -25,6 +25,11 @@ export const messageStore = proxy<ModalState>({ ...@@ -25,6 +25,11 @@ export const messageStore = proxy<ModalState>({
isOpen: false, isOpen: false,
options: [], options: [],
}, },
announceModal: {
isOpen: false,
min: 1,
options: [],
},
}); });
// >>> modal types >>> // >>> modal types >>>
...@@ -87,4 +87,14 @@ export interface ModalState { ...@@ -87,4 +87,14 @@ export interface ModalState {
response: number; response: number;
}[]; }[];
}; };
// 宣言弹窗
announceModal: {
isOpen: boolean;
title?: string;
min: number;
options: {
info: string;
response: number;
}[];
};
} }
...@@ -2,6 +2,7 @@ import React from "react"; ...@@ -2,6 +2,7 @@ import React from "react";
import { import {
Alert, Alert,
AnnounceModal,
CardListModal, CardListModal,
CardModal, CardModal,
CheckCounterModal, CheckCounterModal,
...@@ -28,6 +29,7 @@ const NeosDuel = () => { ...@@ -28,6 +29,7 @@ const NeosDuel = () => {
<OptionModal /> <OptionModal />
<CheckCounterModal /> <CheckCounterModal />
<SortCardModal /> <SortCardModal />
<AnnounceModal />
</> </>
); );
}; };
......
import { CheckCard } from "@ant-design/pro-components";
import { Button } from "antd";
import React, { useState } from "react";
import { useSnapshot } from "valtio";
import { sendSelectOptionResponse } from "@/api";
import { messageStore } from "@/stores";
import { DragModal } from "./DragModal";
const { announceModal } = messageStore;
export const AnnounceModal = () => {
const snap = useSnapshot(announceModal);
const isOpen = snap.isOpen;
const title = snap.title;
const min = snap.min;
const options = snap.options;
const [selected, setSelected] = useState<number[]>([]);
return (
<DragModal
title={title}
open={isOpen}
closable={false}
footer={
<Button
disabled={selected.length != min}
onClick={() => {
let response = selected.reduce((res, current) => res | current, 0); // 多个选择求或
sendSelectOptionResponse(response);
announceModal.isOpen = false;
announceModal.title = undefined;
announceModal.options = [];
}}
>
submit
</Button>
}
>
<CheckCard.Group
bordered
multiple
size="small"
onChange={(value: any) => {
setSelected(value);
}}
>
{options.map((option, idx) => (
<CheckCard key={idx} title={option.info} value={option.response} />
))}
</CheckCard.Group>
</DragModal>
);
};
export * from "./Alert"; export * from "./Alert";
export * from "./AnnounceModal";
export * from "./CardListModal"; export * from "./CardListModal";
export * from "./CardModal"; export * from "./CardModal";
export * from "./CheckCounterModal"; export * from "./CheckCounterModal";
......
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