Esempio n. 1
0
 public TeleportOptions(IOpenModComponent instance, int delay, bool cancelOnMove, bool cancelOnDamage)
 {
     Instance       = instance;
     Delay          = delay;
     CancelOnMove   = cancelOnMove;
     CancelOnDamage = cancelOnDamage;
 }
Esempio n. 2
0
 public OpenModComponentCommandSource(ILogger logger, IOpenModComponent openModComponent, Assembly assembly)
 {
     m_Logger           = logger;
     m_OpenModComponent = openModComponent;
     Commands           = new List <ICommandRegistration>();
     ScanAssemblyForCommmmands(assembly);
 }
Esempio n. 3
0
        public virtual void Subscribe(IOpenModComponent component, string eventName, EventCallback callback)
        {
            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            if (string.IsNullOrEmpty(eventName))
            {
                throw new ArgumentException(eventName);
            }

            if (!component.IsComponentAlive)
            {
                return;
            }

            var attribute = GetEventListenerAttribute(callback.Method);

            m_EventSubscriptions.Add(new EventSubscription(component, callback.Invoke, attribute, eventName, component.LifetimeScope.BeginLifetimeScopeEx()));
        }
Esempio n. 4
0
        public virtual void Subscribe(IOpenModComponent component, Assembly assembly)
        {
            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }

            if (!component.IsComponentAlive)
            {
                return;
            }

            List <(Type eventListenerType, MethodInfo method, EventListenerAttribute eventListenerAttribute, Type eventType)> eventListeners = new List <(Type, MethodInfo, EventListenerAttribute, Type)>();
            var scope = component.LifetimeScope.BeginLifetimeScopeEx((builder =>
            {
                foreach (var type in assembly.FindTypes <IEventListener>())
                {
                    if (m_EventSubscriptions.Any(c => c.EventListener == type))
                    {
                        // Prevent duplicate registration
                        return;
                    }

                    // ReSharper disable once LoopCanBeConvertedToQuery
                    foreach (var @interface in type.GetInterfaces().Where(c => typeof(IEventListener).IsAssignableFrom(c) && c.GetGenericArguments().Length > 0))
                    {
                        var interfaceMethod = @interface.GetMethods().Single();
                        if (interfaceMethod.DeclaringType == null)
                        {
                            continue;
                        }

                        var map = type.GetInterfaceMap(interfaceMethod.DeclaringType);
                        var index = Array.IndexOf(map.InterfaceMethods, interfaceMethod);

                        var method = map.TargetMethods[index];
                        var handler = GetEventListenerAttribute(method);
                        var eventType = @interface.GetGenericArguments()[0];
                        eventListeners.Add((type, method, handler, eventType));
                    }

                    var lifetime = type.GetCustomAttribute <EventListenerLifetimeAttribute>()?.Lifetime ?? ServiceLifetime.Transient;

                    builder.RegisterType(type)
                    .As(type)
                    .WithLifetime(lifetime)
                    .OwnedByLifetimeScope();
                }
            }));

            foreach (var eventListener in eventListeners)
            {
                m_EventSubscriptions.Add(new EventSubscription(component, eventListener.eventListenerType, eventListener.method, eventListener.eventListenerAttribute, eventListener.eventType, scope));
            }
        }
Esempio n. 5
0
        public virtual IDisposable Subscribe <TEvent>(IOpenModComponent component, EventCallback <TEvent> callback) where TEvent : IEvent
        {
            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            if (!component.IsComponentAlive)
            {
                m_Logger.LogDebug($"{component.OpenModComponentId} tried to subscribe a callback but the component is not alive.");
                return(NullDisposable.Instance);
            }

            var attribute = GetEventListenerAttribute(callback.Method);

            var subscription = new EventSubscription(component,
                                                     (serviceProvider, sender, @event) => callback.Invoke(serviceProvider, sender, (TEvent)@event),
                                                     attribute, typeof(TEvent), component.LifetimeScope.BeginLifetimeScopeEx());

            m_EventSubscriptions.Add(subscription);
            return(new DisposeAction(() =>
            {
                m_EventSubscriptions.Remove(subscription);
            }));
        }
