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";
interface CardMeta {
export interface CardMeta {
id: number;
data: {
ot?: number;
......
import {
PayloadAction,
CaseReducer,
createAsyncThunk,
ActionReducerMapBuilder,
} from "@reduxjs/toolkit";
import { createAsyncThunk, ActionReducerMapBuilder } from "@reduxjs/toolkit";
import { DuelState } from "./mod";
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";
export interface Hands {
cards: Card[];
}
// 自己增加手牌
export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
state,
action
) => {
const cards = action.payload.map((id) => {
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);
};
// 增加手牌
export const fetchHandsMeta = createAsyncThunk(
"duel/fetchHandsMeta",
async (param: [number, number[]]) => {
const player = param[0];
const Ids = param[1];
// 对手增加手牌
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(
const metas = await Promise.all(
Ids.map(async (id) => {
if (id === 0) {
return { id, data: {}, text: {} };
} else {
return await fetchCard(id);
}
})
);
const response: [number, CardMeta[]] = [player, metas];
return response;
}
);
export const meHandsCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchMeHandsMeta.fulfilled, (state, action) => {
// TODO: 合法性校验
const cardMetas = action.payload;
export const handsCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchHandsMeta.fulfilled, (state, action) => {
const player = action.payload[0];
const hands = action.payload[1];
const selfType = state.selfType;
const cards = hands.map((meta) => {
return { meta, transform: {} };
});
if (judgeSelf(player, selfType)) {
if (state.meHands) {
for (let meta of cardMetas) {
for (let hand of state.meHands.cards) {
if (hand.meta.id === meta.id) {
hand.meta = meta;
}
}
}
state.meHands.cards = state.meHands.cards.concat(cards);
} else {
state.meHands = {
cards: cardMetas.map((meta) => {
return { meta, transform: {} };
}),
};
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 {
const groundShape = UICONFIG.GroundShape();
const handShape = UICONFIG.HandShape();
......
import { PayloadAction, CaseReducer } from "@reduxjs/toolkit";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface InitInfo {
playerType?: string;
masterRule?: string;
life: number;
deckSize: number;
......@@ -10,17 +10,17 @@ export interface InitInfo {
}
// 更新自己的初始生命值,卡组信息
export const meInfoInitImpl: CaseReducer<DuelState, PayloadAction<InitInfo>> = (
state,
action
) => {
state.meInitInfo = action.payload;
};
export const infoInitImpl: CaseReducer<
DuelState,
PayloadAction<[number, InitInfo]>
> = (state, action) => {
const player = action.payload[0];
const initInfo = action.payload[1];
const selfType = state.selfType;
// 更新对手的初始生命值,卡组信息
export const opInfoInitImpl: CaseReducer<DuelState, PayloadAction<InitInfo>> = (
state,
action
) => {
state.opInitInfo = action.payload;
if (judgeSelf(player, selfType)) {
state.meInitInfo = initInfo;
} else {
state.opInitInfo = initInfo;
}
};
......@@ -3,19 +3,15 @@
*
* */
import { createSlice } from "@reduxjs/toolkit";
import { InitInfo, meInfoInitImpl, opInfoInitImpl } from "./initInfoSlice";
import {
Hands,
meAddHandsImpl,
opAddHandsImpl,
meHandsCase,
} from "./handsSlice";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { InitInfo, infoInitImpl } from "./initInfoSlice";
import { Hands, handsCase } from "./handsSlice";
import { newTurnImpl } from "./turnSlice";
import { newPhaseImpl } from "./phaseSlice";
import { RootState } from "../../store";
export interface DuelState {
selfType?: number;
meInitInfo?: InitInfo; // 自己的初始状态
opInitInfo?: InitInfo; // 对手的初始状态
meHands?: Hands; // 自己的手牌
......@@ -30,26 +26,20 @@ const duelSlice = createSlice({
name: "duel",
initialState,
reducers: {
meInfoInit: meInfoInitImpl,
opInfoInit: opInfoInitImpl,
meAddHands: meAddHandsImpl,
opAddHands: opAddHandsImpl,
setSelfType: (state, action: PayloadAction<number>) => {
state.selfType = action.payload;
},
infoInit: infoInitImpl,
updateTurn: newTurnImpl,
updatePhase: newPhaseImpl,
},
extraReducers(builder) {
meHandsCase(builder);
handsCase(builder);
},
});
export const {
meInfoInit,
opInfoInit,
meAddHands,
opAddHands,
updateTurn,
updatePhase,
} = duelSlice.actions;
export const { setSelfType, infoInit, updateTurn, updatePhase } =
duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => {
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 { AppDispatch } from "../../store";
import { meAddHands, opAddHands } from "../../reducers/duel/mod";
import { fetchMeHandsMeta } from "../../reducers/duel/handsSlice";
import { fetchHandsMeta } from "../../reducers/duel/handsSlice";
export default (
draw: ygopro.StocGameMessage.MsgDraw,
dispatch: AppDispatch
) => {
// FIXME: draw.player 和先后攻有关系
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.");
}
dispatch(fetchHandsMeta([draw.player, draw.cards]));
};
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store";
import { meInfoInit, opInfoInit } from "../../reducers/duel/mod";
import { infoInit, setSelfType } from "../../reducers/duel/mod";
export default (
start: ygopro.StocGameMessage.MsgStart,
dispatch: AppDispatch
) => {
dispatch(setSelfType(start.playerType));
dispatch(
meInfoInit({
playerType: start.playerType.toString(),
infoInit([
0,
{
life: start.life1,
deckSize: start.deckSize1,
extraSize: start.extraSize1,
})
},
])
);
dispatch(
opInfoInit({
infoInit([
1,
{
life: start.life2,
deckSize: start.deckSize2,
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