Commit ca5e9b02 authored by Chunchi Che's avatar Chunchi Che

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

Feat/slice/game

See merge request !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 { export interface InitInfo {
playerType?: string; playerType?: string;
masterRule?: string; masterRule?: string;
...@@ -5,3 +8,19 @@ export interface InitInfo { ...@@ -5,3 +8,19 @@ export interface InitInfo {
deckSize: number; deckSize: number;
extraSize: 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 @@ ...@@ -3,12 +3,16 @@
* *
* */ * */
import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { createSlice } from "@reduxjs/toolkit";
import { InitInfo } from "./initInfoSlice"; import { InitInfo, meInfoInitImpl, opInfoInitImpl } from "./initInfoSlice";
import { Hands, meAddHandsImpl, opAddHandsImpl } from "./handsSlice";
import { RootState } from "../../store";
export interface DuelState { export interface DuelState {
meInitInfo?: InitInfo; // 自己的初始状态 meInitInfo?: InitInfo; // 自己的初始状态
opInitInfo?: InitInfo; // 对手的初始状态 opInitInfo?: InitInfo; // 对手的初始状态
meHands?: Hands; // 自己的手牌
opHands?: Hands; // 对手的手牌
} }
const initialState: DuelState = {}; const initialState: DuelState = {};
...@@ -17,14 +21,16 @@ const duelSlice = createSlice({ ...@@ -17,14 +21,16 @@ const duelSlice = createSlice({
name: "duel", name: "duel",
initialState, initialState,
reducers: { reducers: {
meInfoInit: (state, action: PayloadAction<InitInfo>) => { meInfoInit: meInfoInitImpl,
state.meInitInfo = action.payload; opInfoInit: opInfoInitImpl,
}, meAddHands: meAddHandsImpl,
opInfoInit: (state, action: PayloadAction<InitInfo>) => { opAddHands: opAddHandsImpl,
state.opInitInfo = action.payload;
},
}, },
}); });
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; 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 { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { store } from "../../store"; 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) { export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
const dispatch = store.dispatch; const dispatch = store.dispatch;
...@@ -10,28 +11,14 @@ export default function handleGameMsg(pb: ygopro.YgoStocMsg) { ...@@ -10,28 +11,14 @@ export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
case "start": { case "start": {
const start = msg.start; const start = msg.start;
dispatch( onMsgStart(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,
})
);
break; break;
} }
case "draw": { case "draw": {
// TODO const draw = msg.draw;
console.log(msg.draw);
onMsgDraw(draw, dispatch);
break; 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 @@ ...@@ -3,8 +3,23 @@
* *
* */ * */
import { RootState } from "../../store";
import SimpleDuelPlateImpl from "./simpleDuel/mod"; import SimpleDuelPlateImpl from "./simpleDuel/mod";
import { selectMeHands } from "../../reducers/duel/handsSlice";
export default function Duel() { 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 { ...@@ -25,7 +25,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
render(): React.ReactElement { render(): React.ReactElement {
// ----- 数据获取 ----- // ----- 数据获取 -----
// 默认的手牌Selector,返回个code为-1的Card。 // 默认的手牌Selector,返回个code为-1的Card。
const defaultHandsSelector = (_: RootState) => { const defaultHandsSelector = (_: RootState) => {
return new Array(5).fill({ code: -1 }); return new Array(5).fill({ code: -1 });
}; };
...@@ -79,7 +79,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate { ...@@ -79,7 +79,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
engine.runRenderLoop(() => { engine.runRenderLoop(() => {
scene.render(); scene.render();
}); });
}, [canvasRef]); }, [canvasRef, hands]);
return ( return (
<canvas <canvas
......
...@@ -14,7 +14,10 @@ import { ...@@ -14,7 +14,10 @@ import {
unSelectTpAble, unSelectTpAble,
} from "../reducers/moraSlice"; } from "../reducers/moraSlice";
import { selectPlayer0, selectPlayer1 } from "../reducers/playerSlice"; import { selectPlayer0, selectPlayer1 } from "../reducers/playerSlice";
import { selectDuelHsStart } from "../reducers/duel/mod";
import { store } from "../store"; import { store } from "../store";
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
// TODO: 应该展示聊天信息 // TODO: 应该展示聊天信息
export default function Mora() { export default function Mora() {
...@@ -23,6 +26,16 @@ export default function Mora() { ...@@ -23,6 +26,16 @@ export default function Mora() {
const selectTpAble = useAppSelector(selectTpSelectAble); const selectTpAble = useAppSelector(selectTpSelectAble);
const player0 = useAppSelector(selectPlayer0); const player0 = useAppSelector(selectPlayer0);
const player1 = useAppSelector(selectPlayer1); const player1 = useAppSelector(selectPlayer1);
const duelHsStart = useAppSelector(selectDuelHsStart);
const navigate = useNavigate();
useEffect(() => {
// 若对局已经开始,自动跳转
if (duelHsStart) {
navigate("/duel");
}
}, [duelHsStart]);
const handleSelectScissors = () => { const handleSelectScissors = () => {
sendHandResult("scissors"); 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