Esempio n. 6
0
        public virtual async Task EmitAsync(IOpenModComponent component, object sender, IEvent @event, EventExecutedCallback callback = null)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            m_Logger.LogTrace($"Emitting event: {@event.Name}");
            var eventSubscriptions
                = m_EventSubscriptions
                  .Where(c => (c.EventType != null && c.EventType.IsInstanceOfType(@event)) ||
                         (@event.Name.Equals(c.EventName, StringComparison.OrdinalIgnoreCase) &&
                          c.Owner.IsAlive && ((IOpenModComponent)c.Owner.Target).IsComponentAlive))
                  .ToList();


            void Complete()
            {
                m_Logger.LogTrace($"{@event.Name}: Finished.");
                callback?.Invoke(@event);
            }

            if (eventSubscriptions.Count == 0)
            {
                m_Logger?.LogTrace($"{@event.Name}: No listeners found.");
                Complete();
                return;
            }

            var comparer = new PriorityComparer(PriortyComparisonMode.LowestFirst);

            eventSubscriptions.Sort((a, b) => comparer.Compare(a.EventListenerAttribute.Priority, b.EventListenerAttribute.Priority));

            foreach (var group in eventSubscriptions.GroupBy(e => e.Scope))
            {
                await using var newScope = group.Key.BeginLifetimeScope("AutofacWebRequest");
                foreach (var subscription in group)
                {
                    if (@event is ICancellableEvent cancellableEvent &&
                        cancellableEvent.IsCancelled &&
                        !subscription.EventListenerAttribute.IgnoreCancelled)
                    {
                        continue;
                    }

                    var serviceProvider = newScope.Resolve <IServiceProvider>();

                    try
                    {
                        await subscription.Callback.Invoke(serviceProvider, sender, @event);
                    }
                    catch (Exception ex)
                    {
                        m_Logger.LogError(ex, $"Exception occured during event {@event.Name}");
                    }
                }
            }

            Complete();
        }
Esempio n. 7
0
        public virtual IDisposable Subscribe(IOpenModComponent component, string eventName, EventCallback callback)
        {
            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            if (string.IsNullOrEmpty(eventName))
            {
                throw new ArgumentException(eventName);
            }

            if (!component.IsComponentAlive)
            {
                m_Logger.LogDebug($"{component.OpenModComponentId} tried to subscribe a callback but the component is not alive.");
                return(NullDisposable.Instance);
            }

            var attribute    = GetEventListenerAttribute(callback.Method);
            var subscription = new EventSubscription(component, callback.Invoke, attribute, eventName, component.LifetimeScope.BeginLifetimeScopeEx());

            m_EventSubscriptions.Add(subscription);
            return(new DisposeAction(() =>
            {
                m_EventSubscriptions.Remove(subscription);
            }));
        }
Esempio n. 8
0
        public virtual void Subscribe(IOpenModComponent component, Assembly assembly)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            List <(Type eventListenerType, MethodInfo method, EventListenerAttribute eventListenerAttribute, Type eventType)> eventListeners = new List <(Type, MethodInfo, EventListenerAttribute, Type)>();
            var scope = component.LifetimeScope.BeginLifetimeScope((builder =>
            {
                foreach (var type in assembly.FindTypes <IEventListener>(false))
                {
                    if (m_EventSubscriptions.Any(c => c.EventListener == type))
                    {
                        // Prevent duplicate registration
                        return;
                    }

                    // ReSharper disable once LoopCanBeConvertedToQuery
                    foreach (var @interface in type.GetInterfaces().Where(c => typeof(IEventListener <>).IsAssignableFrom(c) && c.GetGenericArguments().Length >= 1))
                    {
                        var method = @interface.GetMethods().Single();
                        var handler = GetEventListenerAttribute(method);
                        var eventType = @interface.GetGenericArguments()[0];
                        eventListeners.Add((type, method, handler, eventType));
                    }

                    var lifetime = type.GetCustomAttribute <EventListenerLifetimeAttribute>()?.Lifetime ?? ServiceLifetime.Transient;

                    var registrationBuilder = builder.RegisterType(type)
                                              .As(type)
                                              .OwnedByLifetimeScope();

                    switch (lifetime)
                    {
                    case ServiceLifetime.Singleton:
                        registrationBuilder.SingleInstance();
                        break;

                    case ServiceLifetime.Scoped:
                        registrationBuilder.InstancePerLifetimeScope();
                        break;

                    case ServiceLifetime.Transient:
                        registrationBuilder.InstancePerRequest();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }));

            foreach (var eventListener in eventListeners)
            {
                m_EventSubscriptions.Add(new EventSubscription(component, eventListener.eventListenerType, eventListener.method, eventListener.eventListenerAttribute, eventListener.eventType, scope));
            }
        }
Esempio n. 9
0
        public IPermissionRegistration FindPermission(IOpenModComponent component, string permission)
        {
            if (!component.IsComponentAlive || !m_PermissionRegistrations.ContainsKey(component))
            {
                return(null);
            }

            return(m_PermissionRegistrations[component].FirstOrDefault(d => d.Permission.Equals(permission, StringComparison.OrdinalIgnoreCase)));
        }
Esempio n. 10
0
        public virtual void Unsubscribe(IOpenModComponent component, Type eventType)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            m_EventSubscriptions.RemoveAll(c => (!c.Owner.IsAlive || c.Owner.Target == component) && (c.EventType == eventType || c.EventName.Equals(eventType.Name, StringComparison.OrdinalIgnoreCase)));
        }
