Commit 40f7217e authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/interface/duel_plate' into 'main'

Feat/interface/duel plate

See merge request mycard/Neos!14
parents f5654819 9d5ff8ec
neos-protobuf @ 867be3ce
Subproject commit e7cfaff59f5c1ed640e21c2257d0bd39b6a27648 Subproject commit 867be3cee1dfe449735e81a85aa887724e8067cb
...@@ -458,7 +458,7 @@ export namespace ygopro { ...@@ -458,7 +458,7 @@ export namespace ygopro {
} }
} }
export class YgoStocMsg extends pb_1.Message { export class YgoStocMsg extends pb_1.Message {
#one_of_decls: number[][] = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]; #one_of_decls: number[][] = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]];
constructor( constructor(
data?: data?:
| any[] | any[]
...@@ -475,6 +475,7 @@ export namespace ygopro { ...@@ -475,6 +475,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -488,6 +489,7 @@ export namespace ygopro { ...@@ -488,6 +489,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -501,6 +503,7 @@ export namespace ygopro { ...@@ -501,6 +503,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -514,6 +517,7 @@ export namespace ygopro { ...@@ -514,6 +517,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -527,6 +531,7 @@ export namespace ygopro { ...@@ -527,6 +531,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -540,6 +545,7 @@ export namespace ygopro { ...@@ -540,6 +545,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -553,6 +559,7 @@ export namespace ygopro { ...@@ -553,6 +559,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -566,6 +573,7 @@ export namespace ygopro { ...@@ -566,6 +573,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -579,6 +587,7 @@ export namespace ygopro { ...@@ -579,6 +587,7 @@ export namespace ygopro {
stoc_select_tp?: StocSelectTp; stoc_select_tp?: StocSelectTp;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -592,6 +601,7 @@ export namespace ygopro { ...@@ -592,6 +601,7 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: StocDeckCount; stoc_deck_count?: StocDeckCount;
stoc_duel_start?: never; stoc_duel_start?: never;
stoc_game_msg?: never;
} }
| { | {
stoc_join_game?: never; stoc_join_game?: never;
...@@ -605,6 +615,21 @@ export namespace ygopro { ...@@ -605,6 +615,21 @@ export namespace ygopro {
stoc_select_tp?: never; stoc_select_tp?: never;
stoc_deck_count?: never; stoc_deck_count?: never;
stoc_duel_start?: StocDuelStart; stoc_duel_start?: StocDuelStart;
stoc_game_msg?: never;
}
| {
stoc_join_game?: never;
stoc_chat?: never;
stoc_hs_player_enter?: never;
stoc_type_change?: never;
stoc_hs_player_change?: never;
stoc_hs_watch_change?: never;
stoc_select_hand?: never;
stoc_hand_result?: never;
stoc_select_tp?: never;
stoc_deck_count?: never;
stoc_duel_start?: never;
stoc_game_msg?: StocGameMessage;
} }
)) ))
) { ) {
...@@ -660,6 +685,9 @@ export namespace ygopro { ...@@ -660,6 +685,9 @@ export namespace ygopro {
if ("stoc_duel_start" in data && data.stoc_duel_start != undefined) { if ("stoc_duel_start" in data && data.stoc_duel_start != undefined) {
this.stoc_duel_start = data.stoc_duel_start; this.stoc_duel_start = data.stoc_duel_start;
} }
if ("stoc_game_msg" in data && data.stoc_game_msg != undefined) {
this.stoc_game_msg = data.stoc_game_msg;
}
} }
} }
get stoc_join_game() { get stoc_join_game() {
...@@ -801,6 +829,19 @@ export namespace ygopro { ...@@ -801,6 +829,19 @@ export namespace ygopro {
get has_stoc_duel_start() { get has_stoc_duel_start() {
return pb_1.Message.getField(this, 11) != null; return pb_1.Message.getField(this, 11) != null;
} }
get stoc_game_msg() {
return pb_1.Message.getWrapperField(
this,
StocGameMessage,
12
) as StocGameMessage;
}
set stoc_game_msg(value: StocGameMessage) {
pb_1.Message.setOneofWrapperField(this, 12, this.#one_of_decls[0], value);
}
get has_stoc_game_msg() {
return pb_1.Message.getField(this, 12) != null;
}
get msg() { get msg() {
const cases: { const cases: {
[index: number]: [index: number]:
...@@ -815,7 +856,8 @@ export namespace ygopro { ...@@ -815,7 +856,8 @@ export namespace ygopro {
| "stoc_hand_result" | "stoc_hand_result"
| "stoc_select_tp" | "stoc_select_tp"
| "stoc_deck_count" | "stoc_deck_count"
| "stoc_duel_start"; | "stoc_duel_start"
| "stoc_game_msg";
} = { } = {
0: "none", 0: "none",
1: "stoc_join_game", 1: "stoc_join_game",
...@@ -829,9 +871,13 @@ export namespace ygopro { ...@@ -829,9 +871,13 @@ export namespace ygopro {
9: "stoc_select_tp", 9: "stoc_select_tp",
10: "stoc_deck_count", 10: "stoc_deck_count",
11: "stoc_duel_start", 11: "stoc_duel_start",
12: "stoc_game_msg",
}; };
return cases[ return cases[
pb_1.Message.computeOneofCase(this, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) pb_1.Message.computeOneofCase(
this,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
)
]; ];
} }
static fromObject(data: { static fromObject(data: {
...@@ -852,6 +898,7 @@ export namespace ygopro { ...@@ -852,6 +898,7 @@ export namespace ygopro {
stoc_select_tp?: ReturnType<typeof StocSelectTp.prototype.toObject>; stoc_select_tp?: ReturnType<typeof StocSelectTp.prototype.toObject>;
stoc_deck_count?: ReturnType<typeof StocDeckCount.prototype.toObject>; stoc_deck_count?: ReturnType<typeof StocDeckCount.prototype.toObject>;
stoc_duel_start?: ReturnType<typeof StocDuelStart.prototype.toObject>; stoc_duel_start?: ReturnType<typeof StocDuelStart.prototype.toObject>;
stoc_game_msg?: ReturnType<typeof StocGameMessage.prototype.toObject>;
}): YgoStocMsg { }): YgoStocMsg {
const message = new YgoStocMsg({}); const message = new YgoStocMsg({});
if (data.stoc_join_game != null) { if (data.stoc_join_game != null) {
...@@ -903,6 +950,9 @@ export namespace ygopro { ...@@ -903,6 +950,9 @@ export namespace ygopro {
data.stoc_duel_start data.stoc_duel_start
); );
} }
if (data.stoc_game_msg != null) {
message.stoc_game_msg = StocGameMessage.fromObject(data.stoc_game_msg);
}
return message; return message;
} }
toObject() { toObject() {
...@@ -924,6 +974,7 @@ export namespace ygopro { ...@@ -924,6 +974,7 @@ export namespace ygopro {
stoc_select_tp?: ReturnType<typeof StocSelectTp.prototype.toObject>; stoc_select_tp?: ReturnType<typeof StocSelectTp.prototype.toObject>;
stoc_deck_count?: ReturnType<typeof StocDeckCount.prototype.toObject>; stoc_deck_count?: ReturnType<typeof StocDeckCount.prototype.toObject>;
stoc_duel_start?: ReturnType<typeof StocDuelStart.prototype.toObject>; stoc_duel_start?: ReturnType<typeof StocDuelStart.prototype.toObject>;
stoc_game_msg?: ReturnType<typeof StocGameMessage.prototype.toObject>;
} = {}; } = {};
if (this.stoc_join_game != null) { if (this.stoc_join_game != null) {
data.stoc_join_game = this.stoc_join_game.toObject(); data.stoc_join_game = this.stoc_join_game.toObject();
...@@ -958,6 +1009,9 @@ export namespace ygopro { ...@@ -958,6 +1009,9 @@ export namespace ygopro {
if (this.stoc_duel_start != null) { if (this.stoc_duel_start != null) {
data.stoc_duel_start = this.stoc_duel_start.toObject(); data.stoc_duel_start = this.stoc_duel_start.toObject();
} }
if (this.stoc_game_msg != null) {
data.stoc_game_msg = this.stoc_game_msg.toObject();
}
return data; return data;
} }
serialize(): Uint8Array; serialize(): Uint8Array;
...@@ -1008,6 +1062,10 @@ export namespace ygopro { ...@@ -1008,6 +1062,10 @@ export namespace ygopro {
writer.writeMessage(11, this.stoc_duel_start, () => writer.writeMessage(11, this.stoc_duel_start, () =>
this.stoc_duel_start.serialize(writer) this.stoc_duel_start.serialize(writer)
); );
if (this.has_stoc_game_msg)
writer.writeMessage(12, this.stoc_game_msg, () =>
this.stoc_game_msg.serialize(writer)
);
if (!w) return writer.getResultBuffer(); if (!w) return writer.getResultBuffer();
} }
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): YgoStocMsg { static deserialize(bytes: Uint8Array | pb_1.BinaryReader): YgoStocMsg {
...@@ -1096,6 +1154,13 @@ export namespace ygopro { ...@@ -1096,6 +1154,13 @@ export namespace ygopro {
(message.stoc_duel_start = StocDuelStart.deserialize(reader)) (message.stoc_duel_start = StocDuelStart.deserialize(reader))
); );
break; break;
case 12:
reader.readMessage(
message.stoc_game_msg,
() =>
(message.stoc_game_msg = StocGameMessage.deserialize(reader))
);
break;
default: default:
reader.skipField(); reader.skipField();
} }
...@@ -3034,4 +3099,332 @@ export namespace ygopro { ...@@ -3034,4 +3099,332 @@ export namespace ygopro {
return StocDuelStart.deserialize(bytes); return StocDuelStart.deserialize(bytes);
} }
} }
export class StocGameMessage extends pb_1.Message {
#one_of_decls: number[][] = [[1]];
constructor(
data?:
| any[]
| ({} & {
start?: StocGameMessage.MsgStart;
})
) {
super();
pb_1.Message.initialize(
this,
Array.isArray(data) ? data : [],
0,
-1,
[],
this.#one_of_decls
);
if (!Array.isArray(data) && typeof data == "object") {
if ("start" in data && data.start != undefined) {
this.start = data.start;
}
}
}
get start() {
return pb_1.Message.getWrapperField(
this,
StocGameMessage.MsgStart,
1
) as StocGameMessage.MsgStart;
}
set start(value: StocGameMessage.MsgStart) {
pb_1.Message.setOneofWrapperField(this, 1, this.#one_of_decls[0], value);
}
get has_start() {
return pb_1.Message.getField(this, 1) != null;
}
get gameMsg() {
const cases: {
[index: number]: "none" | "start";
} = {
0: "none",
1: "start",
};
return cases[pb_1.Message.computeOneofCase(this, [1])];
}
static fromObject(data: {
start?: ReturnType<typeof StocGameMessage.MsgStart.prototype.toObject>;
}): StocGameMessage {
const message = new StocGameMessage({});
if (data.start != null) {
message.start = StocGameMessage.MsgStart.fromObject(data.start);
}
return message;
}
toObject() {
const data: {
start?: ReturnType<typeof StocGameMessage.MsgStart.prototype.toObject>;
} = {};
if (this.start != null) {
data.start = this.start.toObject();
}
return data;
}
serialize(): Uint8Array;
serialize(w: pb_1.BinaryWriter): void;
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
const writer = w || new pb_1.BinaryWriter();
if (this.has_start)
writer.writeMessage(1, this.start, () => this.start.serialize(writer));
if (!w) return writer.getResultBuffer();
}
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): StocGameMessage {
const reader =
bytes instanceof pb_1.BinaryReader
? bytes
: new pb_1.BinaryReader(bytes),
message = new StocGameMessage();
while (reader.nextField()) {
if (reader.isEndGroup()) break;
switch (reader.getFieldNumber()) {
case 1:
reader.readMessage(
message.start,
() =>
(message.start = StocGameMessage.MsgStart.deserialize(reader))
);
break;
default:
reader.skipField();
}
}
return message;
}
serializeBinary(): Uint8Array {
return this.serialize();
}
static deserializeBinary(bytes: Uint8Array): StocGameMessage {
return StocGameMessage.deserialize(bytes);
}
}
export namespace StocGameMessage {
export class MsgStart extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(
data?:
| any[]
| {
playerType?: StocGameMessage.MsgStart.PlayerType;
life1?: number;
life2?: number;
deckSize1?: number;
deckSize2?: number;
extraSize1?: number;
extraSize2?: number;
}
) {
super();
pb_1.Message.initialize(
this,
Array.isArray(data) ? data : [],
0,
-1,
[],
this.#one_of_decls
);
if (!Array.isArray(data) && typeof data == "object") {
if ("playerType" in data && data.playerType != undefined) {
this.playerType = data.playerType;
}
if ("life1" in data && data.life1 != undefined) {
this.life1 = data.life1;
}
if ("life2" in data && data.life2 != undefined) {
this.life2 = data.life2;
}
if ("deckSize1" in data && data.deckSize1 != undefined) {
this.deckSize1 = data.deckSize1;
}
if ("deckSize2" in data && data.deckSize2 != undefined) {
this.deckSize2 = data.deckSize2;
}
if ("extraSize1" in data && data.extraSize1 != undefined) {
this.extraSize1 = data.extraSize1;
}
if ("extraSize2" in data && data.extraSize2 != undefined) {
this.extraSize2 = data.extraSize2;
}
}
}
get playerType() {
return pb_1.Message.getFieldWithDefault(
this,
1,
StocGameMessage.MsgStart.PlayerType.UNKNOWN
) as StocGameMessage.MsgStart.PlayerType;
}
set playerType(value: StocGameMessage.MsgStart.PlayerType) {
pb_1.Message.setField(this, 1, value);
}
get life1() {
return pb_1.Message.getFieldWithDefault(this, 2, 0) as number;
}
set life1(value: number) {
pb_1.Message.setField(this, 2, value);
}
get life2() {
return pb_1.Message.getFieldWithDefault(this, 3, 0) as number;
}
set life2(value: number) {
pb_1.Message.setField(this, 3, value);
}
get deckSize1() {
return pb_1.Message.getFieldWithDefault(this, 4, 0) as number;
}
set deckSize1(value: number) {
pb_1.Message.setField(this, 4, value);
}
get deckSize2() {
return pb_1.Message.getFieldWithDefault(this, 5, 0) as number;
}
set deckSize2(value: number) {
pb_1.Message.setField(this, 5, value);
}
get extraSize1() {
return pb_1.Message.getFieldWithDefault(this, 6, 0) as number;
}
set extraSize1(value: number) {
pb_1.Message.setField(this, 6, value);
}
get extraSize2() {
return pb_1.Message.getFieldWithDefault(this, 7, 0) as number;
}
set extraSize2(value: number) {
pb_1.Message.setField(this, 7, value);
}
static fromObject(data: {
playerType?: StocGameMessage.MsgStart.PlayerType;
life1?: number;
life2?: number;
deckSize1?: number;
deckSize2?: number;
extraSize1?: number;
extraSize2?: number;
}): MsgStart {
const message = new MsgStart({});
if (data.playerType != null) {
message.playerType = data.playerType;
}
if (data.life1 != null) {
message.life1 = data.life1;
}
if (data.life2 != null) {
message.life2 = data.life2;
}
if (data.deckSize1 != null) {
message.deckSize1 = data.deckSize1;
}
if (data.deckSize2 != null) {
message.deckSize2 = data.deckSize2;
}
if (data.extraSize1 != null) {
message.extraSize1 = data.extraSize1;
}
if (data.extraSize2 != null) {
message.extraSize2 = data.extraSize2;
}
return message;
}
toObject() {
const data: {
playerType?: StocGameMessage.MsgStart.PlayerType;
life1?: number;
life2?: number;
deckSize1?: number;
deckSize2?: number;
extraSize1?: number;
extraSize2?: number;
} = {};
if (this.playerType != null) {
data.playerType = this.playerType;
}
if (this.life1 != null) {
data.life1 = this.life1;
}
if (this.life2 != null) {
data.life2 = this.life2;
}
if (this.deckSize1 != null) {
data.deckSize1 = this.deckSize1;
}
if (this.deckSize2 != null) {
data.deckSize2 = this.deckSize2;
}
if (this.extraSize1 != null) {
data.extraSize1 = this.extraSize1;
}
if (this.extraSize2 != null) {
data.extraSize2 = this.extraSize2;
}
return data;
}
serialize(): Uint8Array;
serialize(w: pb_1.BinaryWriter): void;
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
const writer = w || new pb_1.BinaryWriter();
if (this.playerType != StocGameMessage.MsgStart.PlayerType.UNKNOWN)
writer.writeEnum(1, this.playerType);
if (this.life1 != 0) writer.writeInt32(2, this.life1);
if (this.life2 != 0) writer.writeInt32(3, this.life2);
if (this.deckSize1 != 0) writer.writeInt32(4, this.deckSize1);
if (this.deckSize2 != 0) writer.writeInt32(5, this.deckSize2);
if (this.extraSize1 != 0) writer.writeInt32(6, this.extraSize1);
if (this.extraSize2 != 0) writer.writeInt32(7, this.extraSize2);
if (!w) return writer.getResultBuffer();
}
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): MsgStart {
const reader =
bytes instanceof pb_1.BinaryReader
? bytes
: new pb_1.BinaryReader(bytes),
message = new MsgStart();
while (reader.nextField()) {
if (reader.isEndGroup()) break;
switch (reader.getFieldNumber()) {
case 1:
message.playerType = reader.readEnum();
break;
case 2:
message.life1 = reader.readInt32();
break;
case 3:
message.life2 = reader.readInt32();
break;
case 4:
message.deckSize1 = reader.readInt32();
break;
case 5:
message.deckSize2 = reader.readInt32();
break;
case 6:
message.extraSize1 = reader.readInt32();
break;
case 7:
message.extraSize2 = reader.readInt32();
break;
default:
reader.skipField();
}
}
return message;
}
serializeBinary(): Uint8Array {
return this.serialize();
}
static deserializeBinary(bytes: Uint8Array): MsgStart {
return MsgStart.deserialize(bytes);
}
}
export namespace MsgStart {
export enum PlayerType {
UNKNOWN = 0,
FirstStrike = 1,
SecondStrike = 2,
Observer = 3,
}
}
}
} }
import { ygoProPacket } from "./packet"; import { YgoProPacket } from "./packet";
import { ygopro } from "../idl/ocgcore"; import { ygopro } from "../idl/ocgcore";
import { import {
STOC_CHAT, STOC_CHAT,
...@@ -12,6 +12,7 @@ import { ...@@ -12,6 +12,7 @@ import {
STOC_HAND_RESULT, STOC_HAND_RESULT,
STOC_DECK_COUNT, STOC_DECK_COUNT,
STOC_DUEL_START, STOC_DUEL_START,
STOC_GAME_MSG,
} from "./protoDecl"; } from "./protoDecl";
import StocChat from "./stoc/stocChat"; import StocChat from "./stoc/stocChat";
import StocJoinGame from "./stoc/stocJoinGame"; import StocJoinGame from "./stoc/stocJoinGame";
...@@ -22,6 +23,7 @@ import StocTypeChange from "./stoc/stocTypeChange"; ...@@ -22,6 +23,7 @@ import StocTypeChange from "./stoc/stocTypeChange";
import StocSelectHand from "./stoc/stocSelectHand"; import StocSelectHand from "./stoc/stocSelectHand";
import StocSelectTp from "./stoc/stocSelectTp"; import StocSelectTp from "./stoc/stocSelectTp";
import StocDeckCount from "./stoc/stocDeckCount"; import StocDeckCount from "./stoc/stocDeckCount";
import StocGameMsg from "./stoc/stocGameMsg/mod";
/* /*
* 将[`ygoProPacket`]对象转换成[`ygopro.YgoStocMsg`]对象 * 将[`ygoProPacket`]对象转换成[`ygopro.YgoStocMsg`]对象
...@@ -30,7 +32,7 @@ import StocDeckCount from "./stoc/stocDeckCount"; ...@@ -30,7 +32,7 @@ import StocDeckCount from "./stoc/stocDeckCount";
* @returns The ygopro.YgoStocMsg object * @returns The ygopro.YgoStocMsg object
* *
* */ * */
export function adaptStoc(packet: ygoProPacket): ygopro.YgoStocMsg { export function adaptStoc(packet: YgoProPacket): ygopro.YgoStocMsg {
let pb = new ygopro.YgoStocMsg({}); let pb = new ygopro.YgoStocMsg({});
switch (packet.proto) { switch (packet.proto) {
case STOC_JOIN_GAME: { case STOC_JOIN_GAME: {
...@@ -87,6 +89,11 @@ export function adaptStoc(packet: ygoProPacket): ygopro.YgoStocMsg { ...@@ -87,6 +89,11 @@ export function adaptStoc(packet: ygoProPacket): ygopro.YgoStocMsg {
break; break;
} }
case STOC_GAME_MSG: {
pb = new StocGameMsg(packet).upcast();
break;
}
default: { default: {
break; break;
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet"; import { YgoProPacket } from "../packet";
import { CTOS_HAND_RESULT } from "../protoDecl"; import { CTOS_HAND_RESULT } from "../protoDecl";
/* /*
...@@ -9,7 +9,7 @@ import { CTOS_HAND_RESULT } from "../protoDecl"; ...@@ -9,7 +9,7 @@ import { CTOS_HAND_RESULT } from "../protoDecl";
* *
* @usage - 告知服务端当前玩家的猜拳选择 * @usage - 告知服务端当前玩家的猜拳选择
* */ * */
export default class CtosHandResultPacket extends ygoProPacket { export default class CtosHandResultPacket extends YgoProPacket {
constructor(pb: ygopro.YgoCtosMsg) { constructor(pb: ygopro.YgoCtosMsg) {
const handResult = pb.ctos_hand_result; const handResult = pb.ctos_hand_result;
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet"; import { YgoProPacket } from "../packet";
import { CTOS_HS_READY } from "../protoDecl"; import { CTOS_HS_READY } from "../protoDecl";
/* /*
...@@ -7,7 +7,7 @@ import { CTOS_HS_READY } from "../protoDecl"; ...@@ -7,7 +7,7 @@ import { CTOS_HS_READY } from "../protoDecl";
* *
* @usage - 告诉ygopro服务端当前玩家准备完毕 * @usage - 告诉ygopro服务端当前玩家准备完毕
* */ * */
export default class CtosHsReady extends ygoProPacket { export default class CtosHsReady extends YgoProPacket {
constructor(_: ygopro.YgoCtosMsg) { constructor(_: ygopro.YgoCtosMsg) {
super(1, CTOS_HS_READY, new Uint8Array(0)); super(1, CTOS_HS_READY, new Uint8Array(0));
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet"; import { YgoProPacket } from "../packet";
import { CTOS_HS_START } from "../protoDecl"; import { CTOS_HS_START } from "../protoDecl";
/* /*
...@@ -7,7 +7,7 @@ import { CTOS_HS_START } from "../protoDecl"; ...@@ -7,7 +7,7 @@ import { CTOS_HS_START } from "../protoDecl";
* *
* @usage - 开始游戏对局 * @usage - 开始游戏对局
* */ * */
export default class CtosHsStartPacket extends ygoProPacket { export default class CtosHsStartPacket extends YgoProPacket {
constructor(_: ygopro.YgoCtosMsg) { constructor(_: ygopro.YgoCtosMsg) {
super(1, CTOS_HS_START, new Uint8Array(0)); super(1, CTOS_HS_START, new Uint8Array(0));
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet"; import { YgoProPacket } from "../packet";
import { CTOS_JOIN_GAME } from "../protoDecl"; import { CTOS_JOIN_GAME } from "../protoDecl";
import { strEncodeUTF16 } from "../util"; import { strEncodeUTF16 } from "../util";
...@@ -13,7 +13,7 @@ import { strEncodeUTF16 } from "../util"; ...@@ -13,7 +13,7 @@ import { strEncodeUTF16 } from "../util";
* *
* @usage - 加入房间 * @usage - 加入房间
* */ * */
export default class CtosJoinGamePacket extends ygoProPacket { export default class CtosJoinGamePacket extends YgoProPacket {
constructor(pb: ygopro.YgoCtosMsg) { constructor(pb: ygopro.YgoCtosMsg) {
const joinGame = pb.ctos_join_game; const joinGame = pb.ctos_join_game;
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet"; import { YgoProPacket } from "../packet";
import { CTOS_PLAYER_INFO } from "../protoDecl"; import { CTOS_PLAYER_INFO } from "../protoDecl";
import { strEncodeUTF16 } from "../util"; import { strEncodeUTF16 } from "../util";
...@@ -10,7 +10,7 @@ import { strEncodeUTF16 } from "../util"; ...@@ -10,7 +10,7 @@ import { strEncodeUTF16 } from "../util";
* *
* @usage - 告诉ygopro服务端当前玩家的昵称 * @usage - 告诉ygopro服务端当前玩家的昵称
* */ * */
export default class CtosPlayerInfoPacket extends ygoProPacket { export default class CtosPlayerInfoPacket extends YgoProPacket {
constructor(pb: ygopro.YgoCtosMsg) { constructor(pb: ygopro.YgoCtosMsg) {
const player = pb.ctos_player_info.name; const player = pb.ctos_player_info.name;
const exData = strEncodeUTF16(player); const exData = strEncodeUTF16(player);
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet"; import { YgoProPacket } from "../packet";
import { CTOS_TP_RESULT } from "../protoDecl"; import { CTOS_TP_RESULT } from "../protoDecl";
/* /*
...@@ -10,7 +10,7 @@ import { CTOS_TP_RESULT } from "../protoDecl"; ...@@ -10,7 +10,7 @@ import { CTOS_TP_RESULT } from "../protoDecl";
* @usage - 告知服务端当前玩家的先后攻选择 * @usage - 告知服务端当前玩家的先后攻选择
* *
* */ * */
export default class CtosTpResultPacket extends ygoProPacket { export default class CtosTpResultPacket extends YgoProPacket {
constructor(pb: ygopro.YgoCtosMsg) { constructor(pb: ygopro.YgoCtosMsg) {
const tpResult = pb.ctos_tp_result; const tpResult = pb.ctos_tp_result;
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet"; import { YgoProPacket } from "../packet";
import { CTOS_UPDATE_DECK } from "../protoDecl"; import { CTOS_UPDATE_DECK } from "../protoDecl";
const BYTES_PER_U32 = 4; const BYTES_PER_U32 = 4;
...@@ -16,7 +16,7 @@ const BYTES_PER_U32 = 4; ...@@ -16,7 +16,7 @@ const BYTES_PER_U32 = 4;
* *
* @usage - 更新对局的卡组信息 * @usage - 更新对局的卡组信息
* */ * */
export default class CtosUpdateDeck extends ygoProPacket { export default class CtosUpdateDeck extends YgoProPacket {
constructor(pb: ygopro.YgoCtosMsg) { constructor(pb: ygopro.YgoCtosMsg) {
const updateDeck = pb.ctos_update_deck; const updateDeck = pb.ctos_update_deck;
const main = updateDeck.main; const main = updateDeck.main;
......
...@@ -8,7 +8,7 @@ const littleEndian: boolean = true; ...@@ -8,7 +8,7 @@ const littleEndian: boolean = true;
const PACKET_MIN_LEN = 3; const PACKET_MIN_LEN = 3;
// Ref: https://www.icode9.com/content-1-1341344.html // Ref: https://www.icode9.com/content-1-1341344.html
export class ygoProPacket { export class YgoProPacket {
packetLen: number; // 数据包长度 packetLen: number; // 数据包长度
proto: number; // ygopro协议标识 proto: number; // ygopro协议标识
exData: Uint8Array; // 数据包内容 exData: Uint8Array; // 数据包内容
...@@ -40,7 +40,7 @@ export class ygoProPacket { ...@@ -40,7 +40,7 @@ export class ygoProPacket {
* 返回值可用于业务逻辑处理。 * 返回值可用于业务逻辑处理。
* *
* */ * */
static deserialize(array: ArrayBuffer): ygoProPacket { static deserialize(array: ArrayBuffer): YgoProPacket {
try { try {
if (array.byteLength < PACKET_MIN_LEN) { if (array.byteLength < PACKET_MIN_LEN) {
throw new Error( throw new Error(
...@@ -57,7 +57,7 @@ export class ygoProPacket { ...@@ -57,7 +57,7 @@ export class ygoProPacket {
const proto = dataView.getInt8(2); const proto = dataView.getInt8(2);
const exData = array.slice(3, packetLen + 2); const exData = array.slice(3, packetLen + 2);
return new ygoProPacket(packetLen, proto, new Uint8Array(exData)); return new YgoProPacket(packetLen, proto, new Uint8Array(exData));
} }
} }
...@@ -68,5 +68,5 @@ export interface StocAdapter { ...@@ -68,5 +68,5 @@ export interface StocAdapter {
export interface CtosAdapter { export interface CtosAdapter {
readonly protobuf: ygopro.YgoCtosMsg; readonly protobuf: ygopro.YgoCtosMsg;
downcast(): ygoProPacket; downcast(): YgoProPacket;
} }
...@@ -21,3 +21,6 @@ export const STOC_SELECT_TP = 4; ...@@ -21,3 +21,6 @@ export const STOC_SELECT_TP = 4;
export const STOC_HAND_RESULT = 5; export const STOC_HAND_RESULT = 5;
export const STOC_DECK_COUNT = 9; export const STOC_DECK_COUNT = 9;
export const STOC_DUEL_START = 21; export const STOC_DUEL_START = 21;
export const STOC_GAME_MSG = 1;
export const MSG_START = 4;
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
/* /*
* STOC Chat * STOC Chat
...@@ -9,10 +9,10 @@ import { ygoProPacket, StocAdapter } from "../packet"; ...@@ -9,10 +9,10 @@ import { ygoProPacket, StocAdapter } from "../packet";
* *
* @usage - 更新聊天消息 * @usage - 更新聊天消息
* */ * */
export default class chatAdapter implements StocAdapter { export default class ChatAdapter implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
const LITTLE_ENDIAN = true; const LITTLE_ENDIAN = true;
const INT16_BYTE_OFFSET = 2; const INT16_BYTE_OFFSET = 2;
...@@ -12,10 +12,10 @@ const INT16_BYTE_OFFSET = 2; ...@@ -12,10 +12,10 @@ const INT16_BYTE_OFFSET = 2;
* @usage - 展示双方卡组信息 * @usage - 展示双方卡组信息
* */ * */
export default class deckCountAdapter implements StocAdapter { export default class DeckCountAdapter implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
/*
* STOC GameMsg协议Adapter逻辑
*
* */
import { ygopro } from "../../../idl/ocgcore";
import { YgoProPacket, StocAdapter } from "../../packet";
import { MSG_START } from "../../protoDecl";
import MsgStartAdapter from "./start";
/*
* STOC GameMsg
*
* @param function: unsigned chat - GameMsg协议的function编号
* @param data: binary bytes - GameMsg协议的数据
*
* @usage - 服务端告诉前端/客户端决斗对局中的UI展示逻辑
* */
export default class GameMsgAdapter implements StocAdapter {
packet: YgoProPacket;
constructor(packet: YgoProPacket) {
this.packet = packet;
}
upcast(): ygopro.YgoStocMsg {
const exData = this.packet.exData;
const dataView = new DataView(exData.buffer);
const func = dataView.getUint8(0);
const gameData = exData.slice(1);
const gameMsg = new ygopro.StocGameMessage({});
switch (func) {
case MSG_START: {
gameMsg.start = MsgStartAdapter(gameData);
break;
}
default: {
console.log("Unhandled GameMessage function=", func);
break;
}
}
return new ygopro.YgoStocMsg({
stoc_game_msg: gameMsg,
});
}
}
import { ygopro } from "../../../idl/ocgcore";
const LITTLE_ENDIAN = true;
const INT16_BYTE_OFFSET = 2;
const INT32_BYTE_OFFSET = 4;
/*
* MSG Start
*
* @param todo
*
* @usage - 服务端在决斗开始时告诉前端/客户端双方的基础信息
* */
export default (data: Uint8Array) => {
const dataView = new DataView(data.buffer);
// TODO: 对DataView包装下实现一个BufferIO类,便于解析二进制数据
const pT = dataView.getUint8(0);
const playerType =
(pT & 0xf) <= 0
? ygopro.StocGameMessage.MsgStart.PlayerType.FirstStrike
: (pT & 0xf0) > 0
? ygopro.StocGameMessage.MsgStart.PlayerType.Observer
: ygopro.StocGameMessage.MsgStart.PlayerType.SecondStrike;
let offset = 1;
if (dataView.byteLength > 17) {
// data长度大于17,会多传一个大师规则字段
const masterRule = dataView.getUint8(offset); // TODO
offset += 1;
}
const life1 = dataView.getInt32(offset, LITTLE_ENDIAN);
offset += INT32_BYTE_OFFSET;
const life2 = dataView.getInt32(offset, LITTLE_ENDIAN);
offset += INT32_BYTE_OFFSET;
const deckSize1 = dataView.getInt16(offset, LITTLE_ENDIAN);
offset += INT16_BYTE_OFFSET;
const extraSize1 = dataView.getInt16(offset, LITTLE_ENDIAN);
offset += INT16_BYTE_OFFSET;
const deckSize2 = dataView.getInt16(offset, LITTLE_ENDIAN);
offset += INT16_BYTE_OFFSET;
const extraSize2 = dataView.getInt16(offset, LITTLE_ENDIAN);
offset += INT16_BYTE_OFFSET;
return new ygopro.StocGameMessage.MsgStart({
playerType,
life1,
life2,
deckSize1,
deckSize2,
extraSize1,
extraSize2,
});
};
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
/* /*
* STOC HsPlayerChange * STOC HsPlayerChange
...@@ -8,10 +8,10 @@ import { ygoProPacket, StocAdapter } from "../packet"; ...@@ -8,10 +8,10 @@ import { ygoProPacket, StocAdapter } from "../packet";
* *
* @usage - 更新玩家状态 * @usage - 更新玩家状态
* */ * */
export default class hsPlayerChangeAdapter implements StocAdapter { export default class HsPlayerChangeAdapter implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
import { UTF16_BUFFER_MAX_LEN } from "../util"; import { UTF16_BUFFER_MAX_LEN } from "../util";
const UINT8_PER_UINT16 = 2; const UINT8_PER_UINT16 = 2;
...@@ -12,10 +12,10 @@ const UINT8_PER_UINT16 = 2; ...@@ -12,10 +12,10 @@ const UINT8_PER_UINT16 = 2;
* *
* @usage - 有新玩家进入房间,更新状态 * @usage - 有新玩家进入房间,更新状态
* */ * */
export default class hsPlayerEnterAdapter implements StocAdapter { export default class HsPlayerEnterAdapter implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
/* /*
* STOC HsWatchChange * STOC HsWatchChange
...@@ -8,10 +8,10 @@ import { ygoProPacket, StocAdapter } from "../packet"; ...@@ -8,10 +8,10 @@ import { ygoProPacket, StocAdapter } from "../packet";
* *
* @usage - 更新观战者数量 * @usage - 更新观战者数量
* */ * */
export default class hsWatchChangeAdapter implements StocAdapter { export default class HsWatchChangeAdapter implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
/* /*
* STOC JoinGame * STOC JoinGame
* *
* @usage - 告知客户端/前端已成功加入房间 * @usage - 告知客户端/前端已成功加入房间
* */ * */
export default class joinGameAdapter implements StocAdapter { export default class JoinGameAdapter implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
/* /*
* STOC SelectHand * STOC SelectHand
* *
* @usage - 通知客户端/前端提醒用户进行猜拳选择 * @usage - 通知客户端/前端提醒用户进行猜拳选择
* */ * */
export default class selectHand implements StocAdapter { export default class SelectHand implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
/* /*
* STOC SelectTp * STOC SelectTp
* *
* @usage - 通知客户端/前端提醒用户进行选先后攻 * @usage - 通知客户端/前端提醒用户进行选先后攻
* */ * */
export default class selectTp implements StocAdapter { export default class SelectTp implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
import { ygopro } from "../../idl/ocgcore"; import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, StocAdapter } from "../packet"; import { YgoProPacket, StocAdapter } from "../packet";
/* /*
* STOC TypeChange * STOC TypeChange
...@@ -8,10 +8,10 @@ import { ygoProPacket, StocAdapter } from "../packet"; ...@@ -8,10 +8,10 @@ import { ygoProPacket, StocAdapter } from "../packet";
* *
* @usage - 更新玩家状态 * @usage - 更新玩家状态
* */ * */
export default class typeChangeAdapter implements StocAdapter { export default class TypeChangeAdapter implements StocAdapter {
packet: ygoProPacket; packet: YgoProPacket;
constructor(packet: ygoProPacket) { constructor(packet: YgoProPacket) {
this.packet = packet; this.packet = packet;
} }
......
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
const msg = pb.stoc_game_msg;
switch (msg.gameMsg) {
case "start": {
// TODO
console.log(msg.start);
break;
}
default: {
console.log("Unhandled GameMsg=" + msg.gameMsg);
break;
}
}
}
...@@ -8,11 +8,12 @@ import handleHsPlayerEnter from "./room/hsPlayerEnter"; ...@@ -8,11 +8,12 @@ import handleHsPlayerEnter from "./room/hsPlayerEnter";
import handleJoinGame from "./room/joinGame"; import handleJoinGame from "./room/joinGame";
import handleChat from "./room/chat"; import handleChat from "./room/chat";
import handleHsWatchChange from "./room/hsWatchChange"; import handleHsWatchChange from "./room/hsWatchChange";
import { ygoProPacket } from "../api/ocgcore/ocgAdapter/packet"; import { YgoProPacket } from "../api/ocgcore/ocgAdapter/packet";
import { adaptStoc } from "../api/ocgcore/ocgAdapter/adapter"; import { adaptStoc } from "../api/ocgcore/ocgAdapter/adapter";
import handleSelectHand from "./mora/selectHand"; import handleSelectHand from "./mora/selectHand";
import handleSelectTp from "./mora/selectTp"; import handleSelectTp from "./mora/selectTp";
import handleDeckCount from "./mora/deckCount"; import handleDeckCount from "./mora/deckCount";
import handleGameMsg from "./duel/gameMsg";
/* /*
* 先将从长连接中读取到的二进制数据通过Adapter转成protobuf结构体, * 先将从长连接中读取到的二进制数据通过Adapter转成protobuf结构体,
...@@ -20,7 +21,7 @@ import handleDeckCount from "./mora/deckCount"; ...@@ -20,7 +21,7 @@ import handleDeckCount from "./mora/deckCount";
* *
* */ * */
export default function handleSocketMessage(e: MessageEvent) { export default function handleSocketMessage(e: MessageEvent) {
const packet = ygoProPacket.deserialize(e.data); const packet = YgoProPacket.deserialize(e.data);
const pb = adaptStoc(packet); const pb = adaptStoc(packet);
switch (pb.msg) { switch (pb.msg) {
...@@ -81,6 +82,11 @@ export default function handleSocketMessage(e: MessageEvent) { ...@@ -81,6 +82,11 @@ export default function handleSocketMessage(e: MessageEvent) {
break; break;
} }
case "stoc_game_msg": {
handleGameMsg(pb);
break;
}
default: { default: {
console.log(packet); console.log(packet);
......
/*
* 决斗界面渲染需要的数据结构
*
* */
export interface Card {
code: number; // Currently only code
}
/*
* 决斗界面的抽象接口
*
* - Neos项目采用UI渲染和数据获取相互解耦的设计,
* UI组件内部不应该存在任何与业务耦合的逻辑,
* 而是应该暴露数据注入的接口,供业务方调用;
* - Neos项目在研发初期,会更多的注重业务逻辑的实现,
* 而不会在UI界面上钻研过深,但在项目最终上线前,
* 会对UI界面提出较高的要求,因此在研发过程中可能会存在
* 多套UI界面。为了减少重复性工作,这里设计一个通用的
* 决斗界面抽象接口,接口实现方需要实现独立的,具体的渲染逻辑,
* 接口调用方不感知具体实现,只负责根据外部输入,
* 进行特定UI模块的渲染和更新。
*
* */
import * as DuelData from "./data";
import React from "react";
import type { RootState } from "../../store";
/*
* 通用的决斗界面抽象接口
*
* */
export interface IDuelPlate {
// 渲染接口,返回一个React组件
render(): React.ReactElement;
// 注册手牌selector
registerHands(selector: TypeSelector<DuelData.Card[]>): void;
}
export interface TypeSelector<T> {
(state: RootState): T;
}
/*
* 决斗页面
*
* */
import SimpleDuelPlateImpl from "./simpleDuel";
export default function Duel() {
return new SimpleDuelPlateImpl().render();
}
/*
* 一个简洁的决斗界面实现
*
* */
import { IDuelPlate, TypeSelector } from "./duel";
import * as DuelData from "./data";
import { useAppSelector } from "../../hook";
import React from "react";
import type { RootState } from "../../store";
export default class SimpleDuelPlateImpl implements IDuelPlate {
handsSelector?: TypeSelector<DuelData.Card[]>;
constructor() {}
render(): React.ReactElement {
// 默认的手牌Selector,返回三个code为-1的Card。
const defaultHandsSelector = (_: RootState) => {
return new Array(5).fill({ code: -1 });
};
const hands = useAppSelector(this.handsSelector || defaultHandsSelector);
return (
<div>
<table border={1}>
<tr>
{hands.map((hand) => (
<td>{hand.code}</td>
))}
</tr>
</table>
</div>
);
}
registerHands(selector: TypeSelector<DuelData.Card[]>): void {
this.handsSelector = selector;
}
}
...@@ -5,14 +5,16 @@ import ThreeJs from "./ThreeJs"; ...@@ -5,14 +5,16 @@ import ThreeJs from "./ThreeJs";
import BabylonJs from "./BabylonJs"; import BabylonJs from "./BabylonJs";
import { Routes, Route } from "react-router-dom"; import { Routes, Route } from "react-router-dom";
import Mora from "./Mora"; import Mora from "./Mora";
import Duel from "./Duel/main";
export default function () { export default function () {
// FIXME: 这里Mora路由应该由每个房间指定一个路径 // FIXME: 这里Mora/Duel路由应该由每个房间指定一个路径
return ( return (
<Routes> <Routes>
<Route path="/" element={<JoinRoom />} /> <Route path="/" element={<JoinRoom />} />
<Route path="/:player/:passWd/:ip" element={<WaitRoom />} /> <Route path="/:player/:passWd/:ip" element={<WaitRoom />} />
<Route path="/mora" element={<Mora />} /> <Route path="/mora" element={<Mora />} />
<Route path="/duel" element={<Duel />} />
<Route path="/three" element={<ThreeJs />} /> <Route path="/three" element={<ThreeJs />} />
<Route path="/babylon" element={<BabylonJs />} /> <Route path="/babylon" element={<BabylonJs />} />
</Routes> </Routes>
......
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