using System.Reflection; using Mine2d.engine.extensions; using Mine2d.engine.system.annotations; using Mine2d.game.backend.network.packets; using Mine2d.game.core.extensions; namespace Mine2d.engine; public delegate void InteractionHandler(Packet packet); public class Publisher { private readonly Dictionary> subscribers = new(); private readonly HashSet clientOnlySubscriptions = new(); private readonly HashSet serverSubscriptions = new(); private readonly InteractorKind kind; public Publisher(InteractorKind kind) { Enum.GetValues() .ForEach(type => this.subscribers[type] = new HashSet()); this.kind = kind; this.Scan(); } private void Scan() { Assembly .GetAssembly(this.GetType())! .GetTypesSafe() .Where(t => t.HasAttribute()) .SelectMany(t => t.GetMethods()) .Where(m => m.HasAttribute()) .ForEach(method => { var attribute = method.GetCustomAttribute()!; Console.WriteLine($"Registering interaction method {method.Name} declared in {method.DeclaringType}"); Console.WriteLine($"InteractorKind: {attribute.Kind}"); Console.WriteLine($"PacketType: {attribute.Type}"); switch (attribute.Kind) { case InteractorKind.Hybrid: case InteractorKind.Server: this.serverSubscriptions.Add(attribute.Type); break; case InteractorKind.Client: this.clientOnlySubscriptions.Add(attribute.Type); break; default: throw new ArgumentOutOfRangeException(nameof(attribute.Kind), attribute.Kind, null); } if (attribute.Kind == this.kind || this.kind == InteractorKind.Hybrid) { this.subscribers[attribute.Type].Add(method); Console.WriteLine("Subscribed!"); } Console.WriteLine(); }); } public void Publish(Packet packet) { if (packet.Type != PacketType.Tick) Console.WriteLine($"[{nameof(Publisher)}] Publishing {packet.Type}"); this.subscribers[packet.Type] .ForEach(handler => { var parameterCount = handler.GetParameters().Length; handler.Invoke(null, parameterCount > 0 ? new object[] { packet } : null); }); } public bool IsClientOnlyPacket(Packet packet) => this.clientOnlySubscriptions.Contains(packet.Type); public bool IsServerPacket(Packet packet) => this.serverSubscriptions.Contains(packet.Type); public void Dump() { foreach (var pair in this.subscribers) { Console.WriteLine(pair.Key); foreach (var del in pair.Value) { Console.WriteLine(del); } } } }