mirror of
https://github.com/sbrl/Nibriboard.git
synced 2018-01-10 21:33:49 +00:00
Finish fixing bugs in the core message handling system. It works, more or less! :D
This commit is contained in:
parent
690abc6445
commit
e71ff31ef2
12 changed files with 244 additions and 27 deletions
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
using SBRL.Utilities;
|
||||
|
||||
namespace Nibriboard.Client.Messages
|
||||
{
|
||||
|
@ -11,7 +12,7 @@ namespace Nibriboard.Client.Messages
|
|||
/// <summary>
|
||||
/// The absolute cursor position.
|
||||
/// </summary>
|
||||
public Point AbsCursorPosition;
|
||||
public Vector2 AbsCursorPosition;
|
||||
|
||||
public CursorPositionMessage()
|
||||
{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
// TODO: In C# you can either have namespaces or types in a namespace - not both.
|
||||
using Nibriboard.Utilities.JsonConverters;
|
||||
|
||||
using SBRL.Utilities;
|
||||
using SBRL.Utilities.JsonConverters;
|
||||
|
||||
namespace Nibriboard.Client.Messages
|
||||
{
|
||||
|
@ -13,13 +13,12 @@ namespace Nibriboard.Client.Messages
|
|||
/// The initial visible area on the client's screen.
|
||||
/// Very useful for determining which chunks we should send a client when they first connect.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(RectangleConverter))]
|
||||
public Rectangle InitialViewport = Rectangle.Empty;
|
||||
public Rectangle InitialViewport = Rectangle.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The initial position of the user's cursor.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(RectangleConverter))]
|
||||
public Point InitialAbsCursorPosition = Point.Empty;
|
||||
public Vector2 InitialAbsCursorPosition = Vector2.Zero;
|
||||
|
||||
public HandshakeRequestMessage()
|
||||
{
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using IotWeb.Common.Http;
|
||||
using Newtonsoft.Json;
|
||||
using SBRL.Utilities;
|
||||
using Nibriboard.Client.Messages;
|
||||
using Newtonsoft.Json;
|
||||
using System.Reflection;
|
||||
using RippleSpace;
|
||||
|
||||
namespace Nibriboard.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// A delegate that is used in the event that is fired when a nibri client disconnects.
|
||||
/// </summary>
|
||||
public delegate void NibriDisconnectedEvent(NibriClient disconnectedClient);
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single client connected to the ripple-space on this Nibriboard server.
|
||||
/// </summary>
|
||||
|
@ -41,6 +45,12 @@ namespace Nibriboard.Client
|
|||
["handshakeRequest"] = typeof(HandshakeRequestMessage)
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Whether this nibri client is still connected.
|
||||
/// </summary>
|
||||
public bool Connected = true;
|
||||
public event NibriDisconnectedEvent Disconnected;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this client has completed the handshake yet or not.
|
||||
/// </summary>
|
||||
|
@ -54,12 +64,12 @@ namespace Nibriboard.Client
|
|||
/// The current area that this client is looking at.
|
||||
/// </summary>
|
||||
/// <value>The current view port.</value>
|
||||
public Rectangle CurrentViewPort { get; private set; } = Rectangle.Empty;
|
||||
public Rectangle CurrentViewPort { get; private set; } = Rectangle.Zero;
|
||||
/// <summary>
|
||||
/// The absolute position in plane-space of this client's cursor.
|
||||
/// </summary>
|
||||
/// <value>The absolute cursor position.</value>
|
||||
public Point AbsoluteCursorPosition { get; private set; } = Point.Empty;
|
||||
public Vector2 AbsoluteCursorPosition { get; private set; } = Vector2.Zero;
|
||||
|
||||
#region Core Setup & Message Routing Logic
|
||||
|
||||
|
@ -81,8 +91,8 @@ namespace Nibriboard.Client
|
|||
|
||||
//Task.Run(async () => await onMessage(frame)).Wait();
|
||||
};
|
||||
|
||||
|
||||
// Store whether this NibriClient is still connected or not
|
||||
client.ConnectionClosed += (WebSocket socket) => Connected = false;
|
||||
}
|
||||
|
||||
private async Task handleMessage(string frame)
|
||||
|
@ -107,7 +117,7 @@ namespace Nibriboard.Client
|
|||
|
||||
string handlerMethodName = "handle" + decodedMessage.GetType().Name;
|
||||
Type clientType = this.GetType();
|
||||
MethodInfo handlerInfo = clientType.GetMethod(handlerMethodName);
|
||||
MethodInfo handlerInfo = clientType.GetMethod(handlerMethodName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
await (Task)handlerInfo.Invoke(this, new object[] { decodedMessage });
|
||||
}
|
||||
|
||||
|
@ -129,7 +139,10 @@ namespace Nibriboard.Client
|
|||
/// <param name="message">The message to send.</param>
|
||||
public void SendRaw(string message)
|
||||
{
|
||||
client.Send(Encoding.UTF8.GetBytes(message));
|
||||
if (!Connected)
|
||||
throw new InvalidOperationException($"[NibriClient]{Id}] Can't send a message as the client has disconnected.");
|
||||
|
||||
client.Send(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -49,10 +49,16 @@ namespace Nibriboard.Client
|
|||
public void Connected(WebSocket newSocket)
|
||||
{
|
||||
NibriClient client = new NibriClient(this, newSocket);
|
||||
client.Disconnected += handleDisconnection; // Clean up when the client disconnects
|
||||
|
||||
Clients.Add(client);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message to all the connected clients, except the one who's sending it.
|
||||
/// </summary>
|
||||
/// <param name="sendingClient">The client sending the message.</param>
|
||||
/// <param name="message">The message that is to bee sent.</param>
|
||||
public void Broadcast(NibriClient sendingClient, Message message)
|
||||
{
|
||||
foreach(NibriClient client in Clients)
|
||||
|
@ -64,5 +70,14 @@ namespace Nibriboard.Client
|
|||
client.Send(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean up after a client disconnects from the server.
|
||||
/// </summary>
|
||||
/// <param name="disconnectedClient">The client that has disconnected.</param>
|
||||
private void handleDisconnection(NibriClient disconnectedClient)
|
||||
{
|
||||
Clients.Remove(disconnectedClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@ class RippleLink extends EventEmitter$1
|
|||
this.websocket.addEventListener("message", this.handleMessage.bind(this));
|
||||
this.websocket.addEventListener("close", this.handleDisconnection.bind(this));
|
||||
|
||||
// Close the socket correctly
|
||||
window.addEventListener("beforeunload", (function(event) {
|
||||
this.websocket.close();
|
||||
}).bind(this));
|
||||
}
|
||||
|
||||
handleConnection(event) {
|
||||
|
|
|
@ -20,6 +20,10 @@ class RippleLink extends EventEmitter
|
|||
this.websocket.addEventListener("message", this.handleMessage.bind(this));
|
||||
this.websocket.addEventListener("close", this.handleDisconnection.bind(this));
|
||||
|
||||
// Close the socket correctly
|
||||
window.addEventListener("beforeunload", (function(event) {
|
||||
this.websocket.close();
|
||||
}).bind(this));
|
||||
}
|
||||
|
||||
handleConnection(event) {
|
||||
|
|
|
@ -77,8 +77,10 @@
|
|||
<Compile Include="Client\Messages\CursorPositionMessage.cs" />
|
||||
<Compile Include="Client\Messages\ClientStateMessage.cs" />
|
||||
<Compile Include="RippleSpace\ClientState.cs" />
|
||||
<Compile Include="Utilities\JsonConverters\RectangleConverter.cs" />
|
||||
<Compile Include="Utilities\JsonConverters\PointConverter.cs" />
|
||||
<Compile Include="Utilities\JsonConverters\RectangleJsonConverter.cs" />
|
||||
<Compile Include="Utilities\Rectangle.cs" />
|
||||
<Compile Include="Utilities\Vector2.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="ClientFiles\index.html" />
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
using SBRL.Utilities;
|
||||
|
||||
namespace RippleSpace
|
||||
{
|
||||
|
@ -26,11 +27,11 @@ namespace RippleSpace
|
|||
/// <summary>
|
||||
/// The size and position of the client's viewport.
|
||||
/// </summary>
|
||||
public Rectangle Viewport = Rectangle.Empty;
|
||||
public Rectangle Viewport = Rectangle.Zero;
|
||||
/// <summary>
|
||||
/// The absolute position of the client's cursor.
|
||||
/// </summary>
|
||||
public Point AbsCursorPosition = Point.Empty;
|
||||
public Vector2 AbsCursorPosition = Vector2.Zero;
|
||||
|
||||
public ClientState()
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@ using System.Drawing;
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Nibriboard.Utilities.JsonConverters
|
||||
namespace SBRL.Utilities.JsonConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// Deserialises objects into points from the System.Drawing namespace.
|
||||
|
|
|
@ -4,12 +4,12 @@ using System.Drawing;
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Nibriboard.Utilities.JsonConverters
|
||||
namespace SBRL.Utilities.JsonConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// Deserialises objects into rectangles from the System.Drawing namespace.
|
||||
/// </summary>
|
||||
public class RectangleConverter : JsonConverter
|
||||
public class RectangleJsonConverter : JsonConverter
|
||||
{
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
115
Nibriboard/Utilities/Rectangle.cs
Normal file
115
Nibriboard/Utilities/Rectangle.cs
Normal file
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace SBRL.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a rectangle in 2D space.
|
||||
/// </summary>
|
||||
public struct Rectangle
|
||||
{
|
||||
/// <summary>
|
||||
/// A rectangle with all it's properties initialised to zero.
|
||||
/// </summary>
|
||||
public static Rectangle Zero = new Rectangle() { X = 0, Y = 0, Width = 0, Height = 0 };
|
||||
|
||||
#region Core Data
|
||||
/// <summary>
|
||||
/// The X coordinate of the rectangle.
|
||||
/// </summary>
|
||||
public int X { get; set; }
|
||||
/// <summary>
|
||||
/// The Ycoordinateof the rectangle.
|
||||
/// </summary>
|
||||
/// <value>The y.</value>
|
||||
public int Y { get; set; }
|
||||
/// <summary>
|
||||
/// The width of the rectangle.
|
||||
/// </summary>
|
||||
public int Width { get; set; }
|
||||
/// <summary>
|
||||
/// The height of the rectangle.
|
||||
/// </summary>
|
||||
public int Height { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Corners
|
||||
/// <summary>
|
||||
/// The top-left corner of the rectangle.
|
||||
/// </summary>
|
||||
public Point TopLeft {
|
||||
get {
|
||||
return new Point(X, Y);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The top-right corner of the rectangle.
|
||||
/// </summary>
|
||||
public Point TopRight {
|
||||
get {
|
||||
return new Point(X + Width, Y);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The bottom-left corner of the rectangle.
|
||||
/// </summary>
|
||||
public Point BottomLeft {
|
||||
get {
|
||||
return new Point(X, Y + Height);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The bottom-right corner of the rectangle.
|
||||
/// </summary>
|
||||
public Point BottomRight {
|
||||
get {
|
||||
return new Point(X + Width, Y + Height);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Edges
|
||||
/// <summary>
|
||||
/// The Y coordinate of the top of the rectangle.
|
||||
/// </summary>
|
||||
public int Top {
|
||||
get {
|
||||
return Y;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The Y coordinate of the bottom of the rectangle.
|
||||
/// </summary>
|
||||
public int Bottom {
|
||||
get {
|
||||
return Y + Width;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The X coordinate of the left side of the rectangle.
|
||||
/// </summary>
|
||||
public int Left {
|
||||
get {
|
||||
return X;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The X coordinate of the right side of the rectangle.
|
||||
/// </summary>
|
||||
public int Right {
|
||||
get {
|
||||
return X + Width;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public Rectangle(int x, int y, int width, int height)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
63
Nibriboard/Utilities/Vector2.cs
Normal file
63
Nibriboard/Utilities/Vector2.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
|
||||
namespace SBRL.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single point in 2D space.
|
||||
/// May also be used to represent a direction with a magnitude.
|
||||
/// </summary>
|
||||
public struct Vector2
|
||||
{
|
||||
/// <summary>
|
||||
/// A Vector 2 with all it's proeprties initialised to zero.
|
||||
/// </summary>
|
||||
public static Vector2 Zero = new Vector2() { X = 0, Y = 0 };
|
||||
|
||||
/// <summary>
|
||||
/// The X coordinate.
|
||||
/// </summary>
|
||||
public int X { get; set; }
|
||||
/// <summary>
|
||||
/// The Y coordinate.
|
||||
/// </summary>
|
||||
public int Y { get; set; }
|
||||
|
||||
|
||||
public Vector2(int x, int y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
|
||||
public Vector2 Add(Vector2 b)
|
||||
{
|
||||
return new Vector2(
|
||||
X + b.X,
|
||||
Y + b.X
|
||||
);
|
||||
}
|
||||
public Vector2 Subtract(Vector2 b)
|
||||
{
|
||||
return new Vector2(
|
||||
X - b.X,
|
||||
Y - b.X
|
||||
);
|
||||
}
|
||||
public Vector2 Divide(int b)
|
||||
{
|
||||
return new Vector2(
|
||||
X / b,
|
||||
Y / b
|
||||
);
|
||||
}
|
||||
public Vector2 Multiply(int b)
|
||||
{
|
||||
return new Vector2(
|
||||
X * b,
|
||||
Y * b
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue