import { decode , encode } from "@shelacek/ubjson" ; export enum CommunicationType { HANDSHAKE = 1 , REPLAY = 2 , KEEP_ALIVE = 3 } export interface CommunicationMessage { type : CommunicationType ; payload : { cursor : Uint8Array ; clientToken : Uint8Array ; pos : Uint8Array ; nextPos : Uint8Array ; data : Uint8Array ; nick : string | null ; forcePos : boolean ; nintendontVersion : string | null ; } ; } export class ConsoleCommunication { private receiveBuf = Buffer . from ( [ ] ) ; private messages = new Array < CommunicationMessage > ( ) ; public receive ( data ) { this . receiveBuf = Buffer . concat ( [ this . receiveBuf , data ] ) ; while ( this . receiveBuf . length >= 4 ) { const msgSize = this . receiveBuf . readUInt32BE ( 0 ) ; if ( this . receiveBuf . length < msgSize + 4 ) { return ; } const ubjsonData = this . receiveBuf . slice ( 4 , msgSize + 4 ) ; this . messages . push ( decode ( ubjsonData ) ) ; this . receiveBuf = this . receiveBuf . slice ( msgSize + 4 ) ; } } public getReceiveBuffer ( ) { return this . receiveBuf ; } public getMessages ( ) { const toReturn = this . messages ; this . messages = [ ] ; return toReturn ; } public genHandshakeOut ( cursor , clientToken , isRealtime = false ) { const clientTokenBuf = Buffer . from ( [ 0 , 0 , 0 , 0 ] ) ; clientTokenBuf . writeUInt32BE ( clientToken , 0 ) ; const message = { type : CommunicationType . HANDSHAKE , payload : { cursor : cursor , clientToken : Uint8Array . from ( clientTokenBuf ) , isRealtime : isRealtime , } , } ; const buf = encode ( message , { optimizeArrays : true , } ) ; const msg = Buffer . concat ( [ Buffer . from ( [ 0 , 0 , 0 , 0 ] ) , Buffer . from ( buf ) ] ) ; msg . writeUInt32BE ( buf . byteLength , 0 ) ; return msg ; } }