Purpose
tera-network-proxy forwards TCP traffic between a TERA client and game server, allowing packets to be read, modified, blocked and generated. Ordinary module authors use mod.hook and mod.send. The classes below are for integrating the networking layer itself.
Packet pipeline
Server → TCP → decryption → complete packet assembly → Dispatch
↓ hooks
Client ← TCP ← encryption ← processed packet ←────────────┘
The reverse stream goes from RealClient through decryption and buffering to Dispatch.handle(data, false), then to the server. TCP is a byte stream: one socket data event need not equal one game packet. PacketBuffer assembles complete messages using the header length. The handshake and key exchange precede ordinary packet processing; modules see decrypted messages.
Each connection has its own Dispatch, opcode map, protocol definitions and encryption state. Slow synchronous handlers delay further traffic processing in the event loop. Avoid long computations and file I/O inside them.
Dispatch
Dispatch merges packet-specific and '*' hooks by order, checks filters and parses the message using the required definition version. Modifications invalidate cached parsed events. handle returns false if the packet remains silenced, or the resulting Buffer otherwise.
| Current implementation API | Purpose |
|---|---|
hook(moduleName, name, version, options, callback) |
Low-level registration with an explicit module name |
unhook(handle), unhookModule(name) |
Remove a hook or module hooks |
write(outgoing, buffer) |
Send a complete packet |
write(outgoing, name, version, data) |
Serialize and send an object |
handle(data, incoming, fake = false) |
Run the hook chain |
fromRaw(name, version, data) |
Parse a Buffer using a definition |
toRaw(name, version, data) |
Serialize an object |
resolve(name, version = '*') |
Resolve a definition |
destructor() |
Clear hooks |
For write, outgoing: true means server; for handle, incoming: true means client. Generated packets also pass through handle, with fake: true. Raw sending copies the buffer because encryption changes bytes in place.
Connection
const { Connection, RealClient, FakeClient } = require('tera-network-proxy');
The current signature is new Connection(metadata, clientInterfaceConnection, noIntegrity = false). metadata needs consistent client information: protocolVersion, majorPatchVersion, minorPatchVersion, platform, maps.protocol, maps.sysmsg and dataFolder. Toolbox normally supplies these. This is not a standalone connection example: arbitrary empty metadata cannot initialize a working protocol.
connection.connect(client, options) forwards options to net.connect and returns the server socket. It enables setNoDelay(true) on that socket. connection.dispatch exposes packet dispatching. close() closes both sides, destroys Dispatch and releases connection state. Infrastructure handles encryption and packet integrity according to the client version.
RealClient
new RealClient(connection, socket) attaches an actual game TCP client. It has its own buffer and traffic processing state toward the server. Use socket.setNoDelay(true) on the accepted socket, as Toolbox integration does. Connection manages this client; ordinary modules do not need to create one.
FakeClient
new FakeClient(connection, keys) represents a connection without an incoming game client socket. Optional keys is an array of two 128-byte buffers; omitted keys are randomly generated. The class extends EventEmitter.
| Event | Meaning |
|---|---|
connect |
Initial handshake and key exchange completed |
timeout |
Forwarded server socket event |
error |
Forwarded server socket error |
close |
FakeClient is closing |
FakeClient does not implement account login or game logic. A successful TCP/cryptographic connection does not mean the game has authenticated the client.
Differences from the historical README
The shipped README describes an older TERA Proxy API. In this distribution, module management lives in bin/mod-manager.js/bin/mod.js: Dispatch has no documented legacy load() or reset(). The example calling new Connection() without metadata is also outdated. Use exact names such as S_LOGIN instead of relying on the historical sLogin conversion. Raw hooks receive a copy: return the modified Buffer.
Sources: node_modules/tera-network-proxy/README.md, lib/connection/{index,dispatch}.js, lib/clients/{RealClient,FakeClient}.js, lib/packetBuffer.js.