binary optimization
This commit is contained in:
parent
c31af6b02a
commit
eeaa7915de
@ -87,7 +87,6 @@ export default class DataManager extends Singleton {
|
||||
player.direction = { x, y }
|
||||
break
|
||||
}
|
||||
|
||||
case InputTypeEnum.WeaponShoot: {
|
||||
const { owner, position, direction } = input
|
||||
const bullet: IBullet = {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Singleton from '../Base/Singleton'
|
||||
import { ApiMsgEnum, IModel, strdecode, strencode } from '../Common';
|
||||
import { binaryEncode } from '../Common/Binary';
|
||||
import { binaryDecode } from '../Utils';
|
||||
import { binaryEncode, binaryDecode } from '../Common/Binary';
|
||||
|
||||
const TIMEOUT = 5000
|
||||
|
||||
@ -94,8 +93,6 @@ export default class NetworkManager extends Singleton {
|
||||
|
||||
sendMsg<T extends keyof IModel['msg']>(name: T, data: IModel['msg'][T]) {
|
||||
const view = binaryEncode(name, data)
|
||||
console.log("view", view.buffer);
|
||||
|
||||
this.ws.send(view.buffer)
|
||||
}
|
||||
|
||||
|
@ -8,80 +8,4 @@ const getNumberWithinString = (str: string) => parseInt(str.match(INDEX_REG)?.[1
|
||||
export const sortSpriteFrame = (spriteFrame: Array<SpriteFrame>) =>
|
||||
spriteFrame.sort((a, b) => getNumberWithinString(a.name) - getNumberWithinString(b.name))
|
||||
|
||||
export const rad2Angle = (rad: number) => rad / Math.PI * 180
|
||||
|
||||
export const binaryDecode = (buffer: ArrayBuffer) => {
|
||||
let index = 0
|
||||
const view = new DataView(buffer)
|
||||
const type = view.getUint8(index++)
|
||||
|
||||
if (type === ApiMsgEnum.MsgClientSync) {
|
||||
const inputType = view.getUint8(index++)
|
||||
if (inputType === InputTypeEnum.ActorMove) {
|
||||
const id = view.getUint8(index++)
|
||||
const directionX = view.getFloat32(index)
|
||||
index += 4
|
||||
const directionY = view.getFloat32(index)
|
||||
index += 4
|
||||
const dt = view.getFloat32(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.ActorMove,
|
||||
id,
|
||||
direction: {
|
||||
x: directionX,
|
||||
y: directionY,
|
||||
},
|
||||
dt
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
} else if (inputType === InputTypeEnum.WeaponShoot) {
|
||||
const id = view.getUint8(index++)
|
||||
const positionX = view.getFloat32(index)
|
||||
index += 4
|
||||
const positionY = view.getFloat32(index)
|
||||
index += 4
|
||||
const directionX = view.getFloat32(index)
|
||||
index += 4
|
||||
const directionY = view.getFloat32(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.WeaponShoot,
|
||||
id,
|
||||
position: {
|
||||
x: positionX,
|
||||
y: positionY,
|
||||
},
|
||||
direction: {
|
||||
x: directionX,
|
||||
y: directionY,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
} else {
|
||||
const dt = view.getFloat32(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.TimePast,
|
||||
dt,
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
name: type,
|
||||
data: JSON.parse(strdecode(new Uint8Array(buffer.slice(1))))
|
||||
}
|
||||
}
|
||||
}
|
||||
export const rad2Angle = (rad: number) => rad / Math.PI * 180
|
@ -1,57 +1,92 @@
|
||||
import { ApiMsgEnum, InputTypeEnum } from "./Enum";
|
||||
import { strencode } from "./Utils";
|
||||
import { strdecode, strencode } from "./Utils";
|
||||
|
||||
const encodeActorMove = (proto: ApiMsgEnum, data: any, view: DataView, index: number) => {
|
||||
view.setUint8(index++, data.type)
|
||||
view.setUint8(index++, data.id)
|
||||
view.setFloat32(index, data.direction.x)
|
||||
index += 4
|
||||
view.setFloat32(index, data.direction.y)
|
||||
index += 4
|
||||
view.setFloat32(index, data.dt)
|
||||
index += 4
|
||||
}
|
||||
|
||||
const encodeWeaponShoot = (proto: ApiMsgEnum, data: any, view: DataView, index: number) => {
|
||||
view.setUint8(index++, data.type)
|
||||
view.setUint8(index++, data.owner)
|
||||
view.setFloat32(index, data.position.x)
|
||||
index += 4
|
||||
view.setFloat32(index, data.position.y)
|
||||
index += 4
|
||||
view.setFloat32(index, data.direction.x)
|
||||
index += 4
|
||||
view.setFloat32(index, data.direction.y)
|
||||
index += 4
|
||||
}
|
||||
|
||||
export const encdoeTimePast = (proto: ApiMsgEnum, data: any, view: DataView, index: number) => {
|
||||
view.setUint8(index++, data.type)
|
||||
view.setFloat32(index, data.dt)
|
||||
index += 4
|
||||
}
|
||||
|
||||
export const binaryEncode = (proto: ApiMsgEnum, data: any): DataView => {
|
||||
if (proto === ApiMsgEnum.MsgClientSync) {
|
||||
switch (data.type) {
|
||||
case InputTypeEnum.ActorMove: {
|
||||
let index = 0
|
||||
const ab = new ArrayBuffer(3 + 12)
|
||||
const view = new DataView(ab)
|
||||
view.setUint8(index++, proto)
|
||||
view.setUint8(index++, data.type)
|
||||
view.setUint8(index++, data.id)
|
||||
view.setFloat32(index, data.direction.x)
|
||||
index += 4
|
||||
view.setFloat32(index, data.direction.y)
|
||||
index += 4
|
||||
view.setFloat32(index, data.dt)
|
||||
index += 4
|
||||
return view
|
||||
}
|
||||
case InputTypeEnum.WeaponShoot: {
|
||||
let index = 0
|
||||
const ab = new ArrayBuffer(3 + 16)
|
||||
const view = new DataView(ab)
|
||||
view.setUint8(index++, proto)
|
||||
view.setUint8(index++, data.type)
|
||||
view.setUint8(index++, data.id)
|
||||
view.setFloat32(index, data.position.x)
|
||||
index += 4
|
||||
view.setFloat32(index, data.position.y)
|
||||
index += 4
|
||||
view.setFloat32(index, data.direction.x)
|
||||
index += 4
|
||||
view.setFloat32(index, data.direction.y)
|
||||
index += 4
|
||||
return view
|
||||
}
|
||||
case InputTypeEnum.TimePast: {
|
||||
let index = 0
|
||||
const ab = new ArrayBuffer(1 + 1 + 4)
|
||||
const view = new DataView(ab)
|
||||
view.setUint8(index++, proto)
|
||||
view.setUint8(index++, data.type)
|
||||
view.setFloat32(index, data.dt)
|
||||
index += 4
|
||||
return view
|
||||
}
|
||||
default: {
|
||||
const ab = new ArrayBuffer(0)
|
||||
const view = new DataView(ab)
|
||||
return view
|
||||
if (data.type === InputTypeEnum.ActorMove) {
|
||||
let index = 0
|
||||
const ab = new ArrayBuffer(3 + 12)
|
||||
const view = new DataView(ab)
|
||||
view.setUint8(index++, proto)
|
||||
encodeActorMove(proto, data, view, index)
|
||||
return view
|
||||
} else if (data.type === InputTypeEnum.WeaponShoot) {
|
||||
let index = 0
|
||||
const ab = new ArrayBuffer(3 + 16)
|
||||
const view = new DataView(ab)
|
||||
view.setUint8(index++, proto)
|
||||
encodeWeaponShoot(proto, data, view, index)
|
||||
return view
|
||||
} else {
|
||||
let index = 0
|
||||
const ab = new ArrayBuffer(2 + 4)
|
||||
const view = new DataView(ab)
|
||||
view.setUint8(index++, proto)
|
||||
encdoeTimePast(proto, data, view, index)
|
||||
return view
|
||||
}
|
||||
} else if (proto === ApiMsgEnum.MsgServerSync) {
|
||||
let total = 0
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const item = data[i];
|
||||
if (item.type === InputTypeEnum.ActorMove) {
|
||||
total += 14
|
||||
} else if (item.type === InputTypeEnum.WeaponShoot) {
|
||||
total += 18
|
||||
} else {
|
||||
total += 5
|
||||
}
|
||||
}
|
||||
const ab = new ArrayBuffer(1 + 1 + total)
|
||||
const view = new DataView(ab)
|
||||
let index = 0
|
||||
view.setUint8(index++, proto)
|
||||
view.setUint8(index++, data.length)
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const item = data[i];
|
||||
if (item.type === InputTypeEnum.ActorMove) {
|
||||
encodeActorMove(proto, item, view, index)
|
||||
index += 14
|
||||
} else if (item.type === InputTypeEnum.WeaponShoot) {
|
||||
encodeWeaponShoot(proto, item, view, index)
|
||||
index += 18
|
||||
} else {
|
||||
encdoeTimePast(proto, item, view, index)
|
||||
index += 5
|
||||
}
|
||||
}
|
||||
|
||||
return view
|
||||
} else {
|
||||
let index = 0
|
||||
const str = JSON.stringify(data)
|
||||
@ -64,4 +99,113 @@ export const binaryEncode = (proto: ApiMsgEnum, data: any): DataView => {
|
||||
}
|
||||
return view
|
||||
}
|
||||
}
|
||||
|
||||
const decodeActorMove = (view: DataView, index: number) => {
|
||||
const id = view.getUint8(index++)
|
||||
const directionX = view.getFloat32(index)
|
||||
index += 4
|
||||
const directionY = view.getFloat32(index)
|
||||
index += 4
|
||||
const dt = view.getFloat32(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.ActorMove,
|
||||
id,
|
||||
direction: {
|
||||
x: directionX,
|
||||
y: directionY,
|
||||
},
|
||||
dt
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
const decodeWeaponShoot = (view: DataView, index: number) => {
|
||||
const owner = view.getUint8(index++)
|
||||
const positionX = view.getFloat32(index)
|
||||
index += 4
|
||||
const positionY = view.getFloat32(index)
|
||||
index += 4
|
||||
const directionX = view.getFloat32(index)
|
||||
index += 4
|
||||
const directionY = view.getFloat32(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.WeaponShoot,
|
||||
owner,
|
||||
position: {
|
||||
x: positionX,
|
||||
y: positionY,
|
||||
},
|
||||
direction: {
|
||||
x: directionX,
|
||||
y: directionY,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
const decodeTimePast = (view: DataView, index: number) => {
|
||||
const dt = view.getFloat32(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.TimePast,
|
||||
dt,
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
export const binaryDecode = (buffer: ArrayBuffer) => {
|
||||
let index = 0
|
||||
const view = new DataView(buffer)
|
||||
const proto = view.getUint8(index++)
|
||||
|
||||
if (proto === ApiMsgEnum.MsgClientSync) {
|
||||
const inputType = view.getUint8(index++)
|
||||
if (inputType === InputTypeEnum.ActorMove) {
|
||||
return decodeActorMove(view, index)
|
||||
} else if (inputType === InputTypeEnum.WeaponShoot) {
|
||||
return decodeWeaponShoot(view, index)
|
||||
} else {
|
||||
return decodeTimePast(view, index)
|
||||
}
|
||||
} else if (proto === ApiMsgEnum.MsgServerSync) {
|
||||
const len = view.getUint8(index++)
|
||||
const res = []
|
||||
for (let i = 0; i < len; i++) {
|
||||
const inputType = view.getUint8(index++)
|
||||
|
||||
if (inputType === InputTypeEnum.ActorMove) {
|
||||
res.push(decodeActorMove(view, index).data)
|
||||
index += 13
|
||||
} else if (inputType === InputTypeEnum.WeaponShoot) {
|
||||
res.push(decodeWeaponShoot(view, index).data)
|
||||
index += 17
|
||||
} else {
|
||||
res.push(decodeTimePast(view, index).data)
|
||||
index += 4
|
||||
}
|
||||
}
|
||||
return {
|
||||
name: ApiMsgEnum.MsgServerSync,
|
||||
data: res
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
name: proto,
|
||||
data: JSON.parse(strdecode(new Uint8Array(buffer.slice(1))))
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ export * from './Enum'
|
||||
export * from './Model'
|
||||
export * from './State'
|
||||
export * from './Utils'
|
||||
export * from './Binary'
|
||||
|
||||
export interface IModel {
|
||||
api: {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import WebSocket from 'ws';
|
||||
import { EventEmitter } from 'stream';
|
||||
import { MyServer } from './MyServer';
|
||||
import { binaryDecode, getTime } from '../Utils';
|
||||
import { getTime, toArrayBuffer } from '../Utils';
|
||||
import { ApiMsgEnum, IModel } from '../Common';
|
||||
import { binaryEncode } from '../Common/Binary';
|
||||
import { binaryEncode, binaryDecode } from '../Common/Binary';
|
||||
|
||||
export enum ConnectionEventEnum {
|
||||
Close = 'Close',
|
||||
@ -27,7 +27,7 @@ export class Connection extends EventEmitter {
|
||||
this.ws.on('message', (buffer: Buffer) => {
|
||||
// const str = buffer.toString()
|
||||
try {
|
||||
const json = binaryDecode(buffer)
|
||||
const json = binaryDecode(toArrayBuffer(buffer))
|
||||
const { name, data } = json
|
||||
// console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${str}`)
|
||||
console.log(`${getTime()}接收|字节数${buffer.length}|${this.playerId || -1}|${JSON.stringify(json)}`)
|
||||
|
@ -1,6 +1,5 @@
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import { ApiMsgEnum, InputTypeEnum, strdecode } from '../Common'
|
||||
|
||||
export const getTime = () => new Date().toLocaleString().split("├")[0]
|
||||
|
||||
@ -37,77 +36,11 @@ export const copyCommon = async () => {
|
||||
console.log('同步成功!')
|
||||
}
|
||||
|
||||
export const binaryDecode = (buffer: Buffer) => {
|
||||
let index = 0
|
||||
const type = buffer.readUint8(index++)
|
||||
|
||||
if (type === ApiMsgEnum.MsgClientSync) {
|
||||
const inputType = buffer.readUint8(index++)
|
||||
if (inputType === InputTypeEnum.ActorMove) {
|
||||
const id = buffer.readUint8(index++)
|
||||
const directionX = buffer.readFloatBE(index)
|
||||
index += 4
|
||||
const directionY = buffer.readFloatBE(index)
|
||||
index += 4
|
||||
const dt = buffer.readFloatBE(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.ActorMove,
|
||||
id,
|
||||
direction: {
|
||||
x: directionX,
|
||||
y: directionY,
|
||||
},
|
||||
dt
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
} else if (inputType === InputTypeEnum.WeaponShoot) {
|
||||
const id = buffer.readUint8(index++)
|
||||
const positionX = buffer.readFloatBE(index)
|
||||
index += 4
|
||||
const positionY = buffer.readFloatBE(index)
|
||||
index += 4
|
||||
const directionX = buffer.readFloatBE(index)
|
||||
index += 4
|
||||
const directionY = buffer.readFloatBE(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.WeaponShoot,
|
||||
id,
|
||||
position: {
|
||||
x: positionX,
|
||||
y: positionY,
|
||||
},
|
||||
direction: {
|
||||
x: directionX,
|
||||
y: directionY,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
} else {
|
||||
const dt = buffer.readFloatBE(index)
|
||||
index += 4
|
||||
const msg = {
|
||||
name: ApiMsgEnum.MsgClientSync,
|
||||
data: {
|
||||
type: InputTypeEnum.TimePast,
|
||||
dt,
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
name: type,
|
||||
data: JSON.parse(strdecode(new Uint8Array(buffer.slice(1))))
|
||||
}
|
||||
export const toArrayBuffer = (buffer: Buffer) => {
|
||||
var ab = new ArrayBuffer(buffer.length);
|
||||
var view = new Uint8Array(ab);
|
||||
for (var i = 0; i < buffer.length; ++i) {
|
||||
view[i] = buffer[i];
|
||||
}
|
||||
return ab;
|
||||
}
|
34
test.js
34
test.js
@ -1,30 +1,4 @@
|
||||
const msg = JSON.stringify({
|
||||
a: 123,
|
||||
b: true,
|
||||
c: "456"
|
||||
})
|
||||
|
||||
const strencode = (str) => {
|
||||
let byteArray = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let charCode = str.charCodeAt(i);
|
||||
if (charCode <= 0x7f) {
|
||||
byteArray.push(charCode);
|
||||
} else if (charCode <= 0x7ff) {
|
||||
byteArray.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f));
|
||||
} else if (charCode <= 0xffff) {
|
||||
byteArray.push(0xe0 | (charCode >> 12), 0x80 | ((charCode & 0xfc0) >> 6), 0x80 | (charCode & 0x3f));
|
||||
} else {
|
||||
byteArray.push(0xf0 | (charCode >> 18), 0x80 | ((charCode & 0x3f000) >> 12), 0x80 | ((charCode & 0xfc0) >> 6), 0x80 | (charCode & 0x3f));
|
||||
}
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
var arr = strencode(msg)
|
||||
var buffer = Buffer.from(msg)
|
||||
|
||||
console.log(buffer)
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
console.log(buffer[i], arr[i]);
|
||||
}
|
||||
const ab = new ArrayBuffer(10)
|
||||
const view = new DataView(ab)
|
||||
view.setFloat32(0, 0.0023)
|
||||
console.log(view);
|
Loading…
Reference in New Issue
Block a user