Skip to content

Commit

Permalink
Updated Unity package to v0.8.1
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-weiland committed Nov 14, 2021
1 parent 4587036 commit 631f946
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
<Exec Condition="'$(IncludeTransport)' == 'yes'" Command="if $(ConfigurationName) == Release xcopy $(ProjectDir)$(OutDir)$(TargetName).dll $(SolutionDir)..\Demos\Unity\Server\Assets\Scripts\Multiplayer\$(TargetName).dll /y&#xD;&#xA;if $(ConfigurationName) == Release xcopy $(ProjectDir)$(OutDir)$(TargetName).xml $(SolutionDir)..\Demos\Unity\Server\Assets\Scripts\Multiplayer\$(TargetName).xml /y&#xD;&#xA;&#xD;&#xA;if $(ConfigurationName) == Release xcopy $(ProjectDir)$(OutDir)$(TargetName).dll $(SolutionDir)..\Demos\Unity\Client\Assets\Scripts\Multiplayer\$(TargetName).dll /y&#xD;&#xA;if $(ConfigurationName) == Release xcopy $(ProjectDir)$(OutDir)$(TargetName).xml $(SolutionDir)..\Demos\Unity\Client\Assets\Scripts\Multiplayer\$(TargetName).xml /y" />
<Copy SourceFiles="@(UPMSourceFiles)" DestinationFiles="@(UPMSourceFiles->'$(SolutionDir)..\UnityPackage\Runtime\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(SolutionDir)..\License.md" DestinationFiles="$(SolutionDir)..\UnityPackage\License.md" SkipUnchangedFiles="true" />
<Copy SourceFiles="$(SolutionDir)..\README.md" DestinationFiles="$(SolutionDir)..\UnityPackage\README.md" SkipUnchangedFiles="true" />
</Target>

</Project>
25 changes: 1 addition & 24 deletions UnityPackage/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1 @@
<div align="center">
<img src="https://user-images.githubusercontent.com/51303091/119734159-690afc00-be2f-11eb-9673-c1f998025a3e.png" width="20%" height="auto">
</div>
<h1 align="center">RiptideNetworking - C# Networking Library</h1>

RUDP (Reliable UDP) networking solution built in C#, primarily intended for use in multiplayer games. Features an unreliable channel (regular UDP) as well as a reliable channel (UDP with loss detection). Works in Unity & console apps alike.

## Getting Started
Grab the RiptideNetworking.dll file (and RiptideNetworking.xml file for intellisense documentation) from the <a href="https://github.com/tom-weiland/RiptideNetworking/releases/latest">latest release</a> and drop it in your Unity project.

## Usage
Check out the <a href="https://github.com/tom-weiland/RiptideNetworking/tree/main/Demos">demos</a> to see how to set up the basics.

## License
Distributed under the MIT license. See <a href="https://github.com/tom-weiland/RiptideNetworking/blob/main/License.md">License.md</a> for more information.

---

