/GbxRemote.Net

Trackmania dedicated server XML-RPC async task library for .NET Core

Primary LanguageC#Apache License 2.0Apache-2.0

GbxRemote.NET

Nuget GitHub Lines of code Discord

A library for interacting with the XML-RPC protocol of TrackMania servers and similar titles built with .NET Core. It is built using the async task pattern. It comes with pre-made methods for all the documented XML-RPC methods provided by the trackmania server and allows you to easily hook into and react on callbacks. Interacting with ModeScript is also simplified through special features.

Table of Contents

Installation

The client library is available on Nuget.

Install with Nuget Manager:

Install-Package GbxRemote.Net

Install with dotnet CLI:

dotnet add package GbxRemote.Net

User Guide

The following guide will give you an introduction on how to use the library. Make sure you also check out the Examples for more complete examples on the usage.

Creating an Async Context

The client uses the task async pattern, which means you will have to manage an async context. An easy way to setup your program is this:

static async Task MainAsync(string[] args) {
    // program code here ...
    
    Task.Delay(-1); // wait forever
}

static void Main(string[] args) {
    MainAsync(args).GetAwaiter().GetResult();
}

Server Connection

Connection to a server is simple. Create an instance of GbxRemoteClient and call the LoginAsync method to connect and login automatically:

// 5000 is the default XML-RPC port for TrackMania, change this as needed.
GbxRemoteClient client = new("<server address>", 5000);
await client.LoginAsync("SuperAdmin", "SuperAdmin")

Disconnecting

To properly disconnect from the server you can call the DisconnectAsync method:

await client.DisconnectAsync();

This will stop the recieve loop and dispose of the socket connection.

Calling Methods

The client implements automatic parsing for most of the documented methods of GBXRemote. Therefore for most functions, you just need to call the class method implemented for a specific XML-RPC method.

Calling the main XML-RPC Methods

Calling XML-RPC methods is super simple, just like calling a C# method. For example, let's say you want to get the chat lines.

string[] chatLines = await client.GetChatLinesAsync();

foreach (string line in chatLines)
    Console.WriteLine(line);

Here the code calls the "GetChatLines" XML-RPC method and the client automatically parses the response into a native c# string array for you to simply print out.

Some methods returns structs of data. Let's say you wanted to get the player list:

PlayerInfoStruct[] players = await client.GetPlayerListAsync();

This returns an array of structs containing information about players.

Some useful methods.

Here are a few out of the hundres of available methods. For a complete list, either check library reference or click here.

Chat Methods

Get chat: Returns the lines that appeared in the in-game chat.

string[] GetChatLinesAsync()

Player List

Returns all players currently connected to the server.

PlayerInfoStruct[] GetPlayerListAsync(int maxInfos=-1, int startIndex=0, int? serverType = -1)

The paramters are optional:

  • maxInfos: Maximum number of players to return.
  • startIndex: Start index in the list to begin the list.
  • serverType: Usually not used, 0 = united, 1, 2 = forever

The PlayerInfoStruct contains the following fields:

public class PlayerInfoStruct : PlayerStruct {
    public string NickName;
    public int PlayerId;
    public int TeamId;
    public int IsSpectator;
    public bool IsInOfficialMode;
    public int LadderRanking;
    public int SpectatorStatus;
    public int Flags;

    // Flags
    public int ForceSpectator;
    public bool IsReferee;
    public bool IsPodiumReady;
    public bool IsUsingStereoscopy;
    public bool IsManagedByAnOtherServer;
    public bool IsServer;
    public bool HasPlayerSlot;
    public bool IsBroadcasting;
    public bool HasJoinedGame;

    // SpectatorStatus
    public bool Spectator;
    public bool TemporarySpectator;
    public bool PureSpectator;
    public bool AutoTarget;
    public int CurrentTargetId;
}

Kick/Ban/Blacklist/Ignore(mute) Players

All the functions returns a boolean indicating whether the operation was successful or not.

Kick Player:

bool KickAsync(string login, string message=null)

Ban Player:

bool BanAsync(string login, string message=null)

Unban Player:

bool UnBanAsync(string login)

