darpc.dll
This chapter describes the injected component’s responsibilities and lifecycle. Most tool authors can treat it as the client-side engine behind the Web API.
darpc.dll is a 32-bit x86 dynamic-link library injected into one compatible
game client. It provides the bridge between the client’s internal event system
and the daRPC named-pipe protocol.
IPC lifecycle
darpc_initialize validates the host identity and starts one IPC worker. The
worker binds \\.\pipe\da-rpc-{pid} before initialization reports success,
then waits for one local controller without touching the game thread. DllMain
does not start IPC or wait for the worker.
Each connection begins with the DLL’s Hello and must answer with a compatible
HelloAck. The worker serves bounded Ping, Echo, tick health, diagnostics, snapshot,
event-poll, and main-thread command operations.
It uses overlapped reads, writes, and accepts so darpc_shutdown can signal the
worker, cancel pending input/output, and join it before unloading. If bounded
shutdown cannot prove the worker stopped, shutdown fails and the loader leaves
the DLL loaded.
Malformed frames, invalid ordering, and broken connections end only that connection. The worker returns to listening for a replacement controller. The pipe is local-only, has one instance, and grants access to the process owner, Windows system, and administrators. A disconnected or absent controller does not affect the client process.
Event integration
The client dispatches decoded server events through a central handler. daRPC observes supported events after the client handles them, preserving the client’s original result and behavior.
Client event handlers also use a common function to queue outgoing network actions. Integrating at that boundary allows daRPC to initiate actions through the client’s own serialization and encryption path rather than implementing a second packet stack.
Native actions run through the client’s own methods on its main thread. This keeps local interface state and client timing in the normal path instead of trying to recreate an action with a packet alone.
State ownership
When attached to a running client, darpc.dll reconstructs a snapshot from
validated pointers, relative virtual addresses, and version-specific client
layouts. Capture is scheduled through the client tick hook and runs on the
client main thread. Bounded raw values are published to the pipe worker, which
owns text decoding, allocation, and serialization. See Game data
for the snapshot surface and concurrency model.
The DLL also observes the central decoded-event dispatcher after original handling. Bounded status, collection, effect, position, world-object, message, and audio values update retained state or enter a fixed 1 MiB queue as ordered events. A tick-time lifecycle check records login and disconnect transitions. For the initial map, map-size metadata and the authoritative position are joined regardless of arrival order. Later map-size metadata is staged until a new authoritative position completes the transition. A snapshot also retains that accepted position while the matching local player object is still becoming available. The pipe worker serves those updates through bounded long polls. It requests no allocation, logging, serialization, or IPC work from the hook path.
A separate observer watches the common outbound submission boundary after the client has processed an action. It copies only recognized bounded fields, preserves the original result, and records ordered ability, item, gold, equipment, pickup, emote, and turn events. The DLL tracks an active delayed spell so completion, server or client cancellation, and replacement by another spell remain distinct.
A complete snapshot records the latest event sequence already represented in its values. The queue rebases to that boundary, and overflow or an ordering gap causes the controller to request another complete snapshot. This keeps state ownership inside the DLL while avoiding an unbounded replay log.
This state tracking is independent of darpcd.exe. If the daemon stops, the DLL
continues to update its state and keeps its named-pipe server ready for a new
connection.
Diagnostic logging
The DLL writes one process-specific diagnostic log to
%USERPROFILE%\darpc\logs\pid-{pid}.log. It records lifecycle and connection
transitions, changed snapshot lifecycle or world state, warnings, and failures.
Repeated successful snapshots and successful or accepted commands remain silent.
Identical snapshot failures are recorded once until capture succeeds or the
failure reason changes.
Each log is limited to 1 MiB. After a complete record crosses that limit, the
file is rewritten before the next record and starts with a log_rotated marker.
This keeps the newest actionable records without allowing a long-running client
to grow one log indefinitely.
Command execution
The IPC worker validates command fields and submits pointer-free entries to a fixed 64-slot queue. It may wait up to the protocol’s bounded response window for a state transition, but it never executes client work. The existing tick hook removes at most one queue entry per tick and publishes accepted, executed, failed, cancelled, or timed-out status through atomics.
The diagnostic executor calls no client function and changes no game state.
Turn and walk executors resolve only the supported live world and call the
client’s confirmed direction, collision, reset, and pathfinding functions on
the main thread. Exact-tile walking checks current zero-based map bounds first;
a native builder that cannot reach a valid tile reports no_path. It uses the
ground route builder and never enables the client’s target pursuit or automatic
attack loop. The DLL retains a daRPC-requested destination until the native
route stops, then compares it with the latest accepted position for ordered
walking lifecycle events. Terminal results remain queryable for a bounded
period; new work may evict the oldest completed result rather than allowing
retained history to consume pending queue capacity.
The local self object keeps committed and staged tiles separate during a visual step. A replacement ground route uses the staged tile and remains queued until the native step-completion callback advances it. A direct step is rejected while that transition is active, before reset or prediction calls occur.
An exact-route walk instead validates a map-tagged sequence of at most 256
absolute tiles, appends the client’s native 12-byte route records in reverse
consumption order, and starts normal queued walking. The DLL observes native
route construction and queued-step results without changing native collision
or replanning. Before installation, it also rejects the route with
invalid_state when the packet-confirmed map or position differs from the
client’s native local self object. Only a rejected externally installed exact
route is reset.
Every queued command remains pointer-free.
Chant commands submit a bounded 0x0E message packet with spell-chant mode 2
through the confirmed client packet function. The packet carries one nonempty
length-prefixed ASCII string and preserves every supplied byte. NPC sell,
deposit, withdraw, and repair helpers format their phrases in the controller and
use this same executor.
Message commands submit bounded public or directed chat packets on the client
main thread. Say and shout use 0x0E modes 0 and 1; whisper uses 0x19
with length-prefixed recipient and content strings. Guild and group messages
use whisper recipients ! and !!. A say beginning with / is escaped while
passing through the local command interceptor so the server receives the
requested slash-prefixed text unchanged.
Assail commands submit the one-byte 0x13 basic-attack packet through that
same confirmed client packet function. Server responses remain responsible for
the observed player animation and sound events.
Skill use resolves the live lower-tray root, skill inventory, pointer table, and one-based entry on the main thread, then calls the client’s normal skill activation routine. These pane objects exist independently of the visible tab; daRPC does not select the skill page, synthesize input, or disturb focus. A missing or changed entry fails closed. The native routine retains its ordinary action-delay checks and configured skill-text behavior.
Spell casting resolves the equivalent live spell entry and checks its expected argument type, action delay, denial state, object or map target, and bounded text before calling the matching native routine. It supports no-argument, object-target, tile-target, and text-input spells without selecting the spell page or synthesizing input. A new cast is allowed to replace a delayed cast in progress; ordered outbound observations identify the interrupted and new spells separately.
Item use resolves the live inventory pane and calls its ordinary activation routine. Item and gold transfers, pickup, equipment removal, and emotes build their small confirmed opcode-first request bodies and submit them through the client’s normal plaintext network boundary on the main thread. Tile actions check the current map bounds. Item actions revalidate the live slot, retained slot number, stackability, and quantity immediately before submission.
Operational boundaries
Hook timing is compiled into the production DLL but disabled by default. When enabled, the tick detour times the complete daRPC observation and its movement, command, player, state, and snapshot stages. The incoming event detour also times packet parsing and state updates as one event stage. The hot paths only read or update atomics and the monotonic clock. They do not allocate or format logs for diagnostics, perform IPC, or block. The IPC worker creates query responses and resets counters.
The tick budget is 10,000 microseconds; each child stage budget is 5,000 microseconds. Budget crossings increment a counter rather than writing from the hook. Runtime reset can race with one in-flight observation, so a queried snapshot is diagnostic telemetry rather than a transactional accounting record.
- Client layouts and addresses are version-specific.
- Hooks must not be installed until the executable version and required invariants have been validated.
- Hook paths must avoid unbounded work, blocking IPC, and daemon-owned lifetimes.
- Initialization and cleanup must not perform substantial work under the Windows loader lock.
- Failures must be contained at foreign function and hook boundaries without unwinding into the client.