Commit 363e5d8e authored by Chunchi Che's avatar Chunchi Che

Merge branch 'migrate/buffer' into 'main'

Migrate/buffer

See merge request mycard/Neos!140
parents 6125dec4 99705f45
Pipeline #20747 passed with stages
in 14 minutes and 41 seconds
......@@ -72,3 +72,37 @@ impl BufferReader {
ret
}
}
#[wasm_bindgen]
pub struct BufferWriter {
array: Vec<u8>,
}
#[wasm_bindgen]
impl BufferWriter {
#[wasm_bindgen(constructor)]
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self { array: Vec::new() }
}
pub fn writeUint8(&mut self, value: u8) {
self.array.push(value);
}
pub fn writeInt8(&mut self, value: i8) {
self.array.extend(value.to_le_bytes());
}
pub fn writeUint32(&mut self, value: u32) {
self.array.extend(value.to_le_bytes());
}
pub fn writeInt32(&mut self, value: i32) {
self.array.extend(value.to_le_bytes());
}
pub fn toArray(self) -> Vec<u8> {
self.array
}
}
......@@ -5,7 +5,7 @@ mod buffer;
mod utils;
pub use adapters::*;
pub use buffer::BufferReader;
pub use buffer::{BufferReader, BufferWriter};
pub use utils::set_panic_hook;
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
......
import { ygopro } from "../idl/ocgcore";
import { numberToCardPosition, numberToCardZone } from "./util";
// @ts-ignore
import { BufferReader } from "rust-src";
const OFFSET_UINT8 = 1;
const OFFSET_INT8 = 1;
const OFFSET_UINT16 = 2;
const OFFSET_UINT32 = 4;
const OFFSET_INT32 = 4;
const LOCATION_OVERLAY = 0x80;
export class BufferReader {
dataView: DataView;
littleEndian: boolean;
offset: number;
export class BufferReaderExt {
inner: BufferReader;
constructor(data: Uint8Array, littleEndian: boolean) {
this.dataView = new DataView(data.buffer);
this.littleEndian = littleEndian;
this.offset = 0;
}
readUint8(): number {
const ret = this.dataView.getUint8(this.offset);
this.offset += OFFSET_UINT8;
return ret;
}
readInt8(): number {
const ret = this.dataView.getInt8(this.offset);
this.offset += OFFSET_INT8;
return ret;
}
readUint16(): number {
const ret = this.dataView.getUint16(this.offset, this.littleEndian);
this.offset += OFFSET_UINT16;
return ret;
}
readUint32(): number {
const ret = this.dataView.getUint32(this.offset, this.littleEndian);
this.offset += OFFSET_UINT32;
return ret;
}
readInt32(): number {
const ret = this.dataView.getInt32(this.offset, this.littleEndian);
this.offset += OFFSET_INT32;
return ret;
constructor(data: Uint8Array) {
this.inner = new BufferReader(data);
}
readCardInfo(): ygopro.CardInfo {
const code = this.readUint32();
const controler = this.readUint8();
const location = numberToCardZone(this.readUint8());
const sequence = this.readUint8();
const code = this.inner.readUint32();
const controler = this.inner.readUint8();
const location = numberToCardZone(this.inner.readUint8());
const sequence = this.inner.readUint8();
return new ygopro.CardInfo({
code,
......@@ -69,10 +27,10 @@ export class BufferReader {
}
readCardLocation(): ygopro.CardLocation {
const controler = this.readUint8();
const location = this.readUint8();
const sequence = this.readUint8();
const ss = this.readUint8();
const controler = this.inner.readUint8();
const location = this.inner.readUint8();
const sequence = this.inner.readUint8();
const ss = this.inner.readUint8();
if (location & LOCATION_OVERLAY) {
// 超量素材
......@@ -92,35 +50,3 @@ export class BufferReader {
}
}
}
export class BufferWriter {
dataView: DataView;
littleEndian: boolean;
offset: number;
constructor(data: Uint8Array, littleEndian: boolean) {
this.dataView = new DataView(data.buffer);
this.littleEndian = littleEndian;
this.offset = 0;
}
writeUint8(value: number) {
this.dataView.setUint8(this.offset, value);
this.offset += OFFSET_UINT8;
}
writeInt8(value: number) {
this.dataView.setInt8(this.offset, value);
this.offset += OFFSET_INT8;
}
writeUint32(value: number) {
this.dataView.setUint32(this.offset, value, this.littleEndian);
this.offset += OFFSET_UINT32;
}
writeInt32(value: number) {
this.dataView.setInt32(this.offset, value, this.littleEndian);
this.offset += OFFSET_INT32;
}
}
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
export default (
response: ygopro.CtosGameMsgResponse.SelectBattleCmdResponse
) => {
const array = new Uint8Array(4);
const writer = new BufferWriter(array, true);
const writer = new BufferWriter();
writer.writeUint32(response.selected_cmd);
return array;
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
export default (response: ygopro.CtosGameMsgResponse.SelectCardResponse) => {
const array = new Uint8Array(1 + response.selected_ptrs.length);
const writer = new BufferWriter(array, true);
const writer = new BufferWriter();
writer.writeUint8(response.selected_ptrs.length);
for (const ptr of response.selected_ptrs) {
writer.writeUint8(ptr);
}
return array;
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
export default (response: ygopro.CtosGameMsgResponse.SelectChainResponse) => {
const array = new Uint8Array(4);
const writer = new BufferWriter(array, true);
const writer = new BufferWriter();
writer.writeInt32(response.selected_ptr);
return array;
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
export default (
response: ygopro.CtosGameMsgResponse.SelectEffectYnResponse
) => {
const array = new Uint8Array(4);
const writer = new BufferWriter(array, true);
const writer = new BufferWriter();
writer.writeUint32(response.selected ? 1 : 0);
return array;
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
export default (response: ygopro.CtosGameMsgResponse.SelectIdleCmdResponse) => {
const array = new Uint8Array(4);
const writer = new BufferWriter(array, true);
const writer = new BufferWriter();
writer.writeUint32(response.code);
return array;
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
export default (response: ygopro.CtosGameMsgResponse.SelectOptionResponse) => {
const array = new Uint8Array(4);
const writer = new BufferWriter(array, true);
const writer = new BufferWriter();
writer.writeUint32(response.code);
return array;
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
import { cardZoneToNumber } from "../../util";
export default (response: ygopro.CtosGameMsgResponse.SelectPlaceResponse) => {
const array = new Uint8Array(3);
const writer = new BufferWriter(array, true);
const writer = new BufferWriter();
writer.writeUint8(response.player);
writer.writeUint8(cardZoneToNumber(response.zone));
writer.writeUint8(response.sequence);
return array;
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
export default (
response: ygopro.CtosGameMsgResponse.SelectPositionResponse
) => {
const array = new Uint8Array(4);
const writer = new BufferWriter(array, true);
const writer = new BufferWriter();
switch (response.position) {
case ygopro.CardPosition.FACEUP_ATTACK: {
......@@ -33,5 +33,5 @@ export default (
}
}
return array;
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferWriter } from "../../bufferIO";
// @ts-ignore
import { BufferWriter } from "rust-src";
export default (
response: ygopro.CtosGameMsgResponse.SelectUnselectCardResponse
) => {
const writer = new BufferWriter();
if (response.cancel_or_finish) {
const array = new Uint8Array(4);
const writer = new BufferWriter(array, true);
writer.writeInt32(-1);
return array;
} else {
const array = new Uint8Array(2);
const writer = new BufferWriter(array, true);
writer.writeUint8(1);
writer.writeUint8(response.selected_ptr);
return array;
}
return writer.toArray();
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferReader } from "../../bufferIO";
import { BufferReaderExt } from "../../bufferIO";
import MsgMove = ygopro.StocGameMessage.MsgMove;
/*
......@@ -10,9 +10,9 @@ import MsgMove = ygopro.StocGameMessage.MsgMove;
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data, true);
const reader = new BufferReaderExt(data);
const code = reader.readUint32();
const code = reader.inner.readUint32();
const fromLocation = reader.readCardLocation();
const toLocation = reader.readCardLocation();
......@@ -21,6 +21,6 @@ export default (data: Uint8Array) => {
code,
from: fromLocation,
to: toLocation,
reason: reader.readUint8(),
reason: reader.inner.readUint8(),
});
};
//! 透传协议
import PenetrateData from "./penetrate.json";
import { BufferReader } from "../../bufferIO";
import { BufferReaderExt } from "../../bufferIO";
import { ygopro } from "../../../idl/ocgcore";
import { numberToCardPosition } from "../../util";
type Constructor<T = any> = new (...args: any[]) => T;
const ReadFieldHandlerMap: Map<string, readFieldHandler> = new Map([
["uint8", ((reader) => reader.readUint8()) as readFieldHandler],
["uint16", (reader) => reader.readUint16()],
["uint32", (reader) => reader.readUint32()],
["uint8", ((reader) => reader.inner.readUint8()) as readFieldHandler],
["uint16", (reader) => reader.inner.readUint16()],
["uint32", (reader) => reader.inner.readUint32()],
["CardLocation", (reader) => reader.readCardLocation()],
["CardInfo", (reader) => reader.readCardInfo()],
["CardPosition", (reader) => numberToCardPosition(reader.readUint8())],
["CardPosition", (reader) => numberToCardPosition(reader.inner.readUint8())],
]);
const MsgConstructorMap: Map<string, Constructor> = new Map([
["move", ygopro.StocGameMessage.MsgMove as Constructor],
......@@ -32,7 +32,7 @@ export interface penetrateType {
}
interface readFieldHandler {
(reader: BufferReader): any;
(reader: BufferReaderExt): any;
}
class PenetrateManager {
......@@ -44,7 +44,7 @@ class PenetrateManager {
this.config = _objToMap(config);
}
private readField(reader: BufferReader, fieldType: string): any {
private readField(reader: BufferReaderExt, fieldType: string): any {
const handler = this.readFieldHandlerMap.get(fieldType);
if (handler) {
......@@ -53,11 +53,14 @@ class PenetrateManager {
return undefined;
}
private readRepeatedField(reader: BufferReader, repeatedType: string): any {
private readRepeatedField(
reader: BufferReaderExt,
repeatedType: string
): any {
const handler = this.readFieldHandlerMap.get(repeatedType);
if (handler) {
const count = reader.readUint8();
const count = reader.inner.readUint8();
let repeated = [];
for (let i = 0; i < count; i++) {
......@@ -80,7 +83,7 @@ class PenetrateManager {
penetrate(msgKey: number, gameMsg: any, gameData: Uint8Array): boolean {
const config = this.config.get(msgKey.toString());
const reader = new BufferReader(gameData, true);
const reader = new BufferReaderExt(gameData);
if (config) {
const protoType = config.protoType;
......
import { ygopro } from "../../../idl/ocgcore";
import { BufferReader } from "../../bufferIO";
import { BufferReaderExt } from "../../bufferIO";
import MsgSelectBattleCmd = ygopro.StocGameMessage.MsgSelectBattleCmd;
/*
......@@ -11,20 +11,20 @@ import MsgSelectBattleCmd = ygopro.StocGameMessage.MsgSelectBattleCmd;
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data, true);
const reader = new BufferReaderExt(data);
const msg = new MsgSelectBattleCmd({});
msg.player = reader.readUint8();
msg.player = reader.inner.readUint8();
// 可发动效果
const activateCmd = new MsgSelectBattleCmd.BattleCmd({
battle_type: MsgSelectBattleCmd.BattleCmd.BattleType.ACTIVATE,
battle_datas: [],
});
const activateCount = reader.readUint8();
const activateCount = reader.inner.readUint8();
for (let i = 0; i < activateCount; i++) {
const cardInfo = reader.readCardInfo();
const effectDescription = reader.readUint32();
const effectDescription = reader.inner.readUint32();
const activateData = new MsgSelectBattleCmd.BattleCmd.BattleData({
card_info: cardInfo,
effect_description: effectDescription,
......@@ -38,10 +38,10 @@ export default (data: Uint8Array) => {
battle_type: MsgSelectBattleCmd.BattleCmd.BattleType.ATTACK,
battle_datas: [],
});
const attackCount = reader.readUint8();
const attackCount = reader.inner.readUint8();
for (let i = 0; i < attackCount; i++) {
const cardInfo = reader.readCardInfo();
const directAttackAble = reader.readUint8();
const directAttackAble = reader.inner.readUint8();
const attackData = new MsgSelectBattleCmd.BattleCmd.BattleData({
card_info: cardInfo,
direct_attackable: directAttackAble == 1,
......@@ -53,9 +53,9 @@ export default (data: Uint8Array) => {
msg.battle_cmds = [activateCmd, attackCmd];
// 是否可进入M2阶段
msg.enable_m2 = reader.readUint8() == 1;
msg.enable_m2 = reader.inner.readUint8() == 1;
//时是否可结束回合
msg.enable_ep = reader.readUint8() == 1;
msg.enable_ep = reader.inner.readUint8() == 1;
return msg;
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferReader } from "../../bufferIO";
import { BufferReaderExt } from "../../bufferIO";
import MsgSelectCard = ygopro.StocGameMessage.MsgSelectCard;
/*
......@@ -10,18 +10,18 @@ import MsgSelectCard = ygopro.StocGameMessage.MsgSelectCard;
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data, true);
const reader = new BufferReaderExt(data);
const player = reader.readUint8();
const cancelable = reader.readUint8() != 0;
const min = reader.readUint8();
const max = reader.readUint8();
const count = reader.readUint8();
const player = reader.inner.readUint8();
const cancelable = reader.inner.readUint8() != 0;
const min = reader.inner.readUint8();
const max = reader.inner.readUint8();
const count = reader.inner.readUint8();
const msg = new MsgSelectCard({ player, cancelable, min, max });
for (let i = 0; i < count; i++) {
const code = reader.readUint32();
const code = reader.inner.readUint32();
const location = reader.readCardLocation();
msg.cards.push(
......
import { ygopro } from "../../../idl/ocgcore";
import { BufferReader } from "../../bufferIO";
import { BufferReaderExt } from "../../bufferIO";
import MsgSelectChain = ygopro.StocGameMessage.MsgSelectChain;
import { numberToChainFlag } from "../../util";
......@@ -12,14 +12,14 @@ import { numberToChainFlag } from "../../util";
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data, true);
const reader = new BufferReaderExt(data);
const player = reader.readUint8();
const count = reader.readUint8();
const spCount = reader.readUint8();
const forced = reader.readUint8() != 0;
const hint0 = reader.readUint32();
const hint1 = reader.readUint32();
const player = reader.inner.readUint8();
const count = reader.inner.readUint8();
const spCount = reader.inner.readUint8();
const forced = reader.inner.readUint8() != 0;
const hint0 = reader.inner.readUint32();
const hint1 = reader.inner.readUint32();
const msg = new MsgSelectChain({
player,
......@@ -31,10 +31,10 @@ export default (data: Uint8Array) => {
});
for (let i = 0; i < count; i++) {
const flag = reader.readUint8();
const code = reader.readUint32();
const flag = reader.inner.readUint8();
const code = reader.inner.readUint32();
const location = reader.readCardLocation();
const effect_desc = reader.readUint32();
const effect_desc = reader.inner.readUint32();
msg.chains.push(
new MsgSelectChain.Chain({
......
import { ygopro } from "../../../idl/ocgcore";
import { BufferReader } from "../../bufferIO";
import { BufferReaderExt } from "../../bufferIO";
import MsgSelectEffectYn = ygopro.StocGameMessage.MsgSelectEffectYn;
/*
......@@ -11,12 +11,12 @@ import MsgSelectEffectYn = ygopro.StocGameMessage.MsgSelectEffectYn;
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data, true);
const reader = new BufferReaderExt(data);
const player = reader.readUint8();
const code = reader.readUint32();
const player = reader.inner.readUint8();
const code = reader.inner.readUint32();
const location = reader.readCardLocation();
const effect_description = reader.readUint32();
const effect_description = reader.inner.readUint32();
return new MsgSelectEffectYn({
player,
......
import { ygopro } from "../../../idl/ocgcore";
import { BufferReader } from "../../bufferIO";
import { BufferReaderExt } from "../../bufferIO";
import MsgSelectIdleCmd = ygopro.StocGameMessage.MsgSelectIdleCmd;
const LITTLE_ENDIAN = true;
/*
* Msg Select Idle Command
*
......@@ -13,17 +11,17 @@ const LITTLE_ENDIAN = true;
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data, LITTLE_ENDIAN);
const reader = new BufferReaderExt(data);
const msg = new MsgSelectIdleCmd({});
msg.player = reader.readUint8();
msg.player = reader.inner.readUint8();
// 通常召唤
const summonCmd = new MsgSelectIdleCmd.IdleCmd({
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.SUMMON,
idle_datas: [],
});
const summonCount = reader.readUint8();
const summonCount = reader.inner.readUint8();
for (let i = 0; i < summonCount; i++) {
const idleData = new MsgSelectIdleCmd.IdleCmd.IdleData({
card_info: reader.readCardInfo(),
......@@ -37,7 +35,7 @@ export default (data: Uint8Array) => {
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.SPSUMMON,
idle_datas: [],
});
const spSummonCount = reader.readUint8();
const spSummonCount = reader.inner.readUint8();
for (let i = 0; i < spSummonCount; i++) {
const idleData = new MsgSelectIdleCmd.IdleCmd.IdleData({
card_info: reader.readCardInfo(),
......@@ -51,7 +49,7 @@ export default (data: Uint8Array) => {
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.POS_CHANGE,
idle_datas: [],
});
const posChangeCount = reader.readUint8();
const posChangeCount = reader.inner.readUint8();
for (let i = 0; i < posChangeCount; i++) {
const idleData = new MsgSelectIdleCmd.IdleCmd.IdleData({
card_info: reader.readCardInfo(),
......@@ -65,7 +63,7 @@ export default (data: Uint8Array) => {
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.MSET,
idle_datas: [],
});
const mSetCount = reader.readUint8();
const mSetCount = reader.inner.readUint8();
for (let i = 0; i < mSetCount; i++) {
const idleData = new MsgSelectIdleCmd.IdleCmd.IdleData({
card_info: reader.readCardInfo(),
......@@ -79,7 +77,7 @@ export default (data: Uint8Array) => {
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.SSET,
idle_datas: [],
});
const sSetCount = reader.readUint8();
const sSetCount = reader.inner.readUint8();
for (let i = 0; i < sSetCount; i++) {
const idleData = new MsgSelectIdleCmd.IdleCmd.IdleData({
card_info: reader.readCardInfo(),
......@@ -93,11 +91,11 @@ export default (data: Uint8Array) => {
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.ACTIVATE,
idle_datas: [],
});
const activateCount = reader.readUint8();
const activateCount = reader.inner.readUint8();
for (let i = 0; i < activateCount; i++) {
const idleData = new MsgSelectIdleCmd.IdleCmd.IdleData({
card_info: reader.readCardInfo(),
effect_description: reader.readUint32(),
effect_description: reader.inner.readUint32(),
response: (i << 16) + 5,
});
activateCmd.idle_datas.push(idleData);
......@@ -113,11 +111,11 @@ export default (data: Uint8Array) => {
];
// 进入战斗阶段
msg.enable_bp = reader.readUint8() === 1;
msg.enable_bp = reader.inner.readUint8() === 1;
// 结束回合
msg.enable_ep = reader.readUint8() === 1;
msg.enable_ep = reader.inner.readUint8() === 1;
// 切洗手牌
msg.enable_shuffle = reader.readUint8() === 1;
msg.enable_shuffle = reader.inner.readUint8() === 1;
return msg;
};
import { ygopro } from "../../../idl/ocgcore";
import { BufferReader } from "../../bufferIO";
import { BufferReaderExt } from "../../bufferIO";
import MsgSelectUnselectCard = ygopro.StocGameMessage.MsgSelectUnselectCard;
/*
......@@ -10,13 +10,13 @@ import MsgSelectUnselectCard = ygopro.StocGameMessage.MsgSelectUnselectCard;
* @usage - 玩家选择未选择的卡牌
* */
export default (data: Uint8Array) => {
const reader = new BufferReader(data, true);
const reader = new BufferReaderExt(data);
const player = reader.readUint8();
const finishable = reader.readUint8() != 0;
const cancelable = reader.readUint8() != 0;
const min = reader.readUint8();
const max = reader.readUint8();
const player = reader.inner.readUint8();
const finishable = reader.inner.readUint8() != 0;
const cancelable = reader.inner.readUint8() != 0;
const min = reader.inner.readUint8();
const max = reader.inner.readUint8();
const msg = new MsgSelectUnselectCard({
player,
......@@ -26,9 +26,9 @@ export default (data: Uint8Array) => {
max,
});
const count1 = reader.readUint8();
const count1 = reader.inner.readUint8();
for (let i = 0; i < count1; i++) {
const code = reader.readUint32();
const code = reader.inner.readUint32();
const location = reader.readCardLocation();
msg.selectable_cards.push(
......@@ -36,9 +36,9 @@ export default (data: Uint8Array) => {
);
}
const count2 = reader.readUint8();
const count2 = reader.inner.readUint8();
for (let i = count1; i < count1 + count2; i++) {
const code = reader.readUint32();
const code = reader.inner.readUint32();
const location = reader.readCardLocation();
msg.selected_cards.push(
......
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