v0.1.0

released

This was the first publicly acknowledged release of tera-proxy. Before then, most things had been kept under the radar, but with things suddenly getting noticed, it was time to start getting serious.

Below is a copy of a page from the tera-proxy wiki titled “Upgrading to 1.0.0”. Let’s pretend it wasn’t actually 1.0.0 because I keep adding breaking changes and I don’t want to bump to v2 already. Dear semver, I’m sorry. Let’s start with a clean slate and call it “0.1.0”.


Both tera-data and tera-proxy-game have undergone a number of potentially breaking changes. Commit logs for each can be seen here:

For normal users this will mean completely updating tera-proxy-game and tera-data as well as installing tera-data-parser. It is probably most convenient to just get a new copy of the whole thing and transferring old proxy modules over. One will be provided once Valkyrie lands on NA.

For module developers, most things will be backwards compatible except for two specific cases:

  • implicit raw hooks on * (see: logger)
  • explicit pre hooks. I don’t think anyone ever used these but the old type parameter in Dispatch#hook() is now a version parameter.

Details are below.

tera-data(-parser-js)

Separation of Code and Data

tera-data now only houses mappings and protocol definitions. The Node.js parser was moved to meishuu/tera-data-parser-js which will be renamed tera-data-parser when installed via npm.

Both tera-data-parser-js and tera-proxy-game have a peer dependency on tera-data, so you must install all three together for things to work nicely.

Original Identifiers

Before, tera-data converted names to use lowerCamelCase. This has been dropped in favor of using the original names. For module developers, this is backwards compatible as tera-proxy-game’s Dispatch performs transformations to ensure the old style still works. However, the methods exposed by tera-data-parser-js’s Protocol do not perform those transformations.

Versioning

All definitions now include a version number before the .def extension. Instead of changing existing versions of a definition, contributors must instead commit the updated definition as a new file with the version number incremented. For more information, check the updated README.

Extras

  • Tests, linting, and CI/coverage tools have been added to the parser. Tests are still being written, but eventually this should mean no more silly regressions. It is strongly recommended to install with NODE_ENV=production or --only=production if you don’t need these, which you probably don’t.

  • Protocol is now implemented as a class, and the exported protocol is an instance of it. You can create another instance by calling protocol.createInstance([args...]). This will be handy for anyone needing to support multiple protocol versions.

  • Protocol now lazy loads data files, which means the map and messages maps may be empty if they are accessed before any call to load, parse, write, (or resolveIdentifier). By default, it will load from require.resolve('tera-data') and this is likely what you’ll want to pass to load() as well.

  • All types (including int64s) now have default values for writing (0, or empty array, or empty string).

  • Anything using the exported sysmsg must perform its own conversions because these were updated to the new name case system. Also it’s very ugly and untested and will probably catch up to protocol eventually, but not now.

tera-proxy-game

Versioning

See above. With the advent of versioning, Dispatch#hook() as well as the toClient() and toServer() methods now expect the second parameter to be the version number. If it is not a numeric value, it may be '*' to use the latest version (not recommended) or 'raw' to use a raw hook which performs no parsing. If no version info is supplied, it will emit warnings to the console unless the environment variable NO_WARN_IMPLIED_VERSION is nonempty.

Currently not implemented but hopefully very soon will be deprecation warnings if the requested version is not the latest. You will likely also be able to disable the warnings through an environment variable.

Hook Options

The parameters for Dispatch#hook() are now identifier[, version][, options], callback. options is an object with the following optional properties:

  • order: A lower number causes this hook to run before hooks with a higher order. This defaults to 0, so you can imagine negative values running closer to the source side and positive values running closer to the destination side. This is helpful for modules that way want to examine packets before another module modifies or silences them, or filter to what the receiving side will see by running later than most other hooks.

  • type: One of 'real' (default), 'fake', or 'all'. Packets created and sent through Dispatch are now first routed back through the handler, so now you can, for instance, examine only “fake” (generated) packets by making a hook with type: 'fake'. Just be extra sure that any packets generated in a fake/all hook do not generate more in an infinite loop.

These are pretty untested right now so don’t expect these options to be perfect, but they’re there for anyone who might need them.

Extras

  • All hook callbacks are now passed an extra parameter at the end, fake, to identify if the packet was generated by the proxy.

  • Before, Dispatch would dump a full stacktrace upon encountering a warning or error. This was pretty unwieldy to look at, so now it trims native node callsites as well as tera-proxy-game callsites unless deemed necessary.

  • Dispatch#unhook() is currently untested, but before it accepted a callback. Now, it expects the hook object returned from calling Dispatch#hook().

  • Dispatch#handle() used to take the opcode as the first argument. This was redundant because it was always being retrieved from the second argument (the data buffer) anyway, so it was removed and the new parameter list is data, fromServer[, fake].

  • There were a number of changes to how things were being implemented. Thus, performance may have changed. At the end of the day, there probably isn’t nearly enough processing at all for any extra overhead to matter, but it’s worth pointing out just in case of the off chance that there’s something really inefficient about what we’re doing now.

Updated: