Files
psn-js/src/encoder.ts
T

133 lines
4.0 KiB
TypeScript

import { Encoders, Tracker } from '.';
import { Constants } from './constants';
export class Encoder {
private systemName: string;
private versionHigh: number;
private versionLow: number;
dataFrameId: number = 1;
infoFrameId: number = 1;
constructor(systemName: string, versionHigh: number = 2, versionLow: number = 3) {
this.systemName = systemName;
this.versionHigh = versionHigh;
this.versionLow = versionLow;
}
setSystemName(systemName: string) {
this.systemName = systemName;
}
setVersionHigh(versionHigh: number) {
this.versionHigh = versionHigh;
}
setVersionLow(versionLow: number) {
this.versionLow = versionLow;
}
resetDataFrameId() {
this.dataFrameId = 1;
}
resetInfoFrameId() {
this.infoFrameId = 1;
}
getInfoPackets(timestamp: bigint, trackers: Tracker[], frameId?: number) {
if (frameId !== undefined) {
if (!Number.isInteger(frameId)) {
throw new Error('frame id must be an integer');
}
if (frameId > 255 || frameId < 0) {
throw new Error('frame id must be >= 0 and <= 255');
}
}
const systemNameChunk = Encoders.InfoSystemNameChunk(this.systemName);
const trackerChunks = trackers.map((tracker: Tracker) => tracker.getInfoChunk());
const infoPackets: Uint8Array[] = [];
const trackerChunksLists: Uint8Array[][] = [];
let currentTrackerList: Uint8Array[] = [];
let currentInfoPacketSize = Constants.PACKET_HEADER_SIZE + systemNameChunk.length + Constants.CHUNK_HEADER_SIZE;
trackerChunks.forEach((trackerChunk: Uint8Array) => {
if (currentInfoPacketSize + trackerChunk.length > Constants.MAX_UDP_PACKET_SIZE) {
trackerChunksLists.push(currentTrackerList);
currentTrackerList = [];
currentInfoPacketSize = 0;
}
currentTrackerList.push(trackerChunk);
currentInfoPacketSize += trackerChunk.length;
});
trackerChunksLists.push(currentTrackerList);
const header = Encoders.PacketHeaderChunk(
timestamp,
this.versionHigh,
this.versionLow,
frameId ? frameId : this.infoFrameId,
trackerChunksLists.length
);
trackerChunksLists.forEach((trackerChunkList) => {
infoPackets.push(
Encoders.InfoPacketChunk(header, systemNameChunk, Encoders.InfoTrackerListChunk(trackerChunkList))
);
});
this.infoFrameId += 1;
if (this.infoFrameId > 255) {
this.infoFrameId = 0;
}
return infoPackets;
}
getDataPackets(timestamp: bigint, trackers: Tracker[], frameId?: number) {
if (frameId !== undefined) {
if (!Number.isInteger(frameId)) {
throw new Error('frame id must be an integer');
}
if (frameId > 255 || frameId < 0) {
throw new Error('frame id must be >= 0 and <= 255');
}
}
const allTrackerChunks = trackers.map((tracker) => tracker.getDataChunk());
const dataPackets: Uint8Array[] = [];
const trackerChunksLists: Uint8Array[][] = [];
let currentTrackerList: Uint8Array[] = [];
let currentDataPacketSize = Constants.PACKET_HEADER_SIZE + Constants.CHUNK_HEADER_SIZE;
allTrackerChunks.forEach((trackerChunk) => {
if (currentDataPacketSize + trackerChunk.length > Constants.MAX_UDP_PACKET_SIZE) {
trackerChunksLists.push(currentTrackerList);
currentTrackerList = [];
currentDataPacketSize = 0;
}
currentTrackerList.push(trackerChunk);
currentDataPacketSize += trackerChunk.length;
});
trackerChunksLists.push(currentTrackerList);
const header = Encoders.PacketHeaderChunk(
timestamp,
this.versionHigh,
this.versionLow,
frameId ? frameId : this.dataFrameId,
trackerChunksLists.length
);
trackerChunksLists.forEach((trackerChunks) => {
dataPackets.push(Encoders.DataPacketChunk(header, Encoders.DataTrackerListChunk(trackerChunks)));
});
this.dataFrameId += 1;
if (this.dataFrameId > 255) {
this.dataFrameId = 0;
}
return dataPackets;
}
}