mine2d/Mine2d/engine/Publisher.cs

125 lines
3.7 KiB
C#

using System.Reflection;
using Mine2d.engine.networking;
using Mine2d.engine.system.annotations;
using Mine2d.game.core.extensions;
namespace Mine2d.engine;
public class Publisher
{
private readonly Dictionary<string, HashSet<Delegate>> subscribers =
new();
private readonly HashSet<string> clientOnlySubscriptions = new();
private readonly HashSet<string> serverSubscriptions = new();
private readonly InteractorKind kind;
public Publisher(InteractorKind kind)
{
this.kind = kind;
this.Scan();
}
private void Scan()
{
var types = Assembly
.GetAssembly(this.GetType())!
.GetTypesSafe();
foreach (var type in types)
{
var classAttrs = type.GetCustomAttributes(typeof(InteractorAttribute), false);
if (classAttrs.Length == 0)
{
continue;
}
var methods = type.GetMethods();
foreach (var method in methods)
{
var methodAttrs = method.GetCustomAttributes(typeof(InteractionAttribute), false);
if (methodAttrs.Length == 0)
{
continue;
}
var attr = (InteractionAttribute)methodAttrs[0];
if (attr.Kind is InteractorKind.Server or InteractorKind.Hybrid)
{
this.serverSubscriptions.Add(attr.Type);
}
if (attr.Kind is InteractorKind.Client)
{
this.clientOnlySubscriptions.Add(attr.Type);
}
if (attr.Kind != this.kind && this.kind != InteractorKind.Hybrid)
{
continue;
}
var del = method.GetParameters().Length == 0 ?
Delegate.CreateDelegate(typeof(Action), method) :
Delegate.CreateDelegate(
typeof(Action<>).MakeGenericTypeSafely(method.GetParameters()[0].ParameterType),
method
);
this.Subscribe(attr.Type, del);
}
}
this.clientOnlySubscriptions.ExceptWith(this.serverSubscriptions);
}
private void Subscribe(string type, Delegate callback)
{
if (!this.subscribers.ContainsKey(type))
{
this.subscribers[type] = new HashSet<Delegate>();
}
this.subscribers[type].Add(callback);
}
public void Dump()
{
foreach (var pair in this.subscribers)
{
Console.WriteLine(pair.Key);
foreach (var del in pair.Value)
{
Console.WriteLine(del);
}
}
}
public void Publish(ValueType packet)
{
var type = PacketUtils.GetType(packet);
if (type != "tick")
{
Console.WriteLine("Publishing packet: " + type);
}
if (this.subscribers.ContainsKey(type))
{
if (type != "tick")
{
Console.WriteLine("Found " + this.subscribers[type].Count + " subscribers");
}
foreach (var del in this.subscribers[type])
{
if (del.Method.GetParameters().Length == 0)
{
del.DynamicInvoke();
}
else
{
del.DynamicInvoke(packet);
}
}
}
}
public bool IsClientOnlyPacket(string type)
{
return this.clientOnlySubscriptions.Contains(type);
}
public bool IsServerPacket(string type)
{
return this.serverSubscriptions.Contains(type);
}
}