Development with Visual Studio Code

From RAGE Multiplayer Wiki
Jump to navigation Jump to search

This tutorial explains a basic to develop & debug a RAGE-MP resource / server-side script using VSCode on C# bridge


Note: it is not required for you to compile the .cs scripts to run the resource, you can let the server compile them when server starts. See the comparison below.

This tutorial will mainly describe about compiling your server-side resource into .dll binary which you can attach a debugger on it. A similar step can be also done in Visual Studio IDE, except the launch & task part.

Requirement

  • Visual Studio Code - Download
  • .NET Core SDK version 2.2 - Download (As of RAGE:MP 0.3.7, Server side uses version 2.0.3 and Client side uses version 2.2.0 so it's safe to install the latest which are backward compatible)
  • C# Extension for Visual Studio Code powered by OmniSharp - Download (in Visual Studio Code)

Setting Up Project

  1. Open Visual Studio Code on bridge/resources folder
  2. Create a new folder, example mygamemode then select the folder
  3. Open the terminal Ctrl+` (control + tilde)
  4. Enter >dotnet new classlib -f netcoreapp2 to create a new .NET Core class library
  5. A .csproj file will be created, click to edit it
    1. Change the TargetFramework to netcoreapp2.0
    2. Set the RuntimeFrameworkVersion to 2.0.3
    3. Include GTANetworkAPI by adding reference to bridge/runtime/Bootstrapper.dll
    4. Your mygamemode.csproj should look like this:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <RuntimeFrameworkVersion>2.0.3</RuntimeFrameworkVersion>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="GTANetworkAPI">
      <HintPath>..\..\runtime\Bootstrapper.dll</HintPath> <!-- Or absolute path to your X:/RAGEMP/server-files/bridge/runtime/Bootstrapper.dll -->
      <Private Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">False</Private>
    </Reference>
  </ItemGroup>

</Project>

Save the files and enter in terminal: >dotnet restore.

Setting up Launch and Task command

Visual Studio Code comes with two kind of project commands: launch.json and tasks.json

These commands are saved inside a .vscode folder of your project, so you have to do this on every different projects you created.

launch.json

The launch command is used for running server debug with F5 key (or from Debug menu) later

  1. Proceed to Debugging Tab (Ctrl+Shift+D)
  2. Click the Gear button (next to DEBUG button) to configure the launch.json, select .NET Core or Others
  3. Modify the configuration like this:
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "RAGE-MP Launch (build)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "compile",
            "program": "server.exe", // The RAGEMP server executable
            "args": [],
            "cwd": "${workspaceFolder}/../../../", // Or absolute path to your X:/RAGEMP/server-files/
            "stopAtEntry": false,
            "console": "externalTerminal",
            "internalConsoleOptions": "neverOpen"
        }
    ]
}

Save the launch.json file.

tasks.json

We will create two kind of tasks:

  • compile - to compile the resource into .dll, required for debugging in launch task we created before (located in bin/Debug/ by default)
  • release - to build the end product of the resource with optimized .dll ready to deploy & run in real server (located in bin/Release/ by default)

You can run these tasks by selecting Terminal>Run Task... later time.

  1. Select on menu bar Terminal>Configure Tasks..., select .NET Core or Others
  2. Modify the configuration like this:
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "compile",
            "type": "shell",
            "command": "dotnet build",
            "presentation": {
                "reveal": "silent"
            },
            "problemMatcher": "$msCompile",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "promptOnClose": true
        },
        {
            "label": "release",
            "type": "shell",
            "command": "dotnet build -c Release",
            "problemMatcher": "$msCompile",
            "group": "build"
        }
    ]
}

Save the tasks.json file.

Setting Up Resource

Now you can create your script in Class1.cs, rename it if you wish (make sure the class name is also renamed)

Writing the gamemode

  1. Add the C# server-side bridge dependency with using GTANetworkAPI
  2. Extends your class to Script API like public class Class1 : Script
  3. Add Hello World! code in the entry point or class constructor of the script, your code would look like this:
using System;
using GTANetworkAPI;

namespace mygamemode
{
    public class Class1 : Script
    {
        public Class1()
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Configuring resource meta file

  1. Create a new file meta.xml in your resource folder (if not exist)
  2. Put some resource information, and add the mygamemode.dll file
<meta>
    <info name="My Gamemode" description="My C# bridge gamemode Resource" />
    <!-- Uncompiled: -->
    <!-- <script src="Class1.cs" /> -->
    <!-- Compiled: -->
    <script src="bin/Debug/netcoreapp2.0/mygamemode.dll" />
</meta>

Note that after running compile task, your .cs scripts will be compiled into .dll by default located on bin/Debug/netcoreapp2.0/ folder relative to your resource directory.

If you are not sure why your .dll does not work, try running the server with raw Class1.cs source code (uncomment the Uncompiled and comment the Compiled script tag).

Configuring bridge setting

  1. Edit bridge/settings.xml file in your server folder, add your resource like the following:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <acl_enabled>false</acl_enabled>
  <resource src="mygamemode" />
</config>

Save the files.

Debugging the Script

When you are set up ready, it's time to build the resource!

If there are errors on compilation, try to close the folder and re-open it in your Visual Studio Code, usually the OmniSharp server need to refresh new files.

You can also try >dotnet clean in case you have changes on the referenced files (i.e. Bootstrapper update).

Since we have not added any gameplay code in this tutorial, we do not have to play & join the server.

  1. Open your script Class1.cs, add a code breakpoint by clicking on the left side of the line number
  2. For example, you may want to put a pause before the server prints "Hello World" line
        public Class1()
        {
            Console.WriteLine("Hello World!");
        }
  1. Go to Debug tab
  2. Hit F5 button
  3. Your server will run, and the server threads will pause on your breakpoint line
  4. Click ► Continue button (F5) on top of your Visual Studio window
  5. You will get output "Hello World" in your server console.
Loading resources..
-> Starting mygamemode resource..
mygamemode: loading scripts...
mygamemode: instantiating mygamemode.Class1..
Hello world!
-> Resource mygamemode started!

Close the server/hit the ■ Stop debugging button (Shift+F5).

After you made changes to your script, you can always hit F5 again to restart debugging.

Deploying the Resource

Now that you have learn how to build and debug your script, later when your resource is ready, you may want to compile it with the Release task to deploy an optimized binary.

Simply, click on menu Terminal>Run Task... then select release

You can find your .dll in bin/Release/netcoreapp2.0/ as you may notice it contains cleaner files, since we configured to not copy the .dll files from runtime folder with the <Private> option. This build will be not debugable as the symbols are already removed and optimized for run time.

Proceed to upload these .dll file to your server, and be sure to set your meta.xml differently as it will be using the non-debugged version.

<meta>
    <info name="My Gamemode" description="My C# bridge gamemode Resource" />
    <script src="bin/Release/netcoreapp2.0/mygamemode.dll" />
</meta>

You might want to have the .pdb file together with it, it will create useful traceable dump in case your code causes server crash during runtime, even though it is not really possible to debug it.

Client-side

You can also do similar thing to work with client-side scripts, except you do not deal with launch or task commands. However, please note that in RAGE MP Client-side C-Sharp scripts are NOT compiled nor build into .dll. Which means you cannot debug it like in this tutorial.

You can still make the project, reference to rage-sharp.dll in RAGEMP/dotnet/ folder to get IntelliSense auto completion benefit in VSCode, similar way we did on Bootstrapper:

  <ItemGroup>
    <Reference Include="RAGE">
      <HintPath>..\..\..\dotnet\rage-sharp.dll</HintPath> <!-- Or absolute path to your X:/RAGEMP/dotnet/rage-sharp.dll -->
      <Private>False</Private>
    </Reference>
  </ItemGroup>

And you just have to save the .cs file, they will be downloaded to your player's RAGE-MP client and will be compiled as how you configured it.

A brief comparison how C# works in RAGE-MP
Server-side Bridge (Compiled) Server-side (Raw) Client-side
Output IL "binary" (.dll) C-Sharp source code (.cs)
Dependency Bootstrapper.dll runtimes & bridge.dll plugin rage-sharp.dll runtimes
Compile Time By server developer with C# Compiler (in SDK) By server.exe By ragemp_v.exe
.NET Core Version 2.0.3 1) 2.2.0 2)
Debugging Developer's debugger tool choice (in SDK) RAGE MP app built in error handling & logging

Notes:

  • 1) As of 0.3.7 based on .version file found in RAGEMP/server-files/bridge/runtime/ folder
  • 2) As of 0.3.7 based on .version file found in RAGEMP/dotnet/ folder

See also