Commit ca5e9b02 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/slice/game' into 'main'

Feat/slice/game

See merge request mycard/Neos!19
parents 430350b1 f2587542
Pipeline #18020 failed with stages
in 3 minutes and 15 seconds
import { PayloadAction, CaseReducer } from "@reduxjs/toolkit";
import { DuelState } from "./mod";
import { RootState } from "../../store";
export interface Hands {
cards: number[]; // TODO: use Card struct Unitly
}
// 自己增加手牌
export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
state,
action
) => {
if (state.meHands) {
state.meHands.cards = state.meHands.cards.concat(action.payload);
} else {
state.meHands = { cards: action.payload };
}
};
// 对手增加手牌
export const opAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
state,
action
) => {
if (state.opHands) {
state.opHands.cards = state.opHands.cards.concat(action.payload);
} else {
state.opHands = { cards: action.payload };
}
};
export const selectMeHands = (state: RootState) =>
state.duel.meHands || { cards: [] };
export const selectOpHands = (state: RootState) =>
state.duel.opHands || { cards: [] };
import { PayloadAction, CaseReducer } from "@reduxjs/toolkit";
import { DuelState } from "./mod";
export interface InitInfo {
playerType?: string;
masterRule?: string;
......@@ -5,3 +8,19 @@ export interface InitInfo {
deckSize: number;
extraSize: number;
}
// 更新自己的初始生命值,卡组信息
export const meInfoInitImpl: CaseReducer<DuelState, PayloadAction<InitInfo>> = (
state,
action
) => {
state.meInitInfo = action.payload;
};
// 更新对手的初始生命值,卡组信息
export const opInfoInitImpl: CaseReducer<DuelState, PayloadAction<InitInfo>> = (
state,
action
) => {
state.opInitInfo = action.payload;
};
......@@ -3,12 +3,16 @@
*
* */
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { InitInfo } from "./initInfoSlice";
import { createSlice } from "@reduxjs/toolkit";
import { InitInfo, meInfoInitImpl, opInfoInitImpl } from "./initInfoSlice";
import { Hands, meAddHandsImpl, opAddHandsImpl } from "./handsSlice";
import { RootState } from "../../store";
export interface DuelState {
meInitInfo?: InitInfo; // 自己的初始状态
opInitInfo?: InitInfo; // 对手的初始状态
meHands?: Hands; // 自己的手牌
opHands?: Hands; // 对手的手牌
}
const initialState: DuelState = {};
......@@ -17,14 +21,16 @@ const duelSlice = createSlice({
name: "duel",
initialState,
reducers: {
meInfoInit: (state, action: PayloadAction<InitInfo>) => {
state.meInitInfo = action.payload;
},
opInfoInit: (state, action: PayloadAction<InitInfo>) => {
state.opInitInfo = action.payload;
},
meInfoInit: meInfoInitImpl,
opInfoInit: opInfoInitImpl,
meAddHands: meAddHandsImpl,
opAddHands: opAddHandsImpl,
},
});
export const { meInfoInit, opInfoInit } = duelSlice.actions;
export const { meInfoInit, opInfoInit, meAddHands, opAddHands } =
duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => {
return state.duel.meInitInfo != null;
};
export default duelSlice.reducer;
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store";
import { meAddHands, opAddHands } from "../../reducers/duel/mod";
export default (
draw: ygopro.StocGameMessage.MsgDraw,
dispatch: AppDispatch
) => {
// FIXME: draw.player 和先后攻有关系
if (draw.player === 0) {
dispatch(meAddHands(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 { store } from "../../store";
import { meInfoInit, opInfoInit } from "../../reducers/duel/mod";
import onMsgStart from "./start";
import onMsgDraw from "./draw";
export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
const dispatch = store.dispatch;
......@@ -10,28 +11,14 @@ export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
case "start": {
const start = msg.start;
dispatch(
meInfoInit({
playerType: start.playerType.toString(),
life: start.life1,
deckSize: start.deckSize1,
extraSize: start.extraSize1,
})
);
dispatch(
opInfoInit({
life: start.life2,
deckSize: start.deckSize2,
extraSize: start.extraSize2,
})
);
onMsgStart(start, dispatch);
break;
}
case "draw": {
// TODO
console.log(msg.draw);
const draw = msg.draw;
onMsgDraw(draw, dispatch);
break;
}
......
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store";
import { meInfoInit, opInfoInit } from "../../reducers/duel/mod";
export default (
start: ygopro.StocGameMessage.MsgStart,
dispatch: AppDispatch
) => {
dispatch(
meInfoInit({
playerType: start.playerType.toString(),
life: start.life1,
deckSize: start.deckSize1,
extraSize: start.extraSize1,
})
);
dispatch(
opInfoInit({
life: start.life2,
deckSize: start.deckSize2,
extraSize: start.extraSize2,
})
);
};
......@@ -3,8 +3,23 @@
*
* */
import { RootState } from "../../store";
import SimpleDuelPlateImpl from "./simpleDuel/mod";
import { selectMeHands } from "../../reducers/duel/handsSlice";
export default function Duel() {
return new SimpleDuelPlateImpl().render();
const simpleDuelPlate = new SimpleDuelPlateImpl();
// TODO: opHands
const handsSelector = (state: RootState) => {
const cards = selectMeHands(state).cards;
return cards.map((item) => {
return { code: item };
});
};
simpleDuelPlate.registerHands(handsSelector);
return simpleDuelPlate.render();
}
......@@ -25,7 +25,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
render(): React.ReactElement {
// ----- 数据获取 -----
// 默认的手牌Selector,返回个code为-1的Card。
// 默认的手牌Selector,返回个code为-1的Card。
const defaultHandsSelector = (_: RootState) => {
return new Array(5).fill({ code: -1 });
};
......@@ -79,7 +79,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
engine.runRenderLoop(() => {
scene.render();
});
}, [canvasRef]);
}, [canvasRef, hands]);
return (
<canvas
......
......@@ -14,7 +14,10 @@ import {
unSelectTpAble,
} from "../reducers/moraSlice";
import { selectPlayer0, selectPlayer1 } from "../reducers/playerSlice";
import { selectDuelHsStart } from "../reducers/duel/mod";
import { store } from "../store";
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
// TODO: 应该展示聊天信息
export default function Mora() {
......@@ -23,6 +26,16 @@ export default function Mora() {
const selectTpAble = useAppSelector(selectTpSelectAble);
const player0 = useAppSelector(selectPlayer0);
const player1 = useAppSelector(selectPlayer1);
const duelHsStart = useAppSelector(selectDuelHsStart);
const navigate = useNavigate();
useEffect(() => {
// 若对局已经开始,自动跳转
if (duelHsStart) {
navigate("/duel");
}
}, [duelHsStart]);
const handleSelectScissors = () => {
sendHandResult("scissors");
......
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