Commit 1b9b2fca authored by Chunchi Che's avatar Chunchi Che

Merge branch 'fix/hands' into 'main'

Fix/hands

See merge request mycard/Neos!29
parents 426b4473 b28c301f
import axios from "axios"; import axios from "axios";
interface CardMeta { export interface CardMeta {
id: number; id: number;
data: { data: {
ot?: number; ot?: number;
......
import { import { createAsyncThunk, ActionReducerMapBuilder } from "@reduxjs/toolkit";
PayloadAction,
CaseReducer,
createAsyncThunk,
ActionReducerMapBuilder,
} from "@reduxjs/toolkit";
import { DuelState } from "./mod"; import { DuelState } from "./mod";
import { RootState } from "../../store"; import { RootState } from "../../store";
import { Card, fetchCard } from "../../api/cards"; import { Card, fetchCard, CardMeta } from "../../api/cards";
import { judgeSelf } from "./util";
import * as UICONFIG from "../../config/ui"; import * as UICONFIG from "../../config/ui";
export interface Hands { export interface Hands {
cards: Card[]; cards: Card[];
} }
// 自己增加手牌 // 增加手牌
export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = ( export const fetchHandsMeta = createAsyncThunk(
state, "duel/fetchHandsMeta",
action async (param: [number, number[]]) => {
) => { const player = param[0];
const cards = action.payload.map((id) => { const Ids = param[1];
return { meta: { id, data: {}, text: {} }, transform: {} };
});
if (state.meHands) {
state.meHands.cards = state.meHands.cards.concat(cards);
} else {
state.meHands = { cards };
}
setHandsTransform(state.meHands.cards);
};
// 对手增加手牌 const metas = await Promise.all(
export const opAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
state,
action
) => {
const cards = action.payload.map((id) => {
return { meta: { id, data: {}, text: {} }, transform: {} };
});
if (state.opHands) {
state.opHands.cards = state.opHands.cards.concat(cards);
} else {
state.opHands = { cards };
}
};
export const fetchMeHandsMeta = createAsyncThunk(
"duel/fetchMeHandsMeta",
async (Ids: number[]) => {
return await Promise.all(
Ids.map(async (id) => { Ids.map(async (id) => {
if (id === 0) {
return { id, data: {}, text: {} };
} else {
return await fetchCard(id); return await fetchCard(id);
}
}) })
); );
const response: [number, CardMeta[]] = [player, metas];
return response;
} }
); );
export const meHandsCase = (builder: ActionReducerMapBuilder<DuelState>) => { export const handsCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchMeHandsMeta.fulfilled, (state, action) => { builder.addCase(fetchHandsMeta.fulfilled, (state, action) => {
// TODO: 合法性校验 const player = action.payload[0];
const cardMetas = action.payload; const hands = action.payload[1];
const selfType = state.selfType;
const cards = hands.map((meta) => {
return { meta, transform: {} };
});
if (judgeSelf(player, selfType)) {
if (state.meHands) { if (state.meHands) {
for (let meta of cardMetas) { state.meHands.cards = state.meHands.cards.concat(cards);
for (let hand of state.meHands.cards) {
if (hand.meta.id === meta.id) {
hand.meta = meta;
}
}
}
} else { } else {
state.meHands = { state.meHands = { cards };
cards: cardMetas.map((meta) => { }
return { meta, transform: {} };
}),
};
setHandsTransform(state.meHands.cards); setHandsTransform(state.meHands.cards);
} else {
if (state.opHands) {
state.opHands.cards = state.opHands.cards.concat(cards);
} else {
state.opHands = { cards };
}
} }
}); });
}; };
// 更新手牌的位置和旋转信息 // 更新手牌的位置和旋转信息
//
// TODO: 兼容对方手牌
function setHandsTransform(hands: Card[]): void { function setHandsTransform(hands: Card[]): void {
const groundShape = UICONFIG.GroundShape(); const groundShape = UICONFIG.GroundShape();
const handShape = UICONFIG.HandShape(); const handShape = UICONFIG.HandShape();
......
import { PayloadAction, CaseReducer } from "@reduxjs/toolkit"; import { PayloadAction, CaseReducer } from "@reduxjs/toolkit";
import { DuelState } from "./mod"; import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface InitInfo { export interface InitInfo {
playerType?: string;
masterRule?: string; masterRule?: string;
life: number; life: number;
deckSize: number; deckSize: number;
...@@ -10,17 +10,17 @@ export interface InitInfo { ...@@ -10,17 +10,17 @@ export interface InitInfo {
} }
// 更新自己的初始生命值,卡组信息 // 更新自己的初始生命值,卡组信息
export const meInfoInitImpl: CaseReducer<DuelState, PayloadAction<InitInfo>> = ( export const infoInitImpl: CaseReducer<
state, DuelState,
action PayloadAction<[number, InitInfo]>
) => { > = (state, action) => {
state.meInitInfo = action.payload; const player = action.payload[0];
}; const initInfo = action.payload[1];
const selfType = state.selfType;
// 更新对手的初始生命值,卡组信息 if (judgeSelf(player, selfType)) {
export const opInfoInitImpl: CaseReducer<DuelState, PayloadAction<InitInfo>> = ( state.meInitInfo = initInfo;
state, } else {
action state.opInitInfo = initInfo;
) => { }
state.opInitInfo = action.payload;
}; };
...@@ -3,19 +3,15 @@ ...@@ -3,19 +3,15 @@
* *
* */ * */
import { createSlice } from "@reduxjs/toolkit"; import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { InitInfo, meInfoInitImpl, opInfoInitImpl } from "./initInfoSlice"; import { InitInfo, infoInitImpl } from "./initInfoSlice";
import { import { Hands, handsCase } from "./handsSlice";
Hands,
meAddHandsImpl,
opAddHandsImpl,
meHandsCase,
} from "./handsSlice";
import { newTurnImpl } from "./turnSlice"; import { newTurnImpl } from "./turnSlice";
import { newPhaseImpl } from "./phaseSlice"; import { newPhaseImpl } from "./phaseSlice";
import { RootState } from "../../store"; import { RootState } from "../../store";
export interface DuelState { export interface DuelState {
selfType?: number;
meInitInfo?: InitInfo; // 自己的初始状态 meInitInfo?: InitInfo; // 自己的初始状态
opInitInfo?: InitInfo; // 对手的初始状态 opInitInfo?: InitInfo; // 对手的初始状态
meHands?: Hands; // 自己的手牌 meHands?: Hands; // 自己的手牌
...@@ -30,26 +26,20 @@ const duelSlice = createSlice({ ...@@ -30,26 +26,20 @@ const duelSlice = createSlice({
name: "duel", name: "duel",
initialState, initialState,
reducers: { reducers: {
meInfoInit: meInfoInitImpl, setSelfType: (state, action: PayloadAction<number>) => {
opInfoInit: opInfoInitImpl, state.selfType = action.payload;
meAddHands: meAddHandsImpl, },
opAddHands: opAddHandsImpl, infoInit: infoInitImpl,
updateTurn: newTurnImpl, updateTurn: newTurnImpl,
updatePhase: newPhaseImpl, updatePhase: newPhaseImpl,
}, },
extraReducers(builder) { extraReducers(builder) {
meHandsCase(builder); handsCase(builder);
}, },
}); });
export const { export const { setSelfType, infoInit, updateTurn, updatePhase } =
meInfoInit, duelSlice.actions;
opInfoInit,
meAddHands,
opAddHands,
updateTurn,
updatePhase,
} = duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => { export const selectDuelHsStart = (state: RootState) => {
return state.duel.meInitInfo != null; return state.duel.meInitInfo != null;
}; };
......
/*
* 对局内状态更新逻辑的一些共用函数
*
* */
/*
* 通过`player`和`selfType`判断是应该处理自己还是对手
* */
export function judgeSelf(
player: number,
selfType: number | undefined
): boolean {
if (selfType === 1) {
// 自己是先攻
return player === 0;
} else if (selfType === 2) {
// 自己是后攻
return player === 1;
} else {
// currently never reach
return false;
}
}
import { ygopro } from "../../api/ocgcore/idl/ocgcore"; import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store"; import { AppDispatch } from "../../store";
import { meAddHands, opAddHands } from "../../reducers/duel/mod"; import { fetchHandsMeta } from "../../reducers/duel/handsSlice";
import { fetchMeHandsMeta } from "../../reducers/duel/handsSlice";
export default ( export default (
draw: ygopro.StocGameMessage.MsgDraw, draw: ygopro.StocGameMessage.MsgDraw,
dispatch: AppDispatch dispatch: AppDispatch
) => { ) => {
// FIXME: draw.player 和先后攻有关系 dispatch(fetchHandsMeta([draw.player, draw.cards]));
if (draw.player === 0) {
dispatch(meAddHands(draw.cards));
dispatch(fetchMeHandsMeta(draw.cards));
} else if (draw.player === 1) {
dispatch(opAddHands(draw.cards));
} else {
console.log("Currently only support 2v2 mode.");
}
}; };
import { ygopro } from "../../api/ocgcore/idl/ocgcore"; import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store"; import { AppDispatch } from "../../store";
import { meInfoInit, opInfoInit } from "../../reducers/duel/mod"; import { infoInit, setSelfType } from "../../reducers/duel/mod";
export default ( export default (
start: ygopro.StocGameMessage.MsgStart, start: ygopro.StocGameMessage.MsgStart,
dispatch: AppDispatch dispatch: AppDispatch
) => { ) => {
dispatch(setSelfType(start.playerType));
dispatch( dispatch(
meInfoInit({ infoInit([
playerType: start.playerType.toString(), 0,
{
life: start.life1, life: start.life1,
deckSize: start.deckSize1, deckSize: start.deckSize1,
extraSize: start.extraSize1, extraSize: start.extraSize1,
}) },
])
); );
dispatch( dispatch(
opInfoInit({ infoInit([
1,
{
life: start.life2, life: start.life2,
deckSize: start.deckSize2, deckSize: start.deckSize2,
extraSize: start.extraSize2, extraSize: start.extraSize2,
}) },
])
); );
}; };
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