Commit 0eb554ec authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/reload_field' into 'main'

Feat/reload field

See merge request !148
parents 998fb4a9 1d44f99e
neos-protobuf @ 4f6cdd7c
Subproject commit 96e06224838437a6cd0c985070f31ddedc08ad89
Subproject commit 4f6cdd7ccc3b11b39ff8aa649e423bcf401f7ad5
This diff is collapsed.
......@@ -50,3 +50,4 @@ export const MSG_PAY_LP_COST = 100;
export const MSG_WIN = 5;
export const MSG_WAITING = 3;
export const MSG_UPDATE_DATA = 6;
export const MSG_RELOAD_FIELD = 162;
......@@ -26,6 +26,7 @@ import MsgDamage from "./damage";
import MsgRecover from "./recover";
import MsgWin from "./win";
import MsgUpdateDataAdapter from "./updateData";
import MsgReloadFieldAdapter from "./reloadField";
import PENETRATE from "./penetrate";
/*
......@@ -154,6 +155,11 @@ export default class GameMsgAdapter implements StocAdapter {
break;
}
case GAME_MSG.MSG_RELOAD_FIELD: {
gameMsg.reload_field = MsgReloadFieldAdapter(gameData);
break;
}
default: {
gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({
command: func,
......
import { ygopro } from "../../../idl/ocgcore";
// @ts-ignore
import { BufferReaderExt } from "../../bufferIO";
import MsgReloadField = ygopro.StocGameMessage.MsgReloadField;
import { numberToCardPosition } from "../../util";
export default (data: Uint8Array) => {
const reader = new BufferReaderExt(data);
const duel_rule = reader.inner.readUint8();
const actions = [];
for (let player = 0; player < 2; player++) {
const lp = reader.inner.readUint32();
const zone_actions = [];
// MZONE
for (let sequence = 0; sequence < 7; sequence++) {
const flag = reader.inner.readUint8();
if (flag) {
const position = reader.inner.readUint8();
const overlay_count = reader.inner.readUint8();
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.MZONE,
sequence,
position: numberToCardPosition(position),
overlay_count,
})
);
} else {
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.MZONE,
sequence,
position: ygopro.CardPosition.FACEDOWN,
})
);
}
}
// SZONE
for (let sequence = 0; sequence < 8; sequence++) {
const flag = reader.inner.readUint8();
if (flag) {
const position = reader.inner.readUint8();
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.SZONE,
sequence,
position: numberToCardPosition(position),
})
);
} else {
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.SZONE,
sequence,
position: ygopro.CardPosition.FACEDOWN,
})
);
}
}
const main_size = reader.inner.readUint8();
for (let sequence = 0; sequence < main_size; sequence++) {
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.DECK,
sequence,
position: ygopro.CardPosition.FACEDOWN_ATTACK,
})
);
}
const hand_size = reader.inner.readUint8();
for (let sequence = 0; sequence < hand_size; sequence++) {
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.HAND,
sequence,
})
);
}
const grave_size = reader.inner.readUint8();
for (let sequence = 0; sequence < grave_size; sequence++) {
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.GRAVE,
sequence,
})
);
}
const removed_size = reader.inner.readUint8();
for (let sequence = 0; sequence < removed_size; sequence++) {
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.REMOVED,
sequence,
})
);
}
const extra_size = reader.inner.readUint8();
for (let sequence = 0; sequence < extra_size; sequence++) {
zone_actions.push(
new MsgReloadField.ZoneAction({
zone: ygopro.CardZone.EXTRA,
sequence,
position: ygopro.CardPosition.FACEDOWN_ATTACK,
})
);
}
const _extra_p_size = reader.inner.readUint8();
// const chain_size = reader.inner.readUint8();
// const chain_actions = [];
// for (let i = 0; i < chain_size; i += 1) {
// const chain_code = reader.inner.readUint32();
// const location = reader.readCardLocation();
// const triggering_controller = reader.inner.readUint8();
// const triggering_location = reader.inner.readUint8();
// const triggering_sequence = reader.inner.readUint8();
// const effect_description = reader.inner.readUint32();
//
// chain_actions.push(
// new MsgReloadField.ChainAction({
// chain_code,
// location,
// triggering_controller,
// triggering_location,
// triggering_sequence,
// effect_description,
// })
// );
// }
actions.push(
new MsgReloadField.Action({
player,
lp,
zone_actions,
// chain_actions,
})
);
}
return new MsgReloadField({
duel_rule,
actions,
});
};
......@@ -3,9 +3,11 @@ import {
clearIdleInteractivities,
clearPlaceInteractivities,
DuelReducer,
reloadFieldMeta,
updateCardData,
} from "./generic";
import { judgeSelf } from "./util";
import MsgReloadField = ygopro.StocGameMessage.MsgReloadField;
type MsgUpdateData = ReturnType<
typeof ygopro.StocGameMessage.MsgUpdateData.prototype.toObject
>;
......@@ -124,3 +126,87 @@ export const updateFieldDataImpl: DuelReducer<MsgUpdateData> = (
}
}
};
export const reloadFieldImpl: DuelReducer<MsgReloadField> = (state, action) => {
const _duel_rule = action.payload.duel_rule;
// 初始化`DuelState`
state.meDeck = { inner: [] };
state.opDeck = { inner: [] };
state.meExtraDeck = { inner: [] };
state.opExtraDeck = { inner: [] };
state.meMonsters = { inner: [] };
state.opMonsters = { inner: [] };
state.meMagics = { inner: [] };
state.opMagics = { inner: [] };
state.meCemetery = { inner: [] };
state.opCemetery = { inner: [] };
state.meExclusion = { inner: [] };
state.opExclusion = { inner: [] };
state.meHands = { inner: [] };
state.opHands = { inner: [] };
for (const reload of action.payload.actions) {
const player = reload.player;
// DECK
const deck = judgeSelf(player, state) ? state.meDeck : state.opDeck;
reloadFieldMeta(
deck,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.DECK),
player
);
// EXTRA_DECK
const extraDeck = judgeSelf(player, state)
? state.meExtraDeck
: state.opExtraDeck;
reloadFieldMeta(
extraDeck,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.EXTRA),
player
);
// MZONE
const monster = judgeSelf(player, state)
? state.meMonsters
: state.opMonsters;
reloadFieldMeta(
monster,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.MZONE),
player
);
// SZONE
const magics = judgeSelf(player, state) ? state.meMagics : state.opMagics;
reloadFieldMeta(
magics,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.SZONE),
player
);
// GRAVE
const cemetery = judgeSelf(player, state)
? state.meCemetery
: state.opCemetery;
reloadFieldMeta(
cemetery,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.GRAVE),
player
);
// REMOVED
const exclusion = judgeSelf(player, state)
? state.meExclusion
: state.opExclusion;
reloadFieldMeta(
exclusion,
reload.zone_actions.filter(
(item) => item.zone == ygopro.CardZone.REMOVED
),
player
);
// HANDS
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
reloadFieldMeta(
hands,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.HAND),
player
);
}
};
......@@ -8,6 +8,7 @@ import { CardMeta } from "../../api/cards";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { fetchCard } from "../../api/cards";
import { DuelState } from "./mod";
import ReloadFieldAction = ygopro.StocGameMessage.MsgReloadField.ZoneAction;
type UpdateDataAction = ReturnType<
typeof ygopro.StocGameMessage.MsgUpdateData.Action.prototype.toObject
>;
......@@ -33,6 +34,7 @@ export interface CardState {
sequence: number;
}>; // 选择位置状态下的互动信息
overlay_materials?: CardMeta[]; // 超量素材
reload?: boolean; // 这个字段会在收到MSG_RELOAD_FIELD的时候设置成true,在收到MSG_UPDATE_DATE的时候设置成false
}
export enum InteractType {
......@@ -294,9 +296,11 @@ export function updateCardData<T extends DuelFieldState>(
for (const payload of actions) {
const sequence = payload.location?.sequence;
if (typeof sequence !== "undefined") {
console.log(payload.type_);
const target = state?.inner.find((_, idx) => idx == sequence);
if (target && target.occupant) {
if (target && (target.occupant || target.reload)) {
if (target.occupant === undefined) {
target.occupant = { id: payload.code!, data: {}, text: {} };
}
const occupant = target.occupant;
// 目前只更新以下字段
if (payload.code !== undefined && payload.code >= 0) {
......@@ -325,6 +329,31 @@ export function updateCardData<T extends DuelFieldState>(
occupant.data.def = payload.defense;
}
}
if (target?.reload) {
target.reload = false;
}
}
}
}
export function reloadFieldMeta<T extends DuelFieldState>(
state: T,
actions: ReloadFieldAction[],
controler: number
) {
actions.sort((a, b) => a.sequence - b.sequence);
const cards = actions.map((action) => {
// FIXME: OVERLAY
return {
location: {
controler,
location: action.zone,
position: action.position,
},
idleInteractivities: [],
reload: true,
};
});
state.inner = cards;
}
......@@ -96,6 +96,7 @@ import {
clearAllIdleInteractivitiesImpl,
clearAllPlaceInteractivitiesImpl,
updateFieldDataImpl,
reloadFieldImpl,
} from "./commonSlice";
import {
ExtraDeckState,
......@@ -258,6 +259,7 @@ const duelSlice = createSlice({
clearAllIdleInteractivities: clearAllIdleInteractivitiesImpl,
clearAllPlaceInteractivities: clearAllPlaceInteractivitiesImpl,
updateFieldData: updateFieldDataImpl,
reloadField: reloadFieldImpl,
// 对局结果`Reducer`
setResult: (state, action: PayloadAction<MsgWin.ActionType>) => {
......@@ -355,6 +357,7 @@ export const {
setWaiting,
setUnimplemented,
updateFieldData,
reloadField,
} = duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => {
return state.duel.meInitInfo != null;
......
......@@ -23,6 +23,7 @@ import onMsgWin from "./win";
import onMsgWait from "./wait";
import onUnimplemented from "./unimplemented";
import onMsgUpdateData from "./updateData";
import onMsgReloadField from "./reloadField";
import { setWaiting } from "../../reducers/duel/mod";
const ActiveList = [
......@@ -157,6 +158,11 @@ export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
break;
}
case "reload_field": {
onMsgReloadField(msg.reload_field, dispatch);
break;
}
case "unimplemented": {
onUnimplemented(msg.unimplemented, dispatch);
......
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { reloadField } from "../../reducers/duel/mod";
import { AppDispatch } from "../../store";
import MsgReloadField = ygopro.StocGameMessage.MsgReloadField;
export default (field: MsgReloadField, dispatch: AppDispatch) => {
dispatch(reloadField(field));
};
......@@ -19,7 +19,7 @@ export const store = configureStore({
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: ["duel/updateHp"],
ignoredActions: ["duel/updateHp", "duel/reloadField"],
},
}),
});
......
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