Commit 58ce6d5e authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/service/select_place' into 'main'

Feat/service/select place

See merge request !48
parents e0fc2b96 6dad97f5
Pipeline #18836 passed with stages
in 2 minutes and 11 seconds
neos-protobuf @ 8cfeb7ac
Subproject commit 1ba7de35c6c717fe9f361dcdada8ffd6c43f9a8b Subproject commit 8cfeb7ac4563b27f2f56e36b53b1453a953d9a9c
This diff is collapsed.
...@@ -52,8 +52,8 @@ export class BufferReader { ...@@ -52,8 +52,8 @@ export class BufferReader {
return ret; return ret;
} }
readCardInfo(): ygopro.StocGameMessage.CardInfo { readCardInfo(): ygopro.CardInfo {
const cardInfo = new ygopro.StocGameMessage.CardInfo({}); const cardInfo = new ygopro.CardInfo({});
cardInfo.code = this.readUint32(); cardInfo.code = this.readUint32();
cardInfo.controler = this.readUint8(); cardInfo.controler = this.readUint8();
......
...@@ -32,3 +32,4 @@ export const MSG_NEW_TURN = 40; ...@@ -32,3 +32,4 @@ export const MSG_NEW_TURN = 40;
export const MSG_NEW_PHASE = 41; export const MSG_NEW_PHASE = 41;
export const MSG_HINT = 2; export const MSG_HINT = 2;
export const MSG_SELECT_IDLE_CMD = 11; export const MSG_SELECT_IDLE_CMD = 11;
export const MSG_SELECT_PLACE = 18;
...@@ -12,6 +12,7 @@ import MsgNewTurnAdapter from "./newTurn"; ...@@ -12,6 +12,7 @@ import MsgNewTurnAdapter from "./newTurn";
import MsgNewPhaseAdapter from "./newPhase"; import MsgNewPhaseAdapter from "./newPhase";
import MsgHintAdapter from "./hint"; import MsgHintAdapter from "./hint";
import MsgSelectIdleCmdAdapter from "./selectIdleCmd"; import MsgSelectIdleCmdAdapter from "./selectIdleCmd";
import MsgSelectPlaceAdapter from "./selectPlace";
/* /*
* STOC GameMsg * STOC GameMsg
...@@ -67,6 +68,11 @@ export default class GameMsgAdapter implements StocAdapter { ...@@ -67,6 +68,11 @@ export default class GameMsgAdapter implements StocAdapter {
break; break;
} }
case GAME_MSG.MSG_SELECT_PLACE: {
gameMsg.select_place = MsgSelectPlaceAdapter(gameData);
break;
}
default: { default: {
console.log("Unhandled GameMessage function=", func); console.log("Unhandled GameMessage function=", func);
......
import { ygopro } from "../../../idl/ocgcore";
import { BufferReader } from "../../bufferIO";
import MsgSelectPlace = ygopro.StocGameMessage.MsgSelectPlace;
/*
* Msg Select Place
*
* @param - see: https://code.mycard.moe/mycard/neos-protobuf/-/blob/main/idl/ocgcore.proto
*
* @usage - 玩家可选择的位置
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data, true);
const player = reader.readUint8();
let count = reader.readUint8();
const _field = ~reader.readUint32();
// TODO: 暂时和`ygopro2`一样不支持取消操作,后续需要再考虑加上
if (count == 0) {
count = 1;
}
const msg = new MsgSelectPlace({
player,
count,
places: [],
});
for (let i = 0; i < 2; i++) {
const controler = i == 0 ? player : 1 - player;
const field = i == 0 ? _field & 0xffff : _field >> 16;
if ((field & 0x7f) != 0) {
// 怪兽区
const zone = ygopro.CardZone.MZONE;
const filter = field & 0x7f;
for (let sequence = 0; sequence < 7; sequence++) {
if ((filter & (1 << sequence)) != 0) {
msg.places.push(
new MsgSelectPlace.SelectAblePlace({
controler,
zone,
sequence: sequence,
})
);
}
}
}
if ((field & 0x1f00) != 0) {
// 魔法陷阱区
const zone = ygopro.CardZone.SZONE;
const filter = (field >> 8) & 0x1f;
for (let sequence = 0; sequence < 5; sequence++) {
if ((filter & (1 << sequence)) != 0) {
msg.places.push(
new MsgSelectPlace.SelectAblePlace({
controler,
zone,
sequence,
})
);
}
}
}
if ((field & 0xc000) != 0) {
// 灵摆区?
const zone = ygopro.CardZone.SZONE;
const filter = (field >> 14) & 0x3;
if ((filter & 0x1) != 0) {
msg.places.push(
new MsgSelectPlace.SelectAblePlace({
controler,
zone,
sequence: 6,
})
);
}
if ((filter & 0x2) != 0) {
msg.places.push(
new MsgSelectPlace.SelectAblePlace({
controler,
zone,
sequence: 7,
})
);
}
}
}
return msg;
};
...@@ -2,6 +2,7 @@ import { createAsyncThunk, ActionReducerMapBuilder } from "@reduxjs/toolkit"; ...@@ -2,6 +2,7 @@ import { createAsyncThunk, ActionReducerMapBuilder } from "@reduxjs/toolkit";
import { DuelState } from "./mod"; import { DuelState } from "./mod";
import { RootState } from "../../store"; import { RootState } from "../../store";
import { fetchStrings } from "../../api/strings"; import { fetchStrings } from "../../api/strings";
import { fetchCard } from "../../api/cards";
import { judgeSelf } from "./util"; import { judgeSelf } from "./util";
export interface HintState { export interface HintState {
...@@ -9,8 +10,8 @@ export interface HintState { ...@@ -9,8 +10,8 @@ export interface HintState {
msg?: string; msg?: string;
} }
export const fetchHintMeta = createAsyncThunk( export const fetchCommonHintMeta = createAsyncThunk(
"duel/fetchHintMeta", "duel/fetchCommonHintMeta",
async (param: [number, number]) => { async (param: [number, number]) => {
const player = param[0]; const player = param[0];
const hintData = param[1]; const hintData = param[1];
...@@ -22,8 +23,21 @@ export const fetchHintMeta = createAsyncThunk( ...@@ -22,8 +23,21 @@ export const fetchHintMeta = createAsyncThunk(
} }
); );
export const fetchSelectPlaceHintMeta = createAsyncThunk(
"duel/fetchSelectPlaceHintMeta",
async (param: [number, number]) => {
const player = param[0];
const hintData = param[1];
const hintMeta = (await fetchCard(hintData)).text.name || "[?]";
const response: [number, string] = [player, hintMeta];
return response;
}
);
export const hintCase = (builder: ActionReducerMapBuilder<DuelState>) => { export const hintCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchHintMeta.pending, (state, action) => { builder.addCase(fetchCommonHintMeta.pending, (state, action) => {
const player = action.meta.arg[0]; const player = action.meta.arg[0];
const code = action.meta.arg[1]; const code = action.meta.arg[1];
...@@ -33,7 +47,7 @@ export const hintCase = (builder: ActionReducerMapBuilder<DuelState>) => { ...@@ -33,7 +47,7 @@ export const hintCase = (builder: ActionReducerMapBuilder<DuelState>) => {
state.opHint = { code }; state.opHint = { code };
} }
}); });
builder.addCase(fetchHintMeta.fulfilled, (state, action) => { builder.addCase(fetchCommonHintMeta.fulfilled, (state, action) => {
const player = action.payload[0]; const player = action.payload[0];
const hintMeta = action.payload[1]; const hintMeta = action.payload[1];
...@@ -42,6 +56,31 @@ export const hintCase = (builder: ActionReducerMapBuilder<DuelState>) => { ...@@ -42,6 +56,31 @@ export const hintCase = (builder: ActionReducerMapBuilder<DuelState>) => {
hint.msg = hintMeta; hint.msg = hintMeta;
} }
}); });
builder.addCase(fetchSelectPlaceHintMeta.pending, (state, action) => {
const player = action.meta.arg[0];
const code = action.meta.arg[1];
if (judgeSelf(player, state)) {
state.meHint = { code };
} else {
state.opHint = { code };
}
});
builder.addCase(fetchSelectPlaceHintMeta.fulfilled, (state, action) => {
const player = action.payload[0];
const hintMeta = action.payload[1];
// TODO: 国际化文案
const hintMsg = judgeSelf(player, state)
? `请为我方的<${hintMeta}>选择位置`
: `请为对方的<${hintMeta}>选择位置`;
const hint = judgeSelf(player, state) ? state.meHint : state.opHint;
if (hint) {
hint.msg = hintMsg;
}
});
}; };
export const selectMeHint = (state: RootState) => state.duel.meHint; export const selectMeHint = (state: RootState) => state.duel.meHint;
......
...@@ -6,6 +6,7 @@ import onMsgNewTurn from "./newTurn"; ...@@ -6,6 +6,7 @@ import onMsgNewTurn from "./newTurn";
import onMsgNewPhase from "./newPhase"; import onMsgNewPhase from "./newPhase";
import onMsgHint from "./hint"; import onMsgHint from "./hint";
import onMsgSelectIdleCmd from "./selectIdleCmd"; import onMsgSelectIdleCmd from "./selectIdleCmd";
import onMsgSelectPlace from "./selectPlace";
export default function handleGameMsg(pb: ygopro.YgoStocMsg) { export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
const dispatch = store.dispatch; const dispatch = store.dispatch;
...@@ -54,6 +55,13 @@ export default function handleGameMsg(pb: ygopro.YgoStocMsg) { ...@@ -54,6 +55,13 @@ export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
break; break;
} }
case "select_place": {
const selectPlace = msg.select_place;
onMsgSelectPlace(selectPlace, dispatch);
break;
}
default: { default: {
break; break;
} }
......
import { ygopro } from "../../api/ocgcore/idl/ocgcore"; import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store"; import { AppDispatch } from "../../store";
import { fetchHintMeta } from "../../reducers/duel/hintSlice"; import {
fetchCommonHintMeta,
fetchSelectPlaceHintMeta,
} from "../../reducers/duel/hintSlice";
import MsgHint = ygopro.StocGameMessage.MsgHint; import MsgHint = ygopro.StocGameMessage.MsgHint;
export default (hint: MsgHint, dispatch: AppDispatch) => { export default (hint: MsgHint, dispatch: AppDispatch) => {
...@@ -8,7 +11,11 @@ export default (hint: MsgHint, dispatch: AppDispatch) => { ...@@ -8,7 +11,11 @@ export default (hint: MsgHint, dispatch: AppDispatch) => {
switch (hint.hint_type) { switch (hint.hint_type) {
case MsgHint.HintType.HINT_EVENT: case MsgHint.HintType.HINT_EVENT:
case MsgHint.HintType.HINT_MESSAGE: { case MsgHint.HintType.HINT_MESSAGE: {
dispatch(fetchHintMeta([player, hint.hint_data])); dispatch(fetchCommonHintMeta([player, hint.hint_data]));
break;
}
case MsgHint.HintType.HINT_SELECTMSG: {
dispatch(fetchSelectPlaceHintMeta([player, hint.hint_data]));
break; break;
} }
default: { default: {
......
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store";
import MsgSelectPlace = ygopro.StocGameMessage.MsgSelectPlace;
export default (selectPlace: MsgSelectPlace, dispatch: AppDispatch) => {
// TODO
console.log(selectPlace);
};
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