Source-checkedAdmin & protection

HookDOTS API

by cheesasaurus · for V Rising

Provides an API for mods to hook Unity DOTS systems.

14KDownloads
12 mo agoLast updated
BepInExLoaders
ThunderstoreSource

About HookDOTS API

From Thunderstore

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

  1. Install BepInEx
  2. 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

1. Add a reference to the plugin.

>dotnet add package HookDOTS.API -v 1.*

2. 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

3. 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();
}

4. Teardown in your plugin's Unload method.

public override bool Unload()
{
    //... other unloading code

    _hookDOTS.Dispose();
    return true;
}

5. 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 = HookDOTS.Hooks.System_OnUpdate_Prefix.CreateHook(MyHookMethod);
hookDOTS.HookRegistrar.RegisterHook_System_OnUpdate_Prefix<TakeDamageInSunSystem_Server>(hook);

Builder style, using SetupHooks:

var hookDOTS = new HookDOTS.API.HookDOTS(MyPluginInfo.PLUGIN_GUID, Log);
//...
hookDOTS
    .SetupHooks()
        .BeforeSystemUpdates<EquipItemSystem>()
            .ExecuteDetour(MyMethodA).Always()
            .And()
            .ExecuteDetour(MyMethodB).Always()
    .Also()
        .AfterSystemUpdates<TakeDamageInSunSystem_Server>()
            .ExecuteAction(MyMethodC).Throttled(seconds: 2)
    .Also()
        .BeforeSystemUpdates<DropInventoryItemSystem>(onlyWhenSystemRuns: false)
            .ExecuteDetour(MyMethodD).Throttled(seconds: 5)
    .RegisterChain();
    // be sure to call RegisterChain! Otherwise the entire chain will be discarded.

World Readiness triggers for Initialization

There are world readiness checks/triggers if you need to defer something until after worlds are created.

Worlds are immediately checked during hook registration, in case they were already set up.\

Read the full description on Thunderstore →

Highlights

From source data

Loaders

Runs on BepInEx.

Footprint

Rated a light load on a server.

Last update

Its author last shipped an update 12 mo ago.

HookDOTS API on Nxeon

From our catalogue
One-click install
Not available. One-click install isn't available for this game's mods yet. Download it and upload it to your server in Files.
Server type needed
BepInEx
Server load
light
Smallest plan we suggest
V Rising — 6 GB (6 GB RAM). This follows our own load rating above, not a benchmark.
Latest build
1.1.1, released 2025-10-22

Game versions by loader

LoaderGame versionsNewest
BepInEx

From 3 recorded builds of HookDOTS API.

Recent builds

BuildReleasedGame versionsLoaders
1.1.12025-10-22n/aBepInEx
1.1.02025-07-15n/aBepInEx
1.0.02025-06-08n/aBepInEx

Dependencies

Declared by the newest build that lists any. Required ones are installed with it on one-click installs.

Run HookDOTS API on a V Rising server

Deploy a server above, then upload the file in Files.

What kind of mod it is

From the catalog
Listed on Thunderstore as “Admin”

Admin & protection

Permissions, moderation, anti-cheat and land protection for the people running the server.

Compatibility

Game
V Rising
Loaders
BepInEx
Requires
One-click install needs a BepInEx server.

Verified at the source

  • ✓ThunderstoreOfficial listing, checked 2026-10-02Open ↗
  • ✓Authorcheesasaurus, as published on Thunderstore
  • ✓LicenseNot published by the sourceFree

HookDOTS API, answered

Generated from the mod’s own source data.

Which loaders does it support?

BepInEx.

Is it free?

Yes. HookDOTS API is free to download from Thunderstore.

How do I add it to my Nxeon server?

One-click install isn't available for this game's mods yet. Download HookDOTS API from Thunderstore and upload it to your Nxeon V Rising server in Files.

NxLabs

Run HookDOTS API on a V Rising server.

Deploy in about a minute from $12.00 a month, then upload HookDOTS API in Files.