Skip to content

Commit

Permalink
Merge pull request #84 from EvoEsports/83_gbxremoteclient_interface
Browse files Browse the repository at this point in the history
GBXRemoteClient interface to improve mocking functionality
  • Loading branch information
snixtho authored Jul 12, 2023
2 parents 1bf4db7 + e1e3252 commit 511ca20
Show file tree
Hide file tree
Showing 23 changed files with 2,426 additions and 1,588 deletions.
3 changes: 2 additions & 1 deletion src/Examples/CallbackExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Examples.Common;
using GbxRemoteNet;
using GbxRemoteNet.Events;
using GbxRemoteNet.Interfaces;
using GbxRemoteNet.Structs;
using GbxRemoteNet.XmlRpc.Packets;
using Microsoft.Extensions.Logging;
Expand All @@ -17,7 +18,7 @@ internal class Program
private static async Task Main(string[] args)
{
// create client instance
GbxRemoteClient client = new("127.0.0.1", 5001, Logger.New<Program>(LogLevel.Debug));
var client = new GbxRemoteClient("127.0.0.1", 5001, Logger.New<Program>(LogLevel.Debug));

// connect and login
if (!await client.LoginAsync("SuperAdmin", "SuperAdmin"))
Expand Down
146 changes: 27 additions & 119 deletions src/GbxRemote.Net/GbxRemoteClient.Callbacks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading.Tasks;
using GbxRemoteNet.Enums;
using GbxRemoteNet.Events;
using GbxRemoteNet.Interfaces;
using GbxRemoteNet.Structs;
using GbxRemoteNet.XmlRpc;
using GbxRemoteNet.XmlRpc.ExtraTypes;
Expand All @@ -12,125 +13,29 @@ namespace GbxRemoteNet;

public partial class GbxRemoteClient
{
public delegate Task AsyncEventHandler(object sender, EventArgs e);

public delegate Task AsyncEventHandler<TArgs>(object sender, TArgs e);

/// <summary>
/// Triggered for all possible callbacks.
/// </summary>
public event AsyncEventHandler<CallbackGbxEventArgs<object>> OnAnyCallback;

/// <summary>
/// When a player connects to the server.
/// </summary>
public event AsyncEventHandler<PlayerConnectGbxEventArgs> OnPlayerConnect;

/// <summary>
/// When a player disconnects from the server.
/// </summary>
public event AsyncEventHandler<PlayerDisconnectGbxEventArgs> OnPlayerDisconnect;

/// <summary>
/// When a player sends a chat message.
/// </summary>
public event AsyncEventHandler<PlayerChatGbxEventArgs> OnPlayerChat;

/// <summary>
/// When a echo message is sent. Can be used for communication with other.
/// XMLRPC-clients.
/// </summary>
public event AsyncEventHandler<EchoGbxEventArgs> OnEcho;

/// <summary>
/// When the match itself starts, triggered after begin map.
/// </summary>
public event AsyncEventHandler OnBeginMatch;

/// <summary>
/// When the match ends, does not give a lot of info in TM2020.
/// </summary>
public event AsyncEventHandler<EndMatchGbxEventArgs> OnEndMatch;

/// <summary>
/// When the map has loaded on the server.
/// </summary>
public event AsyncEventHandler<MapGbxEventArgs> OnBeginMap;

/// <summary>
/// When the map unloads from the server.
/// </summary>
public event AsyncEventHandler<MapGbxEventArgs> OnEndMap;

/// <summary>
/// When the server status changed.
/// </summary>
public event AsyncEventHandler<StatusChangedGbxEventArgs> OnStatusChanged;

/// <summary>
/// When data about a player changed, it is usually called when
/// a player joins or leaves. Gives you more detailed info about a player.
/// </summary>
public event AsyncEventHandler<PlayerInfoChangedGbxEventArgs> OnPlayerInfoChanged;

/// <summary>
/// When a user triggers the page answer callback from a manialink.
/// </summary>
public event AsyncEventHandler<ManiaLinkPageActionGbxEventArgs> OnPlayerManialinkPageAnswer;

/// <summary>
/// Triggered when the map list changed.
/// </summary>
public event AsyncEventHandler<MapListModifiedGbxEventArgs> OnMapListModified;

/// <summary>
/// When the server is about to start.
/// </summary>
public event AsyncEventHandler OnServerStart;

/// <summary>
/// When the server is about to stop.
/// </summary>
public event AsyncEventHandler OnServerStop;

/// <summary>
/// Tunnel data received from a player.
/// </summary>
public event AsyncEventHandler<TunnelDataGbxEventArgs> OnTunnelDataReceived;

/// <summary>
/// When a current vote has been updated.
/// </summary>
public event AsyncEventHandler<VoteUpdatedGbxEventArgs> OnVoteUpdated;

/// <summary>
/// When a player bill is updated.
/// </summary>
public event AsyncEventHandler<BillUpdatedGbxEventArgs> OnBillUpdated;

/// <summary>
/// When a player changed allies.
/// </summary>
public event AsyncEventHandler<PlayerGbxEventArgs> OnPlayerAlliesChanged;

/// <summary>
/// When a variable from the script cloud is loaded.
/// </summary>
public event AsyncEventHandler<ScriptCloudGbxEventArgs> OnScriptCloudLoadData;

/// <summary>
/// When a variable from the script cloud is saved.
/// </summary>
public event AsyncEventHandler<ScriptCloudGbxEventArgs> OnScriptCloudSaveData;

/// <summary>
/// Enable callbacks. If no parameter is provided,
/// all callbacks are enabled by default.
/// </summary>
/// <param name="gbxCallbackType"></param>
/// <returns></returns>
public async Task EnableCallbackTypeAsync(
GbxCallbackType gbxCallbackType = GbxCallbackType.Internal | GbxCallbackType.ModeScript | GbxCallbackType.Checkpoints)
public event IGbxRemoteClient.AsyncEventHandler<CallbackGbxEventArgs<object>> OnAnyCallback;
public event IGbxRemoteClient.AsyncEventHandler<PlayerConnectGbxEventArgs> OnPlayerConnect;
public event IGbxRemoteClient.AsyncEventHandler<PlayerDisconnectGbxEventArgs> OnPlayerDisconnect;
public event IGbxRemoteClient.AsyncEventHandler<PlayerChatGbxEventArgs> OnPlayerChat;
public event IGbxRemoteClient.AsyncEventHandler<EchoGbxEventArgs> OnEcho;
public event IGbxRemoteClient.AsyncEventHandler OnBeginMatch;
public event IGbxRemoteClient.AsyncEventHandler<EndMatchGbxEventArgs> OnEndMatch;
public event IGbxRemoteClient.AsyncEventHandler<MapGbxEventArgs> OnBeginMap;
public event IGbxRemoteClient.AsyncEventHandler<MapGbxEventArgs> OnEndMap;
public event IGbxRemoteClient.AsyncEventHandler<StatusChangedGbxEventArgs> OnStatusChanged;
public event IGbxRemoteClient.AsyncEventHandler<PlayerInfoChangedGbxEventArgs> OnPlayerInfoChanged;
public event IGbxRemoteClient.AsyncEventHandler<ManiaLinkPageActionGbxEventArgs> OnPlayerManialinkPageAnswer;
public event IGbxRemoteClient.AsyncEventHandler<MapListModifiedGbxEventArgs> OnMapListModified;
public event IGbxRemoteClient.AsyncEventHandler OnServerStart;
public event IGbxRemoteClient.AsyncEventHandler OnServerStop;
public event IGbxRemoteClient.AsyncEventHandler<TunnelDataGbxEventArgs> OnTunnelDataReceived;
public event IGbxRemoteClient.AsyncEventHandler<VoteUpdatedGbxEventArgs> OnVoteUpdated;
public event IGbxRemoteClient.AsyncEventHandler<BillUpdatedGbxEventArgs> OnBillUpdated;
public event IGbxRemoteClient.AsyncEventHandler<PlayerGbxEventArgs> OnPlayerAlliesChanged;
public event IGbxRemoteClient.AsyncEventHandler<ScriptCloudGbxEventArgs> OnScriptCloudLoadData;
public event IGbxRemoteClient.AsyncEventHandler<ScriptCloudGbxEventArgs> OnScriptCloudSaveData;

public async Task EnableCallbackTypeAsync(GbxCallbackType gbxCallbackType)
{
if (gbxCallbackType.HasFlag(GbxCallbackType.Internal))
await EnableCallbacksAsync(true);
Expand All @@ -140,6 +45,9 @@ public async Task EnableCallbackTypeAsync(
await TriggerModeScriptEventArrayAsync("Trackmania.Event.SetCurLapCheckpointsMode", "always");
}

public Task EnableCallbackTypeAsync() =>
EnableCallbackTypeAsync(GbxCallbackType.ModeScript | GbxCallbackType.Internal | GbxCallbackType.Checkpoints);

private async Task InternalInvokeEventsAsync(Delegate[]? invocationList, EventArgs e)
{
if (invocationList == null)
Expand Down
89 changes: 13 additions & 76 deletions src/GbxRemote.Net/GbxRemoteClient.Methods.Chat.cs
Original file line number Diff line number Diff line change
@@ -1,157 +1,94 @@
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Threading.Tasks;
using GbxRemoteNet.Structs;
using GbxRemoteNet.XmlRpc;

namespace GbxRemoteNet;

/// <summary>
/// Method Category: Chat
/// Method Category: Chat
/// </summary>
public partial class GbxRemoteClient
{
/// <summary>
/// Send a text message to all clients without the server login. Only available to Admin.
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public async Task<bool> ChatSendServerMessageAsync(string message)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatSendServerMessage", message)
);
}

/// <summary>
/// Send a localised text message to all clients without the server login, or optionally to a Login (which can be a
/// single login or a list of comma-separated logins). The parameter is an array of structures {Lang='xx', Text='...'}.
/// If no matching language is found, the last text in the array is used. Only available to Admin.
/// </summary>
/// <param name="lang"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<bool> ChatSendServerMessageToLanguageAsync(TmLanguage[] lang, string message)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatSendServerMessage", lang, message)
);
}

/// <summary>
/// Send a text message without the server login to the client with the specified PlayerId. Only available to Admin.
/// </summary>
/// <param name="message"></param>
/// <param name="loginId"></param>
/// <returns></returns>
public async Task<bool> ChatSendServerMessageToIdAsync(string message, int loginId)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatSendServerMessageToId", message, loginId)
);
}

