import { ApiMsgEnum, InputTypeEnum } from "./Enum"; import { strdecode, strencode, toFixed } 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) { 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) const ta = strencode(str) const ab = new ArrayBuffer(ta.length + 1) const view = new DataView(ab) view.setUint8(index++, proto) 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 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 = 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 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 = toFixed(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)))) } } }