Commit c9dfd8b0 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'optimize/migrate/non_proxy' into 'main'

Optimize/migrate/non proxy

See merge request mycard/Neos!8
parents e0247a37 f43d12d0
Pipeline #17427 passed with stages
in 2 minutes and 25 seconds
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet";
import { CTOS_HS_READY } from "../protoDecl";
export default class CtosHsReady extends ygoProPacket {
constructor(_: ygopro.YgoCtosMsg) {
super(1, CTOS_HS_READY, new Uint8Array(0));
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet";
import { CTOS_HS_START } from "../protoDecl";
export default class CtosHsStartPacket extends ygoProPacket {
constructor(_: ygopro.YgoCtosMsg) {
super(1, CTOS_HS_START, new Uint8Array(0));
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet";
import { CTOS_JOIN_GAME } from "../protoDecl";
import { strEncodeUTF16 } from "../util";
export default class CtosJoinGamePacket extends ygoProPacket {
constructor(pb: ygopro.YgoCtosMsg) {
const joinGame = pb.ctos_join_game;
const version = joinGame.version;
const gameId = joinGame.gameid;
const passWd = strEncodeUTF16(joinGame.passwd);
const exDataLen = 4 + 4 + passWd.length;
const exData = new Uint8Array(exDataLen);
const dataView = new DataView(exData.buffer);
dataView.setUint8(0, version & 0xff);
dataView.setUint8(1, (version >> 8) & 0xff);
dataView.setUint8(2, 0);
dataView.setUint8(3, 0);
dataView.setUint8(4, gameId & 0xff);
dataView.setUint8(5, (gameId >> 8) & 0xff);
dataView.setUint8(6, (gameId >> 16) & 0xff);
dataView.setUint8(7, (gameId >> 32) & 0xff);
exData.set(passWd, 8);
super(exData.length + 1, CTOS_JOIN_GAME, exData);
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet";
import { CTOS_PLAYER_INFO } from "../protoDecl";
import { strEncodeUTF16 } from "../util";
export default class CtosPlayerInfoPacket extends ygoProPacket {
constructor(pb: ygopro.YgoCtosMsg) {
const player = pb.ctos_player_info.name;
const exData = strEncodeUTF16(player);
super(exData.length + 1, CTOS_PLAYER_INFO, exData);
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket } from "../packet";
import { CTOS_UPDATE_DECK } from "../protoDecl";
const BYTES_PER_U32 = 4;
export default class CtosUpdateDeck extends ygoProPacket {
constructor(pb: ygopro.YgoCtosMsg) {
const updateDeck = pb.ctos_update_deck;
const main = updateDeck.main;
const extra = updateDeck.extra;
const side = updateDeck.side;
const mainLen = main.length + extra.length;
const sideLen = side.length;
const exDataLen = (2 + mainLen + sideLen) * BYTES_PER_U32;
const exData = new Uint8Array(exDataLen);
const dataView = new DataView(exData.buffer);
dataView.setInt32(0, mainLen, true);
dataView.setInt32(1 * BYTES_PER_U32, sideLen, true);
let offset = 2;
for (let card of main) {
dataView.setInt32(offset * BYTES_PER_U32, card, true);
offset += 1;
}
for (let card of extra) {
dataView.setInt32(offset * BYTES_PER_U32, card, true);
offset += 1;
}
for (let card of side) {
dataView.setInt32(offset * BYTES_PER_U32, card, true);
offset += 1;
}
super(exDataLen + 3, CTOS_UPDATE_DECK, exData);
}
}
import { ygopro } from "../idl/ocgcore";
const littleEndian: boolean = true;
const PACKET_MIN_LEN = 3;
export class ygoProPacket {
packetLen: number;
proto: number;
exData: Uint8Array;
constructor(packetLen: number, proto: number, exData: Uint8Array) {
this.packetLen = packetLen;
this.proto = proto;
this.exData = exData;
}
serialize(): Uint8Array {
const array = new Uint8Array(this.packetLen + 2);
const dataView = new DataView(array.buffer);
dataView.setUint16(0, this.packetLen, littleEndian);
dataView.setUint8(2, this.proto);
array.set(this.exData, 3);
return array;
}
}
export class ygoArrayBuilder extends ygoProPacket {
constructor(array: ArrayBuffer) {
try {
if (array.byteLength < PACKET_MIN_LEN) {
throw new Error(
"Packet length too short, length = " + array.byteLength
);
}
} catch (e) {
console.log("[e][ygoProPacket][constructor]" + e);
}
const dataView = new DataView(array);
const packetLen = dataView.getInt16(0, littleEndian);
const proto = dataView.getInt8(2);
const exData = array.slice(3, packetLen + 2);
super(packetLen, proto, new Uint8Array(exData));
}
}
export interface ygoProtobuf {
readonly packet: ygoProPacket;
adapt(): ygopro.YgoStocMsg;
}
export const CTOS_PLAYER_INFO = 16;
export const CTOS_JOIN_GAME = 18;
export const CTOS_UPDATE_DECK = 2;
export const CTOS_HS_READY = 34;
export const CTOS_HS_START = 37;
export const STOC_JOIN_GAME = 18;
export const STOC_CHAT = 25;
export const STOC_HS_PLAYER_ENTER = 32;
export const STOC_HS_PLAYER_CHANGE = 33;
export const STOC_HS_WATCH_CHANGE = 34;
export const STOC_TYPE_CHANGE = 19;
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, ygoProtobuf } from "../packet";
export default class StocChatPB implements ygoProtobuf {
packet: ygoProPacket;
constructor(packet: ygoProPacket) {
this.packet = packet;
}
adapt(): ygopro.YgoStocMsg {
const player = new DataView(this.packet.exData.buffer).getInt16(0, true);
const decoder = new TextDecoder("utf-16");
const msg = decoder.decode(this.packet.exData.slice(2));
return new ygopro.YgoStocMsg({
stoc_chat: new ygopro.StocChat({
player,
msg,
}),
});
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, ygoProtobuf } from "../packet";
export default class StocHsPlayerChange implements ygoProtobuf {
packet: ygoProPacket;
constructor(packet: ygoProPacket) {
this.packet = packet;
}
adapt(): ygopro.YgoStocMsg {
const pb = new ygopro.StocHsPlayerChange({});
pb.state = ygopro.StocHsPlayerChange.State.UNKNOWN;
const Status = new DataView(this.packet.exData.buffer).getUint8(0);
const pos = (Status >> 4) & 0xf;
const state = Status & 0xf;
pb.pos = pos;
if (pos < 4) {
if (state < 8) {
pb.state = ygopro.StocHsPlayerChange.State.MOVE;
pb.moved_pos = state;
} else if (state === 0x9) {
pb.state = ygopro.StocHsPlayerChange.State.READY;
} else if (state === 0xa) {
pb.state = ygopro.StocHsPlayerChange.State.NO_READY;
} else if (state === 0xb) {
pb.state = ygopro.StocHsPlayerChange.State.LEAVE;
} else if (state === 0x8) {
pb.state = ygopro.StocHsPlayerChange.State.TO_OBSERVER;
}
}
return new ygopro.YgoStocMsg({
stoc_hs_player_change: pb,
});
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, ygoProtobuf } from "../packet";
import { UTF16_BUFFER_MAX_LEN } from "../util";
const UINT8_PER_UINT16 = 2;
export default class StocHsPlayerEnter implements ygoProtobuf {
packet: ygoProPacket;
constructor(packet: ygoProPacket) {
this.packet = packet;
}
adapt(): ygopro.YgoStocMsg {
const exData = this.packet.exData;
const decoder = new TextDecoder("utf-16");
const name = decoder.decode(
exData.slice(0, UTF16_BUFFER_MAX_LEN * UINT8_PER_UINT16)
);
const dataView = new DataView(exData.buffer);
const pos =
dataView.getUint8(UTF16_BUFFER_MAX_LEN * UINT8_PER_UINT16) & 0x3;
return new ygopro.YgoStocMsg({
stoc_hs_player_enter: new ygopro.StocHsPlayerEnter({
name,
pos,
}),
});
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, ygoProtobuf } from "../packet";
export default class StocHsWatchChange implements ygoProtobuf {
packet: ygoProPacket;
constructor(packet: ygoProPacket) {
this.packet = packet;
}
adapt(): ygopro.YgoStocMsg {
const count = new DataView(this.packet.exData.buffer).getUint16(0, true);
return new ygopro.YgoStocMsg({
stoc_hs_watch_change: new ygopro.StocHsWatchChange({
count,
}),
});
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, ygoProtobuf } from "../packet";
export default class StocJoinGamePB implements ygoProtobuf {
packet: ygoProPacket;
constructor(packet: ygoProPacket) {
this.packet = packet;
}
adapt(): ygopro.YgoStocMsg {
// todo
return new ygopro.YgoStocMsg({
stoc_join_game: new ygopro.StocJoinGame({}),
});
}
}
import { ygopro } from "../../idl/ocgcore";
import { ygoProPacket, ygoProtobuf } from "../packet";
export default class StocTypeChange implements ygoProtobuf {
packet: ygoProPacket;
constructor(packet: ygoProPacket) {
this.packet = packet;
}
adapt(): ygopro.YgoStocMsg {
const type_ = new DataView(this.packet.exData.buffer).getUint8(0);
const isHost = ((type_ >> 4) & 0xf) != 0;
let selfType = ygopro.StocTypeChange.SelfType.UNKNOWN;
switch (type_ & 0xf) {
case 0: {
selfType = ygopro.StocTypeChange.SelfType.PLAYER1;
break;
}
case 1: {
selfType = ygopro.StocTypeChange.SelfType.PLAYER2;
break;
}
case 2: {
selfType = ygopro.StocTypeChange.SelfType.PLAYER3;
break;
}
case 3: {
selfType = ygopro.StocTypeChange.SelfType.PLAYER4;
break;
}
case 4: {
selfType = ygopro.StocTypeChange.SelfType.PLAYER5;
break;
}
case 5: {
selfType = ygopro.StocTypeChange.SelfType.PLAYER6;
break;
}
}
return new ygopro.YgoStocMsg({
stoc_type_change: new ygopro.StocTypeChange({
self_type: selfType,
is_host: isHost,
}),
});
}
}
export const UTF16_BUFFER_MAX_LEN = 20;
const FILLING_TOKEN: number = 0xcccc;
export function strEncodeUTF16(str: string) {
let buf = new ArrayBuffer(UTF16_BUFFER_MAX_LEN * 2);
let bufView = new Uint16Array(buf);
bufView.fill(FILLING_TOKEN, 0, UTF16_BUFFER_MAX_LEN);
for (
let i = 0, strLen = str.length;
i < strLen && i < UTF16_BUFFER_MAX_LEN;
i++
) {
bufView[i] = str.charCodeAt(i);
if (i === strLen - 1 && i < bufView.length - 1) {
bufView[i + 1] = 0;
}
}
return new Uint8Array(buf);
}
// currently not used, but remain.
export function utf8ArrayToStr(array: Uint8Array) {
let out, i, len, c;
let char2, char3;
out = "";
len = array.length;
i = 0;
while (i < len) {
c = array[i++];
switch (c >> 4) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12:
case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(
((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0)
);
break;
}
}
return out;
}
import { ygopro } from "./idl/ocgcore";
import socketMiddleWare, { socketCmd } from "../middleware/socket";
import { IDeck } from "./Card";
import socketMiddleWare, { socketCmd } from "../../middleware/socket";
import { IDeck } from "../Card";
import CtosPlayerInfo from "./ocgAdapter/ctos/ctosPlayerInfo";
import CtosJoinGame from "./ocgAdapter/ctos/ctosJoinGame";
import CtosUpdateDeck from "./ocgAdapter/ctos/ctosUpdateDeck";
import CtosHsReady from "./ocgAdapter/ctos/ctosHsReady";
import CtosHsStart from "./ocgAdapter/ctos/ctosHsStart";
export function sendUpdateDeck(deck: IDeck) {
const updateDeck = new ygopro.YgoCtosMsg({
......@@ -10,24 +15,27 @@ export function sendUpdateDeck(deck: IDeck) {
side: deck.side,
}),
});
const payload = new CtosUpdateDeck(updateDeck).serialize();
socketMiddleWare({ cmd: socketCmd.SEND, payload: updateDeck });
socketMiddleWare({ cmd: socketCmd.SEND, payload });
}
export function sendHsReady() {
const hasReady = new ygopro.YgoCtosMsg({
ctos_hs_ready: new ygopro.CtosHsReady({}),
});
const payload = new CtosHsReady(hasReady).serialize();
socketMiddleWare({ cmd: socketCmd.SEND, payload: hasReady });
socketMiddleWare({ cmd: socketCmd.SEND, payload });
}
export function sendHsStart() {
const hasStart = new ygopro.YgoCtosMsg({
ctos_hs_start: new ygopro.CtosHsStart({}),
});
const payload = new CtosHsStart(hasStart).serialize();
socketMiddleWare({ cmd: socketCmd.SEND, payload: hasStart });
socketMiddleWare({ cmd: socketCmd.SEND, payload });
}
export function sendPlayerInfo(ws: WebSocket, player: string) {
......@@ -36,8 +44,9 @@ export function sendPlayerInfo(ws: WebSocket, player: string) {
name: player,
}),
});
const packet = new CtosPlayerInfo(playerInfo); // todo: 需要收敛在一个层次里
ws.send(playerInfo.serialize());
ws.send(packet.serialize());
}
export function sendJoinGame(ws: WebSocket, version: number, passWd: string) {
......@@ -48,6 +57,7 @@ export function sendJoinGame(ws: WebSocket, version: number, passWd: string) {
passwd: passWd,
}),
});
const packet = new CtosJoinGame(joinGame);
ws.send(joinGame.serialize());
ws.send(packet.serialize());
}
import { ygopro } from "../api/idl/ocgcore";
import handleSocketOpen from "../service/onSocketOpen";
import handleSocketMessage from "../service/onSocketMessage";
......@@ -15,7 +14,7 @@ export interface socketAction {
player: string;
passWd: string;
};
payload?: ygopro.YgoCtosMsg;
payload?: Uint8Array;
}
let ws: WebSocket | null = null;
......@@ -47,9 +46,9 @@ export default function (action: socketAction) {
break;
}
case socketCmd.SEND: {
const pb = action.payload;
if (ws && pb) {
ws.send(pb.serialize());
const payload = action.payload;
if (ws && payload) {
ws.send(payload);
}
break;
......
import { ygopro } from "../api/idl/ocgcore";
import { ygopro } from "../api/ocgcore/idl/ocgcore";
import handleHsPlayerChange from "./room/hsPlayerChange";
import handleTypeChange from "./room/typeChange";
import handleHsPlayerEnter from "./room/hsPlayerEnter";
import handleJoinGame from "./room/joinGame";
import handleChat from "./room/chat";
import handleHsWatchChange from "./room/hsWatchChange";
import { ygoArrayBuilder } from "../api/ocgcore/ocgAdapter/packet";
import StocJoinGame from "../api/ocgcore/ocgAdapter/stoc/stocJoinGame";
import {
STOC_CHAT,
STOC_HS_PLAYER_CHANGE,
STOC_HS_PLAYER_ENTER,
STOC_HS_WATCH_CHANGE,
STOC_JOIN_GAME,
STOC_TYPE_CHANGE,
} from "../api/ocgcore/ocgAdapter/protoDecl";
import StocChat from "../api/ocgcore/ocgAdapter/stoc/stocChat";
import StocHsPlayerEnter from "../api/ocgcore/ocgAdapter/stoc/stocHsPlayerEnter";
import StocHsPlayerChange from "../api/ocgcore/ocgAdapter/stoc/stocHsPlayerChange";
import StocHsWatchChange from "../api/ocgcore/ocgAdapter/stoc/stocHsWatchChange";
import StocTypeChange from "../api/ocgcore/ocgAdapter/stoc/stocTypeChange";
export default function handleSocketMessage(e: MessageEvent) {
const pb = ygopro.YgoStocMsg.deserializeBinary(e.data);
const packet = new ygoArrayBuilder(e.data);
console.log(packet);
let pb = new ygopro.YgoStocMsg({});
switch (packet.proto) {
case STOC_JOIN_GAME: {
pb = new StocJoinGame(packet).adapt();
break;
}
case STOC_CHAT: {
pb = new StocChat(packet).adapt();
break;
}
case STOC_HS_PLAYER_ENTER: {
pb = new StocHsPlayerEnter(packet).adapt();
break;
}
case STOC_HS_PLAYER_CHANGE: {
pb = new StocHsPlayerChange(packet).adapt();
break;
}
case STOC_HS_WATCH_CHANGE: {
pb = new StocHsWatchChange(packet).adapt();
break;
}
case STOC_TYPE_CHANGE: {
pb = new StocTypeChange(packet).adapt();
break;
}
default: {
break;
}
}
switch (pb.msg) {
case "stoc_join_game": {
......
import { sendJoinGame, sendPlayerInfo } from "../api/helper";
import { sendJoinGame, sendPlayerInfo } from "../api/ocgcore/ocgHelper";
export default function handleSocketOpen(
ws: WebSocket | null,
......
import { ygopro } from "../../api/idl/ocgcore";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { postChat } from "../../reducers/chatSlice";
import { store } from "../../store";
......
import { ygopro } from "../../api/idl/ocgcore";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { store } from "../../store";
import {
player0Update,
......
import { ygopro } from "../../api/idl/ocgcore";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { store } from "../../store";
import { player0Enter, player1Enter } from "../../reducers/playerSlice";
......
import { ygopro } from "../../api/idl/ocgcore";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { observerChange } from "../../reducers/playerSlice";
import { store } from "../../store";
......
import { ygopro } from "../../api/idl/ocgcore";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { store } from "../../store";
import { setJoined } from "../../reducers/joinSlice";
......
import { ygopro } from "../../api/idl/ocgcore";
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import {
player0Update,
player1Update,
......
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { ygopro } from "../api/idl/ocgcore";
import { fetchDeck, IDeck } from "../api/Card";
import { fetchDeck } from "../api/Card";
import "../css/WaitRoom.css";
import { useAppSelector } from "../hook";
import { selectJoined } from "../reducers/joinSlice";
......@@ -12,7 +11,11 @@ import {
selectPlayer1,
selectObserverCount,
} from "../reducers/playerSlice";
import { sendUpdateDeck, sendHsReady, sendHsStart } from "../api/helper";
import {
sendUpdateDeck,
sendHsReady,
sendHsStart,
} from "../api/ocgcore/ocgHelper";
import socketMiddleWare, { socketCmd } from "../middleware/socket";
const READY_STATE = "ready";
......
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