Rust mod local development with Oxide

This article is a short how-to on developing mods/plugins for the game Rust. We will try to describe the best way to set up your local work environment, so you are most efficient and stop wasting time during development. We will also set up code completion/IntelliSense for your local Rust server, so you can simultaneously code your plugin and check it in your game. This is in contrast with the common simple way of just editing the plugin file in a text editor and uploading it over and over via FTP. The initial setup time is a bit longer, but the comfort of the development boosts your productivity and you can work much faster.

Rust game mod development

Integrated Development Environment

What you want rather than a text editor is an IDE. The name stands for Integrated Development Environment. It means that it’s a smart editor that will help you finish your code as you type it and remind you of all the functions you can use. Also, it can detect the mistakes you make and prompt you to correct them. All in all, it speeds up your work and that’s what this is all about.

Installing an IDE

For this article, we will be using JetBrains Rider. I’m using it daily both in my work and hobby projects, so my best-added value for you is to use it in this article as well, but you can use any C#/.NET IDE available.

Rider environment

Creating a Project

When you install Rider (or any other IDE), the first thing you’ll need to do is to create a new Project. We will work on our mod in the Project and it’s best to have one Project (and code repository) per mod.

Solution

First, we need to create a Solution. A Solution in the .NET world is a container to group your similar Projects. You can use one Solution for several mods you develop, especially if you need to make them communicate together, or test them together.

In Rider, go to File > New > Empty Solution:

Creating a new Solution in Rider

Project

Then, when you have the Solution ready and open, we can add our first Project, our first mod.

Right-click on your Solution name and choose Add > New Project:

Adding a new Project to a Rider Solution

Then as the Project template select Class Library and type Empty:

Selecting a Project template
Desired folder structure

If you see a folder structure similar to the screenshot above, we’re good to go to the next part!

Getting that IntelliSense to work

What we need from and IDE the most, is the intelligent code inspection/completion. We now need a way to tell the editor that we’re developing a Rust mod. We’ll be doing that by pulling in Oxide core and Rust related packages into our project.

Oxide NuGet package source

C# and .NET use NuGet as a package manager. This means on NuGet there are plenty of useful packages that someone has already created and you can use them in your project to make your life easier and code shorter. This is true also for Rust mod development — we are basing our mods on Oxide mod, which is a framework for making Rust mods (and for other games as well). So we need to fetch the relevant packages. Oxide has its source for the packages, it doesn’t use the default NuGet packages, so we need to add a source feed. In Rider click NuGet at the bottom, then Source and then add this URL

https://www.myget.org/f/oxide/api/v3/index.json

as a new source (see screenshot):

Adding Oxide source URL for NuGet package

Necessary packages

Now we need to install packages needed for Rust mod development. Click on Packages next to Sources and install all the packages you can see on the following screenshot:

Oxide package library

Some of them may not be necessary for simpler mods, but you’ll figure it out later when you start developing. When you’ll have multiple Projects in the Solution, you can simply install the package into all Projects using the top right plus button:

Installing Rust mod package to Projects

Verification

Now we should have everything prepared to develop mods locally. To test this, we create the simplest mod possible. Create a new file under MyFirstMod/src and call it EpicStuff.cs

Paste the following code into it (taken from Oxide documentation — getting started):

namespace Oxide.Plugins
{
[Info(“Epic Stuff”, “Unknown Author”, “0.1.0”)]
[Description(“Makes epic stuff happen”)]
class EpicStuff : CovalencePlugin
{
private void Init()
{
Puts(“A baby plugin is born!”);
}
// The rest of the code magic // TODO (you): Make more epic stuff
}
}

Now, when you hold CTRL and hover over the CovalencePlugin you should see IntelliSense in action:

IntelliSense

Try clicking on it!

Great! Now we’re ready to start developing!

Local Rust server

While developing plugins, you ideally want to run a local Rust server. Otherwise, you’d have to connect to your remote server and upload the plugin file over and over. To run a local Rust server, we’ll use the most simple method independent of the OS you use — Docker.

Docker

As you can read on Wikipedia, Docker is a set of platform as a service (PaaS) products that use OS-level virtualization to deliver software in packages called containers. Containers are isolated from one another and bundle their own software, libraries, and configuration files; they can communicate with each other through well-defined channels. All containers are run by a single operating system kernel and therefore use fewer resources than virtual machines.

In English, this means that it’s a tool that can run virtual computers on your machine, and run pre-configured stuff on those computers, that would take ages to configure on your machine. For our use, it means that we will simply download an image with a pre-configured Rust server, and run it using Docker.

First, you’ll need to install docker. The Get docker page will help you to install it for your platform. Once you have Docker up and running, verify that you have a docker command in your terminal, and move on to the next section.

Installing the server

We will be using a pre-configured didstopia Rust server Docker image. You can find all the info about the image and the creator on their website.

Configuration

First, we will create a configuration file. Create a file (anywhere, e.g. you can use the OxideMods folder where our plugin code sits) called rust.env and navigate to that folder in your terminal. Open the file in an editor and write the following:

RUST_SERVER_IDENTITY=my_awesome_server
RUST_SERVER_SEED=12345
RUST_SERVER_NAME=My Awesome Server
RUST_SERVER_DESCRIPTION=This is my awesome server
RUST_RCON_PASSWORD=SuperSecurePassword
RUST_OXIDE_ENABLED=1

