Skip to content
RustPluginGenerator

Rust Plugin Development Setup: IDE, DLL References, Test Server and Hot Reload

A working Rust plugin development setup has three parts: an IDE with a class library that references the DLLs from RustDedicated_Data/Managed for IntelliSense, a local dedicated server with Oxide or Carbon installed, and a folder workflow where saving a .cs file in oxide/plugins reloads it automatically. The server compiles your plugin, not the IDE project, so the project only exists for code completion and error checking.

8 min readUpdated Oct 26, 2026

A Rust plugin development setup needs an editor with IntelliSense, a class library project that references the DLLs from your server's RustDedicated_Data/Managed folder, and a local dedicated server with Oxide (or Carbon) installed where you drop the .cs file. The server compiles the plugin itself; the IDE project is only there so you get completion, navigation and error squiggles while you type.

If you have not written a plugin yet, start with how to make a Rust plugin and come back here to build the environment.

The overall workflow

  1. Install a dedicated server and Oxide on your own machine (install Oxide on a Rust server).
  2. Create a class library project whose references point at that server's DLLs.
  3. Write the plugin in the IDE, with the project file living outside the plugins folder.
  4. Copy or save the .cs file into oxide/plugins. Oxide compiles and loads it.
  5. Read the console, fix errors, repeat.

The key point: the project is never built for deployment. You do not ship a DLL. You ship the single .cs file.

Choosing an IDE

IDENotes
Visual Studio (Community)Full C# support with the ".NET desktop development" workload. Strong IntelliSense and refactoring. Windows only.
JetBrains RiderCross-platform, excellent code analysis and navigation, built-in decompiler for referenced assemblies. Paid for commercial use.
VS CodeLightweight. Needs the C# extension (or C# Dev Kit) and the .NET SDK. Fine for single-file plugins.

All three work equally well here because they only read the project for analysis. Pick the one you already know.

Installing a local server for references

Use SteamCMD to install the Rust dedicated server (app id 258550) into a folder on your machine, then install Oxide over it. Oxide's installation also places Oxide.Core.dll, Oxide.Rust.dll and related assemblies in RustDedicated_Data/Managed. If you run Carbon, its own files differ, but Carbon loads Oxide plugins, so referencing the Oxide-style assemblies is still the usual way to get IntelliSense.

Do not copy DLLs from a different machine or an old install. References must match the version your server runs.

Creating the class library

Create a new Class Library project. Any recent .NET target that the IDE can analyze is fine, because the project is never run. A .NET Framework 4.x or netstandard-style target avoids most surprises. Name the project after your plugin, for example MyPlugin.

Then add references to DLLs in the server's RustDedicated_Data/Managed folder. A practical set:

AssemblyWhy you need it
Assembly-CSharp.dllGame code: BasePlayer, BaseEntity, HitInfo, ItemManager and more
Assembly-CSharp-firstpass.dllAdditional game types
Oxide.Core.dllInterface, Plugin, permission and data APIs
Oxide.Rust.dllRustPlugin, [ChatCommand], CUI classes
Oxide.CSharp.dll (if present)Plugin attributes and compiler glue
UnityEngine.dll and UnityEngine.CoreModule.dllVector3, Quaternion, Time, TextAnchor
Other UnityEngine.*Module.dllAdd only when you use their types, such as physics
Facepunch.System.dll, Facepunch.Network.dll, Facepunch.Console.dll and similarTypes such as ConsoleSystem.Arg and networking pieces
Newtonsoft.Json.dll[JsonProperty] for config classes
Rust.Global.dll, Rust.Data.dll and similarRust.DamageType and shared types

File names vary slightly between versions, so browse the Managed folder and add what your code needs. Set each reference to "Copy Local: false" so the build does not duplicate the server's DLLs into your project output.

If the IDE says a type is missing

Add the assembly that defines it. Right-click the type in a decompiler, or search the Managed folder. The server-side message for the same problem is explained at CS0246 type or namespace not found.

Adding your plugin file

Create a .cs file in the project, with the class name equal to the file name. Start from this skeleton:

C#
using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace Oxide.Plugins
{
    [Info("My Plugin", "RustPluginGenerator", "1.0.0")]
    [Description("Minimal plugin used to verify the development setup")]
    public class MyPlugin : RustPlugin
    {
        private PluginConfig config;

        private class PluginConfig
        {
            [JsonProperty("Welcome enabled")]
            public bool WelcomeEnabled = true;
        }

        protected override void LoadDefaultConfig() => config = new PluginConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Configuration file is invalid, using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(config);

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Welcome"] = "Welcome, {0}."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args) =>
            string.Format(lang.GetMessage(key, this, userId), args);

        private void OnPlayerConnected(BasePlayer player)
        {
            if (player == null || !config.WelcomeEnabled) return;
            player.ChatMessage(Msg("Welcome", player.UserIDString, player.displayName));
        }
    }
}

If IntelliSense completes BasePlayer, RustPlugin and Config, your references are correct. See OnPlayerConnected for when that hook fires.

Project layout that avoids problems

  • Keep the project folder outside oxide/plugins. Otherwise the server tries to compile stray .cs files such as AssemblyInfo.cs or build artifacts.
  • Keep one plugin per file. The class name must match the file name, or Oxide will not find the main class (plugin filename must match main class).
  • Use the classic block namespace namespace Oxide.Plugins { } and avoid language features the server compiler may not support, such as file-scoped namespaces.
  • Do not add a constructor to the main class (main plugin class should not have a constructor). Use Init instead.

Running a local test server

Create a start script with a small map and a private identity so that your test data is separate from any production server. Typical settings include a low server.worldsize, a fixed server.seed, server.identity set to something like dev, and a local server.port. Remember to use the server's own startup arguments and keep it off your public listing.

