public TeleportOptions(IOpenModComponent instance, int delay, bool cancelOnMove, bool cancelOnDamage) { Instance = instance; Delay = delay; CancelOnMove = cancelOnMove; CancelOnDamage = cancelOnDamage; }
public OpenModComponentCommandSource(ILogger logger, IOpenModComponent openModComponent, Assembly assembly) { m_Logger = logger; m_OpenModComponent = openModComponent; Commands = new List <ICommandRegistration>(); ScanAssemblyForCommmmands(assembly); }
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())); }
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)); } }
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); })); }
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(); }
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); })); }
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)); } }
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))); }
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))); }
public IReadOnlyCollection <IPermissionRegistration> GetPermissions(IOpenModComponent component) { if (!component.IsComponentAlive || !m_PermissionRegistrations.ContainsKey(component)) { return(new List <IPermissionRegistration>()); } return(m_PermissionRegistrations[component].AsReadOnly()); }
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))); }
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); }
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))); }
public virtual void Unsubscribe(IOpenModComponent component) { if (!component.IsComponentAlive) { return; } m_EventSubscriptions.RemoveAll(c => !c.Owner.IsAlive || c.Owner.Target == component); }
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; }
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; }
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(); }
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())); }
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())); }
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); } }
public EventSubscription( IOpenModComponent ownerComponent, EventCallback callback, EventListenerAttribute attribute, string eventName, ILifetimeScope scope) { Owner = new WeakReference(ownerComponent); Callback = callback; EventListenerAttribute = attribute; EventName = eventName; Scope = scope; }
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; } } })); } }
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; }
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 }); }
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); } })); } }
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); }
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); }