import Color from 'color' import { decrypt, encrypt } from 'romulus-js' import { DEFAULT_KEY, MessageTypes } from '../common' import { numberToUint16BE } from '../utilities/number' import { SmartBuffer } from '../utilities/smart-buffer' import { packOutgoingPacket } from './packet' const MESSAGE_TYPE = numberToUint16BE(MessageTypes.UserDataRequest) export interface UserDataRequestMessage { username: string colour: Color clientId: string } /** * Create an outgoing user data request (0x0002) packet. * @param properties The properties for the message. * @param key The key to encrypt the data with. * @returns An outgoing user data request (0x0002) packet. */ export function packUserDataRequestMessage (properties: UserDataRequestMessage, key: Uint8Array = DEFAULT_KEY): Uint8Array { const encoder = new TextEncoder() // Prepare data in correct format. const username = encoder.encode(properties.username) const usernameLength = numberToUint16BE(username.length) const colour = new Uint8Array(properties.colour.array()) const clientId = encoder.encode(properties.clientId) const clientIdLength = numberToUint16BE(clientId.length) // Pack data. const packedData = new SmartBuffer() packedData.writeBytes(usernameLength) packedData.writeBytes(username) packedData.writeBytes(colour) packedData.writeBytes(clientIdLength) packedData.writeBytes(clientId) // Encrypt the data. const data = encrypt(packedData.data, MESSAGE_TYPE, key) return packOutgoingPacket({ messageType: MESSAGE_TYPE, data: data }) } /** * Unpack the decrypted data section of an incoming user data request (0x0002) message. * @param data The decrypted data section of an incoming user data request (0x0002) message. * @returns An unpacked user data request (0x0002) message. */ export function unpackUserDataRequestMessage (data: Uint8Array): UserDataRequestMessage { // Unpack and read data in correct format. const packedData = SmartBuffer.from(data) const usernameLength = packedData.readUInt16() const username = packedData.readBytes(usernameLength) const colour = packedData.readBytes(3) const clientIdLength = packedData.readUInt16() const clientId = packedData.readBytes(clientIdLength) const decoder = new TextDecoder() // Return data in correct format. return { username: decoder.decode(username), colour: Color.rgb(colour), clientId: decoder.decode(clientId), } }