Practical habits:

  • Make yourself owner or admin (ownerid <steamid64> "name" "reason") so you can test permission-gated features.
  • Test with oxide.grant user <name|id> <perm> and oxide.revoke to verify permission checks both ways (Oxide permissions and groups).
  • Join with the Rust client using connect 127.0.0.1:<port> from the F1 console.
  • Use a second Steam account or friend if you must test team, trade or PvP behavior.
  • Keep copies of your oxide/config and oxide/data folders when testing destructive changes so you can restore them.

Server commands you will use often are listed in Oxide console commands.

Hot reload workflow

Oxide watches oxide/plugins. Saving a .cs file there compiles and reloads it automatically, with no server restart. A typical loop:

  1. Edit the plugin in your IDE.
  2. Save it into oxide/plugins (or copy it there; a post-build or save script, or a symbolic link from the plugins folder to your project file, removes the manual step).
  3. Watch the console. A good load prints Loaded plugin <Title> v<Version> by <Author>. There is no separate "compiled successfully" line.
  4. Test in game.

If compilation fails, the console prints Error while compiling <PluginName>: followed by numbered messages such as [1] <message> at <line>:<column>. The failed file is skipped while other plugins stay loaded. The CS code and details are also written into oxide/logs. Look up the CS number in the error pages when it is not obvious.

You can reload manually with oxide.reload <Name>, or load and unload with oxide.load and oxide.unload.

What a reload does

A reload calls Unload on the old instance, then starts a fresh instance: Init, config and lang loading, Loaded, then OnServerInitialized with false because the server is already running. Anything you hold only in memory is gone, so save data in Unload and clean up UI and timers there. This is why every plugin should destroy its CUI panels and timers on unload; otherwise old panels stay on players' screens after you reload.

Hot reload is also the best test for your lifecycle code: reload several times while players are connected and confirm nothing duplicates or leaks.

Reading game code with a decompiler

Hooks are injected into game methods, and the clearest way to understand a hook is to read the method around it. Open Assembly-CSharp.dll in a .NET decompiler (ILSpy, dnSpy-style tools, or Rider's built-in decompiler) and search for the class and method named on the hook page.

Useful questions to answer by reading:

  • What are the argument types and can any be null?
  • What does the surrounding code do if a plugin cancels the action?
  • Which members does an entity expose that you can use, for example BuildingPrivlidge.IsAuthed?

Decompiled output is for understanding only. Write your own code and do not paste decompiled sections into plugins you publish. Also note that decompiled names can differ slightly from what the compiler originally saw, so confirm member names against your IDE's IntelliSense with the same references.

For deeper background see Oxide hooks explained, Rust entities and prefabs and Rust items and inventories.

Keeping references updated

Rust updates monthly (on the first Thursday for forced wipe) with smaller patches between. Each update can change game DLLs, and Oxide ships a matching build.

A safe update routine:

  1. Update the dedicated server with SteamCMD.
  2. Install the matching Oxide build over it.
  3. Refresh the references in your IDE. If the references point at the Managed folder, they update in place; rebuild or reload the solution so IntelliSense re-reads them. If you copied DLLs to a separate folder, copy them again.
  4. Rebuild the project and read the new errors. Missing members show up here before you test in game.
  5. Start the server and watch for hook warnings and compile errors.

Typical symptoms after an update are CS1061 and CS0117 (CS1061, CS0117), deprecated hook warnings (deprecated hook will stop working), and hooks that no longer fire. The fix Rust plugins after update guide has the full triage. The monthly updates reports list hook changes so you can check them first.

Debugging and testing habits

Generating a starting point

If you want a working file to open in your new environment, the plugin generator produces a complete Oxide plugin from a description, which you can then read, modify and test with the loop above. Browse how-to recipes for small examples to study.

Setup checklist

  • Dedicated server installed and running locally with Oxide or Carbon.
  • Class library project with references to the server's Managed DLLs, matching the server version.
  • Project folder outside oxide/plugins.
  • File name equals the class name.
  • Admin rights and test permissions set up on the local server.
  • Decompiler installed for reading game methods.
  • Update routine written down: server, Oxide, references, rebuild.

FAQ

Do I need Visual Studio to write Oxide plugins?

No. A plugin is a single .cs file that the server compiles itself, so Notepad would work. An IDE such as Visual Studio, Rider or VS Code only adds IntelliSense, navigation and early error detection when the project references the game DLLs. Pick whichever editor you are comfortable with.

Why does my IDE show no errors but the server fails to compile the plugin?

The IDE and the server use different compilers, language versions and reference sets. If your project references DLLs from a different game version than the server runs, or uses newer C# features than the server's Roslyn accepts, the IDE passes and the server fails. Trust the server log, and read the CS0246 error page for missing types.

Should my test server be public?

No. Run it on localhost or a private port with a small map size, and join through the client console with connect 127.0.0.1:28015 (or your configured port). A private server lets you restart freely, grant yourself admin, and test destructive features without affecting players.

How do I get readable game code to understand hooks?

Open Assembly-CSharp.dll in a .NET decompiler such as ILSpy or dnSpy and search for the method named in a hook's signature, for example StorageContainer.PlayerOpenLoot. You can see what arguments exist and what code runs before and after the hook point. Use it for reading only and never copy it into a published plugin.

What breaks most often after a Rust update?

Renamed or removed game members, changed method signatures and changed hooks. Plugins then fail with CS1061 or CS0117 compile errors or runtime exceptions. Update the server, Oxide and your IDE references together, then rebuild. The fix plugins after update guide covers the workflow.

Skip the C#: describe your plugin

Open generator