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

Merge branch 'feat/reload_field' into 'main'

Feat/reload field

See merge request mycard/Neos!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; ...@@ -50,3 +50,4 @@ export const MSG_PAY_LP_COST = 100;
export const MSG_WIN = 5; export const MSG_WIN = 5;
export const MSG_WAITING = 3; export const MSG_WAITING = 3;
export const MSG_UPDATE_DATA = 6; export const MSG_UPDATE_DATA = 6;
export const MSG_RELOAD_FIELD = 162;
...@@ -26,6 +26,7 @@ import MsgDamage from "./damage"; ...@@ -26,6 +26,7 @@ import MsgDamage from "./damage";
import MsgRecover from "./recover"; import MsgRecover from "./recover";
import MsgWin from "./win"; import MsgWin from "./win";
import MsgUpdateDataAdapter from "./updateData"; import MsgUpdateDataAdapter from "./updateData";
import MsgReloadFieldAdapter from "./reloadField";
import PENETRATE from "./penetrate"; import PENETRATE from "./penetrate";
/* /*
...@@ -154,6 +155,11 @@ export default class GameMsgAdapter implements StocAdapter { ...@@ -154,6 +155,11 @@ export default class GameMsgAdapter implements StocAdapter {
break; break;
} }
case GAME_MSG.MSG_RELOAD_FIELD: {
gameMsg.reload_field = MsgReloadFieldAdapter(gameData);
break;
}
default: { default: {
gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({ gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({
command: func, 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 { ...@@ -3,9 +3,11 @@ import {
clearIdleInteractivities, clearIdleInteractivities,
clearPlaceInteractivities, clearPlaceInteractivities,
DuelReducer, DuelReducer,
reloadFieldMeta,
updateCardData, updateCardData,
} from "./generic"; } from "./generic";
import { judgeSelf } from "./util"; import { judgeSelf } from "./util";
import MsgReloadField = ygopro.StocGameMessage.MsgReloadField;
type MsgUpdateData = ReturnType< type MsgUpdateData = ReturnType<
typeof ygopro.StocGameMessage.MsgUpdateData.prototype.toObject typeof ygopro.StocGameMessage.MsgUpdateData.prototype.toObject
>; >;
...@@ -124,3 +126,87 @@ export const updateFieldDataImpl: DuelReducer<MsgUpdateData> = ( ...@@ -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"; ...@@ -8,6 +8,7 @@ import { CardMeta } from "../../api/cards";
import { ygopro } from "../../api/ocgcore/idl/ocgcore"; import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { fetchCard } from "../../api/cards"; import { fetchCard } from "../../api/cards";
import { DuelState } from "./mod"; import { DuelState } from "./mod";
import ReloadFieldAction = ygopro.StocGameMessage.MsgReloadField.ZoneAction;
type UpdateDataAction = ReturnType< type UpdateDataAction = ReturnType<
typeof ygopro.StocGameMessage.MsgUpdateData.Action.prototype.toObject typeof ygopro.StocGameMessage.MsgUpdateData.Action.prototype.toObject
>; >;
...@@ -33,6 +34,7 @@ export interface CardState { ...@@ -33,6 +34,7 @@ export interface CardState {
sequence: number; sequence: number;
}>; // 选择位置状态下的互动信息 }>; // 选择位置状态下的互动信息
overlay_materials?: CardMeta[]; // 超量素材 overlay_materials?: CardMeta[]; // 超量素材
reload?: boolean; // 这个字段会在收到MSG_RELOAD_FIELD的时候设置成true,在收到MSG_UPDATE_DATE的时候设置成false
} }
export enum InteractType { export enum InteractType {
...@@ -294,9 +296,11 @@ export function updateCardData<T extends DuelFieldState>( ...@@ -294,9 +296,11 @@ export function updateCardData<T extends DuelFieldState>(
for (const payload of actions) { for (const payload of actions) {
const sequence = payload.location?.sequence; const sequence = payload.location?.sequence;
if (typeof sequence !== "undefined") { if (typeof sequence !== "undefined") {
console.log(payload.type_);
const target = state?.inner.find((_, idx) => idx == sequence); 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; const occupant = target.occupant;
// 目前只更新以下字段 // 目前只更新以下字段
if (payload.code !== undefined && payload.code >= 0) { if (payload.code !== undefined && payload.code >= 0) {
...@@ -325,6 +329,31 @@ export function updateCardData<T extends DuelFieldState>( ...@@ -325,6 +329,31 @@ export function updateCardData<T extends DuelFieldState>(
occupant.data.def = payload.defense; 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 { ...@@ -96,6 +96,7 @@ import {
clearAllIdleInteractivitiesImpl, clearAllIdleInteractivitiesImpl,
clearAllPlaceInteractivitiesImpl, clearAllPlaceInteractivitiesImpl,
updateFieldDataImpl, updateFieldDataImpl,
reloadFieldImpl,
} from "./commonSlice"; } from "./commonSlice";
import { import {
ExtraDeckState, ExtraDeckState,
...@@ -258,6 +259,7 @@ const duelSlice = createSlice({ ...@@ -258,6 +259,7 @@ const duelSlice = createSlice({
clearAllIdleInteractivities: clearAllIdleInteractivitiesImpl, clearAllIdleInteractivities: clearAllIdleInteractivitiesImpl,
clearAllPlaceInteractivities: clearAllPlaceInteractivitiesImpl, clearAllPlaceInteractivities: clearAllPlaceInteractivitiesImpl,
updateFieldData: updateFieldDataImpl, updateFieldData: updateFieldDataImpl,
reloadField: reloadFieldImpl,
// 对局结果`Reducer` // 对局结果`Reducer`
setResult: (state, action: PayloadAction<MsgWin.ActionType>) => { setResult: (state, action: PayloadAction<MsgWin.ActionType>) => {
...@@ -355,6 +357,7 @@ export const { ...@@ -355,6 +357,7 @@ export const {
setWaiting, setWaiting,
setUnimplemented, setUnimplemented,
updateFieldData, updateFieldData,
reloadField,
} = duelSlice.actions; } = duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => { export const selectDuelHsStart = (state: RootState) => {
return state.duel.meInitInfo != null; return state.duel.meInitInfo != null;
......
...@@ -23,6 +23,7 @@ import onMsgWin from "./win"; ...@@ -23,6 +23,7 @@ import onMsgWin from "./win";
import onMsgWait from "./wait"; import onMsgWait from "./wait";
import onUnimplemented from "./unimplemented"; import onUnimplemented from "./unimplemented";
import onMsgUpdateData from "./updateData"; import onMsgUpdateData from "./updateData";
import onMsgReloadField from "./reloadField";
import { setWaiting } from "../../reducers/duel/mod"; import { setWaiting } from "../../reducers/duel/mod";
const ActiveList = [ const ActiveList = [
...@@ -157,6 +158,11 @@ export default function handleGameMsg(pb: ygopro.YgoStocMsg) { ...@@ -157,6 +158,11 @@ export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
break; break;
} }
case "reload_field": {
onMsgReloadField(msg.reload_field, dispatch);
break;
}
case "unimplemented": { case "unimplemented": {
onUnimplemented(msg.unimplemented, dispatch); 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({ ...@@ -19,7 +19,7 @@ export const store = configureStore({
middleware: (getDefaultMiddleware) => middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ getDefaultMiddleware({
serializableCheck: { 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