HookDOTS API
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 外掛
- 本站下載的壓縮包就是模組本體,通常是 BepInEx 外掛(解壓後得到 .dll 或外掛資料夾)。
- 建議流程:用社群模組管理器(如 r2modman)選中本遊戲後匯入該模組,管理器會自動裝好 BepInEx 前置並處理依賴。
- 手動流程:先在遊戲目錄裝好 BepInEx 載入器,再把解壓出的 .dll 或外掛資料夾放進 BepInEx/plugins/。
- 啟動遊戲,BepInEx 控制台會列印載入日誌;確認這個模組出現在日誌裡即為安裝成功。
帶「前置依賴」的模組需要一併安裝,否則不會載入。功能開關通常在遊戲內或外掛自帶的設定檔裡調整。
下面這些內容需要先安裝,否則該模組不會生效: