Skip to main content

Interposer 1.0.5 Release Notes

Downloads

Loading release downloads…

What's Changed

Rich Presence

Rich presence lets games display detailed status information in Discord — showing the current game, activity details, images, party info, and clickable buttons — all configured through Config.yml with no code changes to the game itself.

The implementation communicates directly with the Discord client over local named pipes (\\.\pipe\discord-ipc-N) using length-prefixed JSON frames. There are no external SDK dependencies — the entire IPC protocol (handshake, SET_ACTIVITY, close) is handled internally.

Configuration

Add a RichPresence section to .interposer\Config.yml:

RichPresence:
Discord:
Enabled: true
ApplicationId: "123456789012345678"
Name: "My Game"
Details: "In Menu"
State: "Idle"
LargeImage: "logo"
LargeImageText: "My Game v1.0"

You'll need a Discord Application ID from the Discord Developer Portal — no bot token is required. All default activity fields (Type, Name, Details, State, images, buttons) are optional and define the presence shown immediately when the game starts. See the Rich Presence documentation page for the full configuration reference.

Behavior

  • Rich presence is initialized after all hooks are installed and enabled, so it doesn't interfere with the hook setup sequence.
  • If Discord is not running, a [RICH PRESENCE] log entry is written and the game continues normally — presence never blocks startup.
  • If Discord restarts while the game is running, the next presence update from a plugin will automatically reconnect.
  • On DLL detach, presence is cleared and the pipe is closed gracefully.

Backend Architecture

The system is built around an abstract IRichPresenceBackend interface (Connect, Disconnect, IsConnected, UpdatePresence, ClearPresence). Discord is the first backend, but the interface is designed so that additional presence services (e.g. a LANCommander-native presence system) can be added in the future. All backends receive the same PresenceData — plugins don't need to know which backends are active.

Rich Presence Plugin API

Plugins can update presence at runtime to show dynamic information like the current map, score, or match progress. The API exposes 11 C-callable functions resolved via GetProcAddress:

FunctionDescription
InterposerSetPresenceDetailsSet the first detail line
InterposerSetPresenceStateSet the second detail line
InterposerSetPresenceTimestampsSet start/end epoch timestamps
InterposerSetPresenceLargeImageSet large image key and tooltip
InterposerSetPresenceSmallImageSet small image key and tooltip
InterposerSetPresencePartySet party ID, current size, and max
InterposerSetPresenceButtonSet button text and URL (index 0 or 1)
InterposerSetPresenceTypeSet activity type (Playing, Streaming, etc.)
InterposerSetPresenceNameSet the display name
InterposerUpdatePresencePush accumulated changes to all backends
InterposerClearPresenceReset to config defaults and clear all backends

The pattern is: call one or more setters to stage changes, then call InterposerUpdatePresence to push them. All functions are thread-safe (guarded by a mutex). InterposerClearPresence resets to the default values from Config.yml rather than blanking everything.

See the Rich Presence Plugin API documentation for the full reference, including C/C++ type definitions and usage examples.

Plugin Init Entry Point

Plugins no longer need to guess the Interposer's DLL name (which varies between LANCommander.Interposer.dll, version.dll, dinput8.dll, and .asi depending on the deployment variant). Instead, the Interposer calls an optional exported function on each plugin immediately after loading it:

extern "C" __declspec(dllexport) void WINAPI InterposerPluginInit(HMODULE hInterposer);

The Interposer passes its own HMODULE, which the plugin uses for all GetProcAddress calls. This eliminates the name-guessing problem entirely and is now the recommended way to initialize a plugin. The old DllMain + GetModuleHandle approach still works for backwards compatibility.

See the updated Creating a Plugin guide for the full pattern.

Plugin Config Registration

Plugins can now declare their default configuration at init time. The new InterposerRegisterPluginConfig export accepts a plugin name and a YAML string of default key-value pairs:

using FnRegConfig = BOOL (WINAPI*)(const wchar_t* pluginName, const wchar_t* yamlDefaults);
auto pfnRegConfig = (FnRegConfig)GetProcAddress(hInterposer, "InterposerRegisterPluginConfig");

pfnRegConfig(L"MyPlugin", L"Setting: 'default'\nCount: 42");

On first run, the defaults are merged into the in-memory config and appended to Config.yml under Plugins.<name>. On subsequent runs, the user's existing configuration is preserved — registration is a no-op if the section already exists.

This means plugin authors no longer need to document "add these lines to Config.yml" — the plugin populates its own defaults automatically, and users only need to edit the values they want to change.

See the updated Creating a Plugin guide and the Plugin API reference for details.

Expanded Logging

Four new logging categories have been added:

KeyDefaultDescription
PluginsfalseLog plugin load, unload, error, and config registration events.
IdentityfalseLog identity override operations — when GetUserNameW/A or GetComputerNameW/A hooks return the configured override value.
RichPresencefalseLog rich presence field changes, update pushes, and clear operations.
DnsRedirectstrueLog DNS redirect matches. Enabled by default because DNS redirects are deliberate user-configured actions. Has its own toggle separate from Network.

Previously, plugin load/error events were gated behind Logging.Files, which was misleading — they now have their own dedicated Logging.Plugins toggle. DNS redirect logging was previously gated behind Logging.Network and now has its own dedicated flag.

See the updated Logging documentation for the full verb reference.

Example Plugin

A new LANCommander.Interposer.Plugin.Example project is included in the solution as a minimal, well-commented reference for plugin authors. It demonstrates:

  • The InterposerPluginInit entry point pattern
  • Resolving API exports from the provided HMODULE
  • Registering default config with InterposerRegisterPluginConfig
  • Reading config values and logging

The example project includes a ready-to-build .vcxproj and can be used as a starting point for new plugins.