HookDOTS API

版本 v1.1.1·更新於 2025-10-22

Provides an API for mods to hook Unity DOTS systems.

模組介紹 作者原文

HookDOTS API

HookDOTS is a modding library for hooking Unity DOTS games. By itself, it doesn't do anything.

Why use HookDOTS?

Harmony is an excellent tool, but it fails at one important thing: Hooking unmanaged systems in IL2CPP builds.\

HookDOTS was created to solve this problem.

Notable attributes provided (for plugin developers):

  • [EcsSystemUpdatePrefix(typeof(EquipItemSystem))]
  • [EcsSystemUpdatePostfix(typeof(EquipItemSystem))]
  • [WhenCreatedWorldsContainAny("Server", "Client_0")]

Installation

  • Install BepInEx
  • Extract HookDOTS.API.dll into (VRising folder)/BepInEx/plugins

Usage

For Server Operators

By itself, HookDOTS doesn't do anything. It is required by other plugins and should be kept up to date.

For Plugin Developers

How to use

  • Add a reference to the plugin.

dotnet add package HookDOTS.API -v 1.*

  • Add the API plugin as a dependency via the BepInDependency attribute on your plugin class.

[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]

[BepInDependency("HookDOTS.API")]

public class ExamplePlugin: BasePlugin

  • Register hooks in your plugin's Load method.

public override void Load()

{

//... other initialization code

// Register your plugin's hooks with HookDOTS

_hookDOTS = new HookDOTS.API.HookDOTS(MyPluginInfo.PLUGIN_GUID, Log);

_hookDOTS.RegisterAnnotatedHooks();

}

  • Teardown in your plugin's Unload method.

public override bool Unload()

{

//... other unloading code

_hookDOTS.Dispose();

return true;

}

  • Set up prefix and postifx hooks for System OnUpdate calls. Both managed and unmanaged systems can be hooked.

public class ExamplePatch

{

// The hook must be public and static.

// If you want SystemState* passed in, an unsafe context is also required.

[EcsSystemUpdatePrefix(typeof(EquipItemSystem))]

unsafe public static bool ExamplePrefix(SystemState* systemState)

{

var world = systemState->World;

ExamplePlugin.LogInstance.LogInfo($"ExamplePrefix executing in world {world.Name}.");

// You can return false, to skip the hooked OnUpdate. Other prefix hooks will still run.

bool shouldSkipTheOriginal = true;

return!shouldSkipTheOriginal; // this will be returned, and is false. Therefore the original will be skipped.

}

[EcsSystemUpdatePrefix(typeof(EquipItemSystem))]

unsafe public static bool ExamplePrefixNoSkip(SystemState* systemState)

{

// Prefer to use the AfterDetours constants instead of true/false.

// return AfterDetours.SkipOriginalMethod;

return AfterDetours.OkToRunOriginalMethod;

}

[EcsSystemUpdatePostfix(typeof(EquipItemSystem))]

unsafe public static void ExamplePostfix(SystemState* systemState)

{

var world = systemState->World;

ExamplePlugin.LogInstance.LogInfo($"ExamplePostfix executing in world {world.Name}.");

// Unlike a prefix hook, a postfix hook cannot return false to skip anything.

// The only valid return type is void.

}

}

onlyWhenSystemRuns

You can set onlyWhenSystemRuns to false, and the hook will be called even if the system doesn't actually run.

[EcsSystemUpdatePrefix(typeof(EquipItemSystem), onlyWhenSystemRuns: false)]

public static void ExamplePrefix2()

{

// (this is commented out, because the log would be spammed every frame)

// ExamplePlugin.LogInstance.LogInfo($"ExamplePrefix2 executing");

}

Throttling

If you're using hooks to dump information and don't want to be flooded every frame, the Throttle attribute can be used.

// You can specify days, hours, minutes, seconds, and milliseconds to define the throttle interval.

// Internally, these are used to create a System.TimeSpan

[Throttle(seconds: 10)]

[EcsSystemUpdatePrefix(typeof(EquipItemSystem), onlyWhenSystemRuns: false)]

public static void ExamplePrefixThrottled()

{

ExamplePlugin.LogInstance.LogInfo($"ExamplePrefixThrottled executing (throttled to once every 10 seconds)");

}

Alternative ways to register hooks

Procedurally, using a HookRegistrar:

var hookDOTS = new HookDOTS.API.HookDOTS(MyPluginInfo.PLUGIN_GUID, Log);

//...

var hook =

安裝與使用 安裝:BepInEx 外掛

  1. 本站下載的壓縮包就是模組本體,通常是 BepInEx 外掛(解壓後得到 .dll 或外掛資料夾)。
  2. 建議流程:用社群模組管理器(如 r2modman)選中本遊戲後匯入該模組,管理器會自動裝好 BepInEx 前置並處理依賴。
  3. 手動流程:先在遊戲目錄裝好 BepInEx 載入器,再把解壓出的 .dll 或外掛資料夾放進 BepInEx/plugins/。
  4. 啟動遊戲,BepInEx 控制台會列印載入日誌;確認這個模組出現在日誌裡即為安裝成功。

帶「前置依賴」的模組需要一併安裝,否則不會載入。功能開關通常在遊戲內或外掛自帶的設定檔裡調整。

前置依賴

下面這些內容需要先安裝,否則該模組不會生效:

BepInEx-BepInExPack_V_Rising

檔案與校驗

檔案名稱
HookDOTS_API-1.1.1.zip
檔案大小
122.8 KiB