2022-12-08 21:14:02 +08:00

237 lines
6.2 KiB
TypeScript

import { ApiMsgEnum, InputTypeEnum } from "./Enum";
import { strdecode, strencode, toFixed } from "./Utils";
const encodeActorMove = (input: any, view: DataView, index: number) => {
view.setUint8(index++, input.type)
view.setUint8(index++, input.id)
view.setFloat32(index, input.direction.x)
index += 4
view.setFloat32(index, input.direction.y)
index += 4
view.setFloat32(index, input.dt)
index += 4
}
const encodeWeaponShoot = (input: any, view: DataView, index: number) => {
view.setUint8(index++, input.type)
view.setUint8(index++, input.owner)
view.setFloat32(index, input.position.x)
index += 4
view.setFloat32(index, input.position.y)
index += 4
view.setFloat32(index, input.direction.x)
index += 4
view.setFloat32(index, input.direction.y)
index += 4
}
export const encodeTimePast = (input: any, view: DataView, index: number) => {
view.setUint8(index++, input.type)
view.setFloat32(index, input.dt)
index += 4
}
export const binaryEncode = (name: ApiMsgEnum, data: any): DataView => {
if (name === ApiMsgEnum.MsgClientSync) {
//name 1字节 + frameId 4字节 + 数据长度 n 字节
const { frameId, input } = data
if (input.type === InputTypeEnum.ActorMove) {
let index = 0
const ab = new ArrayBuffer(1 + 4 + 14)
const view = new DataView(ab)
view.setUint8(index++, name)
view.setUint32(index, frameId)
index += 4
encodeActorMove(input, view, index)
return view
} else if (input.type === InputTypeEnum.WeaponShoot) {
let index = 0
const ab = new ArrayBuffer(1 + 4 + 18)
const view = new DataView(ab)
view.setUint8(index++, name)
view.setUint32(index, frameId)
index += 4
encodeWeaponShoot(input, view, index)
return view
} else {
let index = 0
const ab = new ArrayBuffer(1 + 4 + 5)
const view = new DataView(ab)
view.setUint8(index++, name)
view.setUint32(index, frameId)
index += 4
encodeTimePast(input, view, index)
return view
}
} else if (name === ApiMsgEnum.MsgServerSync) {
const { lastFrameId, inputs } = data
let total = 0
for (const input of inputs) {
if (input.type === InputTypeEnum.ActorMove) {
total += 14
} else if (input.type === InputTypeEnum.WeaponShoot) {
total += 18
} else {
total += 5
}
}
//name 1字节 + lastFrameId 4字节 + 数组长度 1字节 + 数据长度 n 字节
const ab = new ArrayBuffer(1 + 4 + 1 + total)
const view = new DataView(ab)
let index = 0
view.setUint8(index++, name)
view.setUint32(index, lastFrameId)
index += 4
view.setUint8(index++, inputs.length)
for (const input of inputs) {
if (input.type === InputTypeEnum.ActorMove) {
encodeActorMove(input, view, index)
index += 14
} else if (input.type === InputTypeEnum.WeaponShoot) {
encodeWeaponShoot(input, view, index)
index += 18
} else {
encodeTimePast(input, view, index)
index += 5
}
}
return view
} else {
let index = 0
const str = JSON.stringify(data)
const ta = strencode(str)
const ab = new ArrayBuffer(ta.length + 1)
const view = new DataView(ab)
view.setUint8(index++, name)
for (let i = 0; i < ta.length; i++) {
view.setUint8(index++, ta[i])
}
return view
}
}
const decodeActorMove = (view: DataView, index: number) => {
const id = view.getUint8(index++)
const directionX = toFixed(view.getFloat32(index))
index += 4
const directionY = toFixed(view.getFloat32(index))
index += 4
const dt = toFixed(view.getFloat32(index))
index += 4
const input = {
type: InputTypeEnum.ActorMove,
id,
direction: {
x: directionX,
y: directionY,
},
dt
}
return input
}
const decodeWeaponShoot = (view: DataView, index: number) => {
const owner = view.getUint8(index++)
const positionX = toFixed(view.getFloat32(index))
index += 4
const positionY = toFixed(view.getFloat32(index))
index += 4
const directionX = toFixed(view.getFloat32(index))
index += 4
const directionY = toFixed(view.getFloat32(index))
index += 4
const input = {
type: InputTypeEnum.WeaponShoot,
owner,
position: {
x: positionX,
y: positionY,
},
direction: {
x: directionX,
y: directionY,
},
}
return input
}
const decodeTimePast = (view: DataView, index: number) => {
const dt = toFixed(view.getFloat32(index))
index += 4
const input = {
type: InputTypeEnum.TimePast,
dt,
}
return input
}
export const binaryDecode = (buffer: ArrayBuffer) => {
let index = 0
const view = new DataView(buffer)
const name = view.getUint8(index++)
if (name === ApiMsgEnum.MsgClientSync) {
const frameId = view.getUint32(index)
index += 4
const inputType = view.getUint8(index++)
if (inputType === InputTypeEnum.ActorMove) {
const input = decodeActorMove(view, index)
return {
name,
data: {
frameId,
input
}
}
} else if (inputType === InputTypeEnum.WeaponShoot) {
const input = decodeWeaponShoot(view, index)
return {
name,
data: {
frameId,
input
}
}
} else {
const input = decodeTimePast(view, index)
return {
name,
data: {
frameId,
input
}
}
}
} else if (name === ApiMsgEnum.MsgServerSync) {
const lastFrameId = view.getUint32(index)
index += 4
const len = view.getUint8(index++)
const inputs = []
for (let i = 0; i < len; i++) {
const inputType = view.getUint8(index++)
if (inputType === InputTypeEnum.ActorMove) {
inputs.push(decodeActorMove(view, index))
index += 13
} else if (inputType === InputTypeEnum.WeaponShoot) {
inputs.push(decodeWeaponShoot(view, index))
index += 17
} else {
inputs.push(decodeTimePast(view, index))
index += 4
}
}
return {
name: ApiMsgEnum.MsgServerSync,
data: {
lastFrameId,
inputs
}
}
} else {
return {
name: name,
data: JSON.parse(strdecode(new Uint8Array(buffer.slice(1))))
}
}
}