diff --git a/Robust.Shared/GameObjects/EntitySystemManager.cs b/Robust.Shared/GameObjects/EntitySystemManager.cs index f8901b616..a1808e1ef 100644 --- a/Robust.Shared/GameObjects/EntitySystemManager.cs +++ b/Robust.Shared/GameObjects/EntitySystemManager.cs @@ -3,12 +3,15 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Runtime.CompilerServices; using Prometheus; using Robust.Shared.IoC; +using Robust.Shared.IoC.Exceptions; using Robust.Shared.Log; using Robust.Shared.Reflection; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; +using Dependency = Robust.Shared.IoC.DependencyAttribute; #if EXCEPTION_TOLERANCE using Robust.Shared.Exceptions; #endif @@ -53,13 +56,47 @@ namespace Robust.Shared.GameObjects /// public event EventHandler? SystemUnloaded; - /// Thrown if the provided type is not registered. + /// Thrown if the provided type is not registered. public T GetEntitySystem() where T : IEntitySystem { return _systemDependencyCollection.Resolve(); } + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public void Resolve([NotNull] ref T? instance) + where T : IEntitySystem + { + _systemDependencyCollection.Resolve(ref instance); + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2) + where T1 : IEntitySystem + where T2 : IEntitySystem + { + _systemDependencyCollection.Resolve(ref instance1, ref instance2); + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3) + where T1 : IEntitySystem + where T2 : IEntitySystem + where T3 : IEntitySystem + { + _systemDependencyCollection.Resolve(ref instance1, ref instance2, ref instance3); + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3, [NotNull] ref T4? instance4) + where T1 : IEntitySystem + where T2 : IEntitySystem + where T3 : IEntitySystem + where T4 : IEntitySystem + { + _systemDependencyCollection.Resolve(ref instance1, ref instance2, ref instance3, ref instance4); + } + /// public bool TryGetEntitySystem([NotNullWhen(true)] out T? entitySystem) where T : IEntitySystem diff --git a/Robust.Shared/GameObjects/IEntitySystemManager.cs b/Robust.Shared/GameObjects/IEntitySystemManager.cs index f38cb5603..48faa6d38 100644 --- a/Robust.Shared/GameObjects/IEntitySystemManager.cs +++ b/Robust.Shared/GameObjects/IEntitySystemManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using Robust.Shared.IoC.Exceptions; namespace Robust.Shared.GameObjects { @@ -39,6 +40,44 @@ namespace Robust.Shared.GameObjects /// The instance matching the specified type. T GetEntitySystem() where T : IEntitySystem; + /// + /// Resolves an entity system. + /// + /// Thrown if the provided type is not registered. + /// + /// Thrown if the resolved type hasn't been created yet + /// because the dependency collection object graph still needs to be constructed for it. + /// + void Resolve([NotNull] ref T? instance) + where T : IEntitySystem; + + /// + /// + /// Resolve two entity systems. + /// + void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2) + where T1 : IEntitySystem + where T2 : IEntitySystem; + + /// + /// + /// Resolve three entity systems. + /// + void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3) + where T1 : IEntitySystem + where T2 : IEntitySystem + where T3 : IEntitySystem; + + /// + /// + /// Resolve four entity systems. + /// + void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3, [NotNull] ref T4? instance4) + where T1 : IEntitySystem + where T2 : IEntitySystem + where T3 : IEntitySystem + where T4 : IEntitySystem; + /// /// Tries to get an entity system of the specified type. /// diff --git a/Robust.Shared/IoC/DependencyCollection.cs b/Robust.Shared/IoC/DependencyCollection.cs index f473d4f29..4d87e3855 100644 --- a/Robust.Shared/IoC/DependencyCollection.cs +++ b/Robust.Shared/IoC/DependencyCollection.cs @@ -4,9 +4,11 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.CompilerServices; using JetBrains.Annotations; using Robust.Shared.IoC.Exceptions; using Robust.Shared.Utility; +using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Robust.Shared.IoC { @@ -242,6 +244,34 @@ namespace Robust.Shared.IoC return (T) ResolveType(typeof(T)); } + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public void Resolve([NotNull] ref T? instance) + { + // Resolve() will either throw or return a concrete instance, therefore we suppress the nullable warning. + instance ??= Resolve()!; + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2) + { + Resolve(ref instance1); + Resolve(ref instance2); + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3) + { + Resolve(ref instance1, ref instance2); + Resolve(ref instance3); + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3, [NotNull] ref T4? instance4) + { + Resolve(ref instance1, ref instance2); + Resolve(ref instance3, ref instance4); + } + /// [System.Diagnostics.Contracts.Pure] public object ResolveType(Type type) diff --git a/Robust.Shared/IoC/IDependencyCollection.cs b/Robust.Shared/IoC/IDependencyCollection.cs index 3068197e6..046cd0112 100644 --- a/Robust.Shared/IoC/IDependencyCollection.cs +++ b/Robust.Shared/IoC/IDependencyCollection.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using Robust.Shared.IoC.Exceptions; using Robust.Shared.Reflection; +using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Robust.Shared.IoC { @@ -134,6 +135,27 @@ namespace Robust.Shared.IoC [System.Diagnostics.Contracts.Pure] T Resolve(); + /// + void Resolve([NotNull] ref T? instance); + + /// + /// + /// Resolve two dependencies manually. + /// + void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2); + + /// + /// + /// Resolve three dependencies manually. + /// + void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3); + + /// + /// + /// Resolve four dependencies manually. + /// + void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3, [NotNull] ref T4? instance4); + /// /// Resolve a dependency manually. /// diff --git a/Robust.Shared/IoC/IoCManager.cs b/Robust.Shared/IoC/IoCManager.cs index 3d1c1cf4a..f1cdb6a20 100644 --- a/Robust.Shared/IoC/IoCManager.cs +++ b/Robust.Shared/IoC/IoCManager.cs @@ -1,10 +1,13 @@ using Robust.Shared.IoC.Exceptions; using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using JetBrains.Annotations; using Robust.Shared.Reflection; using Robust.Shared.Utility; +using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Robust.Shared.IoC { @@ -190,6 +193,51 @@ namespace Robust.Shared.IoC return _container.Value!.Resolve(); } + /// + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public static void Resolve([NotNull] ref T? instance) + { + DebugTools.Assert(_container.IsValueCreated, NoContextAssert); + + _container.Value!.Resolve(ref instance); + } + + /// + /// + /// Resolve two dependencies manually. + /// + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public static void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2) + { + DebugTools.Assert(_container.IsValueCreated, NoContextAssert); + + _container.Value!.Resolve(ref instance1, ref instance2); + } + + /// + /// + /// Resolve three dependencies manually. + /// + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public static void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3) + { + DebugTools.Assert(_container.IsValueCreated, NoContextAssert); + + _container.Value!.Resolve(ref instance1, ref instance2, ref instance3); + } + + /// + /// + /// Resolve four dependencies manually. + /// + [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)] + public static void Resolve([NotNull] ref T1? instance1, [NotNull] ref T2? instance2, [NotNull] ref T3? instance3, [NotNull] ref T4? instance4) + { + DebugTools.Assert(_container.IsValueCreated, NoContextAssert); + + _container.Value!.Resolve(ref instance1, ref instance2, ref instance3, ref instance4); + } + /// /// Resolve a dependency manually. /// diff --git a/Robust.Shared/Player/Filter.cs b/Robust.Shared/Player/Filter.cs index 2188f8d39..ec03df2c2 100644 --- a/Robust.Shared/Player/Filter.cs +++ b/Robust.Shared/Player/Filter.cs @@ -41,7 +41,7 @@ namespace Robust.Shared.Player /// public Filter AddPlayersByPvs(EntityUid origin, float rangeMultiplier = 2f, IEntityManager? entityManager = null) { - entityManager ??= IoCManager.Resolve(); + IoCManager.Resolve(ref entityManager); var transform = entityManager.GetComponent(origin); return AddPlayersByPvs(transform.MapPosition, rangeMultiplier); } @@ -70,7 +70,7 @@ namespace Robust.Shared.Player /// public Filter AddPlayersByPvs(EntityCoordinates origin, float rangeMultiplier = 2f, IEntityManager? entityMan = null, ISharedPlayerManager? playerMan = null) { - entityMan ??= IoCManager.Resolve(); + IoCManager.Resolve(ref entityMan, ref playerMan); return AddPlayersByPvs(origin.ToMap(entityMan), rangeMultiplier, playerMan); } @@ -78,9 +78,9 @@ namespace Robust.Shared.Player /// Adds all players inside an entity's PVS. /// The current PVS range will be multiplied by . /// - public Filter AddPlayersByPvs(MapCoordinates origin, float rangeMultiplier = 2f, ISharedPlayerManager? playerMan = null) + public Filter AddPlayersByPvs(MapCoordinates origin, float rangeMultiplier = 2f, ISharedPlayerManager? playerMan = null, IConfigurationManager? cfgMan = null) { - var cfgMan = IoCManager.Resolve(); + IoCManager.Resolve(ref playerMan, ref cfgMan); // If PVS is disabled, we simply return all players. if (!cfgMan.GetCVar(CVars.NetPVS)) @@ -107,9 +107,9 @@ namespace Robust.Shared.Player /// /// Adds all players to the filter. /// - public Filter AddAllPlayers() + public Filter AddAllPlayers(ISharedPlayerManager? playerMan = null) { - var playerMan = IoCManager.Resolve(); + IoCManager.Resolve(ref playerMan); _recipients = new HashSet(playerMan.NetworkedSessions); @@ -121,7 +121,7 @@ namespace Robust.Shared.Player /// public Filter AddWhere(Predicate predicate, ISharedPlayerManager? playerMan = null) { - playerMan ??= IoCManager.Resolve(); + IoCManager.Resolve(ref playerMan); foreach (var player in playerMan.NetworkedSessions) { if (predicate(player))