Running the image

Then run the following command in your terminal:

docker run — name rust-server -d -p 28015:28015 -p 28015:28015/udp -p 28016:28016 -p 8080:8080 -v your/path/to/OxideMods/rust:/steamcmd/rust — env-file rust.env didstopia/rust-server

You can check the Didscraft website linked above for a detailed explanation of what this command does. To put it shortly, it downloads the pre-configured Docker image with the Rust server, binds ports from your local machine to it (so we can connect), loads your configuration file that we created in the previous step, and runs the server. Be careful to put the correct path to your OxideMods folder, where the persistent files needed for the rust server will be stored in the rust subfolder.

Verifying

Note that the first run of this image can take a long time, because it will download the steamcmd app and the whole rust server, so be patient. You can check the logs from the Docker container using the following command:

docker logs -f rust-serverEventually, you’ll see something like this, in the logs:SteamServer Initialized
IP address from Steam query: 0.0.0.0
Server startup complete
SteamServer Connected
BradleyAPC Spawned at :(600.6, 32.2, -606.9)
Checking for new Steam Item Definitions…

Testing the connection

Now you can try and connect to your server. Also, this Docker image provides a WebRCON, so we can check that first: visit http://localhost:8080 in your browser (for Win7/8 users using older Docker installation, it will be on http://192.168.99.100:8080/)

Enter your RCON password (set in the .env file) and you’ll see something like this:

WebRCON environment

Now open your Rust game and connect to your server! Open the in-game console using F1 and type:

client.connect 127.0.0.1:28015

(or 192.168.99.100:28015 for Win7/8 users) and voila! Welcome to your own local Rust server!

WebRCON Chat window
Welcome to your local Rust development server

One last step

So now we have a local environment working in Rider, we have IntelliSense and code completion, and we have a locally running Rust server in Docker. We did all this to have a comfortable environment for writing our plugins and so that we don’t need to copy the plugin file over and over. And to achieve the latter, we need to modify our command to run the Docker container a little bit.

docker run — name rust-server -d -p 28015:28015 -p 28015:28015/udp -p 28016:28016 -p 8080:8080 -v your/path/to/OxideMods/rust:/steamcmd/rust -v your/path/to/OxideMods/src:/steamcmd/rust/oxide/plugins — env-file rust.env didstopia/rust-server

This will ensure that our source folder where we develop our plugins will get mounted into the oxide’s plugins directory in our Rust server.

Advanced stuff

During the writing of this article, I encountered two things that I needed to solve. I was using a setup on an older Docker installation and my virtual machine ran out of memory. The first subsection talks about what to do in that case. The second subsection provides a solution on how to simplify the setup a little bit if you become more familiar with Docker.

Memory issues

Sometimes, when reloading a plugin, Oxide’s compiler can fail due to being out of memory. This happens especially if you’re using Windows 7, Windows 8, or Windows10 Home with the older Docker setup that uses VirtualBox in the background. On modern Docker solutions (on Windows 10 Pro, Linux, or OSX) the containers utilize your whole computer and only run out of memory if your whole PC runs out of it (then you have a bigger problem, though). But your VirtualBox machine is usually set-up with less RAM. For running a local Rust server you’ll need at least 8GB in the VM, and a good swap (preferably on an SSD) with at least 4GB. If you ever encounter out of memory issues, your best bet if you don’t want to restart everything and reconfigure the whole VM, is to add some swap on the fly. Here is how:

Login to your running machine (see screenshot below, if you’re using Oracle VM VirtualBox)

Oracle VM VirtualBox Manager

And run the following commands:

export SWAPFILE=/mnt/sda1/swapfile
sudo dd if=/dev/zero of=$SWAPFILE bs=1024 count=4194304
sudo mkswap $SWAPFILE
sudo chmod 600 $SWAPFILE
sudo swapon $SWAPFILE
exit

This will increase your total swap by approx. 1.5GB. Add another one, if that’s not enough, but usually, the Oxide compiler starts working after doing this process once.

Docker Compose

If you’re more familiar with Docker, or you’d like to make your life easier in exchange for a little bit more complicated initial setup, you can use Docker Compose to automate running your container. In other words, instead of running the whole multi-line docker run … command, you can create a file called docker-compose.yml in your OxideMods folder, with the following contents:

version: ‘3.6’services: rust-server:
image: didstopia/rust-server
environment:
RUST_SERVER_IDENTITY: my_awesome_server
RUST_SERVER_SEED: 12345
RUST_SERVER_NAME: My Awesome Server
RUST_SERVER_DESCRIPTION: This is my awesome server
RUST_RCON_PASSWORD: SuperSecurePassword
RUST_OXIDE_ENABLED: 1
ports:
— “28015:28015”
— “28015:28015/udp”
— “28016:28016”
— “8080:8080”
volumes:
— ./rust:/steamcmd/rust
— ./src:/steamcmd/rust/oxide/plugins
networks:
— default

From now on, you can start your container by running the command docker-compose up in your OxideMods folder. And you don’t need the rust.env file anymore as the yml configuration takes care of that as well.

Happy Coding!

teo for SOLO ISLAND

Extreme RUST survival