Blacklist Player:

bool BlackListAsync(string login)

Remove from Blacklist:

bool UnBlackListAsync(string login)

Ignore (mute) Player:

bool IgnoreAsync(string login)

Unignore (unmute) Player:

bool UnIgnoreAsync(string login)

Send chat messages

There are two ways to send a chat message, with or without the server name.

With server name

bool ChatSendAsync(string message)

Without server name

bool ChatSendServerMessageAsync(string message)

Set Server Password

bool SetServerPasswordAsync(string password)

Multicall

Multicall is a technique to send several calls in the same payload and get back one response for all the calls. This can avoid round-trip times for each call when you need to do multiple smaller calls. Sometimes this saves saves several seconds. The client have implemented support for this. To perform a multicall you first need to create a multicall with the MultiCall builder:

MultiCall multicall = new();

multicall.Add(client.GetChatLinesAsync)
         .Add("system.methodHelp", "SetApiVersion")
         .Add(nameof(client.GetVersionAsync))
         .Add("NonExistentMethod");

The multicall class supports the builder pattern and there are several ways to add a call. Arguments to the methods can be passed like normally in the Add method. Executing the multicall is done with the MultiCallAsync method:

object[] results = await client.MultiCallAsync(multicall);

Due to the nature of XML-RPC in that it can return different value types, the MultiCallAsync returns an object array as each result. They are properly converted but it's up to the programmer to cast then to the correct type.

If a fault occured the result will be of type XmlRpcFault containing fault information.

Callbacks

You can also subscribe to callbacks from the server. To subscribe to any callback you can create a listener to the OnAnyCallback event:

client.OnAnyCallback += Client_OnAnyCallback;

// .
// . 
// .

private static Task Client_OnAnyCallback(MethodCall call, object[] pars) {
    // code to react on callback ...
    
    return Task.CompletedTask;
}

There are also implemented special events for some types of callbacks that you can listen to:

Task OnPlayerConnect(string login, bool isSpectator);
Task OnPlayerDisconnect(string login, string reason);
Task OnPlayerChat(int playerUid, string login, string text, bool isRegisteredCmd);
Task OnEcho(string internalParam, string publicParam);
Task OnBeginMatch(SPlayerRanking[] rankings, int winnerTeam);
Task OnEndMatch(SPlayerRanking[] rankings, int winnerTeam);
Task OnBeginMap(SMapInfo map);
Task OnEndMap(SMapInfo map);
Task OnStatusChanged(int statusCode, string statusName);
Task OnPlayerInfoChanged(SPlayerInfo playerInfo);

These are documented and explained in the reference/code.

Enable Callbacks

Before you can listen to callbacks, you must first tell the server to enable this. GbxRemote.NET provides a easy method that does this for you:

await client.EnableCallbackTypeAsync();

The method can also enable different types of callbacks if you chose so by providing an argument.

ModeScript Functions

ModeScript is a feature in GBXRemote to interact with the functionality of game modes and maniascript on the server. These functions have special callbacks and is called through the TriggerModeScript* methods. Due to way it is set up, you must call a ModeScript method through one of these methods and wait for the response in a callback. GbxRemote.NET tries to simplify this a bit by providing a method that can call a ModeScript method and wait for a response all in one:

Task<JObject> GetModeScriptResponseAsync(string method, params string[] args)

ModeScript returns responses in JSON, so you will get a JObject back from Json.NET which holds the response. So for example, let's say you want to get a list of callbacks and print them:

JObject ret = await client.GetModeScriptResponseAsync("XmlRpc.GetCallbacksList")

foreach (string callback in ret["callbacks"].Values<string>())
                Console.WriteLine($"- {callback}");

The complete ModeScript documentation can be found here.

ModeScript Callbacks

You can listen to any ModeScript callbacks by creating a listener for the OnModeScriptCallback event.

Documentation

Library reference and full documentation is currently being worked on and will be released soon. In the meantime, all methods are documented in the code.

Contributing

If you have any questions, issues, bugs or suggestions, don't hesitate create open an Issue! You can also join our Discord for questions.

You may also help with development by creating a pull request, but please create a new branch first.