<p align="center">
<a href="https://tomweiland.net/youtube">YouTube</a>&emsp;<b>•</b>&emsp;<a href="https://discord.com/invite/tomweiland">Discord</a><br>
<a href="https://ko-fi.com/Y8Y21O02J">
<img src="https://www.ko-fi.com/img/githubbutton_sm.svg">
</a>
</p>
Riptide Networking provides functionality for sending data back and forth in multiplayer games.
61 changes: 42 additions & 19 deletions UnityPackage/Runtime/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,30 @@ namespace RiptideNetworking
/// <summary>A client that can connect to a <see cref="Server"/>.</summary>
public class Client : Common
{
/// <summary>Invoked when a connection to the server is established.</summary>
/// <inheritdoc cref="IClient.Connected"/>
public event EventHandler Connected;
/// <summary>Invoked when a connection to the server fails to be established.</summary>
/// <remarks>This occurs when a connection request times out, either because no server is listening on the expected IP and port, or because something (firewall, antivirus, no/poor internet access, etc.) is preventing the connection.</remarks>
/// <inheritdoc cref="IClient.ConnectionFailed"/>
public event EventHandler ConnectionFailed;
/// <summary>Invoked when a message is received from the server.</summary>
/// <inheritdoc cref="IClient.MessageReceived"/>
public event EventHandler<ClientMessageReceivedEventArgs> MessageReceived;
/// <summary>Invoked when disconnected by the server.</summary>
/// <inheritdoc cref="IClient.Disconnected"/>
public event EventHandler Disconnected;
/// <summary>Invoked when a new client connects.</summary>
/// <inheritdoc cref="IClient.ClientConnected"/>
public event EventHandler<ClientConnectedEventArgs> ClientConnected;
/// <summary>Invoked when a client disconnects.</summary>
/// <inheritdoc cref="IClient.ClientDisconnected"/>
public event EventHandler<ClientDisconnectedEventArgs> ClientDisconnected;

/// <summary>The numeric ID of the client.</summary>
/// <inheritdoc cref="IConnectionInfo.Id"/>
public ushort Id => client.Id;
/// <summary>The round trip time of the connection. -1 if not calculated yet.</summary>
/// <inheritdoc cref="IConnectionInfo.RTT"/>
public short RTT => client.RTT;
/// <summary>The smoothed round trip time of the connection. -1 if not calculated yet.</summary>
/// <inheritdoc cref="IConnectionInfo.SmoothRTT"/>
public short SmoothRTT => client.SmoothRTT;
/// <summary>Whether or not the client is currently in the process of connecting.</summary>
/// <inheritdoc cref="IConnectionInfo.IsNotConnected"/>
public bool IsNotConnected => client.IsNotConnected;
/// <inheritdoc cref="IConnectionInfo.IsConnecting"/>
public bool IsConnecting => client.IsConnecting;
/// <summary>Whether or not the client is currently connected.</summary>
/// <inheritdoc cref="IConnectionInfo.IsConnected"/>
public bool IsConnected => client.IsConnected;
/// <inheritdoc/>
public override bool ShouldOutputInfoLogs
Expand Down Expand Up @@ -64,9 +65,9 @@ public void Connect(string hostAddress, byte messageHandlerGroupId = 0)
CreateMessageHandlersDictionary(Assembly.GetCallingAssembly(), messageHandlerGroupId);

client.Connected += Connected;
client.ConnectionFailed += ConnectionFailed;
client.ConnectionFailed += OnConnectionFailed;
client.MessageReceived += OnMessageReceived;
client.Disconnected += Disconnected;
client.Disconnected += OnDisconnected;
client.ClientConnected += ClientConnected;
client.ClientDisconnected += ClientDisconnected;
client.Connect(hostAddress);
Expand All @@ -87,6 +88,12 @@ protected override void CreateMessageHandlersDictionary(Assembly assembly, byte
if (attribute.GroupId != messageHandlerGroupId)
break;

if (!methods[i].IsStatic)
{
RiptideLogger.Log("ERROR", $"Message handler methods should be static, but '{methods[i].DeclaringType}.{methods[i].Name}' is an instance method!");
break;
}

Delegate clientMessageHandler = Delegate.CreateDelegate(typeof(MessageHandler), methods[i], false);
if (clientMessageHandler != null)
{
Expand All @@ -101,24 +108,26 @@ protected override void CreateMessageHandlersDictionary(Assembly assembly, byte
// It's not a message handler for Client instances, but it might be one for Server instances
Delegate serverMessageHandler = Delegate.CreateDelegate(typeof(Server.MessageHandler), methods[i], false);
if (serverMessageHandler == null)
RiptideLogger.Log("ERROR", $"Method '{methods[i].Name}' didn't match any acceptable message handler signatures, double-check its parameters!");
RiptideLogger.Log("ERROR", $"'{methods[i].DeclaringType}.{methods[i].Name}' doesn't match any acceptable message handler method signatures, double-check its parameters!");
}
}
}

/// <inheritdoc/>
public override void Tick() => client.Tick();

/// <summary>Sends a message to the server.</summary>
/// <param name="message">The message to send.</param>
/// <param name="maxSendAttempts">How often to try sending <paramref name="message"/> before giving up. Only applies to messages with their <see cref="Message.SendMode"/> set to <see cref="MessageSendMode.reliable"/>.</param>
/// <param name="shouldRelease">Whether or not <paramref name="message"/> should be returned to the pool once its data has been sent.</param>
/// <inheritdoc cref="IClient.Send(Message, byte, bool)"/>
public void Send(Message message, byte maxSendAttempts = 15, bool shouldRelease = true) => client.Send(message, maxSendAttempts, shouldRelease);

/// <summary>Disconnects from the server.</summary>
public void Disconnect()
{
client.Disconnect();
LocalDisconnect();
}

private void LocalDisconnect()
{
client.Connected -= Connected;
client.ConnectionFailed -= ConnectionFailed;
client.MessageReceived -= OnMessageReceived;
Expand All @@ -127,6 +136,13 @@ public void Disconnect()
client.ClientDisconnected -= ClientDisconnected;
}

/// <summary>Invokes the <see cref="ConnectionFailed"/> event.</summary>
private void OnConnectionFailed(object s, EventArgs e)
{
LocalDisconnect();
ConnectionFailed?.Invoke(this, e);
}

/// <summary>Invokes the <see cref="MessageReceived"/> event and initiates handling of the received message.</summary>
private void OnMessageReceived(object s, ClientMessageReceivedEventArgs e)
{
Expand All @@ -137,5 +153,12 @@ private void OnMessageReceived(object s, ClientMessageReceivedEventArgs e)
else
RiptideLogger.Log("ERROR", $"No handler method (type: client) found for message ID {e.MessageId}!");
}

/// <summary>Invokes the <see cref="Disconnected"/> event.</summary>
private void OnDisconnected(object s, EventArgs e)
{
LocalDisconnect();
Disconnected?.Invoke(this, e);
}
}
}
8 changes: 4 additions & 4 deletions UnityPackage/Runtime/Common.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
using System.Reflection;
using RiptideNetworking.Transports;
using System.Reflection;

