summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Bradley <git@sarahduck.ca>2023-12-16 21:15:14 -0800
committerSarah Bradley <git@sarahduck.ca>2023-12-16 21:15:14 -0800
commit217c93639fc6dee3222e0a3724dd5ed67b34f412 (patch)
tree8a1373b2bf41e329b78d888aabea59745546aab8
parentdbba03fe210a80f7d89d3ad021ec901a9196a537 (diff)
Network Oneko position!
-rw-r--r--Drawable.cs2
-rw-r--r--Main.cs2
-rw-r--r--Net.cs17
-rw-r--r--NetClient.cs29
-rw-r--r--NetServer.cs18
-rw-r--r--Oneko.cs32
-rw-r--r--OnekoLocal.cs36
-rw-r--r--OnekoNet.cs46
8 files changed, 147 insertions, 35 deletions
diff --git a/Drawable.cs b/Drawable.cs
index f6e5e1b..0f89de9 100644
--- a/Drawable.cs
+++ b/Drawable.cs
@@ -19,7 +19,7 @@ abstract class Drawable : IDisposable
public static void DrawAll()
{
float delta = Raylib.GetFrameTime();
- foreach (Drawable drawable in Drawables.OrderBy(d => -d.Position.Y)) {
+ foreach (Drawable drawable in Drawables.OrderBy(d => d.Position.Y)) {
drawable?.Update(delta);
drawable?.Draw();
}
diff --git a/Main.cs b/Main.cs
index 85306ec..b281710 100644
--- a/Main.cs
+++ b/Main.cs
@@ -24,7 +24,7 @@ static class OnekoOnline
Raylib.InitWindow(640, 480, "OnekoOnline");
Raylib.SetTargetFPS(30);
- Oneko LocalOneko = new();
+ OnekoLocal LocalOneko = new();
RenderTexture2D RenderTexture = Raylib.LoadRenderTexture(320,240);
diff --git a/Net.cs b/Net.cs
index b99a0f6..83b6b26 100644
--- a/Net.cs
+++ b/Net.cs
@@ -1,4 +1,5 @@
using System.Buffers.Binary;
+using System.Numerics;
using LiteNetLib.Utils;
namespace OnekoOnline.Net;
@@ -32,12 +33,25 @@ public static class NetExtensions
writer.Reset(size+PacketInfo.SizeOf);
writer.Put(info);
}
+
+ public static void Put(this NetDataWriter writer, Vector2 vec2)
+ {
+ writer.Put(vec2.X);
+ writer.Put(vec2.Y);
+ }
+
+ public static Vector2 GetVector2(this NetDataReader reader)
+ {
+ float X = reader.GetFloat();
+ float Y = reader.GetFloat();
+ return new Vector2(X, Y);
+ }
}
public enum PacketType : byte
{
MousePosition,
- OnekoState,
+ OnekoTargetPosition,
OnekoSpritesheet,
Username,
UserId,
@@ -84,6 +98,7 @@ public struct PacketInfo
class User(int id)
{
public readonly int Id = id;
+ public bool Initialized = false;
//Oneko Stuff
public byte[]? SpriteSheet;
diff --git a/NetClient.cs b/NetClient.cs
index 65fd484..f7d14a1 100644
--- a/NetClient.cs
+++ b/NetClient.cs
@@ -17,6 +17,11 @@ class Client
readonly Dictionary<int, User> users = [];
public ReadOnlyDictionary<int, User> Users => users.AsReadOnly();
+ static public Action<User>? UserConnected;
+ static public Action<User>? UserDisconnected;
+ static public Action<NetDataReader, User, PacketType>? PacketRecived;
+ static public Action? ServerDisconnected;
+
public Client(string ServerAddress, int port, string ServerPassword)
{
if (ServerAddress == "") throw new Exception("Server Address invalid!");
@@ -32,7 +37,7 @@ class Client
NetDataWriter writer = new();
writer.Put(new PacketInfo(PacketType.OnekoSpritesheet, Id));
- writer.Put(Oneko.LocalOneko!.SpriteSheet.Serialize());
+ writer.Put(OnekoLocal.Instance!.SpriteSheet.Serialize());
peer.Send(writer, DeliveryMethod.ReliableUnordered);
writer.ResetWithInfo(new PacketInfo(PacketType.Username, Id));
@@ -40,6 +45,12 @@ class Client
peer.Send(writer, DeliveryMethod.ReliableUnordered);
};
+ Listener.PeerDisconnectedEvent += (peer, info) => {
+ ServerDisconnected?.Invoke();
+ users.Clear();
+ Console.WriteLine("Server Disconnected! You're offline!");
+ };
+
Listener.NetworkReceiveEvent += (fromPeer, reader, channel, DeliveryMethod) => {
if (reader.AvailableBytes < PacketInfo.SizeOf) return;
PacketInfo info = reader.GetPacketInfo();
@@ -56,15 +67,25 @@ class Client
}
if (info.Type == PacketType.Disconnect) {
+ //Disconnect user that has disconnected
if (from.Username != null) Console.WriteLine($"User {from.Username} left.");
users.Remove(info.FromId);
+ UserDisconnected?.Invoke(from);
+ return;
}
- if (info.Type == PacketType.OnekoSpritesheet) from.SpriteSheet = reader.GetRemainingBytes();
- if (info.Type == PacketType.Username) {
- from.Username = reader.GetString();
+ else if (info.Type == PacketType.OnekoSpritesheet) from.SpriteSheet = reader.GetRemainingBytes();
+ else if (info.Type == PacketType.Username) from.Username = reader.GetString();
+
+ if (from.ExchangedData && !from.Initialized) {
+ //Announce user connection
Console.WriteLine($"User {from.Username} joined!");
+ from.Initialized = true;
+ UserConnected?.Invoke(from);
}
+
+ NetDataReader newReader = new(reader.GetRemainingBytes());
+ PacketRecived?.Invoke(newReader, from, info.Type);
};
}
diff --git a/NetServer.cs b/NetServer.cs
index a0910ba..c2c626a 100644
--- a/NetServer.cs
+++ b/NetServer.cs
@@ -51,12 +51,14 @@ class Server
if (info.Type == PacketType.OnekoSpritesheet) user.SpriteSheet = dataReader.GetRemainingBytes();
else if (info.Type == PacketType.Username) user.Username = dataReader.GetString(64);
- if (user.ExchangedData && !user.sentId) {
- NetDataWriter writer = new();
+ NetDataWriter writer = new();
+
+ if (user.ExchangedData && !user.Initialized) {
//Send ID
+ writer.ResetWithInfo(new PacketInfo(PacketType.UserId, -1));
writer.Put(user.Id);
fromPeer.Send(writer, DeliveryMethod.ReliableUnordered);
- user.sentId = true;
+ user.Initialized = true;
Console.WriteLine($"{fromPeer.EndPoint} is {user.Username}!");
@@ -83,6 +85,15 @@ class Server
toSend.Peer.Send(writer, DeliveryMethod.ReliableUnordered);
}
}
+
+ if (info.Type == PacketType.OnekoTargetPosition || info.Type == PacketType.MousePosition) {
+ writer.ResetWithInfo(new PacketInfo(info.Type, fromPeer.Id));
+ writer.Put(dataReader.GetRemainingBytes());
+ foreach (ServerUser toSend in users.Values) {
+ if (!toSend.ExchangedData || toSend == user) continue;
+ toSend.Peer.Send(writer, DeliveryMethod);
+ }
+ }
};
Console.WriteLine("Server Initialized!");
@@ -103,7 +114,6 @@ class ServerUser(int id, NetPeer peer) : User(id), IDisposable
{
//Network
public readonly NetPeer Peer = peer;
- public bool sentId = false;
public void Dispose()
{
diff --git a/Oneko.cs b/Oneko.cs
index a3d0a1c..3b9c5bc 100644
--- a/Oneko.cs
+++ b/Oneko.cs
@@ -1,5 +1,4 @@
using System.Numerics;
-using OnekoOnline.Net;
using Raylib_cs;
namespace OnekoOnline;
@@ -7,17 +6,13 @@ namespace OnekoOnline;
class Oneko : Drawable
{
public readonly Bitmap SpriteSheet;
- Vector2 TargetPosition;
+ protected Vector2 TargetPosition;
OnekoAnimation Animation = ScratchSelf;
float updateTimer = 0f;
const float updateRate = 1f/5f;
int Frame = 0;
- public static Oneko? LocalOneko;
-
- public static Dictionary<int, Oneko> NetNekos = [];
-
public Oneko()
{
Size = new(32,32);
@@ -32,8 +27,6 @@ class Oneko : Drawable
SpriteSheet = Bitmap.FromPNGMemory(EmbeddedResources.GetResource("oneko.png"));
}
- LocalOneko ??= this;
-
Drawables.Add(this);
}
@@ -53,31 +46,22 @@ class Oneko : Drawable
public override void Update(float delta)
{
- if (this == LocalOneko) {
- foreach (User user in OnekoOnline.Client!.Users.Values) {
- if (user.ExchangedData && !NetNekos.ContainsKey(user.Id)) {
- Bitmap spriteSheet = Bitmap.Deserialize(user.SpriteSheet);
- NetNekos.Add(user.Id, new Oneko(spriteSheet));
- }
- }
- }
-
updateTimer += delta;
if (updateTimer < updateRate) return;
- if (Raylib.IsWindowFocused()) {
- TargetPosition = Raylib.GetMousePosition()/2;
- } else {
- TargetPosition = new Vector2(320/2, 240/2);
- }
+ OnekoUpdate(delta);
+
+ updateTimer = 0f;
+ }
+
+ public virtual void OnekoUpdate(float delta)
+ {
Vector2 TargetDirection = (TargetPosition-Position).LimitLength(10f);
if (TargetDirection.Length() > 1) Animation = GetDirectionalRun(TargetDirection);
else Animation = Idle;
Position += TargetDirection;
Frame = (Frame + 1) % 2;
-
- updateTimer = 0f;
}
public override void Dispose()
diff --git a/OnekoLocal.cs b/OnekoLocal.cs
new file mode 100644
index 0000000..64a4c6f
--- /dev/null
+++ b/OnekoLocal.cs
@@ -0,0 +1,36 @@
+using System.Numerics;
+using LiteNetLib.Utils;
+using OnekoOnline.Net;
+using Raylib_cs;
+
+namespace OnekoOnline;
+
+class OnekoLocal : Oneko
+{
+ public static Oneko? Instance;
+
+ static int Id => OnekoOnline.Client?.Id ?? -1;
+
+ public OnekoLocal() : base()
+ {
+ Instance ??= this;
+
+ Client.UserConnected += OnekoNet.SpawnNetNeko;
+ Client.ServerDisconnected += OnekoNet.DisconnectAll;
+ }
+
+ public override void OnekoUpdate(float delta)
+ {
+ if (Raylib.IsWindowFocused()) TargetPosition = Raylib.GetMousePosition()/2;
+ else TargetPosition = new Vector2(320/2, 240/2);
+
+ if (OnekoOnline.Client!.Connected) {
+ NetDataWriter writer = new();
+ writer.Put(new PacketInfo(PacketType.OnekoTargetPosition, Id));
+ writer.Put(TargetPosition);
+ OnekoOnline.Client?.ConnectedServer.Send(writer, LiteNetLib.DeliveryMethod.Unreliable);
+ }
+
+ base.OnekoUpdate(delta);
+ }
+} \ No newline at end of file
diff --git a/OnekoNet.cs b/OnekoNet.cs
new file mode 100644
index 0000000..a7f2d83
--- /dev/null
+++ b/OnekoNet.cs
@@ -0,0 +1,46 @@
+using System.Numerics;
+using OnekoOnline.Net;
+using Raylib_cs;
+
+namespace OnekoOnline;
+
+class OnekoNet : Oneko
+{
+ readonly User MyUser;
+
+ public static Dictionary<int, OnekoNet> NetNekos = [];
+
+ public OnekoNet(Bitmap bitmap, User user) : base(bitmap)
+ {
+ MyUser = user;
+
+ Client.UserDisconnected += disconnectedUser => {
+ if (disconnectedUser == MyUser) Dispose();
+ };
+
+ Client.PacketRecived += (reader, user, packetType) => {
+ if (user != MyUser) return;
+
+ if (packetType == PacketType.OnekoTargetPosition) TargetPosition = reader.GetVector2();
+ };
+ }
+
+ public static void SpawnNetNeko(User user)
+ {
+ if (user.ExchangedData && !NetNekos.ContainsKey(user.Id)) {
+ Bitmap spriteSheet = Bitmap.Deserialize(user.SpriteSheet);
+ NetNekos.Add(user.Id, new OnekoNet(spriteSheet, user));
+ }
+ }
+
+ public override void Dispose()
+ {
+ NetNekos.Remove(MyUser.Id);
+ base.Dispose();
+ }
+
+ public static void DisconnectAll()
+ {
+ foreach (OnekoNet neko in NetNekos.Values) neko.Dispose();
+ }
+} \ No newline at end of file