Getting Started with Development

From GTA Network Wiki
Jump to: navigation, search

Getting Started with Development



dialog-warning.pngRework required!

The contents of this page are possibly invalid or incomplete. Please treat the contents of this page with caution!

If you are able to, please modify the page so that it's factually correct.


Requirements

  • Basic C# programming knowledge

Introduction

This page will be going over how to set up a server and write your first resource. A resource is a custom script which can be run on the server or the client.

If you are an experienced developer, you can just reference GTANetworkServer.exe and GTANetworkShared.dll in your Visual Studio project. Then you can set the 'lang' attribute of the '<script>' tag to 'compiled' and use the compiled .dll assembly instead of .cs source files.

Starting the server

In your GTANetwork server folder you will find the main executable used to start the server, GTANetworkServer.exe, a settings.xml file used to configure your server and a resource folder which will contain your resources. Open settings.xml with notepad and edit your `<servername>` to your own.

Creating a new resource

Every resource goes into its own folder inside the `resources` folder. Let's make our own resource!

1. Create a new folder called 'mines'.

2. Create a new text file called 'meta.xml' (Make sure you don't have file extensions hidden!) and fill it with the following:

<meta>
    <info name="Mines" description="Test resource to play around with mines" />

    <script src="mines.cs" type="server" lang="csharp" />
</meta>

On the second line we declare an `info` tag, this will contain basic information about our resource such as name, description, author, etc. On the fourth line we add our script file and this is where the magic will happen. The `type` is `server` since it will be running on the server, not the client, and `lang` is C#. You can also write in Visual Basic.NET, but we won't in this guide. (Use "vbasic" instead)

Main article: meta.xml

3. Create a new text file called 'mines.cs' and fill it with the following:

using System;
using GTANetworkServer;
using GTANetworkShared;

public class MinesTest : Script
{
    public MinesTest()
    {
        
    }
}

This is a basic template for our scripts. All scripts must inherit the `Script` class and must reference GTANetworkServer and GTANetworkShared.

Let's fill it with some useful stuff. You can interact with GTANetwork using the `API` object. Let's make it write something to the server console when it starts:

We add an event handler called 'myResourceStart', and then attach it to API's `onResourceStart` event inside the constructor.

using System;
using GTANetworkServer;
using GTANetworkShared;

public class MinesTest : Script
{
    public MinesTest()
    {
        API.onResourceStart += myResourceStart;
    }

    public void myResourceStart()
    {
        // This will be ran once all scripts are initialized!
        API.consoleOutput("Starting mines!");
    }
}

If you start the resource, you'll see "Starting mines!" pop up on your server console.

Now, we want it to do something useful. We want the resource to create a mine when the user types the command "/mine". Creating commands with GTANetwork is very easy, and it doesnt need any input sanitation, since the server does it for you! All commands use the "[Command]" attribute, and take Client as the first parameter, indicating the player that sent the command.

using System;
using GTANetworkServer;
using GTANetworkShared;

public class MinesTest : Script
{
    public MinesTest()
    {
        API.onResourceStart += myResourceStart;
    }

    public void myResourceStart()
    {
        API.consoleOutput("Starting mines!");
    }

    [Command("mine")]
    public void PlaceMine(Client sender)
    {
        // This is our command!
    }
}

Now let's make the command do something useful.

using System;
using GTANetworkServer;
using GTANetworkShared;

public class MinesTest : Script
{
    public MinesTest()
    {
        API.onResourceStart += myResourceStart;
    }

    public void myResourceStart()
    {
        API.consoleOutput("Starting mines!");
    }

    [Command("mine")]
    public void PlaceMine(Client sender, float MineRange = 10f)
    {
        var pos = API.getEntityPosition(sender);
        var playerDimension = API.getEntityDimension(sender);

        var prop = API.createObject(API.getHashKey("prop_bomb_01"), pos - new Vector3(0, 0, 1f), new Vector3(), playerDimension);     
        var shape = API.createSphereColShape(pos, MineRange);
        shape.dimension = playerDimension;
    }
}

We can see how easily we can add arguments to our commands. The command takes a single optional parameter, the mine detonation range, which is defaulted to 10 meters. The player can input "/mine" to create a mine with a range of 10 meters, or "/mine 5" to create one with a range of 5 meters.

On the first line we get the player's position in the world and store it inside the "pos" variable. Then we do the same to player's dimension (virtual world) and store it in the "playerDimension" variable.

On the next two lines we create an object in the world (a bomb) on player's feet and inside the player's dimension. Next we create a sphere collision shape, which will detect any player/vehicle/object that enters or exits the shape. We also set it so it only detects entities inside player's dimension.


Now let's make it explode when someone enters it's range. As the player is already inside the collision sphere when placing the mine, first we have to arm it when player leaves the range, so it doesnt kill him instantly.

using System;
using GTANetworkServer;
using GTANetworkShared;

public class MinesTest : Script
{
    public MinesTest()
    {
        API.onResourceStart += myResourceStart;
    }

    public void myResourceStart()
    {
        API.consoleOutput("Starting mines!");
    }

    [Command("mine")]
    public void PlaceMine(Client sender, float MineRange = 10f)
    {
        var pos = API.getEntityPosition(sender);
        var playerDimension = API.getEntityDimension(sender);

        var prop = API.createObject(API.getHashKey("prop_bomb_01"), pos - new Vector3(0, 0, 1f), new Vector3(), playerDimension);     
        var shape = API.createSphereColShape(pos, MineRange);
        shape.dimension = playerDimension;
        
        bool mineArmed = false;
        
        // Triggered when a player, vehicle or object enter the mine's range
        shape.onEntityEnterColShape += (s, ent) =>
        {
            if (!mineArmed) return; // If the mine is not armed, do nothing.
            // Otherwise, create an explosion at mine's position, in player's dimension
            API.createOwnedExplosion(sender, ExplosionType.EXPLOSION_HI_OCTANE, pos, 1f, playerDimension);
            API.deleteEntity(prop); // Delete the object
            API.deleteColShape(shape); // Delete the collision shape
        };

        // Triggered when a player, vehicle or object exit the mine's range
        shape.onEntityExitColShape += (s, ent) =>
        {
            if (ent == sender.handle && !mineArmed)
            { // The player that placed the mine left it's range, let's arm the mine!
                mineArmed = true;
                API.sendNotificationToPlayer(sender, "Mine has been ~r~armed~w~!", true);
            }
        };
    }
}

We use lambda expressions to attach to our collision shape's events inside the command method. The mine wont explode until the player has left the mine range.

Now let's try it in game! Don't forget to add our new resource to your server's settings.xml file:

<resource src="mines" />

Connect to your server using Direct Connect and input "127.0.0.1" as the server, and type "/mine" to spawn a mine at your feet!