Files
psn-js/src/encoder.ts
T
Joel Wetzell 68db557090 linting
2026-07-13 14:15:47 -05:00

158 lines
3.8 KiB
TypeScript

import { Constants } from './constants.js';
import { Encoders, type Tracker } from './index.js';
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;
}
}