Commit b23c5ab2 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/field_disabled' into 'main'

Feat/field disabled

See merge request !232
parents feb483cc a0764834
Pipeline #22342 passed with stages
in 16 minutes and 1 second
neos-protobuf @ 984aa1c4
Subproject commit 2caaa3aa310f699ebf5b52a08413d0a555ac4065
Subproject commit 984aa1c40cee961f2a0f4540eaae7bc9d8d907a2
......@@ -2,7 +2,7 @@
"version":4960,
"servers":[
{
"ip":"koishi-r.momobako.com",
"ip":"koishi.momobako.com",
"port":"7211"
}
],
......
This diff is collapsed.
......@@ -65,3 +65,4 @@ export const MSG_ANNOUNCE_NUMBER = 143;
export const MSG_TOSS_COIN = 130;
export const MSG_TOSS_DICE = 131;
export const MSG_SHUFFLE_SET_CARD = 36;
export const MSG_FIELD_DISABLED = 56;
import { ygopro } from "@/api/ocgcore/idl/ocgcore";
import { BufferReader } from "../../../../../../rust-src/pkg/rust_src";
import MsgFieldDisabled = ygopro.StocGameMessage.MsgFieldDisabled;
import CardZone = ygopro.CardZone;
/*
* Msg Field Disabled
* @param - TODO
*
* @usage - 区域禁用
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data);
const flag = reader.readInt32();
const actions = [];
let filter = 0x1;
for (let i = 0; i < 5; i++, filter <<= 1) {
const disabled = (flag & filter) > 0;
actions.push(
new MsgFieldDisabled.Action({
controller: 0,
zone: CardZone.MZONE,
sequence: i,
disabled,
})
);
}
filter = 0x100;
for (let i = 0; i < 8; i++, filter <<= 1) {
const disabled = (flag & filter) > 0;
actions.push(
new MsgFieldDisabled.Action({
controller: 0,
zone: CardZone.SZONE,
sequence: i,
disabled,
})
);
}
filter = 0x10000;
for (let i = 0; i < 5; i++, filter <<= 1) {
const disabled = (flag & filter) > 0;
actions.push(
new MsgFieldDisabled.Action({
controller: 1,
zone: CardZone.MZONE,
sequence: i,
disabled,
})
);
}
filter = 0x1000000;
for (let i = 0; i < 8; i++, filter <<= 1) {
const disabled = (flag & filter) > 0;
actions.push(
new MsgFieldDisabled.Action({
controller: 1,
zone: CardZone.SZONE,
sequence: i,
disabled,
})
);
}
return new MsgFieldDisabled({
actions,
});
};
......@@ -14,6 +14,7 @@ import MsgAnnounceRace from "./announceRace";
import MsgAttack from "./attack";
import MsgDamage from "./damage";
import MsgDrawAdapter from "./draw";
import MsgFieldDisabledAdapter from "./fieldDisabled";
import MsgHintAdapter from "./hint";
import MsgNewPhaseAdapter from "./newPhase";
import MsgNewTurnAdapter from "./newTurn";
......@@ -244,6 +245,11 @@ export default class GameMsgAdapter implements StocAdapter {
break;
}
case GAME_MSG.MSG_FIELD_DISABLED: {
gameMsg.field_disabled = MsgFieldDisabledAdapter(gameData);
break;
}
default: {
gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({
command: func,
......
import { ygopro } from "@/api";
import { placeStore } from "@/stores";
import MsgFieldDisabled = ygopro.StocGameMessage.MsgFieldDisabled;
export default (fieldDisabled: MsgFieldDisabled) => {
for (const action of fieldDisabled.actions) {
switch (action.zone) {
case ygopro.CardZone.MZONE:
case ygopro.CardZone.SZONE:
placeStore.set(action.zone, action.controller, action.sequence, {
interactivity: undefined,
disabled: action.disabled,
});
break;
default:
console.warn("<FieldDisabled>zone is not MZONE nor SZONE!");
}
}
};
......@@ -11,6 +11,7 @@ import onMsgChaining from "./chaining";
import onMsgChainSolved from "./chainSolved";
import onConfirmCards from "./confirmCards";
import onMsgDraw from "./draw";
import onMsgFieldDisabled from "./fieldDisabled";
import onMsgFilpSummoned from "./flipSummoned";
import onMsgFlipSummoning from "./flipSummoning";
import onMsgHint from "./hint";
......@@ -315,6 +316,11 @@ async function _handleGameMsg(pb: ygopro.YgoStocMsg) {
break;
}
case "field_disabled": {
onMsgFieldDisabled(msg.field_disabled);
break;
}
case "unimplemented": {
onUnimplemented(msg.unimplemented);
......
......@@ -14,12 +14,15 @@ export default (selectPlace: MsgSelectPlace) => {
case ygopro.CardZone.MZONE:
case ygopro.CardZone.SZONE:
placeStore.set(place.zone, place.controller, place.sequence, {
interactType: InteractType.PLACE_SELECTABLE,
response: {
controller: place.controller,
zone: place.zone,
sequence: place.sequence,
interactivity: {
interactType: InteractType.PLACE_SELECTABLE,
response: {
controller: place.controller,
zone: place.zone,
sequence: place.sequence,
},
},
disabled: false,
});
break;
}
......
......@@ -15,31 +15,60 @@ export type PlaceInteractivity =
const { MZONE, SZONE } = ygopro.CardZone;
export interface BlockState {
interactivity?: PlaceInteractivity; // 互动性
disabled: boolean; // 是否被禁用
}
export const placeStore = proxy({
inner: {
[MZONE]: {
me: Array.from({ length: 7 }).map(() => undefined as PlaceInteractivity),
op: Array.from({ length: 7 }).map(() => undefined as PlaceInteractivity),
me: Array.from({ length: 7 }).map(
() =>
({
interactivity: undefined,
disabled: false,
} as BlockState)
),
op: Array.from({ length: 7 }).map(
() =>
({
interactivity: undefined,
disabled: false,
} as BlockState)
),
},
[SZONE]: {
me: Array.from({ length: 6 }).map(() => undefined as PlaceInteractivity),
op: Array.from({ length: 6 }).map(() => undefined as PlaceInteractivity),
me: Array.from({ length: 6 }).map(
() =>
({
interactivity: undefined,
disabled: false,
} as BlockState)
),
op: Array.from({ length: 6 }).map(
() =>
({
interactivity: undefined,
disabled: false,
} as BlockState)
),
},
},
set(
zone: ygopro.CardZone.MZONE | ygopro.CardZone.SZONE,
controller: number,
sequence: number,
placeInteractivity: PlaceInteractivity
state: BlockState
) {
placeStore.inner[zone][matStore.isMe(controller) ? "me" : "op"][sequence] =
placeInteractivity;
state;
},
clearAll() {
clearAllInteractivity() {
(["me", "op"] as const).forEach((who) => {
([MZONE, SZONE] as const).forEach((where) => {
placeStore.inner[where][who] = placeStore.inner[where][who].map(
() => undefined
placeStore.inner[where][who].forEach(
(block) => (block.interactivity = undefined)
);
});
});
......
import "./index.scss";
import classnames from "classnames";
import { type FC } from "react";
import { type CSSProperties, type FC } from "react";
import { type INTERNAL_Snapshot as Snapshot, useSnapshot } from "valtio";
import { sendSelectPlaceResponse, ygopro } from "@/api";
import { cardStore, type PlaceInteractivity, placeStore } from "@/stores";
import {
BlockState,
cardStore,
type PlaceInteractivity,
placeStore,
} from "@/stores";
// Block被禁用的样式
const BgDisabledStyle = {
background: `linear-gradient(
to top right,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0) calc(50% - 1.5px),
red 50%,
rgba(0, 0, 0, 0) calc(50% + 1.5px),
rgba(0, 0, 0, 0) 100%
), linear-gradient(
to bottom right,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0) calc(50% - 1.5px),
red 50%,
rgba(0, 0, 0, 0) calc(50% + 1.5px),
rgba(0, 0, 0, 0) 100%
)`,
};
const BgExtraRow: FC<{
meSnap: Snapshot<PlaceInteractivity[]>;
opSnap: Snapshot<PlaceInteractivity[]>;
meSnap: Snapshot<BlockState[]>;
opSnap: Snapshot<BlockState[]>;
}> = ({ meSnap, opSnap }) => {
return (
<div className={classnames("bg-row")}>
......@@ -17,11 +41,16 @@ const BgExtraRow: FC<{
<div
key={i}
className={classnames("block", "extra", {
highlight: !!meSnap[i] || !!opSnap[i],
highlight: !!meSnap[i].interactivity || !!opSnap[i].interactivity,
})}
style={
meSnap[i].disabled || opSnap[i].disabled
? (BgDisabledStyle as CSSProperties)
: {}
}
onClick={() => {
onBlockClick(meSnap[i]);
onBlockClick(opSnap[i]);
onBlockClick(meSnap[i].interactivity);
onBlockClick(opSnap[i].interactivity);
}}
></div>
))}
......@@ -32,7 +61,7 @@ const BgExtraRow: FC<{
const BgRow: FC<{
isSzone?: boolean;
opponent?: boolean;
snap: Snapshot<PlaceInteractivity[]>;
snap: Snapshot<BlockState[]>;
}> = ({ isSzone = false, opponent = false, snap }) => (
<div className={classnames("bg-row", { opponent })}>
{Array.from({ length: 5 }).map((_, i) => (
......@@ -40,9 +69,10 @@ const BgRow: FC<{
key={i}
className={classnames("block", {
szone: isSzone,
highlight: !!snap[i],
highlight: !!snap[i].interactivity,
})}
onClick={() => onBlockClick(snap[i])}
style={snap[i].disabled ? (BgDisabledStyle as CSSProperties) : {}}
onClick={() => onBlockClick(snap[i].interactivity)}
></div>
))}
</div>
......@@ -68,6 +98,6 @@ const onBlockClick = (placeInteractivity: PlaceInteractivity) => {
if (placeInteractivity) {
sendSelectPlaceResponse(placeInteractivity.response);
cardStore.inner.forEach((card) => (card.idleInteractivities = []));
placeStore.clearAll();
placeStore.clearAllInteractivity();
}
};
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