using System; using System.Collections.Generic; using NLog; using Ragon.Common; namespace Ragon.Core { public class PluginBase { private delegate void SubscribeDelegate(Player player, ref ReadOnlySpan data); private delegate void SubscribeEntityDelegate(Player player, Entity entity, ref ReadOnlySpan data); private Dictionary _globalEvents = new(); private Dictionary> _entityEvents = new(); private readonly RagonSerializer _serializer = new(); protected GameRoom Room { get; private set; } = null!; protected ILogger Logger = null!; public void Attach(GameRoom gameRoom) { Logger = LogManager.GetLogger($"Plugin<{GetType().Name}>"); Room = gameRoom; _globalEvents.Clear(); _entityEvents.Clear(); } public void Detach() { _globalEvents.Clear(); _entityEvents.Clear(); } public void OnEvent(ushort evntCode, Action action) where T : IRagonSerializable, new() { if (_globalEvents.ContainsKey(evntCode)) { Logger.Warn($"Event subscriber already added {evntCode}"); return; } var data = new T(); _globalEvents.Add(evntCode, (Player player, ref ReadOnlySpan raw) => { if (raw.Length == 0) { Logger.Warn($"Payload is empty for event {evntCode}"); return; } _serializer.Clear(); _serializer.FromSpan(ref raw); data.Deserialize(_serializer); action.Invoke(player, data); }); } public void OnEvent(ushort evntCode, Action action) { if (_globalEvents.ContainsKey(evntCode)) { Logger.Warn($"Event subscriber already added {evntCode}"); return; } _globalEvents.Add(evntCode, (Player player, ref ReadOnlySpan raw) => { action.Invoke(player); }); } public void OnEvent(Entity entity, ushort evntCode, Action action) where T : IRagonSerializable, new() { if (_entityEvents.ContainsKey(entity.EntityId)) { if (_entityEvents[entity.EntityId].ContainsKey(evntCode)) { Logger.Warn($"Event subscriber already added {evntCode} for {entity.EntityId}"); return; } var data = new T(); _entityEvents[entity.EntityId].Add(evntCode, (Player player, Entity ent, ref ReadOnlySpan raw) => { if (raw.Length == 0) { Logger.Warn($"Payload is empty for entity {ent.EntityId} event {evntCode}"); return; } _serializer.Clear(); _serializer.FromSpan(ref raw); data.Deserialize(_serializer); action.Invoke(player, ent, data); }); return; } { var data = new T(); _entityEvents.Add(entity.EntityId, new Dictionary()); _entityEvents[entity.EntityId].Add(evntCode, (Player player, Entity ent, ref ReadOnlySpan raw) => { if (raw.Length == 0) { Logger.Warn($"Payload is empty for entity {ent.EntityId} event {evntCode}"); return; } _serializer.Clear(); _serializer.FromSpan(ref raw); data.Deserialize(_serializer); action.Invoke(player, ent, data); }); } } public void OnEvent(Entity entity, ushort evntCode, Action action) { if (_entityEvents.ContainsKey(entity.EntityId)) { if (_entityEvents[entity.EntityId].ContainsKey(evntCode)) { Logger.Warn($"Event subscriber already added {evntCode} for {entity.EntityId}"); return; } _entityEvents[entity.EntityId].Add(evntCode, (Player player, Entity ent, ref ReadOnlySpan raw) => { action.Invoke(player, ent); }); return; } { _entityEvents.Add(entity.EntityId, new Dictionary()); _entityEvents[entity.EntityId].Add(evntCode, (Player player, Entity ent, ref ReadOnlySpan raw) => { action.Invoke(player, ent); }); } } public void UnsubscribeAll() { _globalEvents.Clear(); _entityEvents.Clear(); } public bool InternalHandle(uint peerId, int entityId, ushort evntCode, ref ReadOnlySpan payload) { if (!_entityEvents.ContainsKey(entityId)) return false; if (!_entityEvents[entityId].ContainsKey(evntCode)) return false; // var player = Room.GetPlayerById(peerId); var entity = Room.GetEntityById(entityId); // _entityEvents[entityId][evntCode].Invoke(player, entity, ref payload); return true; } public bool InternalHandle(uint peerId, ushort evntCode, ref ReadOnlySpan payload) { if (_globalEvents.ContainsKey(evntCode)) { // var player = Room.GetPlayerById(peerId); // _globalEvents[evntCode].Invoke(player, ref payload); return true; } return false; } #region VIRTUAL public virtual void OnPlayerJoined(Player player) { } public virtual void OnPlayerLeaved(Player player) { } public virtual void OnOwnershipChanged(Player player) { } public virtual bool OnEntityCreated(Player player, Entity entity) { return false; } public virtual bool OnEntityDestroyed(Player player, Entity entity) { return false; } public virtual void OnStart() { } public virtual void OnStop() { } #endregion } }