Commit 0536f9ab authored by Chunchi Che's avatar Chunchi Che

Merge branch 'optimize/idle_cmd' into 'main'

Optimize/idle cmd

See merge request mycard/Neos!79
parents c59e11f2 2767c807
neos-protobuf @ a5908aff
Subproject commit 9b1e1b0fdb8982b80c535178f44981cb17206866
Subproject commit a5908affcf8a663bd2d5e0bf8acf9f77162f7d64
......@@ -42,7 +42,7 @@ export namespace ygopro {
| {
code?: number;
controler?: number;
location?: number;
location?: CardZone;
sequence?: number;
}
) {
......@@ -83,9 +83,13 @@ export namespace ygopro {
pb_1.Message.setField(this, 2, value);
}
get location() {
return pb_1.Message.getFieldWithDefault(this, 3, 0) as number;
return pb_1.Message.getFieldWithDefault(
this,
3,
CardZone.DECK
) as CardZone;
}
set location(value: number) {
set location(value: CardZone) {
pb_1.Message.setField(this, 3, value);
}
get sequence() {
......@@ -97,7 +101,7 @@ export namespace ygopro {
static fromObject(data: {
code?: number;
controler?: number;
location?: number;
location?: CardZone;
sequence?: number;
}): CardInfo {
const message = new CardInfo({});
......@@ -119,7 +123,7 @@ export namespace ygopro {
const data: {
code?: number;
controler?: number;
location?: number;
location?: CardZone;
sequence?: number;
} = {};
if (this.code != null) {
......@@ -142,7 +146,7 @@ export namespace ygopro {
const writer = w || new pb_1.BinaryWriter();
if (this.code != 0) writer.writeInt32(1, this.code);
if (this.controler != 0) writer.writeInt32(2, this.controler);
if (this.location != 0) writer.writeInt32(3, this.location);
if (this.location != CardZone.DECK) writer.writeEnum(3, this.location);
if (this.sequence != 0) writer.writeInt32(4, this.sequence);
if (!w) return writer.getResultBuffer();
}
......@@ -162,7 +166,7 @@ export namespace ygopro {
message.controler = reader.readInt32();
break;
case 3:
message.location = reader.readInt32();
message.location = reader.readEnum();
break;
case 4:
message.sequence = reader.readInt32();
......@@ -187,7 +191,7 @@ export namespace ygopro {
| any[]
| {
controler?: number;
location?: number;
location?: CardZone;
sequence?: number;
position?: CardPosition;
overlay_sequence?: number;
......@@ -227,9 +231,13 @@ export namespace ygopro {
pb_1.Message.setField(this, 1, value);
}
get location() {
return pb_1.Message.getFieldWithDefault(this, 2, 0) as number;
return pb_1.Message.getFieldWithDefault(
this,
2,
CardZone.DECK
) as CardZone;
}
set location(value: number) {
set location(value: CardZone) {
pb_1.Message.setField(this, 2, value);
}
get sequence() {
......@@ -256,7 +264,7 @@ export namespace ygopro {
}
static fromObject(data: {
controler?: number;
location?: number;
location?: CardZone;
sequence?: number;
position?: CardPosition;
overlay_sequence?: number;
......@@ -282,7 +290,7 @@ export namespace ygopro {
toObject() {
const data: {
controler?: number;
location?: number;
location?: CardZone;
sequence?: number;
position?: CardPosition;
overlay_sequence?: number;
......@@ -309,7 +317,7 @@ export namespace ygopro {
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
const writer = w || new pb_1.BinaryWriter();
if (this.controler != 0) writer.writeInt32(1, this.controler);
if (this.location != 0) writer.writeInt32(2, this.location);
if (this.location != CardZone.DECK) writer.writeEnum(2, this.location);
if (this.sequence != 0) writer.writeInt32(3, this.sequence);
if (this.position != CardPosition.FACEUP_ATTACK)
writer.writeEnum(4, this.position);
......@@ -330,7 +338,7 @@ export namespace ygopro {
message.controler = reader.readInt32();
break;
case 2:
message.location = reader.readInt32();
message.location = reader.readEnum();
break;
case 3:
message.sequence = reader.readInt32();
......
......@@ -54,14 +54,17 @@ export class BufferReader {
}
readCardInfo(): ygopro.CardInfo {
const cardInfo = new ygopro.CardInfo({});
cardInfo.code = this.readUint32();
cardInfo.controler = this.readUint8();
cardInfo.location = this.readUint8();
cardInfo.sequence = this.readUint8();
const code = this.readUint32();
const controler = this.readUint8();
const location = numberToCardZone(this.readUint8());
const sequence = this.readUint8();
return cardInfo;
return new ygopro.CardInfo({
code,
controler,
location,
sequence,
});
}
readCardLocation(overlay?: boolean): ygopro.CardLocation {
......
......@@ -3,7 +3,7 @@ import { DuelState } from "./mod";
import { RootState } from "../../store";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { PayloadAction, CaseReducer } from "@reduxjs/toolkit";
import { CardState, InteractType } from "./generic";
import { CardState, Interactivity, InteractType } from "./generic";
export interface FieldState {
inner?: CardState;
......@@ -69,5 +69,35 @@ export const clearFieldPlaceInteractivitiesImpl: CaseReducer<
}
};
export const addFieldIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}>
> = (state, action) => {
const field = judgeSelf(action.payload.player, state)
? state.meField
: state.opField;
if (field && field.inner) {
field.inner.idleInteractivities.push(action.payload.interactivity);
}
};
export const clearFieldIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const field = judgeSelf(action.payload, state)
? state.meField
: state.opField;
if (field && field.inner) {
field.inner.idleInteractivities = [];
}
};
export const selectMeField = (state: RootState) => state.duel.meField;
export const selectOpField = (state: RootState) => state.duel.opField;
......@@ -224,3 +224,26 @@ export function updateCardMeta<T extends DuelFieldState>(
});
}
}
export function extendIdleInteractivities<T extends DuelFieldState>(
state: T | undefined,
sequence: number,
interactivity: Interactivity<number>
) {
if (state) {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.idleInteractivities.push(interactivity);
}
}
}
export function clearIdleInteractivities<T extends DuelFieldState>(
state: T | undefined
) {
if (state) {
state.inner.forEach((item) => {
item.idleInteractivities = [];
});
}
}
......@@ -14,6 +14,9 @@ import {
extendPlaceInteractivity,
clearPlaceInteractivities,
removeOccupant,
Interactivity,
extendIdleInteractivities,
clearIdleInteractivities,
} from "./generic";
export interface MagicState extends DuelFieldState {}
......@@ -97,6 +100,35 @@ export const clearMagicPlaceInteractivitiesImpl: CaseReducer<
clearPlaceInteractivities(magics);
};
export const addMagicIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}>
> = (state, action) => {
const magics = judgeSelf(action.payload.player, state)
? state.meMagics
: state.opMagics;
extendIdleInteractivities(
magics,
action.payload.sequence,
action.payload.interactivity
);
};
export const clearMagicIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const magics = judgeSelf(action.payload, state)
? state.meMagics
: state.opMagics;
clearIdleInteractivities(magics);
};
// 增加魔法陷阱
export const fetchMagicMeta = createAsyncMetaThunk("duel/fetchMagicMeta");
......
......@@ -46,6 +46,8 @@ import {
initMonstersImpl,
addMonsterPlaceInteractivitiesImpl,
clearMonsterPlaceInteractivitiesImpl,
addMonsterIdleInteractivitiesImpl,
clearMonsterIdleInteractivitiesImpl,
removeMonsterImpl,
monsterCase,
} from "./monstersSlice";
......@@ -54,6 +56,8 @@ import {
initMagicsImpl,
addMagicPlaceInteractivitiesImpl,
clearMagicPlaceInteractivitiesImpl,
addMagicIdleInteractivitiesImpl,
clearMagicIdleInteractivitiesImpl,
removeMagicImpl,
magicCase,
} from "./magicSlice";
......@@ -69,6 +73,8 @@ import {
initFieldImpl,
clearFieldPlaceInteractivitiesImpl,
addFieldPlaceInteractivitiesImpl,
addFieldIdleInteractivitiesImpl,
clearFieldIdleInteractivitiesImpl,
} from "./fieldSlice";
export interface DuelState {
......@@ -142,12 +148,16 @@ const duelSlice = createSlice({
initMonsters: initMonstersImpl,
addMonsterPlaceInteractivities: addMonsterPlaceInteractivitiesImpl,
clearMonsterPlaceInteractivities: clearMonsterPlaceInteractivitiesImpl,
addMonsterIdleInteractivities: addMonsterIdleInteractivitiesImpl,
clearMonsterIdleInteractivities: clearMonsterIdleInteractivitiesImpl,
removeMonster: removeMonsterImpl,
// 魔法陷阱区相关`Reducer`
initMagics: initMagicsImpl,
addMagicPlaceInteractivities: addMagicPlaceInteractivitiesImpl,
clearMagicPlaceInteractivities: clearMagicPlaceInteractivitiesImpl,
addMagicIdleInteractivities: addMagicIdleInteractivitiesImpl,
clearMagicIdleInteractivities: clearMagicIdleInteractivitiesImpl,
removeMagic: removeMagicImpl,
// 墓地相关`Reducer`
......@@ -163,6 +173,8 @@ const duelSlice = createSlice({
initField: initFieldImpl,
clearFieldPlaceInteractivities: clearFieldPlaceInteractivitiesImpl,
addFieldPlaceInteractivities: addFieldPlaceInteractivitiesImpl,
addFieldIdleInteractivities: addFieldIdleInteractivitiesImpl,
clearFieldIdleInteractivities: clearFieldIdleInteractivitiesImpl,
// UI相关`Reducer`
setCardModalIsOpen: setCardModalIsOpenImpl,
......@@ -212,10 +224,14 @@ export const {
initMonsters,
addMonsterPlaceInteractivities,
clearMonsterPlaceInteractivities,
addMonsterIdleInteractivities,
clearMonsterIdleInteractivities,
removeMonster,
initMagics,
addMagicPlaceInteractivities,
clearMagicPlaceInteractivities,
addMagicIdleInteractivities,
clearMagicIdleInteractivities,
removeMagic,
removeHand,
initCemetery,
......@@ -238,6 +254,8 @@ export const {
initField,
clearFieldPlaceInteractivities,
addFieldPlaceInteractivities,
addFieldIdleInteractivities,
clearFieldIdleInteractivities,
} = duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => {
return state.duel.meInitInfo != null;
......
......@@ -9,11 +9,14 @@ import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { RootState } from "../../store";
import {
DuelFieldState,
Interactivity,
createAsyncMetaThunk,
extendOccupant,
extendPlaceInteractivity,
clearPlaceInteractivities,
removeOccupant,
extendIdleInteractivities,
clearIdleInteractivities,
} from "./generic";
export interface MonsterState extends DuelFieldState {}
......@@ -107,6 +110,35 @@ export const clearMonsterPlaceInteractivitiesImpl: CaseReducer<
clearPlaceInteractivities(monsters);
};
export const addMonsterIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}>
> = (state, action) => {
const monsters = judgeSelf(action.payload.player, state)
? state.meMonsters
: state.opMonsters;
extendIdleInteractivities(
monsters,
action.payload.sequence,
action.payload.interactivity
);
};
export const clearMonsterIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const monsters = judgeSelf(action.payload, state)
? state.meMonsters
: state.opMonsters;
clearIdleInteractivities(monsters);
};
// 增加怪兽
export const fetchMonsterMeta = createAsyncMetaThunk("duel/fetchMonsterMeta");
......
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store";
import { InteractType } from "../../reducers/duel/generic";
import { Interactivity, InteractType } from "../../reducers/duel/generic";
import {
clearHandsIdleInteractivity,
addHandsIdleInteractivity,
addMonsterIdleInteractivities,
addMagicIdleInteractivities,
clearMonsterIdleInteractivities,
clearMagicIdleInteractivities,
clearFieldIdleInteractivities,
addFieldIdleInteractivities,
} from "../../reducers/duel/mod";
import MsgSelectIdleCmd = ygopro.StocGameMessage.MsgSelectIdleCmd;
import { ActionCreatorWithPayload } from "@reduxjs/toolkit";
export default (selectIdleCmd: MsgSelectIdleCmd, dispatch: AppDispatch) => {
const player = selectIdleCmd.player;
const cmds = selectIdleCmd.idle_cmds;
// 先清掉之前的手牌互动性
// 先清掉之前的互动性
dispatch(clearHandsIdleInteractivity(player));
dispatch(clearMonsterIdleInteractivities(player));
dispatch(clearMagicIdleInteractivities(player));
dispatch(clearFieldIdleInteractivities(player));
for (let cmd of cmds) {
let interactType;
switch (cmd.idle_type) {
case MsgSelectIdleCmd.IdleCmd.IdleType.SUMMON: {
interactType = InteractType.SUMMON;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.SPSUMMON: {
interactType = InteractType.SP_SUMMON;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.POS_CHANGE: {
interactType = InteractType.POS_CHANGE;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.MSET: {
interactType = InteractType.MSET;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.SSET: {
interactType = InteractType.SSET;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.ACTIVATE: {
interactType = InteractType.ACTIVATE;
break;
}
const dispatcher = (
idleData: MsgSelectIdleCmd.IdleCmd.IdleData,
interactType: InteractType | undefined,
actionCreator: ActionCreatorWithPayload<
{
player: number;
sequence: number;
interactivity: Interactivity<number>;
},
string
>
) => {
const cardInfo = idleData.card_info;
if (interactType === InteractType.ACTIVATE) {
// 发动效果会多一个字段
dispatch(
actionCreator({
player,
sequence: cardInfo.sequence,
interactivity: {
interactType,
activateIndex: idleData.effect_description,
response: idleData.response,
},
})
);
} else if (interactType) {
dispatch(
actionCreator({
player,
sequence: cardInfo.sequence,
interactivity: { interactType, response: idleData.response },
})
);
} else {
console.log(`InteractType undefined`);
}
};
cmds.forEach((cmd) => {
const interactType = idleTypeToInteractType(cmd.idle_type);
cmd.idle_datas.forEach((data) => {
const cardInfo = data.card_info;
switch (cardInfo.location) {
case ygopro.CardZone.HAND: {
dispatcher(data, interactType, addHandsIdleInteractivity);
break;
}
case ygopro.CardZone.MZONE: {
dispatcher(data, interactType, addMonsterIdleInteractivities);
break;
}
case ygopro.CardZone.SZONE: {
dispatcher(data, interactType, addMagicIdleInteractivities);
for (let data of cmd.idle_datas) {
const card_info = data.card_info;
if (card_info.location === 2) {
// 目前只处理手牌场景
if (interactType === InteractType.ACTIVATE) {
// 发动效果会多一个字段
dispatch(
addHandsIdleInteractivity({
player,
sequence: card_info.sequence,
interactivity: {
interactType,
activateIndex: data.effect_description,
response: data.response,
},
})
);
} else if (interactType) {
dispatch(
addHandsIdleInteractivity({
player,
sequence: card_info.sequence,
interactivity: { interactType, response: data.response },
})
);
break;
}
case ygopro.CardZone.ONFIELD: {
dispatcher(data, interactType, addFieldIdleInteractivities);
break;
}
default: {
}
}
});
});
};
function idleTypeToInteractType(
idleType: MsgSelectIdleCmd.IdleCmd.IdleType
): InteractType | undefined {
switch (idleType) {
case MsgSelectIdleCmd.IdleCmd.IdleType.SUMMON: {
return InteractType.SUMMON;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.SPSUMMON: {
return InteractType.SP_SUMMON;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.POS_CHANGE: {
return InteractType.POS_CHANGE;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.MSET: {
return InteractType.MSET;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.SSET: {
return InteractType.SSET;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.ACTIVATE: {
return InteractType.ACTIVATE;
}
default: {
return undefined;
}
}
};
}
......@@ -13,6 +13,7 @@ import {
setCardModalText,
} from "../../reducers/duel/mod";
import { ActionCreatorWithPayload } from "@reduxjs/toolkit";
import { interactTypeToString } from "./util";
const shape = CONFIG.CardSlotShape();
......@@ -59,7 +60,16 @@ const FixedSlot = (props: {
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${props.state.occupant.id}.jpg`
)
);
dispatch(setCardModalInteractivies([])); // TODO
dispatch(
setCardModalInteractivies(
props.state.idleInteractivities.map((interactivity) => {
return {
desc: interactTypeToString(interactivity.interactType),
response: interactivity.response,
};
})
)
);
dispatch(setCardModalIsOpen(true));
}
},
......
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