Esempio n. 11
0
        public IReadOnlyCollection <IPermissionRegistration> GetPermissions(IOpenModComponent component)
        {
            if (!component.IsComponentAlive || !m_PermissionRegistrations.ContainsKey(component))
            {
                return(new List <IPermissionRegistration>());
            }

            return(m_PermissionRegistrations[component].AsReadOnly());
        }
Esempio n. 12
0
        public virtual void Unsubscribe <TEvent>(IOpenModComponent component) where TEvent : IEvent
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            m_EventSubscriptions.RemoveAll(c => (!c.Owner.IsAlive || c.Owner.Target == component) && (c.EventType == typeof(TEvent) || c.EventName.Equals(typeof(TEvent).Name, StringComparison.OrdinalIgnoreCase)));
        }
Esempio n. 13
0
        public virtual void Unsubscribe(IOpenModComponent component)
        {
            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            m_EventSubscriptions.RemoveAll(c => !c.Owner.IsAlive || c.Owner.Target == component);
        }
Esempio n. 14
0
        public virtual void Unsubscribe(IOpenModComponent component, Type eventType)
        {
            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            m_EventSubscriptions.RemoveAll(c => (!c.Owner.IsAlive || c.Owner.Target == component) && (c.EventType == eventType || c.EventName.Equals(eventType.Name, StringComparison.OrdinalIgnoreCase)));
        }
Esempio n. 15
0
        public virtual void Unsubscribe(IOpenModComponent component)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            m_EventSubscriptions.RemoveAll(c => !c.Owner.IsAlive || c.Owner.Target == component);
        }
Esempio n. 16
0
 public UnturnedCommandRegistration(IOpenModComponent component, Command cmd)
 {
     Component   = component;
     Cmd         = cmd;
     Name        = cmd.command.ToLower(CultureInfo.InvariantCulture);
     Syntax      = string.Join(" ", cmd.info.Split(' ').Skip(1)); /* skip first word in info, which is the command */
     Description = cmd.help;
     Aliases     = new List <string>();
     Id          = cmd.GetType().FullName;
 }
Esempio n. 17
0
 public UnturnedCommandRegistration(IOpenModComponent component, Command cmd)
 {
     Component   = component;
     Cmd         = cmd;
     Name        = cmd.command;
     Syntax      = cmd.help;
     Description = cmd.info;
     Aliases     = new List <string>();
     Id          = cmd.GetType().FullName;
 }
Esempio n. 18
0
        public virtual async Task EmitAsync(IOpenModComponent component, object sender, IEvent @event, EventExecutedCallback callback = null)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            m_Logger.LogTrace($"Emitting event: {@event.Name}");
            var eventSubscriptions
                = m_EventSubscriptions
                  .Where(c => (c.EventType != null && c.EventType.IsInstanceOfType(@event)) ||
                         (@event.Name.Equals(c.EventName, StringComparison.OrdinalIgnoreCase) &&
                          c.Owner.IsAlive && ((IOpenModComponent)c.Owner.Target).IsComponentAlive))
                  .ToList();


            void Complete()
            {
                m_Logger.LogTrace($"{@event.Name}: Finished.");
                callback?.Invoke(@event);
            }

            if (eventSubscriptions.Count == 0)
            {
                m_Logger?.LogTrace($"{@event.Name}: No listeners found.");
                Complete();
                return;
            }

            var comparer = new PriorityComparer(PriortyComparisonMode.LowestFirst);

            eventSubscriptions.Sort((a, b) => comparer.Compare(a.EventListenerAttribute.Priority, b.EventListenerAttribute.Priority));

            foreach (var subscription in eventSubscriptions)
            {
                var owner = subscription.Owner;
                if (!owner.IsAlive || !((IOpenModComponent)owner.Target).IsComponentAlive)
                {
                    m_EventSubscriptions.Remove(subscription);
                    continue;
                }

                if (@event is ICancellableEvent cancellableEvent &&
                    cancellableEvent.IsCancelled &&
                    !subscription.EventListenerAttribute.IgnoreCancelled)
                {
                    continue;
                }

                var serviceProvider = subscription.Scope.Resolve <IServiceProvider>();
                await subscription.Callback.Invoke(serviceProvider, sender, @event);
            }

            Complete();
        }
