diff options
| -rw-r--r-- | Drawable.cs | 2 | ||||
| -rw-r--r-- | Main.cs | 2 | ||||
| -rw-r--r-- | Net.cs | 17 | ||||
| -rw-r--r-- | NetClient.cs | 29 | ||||
| -rw-r--r-- | NetServer.cs | 18 | ||||
| -rw-r--r-- | Oneko.cs | 32 | ||||
| -rw-r--r-- | OnekoLocal.cs | 36 | ||||
| -rw-r--r-- | OnekoNet.cs | 46 |
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(); } @@ -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); @@ -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() { @@ -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 |
