Commit ddd5f1ac authored by Chunchi Che's avatar Chunchi Che

Merge branch 'optimize/move' into 'main'

Optimize/move

See merge request !75
parents d521a1cd 25910ff5
Pipeline #19515 passed with stages
in 3 minutes and 10 seconds
......@@ -22,7 +22,6 @@ export const initDeckImpl: CaseReducer<
location: {
controler: player,
location: ygopro.CardZone.DECK,
sequence: i,
},
idleInteractivities: [],
});
......
......@@ -20,7 +20,6 @@ export const initFieldImpl: CaseReducer<DuelState, PayloadAction<number>> = (
inner: {
location: {
controler: player,
sequence: 0,
location: ygopro.CardZone.ONFIELD,
},
idleInteractivities: [],
......@@ -31,7 +30,6 @@ export const initFieldImpl: CaseReducer<DuelState, PayloadAction<number>> = (
inner: {
location: {
controler: player,
sequence: 0,
location: ygopro.CardZone.ONFIELD,
},
idleInteractivities: [],
......
......@@ -12,7 +12,6 @@ export interface CardState {
location: {
controler: number;
location?: number;
sequence: number;
position?: ygopro.CardPosition;
overlay_sequence?: number;
}; // 位置信息
......@@ -97,12 +96,11 @@ export function extendOccupant<T extends DuelFieldState>(
position?: ygopro.CardPosition
) {
if (state) {
for (const item of state.inner) {
if (item.location.sequence == sequence) {
item.occupant = newMeta;
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.occupant = newMeta;
if (position) {
item.location.position = position;
}
target.location.position = position;
}
}
}
......@@ -114,10 +112,9 @@ export function extendMeta<T extends DuelFieldState>(
sequence: number
) {
if (state) {
for (const item of state.inner) {
if (item.location.sequence == sequence) {
item.occupant = newMeta;
}
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.occupant = newMeta;
}
}
}
......@@ -129,9 +126,9 @@ export function extendPlaceInteractivity<T extends DuelFieldState>(
zone: ygopro.CardZone
) {
if (state) {
for (let item of state.inner) {
if (item.location.sequence == sequence) {
item.placeInteractivities = {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.placeInteractivities = {
interactType: InteractType.PLACE_SELECTABLE,
response: {
controler,
......@@ -141,7 +138,6 @@ export function extendPlaceInteractivity<T extends DuelFieldState>(
};
}
}
}
}
export function clearPlaceInteractivities<T extends DuelFieldState>(
......@@ -153,3 +149,34 @@ export function clearPlaceInteractivities<T extends DuelFieldState>(
}
}
}
export function removeCard<T extends DuelFieldState>(
state: T | undefined,
sequence: number
) {
if (state) {
state.inner = state.inner.filter((_, idx) => idx != sequence);
}
}
export function removeOccupant<T extends DuelFieldState>(
state: T | undefined,
sequence: number
) {
if (state) {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.occupant = undefined;
}
}
}
export function insertCard<T extends DuelFieldState>(
state: T | undefined,
sequence: number,
card: CardState
) {
if (state) {
state.inner.splice(sequence, 0, card);
}
}
......@@ -8,7 +8,14 @@ import { DuelState } from "./mod";
import { RootState } from "../../store";
import { fetchCard, CardMeta } from "../../api/cards";
import { judgeSelf } from "./util";
import { Interactivity, DuelFieldState } from "./generic";
import {
Interactivity,
DuelFieldState,
removeCard,
createAsyncMetaThunk,
insertCard,
extendMeta,
} from "./generic";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
export interface HandState extends DuelFieldState {}
......@@ -35,6 +42,56 @@ export const fetchHandsMeta = createAsyncThunk(
}
);
// 清空手牌互动性
export const clearHandsIdleInteractivityImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const player = action.payload;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
if (hands) {
for (let hand of hands.inner) {
hand.idleInteractivities = [];
}
}
};
// 添加手牌互动性
export const addHandsIdleInteractivityImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}>
> = (state, action) => {
const player = action.payload.player;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
if (hands) {
const sequence = action.payload.sequence;
const interactivity = action.payload.interactivity;
hands.inner[sequence].idleInteractivities.push(interactivity);
}
};
// 删除手牌
export const removeHandImpl: CaseReducer<
DuelState,
PayloadAction<[number, number]>
> = (state, action) => {
const controler = action.payload[0];
const sequence = action.payload[1];
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
removeCard(hands, sequence);
};
export const insertHandMeta = createAsyncMetaThunk("duel/insertHandMeta");
export const handsCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchHandsMeta.pending, (state, action) => {
// Meta结果没返回之前先更新手牌`ID`
......@@ -82,60 +139,33 @@ export const handsCase = (builder: ActionReducerMapBuilder<DuelState>) => {
}
}
});
};
// 清空手牌互动性
export const clearHandsIdleInteractivityImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const player = action.payload;
builder.addCase(insertHandMeta.pending, (state, action) => {
const controler = action.meta.arg.controler;
const sequence = action.meta.arg.sequence;
const code = action.meta.arg.code;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
if (hands) {
for (let hand of hands.inner) {
hand.idleInteractivities = [];
}
}
};
// 添加手牌互动性
export const addHandsIdleInteractivityImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}>
> = (state, action) => {
const player = action.payload.player;
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
if (hands) {
insertCard(hands, sequence, {
occupant: { id: code, data: {}, text: {} },
location: { controler },
idleInteractivities: [],
});
});
builder.addCase(insertHandMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const interactivity = action.payload.interactivity;
hands.inner[sequence].idleInteractivities.push(interactivity);
}
};
// 删除手牌
export const removeHandImpl: CaseReducer<
DuelState,
PayloadAction<[number, number]>
> = (state, action) => {
const controler = action.payload[0];
const sequence = action.payload[1];
const meta = action.payload.meta;
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
if (hands) {
hands.inner = hands.inner.filter(
(card) => card.location.sequence != sequence
);
}
extendMeta(hands, meta, sequence);
});
};
// 在特定位置增加手牌
export const selectMeHands = (state: RootState) =>
state.duel.meHands || { inner: [] };
export const selectOpHands = (state: RootState) =>
......
......@@ -13,6 +13,7 @@ import {
extendOccupant,
extendPlaceInteractivity,
clearPlaceInteractivities,
removeOccupant,
} from "./generic";
export interface MagicState extends DuelFieldState {}
......@@ -127,6 +128,18 @@ export const magicCase = (builder: ActionReducerMapBuilder<DuelState>) => {
});
};
// 删除魔法陷阱
export const removeMagicImpl: CaseReducer<
DuelState,
PayloadAction<{ controler: number; sequence: number }>
> = (state, action) => {
const controler = action.payload.controler;
const magics = judgeSelf(controler, state) ? state.meMagics : state.opMagics;
removeOccupant(magics, action.payload.sequence);
};
export const selectMeMagics = (state: RootState) =>
state.duel.meMagics || { inner: [] };
export const selectOpMagics = (state: RootState) =>
......
......@@ -46,6 +46,7 @@ import {
initMonstersImpl,
addMonsterPlaceInteractivitiesImpl,
clearMonsterPlaceInteractivitiesImpl,
removeMonsterImpl,
monsterCase,
} from "./monstersSlice";
import {
......@@ -53,6 +54,7 @@ import {
initMagicsImpl,
addMagicPlaceInteractivitiesImpl,
clearMagicPlaceInteractivitiesImpl,
removeMagicImpl,
magicCase,
} from "./magicSlice";
import { CemeteryState, initCemeteryImpl, cemeteryCase } from "./cemeretySlice";
......@@ -135,11 +137,13 @@ const duelSlice = createSlice({
initMonsters: initMonstersImpl,
addMonsterPlaceInteractivities: addMonsterPlaceInteractivitiesImpl,
clearMonsterPlaceInteractivities: clearMonsterPlaceInteractivitiesImpl,
removeMonster: removeMonsterImpl,
// 魔法陷阱区相关`Reducer`
initMagics: initMagicsImpl,
addMagicPlaceInteractivities: addMagicPlaceInteractivitiesImpl,
clearMagicPlaceInteractivities: clearMagicPlaceInteractivitiesImpl,
removeMagic: removeMagicImpl,
// 墓地相关`Reducer`
initCemetery: initCemeteryImpl,
......@@ -201,9 +205,11 @@ export const {
initMonsters,
addMonsterPlaceInteractivities,
clearMonsterPlaceInteractivities,
removeMonster,
initMagics,
addMagicPlaceInteractivities,
clearMagicPlaceInteractivities,
removeMagic,
removeHand,
initCemetery,
setCardListModalIsOpen,
......
......@@ -13,6 +13,7 @@ import {
extendOccupant,
extendPlaceInteractivity,
clearPlaceInteractivities,
removeOccupant,
} from "./generic";
export interface MonsterState extends DuelFieldState {}
......@@ -137,6 +138,20 @@ export const monsterCase = (builder: ActionReducerMapBuilder<DuelState>) => {
});
};
// 删除怪兽
export const removeMonsterImpl: CaseReducer<
DuelState,
PayloadAction<{ controler: number; sequence: number }>
> = (state, action) => {
const controler = action.payload.controler;
const monsters = judgeSelf(controler, state)
? state.meMonsters
: state.opMonsters;
removeOccupant(monsters, action.payload.sequence);
};
export const selectMeMonsters = (state: RootState) =>
state.duel.meMonsters || { inner: [] };
export const selectOpMonsters = (state: RootState) =>
......
......@@ -2,9 +2,14 @@ import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import MsgMove = ygopro.StocGameMessage.MsgMove;
import { AppDispatch } from "../../store";
import { fetchMonsterMeta } from "../../reducers/duel/monstersSlice";
import { removeHand } from "../../reducers/duel/mod";
import {
removeHand,
removeMagic,
removeMonster,
} from "../../reducers/duel/mod";
import { fetchMagicMeta } from "../../reducers/duel/magicSlice";
import { fetchCemeteryMeta } from "../../reducers/duel/cemeretySlice";
import { insertHandMeta } from "../../reducers/duel/handsSlice";
export default (move: MsgMove, dispatch: AppDispatch) => {
const code = move.code;
......@@ -18,6 +23,20 @@ export default (move: MsgMove, dispatch: AppDispatch) => {
break;
}
case ygopro.CardZone.MZONE: {
dispatch(
removeMonster({ controler: from.controler, sequence: from.sequence })
);
break;
}
case ygopro.CardZone.SZONE: {
dispatch(
removeMagic({ controler: from.controler, sequence: from.sequence })
);
break;
}
default: {
console.log(`Unhandled zone type ${from.location}`);
break;
......@@ -60,6 +79,13 @@ export default (move: MsgMove, dispatch: AppDispatch) => {
break;
}
case ygopro.CardZone.HAND: {
dispatch(
insertHandMeta({ controler: to.controler, sequence: to.sequence, code })
);
break;
}
default: {
console.log(`Unhandled zone type ${to.location}`);
......
......@@ -14,6 +14,7 @@ const Field = () => {
{meField ? (
<FixedSlot
state={meField}
sequence={0}
position={fieldPosition(0)}
rotation={CONFIG.CardSlotRotation(false)}
/>
......@@ -23,6 +24,7 @@ const Field = () => {
{opField ? (
<FixedSlot
state={opField}
sequence={0}
position={fieldPosition(1)}
rotation={CONFIG.CardSlotRotation(true)}
/>
......
......@@ -18,6 +18,7 @@ const shape = CONFIG.CardSlotShape();
const FixedSlot = (props: {
state: CardState;
sequence: number;
position: BABYLON.Vector3;
rotation: BABYLON.Vector3;
deffenseRotation?: BABYLON.Vector3;
......@@ -67,7 +68,7 @@ const FixedSlot = (props: {
return (
<plane
name={`fixedslot-${props.state.location.sequence}`}
name={`fixedslot-${props.sequence}`}
ref={planeRef}
width={shape.width}
height={shape.height}
......@@ -83,7 +84,7 @@ const FixedSlot = (props: {
edgesColor={edgesColor}
>
<standardMaterial
name={`fixedslot-mat-${props.state.location.sequence}`}
name={`fixedslot-mat-${props.sequence}`}
diffuseTexture={
props.state.occupant
? faceDown
......
......@@ -19,21 +19,23 @@ const Magics = () => {
return (
<>
{zip(meMagics, meMagicPositions).map(([magic, position]) => {
{zip(meMagics, meMagicPositions).map(([magic, position], sequence) => {
return (
<FixedSlot
state={magic}
key={magic.location.sequence}
key={sequence}
sequence={sequence}
position={position}
rotation={CONFIG.CardSlotRotation(false)}
/>
);
})}
{zip(opMagics, opMagicPositions).map(([magic, position]) => {
{zip(opMagics, opMagicPositions).map(([magic, position], sequence) => {
return (
<FixedSlot
state={magic}
key={magic.location.sequence}
key={sequence}
sequence={sequence}
position={position}
rotation={CONFIG.CardSlotRotation(true)}
/>
......@@ -49,9 +51,7 @@ const magicPositions = (player: number, magics: CardState[]) => {
const y = shape.depth / 2 + CONFIG.Floating;
const z = player == 0 ? -2.6 : 2.6;
return magics.map(
(magic) => new BABYLON.Vector3(x(magic.location.sequence), y, z)
);
return magics.map((_, sequence) => new BABYLON.Vector3(x(sequence), y, z));
};
export default Magics;
......@@ -22,28 +22,34 @@ const Monsters = () => {
return (
<>
{zip(meMonsters, meMonsterPositions).map(([monster, position], idx) => {
{zip(meMonsters, meMonsterPositions).map(
([monster, position], sequence) => {
return (
<FixedSlot
state={monster}
key={idx}
key={sequence}
sequence={sequence}
position={position}
rotation={CONFIG.CardSlotRotation(false)}
deffenseRotation={CONFIG.CardSlotDefenceRotation()}
/>
);
})}
{zip(opMonsters, opMonsterPositions).map(([monster, position], idx) => {
}
)}
{zip(opMonsters, opMonsterPositions).map(
([monster, position], sequence) => {
return (
<FixedSlot
state={monster}
key={idx}
key={sequence}
sequence={sequence}
position={position}
rotation={CONFIG.CardSlotRotation(true)}
deffenseRotation={CONFIG.CardSlotDefenceRotation()}
/>
);
})}
}
)}
<ExtraMonsters />
<ExtraMonsters />
</>
......@@ -86,9 +92,7 @@ const monsterPositions = (player: number, monsters: CardState[]) => {
const y = shape.depth / 2 + CONFIG.Floating;
const z = player == 0 ? -1.35 : 1.35;
return monsters.map(
(monster) => new BABYLON.Vector3(x(monster.location.sequence), y, z)
);
return monsters.map((_, sequence) => new BABYLON.Vector3(x(sequence), y, z));
};
export default Monsters;
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