Mod API reference
The C API that T3SDK hands to every mod, as declared in t3sdk.h. This page is generated from that header's comments (API version 1). The optional C++ header unreal.hpp has the engine's memory layouts and fixed addresses for advanced use; they are specific to the supported game build.
How a mod uses these calls over the game's lifetime is in The mod lifecycle.
Overview
A mod is a 32-bit DLL in the game's System/mods/ folder that exports
T3SDK_EXPORT int T3SDK_CALL T3Mod_Init(const T3SdkApi* api); // 0 = loaded
T3SDK_EXPORT void T3SDK_CALL T3Mod_Shutdown(void); // optionalA packaged mod (a .t3mod the launcher installed; docs/mods.md) has a folder of its own there, named after its id, and System/mods/load-order.txt lists its DLL as "id/file.dll". The SDK loads the listed DLLs first, in that order, each with its own folder on the DLL search path, then the DLLs put straight into System/mods/, in name order. In T3SDK.log a mod goes by its folder name (a loose DLL by its file name).
T3Mod_Init runs before the game's own startup code, so the engine does not exist yet: register callbacks there and wait for api->EngineReady().
The API is plain C so a mod can use any compiler. The table only grows: a member added after version 1 is usable when api->size covers it.
Threading: frame callbacks run on the game's main thread, once per pass of its message loop, starting once EngineReady() first returns non-zero and stopping once the game begins exiting. Engine log callbacks run on whichever thread logged, from start-up onward (so possibly before EngineReady()); protect any state shared with a frame callback.
Objects: T3Object* pointers, and the object functions below, are only good while EngineReady() holds; the engine can free objects once the game starts exiting, when EngineReady() goes back to 0.
Memory: strings come back through caller buffers; nothing allocated on one side of the API is freed on the other.
T3SdkApi
T3Mod_Init receives a pointer to this table. Call through it: api->Log(...).
version, size
uint32_t version;
uint32_t size;version:T3SDK_API_VERSIONimplemented by the SDK.size:sizeof(T3SdkApi)in the SDK.
Log
void Log(const char* fmt, ...);Log: printf-style line inT3SDK.log, tagged with the calling mod's name.
Callbacks
Each returns 0 on success, -1 if callback is NULL. See Threading, above, for when each one runs.
int AddFrameCallback(T3FrameCallback callback, void* user);
int AddEngineLogCallback(T3LogCallback callback, void* user);Inline function hooks
Inline function hooks (MinHook: one table shared by every mod, so two mods cannot hook the same target). target is a code address in T3Main.exe; detour replaces it; original (may be NULL) receives a trampoline that calls the unhooked function. CreateHook leaves the hook disabled; call EnableHook to activate it. Each returns 0 (MH_OK) on success, another MH_STATUS otherwise (MinHook.h has the values, e.g. MH_ERROR_ALREADY_CREATED for a target another mod already hooked).
int CreateHook(void* target, void* detour, void** original);
int EnableHook(void* target);
int DisableHook(void* target);
int RemoveHook(void* target);Engine objects
Usable once EngineReady() returns non-zero (see Objects, above); ObjectCount/ObjectAt/FindObject return 0/NULL before that.
int EngineReady(void);
int ObjectCount(void);
T3Object* ObjectAt(int index);
T3Object* FindObject(const char* className, const char* pathName);
T3Object* ObjectClass(T3Object* object);
T3Object* ObjectOuter(T3Object* object);
int IsA(T3Object* object, T3Object* cls);
size_t ObjectName(T3Object* object, char* buf, size_t size);
size_t ObjectPathName(T3Object* object, char* buf, size_t size);
size_t NameToString(uint32_t name, char* buf, size_t size);ObjectCount: size of the object table, including free slots.ObjectAt:NULLfor a free slot or an out-of-range index.FindObject: Linear search by full path, e.g.FindObject("Class", "Engine.Actor").classNamemay beNULLto match any class.NULLif not found.ObjectClass:NULLfor aNULLobject.ObjectOuter: the object's Outer, orNULL.IsA: 1 if object's class isclsor derives from it.ObjectName: Text intobuf, NUL-terminated even when truncated; returns the full untruncated length, like snprintf (bufmay beNULLand size 0 to size a buffer first)."None"for aNULLobject.ObjectPathName: Dotted Outer chain, e.g."Engine.Actor";""for aNULLobject.NameToString:"<invalid name>"for an unknown value.
Types
T3Object
typedef t3::UObject T3Object; /* C++ */
typedef struct T3Object T3Object; /* C */Opaque handle to an engine UObject (see unreal.hpp for the real layout, C++ only): mods just carry pointers to it back into the calls below.
T3FrameCallback
typedef void(T3SDK_CALL* T3FrameCallback)(void* user);T3LogCallback
typedef void(T3SDK_CALL* T3LogCallback)(void* user, const char* text, const char* category);category is the engine's log category, e.g. "Log", "Init", "Warning".
T3ModInitFn
typedef int(T3SDK_CALL* T3ModInitFn)(const T3SdkApi* api);T3ModShutdownFn
typedef void(T3SDK_CALL* T3ModShutdownFn)(void);Macros
| Macro | Value | Meaning |
|---|---|---|
T3SDK_EXTERN_C | extern "C" (C++), empty (C) | so a C++ mod's exports keep their plain-C names |
T3SDK_EXPORT | T3SDK_EXTERN_C __declspec(dllexport) | use on a mod's T3Mod_Init/T3Mod_Shutdown |
T3SDK_CALL | __cdecl | calling convention for every function in this header |
T3SDK_API_VERSION | 1 | current version; see T3SdkApi::version/size below |