/// <summary>
/// Send a text message without the server login to the client with the specified login. Login can be a single login or
/// a list of comma-separated logins. Only available to Admin.
/// </summary>
/// <param name="message"></param>
/// <param name="playerLogins"></param>
/// <returns></returns>
public async Task<bool> ChatSendServerMessageToLoginAsync(string message, string playerLogins)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatSendServerMessageToLogin", message, playerLogins)
);
}

/// <summary>
/// Send a text message to all clients. Only available to Admin.
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public Task<bool> ChatSendServerMessageToLoginAsync(string message, IEnumerable<string> playerLogins) =>
ChatSendServerMessageToLoginAsync(message, string.Join(',', playerLogins));

public async Task<bool> ChatSendAsync(string message)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatSend", message)
);
}

/// <summary>
/// Send a localised text message to all clients, or optionally to a Login (which can be a single login or a list of
/// comma-separated logins). The parameter is an array of structures {Lang='xx', Text='...'}. If no matching language
/// is found, the last text in the array is used. Only available to Admin.
/// </summary>
/// <param name="lang"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<bool> ChatSendToLanguageAsync(TmLanguage[] lang, string message)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatSendToLanguage", lang, message)
);
}

/// <summary>
/// Send a text message to the client with the specified login. Login can be a single login or a list of
/// comma-separated logins. Only available to Admin.
/// </summary>
/// <param name="message"></param>
/// <param name="playerLogins"></param>
/// <returns></returns>
public async Task<bool> ChatSendToLoginAsync(string message, string playerLogins)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatSendToLogin", message, playerLogins)
);
}