Esempio n. 19
0
        public virtual void Subscribe <TEvent>(IOpenModComponent component, EventCallback <TEvent> callback) where TEvent : IEvent
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            var attribute = GetEventListenerAttribute(callback.Method);

            m_EventSubscriptions.Add(new EventSubscription(component, (serviceProvider, sender, @event) => callback.Invoke(serviceProvider, sender, (TEvent)@event), attribute, typeof(TEvent), component.LifetimeScope.BeginLifetimeScope()));
        }
Esempio n. 20
0
        public virtual void Subscribe(IOpenModComponent component, Type eventType, EventCallback callback)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            var attribute = GetEventListenerAttribute(callback.Method);

            m_EventSubscriptions.Add(new EventSubscription(component, callback.Invoke, attribute, eventType, component.LifetimeScope.BeginLifetimeScope()));
        }
Esempio n. 21
0
        private void RegisterComponentPermissions(IOpenModComponent component, Assembly?assembly = null)
        {
            assembly ??= component.GetType().Assembly;

            var attribs = assembly.GetCustomAttributes <RegisterPermissionAttribute>();

            foreach (var attrib in attribs)
            {
                m_PermissionRegistry.RegisterPermission(component, attrib.Permission, attrib.Description,
                                                        attrib.DefaultGrant);
            }
        }
Esempio n. 22
0
 public EventSubscription(
     IOpenModComponent ownerComponent,
     EventCallback callback,
     EventListenerAttribute attribute,
     string eventName,
     ILifetimeScope scope)
 {
     Owner    = new WeakReference(ownerComponent);
     Callback = callback;
     EventListenerAttribute = attribute;
     EventName = eventName;
     Scope     = scope;
 }
Esempio n. 23
0
        public IDisposable AddChangeWatcher(string key, IOpenModComponent component, Action onChange)
        {
            var filePath = GetFilePathForKey(key);

            var directory = Path.GetDirectoryName(filePath);

            if (directory == null)
            {
                throw new Exception("Unable to retrieve directory info for file");
            }

            var fileName = Path.GetFileName(filePath);

            lock (GetLock(filePath))
            {
                var pair = new KeyValuePair <IOpenModComponent, Action>(component, onChange);

                m_ChangeListeners.Add(pair);
                var idx = m_ChangeListeners.Count - 1;

                if (idx == 0)
                {
                    // first element, start watcher
                    m_FileSystemWatcher                     = new FileSystemWatcher(directory, fileName);
                    m_FileSystemWatcher.Changed            += (s, a) => OnFileChange(filePath);
                    m_FileSystemWatcher.EnableRaisingEvents = true;
                }

                return(new DisposeAction(() =>
                {
                    lock (GetLock(filePath))
                    {
                        m_ChangeListeners.Remove(pair);

                        if (m_ChangeListeners.Count == 0 && m_FileSystemWatcher != null)
                        {
                            m_FileSystemWatcher.Dispose();
                            m_FileSystemWatcher = null;
                        }
                    }
                }));
            }
        }
Esempio n. 24
0
 public EventSubscription(
     IOpenModComponent ownerComponent,
     Type eventListener,
     MethodBase method,
     EventListenerAttribute attribute,
     Type eventType,
     ILifetimeScope scope)
 {
     Owner         = new WeakReference(ownerComponent);
     EventListener = eventListener;
     Callback      = (serviceProvider, sender, @event) =>
     {
         var listener = serviceProvider.GetRequiredService(eventListener);
         return(method.InvokeWithTaskSupportAsync(listener, new[] { sender, @event }));
     };
     EventListenerAttribute = attribute;
     EventName = eventType.Name;
     EventType = eventType;
     Scope     = scope;
 }
Esempio n. 25
0
        public void RegisterPermission(
            IOpenModComponent component,
            string permission,
            string description = null,
            PermissionGrantResult?defaultGrant = null)
        {
            if (!m_PermissionRegistrations.ContainsKey(component))
            {
                m_PermissionRegistrations.Add(component, new List <PermissionRegistration>());
            }

            var list = m_PermissionRegistrations[component];

            list.RemoveAll(d => d.Permission.Equals(permission, StringComparison.OrdinalIgnoreCase));
            list.Add(new PermissionRegistration
            {
                Owner        = component,
                DefaultGrant = defaultGrant ?? PermissionGrantResult.Default,
                Description  = string.IsNullOrEmpty(description) ? null : description,
                Permission   = permission
            });
        }