namespace RiptideNetworking
{
/// <summary>Contains shared functionality for <see cref="Server"/> and <see cref="Client"/>.</summary>
public abstract class Common
{
/// <summary>Whether or not to output informational log messages. Error-related log messages ignore this setting.</summary>
/// <inheritdoc cref="ICommon.ShouldOutputInfoLogs"/>
public abstract bool ShouldOutputInfoLogs { get; set; }

/// <summary>Searches the given assembly for methods with the <see cref="MessageHandlerAttribute"/> and adds them to the dictionary of handler methods.</summary>
/// <param name="assembly">The assembly to search for methods with the <see cref="MessageHandlerAttribute"/>.</param>
/// <param name="messageHandlerGroupId">The ID of the group of message handler methods to use when building the message handlers dictionary.</param>
protected abstract void CreateMessageHandlersDictionary(Assembly assembly, byte messageHandlerGroupId);

/// <summary>Initiates handling of currently queued messages.</summary>
/// <remarks>This should generally be called from within a regularly executed update loop (like FixedUpdate in Unity). Messages will continue to be received in between calls, but won't be handled fully until this method is executed.</remarks>
/// <inheritdoc cref="ICommon.Tick"/>
public abstract void Tick();
}
}
4 changes: 2 additions & 2 deletions UnityPackage/Runtime/MessageHandlerAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ namespace RiptideNetworking
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class MessageHandlerAttribute : Attribute
{
/// <summary>The ID of the message type that this method is meant to handle.</summary>
/// <inheritdoc cref="messageId"/>
public ushort MessageId => messageId;
/// <summary>The ID of the group of message handlers this method belongs to.</summary>
/// <inheritdoc cref="groupId"/>
public byte GroupId => groupId;

/// <summary>The ID of the message type that this method is meant to handle.</summary>
Expand Down
43 changes: 18 additions & 25 deletions UnityPackage/Runtime/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,22 @@ namespace RiptideNetworking
/// <summary>A server that can accept connections from <see cref="Client"/>s.</summary>
public class Server : Common
{
/// <summary>Invoked when a new client connects.</summary>
/// <inheritdoc cref="IServer.ClientConnected"/>
public event EventHandler<ServerClientConnectedEventArgs> ClientConnected;
/// <summary>Invoked when a message is received from a client.</summary>
/// <inheritdoc cref="IServer.MessageReceived"/>
public event EventHandler<ServerMessageReceivedEventArgs> MessageReceived;
/// <summary>Invoked when a client disconnects.</summary>
/// <inheritdoc cref="IServer.ClientDisconnected"/>
public event EventHandler<ClientDisconnectedEventArgs> ClientDisconnected;

/// <summary>Whether or not the server is currently running.</summary>
public bool IsRunning { get; private set; }
/// <summary>The local port that the server is running on.</summary>
/// <inheritdoc cref="IServer.Port"/>
public ushort Port => server.Port;
/// <summary>An array of all the currently connected clients.</summary>
/// <remarks>The position of each <see cref="IConnectionInfo"/> instance in the array does <i>not</i> correspond to that client's numeric ID (except by coincidence).</remarks>
/// <inheritdoc cref="IServer.Clients"/>
public IConnectionInfo[] Clients => server.Clients;
/// <summary>The maximum number of clients that can be connected at any time.</summary>
/// <inheritdoc cref="IServer.MaxClientCount"/>
public ushort MaxClientCount => server.MaxClientCount;
/// <summary>The number of currently connected clients.</summary>
/// <inheritdoc cref="IServer.ClientCount"/>
public int ClientCount => server.ClientCount;
/// <inheritdoc/>
public override bool ShouldOutputInfoLogs
Expand Down Expand Up @@ -78,6 +77,12 @@ protected override void CreateMessageHandlersDictionary(Assembly assembly, byte
if (attribute.GroupId != messageHandlerGroupId)
break;

if (!methods[i].IsStatic)
{
RiptideLogger.Log("ERROR", $"Message handler methods should be static, but '{methods[i].DeclaringType}.{methods[i].Name}' is an instance method!");
break;
}

Delegate clientMessageHandler = Delegate.CreateDelegate(typeof(MessageHandler), methods[i], false);
if (clientMessageHandler != null)
{
Expand All @@ -92,36 +97,24 @@ protected override void CreateMessageHandlersDictionary(Assembly assembly, byte
// It's not a message handler for Server instances, but it might be one for Client instances
Delegate serverMessageHandler = Delegate.CreateDelegate(typeof(Client.MessageHandler), methods[i], false);
if (serverMessageHandler == null)
RiptideLogger.Log("ERROR", $"Method '{methods[i].Name}' didn't match any acceptable message handler signatures, double-check its parameters!");
RiptideLogger.Log("ERROR", $"'{methods[i].DeclaringType}.{methods[i].Name}' doesn't match any acceptable message handler method signatures, double-check its parameters!");
}
}
}

/// <inheritdoc/>
public override void Tick() => server.Tick();

/// <summary>Sends a message to a specific client.</summary>
/// <param name="message">The message to send.</param>
/// <param name="toClientId">The numeric ID of the client to send the message to.</param>
/// <param name="maxSendAttempts">How often to try sending <paramref name="message"/> before giving up. Only applies to messages with their <see cref="Message.SendMode"/> set to <see cref="MessageSendMode.reliable"/>.</param>
/// <param name="shouldRelease">Whether or not <paramref name="message"/> should be returned to the pool once its data has been sent.</param>
/// <inheritdoc cref="IServer.Send(Message, ushort, byte, bool)"/>
public void Send(Message message, ushort toClientId, byte maxSendAttempts = 15, bool shouldRelease = true) => server.Send(message, toClientId, maxSendAttempts, shouldRelease);

/// <summary>Sends a message to all conected clients.</summary>
/// <param name="message">The message to send.</param>
/// <param name="maxSendAttempts">How often to try sending <paramref name="message"/> before giving up. Only applies to messages with their <see cref="Message.SendMode"/> set to <see cref="MessageSendMode.reliable"/>.</param>
/// <param name="shouldRelease">Whether or not <paramref name="message"/> should be returned to the pool once its data has been sent.</param>
/// <inheritdoc cref="IServer.SendToAll(Message, byte, bool)"/>
public void SendToAll(Message message, byte maxSendAttempts = 15, bool shouldRelease = true) => server.SendToAll(message, maxSendAttempts, shouldRelease);

/// <summary>Sends a message to all connected clients except one.</summary>
/// <param name="message">The message to send.</param>
/// <param name="exceptToClientId">The numeric ID of the client to <i>not</i> send the message to.</param>
/// <param name="maxSendAttempts">How often to try sending <paramref name="message"/> before giving up. Only applies to messages with their <see cref="Message.SendMode"/> set to <see cref="MessageSendMode.reliable"/>.</param>
/// <param name="shouldRelease">Whether or not <paramref name="message"/> should be returned to the pool once its data has been sent.</param>
/// <inheritdoc cref="IServer.SendToAll(Message, ushort, byte, bool)"/>
public void SendToAll(Message message, ushort exceptToClientId, byte maxSendAttempts = 15, bool shouldRelease = true) => server.SendToAll(message, exceptToClientId, maxSendAttempts, shouldRelease);

/// <summary>Kicks a specific client.</summary>
/// <param name="clientId">The numeric ID of the client to kick.</param>
/// <inheritdoc cref="IServer.DisconnectClient(ushort)"/>
public void DisconnectClient(ushort clientId) => server.DisconnectClient(clientId);

/// <summary>Stops the server.</summary>
Expand Down
Loading

0 comments on commit 631f946

Please sign in to comment.