/// <summary>
/// Send a text message to the client with the specified PlayerId. Only available to Admin.
/// </summary>
/// <param name="message"></param>
/// <param name="playerId"></param>
/// <returns></returns>
public Task<bool> ChatSendToLoginAsync(string message, IEnumerable<string> playerLogins) =>
ChatSendToLoginAsync(message, string.Join(',', playerLogins));

public async Task<bool> ChatSendToIdAsync(string message, int playerId)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatSendToId", message, playerId)
);
}

/// <summary>
/// Returns the last chat lines. Maximum of 40 lines. Only available to Admin.
/// </summary>
/// <returns></returns>
public async Task<string[]> GetChatLinesAsync()
{
return (string[]) XmlRpcTypes.ToNativeValue<string>(
await CallOrFaultAsync("GetChatLines")
);
}

/// <summary>
/// The chat messages are no longer dispatched to the players, they only go to the rpc callback and the controller has
/// to manually forward them. The second (optional) parameter allows all messages from the server to be automatically
/// forwarded. Only available to Admin.
/// </summary>
/// <param name="enable"></param>
/// <param name="forward"></param>
/// <returns></returns>
public async Task<bool> ChatEnableManualRoutingAsync(bool enable=true, bool forward=false)
public async Task<bool> ChatEnableManualRoutingAsync(bool enable, bool forward)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
await CallOrFaultAsync("ChatEnableManualRouting", enable, forward)
);
}

/// <summary>
/// (Text, SenderLogin, DestLogin) Send a text message to the specified DestLogin (or everybody if empty) on behalf of
/// SenderLogin. DestLogin can be a single login or a list of comma-separated logins. Only available if manual routing
/// is enabled. Only available to Admin.
/// </summary>
/// <param name="text"></param>
/// <param name="senderLogin"></param>
/// <param name="destinationLogin"></param>
/// <returns></returns>
public Task<bool> ChatEnableManualRoutingAsync() =>
ChatEnableManualRoutingAsync(true, false);

public async Task<bool> ChatForwardToLoginAsync(string text, string senderLogin, string destinationLogin)
{
return (bool) XmlRpcTypes.ToNativeValue<bool>(
Expand Down
Loading

0 comments on commit 511ca20

Please sign in to comment.