packages/net/src/writer.js

/**
 * Writes packets in little endian format
 * @class
 * @memberof module:@perion/net
 */
 class Writer {
  /**
   * @constructor
   * @param {number} length The length of the packet in bytes
   */
  constructor(length = 32) {
    this.data = Buffer.alloc(length);
    this.bytesWritten = 0;
  }
  /**
   * Used to allocated more bytes to the Buffer dynamically
   * @param {number} byteSize Total byte length required
   */
  dynamicAlloc(byteSize) {
    const bytesAvailable = this.data.length - this.bytesWritten;
    if (bytesAvailable < byteSize) {
      const bytesNeeded = byteSize - bytesAvailable;
      this.data = Buffer.alloc(this.data.length + bytesNeeded, this.data);
    }
  }
  /**
   * Writes a byte
   * @param {number} byte The byte to write
   * @return {Writer} A reference to the current Writer
   */
  byte(byte) {
    this.dynamicAlloc(1);
    this.data.writeIntLE(byte, this.bytesWritten, 1);
    this.bytesWritten += 1;
    return this;
  }
  /**
   * Writes an unsigned byte
   * @param {number} uByte An unsigned byte
   * @return {Writer} A reference to the current Writer
   */
  ubyte(uByte) {
    this.dynamicAlloc(1);
    this.data.writeUIntLE(uByte, this.bytesWritten, 1);
    this.bytesWritten += 1;
    return this;
  }
  /**
   * Writes a short
   * @param {number} short A short
   * @return {Writer} A reference to the current Writer
   */
  short(short) {
    this.dynamicAlloc(2);
    this.data.writeInt16LE(short, this.bytesWritten);
    this.bytesWritten += 2;
    return this;
  }
  /**
   * Writes an unsigned short
   * @param {number} uShort An unsigned short
   * @return {Writer} A reference to the current Writer
   */
  ushort(uShort) {
    /* Lol u short */
    this.dynamicAlloc(2);
    this.data.writeUInt16LE(uShort, this.bytesWritten);
    this.bytesWritten += 2;
    return this;
  }
  /**
   * Writes an integer
   * @param {number} int An integer
   * @return {Writer} A reference to the current Writer
   */
  int(int) {
    this.dynamicAlloc(4);
    this.data.writeInt32LE(int, this.bytesWritten);
    this.bytesWritten += 4;
    return this;
  }
  /**
   * Writes an unsigned integer
   * @param {number} uInt An unsigned integer
   * @return {Writer} A reference to the current Writer
   */
  uint(uInt) {
    this.dynamicAlloc(4);
    this.data.writeUInt32LE(uInt, this.bytesWritten);
    this.bytesWritten += 4;
    return this;
  }
  /**
   * Writes a long
   * @param {bigint} long A long
   * @return {Writer} A reference to the current Writer
   */
  long(long) {
    this.dynamicAlloc(8);
    this.data.writeBigInt64LE(long, this.bytesWritten);
    this.bytesWritten += 8;
    return this;
  }
  /**
   * Writes an unsigned long
   * @param {bigint} uLong An unsigned long
   * @return {Writer} A reference to the current Writer
   */
  ulong(uLong) {
    this.dynamicAlloc(8);
    this.data.writeBigUInt64LE(uLong, this.bytesWritten);
    this.bytesWritten += 8;
    return this;
  }
  /**
   * Writes a Buffer
   * @param {Buffer} buf A buffer
   * @return {Writer} A reference to the current Writer
   */
  write(buf) {
    for (const byte of buf) this.byte(byte);
    return this;
  }
  /**
   * Writes an ASCII string
   * @param {string} str A string
   * @return {Writer} A reference to the current Writer
   */
  ascii(str) {
    this.write(Buffer.from(str, 'utf-8'));
    return this;
  }
  /**
   * Writes a null-terminated ASCII string
   * @param {string} str A string
   * @return {Writer} A reference to the current Writer
   */
  nullascii(str) {
    this.ascii(str);
    this.byte(0);
    return this;
  }
  /**
   * Writes a MapleStory ASCII string
   * @param {string} str A string
   * @return {Writer} A reference to the current Writer
   */
  mapleascii(str) {
    this.short(str.length);
    this.ascii(str);
    return this;
  }
  /**
   * Writes a position
   * @param {Point} pos A position {x, y}
   * @return {Writer} A reference to the current Writer
   */
  pos(pos) {
    this.short(pos.x);
    this.short(pos.y);
    return this;
  }
  /**
   * Writes a boolean value
   * @param {boolean} bool A boolean
   * @return {Writer} A reference to the current Writer
   */
  bool(bool) {
    this.byte(bool ? 1 : 0);
    return this;
  }
  /**
   * Returns the packet Buffer
   * @return {Buffer} The output Buffer
   */
  buffer() {
    return this.data;
  }
}
module.exports = Writer;