Esempio n. 26
0
        public IDisposable AddChangeWatcher(string key, IOpenModComponent component, Action onChange)
        {
            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            if (onChange == null)
            {
                throw new ArgumentNullException(nameof(onChange));
            }

            CheckKeyValid(key);
            RegisterKnownKey(key);

            var filePath  = GetFilePathForKey(key);
            var directory = Path.GetDirectoryName(filePath);

            if (directory == null)
            {
                throw new Exception($"Unable to retrieve directory info for file: {filePath}");
            }

            var @lock = GetLock(key);

            lock (@lock)
            {
                var changeListener = new RegisteredChangeListener(component, key, onChange);
                m_ChangeListeners.Add(changeListener);

                return(new DisposeAction(() =>
                {
                    lock (@lock)
                    {
                        m_ChangeListeners.Remove(changeListener);
                    }
                }));
            }
        }
Esempio n. 27
0
        public virtual async Task EmitAsync(IOpenModComponent component, object sender, IEvent @event,
                                            EventExecutedCallback callback = null)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            var eventTypes = new List <Type>();

            var currentType = @event.GetType();

            while (currentType != null && typeof(IEvent).IsAssignableFrom(currentType))
            {
                eventTypes.Add(currentType);
                currentType = currentType.BaseType;
            }

            eventTypes.AddRange(@event.GetType().GetInterfaces().Where(d => typeof(IEvent).IsAssignableFrom(d)));

            foreach (var eventType in eventTypes.Except(s_OmittedTypes))
            {
                string eventName = GetEventName(eventType);

                m_Logger.LogTrace($"Emitting event: {eventName}");
                var eventSubscriptions
                    = m_EventSubscriptions
                      .Where(c => (c.EventType != null && c.EventType == eventType) ||
                             (eventName.Equals(c.EventName, StringComparison.OrdinalIgnoreCase) &&
                              c.Owner.IsAlive && ((IOpenModComponent)c.Owner.Target).IsComponentAlive))
                      .ToList();


                if (eventSubscriptions.Count == 0)
                {
                    continue;
                }

                var comparer = new PriorityComparer(PriortyComparisonMode.LowestFirst);
                eventSubscriptions.Sort((a, b) =>
                                        comparer.Compare(
                                            (Priority)a.EventListenerAttribute.Priority,
                                            (Priority)b.EventListenerAttribute.Priority)
                                        );

                foreach (var group in eventSubscriptions.GroupBy(e => e.Scope))
                {
                    await using var newScope = group.Key.BeginLifetimeScope("AutofacWebRequest");
                    foreach (var subscription in group)
                    {
                        var cancellableEvent = @event as ICancellableEvent;

                        if (cancellableEvent != null &&
                            cancellableEvent.IsCancelled &&
                            !subscription.EventListenerAttribute.IgnoreCancelled)
                        {
                            continue;
                        }

                        var wasCancelled = false;
                        if (cancellableEvent != null)
                        {
                            wasCancelled = cancellableEvent.IsCancelled;
                        }

                        var serviceProvider = newScope.Resolve <IServiceProvider>();

                        try
                        {
                            await subscription.Callback.Invoke(serviceProvider, sender, @event);

                            if (cancellableEvent != null && subscription.EventListenerAttribute.Priority ==
                                EventListenerPriority.Monitor)
                            {
                                if (cancellableEvent.IsCancelled != wasCancelled)
                                {
                                    cancellableEvent.IsCancelled = wasCancelled;
                                    m_Logger.LogWarning(
                                        $"{((IOpenModComponent)@subscription.Owner.Target).OpenModComponentId} changed {@eventName} cancellation status with Monitor priority which is not permitted.");
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            m_Logger.LogError(ex, $"Exception occured during event {@eventName}");
                        }
                    }
                }

                m_Logger.LogTrace($"{eventName}: Finished.");
            }

            callback?.Invoke(@event);
        }
Esempio n. 28
0
 public RegisteredChangeListener(IOpenModComponent component, string key, Action callback)
 {
     Component = component;
     Key       = key;
     Callback  = callback;
 }
 public OpenModComponentBoundCommandRegistration(IOpenModComponent component, Type commandType)
 {
     Component   = component;
     CommandType = commandType;
     ReadAttributes(commandType);
 }
 public OpenModComponentBoundCommandRegistration(IOpenModComponent component, MethodInfo methodInfo)
 {
     Component     = component;
     CommandMethod = methodInfo;
     ReadAttributes(methodInfo);
 }