Commit 736537f0 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'fix/select_xx' into 'main'

fix MSG_SELECT_CHAIN, MSG_SELECT_SUM and MSG_CONFIRM_CARDS

See merge request !423
parents 977849d7 c284e77c
Pipeline #42402 passed with stages
in 1 minute and 20 seconds
...@@ -78,3 +78,5 @@ export const MSG_HAND_RES = 133; ...@@ -78,3 +78,5 @@ export const MSG_HAND_RES = 133;
export const MSG_SHUFFLE_HAND = 33; export const MSG_SHUFFLE_HAND = 33;
export const MSG_SHUFFLE_EXTRA = 39; export const MSG_SHUFFLE_EXTRA = 39;
export const MSG_SIBYL_NAME = 235; export const MSG_SIBYL_NAME = 235;
export const MSG_CONFIRM_CARDS = 30;
export const MSG_CONFIRM_DECKTOP = 31;
import { ygopro } from "../../../idl/ocgcore";
import { BufferReaderExt } from "../../bufferIO";
import MsgConfirmCards = ygopro.StocGameMessage.MsgConfirmCards;
/*
* Msg Confirm Cards
*
* @usage - 确认卡片(展示手牌、确认盖卡等)
* */
export default (data: Uint8Array) => {
const reader = new BufferReaderExt(data);
const player = reader.inner.readUint8();
// 新协议在 player 和 count 之间增加了一个字节,用途暂不明确。
// 参考 C# 实现:
// if (condition != Condition.Replay || CurrentReplayUseYRP2)
// reader.ReadByte();
// C# 中在非回放模式或使用 YRP2 格式回放时会跳过这个字节。
// 如果后续需要支持旧版回放文件,可能需要加条件判断。
reader.inner.readUint8();
const count = reader.inner.readUint8();
const cards: ygopro.CardInfo[] = [];
for (let i = 0; i < count; i++) {
cards.push(reader.readCardInfo());
}
return new MsgConfirmCards({
player,
cards,
});
};
...@@ -12,6 +12,7 @@ import MsgAnnounceCard from "./announceCard"; ...@@ -12,6 +12,7 @@ import MsgAnnounceCard from "./announceCard";
import MsgAnnounceNumber from "./announceNumber"; import MsgAnnounceNumber from "./announceNumber";
import MsgAnnounceRace from "./announceRace"; import MsgAnnounceRace from "./announceRace";
import MsgAttack from "./attack"; import MsgAttack from "./attack";
import MsgConfirmCardsAdapter from "./confirmCards";
import MsgDamage from "./damage"; import MsgDamage from "./damage";
import MsgDrawAdapter from "./draw"; import MsgDrawAdapter from "./draw";
import MsgFieldDisabledAdapter from "./fieldDisabled"; import MsgFieldDisabledAdapter from "./fieldDisabled";
...@@ -245,6 +246,11 @@ export default class GameMsgAdapter implements StocAdapter { ...@@ -245,6 +246,11 @@ export default class GameMsgAdapter implements StocAdapter {
gameMsg.sibyl_name = MsgSibylNameAdapter(gameData); gameMsg.sibyl_name = MsgSibylNameAdapter(gameData);
break; break;
} }
case GAME_MSG.MSG_CONFIRM_CARDS:
case GAME_MSG.MSG_CONFIRM_DECKTOP: {
gameMsg.confirm_cards = MsgConfirmCardsAdapter(gameData);
break;
}
default: { default: {
gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({ gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({
command: func, command: func,
......
...@@ -161,34 +161,7 @@ ...@@ -161,34 +161,7 @@
} }
] ]
}, },
"30": {
"protoType": "confirm_cards",
"fields": [
{
"fieldName": "player",
"fieldType": "uint8"
},
{
"fieldName": "cards",
"fieldType": "repeated",
"repeatedType": "CardInfo"
}
]
},
"31": {
"protoType": "confirm_cards",
"fields": [
{
"fieldName": "player",
"fieldType": "uint8"
},
{
"fieldName": "cards",
"fieldType": "repeated",
"repeatedType": "CardInfo"
}
]
},
"83": { "83": {
"protoType": "become_target", "protoType": "become_target",
"fields": [ "fields": [
......
...@@ -32,7 +32,6 @@ const MsgConstructorMap: Map<string, Constructor> = new Map([ ...@@ -32,7 +32,6 @@ const MsgConstructorMap: Map<string, Constructor> = new Map([
["chain_solved", ygopro.StocGameMessage.MsgChainSolved], ["chain_solved", ygopro.StocGameMessage.MsgChainSolved],
["chain_end", ygopro.StocGameMessage.MsgChainEnd], ["chain_end", ygopro.StocGameMessage.MsgChainEnd],
["lp_update", ygopro.StocGameMessage.MsgLpUpdate], ["lp_update", ygopro.StocGameMessage.MsgLpUpdate],
["confirm_cards", ygopro.StocGameMessage.MsgConfirmCards],
["become_target", ygopro.StocGameMessage.MsgBecomeTarget], ["become_target", ygopro.StocGameMessage.MsgBecomeTarget],
["shuffle_deck", ygopro.StocGameMessage.MsgShuffleDeck], ["shuffle_deck", ygopro.StocGameMessage.MsgShuffleDeck],
["rock_paper_scissors", ygopro.StocGameMessage.MsgRockPaperScissors], ["rock_paper_scissors", ygopro.StocGameMessage.MsgRockPaperScissors],
......
...@@ -17,35 +17,41 @@ export default (data: Uint8Array) => { ...@@ -17,35 +17,41 @@ export default (data: Uint8Array) => {
const player = reader.inner.readUint8(); const player = reader.inner.readUint8();
const count = reader.inner.readUint8(); const count = reader.inner.readUint8();
const spCount = reader.inner.readUint8(); const spCount = reader.inner.readUint8();
const forced = reader.inner.readUint8() !== 0;
const hint0 = reader.inner.readUint32(); const hint0 = reader.inner.readUint32();
const hint1 = reader.inner.readUint32(); const hint1 = reader.inner.readUint32();
const msg = new MsgSelectChain({ const msg = new MsgSelectChain({
player, player,
special_count: spCount, special_count: spCount,
forced, forced: false,
hint0, hint0,
hint1, hint1,
chains: [], chains: [],
}); });
let forceCount = 0;
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const flag = reader.inner.readUint8(); const flag = reader.inner.readUint8();
const code = reader.inner.readUint32(); const forced = reader.inner.readUint8();
forceCount += forced;
const code = reader.inner.readUint32() % 1000000000;
const location = reader.readCardLocation(); const location = reader.readCardLocation();
const effect_desc = reader.inner.readUint32(); const effect_desc = reader.inner.readUint32();
msg.chains.push( const chain = new MsgSelectChain.Chain({
new MsgSelectChain.Chain({ flag: numberToChainFlag(flag),
flag: numberToChainFlag(flag), code,
code, location,
location, effect_description: effect_desc,
effect_description: effect_desc, response: i,
response: i, });
}), // 由于 protobuf 定义中 Chain 没有 forced 字段,使用类型扩展
); (chain as any).forced = forced > 0;
msg.chains.push(chain);
} }
msg.forced = forceCount > 0;
return msg; return msg;
}; };
...@@ -34,12 +34,23 @@ export default (data: Uint8Array) => { ...@@ -34,12 +34,23 @@ export default (data: Uint8Array) => {
const location = reader.readCardShortLocation(); const location = reader.readCardShortLocation();
const para = reader.inner.readInt32(); const para = reader.inner.readInt32();
let level1 = para & 0xffff;
let level2 = para >> 16;
// 检查 0x80000000 标志位
if ((para & 0x80000000) !== 0) {
level1 = para & 0x7fffffff;
level2 = level1;
}
if (level2 === 0) {
level2 = level1;
}
msg.must_select_cards.push( msg.must_select_cards.push(
new MsgSelectSum.Info({ new MsgSelectSum.Info({
code, code,
location, location,
level1: para & 0xffff, level1,
level2: para >> 16, level2,
response: i, response: i,
}), }),
); );
...@@ -50,8 +61,17 @@ export default (data: Uint8Array) => { ...@@ -50,8 +61,17 @@ export default (data: Uint8Array) => {
const code = reader.inner.readInt32(); const code = reader.inner.readInt32();
const location = reader.readCardShortLocation(); const location = reader.readCardShortLocation();
const para = reader.inner.readInt32(); const para = reader.inner.readInt32();
const level1 = para & 0xffff;
const level2 = para >> 16 > 0 ? para >> 16 : level1; let level1 = para & 0xffff;
let level2 = para >> 16;
// 检查 0x80000000 标志位
if ((para & 0x80000000) !== 0) {
level1 = para & 0x7fffffff;
level2 = level1;
}
if (level2 === 0) {
level2 = level1;
}
msg.selectable_cards.push( msg.selectable_cards.push(
new MsgSelectSum.Info({ new MsgSelectSum.Info({
......
...@@ -10,20 +10,22 @@ export default async (container: Container, selectChain: MsgSelectChain) => { ...@@ -10,20 +10,22 @@ export default async (container: Container, selectChain: MsgSelectChain) => {
const conn = container.conn; const conn = container.conn;
const context = container.context; const context = container.context;
const spCount = selectChain.special_count; const spCount = selectChain.special_count;
const forced = selectChain.forced;
const _hint0 = selectChain.hint0; const _hint0 = selectChain.hint0;
const _hint1 = selectChain.hint1; const _hint1 = selectChain.hint1;
const chains = selectChain.chains; const chains = selectChain.chains;
const chainSetting = context.matStore.chainSetting; const chainSetting = context.matStore.chainSetting;
if (chainSetting === ChainSetting.CHAIN_IGNORE) { // 计算强制发动的卡片数量
// 如果玩家配置了忽略连锁,直接回应后端并返回 const forceCount = chains.filter((chain) => (chain as any).forced).length;
if (chainSetting === ChainSetting.CHAIN_IGNORE && forceCount === 0) {
// 如果玩家配置了忽略连锁,且没有强制发动的卡,直接回应后端并返回
sendSelectSingleResponse(conn, -1); sendSelectSingleResponse(conn, -1);
return; return;
} }
let handle_flag = 0; let handle_flag = 0;
if (!forced) { if (forceCount === 0) {
// 无强制发动的卡 // 无强制发动的卡
if (spCount === 0) { if (spCount === 0) {
// 无关键卡 // 无关键卡
...@@ -32,8 +34,12 @@ export default async (container: Container, selectChain: MsgSelectChain) => { ...@@ -32,8 +34,12 @@ export default async (container: Container, selectChain: MsgSelectChain) => {
handle_flag = 0; handle_flag = 0;
} else { } else {
if (chainSetting === ChainSetting.CHAIN_ALL) { if (chainSetting === ChainSetting.CHAIN_ALL) {
// 配置了全部连锁,则处理多张 // 配置了全部连锁,则处理
handle_flag = 2; if (chains.length === 1) {
handle_flag = 1;
} else {
handle_flag = 2;
}
} else { } else {
// 否则不连锁 // 否则不连锁
handle_flag = 0; handle_flag = 0;
...@@ -44,32 +50,45 @@ export default async (container: Container, selectChain: MsgSelectChain) => { ...@@ -44,32 +50,45 @@ export default async (container: Container, selectChain: MsgSelectChain) => {
if (chains.length === 0) { if (chains.length === 0) {
// 根本没卡,直接回答 // 根本没卡,直接回答
handle_flag = 0; handle_flag = 0;
} else if (chainSetting === ChainSetting.CHAIN_IGNORE) {
// 配置了忽略连锁
handle_flag = 0;
} else { } else {
// 处理多张 // 处理
handle_flag = 2; if (chains.length === 1) {
handle_flag = 1;
} else {
handle_flag = 2;
}
} }
} }
} else { } else {
// 有强制发动的卡 // 有强制发动的卡
if (chains.length === 1) { if (chains.length === 1) {
// 只有一个强制发动的连锁项,直接回应 // 只有一张卡需要处理(强制发动)
handle_flag = 4;
} else {
// 处理强制发动的卡
handle_flag = 3; handle_flag = 3;
} else {
// 多张卡需要处理(强制发动)
handle_flag = 4;
} }
} }
// handle_flag:
// 0 - 无卡,直接回应
// 1 - 一张卡需要处理
// 2 - 多张卡需要处理
// 3 - 一张卡需要处理(强制发动)
// 4 - 多张卡需要处理(强制发动)
switch (handle_flag) { switch (handle_flag) {
case 0: { case 0: {
// 直接回答 // 直接回答
sendSelectSingleResponse(conn, -1); sendSelectSingleResponse(conn, -1);
break; break;
} }
case 2: // 处理多张 case 1:
case 3: { case 2: {
// 处理强制发动的卡 // 处理可选连锁
fetchSelectHintMeta({ fetchSelectHintMeta({
selectHintData: 203, selectHintData: 203,
}); });
...@@ -79,7 +98,7 @@ export default async (container: Container, selectChain: MsgSelectChain) => { ...@@ -79,7 +98,7 @@ export default async (container: Container, selectChain: MsgSelectChain) => {
); );
await displaySelectActionsModal({ await displaySelectActionsModal({
isChain: true, isChain: true,
cancelable: !forced, cancelable: true,
min: 1, min: 1,
max: 1, max: 1,
selecteds, selecteds,
...@@ -88,10 +107,29 @@ export default async (container: Container, selectChain: MsgSelectChain) => { ...@@ -88,10 +107,29 @@ export default async (container: Container, selectChain: MsgSelectChain) => {
}); });
break; break;
} }
case 4: { case 3: {
// 一张强制发动的卡,直接回应 // 一张强制发动的卡,直接回应
sendSelectSingleResponse(conn, chains[0].response); sendSelectSingleResponse(conn, chains[0].response);
break;
}
case 4: {
// 多张强制发动的卡,弹窗选择
fetchSelectHintMeta({
selectHintData: 203,
});
const { selecteds, mustSelects, selectables } = await fetchCheckCardMeta(
context,
chains,
);
await displaySelectActionsModal({
isChain: true,
cancelable: false,
min: 1,
max: 1,
selecteds,
mustSelects,
selectables,
});
break; break;
} }
default: { default: {
......
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