npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

packet-transformer

v1.0.0

Published

Transform basic packet classes containing fields into more advanced packet classes with read/write capabilities. Simplifies the process of making and modifying packets.

Downloads

3

Readme

packet-transformer

Version Downloads License

packet-transformer is a package for transforming basic data structures to have read/write capabilities.

This package was created for working with packets in the game Brawlhalla.

It can be adapted for any game or system and is incredibly useful for defining file formats as data structures.

Installation

You can install packet-transformer through the command line using npm or yarn.

npm install packet-transformer

Setup

This project requires ttypescript to work. This can be installed as a drop-in replacement for typescript, replacing tsc with ttsc. Check their repo for more information.

Once ttsc is installed, add the plugin to your tsconfig.json:

{
  ...
  "compilerOptions": {
    ...
    "plugins": [
      {
        "transform": "./node_modules/packet-transformer/dist/index.js",
        "type": "raw"
      }
    ],
  },
}

Usage

Once properly setup you can import types and Packet from packet-transformer and create your own packets.

Below is an example packet; HelloPacket.

import {
  cint3,
  cuint,
  cuint3,
  Packet,
  uint16,
  uint32,
  vector,
} from "packet-transformer";

export class HelloPacket extends Packet {
  email: string = ""; // The value here is a default for if read is never called.
  pwHash: string = ""; // A method read() will be generated that reads all this data from a buffer.
  username: string = "";

  ticket: vector<byte, cuint> = [];

  userId: string = "";
  platform: byte = -1;
}

This class we be transformed at build time to contain two methods:

  • HelloPacket.read(buffer): HelloPacket

    <static> read a packet from a buffer, a custom buffer implementation is needed which supports the following functions:

    • readBits
    • readByte
    • readBytes
    • readUInt16
    • readUInt32
    • readInt16
    • readInt32
    • readCompressedUInt
    • readCompressedInt
    • read3bitCompressedUInt
    • read3bitCompressedInt
    • readUTFString
    • readBoolean
    • readFloat
  • packet.write(buffer): void

    write a packet to a buffer, a custom buffer implementation is needed which supports the following functions:

    • writeBits
    • writeByte
    • writeBytes
    • writeUInt16
    • writeUInt32
    • writeInt16
    • writeInt32
    • writeCompressedUInt
    • writeCompressedInt
    • write3bitCompressedUInt
    • write3bitCompressedInt
    • writeUTFString
    • writeBoolean
    • writeFloat

Documentation

Types

The following details what types are available and what method it corresponds to, as well as some example transformations.

Please note in all examples the read method is there as an example. Please omit this when writing code.

It supports some primitive types as well as some custom types.

Primitives

This package supports reading two primitive types; string, and boolean.

export class TestPacket extends Packet {
  attr: string = "";
  attr2: boolean = false;

  // Roughly gets compiled to
  static read(buffer) {
    this.attr = buffer.readUTFString();
    this.attr2 = buffer.readBoolean();
  }
}

type byte

Read as a single byte. Internally represented by a number.

export class TestPacket extends Packet {
  attr: byte = -1;

  // Roughly gets compiled to
  static read(buffer) {
    this.attr = buffer.readByte();
  }
}

type int16 && type uint16

Read as a 2 byte int (signed or unsigned respectively). Internally represented by a number.

export class TestPacket extends Packet {
  attr: int16 = -1;
  attr2: uint16 = -1;

  // Roughly gets compiled to
  static read(buffer) {
    this.attr = buffer.readInt16();
    this.attr2 = buffer.readUInt16();
  }
}

type int32 && type uint32

Read as a 4 byte int (signed or unsigned respectively). Internally represented by a number.

export class TestPacket extends Packet {
  attr: int32 = -1;
  attr2: uint32 = -1;

  // Roughly gets compiled to
  static read(buffer) {
    this.attr = buffer.readInt32();
    this.attr2 = buffer.readUInt32();
  }
}

type float

Read as a 4 byte floating point number. Represented internally as a number.

export class TestPacket extends Packet {
  attr: float = -1;

  // Roughly gets compiled to
  static read(buffer) {
    this.attr = buffer.readFloat();
  }
}

type cint && type cuint

'Compressed' int (the name just stuck).
4 bits representing size followed by the actual data:

let size = this.readBits(4);
size = (size + 1) << 1;
return this.readBits(size);
export class TestPacket extends Packet {
  attr: cint = -1;
  attr2: cuint = -1;

  // Roughly gets compiled to
  static read(buffer) {
    this.attr = buffer.readCompressedInt();
    this.attr2 = buffer.readCompressedUInt();
  }
}

type cint3 && type cuint3

'Compressed' 3bit size int.
Same as cint but with 3 bits for size instead of 4.

export class TestPacket extends Packet {
  attr: cint3 = -1;
  attr2: cuint3 = -1;

  // Roughly gets compiled to
  static read(buffer) {
    this.attr = buffer.read3bitCompressedInt();
    this.attr2 = buffer.read3bitCompressedUInt();
  }
}

type nbits<type>

Read a specific number of bits, must be a constant. Internally represented by a number.

export class TestPacket extends Packet {
  attr: nbits<4> = -1;

  // Roughly gets compiled to
  static read(buffer) {
    this.attr = buffer.readBits(4);
  }
}

type vector<type, lengthType>

Read a list of one type.
LengthType can be a constant, another type or a string constant which references an attribute of the packet.
Vector types can be nested.

export class TestPacket extends Packet {
  attr: vector<int32, 4> = [];
  attrNested: vector<vector<int32, 4>, 4> = [];
  attrLength: vector<int32, uint16> = [];

  lengthField: uint16 = -1;
  attrField: vector<int32, "lengthField"> = [];

  // Roughly gets compiled to
  static read(buffer) {
    // Read 4 int32s
    var vectorValues = [];
    for (var i = 0; i < 4; i++) {
      vectorValues[i] = buffer.readInt32();
    }
    this.attr = vectorValues;

    // Nested too long to show

    // Length as uint16
    var vectorValues2 = [];
    var vectorLength2 = buffer.readUInt16();
    for (var i = 0; i < vectorLength2; i++) {
      vectorValues2[i] = buffer.readInt32();
    }
    this.attrLength = vectorValues2;

    this.lengthField = buffer.readUInt16();

    // Length is lengthField
    var vectorValues3 = [];
    for (var i = 0; i < this.lengthField; i++) {
      vectorValues3[i] = buffer.readInt32();
    }
    this.attrField = vectorValues3;
  }
}

type custom<type>

Use another data structure as a type. Represented by the class it's reading.

export class SubTestPacket extends DataStructure {
  otherField: uint32 = -1;

  // Roughly compiled to
  static read(buffer) {
    this.otherField = buffer.readUInt32();
  }
}

export class TestPacket extends Packet {
  field: uint32 = -1;

  subData: custom<SubTestPacket> = new SubTestPacket();

  // Roughly compiled to
  static read(buffer) {
    this.field = buffer.readUInt32();

    this.subData = SubTestPacket.read(buffer);
  }
}

Contributing

Interested in contributing to packet-transformer?

Contributions are welcome, and are accepted via pull requests. Please review these guidelines before submitting any pull requests.

Help

Installing dependencies:

npm install

Compile:

npm run build

Tests

Due to its nature this project does not have any automated testing.

A test project can be found in example/ and built using

npm run test

License

All code in this repository is licensed under GPL-3.0.