diff --git a/.gitmodules b/.gitmodules index 50ad95895..30c23aed2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,6 +13,3 @@ [submodule "cefglue"] path = cefglue url = https://github.com/space-wizards/cefglue.git -[submodule "Arch/Arch"] - path = Arch/Arch - url = https://github.com/space-wizards/Arch.git diff --git a/Arch/Arch b/Arch/Arch deleted file mode 160000 index 12fbc72c5..000000000 --- a/Arch/Arch +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 12fbc72c548138208065947f553aa3a136869fdc diff --git a/Arch/Arch.csproj b/Arch/Arch.csproj deleted file mode 100644 index d4c49a96d..000000000 --- a/Arch/Arch.csproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - true - latest - net7.0 - - true - true - enable - true - snupkg - bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml - - Arch - Arch - 1.2.7.1-alpha - genaray - Apache-2.0 - A high performance c# net.6 and net.7 archetype based ECS ( Entity component system ). - Updated LowLevel which fixes bugs. - c#;.net;.net6;.net7;ecs;game;entity;gamedev; game-development; game-engine; entity-component-system;stride;unity;godot; - - https://github.com/genaray/Arch - https://github.com/genaray/Arch.git - git - true - - 11 - true - Apache2.0 - - 1701;1702;1591 - - Debug;Debug-PureECS;Debug-Events;Release;Release-PureECS;Release-Events; - - Arch - false - false - src/Arch/**/* - $(DefineConstants);PURE_ECS;CONTRACTS_FULL - - - - $(DefineConstants);PURE_ECS;CONTRACTS_FULL;TRACE; - false - AnyCPU - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Arch\%(RecursiveDir)%(Filename)%(Extension) - - - - - - - - - diff --git a/Resources/EngineCredits/Libraries.yml b/Resources/EngineCredits/Libraries.yml index 9b5fd54bd..eb9348c45 100644 --- a/Resources/EngineCredits/Libraries.yml +++ b/Resources/EngineCredits/Libraries.yml @@ -2203,207 +2203,3 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -- name: Arch - license: | - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2022 Lars Matthäus/genaray - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/Robust.Benchmarks/Arch/ArchComponentAccessBenchmark.cs b/Robust.Benchmarks/Arch/ArchComponentAccessBenchmark.cs deleted file mode 100644 index cae65ddfd..000000000 --- a/Robust.Benchmarks/Arch/ArchComponentAccessBenchmark.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using Arch.Core; -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Engines; -using Robust.Shared.Analyzers; -using static Robust.Benchmarks.EntityManager.ArchetypeComponentAccessBenchmark; - -namespace Robust.Benchmarks.Arch; - -[MemoryDiagnoser] -[Virtual] -public class ArchComponentAccessBenchmark -{ - private const int N = 10000; - - private static readonly Consumer Consumer = new(); - private Entity _entity; - private World _world = default!; - private QueryDescription _singleQuery; - private QueryDescription _tenQuery; - - [GlobalSetup] - public void GlobalSetup() - { - var _ = new JobScheduler.JobScheduler("ArchBenchmark"); - - _world = World.Create(); - - for (var i = 0; i < N; i++) - { - var entity = _world.Create(); - - // Randomly chosen id - if (entity.Id == 1584) - _entity = entity; - - _world.Add( - entity, - new Struct1(), - new Struct2(), - new Struct3(), - new Struct4(), - new Struct5(), - new Struct6(), - new Struct7(), - new Struct8(), - new Struct9(), - new Struct10() - ); - } - - _singleQuery = new QueryDescription().WithAll(); - _tenQuery = new QueryDescription().WithAll(); - } - - [GlobalCleanup] - public void GlobalCleanup() - { - JobScheduler.JobScheduler.Instance.Dispose(); - Environment.Exit(0); - } - - [Benchmark] - public Struct1 GetSingle() - { - return _world.Get(_entity); - } - - [Benchmark] - public (Struct1, Struct2, Struct3, Struct4, Struct5, Struct6, Struct7, Struct8, Struct9, Struct10) - GetTen() - { - return ( - _world.Get(_entity), - _world.Get(_entity), - _world.Get(_entity), - _world.Get(_entity), - _world.Get(_entity), - _world.Get(_entity), - _world.Get(_entity), - _world.Get(_entity), - _world.Get(_entity), - _world.Get(_entity) - ); - } - - [Benchmark] - public bool HasSingle() - { - return _world.Has(_entity); - } - - [Benchmark] - public bool HasTen() - { - return _world.Has(_entity) && - _world.Has(_entity) && - _world.Has(_entity) && - _world.Has(_entity) && - _world.Has(_entity) && - _world.Has(_entity) && - _world.Has(_entity) && - _world.Has(_entity) && - _world.Has(_entity) && - _world.Has(_entity); - } - - [Benchmark] - public void IterateSingle() - { - _world.Query(_singleQuery, static (ref Struct1 s) => Consumer.Consume(s)); - } - - [Benchmark] - public void IterateSingleInline() - { - _world.InlineQuery(_singleQuery); - } - - [Benchmark] - public void IterateSingleParallel() - { - _world.ParallelQuery(_singleQuery, static (ref Struct1 s) => Consumer.Consume(s)); - } - - [Benchmark] - public void IterateSingleInlineParallel() - { - _world.InlineParallelQuery(_singleQuery); - } - - [Benchmark] - public void IterateTen() - { - _world.Query(_tenQuery, - static ( - ref Struct1 s1, ref Struct2 s2, ref Struct3 s3, ref Struct4 s4, - ref Struct5 s5, ref Struct6 s6, ref Struct7 s7, ref Struct8 s8, - ref Struct9 s9, ref Struct10 s10) => - Consumer.Consume((s1, s2, s3, s4, s5, s6, s7, s8, s9, s10))); - } - - [Benchmark] - public void IterateTenInline() - { - _world.InlineQuery(_tenQuery); - } - - [Benchmark] - public void IterateTenParallel() - { - _world.ParallelQuery(_tenQuery, - static ( - ref Struct1 s1, ref Struct2 s2, ref Struct3 s3, ref Struct4 s4, - ref Struct5 s5, ref Struct6 s6, ref Struct7 s7, ref Struct8 s8, - ref Struct9 s9, ref Struct10 s10) => - Consumer.Consume((s1, s2, s3, s4, s5, s6, s7, s8, s9, s10))); - } - - [Benchmark] - public void IterateTenInlineParallel() - { - _world.InlineParallelQuery(_tenQuery); - } - - private struct QueryConsumer : IForEach - { - private static readonly Consumer Consumer = new(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Update(Entity entity) - { - Consumer.Consume(entity); - } - } -} diff --git a/Robust.Benchmarks/EntityManager/AddRemoveComponentBenchmark.cs b/Robust.Benchmarks/EntityManager/AddRemoveComponentBenchmark.cs index de589904e..767ba7db3 100644 --- a/Robust.Benchmarks/EntityManager/AddRemoveComponentBenchmark.cs +++ b/Robust.Benchmarks/EntityManager/AddRemoveComponentBenchmark.cs @@ -41,7 +41,7 @@ public partial class AddRemoveComponentBenchmark { for (var i = 2; i <= N+1; i++) { - var uid = new EntityUid(i, -1); + var uid = new EntityUid(i); _entityManager.AddComponent(uid); _entityManager.RemoveComponent(uid); } diff --git a/Robust.Benchmarks/EntityManager/ComponentIndexBenchmark.cs b/Robust.Benchmarks/EntityManager/ComponentIndexBenchmark.cs index 12b11d117..9be074dc2 100644 --- a/Robust.Benchmarks/EntityManager/ComponentIndexBenchmark.cs +++ b/Robust.Benchmarks/EntityManager/ComponentIndexBenchmark.cs @@ -57,7 +57,7 @@ public class ComponentIndexBenchmark private static class CompArrayIndex { // ReSharper disable once StaticMemberInGenericType - public static readonly CompIdx Idx = new(Interlocked.Increment(ref _compIndexMaster), typeof(T)); + public static readonly CompIdx Idx = new(Interlocked.Increment(ref _compIndexMaster)); } private static CompIdx GetCompIdIndex(Type type) diff --git a/Robust.Benchmarks/EntityManager/GetComponentBenchmark.cs b/Robust.Benchmarks/EntityManager/GetComponentBenchmark.cs index d624da923..d3f16b6d3 100644 --- a/Robust.Benchmarks/EntityManager/GetComponentBenchmark.cs +++ b/Robust.Benchmarks/EntityManager/GetComponentBenchmark.cs @@ -46,7 +46,7 @@ public partial class GetComponentBenchmark { for (var i = 2; i <= N+1; i++) { - Comps[i] = _entityManager.GetComponent(new EntityUid(i, -1)); + Comps[i] = _entityManager.GetComponent(new EntityUid(i)); } // Return something so the JIT doesn't optimize out all the GetComponent calls. diff --git a/Robust.Benchmarks/Robust.Benchmarks.csproj b/Robust.Benchmarks/Robust.Benchmarks.csproj index a15c3b979..8dfe2500d 100644 --- a/Robust.Benchmarks/Robust.Benchmarks.csproj +++ b/Robust.Benchmarks/Robust.Benchmarks.csproj @@ -8,7 +8,6 @@ RA0003 - diff --git a/Robust.Client/Console/Commands/Debug.cs b/Robust.Client/Console/Commands/Debug.cs index 3540aeeea..dcf0ef66d 100644 --- a/Robust.Client/Console/Commands/Debug.cs +++ b/Robust.Client/Console/Commands/Debug.cs @@ -256,7 +256,7 @@ namespace Robust.Client.Console.Commands return; } - var uid = EntityUid.Parse(args[0], "-1"); + var uid = EntityUid.Parse(args[0]); var entmgr = _entityManager; if (!entmgr.EntityExists(uid)) { diff --git a/Robust.Client/Console/Commands/ProfileEntitySpawningCommand.cs b/Robust.Client/Console/Commands/ProfileEntitySpawningCommand.cs index 754c99114..a61069e7a 100644 --- a/Robust.Client/Console/Commands/ProfileEntitySpawningCommand.cs +++ b/Robust.Client/Console/Commands/ProfileEntitySpawningCommand.cs @@ -43,7 +43,6 @@ public sealed class ProfileEntitySpawningCommand : IConsoleCommand GC.Collect(); - Span ents = stackalloc EntityUid[amount]; var stopwatch = new Stopwatch(); stopwatch.Start(); @@ -51,17 +50,12 @@ public sealed class ProfileEntitySpawningCommand : IConsoleCommand for (var i = 0; i < amount; i++) { - ents[i] = _entities.SpawnEntity(prototype, MapCoordinates.Nullspace); + _entities.SpawnEntity(prototype, MapCoordinates.Nullspace); } MeasureProfiler.SaveData(); shell.WriteLine($"Client: Profiled spawning {amount} entities in {stopwatch.Elapsed.TotalMilliseconds:N3} ms"); - - foreach (var ent in ents) - { - _entities.DeleteEntity(ent); - } } } #endif diff --git a/Robust.Client/GameObjects/ClientEntityManager.cs b/Robust.Client/GameObjects/ClientEntityManager.cs index 1f8c19957..5f2e87073 100644 --- a/Robust.Client/GameObjects/ClientEntityManager.cs +++ b/Robust.Client/GameObjects/ClientEntityManager.cs @@ -44,7 +44,7 @@ namespace Robust.Client.GameObjects EntityUid IClientEntityManagerInternal.CreateEntity(string? prototypeName, out MetaDataComponent metadata) { - return base.CreateEntity(prototypeName, out metadata, out _); + return base.CreateEntity(prototypeName, out metadata); } void IClientEntityManagerInternal.InitializeEntity(EntityUid entity, MetaDataComponent? meta) diff --git a/Robust.Client/GameObjects/EntitySystems/MapSystem.cs b/Robust.Client/GameObjects/EntitySystems/MapSystem.cs index b9ed64b92..7849f6eaf 100644 --- a/Robust.Client/GameObjects/EntitySystems/MapSystem.cs +++ b/Robust.Client/GameObjects/EntitySystems/MapSystem.cs @@ -1,9 +1,12 @@ using Robust.Client.Graphics; using Robust.Client.Map; +using Robust.Client.Physics; using Robust.Client.ResourceManagement; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Map; +using Robust.Shared.Map.Components; +using Robust.Shared.Physics.Dynamics; namespace Robust.Client.GameObjects { @@ -25,5 +28,10 @@ namespace Robust.Client.GameObjects base.Shutdown(); _overlayManager.RemoveOverlay(); } + + protected override void OnMapAdd(EntityUid uid, MapComponent component, ComponentAdd args) + { + EnsureComp(uid); + } } } diff --git a/Robust.Client/GameStates/ClientDirtySystem.cs b/Robust.Client/GameStates/ClientDirtySystem.cs index 5528ab3f6..25013259e 100644 --- a/Robust.Client/GameStates/ClientDirtySystem.cs +++ b/Robust.Client/GameStates/ClientDirtySystem.cs @@ -39,7 +39,7 @@ public sealed class ClientDirtySystem : EntitySystem private void OnTerminate(ref EntityTerminatingEvent ev) { - if (!_timing.InPrediction || IsClientSide(ev.Entity, ev.Metadata)) + if (!_timing.InPrediction || IsClientSide(ev.Entity)) return; // Client-side entity deletion is not supported and will cause errors. diff --git a/Robust.Client/GameStates/ClientGameStateManager.cs b/Robust.Client/GameStates/ClientGameStateManager.cs index 4d3940b8d..0d07dbbd4 100644 --- a/Robust.Client/GameStates/ClientGameStateManager.cs +++ b/Robust.Client/GameStates/ClientGameStateManager.cs @@ -5,8 +5,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.InteropServices; -using Arch.Core; -using Collections.Pooled; using JetBrains.Annotations; using Microsoft.Extensions.ObjectPool; using Robust.Client.GameObjects; @@ -31,9 +29,7 @@ using Robust.Shared.Network.Messages; using Robust.Shared.Profiling; using Robust.Shared.Replays; using Robust.Shared.Timing; -using Robust.Shared.Toolshed.TypeParsers; using Robust.Shared.Utility; -using ComponentType = Arch.Core.Utils.ComponentType; namespace Robust.Client.GameStates { @@ -56,12 +52,11 @@ namespace Robust.Client.GameStates private readonly Dictionary _compStateWork = new(); private readonly Dictionary> _pendingReapplyNetStates = new(); private readonly HashSet _stateEnts = new(); + private readonly List _toDelete = new(); + private readonly List _toRemove = new(); private readonly Dictionary> _outputData = new(); private readonly List<(EntityUid, TransformComponent)> _queuedBroadphaseUpdates = new(); - private readonly List _created = new(); - private readonly List _detached = new(); - private readonly ObjectPool> _compDataPool = new DefaultObjectPool>(new DictPolicy(), 256); @@ -545,9 +540,7 @@ namespace Robust.Client.GameStates var countReset = 0; var system = _entitySystemManager.GetEntitySystem(); var metaQuery = _entityManager.GetEntityQuery(); - using var toRemove = new PooledList(); - using var toAdd = new PooledList(); - using var toAddStates = new PooledList(); + RemQueue toRemove = new(); foreach (var entity in system.DirtyEntities) { @@ -611,17 +604,12 @@ namespace Robust.Client.GameStates _resettingPredictedEntities = false; } - if (toRemove.Count > 0) + // Remove predicted component additions + foreach (var comp in toRemove) { - // Remove predicted component additions - // TODO: 1 archetype change. - foreach (var comp in toRemove) - { - _entities.RemoveComponent(entity, comp, meta); - } - - toRemove.Clear(); + _entities.RemoveComponent(entity, comp); } + toRemove.Clear(); // Re-add predicted removals if (system.RemovedComponents.TryGetValue(entity, out var netIds)) @@ -634,29 +622,15 @@ namespace Robust.Client.GameStates if (!last.TryGetValue(netId, out var state)) continue; - toAdd.Add(netId); - toAddStates.Add(state); - } + var comp = _entityManager.AddComponent(entity, netId, meta); - if (toAdd.Count > 0) - { - for (var i = 0; i < toAdd.Count; i++) - { - var netId = toAdd[i]; - var state = toAddStates[i]; - var comp = _entityManager.AddComponent(entity, netId, meta); + if (_sawmill.Level <= LogLevel.Debug) + _sawmill.Debug($" A component was removed: {comp.GetType()}"); - if (_sawmill.Level <= LogLevel.Debug) - _sawmill.Debug($" A component was removed: {comp.GetType()}"); - - var stateEv = new ComponentHandleState(state, null); - _entities.EventBus.RaiseComponentEvent(comp, ref stateEv); - comp.ClearCreationTick(); // don't undo the re-adding. - comp.LastModifiedTick = _timing.LastRealTick; - } - - toAdd.Clear(); - toAddStates.Clear(); + var stateEv = new ComponentHandleState(state, null); + _entities.EventBus.RaiseComponentEvent(comp, ref stateEv); + comp.ClearCreationTick(); // don't undo the re-adding. + comp.LastModifiedTick = _timing.LastRealTick; } } @@ -739,9 +713,10 @@ namespace Robust.Client.GameStates _config.TickProcessMessages(); } + (IEnumerable Created, List Detached) output; using (_prof.Group("Entity")) { - ApplyEntityStates(curState, nextState); + output = ApplyEntityStates(curState, nextState); } using (_prof.Group("Player")) @@ -751,13 +726,13 @@ namespace Robust.Client.GameStates using (_prof.Group("Callback")) { - GameStateApplied?.Invoke(new GameStateAppliedArgs(curState, _detached)); + GameStateApplied?.Invoke(new GameStateAppliedArgs(curState, output.Detached)); } - return _created; + return output.Created; } - private void ApplyEntityStates(GameState curState, GameState? nextState) + private (IEnumerable Created, List Detached) ApplyEntityStates(GameState curState, GameState? nextState) { var metas = _entities.GetEntityQuery(); var xforms = _entities.GetEntityQuery(); @@ -766,8 +741,6 @@ namespace Robust.Client.GameStates var enteringPvs = 0; _toApply.Clear(); _toCreate.Clear(); - _detached.Clear(); - _created.Clear(); _pendingReapplyNetStates.Clear(); var curSpan = curState.EntityStates.Span; @@ -792,7 +765,6 @@ namespace Robust.Client.GameStates var uid = _entities.CreateEntity(metaState.PrototypeId, out var newMeta); _toCreate.Add(es.NetEntity, es); - _created.Add(es.NetEntity); _toApply.Add(uid, (es.NetEntity, newMeta, false, GameTick.Zero, es, null)); // Client creates a client-side net entity for the newly created entity. @@ -846,7 +818,7 @@ namespace Robust.Client.GameStates // Detach entities to null space var containerSys = _entitySystemManager.GetEntitySystem(); var lookupSys = _entitySystemManager.GetEntitySystem(); - ProcessPvsDeparture(_detached, curState.ToSequence, metas, xforms, xformSys, containerSys, lookupSys); + var detached = ProcessPvsDeparture(curState.ToSequence, metas, xforms, xformSys, containerSys, lookupSys); // Check next state (AFTER having created new entities introduced in curstate) if (nextState != null) @@ -948,6 +920,8 @@ namespace Robust.Client.GameStates _prof.WriteValue("State Size", ProfData.Int32(curSpan.Length)); _prof.WriteValue("Entered PVS", ProfData.Int32(enteringPvs)); + + return (_toCreate.Keys, detached); } /// @@ -978,7 +952,7 @@ namespace Robust.Client.GameStates var xforms = _entities.GetEntityQuery(); var xformSys = _entitySystemManager.GetEntitySystem(); - using var toDelete = new PooledList(); + _toDelete.Clear(); // Client side entities won't need the transform, but that should always be a tiny minority of entities var metaQuery = _entityManager.AllEntityQueryEnumerator(); @@ -989,7 +963,7 @@ namespace Robust.Client.GameStates if (metadata.NetEntity.IsClientSide()) { if (deleteClientEntities) - toDelete.Add(ent); + _toDelete.Add(ent); continue; } @@ -1016,14 +990,14 @@ namespace Robust.Client.GameStates && !deleteClientEntities // don't add duplicates && _entities.IsClientSide(child.Value)) { - toDelete.Add(child.Value); + _toDelete.Add(child.Value); } } - toDelete.Add(ent); + _toDelete.Add(ent); } - foreach (var ent in toDelete) + foreach (var ent in _toDelete) { _entities.DeleteEntity(ent); } @@ -1083,8 +1057,7 @@ namespace Robust.Client.GameStates Detach(GameTick.MaxValue, null, entities, metas, xforms, xformSys, containerSys, lookupSys); } - private void ProcessPvsDeparture( - IList detached, + private List ProcessPvsDeparture( GameTick toTick, EntityQuery metas, EntityQuery xforms, @@ -1092,17 +1065,18 @@ namespace Robust.Client.GameStates ContainerSystem containerSys, EntityLookupSystem lookupSys) { - using var toDetach = new PooledList<(GameTick Tick, List Entities)>(); - _processor.GetEntitiesToDetach(toDetach, toTick, _pvsDetachBudget); + var toDetach = _processor.GetEntitiesToDetach(toTick, _pvsDetachBudget); + var detached = new List(); if (toDetach.Count == 0) - return; + return detached; // TODO optimize // If an entity is leaving PVS, so are all of its children. If we can preserve the hierarchy we can avoid // things like container insertion and ejection. using var _ = _prof.Group("Leave PVS"); + detached.EnsureCapacity(toDetach.Count); foreach (var (tick, ents) in toDetach) { @@ -1110,6 +1084,7 @@ namespace Robust.Client.GameStates } _prof.WriteValue("Count", ProfData.Int32(detached.Count)); + return detached; } private void Detach(GameTick maxTick, @@ -1120,7 +1095,7 @@ namespace Robust.Client.GameStates SharedTransformSystem xformSys, ContainerSystem containerSys, EntityLookupSystem lookupSys, - IList? detached = null) + List? detached = null) { foreach (var netEntity in entities) { @@ -1174,7 +1149,7 @@ namespace Robust.Client.GameStates var metaQuery = _entityManager.GetEntityQuery(); #if EXCEPTION_TOLERANCE - using var brokenEnts = new PooledList(); + var brokenEnts = new List(); #endif using (_prof.Group("Initialize Entity")) { @@ -1238,28 +1213,18 @@ namespace Robust.Client.GameStates // First remove any deleted components if (curState?.NetComponents != null) { - using var toRemove = new PooledList(); - using var compTypes = new PooledList(); + _toRemove.Clear(); foreach (var (id, comp) in meta.NetComponents) { if (comp.NetSyncEnabled && !curState.NetComponents.Contains(id)) - { - toRemove.Add(comp); - compTypes.Add(comp.GetType()); - } + _toRemove.Add(comp); } - if (toRemove.Count > 0) + foreach (var comp in _toRemove) { - foreach (var comp in toRemove) - { - _entityManager.RemoveComponentInternal(uid, comp, terminating: false, archetypeChange: false, meta); - } + _entities.RemoveComponent(uid, comp, meta); } - - if (compTypes.Count > 0) - _entityManager.RemoveComponentRange(uid, compTypes); } if (enteringPvs) @@ -1274,7 +1239,7 @@ namespace Robust.Client.GameStates if (!meta.NetComponents.TryGetValue(id, out var comp)) { comp = _compFactory.GetComponent(id); - _entityManager.AddComponent(uid, comp, metadata: meta); + _entityManager.AddComponent(uid, comp, true, metadata: meta); } _compStateWork[id] = (comp, state, null); @@ -1282,49 +1247,18 @@ namespace Robust.Client.GameStates } else if (curState != null) { - using var addedComps = new PooledList(); - using var addedCompTypes = new PooledList(); - using var addedRegistrations = new PooledList(); - foreach (var compChange in curState.ComponentChanges.Span) { if (!meta.NetComponents.TryGetValue(compChange.NetID, out var comp)) { - var registration = _compFactory.GetRegistration(compChange.NetID); - addedRegistrations.Add(registration); - comp = _compFactory.GetComponent(registration); - comp.Owner = uid; - addedComps.Add(comp); - addedCompTypes.Add(comp.GetType()); + comp = _compFactory.GetComponent(compChange.NetID); + _entityManager.AddComponent(uid, comp, true, metadata:meta); } else if (compChange.LastModifiedTick <= lastApplied && lastApplied != GameTick.Zero) continue; _compStateWork[compChange.NetID] = (comp, compChange.State, null); } - - // To avoid shuffling the archetype we'll set the component range up-front. - if (addedComps.Count > 0) - { - // TODO: This fucking sucks but - // - Frequent archetype changes PER COMPONENT sucks - // - the components will be null in event handlers until it's done. - _entityManager.AddComponentRange(uid, addedCompTypes); - - for (var i = 0; i < addedComps.Count; i++) - { - var component = addedComps[i]; - var reg = addedRegistrations[i]; - _entityManager.AddComponentInternalOnly(uid, component, reg, meta); - } - - for (var i = 0; i < addedComps.Count; i++) - { - var component = addedComps[i]; - var reg = addedRegistrations[i]; - _entityManager.AddComponentEvents(uid, component, reg, false, meta); - } - } } if (nextState != null) @@ -1414,7 +1348,7 @@ namespace Robust.Client.GameStates return false; } - if (!EntityUid.TryParse(args[0], "-1", out uid)) + if (!EntityUid.TryParse(args[0], out uid)) { shell.WriteError(Loc.GetString("cmd-parse-failure-uid", ("arg", args[0]))); meta = null; @@ -1546,22 +1480,23 @@ namespace Robust.Client.GameStates if (!meta.NetComponents.TryGetValue(id, out var comp)) { comp = _compFactory.GetComponent(id); - _entityManager.AddComponent(uid, comp, meta); + _entityManager.AddComponent(uid, comp, true, meta); } var handleState = new ComponentHandleState(state, null); _entityManager.EventBus.RaiseComponentEvent(comp, ref handleState); } - using var toRemove = new PooledList(); + // ensure we don't have any extra components + _toRemove.Clear(); foreach (var (id, comp) in meta.NetComponents) { if (comp.NetSyncEnabled && !lastState.ContainsKey(id)) - toRemove.Add(comp); + _toRemove.Add(comp); } - foreach (var comp in toRemove) + foreach (var comp in _toRemove) { _entities.RemoveComponent(uid, comp); } @@ -1574,10 +1509,10 @@ namespace Robust.Client.GameStates public sealed class GameStateAppliedArgs : EventArgs { - public readonly GameState AppliedState; - public readonly IReadOnlyList Detached; + public GameState AppliedState { get; } + public readonly List Detached; - public GameStateAppliedArgs(GameState appliedState, IReadOnlyList detached) + public GameStateAppliedArgs(GameState appliedState, List detached) { AppliedState = appliedState; Detached = detached; diff --git a/Robust.Client/GameStates/GameStateProcessor.cs b/Robust.Client/GameStates/GameStateProcessor.cs index e69e8b401..7452b27de 100644 --- a/Robust.Client/GameStates/GameStateProcessor.cs +++ b/Robust.Client/GameStates/GameStateProcessor.cs @@ -304,8 +304,9 @@ Had full state: {LastFullState != null}" public void ClearDetachQueue() => _pvsDetachMessages.Clear(); - public void GetEntitiesToDetach(IList<(GameTick Tick, List Entities)> result, GameTick toTick, int budget) + public List<(GameTick Tick, List Entities)> GetEntitiesToDetach(GameTick toTick, int budget) { + var result = new List<(GameTick Tick, List Entities)>(); foreach (var (tick, entities) in _pvsDetachMessages) { if (tick > toTick) @@ -324,6 +325,7 @@ Had full state: {LastFullState != null}" entities.RemoveRange(index, budget); break; } + return result; } private bool TryGetDeltaState(out GameState? curState, out GameState? nextState) diff --git a/Robust.Client/Placement/Modes/AlignSimilar.cs b/Robust.Client/Placement/Modes/AlignSimilar.cs index ae5bb28ab..8d1a24d6b 100644 --- a/Robust.Client/Placement/Modes/AlignSimilar.cs +++ b/Robust.Client/Placement/Modes/AlignSimilar.cs @@ -44,7 +44,7 @@ namespace Robust.Client.Placement.Modes var closestEntity = snapToEntities[0]; var closestTransform = pManager.EntityManager.GetComponent(closestEntity); - if (!pManager.EntityManager.TryGetComponent(closestEntity, out SpriteComponent? component) || component.BaseRSI == null) + if (!pManager.EntityManager.TryGetComponent(closestEntity, out var component) || component.BaseRSI == null) { return; } diff --git a/Robust.Client/Robust.Client.csproj b/Robust.Client/Robust.Client.csproj index b1eb05fc0..57be10f07 100644 --- a/Robust.Client/Robust.Client.csproj +++ b/Robust.Client/Robust.Client.csproj @@ -27,9 +27,9 @@ - - - + + + diff --git a/Robust.Client/ViewVariables/Editors/VVPropEditorEntityCoordinates.cs b/Robust.Client/ViewVariables/Editors/VVPropEditorEntityCoordinates.cs index 10281870b..91620f5b5 100644 --- a/Robust.Client/ViewVariables/Editors/VVPropEditorEntityCoordinates.cs +++ b/Robust.Client/ViewVariables/Editors/VVPropEditorEntityCoordinates.cs @@ -62,7 +62,7 @@ namespace Robust.Client.ViewVariables.Editors void OnEntered(LineEdit.LineEditEventArgs e) { - var gridVal = EntityUid.Parse(gridId.Text, "-1"); + var gridVal = EntityUid.Parse(gridId.Text); var mapManager = IoCManager.Resolve(); var xVal = float.Parse(x.Text, CultureInfo.InvariantCulture); var yVal = float.Parse(y.Text, CultureInfo.InvariantCulture); diff --git a/Robust.Client/ViewVariables/Editors/VVPropEditorEntityUid.cs b/Robust.Client/ViewVariables/Editors/VVPropEditorEntityUid.cs index 646490a8a..265988d47 100644 --- a/Robust.Client/ViewVariables/Editors/VVPropEditorEntityUid.cs +++ b/Robust.Client/ViewVariables/Editors/VVPropEditorEntityUid.cs @@ -28,7 +28,7 @@ namespace Robust.Client.ViewVariables.Editors if (!ReadOnly) { lineEdit.OnTextEntered += e => - ValueChanged(EntityUid.Parse(e.Text, ", -1")); + ValueChanged(EntityUid.Parse(e.Text)); } var vvButton = new Button() diff --git a/Robust.Server/Console/Commands/ProfileEntitySpawningCommand.cs b/Robust.Server/Console/Commands/ProfileEntitySpawningCommand.cs index 37902decc..a7a1ce928 100644 --- a/Robust.Server/Console/Commands/ProfileEntitySpawningCommand.cs +++ b/Robust.Server/Console/Commands/ProfileEntitySpawningCommand.cs @@ -43,7 +43,6 @@ public sealed class ProfileEntitySpawningCommand : IConsoleCommand GC.Collect(); - Span ents = stackalloc EntityUid[amount]; var stopwatch = new Stopwatch(); stopwatch.Start(); @@ -51,17 +50,12 @@ public sealed class ProfileEntitySpawningCommand : IConsoleCommand for (var i = 0; i < amount; i++) { - ents[i] = _entities.SpawnEntity(prototype, MapCoordinates.Nullspace); + _entities.SpawnEntity(prototype, MapCoordinates.Nullspace); } MeasureProfiler.SaveData(); shell.WriteLine($"Server: Profiled spawning {amount} entities in {stopwatch.Elapsed.TotalMilliseconds:N3} ms"); - - foreach (var ent in ents) - { - _entities.DeleteEntity(ent); - } } } #endif diff --git a/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs b/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs index e304e2c19..86f2526eb 100644 --- a/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs +++ b/Robust.Server/GameObjects/EntitySystems/MapLoaderSystem.cs @@ -5,9 +5,6 @@ using System.Globalization; using System.IO; using System.Linq; using System.Numerics; -using Arch.Core; -using Arch.Core.Utils; -using Collections.Pooled; using Robust.Server.Maps; using Robust.Shared.ContentPack; using Robust.Shared.GameObjects; @@ -157,11 +154,10 @@ public sealed class MapLoaderSystem : EntitySystem var sw = new Stopwatch(); sw.Start(); result = Deserialize(data); + _logLoader.Debug($"Loaded map in {sw.Elapsed}"); - _logLoader.Info($"Loaded map {resPath} in {sw.Elapsed}"); - var xformQuery = _serverEntityManager.GetEntityQuery(); var mapEnt = _mapManager.GetMapEntityId(mapId); - + var xformQuery = _serverEntityManager.GetEntityQuery(); var rootEnts = new List(); // aeoeoeieioe content @@ -178,8 +174,6 @@ public sealed class MapLoaderSystem : EntitySystem } } - EntityManager.CleanupArch(); - rootUids = rootEnts; } @@ -434,10 +428,6 @@ public sealed class MapLoaderSystem : EntitySystem if (data.Version >= 4) { var metaEntities = data.RootMappingNode.Get("entities"); - using var mapSaveCompType = new PooledSet() - { - typeof(MapSaveIdComponent) - }; foreach (var metaDef in metaEntities.Cast()) { @@ -457,30 +447,9 @@ public sealed class MapLoaderSystem : EntitySystem var entities = (SequenceDataNode) metaDef["entities"]; EntityPrototype? proto = null; - var count = entities.Count; - var entTotal = data.Entities.Count + count; - data.Entities.EnsureCapacity(entTotal); - data.UidEntityMap.EnsureCapacity(entTotal); - data.EntitiesToDeserialize.EnsureCapacity(entTotal); if (type != null) - { - if (_prototypeManager.TryIndex(type, out proto) && count > 1) - { - ComponentType[] compTypes; - - if (data.Options.StoreMapUids) - { - compTypes = EntityManager.GetComponentType(proto, mapSaveCompType); - } - else - { - compTypes = EntityManager.GetComponentType(proto); - } - - EntityManager.Reserve(compTypes, count); - } - } + _prototypeManager.TryIndex(type, out proto); foreach (var entityDef in entities.Cast()) { @@ -495,7 +464,6 @@ public sealed class MapLoaderSystem : EntitySystem { deletedPrototypeUids.Add(entity); } - // TODO: Move this elsewhere? else if (data.Options.StoreMapUids) { var comp = _serverEntityManager.AddComponent(entity); @@ -604,7 +572,6 @@ public sealed class MapLoaderSystem : EntitySystem _context.CurrentlyIgnoredComponents = missingComponentList.Cast().Select(x => x.Value).ToHashSet(); _serverEntityManager.FinishEntityLoad(uid, meta.EntityPrototype, _context); - if (_context.CurrentlyIgnoredComponents.Count > 0) meta.LastComponentRemoved = _timing.CurTick; } diff --git a/Robust.Server/GameObjects/EntitySystems/MapSystem.cs b/Robust.Server/GameObjects/EntitySystems/MapSystem.cs index 84c788023..119d566d5 100644 --- a/Robust.Server/GameObjects/EntitySystems/MapSystem.cs +++ b/Robust.Server/GameObjects/EntitySystems/MapSystem.cs @@ -24,6 +24,11 @@ namespace Robust.Server.GameObjects _cfg.OnValueChanged(CVars.GameDeleteEmptyGrids, SetGridDeletion, true); } + protected override void OnMapAdd(EntityUid uid, MapComponent component, ComponentAdd args) + { + EnsureComp(uid); + } + private void SetGridDeletion(bool value) { _deleteEmptyGrids = value; diff --git a/Robust.Server/GameObjects/ServerEntityManager.cs b/Robust.Server/GameObjects/ServerEntityManager.cs index 36aecc46e..280402a16 100644 --- a/Robust.Server/GameObjects/ServerEntityManager.cs +++ b/Robust.Server/GameObjects/ServerEntityManager.cs @@ -26,7 +26,7 @@ namespace Robust.Server.GameObjects /// Manager for entities -- controls things like template loading and instantiation /// [UsedImplicitly] // DI Container - public sealed partial class ServerEntityManager : EntityManager, IServerEntityManagerInternal + public sealed class ServerEntityManager : EntityManager, IServerEntityManagerInternal { private static readonly Gauge EntitiesCount = Metrics.CreateGauge( "robust_entities_count", @@ -62,7 +62,7 @@ namespace Robust.Server.GameObjects EntityUid IServerEntityManagerInternal.AllocEntity(EntityPrototype? prototype) { - return AllocEntity(prototype, out _, out _); + return AllocEntity(prototype, out _); } void IServerEntityManagerInternal.FinishEntityLoad(EntityUid entity, IEntityLoadContext? context) @@ -85,15 +85,15 @@ namespace Robust.Server.GameObjects StartEntity(entity); } - private protected override EntityUid CreateEntity(string? prototypeName, out MetaDataComponent metadata, out TransformComponent xform, IEntityLoadContext? context = null) + private protected override EntityUid CreateEntity(string? prototypeName, out MetaDataComponent metadata, IEntityLoadContext? context = null) { if (prototypeName == null) - return base.CreateEntity(prototypeName, out metadata, out xform, context); + return base.CreateEntity(prototypeName, out metadata, context); if (!PrototypeManager.TryIndex(prototypeName, out var prototype)) throw new EntityCreationException($"Attempted to spawn an entity with an invalid prototype: {prototypeName}"); - var entity = base.CreateEntity(prototype, out metadata, out xform, context); + var entity = base.CreateEntity(prototype, out metadata, context); // At this point in time, all data configure on the entity *should* be purely from the prototype. // As such, we can reset the modified ticks to Zero, @@ -159,7 +159,7 @@ namespace Robust.Server.GameObjects base.TickUpdate(frameTime, noPredictions, histogram); - EntitiesCount.Set(EntityCount); + EntitiesCount.Set(Entities.Count); } public uint GetLastMessageSequence(ICommonSession session) diff --git a/Robust.Server/Placement/PlacementManager.cs b/Robust.Server/Placement/PlacementManager.cs index ec68bc9dd..f2732ee76 100644 --- a/Robust.Server/Placement/PlacementManager.cs +++ b/Robust.Server/Placement/PlacementManager.cs @@ -251,7 +251,7 @@ namespace Robust.Server.Placement /// public void SendPlacementBegin(EntityUid mob, int range, string objectType, string alignOption) { - if (!_entityManager.TryGetComponent(mob, out ActorComponent? actor)) + if (!_entityManager.TryGetComponent(mob, out var actor)) return; var playerConnection = actor.PlayerSession.Channel; @@ -272,7 +272,7 @@ namespace Robust.Server.Placement /// public void SendPlacementBeginTile(EntityUid mob, int range, string tileType, string alignOption) { - if (!_entityManager.TryGetComponent(mob, out ActorComponent? actor)) + if (!_entityManager.TryGetComponent(mob, out var actor)) return; var playerConnection = actor.PlayerSession.Channel; @@ -293,7 +293,7 @@ namespace Robust.Server.Placement /// public void SendPlacementCancel(EntityUid mob) { - if (!_entityManager.TryGetComponent(mob, out ActorComponent? actor)) + if (!_entityManager.TryGetComponent(mob, out var actor)) return; var playerConnection = actor.PlayerSession.Channel; diff --git a/Robust.Server/Robust.Server.csproj b/Robust.Server/Robust.Server.csproj index 9ad79b9b4..eaebf8eca 100644 --- a/Robust.Server/Robust.Server.csproj +++ b/Robust.Server/Robust.Server.csproj @@ -22,7 +22,7 @@ - + diff --git a/Robust.Server/Scripting/ScriptHost.cs b/Robust.Server/Scripting/ScriptHost.cs index 06e43248e..1ae3944d6 100644 --- a/Robust.Server/Scripting/ScriptHost.cs +++ b/Robust.Server/Scripting/ScriptHost.cs @@ -3,7 +3,6 @@ using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; -using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Completion; @@ -295,9 +294,9 @@ namespace Robust.Server.Scripting loader: TextLoader.From(TextAndVersion.Create(SourceText.From(message.Code), VersionStamp.Create())) )); - var results = await (CompletionService - .GetService(document)? - .GetCompletionsAsync(document, message.Cursor) ?? Task.FromResult(null)); + var results = await CompletionService + .GetService(document) + .GetCompletionsAsync(document, message.Cursor); if (results is not null) { diff --git a/Robust.Shared.Scripting/Robust.Shared.Scripting.csproj b/Robust.Shared.Scripting/Robust.Shared.Scripting.csproj index 2b63095fa..59c108282 100644 --- a/Robust.Shared.Scripting/Robust.Shared.Scripting.csproj +++ b/Robust.Shared.Scripting/Robust.Shared.Scripting.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/Robust.Shared.Scripting/ScriptGlobalsShared.cs b/Robust.Shared.Scripting/ScriptGlobalsShared.cs index 86a18db1f..0682ed80d 100644 --- a/Robust.Shared.Scripting/ScriptGlobalsShared.cs +++ b/Robust.Shared.Scripting/ScriptGlobalsShared.cs @@ -51,7 +51,7 @@ namespace Robust.Shared.Scripting public EntityCoordinates gpos(double x, double y, int gridId) { - return gpos(x, y, new EntityUid(gridId, -1)); + return gpos(x, y, new EntityUid(gridId)); } public EntityCoordinates gpos(double x, double y, EntityUid gridId) @@ -61,12 +61,12 @@ namespace Robust.Shared.Scripting public EntityUid eid(int i) { - return new(i, -1); + return new(i); } public MapGridComponent getgrid(int i) { - return map.GetGrid(new EntityUid(i, -1)); + return map.GetGrid(new EntityUid(i)); } public MapGridComponent getgrid(EntityUid mapId) @@ -193,7 +193,7 @@ namespace Robust.Shared.Scripting public bool TryComp(EntityUid uid, out T? comp) where T : IComponent => ent.TryGetComponent(uid, out comp); - public bool HasComp(EntityUid uid) where T : IComponent + public bool HasComp(EntityUid uid) => ent.HasComponent(uid); public EntityUid Spawn(string? prototype, EntityCoordinates position) diff --git a/Robust.Shared/Console/Commands/ArchTrimCommand.cs b/Robust.Shared/Console/Commands/ArchTrimCommand.cs deleted file mode 100644 index e73cb035e..000000000 --- a/Robust.Shared/Console/Commands/ArchTrimCommand.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; - -namespace Robust.Shared.Console.Commands; - -public sealed class ArchTrimCommand : IConsoleCommand -{ - [Dependency] private readonly IEntityManager _entManager = default!; - - public string Command => "arch_trim"; - public string Description => "Runs TrimExcess on arch"; - public string Help => Command; - public void Execute(IConsoleShell shell, string argStr, string[] args) - { - _entManager.CleanupArch(); - } -} diff --git a/Robust.Shared/GameObjects/ArchetypeIterator.cs b/Robust.Shared/GameObjects/ArchetypeIterator.cs deleted file mode 100644 index 9a4f50a07..000000000 --- a/Robust.Shared/GameObjects/ArchetypeIterator.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Arch.Core; -using Collections.Pooled; - -namespace Robust.Shared.GameObjects; - -internal struct ArchetypeIterator -{ - private readonly PooledList _archetypes; - - internal ArchetypeIterator(PooledList archetypes) - { - _archetypes = archetypes; - } - - public ArchetypeEnumerator GetEnumerator() - { - return new ArchetypeEnumerator(_archetypes); - } -} - -internal struct ArchetypeEnumerator -{ - private readonly PooledList _archetypes; - private int _index; - - public ArchetypeEnumerator(PooledList archetypes) - { - _archetypes = archetypes; - _index = _archetypes.Count; - } - - public bool MoveNext() - { - while (--_index >= 0) - { - var archetype = Current; - if (archetype.EntityCount > 0) - { - return true; - } - } - - return false; - } - - public Archetype Current => _archetypes[_index]; -} diff --git a/Robust.Shared/GameObjects/ChunkIterator.cs b/Robust.Shared/GameObjects/ChunkIterator.cs deleted file mode 100644 index 5a70e318c..000000000 --- a/Robust.Shared/GameObjects/ChunkIterator.cs +++ /dev/null @@ -1,60 +0,0 @@ -using Arch.Core; - -namespace Robust.Shared.GameObjects; - -internal struct ArchChunkIterator -{ - private readonly ArchetypeEnumerator _archetypes; - - internal ArchChunkIterator(in ArchetypeEnumerator archetypes) - { - _archetypes = archetypes; - } - - public ArchChunkEnumerator GetEnumerator() - { - return new ArchChunkEnumerator(_archetypes); - } -} - -internal struct ArchChunkEnumerator -{ - private ArchetypeEnumerator _archetypes; - private int _chunkIndex; - public Chunk Current => _archetypes.Current.GetChunk(_chunkIndex); - - internal ArchChunkEnumerator(in ArchetypeEnumerator archetypes) - { - _archetypes = archetypes; - - if (_archetypes.MoveNext()) - { - _chunkIndex = _archetypes.Current.ChunkCount; - } - } - - public bool MoveNext() - { - if (--_chunkIndex >= 0 && Current.Size > 0) - { - return true; - } - - if (!_archetypes.MoveNext()) - { - return false; - } - - _chunkIndex = _archetypes.Current.ChunkCount - 1; - return true; - } -} - -internal static partial class QueryExtensions -{ - internal static ArchChunkIterator ChunkIterator(this in Query query, World world) - { - var archetypeEnumerator = new ArchetypeEnumerator(query.Matches); - return new ArchChunkIterator(in archetypeEnumerator); - } -} diff --git a/Robust.Shared/GameObjects/CompIdx.cs b/Robust.Shared/GameObjects/CompIdx.cs index a5443ebbb..73a5f8f0e 100644 --- a/Robust.Shared/GameObjects/CompIdx.cs +++ b/Robust.Shared/GameObjects/CompIdx.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Reflection; using System.Threading; -using Arch.Core.Utils; using Robust.Shared.Maths; using Robust.Shared.Utility; @@ -14,7 +13,6 @@ public readonly struct CompIdx : IEquatable private static readonly Dictionary SlowStore = new(); internal readonly int Value; - internal readonly ComponentType Type; internal static CompIdx Index() => Store.Index; @@ -64,13 +62,12 @@ public readonly struct CompIdx : IEquatable private static class Store { // ReSharper disable once StaticMemberInGenericType - public static readonly CompIdx Index = new(Interlocked.Increment(ref _CompIdxMaster), typeof(T)); + public static readonly CompIdx Index = new(Interlocked.Increment(ref _CompIdxMaster)); } - internal CompIdx(int value, in ComponentType type) + internal CompIdx(int value) { Value = value; - Type = type; } public bool Equals(CompIdx other) diff --git a/Robust.Shared/GameObjects/ComponentEventArgs.cs b/Robust.Shared/GameObjects/ComponentEventArgs.cs index 367cb2570..3a668f974 100644 --- a/Robust.Shared/GameObjects/ComponentEventArgs.cs +++ b/Robust.Shared/GameObjects/ComponentEventArgs.cs @@ -55,4 +55,17 @@ namespace Robust.Shared.GameObjects Meta = meta; } } + + public readonly struct DeletedComponentEventArgs + { + public readonly ComponentEventArgs BaseArgs; + + public readonly bool Terminating; + + public DeletedComponentEventArgs(ComponentEventArgs baseArgs, bool terminating) + { + BaseArgs = baseArgs; + Terminating = terminating; + } + } } diff --git a/Robust.Shared/GameObjects/Components/Transform/TransformComponent.cs b/Robust.Shared/GameObjects/Components/Transform/TransformComponent.cs index b02cfa5d9..fce60a934 100644 --- a/Robust.Shared/GameObjects/Components/Transform/TransformComponent.cs +++ b/Robust.Shared/GameObjects/Components/Transform/TransformComponent.cs @@ -27,7 +27,7 @@ namespace Robust.Shared.GameObjects [ViewVariables] private NetEntity NetParent => _entMan.GetNetEntity(_parent); - [DataField("parent")] internal EntityUid _parent = EntityUid.Invalid; + [DataField("parent")] internal EntityUid _parent; [DataField("pos")] internal Vector2 _localPosition = Vector2.Zero; // holds offset from grid, or offset from parent [DataField("rot")] internal Angle _localRotation; // local rotation [DataField("noRot")] internal bool _noLocalRotation; @@ -733,7 +733,7 @@ namespace Robust.Shared.GameObjects { public bool IsValid() => Uid.IsValid(); public bool Valid => IsValid(); - public static readonly BroadphaseData Invalid = new(EntityUid.Invalid, EntityUid.Invalid, false, false); + public static readonly BroadphaseData Invalid = default; // TODO include MapId if ever grids are allowed to enter null-space (leave PVS). } diff --git a/Robust.Shared/GameObjects/EntityIterator.cs b/Robust.Shared/GameObjects/EntityIterator.cs deleted file mode 100644 index b0a87ed1d..000000000 --- a/Robust.Shared/GameObjects/EntityIterator.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Arch.Core; - -namespace Robust.Shared.GameObjects; - -internal struct EntityIterator -{ - private readonly Chunk _chunk; - - internal EntityIterator(in Chunk chunk) - { - _chunk = chunk; - } - - public EntityEnumerator GetEnumerator() - { - return new EntityEnumerator(_chunk); - } -} - -internal struct EntityEnumerator -{ - private readonly Chunk _chunk; - private int _entityIndex; - public Entity Current { get; private set; } - - public EntityEnumerator(in Chunk chunk) - { - _chunk = chunk; - } - - public bool MoveNext() - { - if (_entityIndex >= _chunk.Entities.Length) - return false; - - Current = _chunk.Entities[_entityIndex]; - _entityIndex++; - return true; - } -} - -internal static partial class QueryExtensions -{ - internal static EntityIterator ChunkIterator(this in Chunk chunk) - { - return new EntityIterator(chunk); - } -} diff --git a/Robust.Shared/GameObjects/EntityManager.Arch.cs b/Robust.Shared/GameObjects/EntityManager.Arch.cs deleted file mode 100644 index e51ad4495..000000000 --- a/Robust.Shared/GameObjects/EntityManager.Arch.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Arch.Core; -using Arch.Core.Extensions; -using Arch.Core.Utils; -using Collections.Pooled; -using Robust.Shared.Prototypes; -using Robust.Shared.Utility; - -namespace Robust.Shared.GameObjects; - -public partial class EntityManager -{ - private World _world = default!; - - private static readonly ComponentType[] DefaultArchetype = new ComponentType[] - { - typeof(MetaDataComponent), - typeof(TransformComponent), - }; - - protected void InitializeArch() - { - _world = World.Create(); - } - - protected void ShutdownArch() - { - World.Destroy(_world); - } - - protected void DestroyArch(EntityUid uid) - { - var reference = _world.Reference(uid); - - if (!_world.IsAlive(reference)) - { - throw new InvalidOperationException("Tried to delete an invalid entity reference"); - } - - _world.Destroy(reference); - } - - private void SpawnEntityArch(out EntityUid entity) - { - var archEnt = _world.Create(DefaultArchetype); - var reference = _world.Reference(archEnt); - entity = new EntityUid(reference); - } - - public void CleanupArch() - { - var sw = new Stopwatch(); - sw.Start(); - var arc = _world.Archetypes.Count; - _world.TrimExcess(); - arc -= _world.Archetypes.Count; - sw.Stop(); - _sawmill.Debug($"Trimming {arc} archetypes took {sw.Elapsed.TotalMilliseconds} milliseconds"); - } - - internal ComponentType[] GetComponentType(EntityPrototype prototype, ICollection? added = null, ICollection? missing = null) - { - var compTypes = new ComponentType[prototype.Components.Count + (added?.Count ?? 0) - (missing?.Count ?? 0)]; - var idx = 0; - - foreach (var comp in prototype.Components.Values) - { - var componentType = comp.Component.GetType(); - if (missing?.Contains(componentType) == true || added?.Contains(componentType) == true) - continue; - - compTypes[idx++] = componentType; - } - - if (added != null) - { - foreach (var componentType in added) - { - if (missing?.Contains(componentType) == true) - continue; - - compTypes[idx++] = componentType; - } - } - - return compTypes; - } - - /// - /// Reserves additional slots for the specified ComponentTypes. - /// - internal void Reserve(ComponentType[] compTypes, int count) - { - _world.Reserve(compTypes, count); - } - - /// - /// WARNING: DO NOT CALL THIS UNLESS YOU KNOW WHAT YOU ARE DOING. - /// Adds the component types to the entity, shuffling its archetype. - /// - internal void AddComponentRange(EntityUid uid, PooledList compTypes) - { - DebugTools.Assert(compTypes.Count > 0); - _world.AddRange(uid, compTypes); - } - - internal void RemoveComponentRange(EntityUid uid, PooledList compTypes) - { - DebugTools.Assert(compTypes.Count > 0); - _world.RemoveRange(uid, compTypes.Span); - } -} diff --git a/Robust.Shared/GameObjects/EntityManager.Components.cs b/Robust.Shared/GameObjects/EntityManager.Components.cs index 086d982ae..068ffbd6b 100644 --- a/Robust.Shared/GameObjects/EntityManager.Components.cs +++ b/Robust.Shared/GameObjects/EntityManager.Components.cs @@ -2,10 +2,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using Arch.Core; -using Arch.Core.Utils; using JetBrains.Annotations; using Robust.Shared.GameStates; using Robust.Shared.Log; @@ -31,26 +30,62 @@ namespace Robust.Shared.GameObjects public IComponentFactory ComponentFactory => _componentFactory; private const int TypeCapacity = 32; + private const int ComponentCollectionCapacity = 1024; private const int EntityCapacity = 1024; private const int NetComponentCapacity = 8; private static readonly ComponentState DefaultComponentState = new(); + private readonly Dictionary> _entTraitDict + = new(); + + private Dictionary[] _entTraitArray + = Array.Empty>(); + private readonly HashSet _deleteSet = new(TypeCapacity); + private UniqueIndexHkm _entCompIndex = + new(ComponentCollectionCapacity); + /// public event Action? ComponentAdded; /// public event Action? ComponentRemoved; + public void InitializeComponents() + { + if (Initialized) + throw new InvalidOperationException("Already initialized."); + + FillComponentDict(); + _componentFactory.ComponentAdded += OnComponentAdded; + } + /// /// Instantly clears all components from the manager. This will NOT shut them down gracefully. /// Any entities relying on existing components will be broken. /// public void ClearComponents() { + _entCompIndex.Clear(); _deleteSet.Clear(); + foreach (var dict in _entTraitDict.Values) + { + dict.Clear(); + } + } + + private void AddComponentRefType(CompIdx type) + { + var dict = new Dictionary(); + _entTraitDict.Add(_componentFactory.IdxToType(type), dict); + CompIdx.AssignArray(ref _entTraitArray, type, dict); + } + + private void OnComponentAdded(ComponentRegistration obj) + { + AddComponentRefType(obj.Idx); } #region Component Management @@ -58,17 +93,15 @@ namespace Robust.Shared.GameObjects /// public int Count() where T : IComponent { - return _world.CountEntities(new QueryDescription().WithAll()); + var dict = _entTraitDict[typeof(T)]; + return dict.Count; } /// public int Count(Type component) { - var query = new QueryDescription - { - All = new ComponentType[] { component } - }; - return _world.CountEntities(in query); + var dict = _entTraitDict[component]; + return dict.Count; } public void InitializeComponents(EntityUid uid, MetaDataComponent? metadata = null) @@ -90,6 +123,18 @@ namespace Robust.Shared.GameObjects LifeInitialize(comp, CompIdx.Index(comp.GetType())); } +#if DEBUG + // Second integrity check in case of. + foreach (var t in _entCompIndex[uid]) + { + if (!t.Deleted && !t.Initialized) + { + DebugTools.Assert( + $"Component {t.GetType()} was not initialized at the end of {nameof(InitializeComponents)}."); + } + } + +#endif DebugTools.Assert(metadata.EntityLifeStage == EntityLifeStage.Initializing); metadata.EntityLifeStage = EntityLifeStage.Initialized; } @@ -180,7 +225,7 @@ namespace Robust.Shared.GameObjects public CompInitializeHandle AddComponentUninitialized(EntityUid uid) where T : IComponent, new() { var reg = _componentFactory.GetRegistration(); - var newComponent = _componentFactory.GetComponent(); + var newComponent = (T)_componentFactory.GetComponent(reg); #pragma warning disable CS0618 // Type or member is obsolete newComponent.Owner = uid; #pragma warning restore CS0618 // Type or member is obsolete @@ -188,13 +233,13 @@ namespace Robust.Shared.GameObjects if (!uid.IsValid() || !EntityExists(uid)) throw new ArgumentException($"Entity {uid} is not valid.", nameof(uid)); - AddComponentInternal(uid, newComponent, false); + AddComponentInternal(uid, newComponent, false, true); return new CompInitializeHandle(this, uid, newComponent, reg.Idx); } /// - public void AddComponent(EntityUid uid, T component, MetaDataComponent? metadata = null) where T : IComponent + public void AddComponent(EntityUid uid, T component, bool overwrite = false, MetaDataComponent? metadata = null) where T : IComponent { if (!uid.IsValid() || !EntityExists(uid)) throw new ArgumentException($"Entity {uid} is not valid.", nameof(uid)); @@ -212,41 +257,53 @@ namespace Robust.Shared.GameObjects } #pragma warning restore CS0618 // Type or member is obsolete - AddComponentInternal(uid, component, false, metadata); + AddComponentInternal(uid, component, overwrite, false, metadata); } - private void AddComponentInternal(EntityUid uid, T component, bool skipInit, MetaDataComponent? metadata = null) where T : IComponent + private void AddComponentInternal(EntityUid uid, T component, bool overwrite, bool skipInit, MetaDataComponent? metadata = null) where T : IComponent { // get interface aliases for mapping var reg = _componentFactory.GetRegistration(component); - AddComponentInternal(uid, component, reg, skipInit, metadata); + AddComponentInternal(uid, component, reg, overwrite, skipInit, metadata); } - // TODO: Clean up this mess. - - internal void AddComponentInternalOnly(EntityUid uid, T component, ComponentRegistration reg, MetaDataComponent? metadata = null) where T : IComponent + private void AddComponentInternal(EntityUid uid, T component, ComponentRegistration reg, bool overwrite, bool skipInit, MetaDataComponent? metadata = null) where T : IComponent { // We can't use typeof(T) here in case T is just Component DebugTools.Assert(component is MetaDataComponent || (metadata ?? MetaQuery.GetComponent(uid)).EntityLifeStage < EntityLifeStage.Terminating, $"Attempted to add a {component.GetType().Name} component to an entity ({ToPrettyString(uid)}) while it is terminating"); - // We can't use typeof(T) here in case T is just Component - DebugTools.Assert(component is MetaDataComponent || - (metadata ?? MetaQuery.GetComponent(uid)).EntityLifeStage < EntityLifeStage.Terminating, - $"Attempted to add a {reg.Name} component to an entity ({ToPrettyString(uid)}) while it is terminating"); + // Check that there is no existing component. + var type = reg.Idx; + var dict = _entTraitArray[type.Value]; + DebugTools.Assert(dict != null); - // TODO optimize this - // Need multi-comp adds so we can remove this call probably. - if (!_world.Has(uid, reg.Idx.Type)) - _world.Add(uid, (object) component); - else + // Code block to restrict access to ref comp. { - // Okay so technically it may have an existing one not null but pointing to a stale component - // hence just set it and act casual. - _world.Set(uid, (object) component); + ref var comp = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, uid, out var exists); + if (exists) + { + if (!overwrite && !comp!.Deleted) + { + throw new InvalidOperationException( + $"Component reference type {reg.Name} already occupied by {comp}"); + } + + // This will invalidate the comp ref as it removes the key from the dictionary. + // This is inefficient, but component overriding rarely ever happens. + RemoveComponentImmediate(comp!, uid, false, metadata); + dict.Add(uid, component); + } + else + { + comp = component; + } } + // actually ADD the component + _entCompIndex.Add(uid, component); + // add the component to the netId grid if (reg.NetID != null) { @@ -259,11 +316,7 @@ namespace Robust.Shared.GameObjects { component.Networked = false; } - } - internal void AddComponentEvents(EntityUid uid, T component, ComponentRegistration reg, bool skipInit, - MetaDataComponent? metadata = null) where T : IComponent - { var eventArgs = new AddedComponentEventArgs(new ComponentEventArgs(component, uid), reg); ComponentAdded?.Invoke(eventArgs); _eventBus.OnComponentAdded(eventArgs); @@ -275,8 +328,7 @@ namespace Robust.Shared.GameObjects metadata ??= MetaQuery.GetComponentInternal(uid); - // Bur this overhead sucks. - if (metadata.EntityLifeStage < EntityLifeStage.Initializing) + if (!metadata.EntityInitialized && !metadata.EntityInitializing) return; if (component.Networked) @@ -291,12 +343,6 @@ namespace Robust.Shared.GameObjects EventBus.RaiseComponentEvent(component, MapInitEventInstance); } - internal void AddComponentInternal(EntityUid uid, T component, ComponentRegistration reg, bool skipInit, MetaDataComponent? metadata = null) where T : IComponent - { - AddComponentInternalOnly(uid, component, reg, metadata); - AddComponentEvents(uid, component, reg, skipInit, metadata); - } - /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool RemoveComponent(EntityUid uid, MetaDataComponent? meta = null) @@ -311,7 +357,7 @@ namespace Robust.Shared.GameObjects if (!TryGetComponent(uid, type, out var comp)) return false; - RemoveComponentImmediate(comp, uid, false, true, meta); + RemoveComponentImmediate(comp, uid, false, meta); return true; } @@ -325,7 +371,7 @@ namespace Robust.Shared.GameObjects if (!TryGetComponent(uid, netId, out var comp, meta)) return false; - RemoveComponentImmediate(comp, uid, false, true, meta); + RemoveComponentImmediate(comp, uid, false, meta); return true; } @@ -333,7 +379,7 @@ namespace Robust.Shared.GameObjects [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RemoveComponent(EntityUid uid, IComponent component, MetaDataComponent? meta = null) { - RemoveComponentImmediate(component, uid, false, true, meta); + RemoveComponentImmediate(component, uid, false, meta); } /// @@ -373,37 +419,59 @@ namespace Robust.Shared.GameObjects RemoveComponentDeferred(component, owner, false); } + /// + public void RemoveComponentDeferred(EntityUid owner, Component component) + { + RemoveComponentDeferred(component, owner, false); + } + + private static IEnumerable InSafeOrder(IEnumerable comps, bool forCreation = false) + { + static int Sequence(IComponent x) + => x switch + { + MetaDataComponent _ => 0, + TransformComponent _ => 1, + PhysicsComponent _ => 2, + _ => int.MaxValue + }; + + return forCreation + ? comps.OrderBy(Sequence) + : comps.OrderByDescending(Sequence); + } + /// public void RemoveComponents(EntityUid uid, MetaDataComponent? meta = null) { - var objComps = _world.GetAllComponents(uid); - // Reverse order - for (var i = objComps.Length - 1; i >= 0; i--) + if (!MetaQuery.Resolve(uid, ref meta)) + return; + + foreach (var comp in InSafeOrder(_entCompIndex[uid])) { - var comp = (IComponent) objComps[i]!; - RemoveComponentImmediate(comp, uid, false, false, meta); + RemoveComponentImmediate(comp, uid, false, meta); } } /// public void DisposeComponents(EntityUid uid, MetaDataComponent? meta = null) { - var objComps = _world.GetAllComponents(uid); + if (!MetaQuery.Resolve(uid, ref meta)) + return; - // Reverse order - for (var i = objComps.Length - 1; i >= 0; i--) + foreach (var comp in InSafeOrder(_entCompIndex[uid])) { - var comp = (IComponent) objComps[i]!; - try { - RemoveComponentImmediate(comp, uid, true, false, meta); + RemoveComponentImmediate(comp, uid, true, meta); } - catch (Exception exc) + catch (Exception) { - _sawmill.Error($"Caught exception while trying to remove component {_componentFactory.GetComponentName(comp.GetType())} from entity '{ToPrettyString(uid)}'\n{exc.StackTrace}"); + _sawmill.Error($"Caught exception while trying to remove component {_componentFactory.GetComponentName(comp.GetType())} from entity '{ToPrettyString(uid)}'"); } } + + _entCompIndex.Remove(uid); } private void RemoveComponentDeferred(IComponent component, EntityUid uid, bool terminating) @@ -446,22 +514,8 @@ namespace Robust.Shared.GameObjects #endif } - /// - /// WARNING: Do not call this unless you're sure of what you're doing! - /// - internal void RemoveComponentInternal(EntityUid uid, IComponent component, bool terminating, bool archetypeChange, MetaDataComponent? metadata = null) - { - // I hate this but also didn't want the MetaQuery.GetComponent overhead. - // and with archetypes we want to avoid moves at all costs. - RemoveComponentImmediate(component, uid, terminating, archetypeChange, metadata); - } - - /// - /// Removes a component. - /// - /// Is the entity terminating. - /// Should we handle the archetype change or is it being handled externally. - private void RemoveComponentImmediate(IComponent component, EntityUid uid, bool terminating, bool archetypeChange, MetaDataComponent? meta = null) + private void RemoveComponentImmediate(IComponent component, EntityUid uid, bool terminating, + MetaDataComponent? meta) { if (component.Deleted) { @@ -494,13 +548,13 @@ namespace Robust.Shared.GameObjects _runtimeLog.LogException(e, nameof(RemoveComponentImmediate)); } #endif - DeleteComponent(uid, component, terminating, archetypeChange, meta); + DeleteComponent(uid, component, terminating, meta); } /// public void CullRemovedComponents() { - foreach (var component in _deleteSet) + foreach (var component in InSafeOrder(_deleteSet)) { if (component.Deleted) continue; @@ -529,13 +583,13 @@ namespace Robust.Shared.GameObjects _runtimeLog.LogException(e, nameof(CullRemovedComponents)); } #endif - DeleteComponent(uid, component, false, true); + DeleteComponent(uid, component, false); } _deleteSet.Clear(); } - private void DeleteComponent(EntityUid entityUid, IComponent component, bool terminating, bool archetypeChange, MetaDataComponent? metadata = null) + private void DeleteComponent(EntityUid entityUid, IComponent component, bool terminating, MetaDataComponent? metadata = null) { if (!MetaQuery.ResolveInternal(entityUid, ref metadata)) return; @@ -559,12 +613,11 @@ namespace Robust.Shared.GameObjects } } - if (archetypeChange) - { - DebugTools.Assert(_world.Has(entityUid, reg.Idx.Type)); - if (_world.Has(entityUid, reg.Idx.Type)) - _world.Remove(entityUid, reg.Idx.Type); - } + _entTraitArray[reg.Idx.Value].Remove(entityUid); + + // TODO if terminating the entity, maybe defer this? + // _entCompIndex.Remove(uid) gets called later on anyways. + _entCompIndex.Remove(entityUid, component); DebugTools.Assert(_netMan.IsClient // Client side prediction can set LastComponentRemoved to some future tick, @@ -573,17 +626,16 @@ namespace Robust.Shared.GameObjects /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasComponent(EntityUid uid) where T : IComponent + public bool HasComponent(EntityUid uid) { - if (!IsAlive(uid) || !_world.TryGet(uid, out T? comp)) - return false; - - return !comp!.Deleted; + var dict = _entTraitArray[CompIdx.ArrayIndex()]; + DebugTools.Assert(dict != null, $"Unknown component: {typeof(T).Name}"); + return dict.TryGetValue(uid, out var comp) && !comp.Deleted; } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasComponent(EntityUid? uid) where T : IComponent + public bool HasComponent(EntityUid? uid) { return uid.HasValue && HasComponent(uid.Value); } @@ -592,10 +644,8 @@ namespace Robust.Shared.GameObjects [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool HasComponent(EntityUid uid, Type type) { - if (!IsAlive(uid) || !_world.TryGet(uid, type, out var comp)) - return false; - - return !((IComponent)comp!).Deleted; + var dict = _entTraitDict[type]; + return dict.TryGetValue(uid, out var comp) && !comp.Deleted; } /// @@ -607,7 +657,8 @@ namespace Robust.Shared.GameObjects return false; } - return HasComponent(uid.Value, type); + var dict = _entTraitDict[type]; + return dict.TryGetValue(uid.Value, out var comp) && !comp.Deleted; } /// @@ -692,16 +743,27 @@ namespace Robust.Shared.GameObjects [MethodImpl(MethodImplOptions.AggressiveInlining)] public T GetComponent(EntityUid uid) where T : IComponent { - if (IsAlive(uid) && _world.TryGet(uid, out T? comp)) - return comp!; + var dict = _entTraitArray[CompIdx.ArrayIndex()]; + DebugTools.Assert(dict != null, $"Unknown component: {typeof(T).Name}"); + if (dict.TryGetValue(uid, out var comp)) + { + if (!comp.Deleted) + { + return (T)comp; + } + } throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(T)}"); } public IComponent GetComponent(EntityUid uid, CompIdx type) { - if (TryGetComponent(uid, type, out var comp)) - return comp; + var dict = _entTraitArray[type.Value]; + if (dict.TryGetValue(uid, out var comp)) + { + if (!comp.Deleted) + return comp; + } throw new KeyNotFoundException($"Entity {uid} does not have a component of type {_componentFactory.IdxToType(type)}"); } @@ -709,8 +771,15 @@ namespace Robust.Shared.GameObjects /// public IComponent GetComponent(EntityUid uid, Type type) { - if (TryGetComponent(uid, type, out var component)) - return component; + // ReSharper disable once InvertIf + var dict = _entTraitDict[type]; + if (dict.TryGetValue(uid, out var comp)) + { + if (!comp.Deleted) + { + return comp; + } + } throw new KeyNotFoundException($"Entity {uid} does not have a component of type {type}"); } @@ -724,21 +793,26 @@ namespace Robust.Shared.GameObjects /// public IComponent GetComponentInternal(EntityUid uid, CompIdx type) { - if (TryGetComponent(uid, type, out var component)) - return component; + var dict = _entTraitArray[type.Value]; + if (dict.TryGetValue(uid, out var comp)) + { + return comp; + } throw new KeyNotFoundException($"Entity {uid} does not have a component of type {type}"); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGetComponent(EntityUid uid, [NotNullWhen(true)] out T? component) where T : IComponent? + public bool TryGetComponent(EntityUid uid, [NotNullWhen(true)] out T? component) { - if (IsAlive(uid) && _world.TryGet(uid, out component)) + var dict = _entTraitArray[CompIdx.ArrayIndex()]; + DebugTools.Assert(dict != null, $"Unknown component: {typeof(T).Name}"); + if (dict.TryGetValue(uid, out var comp)) { - DebugTools.Assert(component != null); - if (!component!.Deleted) + if (!comp.Deleted) { + component = (T)comp; return true; } } @@ -748,7 +822,7 @@ namespace Robust.Shared.GameObjects } /// - public bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out T? component) where T : IComponent? + public bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out T? component) { if (!uid.HasValue) { @@ -772,11 +846,12 @@ namespace Robust.Shared.GameObjects /// public bool TryGetComponent(EntityUid uid, Type type, [NotNullWhen(true)] out IComponent? component) { - if (IsAlive(uid) && _world.TryGet(uid, type, out var comp)) + var dict = _entTraitDict[type]; + if (dict.TryGetValue(uid, out var comp)) { - component = (IComponent)(comp!); - if (!component.Deleted) + if (!comp.Deleted) { + component = comp; return true; } } @@ -787,11 +862,14 @@ namespace Robust.Shared.GameObjects public bool TryGetComponent(EntityUid uid, CompIdx type, [NotNullWhen(true)] out IComponent? component) { - if (IsAlive(uid) && _world.TryGet(uid, type.Type, out var comp)) + var dict = _entTraitArray[type.Value]; + if (dict.TryGetValue(uid, out var comp)) { - component = (IComponent)comp!; - if (component != null! && !component.Deleted) + if (!comp.Deleted) + { + component = comp; return true; + } } component = null; @@ -808,7 +886,18 @@ namespace Robust.Shared.GameObjects return false; } - return TryGetComponent(uid.Value, type, out component); + var dict = _entTraitDict[type]; + if (dict.TryGetValue(uid.Value, out var comp)) + { + if (!comp.Deleted) + { + component = comp; + return true; + } + } + + component = null; + return false; } /// @@ -841,21 +930,24 @@ namespace Robust.Shared.GameObjects public EntityQuery GetEntityQuery() where TComp1 : IComponent { - return new EntityQuery(this, _world, null, _resolveSawmill); + var comps = _entTraitArray[CompIdx.ArrayIndex()]; + DebugTools.Assert(comps != null, $"Unknown component: {typeof(TComp1).Name}"); + return new EntityQuery(comps, _resolveSawmill); } public EntityQuery GetEntityQuery(Type type) { - return new EntityQuery(this, _world, type, _resolveSawmill); + var comps = _entTraitArray[CompIdx.ArrayIndex(type)]; + DebugTools.Assert(comps != null, $"Unknown component: {type.Name}"); + return new EntityQuery(comps, _resolveSawmill); } /// public IEnumerable GetComponents(EntityUid uid) { - foreach (var obj in _world.GetAllComponents(uid)) + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (var comp in _entCompIndex[uid].ToArray()) { - var comp = (IComponent)(obj!); - if (comp.Deleted) continue; yield return comp; @@ -865,7 +957,8 @@ namespace Robust.Shared.GameObjects /// public int ComponentCount(EntityUid uid) { - return _world.GetArchetype(uid).Types.Length; + var comps = _entCompIndex[uid]; + return comps.Count; } /// @@ -874,29 +967,26 @@ namespace Robust.Shared.GameObjects /// private void CopyComponentsInto(ref Span comps, EntityUid uid) { - var set = _world.GetAllComponents(uid); - - if (set.Length > comps.Length) + var set = _entCompIndex[uid]; + if (set.Count > comps.Length) { - comps = new IComponent[set.Length]; + comps = new IComponent[set.Count]; } var i = 0; foreach (var c in set) { - comps[i++] = (IComponent)c!; + comps[i++] = c; } } /// public IEnumerable GetComponents(EntityUid uid) { - var comps = _world.GetAllComponents(uid); - + var comps = _entCompIndex[uid].ToArray(); foreach (var comp in comps) { - var component = (IComponent)comp!; - if (component.Deleted || component is not T tComp) continue; + if (comp.Deleted || comp is not T tComp) continue; yield return tComp; } @@ -950,14 +1040,17 @@ namespace Robust.Shared.GameObjects public AllEntityQueryEnumerator AllEntityQueryEnumerator() where TComp1 : IComponent { - return new AllEntityQueryEnumerator(_world); + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + return new AllEntityQueryEnumerator(trait1); } public AllEntityQueryEnumerator AllEntityQueryEnumerator() where TComp1 : IComponent where TComp2 : IComponent { - return new AllEntityQueryEnumerator(_world); + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + return new AllEntityQueryEnumerator(trait1, trait2); } public AllEntityQueryEnumerator AllEntityQueryEnumerator() @@ -965,7 +1058,10 @@ namespace Robust.Shared.GameObjects where TComp2 : IComponent where TComp3 : IComponent { - return new AllEntityQueryEnumerator(_world); + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait3 = _entTraitArray[CompIdx.ArrayIndex()]; + return new AllEntityQueryEnumerator(trait1, trait2, trait3); } public AllEntityQueryEnumerator AllEntityQueryEnumerator() @@ -974,20 +1070,27 @@ namespace Robust.Shared.GameObjects where TComp3 : IComponent where TComp4 : IComponent { - return new AllEntityQueryEnumerator(_world); + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait3 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait4 = _entTraitArray[CompIdx.ArrayIndex()]; + return new AllEntityQueryEnumerator(trait1, trait2, trait3, trait4); } public EntityQueryEnumerator EntityQueryEnumerator() where TComp1 : IComponent { - return new EntityQueryEnumerator(_world); + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + return new EntityQueryEnumerator(trait1, MetaQuery); } public EntityQueryEnumerator EntityQueryEnumerator() where TComp1 : IComponent where TComp2 : IComponent { - return new EntityQueryEnumerator(_world); + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + return new EntityQueryEnumerator(trait1, trait2, MetaQuery); } public EntityQueryEnumerator EntityQueryEnumerator() @@ -995,7 +1098,10 @@ namespace Robust.Shared.GameObjects where TComp2 : IComponent where TComp3 : IComponent { - return new EntityQueryEnumerator(_world); + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait3 = _entTraitArray[CompIdx.ArrayIndex()]; + return new EntityQueryEnumerator(trait1, trait2, trait3, MetaQuery); } public EntityQueryEnumerator EntityQueryEnumerator() @@ -1004,26 +1110,38 @@ namespace Robust.Shared.GameObjects where TComp3 : IComponent where TComp4 : IComponent { - return new EntityQueryEnumerator(_world); + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait3 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait4 = _entTraitArray[CompIdx.ArrayIndex()]; + + return new EntityQueryEnumerator(trait1, trait2, trait3, trait4, MetaQuery); } /// public IEnumerable EntityQuery(bool includePaused = false) where T : IComponent { + var comps = _entTraitArray[CompIdx.ArrayIndex()]; + DebugTools.Assert(comps != null, $"Unknown component: {typeof(T).Name}"); + if (includePaused) { - var query = new AllEntityQueryEnumerator(_world); - while (query.MoveNext(out var comp)) + foreach (var t1Comp in comps.Values) { - yield return comp; + if (t1Comp.Deleted) continue; + + yield return (T)t1Comp; } } else { - var query = new EntityQueryEnumerator(_world); - while (query.MoveNext(out var comp)) + foreach (var (uid, t1Comp) in comps) { - yield return comp; + if (t1Comp.Deleted || !MetaQuery.TryGetComponentInternal(uid, out var metaComp)) continue; + + if (metaComp.EntityPaused) continue; + + yield return (T)t1Comp; } } } @@ -1033,20 +1151,42 @@ namespace Robust.Shared.GameObjects where TComp1 : IComponent where TComp2 : IComponent { + // this would prob be faster if trait1 was a list (or an array of structs hue). + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + + // you really want trait1 to be the smaller set of components if (includePaused) { - var query = new AllEntityQueryEnumerator(_world); - while (query.MoveNext(out var comp1, out var comp2)) + foreach (var (uid, t1Comp) in trait1) { - yield return (comp1, comp2); + if (!trait2.TryGetValue(uid, out var t2Comp) || t2Comp.Deleted) + continue; + + yield return ( + (TComp1) t1Comp, + (TComp2) t2Comp); } } else { - var query = new EntityQueryEnumerator(_world); - while (query.MoveNext(out var comp1, out var comp2)) + var metaComps = _entTraitArray[CompIdx.ArrayIndex()]; + + foreach (var (uid, t1Comp) in trait1) { - yield return (comp1, comp2); + // Check paused last because 90% of the time the component's likely not gonna be paused. + if (!trait2.TryGetValue(uid, out var t2Comp) || t2Comp.Deleted) + continue; + + if (t1Comp.Deleted || !metaComps.TryGetValue(uid, out var metaComp)) continue; + + var meta = (MetaDataComponent)metaComp; + + if (meta.EntityPaused) continue; + + yield return ( + (TComp1) t1Comp, + (TComp2) t2Comp); } } } @@ -1057,20 +1197,49 @@ namespace Robust.Shared.GameObjects where TComp2 : IComponent where TComp3 : IComponent { + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait3 = _entTraitArray[CompIdx.ArrayIndex()]; + if (includePaused) { - var query = new AllEntityQueryEnumerator(_world); - while (query.MoveNext(out var comp1, out var comp2, out var comp3)) + foreach (var (uid, t1Comp) in trait1) { - yield return (comp1, comp2, comp3); + if (!trait2.TryGetValue(uid, out var t2Comp) || t2Comp.Deleted) + continue; + + if (!trait3.TryGetValue(uid, out var t3Comp) || t3Comp.Deleted) + continue; + + yield return ( + (TComp1) t1Comp, + (TComp2) t2Comp, + (TComp3) t3Comp); } } else { - var query = new EntityQueryEnumerator(_world); - while (query.MoveNext(out var comp1, out var comp2, out var comp3)) + var metaComps = _entTraitArray[CompIdx.ArrayIndex()]; + + foreach (var (uid, t1Comp) in trait1) { - yield return (comp1, comp2, comp3); + // Check paused last because 90% of the time the component's likely not gonna be paused. + if (!trait2.TryGetValue(uid, out var t2Comp) || t2Comp.Deleted) + continue; + + if (!trait3.TryGetValue(uid, out var t3Comp) || t3Comp.Deleted) + continue; + + if (t1Comp.Deleted || !metaComps.TryGetValue(uid, out var metaComp)) continue; + + var meta = (MetaDataComponent)metaComp; + + if (meta.EntityPaused) continue; + + yield return ( + (TComp1) t1Comp, + (TComp2) t2Comp, + (TComp3) t3Comp); } } } @@ -1083,20 +1252,58 @@ namespace Robust.Shared.GameObjects where TComp3 : IComponent where TComp4 : IComponent { + var trait1 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait2 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait3 = _entTraitArray[CompIdx.ArrayIndex()]; + var trait4 = _entTraitArray[CompIdx.ArrayIndex()]; + if (includePaused) { - var query = new AllEntityQueryEnumerator(_world); - while (query.MoveNext(out var comp1, out var comp2, out var comp3, out var comp4)) + foreach (var (uid, t1Comp) in trait1) { - yield return (comp1, comp2, comp3, comp4); + if (!trait2.TryGetValue(uid, out var t2Comp) || t2Comp.Deleted) + continue; + + if (!trait3.TryGetValue(uid, out var t3Comp) || t3Comp.Deleted) + continue; + + if (!trait4.TryGetValue(uid, out var t4Comp) || t4Comp.Deleted) + continue; + + yield return ( + (TComp1) t1Comp, + (TComp2) t2Comp, + (TComp3) t3Comp, + (TComp4) t4Comp); } } else { - var query = new EntityQueryEnumerator(_world); - while (query.MoveNext(out var comp1, out var comp2, out var comp3, out var comp4)) + var metaComps = _entTraitArray[CompIdx.ArrayIndex()]; + + foreach (var (uid, t1Comp) in trait1) { - yield return (comp1, comp2, comp3, comp4); + // Check paused last because 90% of the time the component's likely not gonna be paused. + if (!trait2.TryGetValue(uid, out var t2Comp) || t2Comp.Deleted) + continue; + + if (!trait3.TryGetValue(uid, out var t3Comp) || t3Comp.Deleted) + continue; + + if (!trait4.TryGetValue(uid, out var t4Comp) || t4Comp.Deleted) + continue; + + if (t1Comp.Deleted || !metaComps.TryGetValue(uid, out var metaComp)) continue; + + var meta = (MetaDataComponent)metaComp; + + if (meta.EntityPaused) continue; + + yield return ( + (TComp1) t1Comp, + (TComp2) t2Comp, + (TComp3) t3Comp, + (TComp4) t4Comp); } } } @@ -1106,34 +1313,24 @@ namespace Robust.Shared.GameObjects /// public IEnumerable<(EntityUid Uid, IComponent Component)> GetAllComponents(Type type, bool includePaused = false) { - var query = new QueryDescription(); + var comps = _entTraitDict[type]; - // TODO arch paused component if (includePaused) { - // TODO arch pool - query.All = new ComponentType[] { type }; + foreach (var (uid, comp) in comps) + { + if (comp.Deleted) continue; + + yield return (uid, comp); + } } else { - query.All = new ComponentType[] { type, typeof(MetaDataComponent) }; - } - - foreach (var chunk in _world.Query(query).ChunkIterator(_world)) - { - var components = chunk.GetArray(type); - var metas = includePaused ? default : chunk.GetArray(); - - for (var i = 0; i < chunk.Size; i++) + foreach (var (uid, comp) in comps) { - var comp = (IComponent)(components.GetValue(i))!; - if (comp.Deleted) - continue; + if (comp.Deleted || !MetaQuery.TryGetComponent(uid, out var meta) || meta.EntityPaused) continue; - if (!includePaused && metas![i].EntityPaused) - continue; - - yield return (_world.Reference(chunk.Entities[i]), comp); + yield return (uid, comp); } } } @@ -1156,6 +1353,18 @@ namespace Robust.Shared.GameObjects } #endregion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void FillComponentDict() + { + _entTraitDict.Clear(); + Array.Fill(_entTraitArray, null); + + foreach (var refType in _componentFactory.GetAllRefTypes()) + { + AddComponentRefType(refType); + } + } } public readonly struct NetComponentEnumerable @@ -1188,16 +1397,12 @@ namespace Robust.Shared.GameObjects public readonly struct EntityQuery where TComp1 : IComponent { - private readonly IEntityManager _manager; - private readonly World _world; - private readonly ComponentType? _type; + private readonly Dictionary _traitDict; private readonly ISawmill _sawmill; - public EntityQuery(IEntityManager manager, World world, ComponentType? type, ISawmill sawmill) + public EntityQuery(Dictionary traitDict, ISawmill sawmill) { - _manager = manager; - _world = world; - _type = type; + _traitDict = traitDict; _sawmill = sawmill; } @@ -1205,16 +1410,17 @@ namespace Robust.Shared.GameObjects [Pure] public TComp1 GetComponent(EntityUid uid) { - return _type == null - ? _manager.GetComponent(uid) - : (TComp1)_manager.GetComponent(uid, _type.Value.Type); + if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted) + return (TComp1) comp; + + throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(TComp1)}"); } [MethodImpl(MethodImplOptions.AggressiveInlining), Pure] public Entity Get(EntityUid uid) { - if (_world.TryGet(uid, out TComp1? comp) && comp != null && !comp.Deleted) - return new Entity(uid, comp); + if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted) + return new Entity(uid, (TComp1) comp); throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(TComp1)}"); } @@ -1236,39 +1442,28 @@ namespace Robust.Shared.GameObjects [Pure] public bool TryGetComponent(EntityUid uid, [NotNullWhen(true)] out TComp1? component) { - if (_type != null) + if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted) { - if (_manager.TryGetComponent(uid, _type.Value.Type, out var comp)) - { - component = (TComp1) comp; - return true; - } + component = (TComp1) comp; + return true; + } - component = default; - return false; - } - else - { - return _manager.TryGetComponent(uid, out component); - } + component = default; + return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public bool HasComponent(EntityUid uid) { - return _type == null - ? _manager.HasComponent(uid) - : _manager.HasComponent(uid, _type.Value.Type); + return _traitDict.TryGetValue(uid, out var comp) && !comp.Deleted; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] public bool HasComponent(EntityUid? uid) { - return _type == null - ? _manager.HasComponent(uid) - : _manager.HasComponent(uid, _type.Value.Type); + return uid != null && HasComponent(uid.Value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1281,8 +1476,9 @@ namespace Robust.Shared.GameObjects return true; } - if (TryGetComponent(uid, out component)) + if (_traitDict.TryGetValue(uid, out var comp) && !comp.Deleted) { + component = (TComp1)comp; return true; } @@ -1317,8 +1513,8 @@ namespace Robust.Shared.GameObjects [Pure] internal TComp1 GetComponentInternal(EntityUid uid) { - if (TryGetComponentInternal(uid, out var comp)) - return comp; + if (_traitDict.TryGetValue(uid, out var comp)) + return (TComp1) comp; throw new KeyNotFoundException($"Entity {uid} does not have a component of type {typeof(TComp1)}"); } @@ -1346,8 +1542,9 @@ namespace Robust.Shared.GameObjects [Pure] internal bool TryGetComponentInternal(EntityUid uid, [NotNullWhen(true)] out TComp1? component) { - if (_world.TryGet(uid, out component!)) + if (_traitDict.TryGetValue(uid, out var comp)) { + component = (TComp1) comp; return true; } @@ -1362,8 +1559,7 @@ namespace Robust.Shared.GameObjects [Pure] internal bool HasComponentInternal(EntityUid uid) { - // TODO fix checking deleted - return _world.TryGet(uid, out TComp1? comp) && !comp!.Deleted; + return _traitDict.TryGetValue(uid, out var comp) && !comp.Deleted; } /// @@ -1379,8 +1575,9 @@ namespace Robust.Shared.GameObjects return true; } - if (TryGetComponentInternal(uid, out component)) + if (_traitDict.TryGetValue(uid, out var comp)) { + component = (TComp1)comp; return true; } @@ -1410,47 +1607,47 @@ namespace Robust.Shared.GameObjects /// /// Returns all matching unpaused components. /// - public struct EntityQueryEnumerator + public struct EntityQueryEnumerator : IDisposable where TComp1 : IComponent { - private readonly World _world; - private ArchChunkEnumerator _chunkEnumerator; - private int _index; + private Dictionary.Enumerator _traitDict; + private readonly EntityQuery _metaQuery; - public EntityQueryEnumerator(World world) + public EntityQueryEnumerator( + Dictionary traitDict, + EntityQuery metaQuery) { - _world = world; - _chunkEnumerator = world.Query(new QueryDescription().WithAll()).ChunkIterator(world).GetEnumerator(); - if (_chunkEnumerator.MoveNext()) - { - _index = _chunkEnumerator.Current.Size; - } + _traitDict = traitDict.GetEnumerator(); + _metaQuery = metaQuery; } public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1) { - uid = default; - comp1 = default; - - if (--_index < 0) + while (true) { - if (!_chunkEnumerator.MoveNext()) + if (!_traitDict.MoveNext()) { + uid = default; + comp1 = default; return false; } - _index = _chunkEnumerator.Current.Size - 1; + var current = _traitDict.Current; + + if (current.Value.Deleted) + { + continue; + } + + if (!_metaQuery.TryGetComponentInternal(current.Key, out var metaComp) || metaComp.EntityPaused) + { + continue; + } + + uid = current.Key; + comp1 = (TComp1)current.Value; + return true; } - - var entity = _chunkEnumerator.Current.Entities[_index]; - var comps = _chunkEnumerator.Current.GetRow(_index); - - if (comps.t0.Deleted || comps.t1.EntityPaused) - return false; - - uid = _world.Reference(entity); - comp1 = comps.t0; - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1458,55 +1655,68 @@ namespace Robust.Shared.GameObjects { return MoveNext(out _, out comp1); } + + public void Dispose() + { + _traitDict.Dispose(); + } } /// /// Returns all matching unpaused components. /// - public struct EntityQueryEnumerator + public struct EntityQueryEnumerator : IDisposable where TComp1 : IComponent where TComp2 : IComponent { - private readonly World _world; - private ArchChunkEnumerator _chunkEnumerator; - private int _index; + private Dictionary.Enumerator _traitDict; + private readonly Dictionary _traitDict2; + private readonly EntityQuery _metaQuery; - public EntityQueryEnumerator(World world) + public EntityQueryEnumerator( + Dictionary traitDict, + Dictionary traitDict2, + EntityQuery metaQuery) { - _world = world; - _chunkEnumerator = world.Query(new QueryDescription().WithAll()).ChunkIterator(world).GetEnumerator(); - if (_chunkEnumerator.MoveNext()) - { - _index = _chunkEnumerator.Current.Size; - } + _traitDict = traitDict.GetEnumerator(); + _traitDict2 = traitDict2; + _metaQuery = metaQuery; } - public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2) + public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2) { - uid = default; - comp1 = default; - comp2 = default; - - if (--_index < 0) + while (true) { - if (!_chunkEnumerator.MoveNext()) + if (!_traitDict.MoveNext()) { + uid = default; + comp1 = default; + comp2 = default; return false; } - _index = _chunkEnumerator.Current.Size - 1; + var current = _traitDict.Current; + + if (current.Value.Deleted) + { + continue; + } + + if (!_metaQuery.TryGetComponentInternal(current.Key, out var metaComp) || metaComp.EntityPaused) + { + continue; + } + + if (!_traitDict2.TryGetValue(current.Key, out var comp2Obj) || comp2Obj.Deleted) + { + continue; + } + + uid = current.Key; + comp1 = (TComp1)current.Value; + comp2 = (TComp2)comp2Obj; + return true; } - - var entity = _chunkEnumerator.Current.Entities[_index]; - var comps = _chunkEnumerator.Current.GetRow(_index); - - if (comps.t0.Deleted || comps.t1.Deleted || comps.t2.EntityPaused) - return false; - - uid = _world.Reference(entity); - comp1 = comps.t0; - comp2 = comps.t1; - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1514,58 +1724,79 @@ namespace Robust.Shared.GameObjects { return MoveNext(out _, out comp1, out comp2); } + + public void Dispose() + { + _traitDict.Dispose(); + } } /// /// Returns all matching unpaused components. /// - public struct EntityQueryEnumerator + public struct EntityQueryEnumerator : IDisposable where TComp1 : IComponent where TComp2 : IComponent where TComp3 : IComponent { - private readonly World _world; - private ArchChunkEnumerator _chunkEnumerator; - private int _index; + private Dictionary.Enumerator _traitDict; + private readonly Dictionary _traitDict2; + private readonly Dictionary _traitDict3; + private readonly EntityQuery _metaQuery; - public EntityQueryEnumerator(World world) + public EntityQueryEnumerator( + Dictionary traitDict, + Dictionary traitDict2, + Dictionary traitDict3, + EntityQuery metaQuery) { - _world = world; - _chunkEnumerator = world.Query(new QueryDescription().WithAll()).ChunkIterator(world).GetEnumerator(); - if (_chunkEnumerator.MoveNext()) - { - _index = _chunkEnumerator.Current.Size; - } + _traitDict = traitDict.GetEnumerator(); + _traitDict2 = traitDict2; + _traitDict3 = traitDict3; + _metaQuery = metaQuery; } public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2, [NotNullWhen(true)] out TComp3? comp3) { - uid = default; - comp1 = default; - comp2 = default; - comp3 = default; - - if (--_index < 0) + while (true) { - if (!_chunkEnumerator.MoveNext()) + if (!_traitDict.MoveNext()) { + uid = default; + comp1 = default; + comp2 = default; + comp3 = default; return false; } - _index = _chunkEnumerator.Current.Size - 1; + var current = _traitDict.Current; + + if (current.Value.Deleted) + { + continue; + } + + if (!_metaQuery.TryGetComponentInternal(current.Key, out var metaComp) || metaComp.EntityPaused) + { + continue; + } + + if (!_traitDict2.TryGetValue(current.Key, out var comp2Obj) || comp2Obj.Deleted) + { + continue; + } + + if (!_traitDict3.TryGetValue(current.Key, out var comp3Obj) || comp3Obj.Deleted) + { + continue; + } + + uid = current.Key; + comp1 = (TComp1)current.Value; + comp2 = (TComp2)comp2Obj; + comp3 = (TComp3)comp3Obj; + return true; } - - var entity = _chunkEnumerator.Current.Entities[_index]; - var comps = _chunkEnumerator.Current.GetRow(_index); - - if (comps.t0.Deleted || comps.t1.Deleted || comps.t2.Deleted || comps.t3.EntityPaused) - return false; - - uid = _world.Reference(entity); - comp1 = comps.t0; - comp2 = comps.t1; - comp3 = comps.t2; - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1576,61 +1807,90 @@ namespace Robust.Shared.GameObjects { return MoveNext(out _, out comp1, out comp2, out comp3); } + + public void Dispose() + { + _traitDict.Dispose(); + } } /// /// Returns all matching unpaused components. /// - public struct EntityQueryEnumerator + public struct EntityQueryEnumerator : IDisposable where TComp1 : IComponent where TComp2 : IComponent where TComp3 : IComponent where TComp4 : IComponent { - private readonly World _world; - private ArchChunkEnumerator _chunkEnumerator; - private int _index; + private Dictionary.Enumerator _traitDict; + private readonly Dictionary _traitDict2; + private readonly Dictionary _traitDict3; + private readonly Dictionary _traitDict4; + private readonly EntityQuery _metaQuery; - public EntityQueryEnumerator(World world) + public EntityQueryEnumerator( + Dictionary traitDict, + Dictionary traitDict2, + Dictionary traitDict3, + Dictionary traitDict4, + EntityQuery metaQuery) { - _world = world; - _chunkEnumerator = world.Query(new QueryDescription().WithAll()).ChunkIterator(world).GetEnumerator(); - if (_chunkEnumerator.MoveNext()) - { - _index = _chunkEnumerator.Current.Size; - } + _traitDict = traitDict.GetEnumerator(); + _traitDict2 = traitDict2; + _traitDict3 = traitDict3; + _traitDict4 = traitDict4; + _metaQuery = metaQuery; } public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2, [NotNullWhen(true)] out TComp3? comp3, [NotNullWhen(true)] out TComp4? comp4) { - uid = default; - comp1 = default; - comp2 = default; - comp3 = default; - comp4 = default; - - if (--_index < 0) + while (true) { - if (!_chunkEnumerator.MoveNext()) + if (!_traitDict.MoveNext()) { + uid = default; + comp1 = default; + comp2 = default; + comp3 = default; + comp4 = default; return false; } - _index = _chunkEnumerator.Current.Size - 1; + var current = _traitDict.Current; + + if (current.Value.Deleted) + { + continue; + } + + if (!_metaQuery.TryGetComponentInternal(current.Key, out var metaComp) || metaComp.EntityPaused) + { + continue; + } + + if (!_traitDict2.TryGetValue(current.Key, out var comp2Obj) || comp2Obj.Deleted) + { + continue; + } + + if (!_traitDict3.TryGetValue(current.Key, out var comp3Obj) || comp3Obj.Deleted) + { + continue; + } + + if (!_traitDict4.TryGetValue(current.Key, out var comp4Obj) || comp4Obj.Deleted) + { + continue; + } + + uid = current.Key; + comp1 = (TComp1)current.Value; + comp2 = (TComp2)comp2Obj; + comp3 = (TComp3)comp3Obj; + comp4 = (TComp4)comp4Obj; + return true; } - - var entity = _chunkEnumerator.Current.Entities[_index]; - var comps = _chunkEnumerator.Current.GetRow(_index); - - if (comps.t0.Deleted || comps.t1.Deleted || comps.t2.Deleted || comps.t3.Deleted || comps.t4.EntityPaused) - return false; - - uid = _world.Reference(entity); - comp1 = comps.t0; - comp2 = comps.t1; - comp3 = comps.t2; - comp4 = comps.t3; - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1642,6 +1902,11 @@ namespace Robust.Shared.GameObjects { return MoveNext(out _, out comp1, out comp2, out comp3, out comp4); } + + public void Dispose() + { + _traitDict.Dispose(); + } } #endregion @@ -1651,47 +1916,39 @@ namespace Robust.Shared.GameObjects /// /// Returns all matching components, paused or not. /// - public struct AllEntityQueryEnumerator + public struct AllEntityQueryEnumerator : IDisposable where TComp1 : IComponent { - private readonly World _world; - private ArchChunkEnumerator _chunkEnumerator; - private int _index; + private Dictionary.Enumerator _traitDict; - public AllEntityQueryEnumerator(World world) + public AllEntityQueryEnumerator( + Dictionary traitDict) { - _world = world; - _chunkEnumerator = world.Query(new QueryDescription().WithAll()).ChunkIterator(world).GetEnumerator(); - if (_chunkEnumerator.MoveNext()) - { - _index = _chunkEnumerator.Current.Size; - } + _traitDict = traitDict.GetEnumerator(); } public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1) { - uid = default; - comp1 = default; - - if (--_index < 0) + while (true) { - if (!_chunkEnumerator.MoveNext()) + if (!_traitDict.MoveNext()) { + uid = default; + comp1 = default; return false; } - _index = _chunkEnumerator.Current.Size - 1; + var current = _traitDict.Current; + + if (current.Value.Deleted) + { + continue; + } + + uid = current.Key; + comp1 = (TComp1)current.Value; + return true; } - - var entity = _chunkEnumerator.Current.Entities[_index]; - var comp = _chunkEnumerator.Current.Get(_index); - - if (comp.Deleted) - return false; - - uid = _world.Reference(entity); - comp1 = comp; - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1699,55 +1956,60 @@ namespace Robust.Shared.GameObjects { return MoveNext(out _, out comp1); } + + public void Dispose() + { + _traitDict.Dispose(); + } } /// /// Returns all matching components, paused or not. /// - public struct AllEntityQueryEnumerator + public struct AllEntityQueryEnumerator : IDisposable where TComp1 : IComponent where TComp2 : IComponent { - private readonly World _world; - private ArchChunkEnumerator _chunkEnumerator; - private int _index; + private Dictionary.Enumerator _traitDict; + private readonly Dictionary _traitDict2; - public AllEntityQueryEnumerator(World world) + public AllEntityQueryEnumerator( + Dictionary traitDict, + Dictionary traitDict2) { - _world = world; - _chunkEnumerator = world.Query(new QueryDescription().WithAll()).ChunkIterator(world).GetEnumerator(); - if (_chunkEnumerator.MoveNext()) - { - _index = _chunkEnumerator.Current.Size; - } + _traitDict = traitDict.GetEnumerator(); + _traitDict2 = traitDict2; } public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2) { - uid = default; - comp1 = default; - comp2 = default; - - if (--_index < 0) + while (true) { - if (!_chunkEnumerator.MoveNext()) + if (!_traitDict.MoveNext()) { + uid = default; + comp1 = default; + comp2 = default; return false; } - _index = _chunkEnumerator.Current.Size - 1; + var current = _traitDict.Current; + + if (current.Value.Deleted) + { + continue; + } + + if (!_traitDict2.TryGetValue(current.Key, out var comp2Obj) || comp2Obj.Deleted) + { + continue; + } + + uid = current.Key; + comp1 = (TComp1)current.Value; + comp2 = (TComp2)comp2Obj; + return true; } - - var entity = _chunkEnumerator.Current.Entities[_index]; - var comps = _chunkEnumerator.Current.GetRow(_index); - - if (comps.t0.Deleted || comps.t1.Deleted) - return false; - - uid = _world.Reference(entity); - comp1 = comps.t0; - comp2 = comps.t1; - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1755,58 +2017,71 @@ namespace Robust.Shared.GameObjects { return MoveNext(out _, out comp1, out comp2); } + + public void Dispose() + { + _traitDict.Dispose(); + } } /// /// Returns all matching components, paused or not. /// - public struct AllEntityQueryEnumerator + public struct AllEntityQueryEnumerator : IDisposable where TComp1 : IComponent where TComp2 : IComponent where TComp3 : IComponent { - private readonly World _world; - private ArchChunkEnumerator _chunkEnumerator; - private int _index; + private Dictionary.Enumerator _traitDict; + private readonly Dictionary _traitDict2; + private readonly Dictionary _traitDict3; - public AllEntityQueryEnumerator(World world) + public AllEntityQueryEnumerator( + Dictionary traitDict, + Dictionary traitDict2, + Dictionary traitDict3) { - _world = world; - _chunkEnumerator = world.Query(new QueryDescription().WithAll()).ChunkIterator(world).GetEnumerator(); - if (_chunkEnumerator.MoveNext()) - { - _index = _chunkEnumerator.Current.Size; - } + _traitDict = traitDict.GetEnumerator(); + _traitDict2 = traitDict2; + _traitDict3 = traitDict3; } public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2, [NotNullWhen(true)] out TComp3? comp3) { - uid = default; - comp1 = default; - comp2 = default; - comp3 = default; - - if (--_index < 0) + while (true) { - if (!_chunkEnumerator.MoveNext()) + if (!_traitDict.MoveNext()) { + uid = default; + comp1 = default; + comp2 = default; + comp3 = default; return false; } - _index = _chunkEnumerator.Current.Size - 1; + var current = _traitDict.Current; + + if (current.Value.Deleted) + { + continue; + } + + if (!_traitDict2.TryGetValue(current.Key, out var comp2Obj) || comp2Obj.Deleted) + { + continue; + } + + if (!_traitDict3.TryGetValue(current.Key, out var comp3Obj) || comp3Obj.Deleted) + { + continue; + } + + uid = current.Key; + comp1 = (TComp1)current.Value; + comp2 = (TComp2)comp2Obj; + comp3 = (TComp3)comp3Obj; + return true; } - - var entity = _chunkEnumerator.Current.Entities[_index]; - var comps = _chunkEnumerator.Current.GetRow(_index); - - if (comps.t0.Deleted || comps.t1.Deleted || comps.t2.Deleted) - return false; - - uid = _world.Reference(entity); - comp1 = comps.t0; - comp2 = comps.t1; - comp3 = comps.t2; - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1817,61 +2092,82 @@ namespace Robust.Shared.GameObjects { return MoveNext(out _, out comp1, out comp2, out comp3); } + + public void Dispose() + { + _traitDict.Dispose(); + } } /// /// Returns all matching components, paused or not. /// - public struct AllEntityQueryEnumerator + public struct AllEntityQueryEnumerator : IDisposable where TComp1 : IComponent where TComp2 : IComponent where TComp3 : IComponent where TComp4 : IComponent { - private readonly World _world; - private ArchChunkEnumerator _chunkEnumerator; - private int _index; + private Dictionary.Enumerator _traitDict; + private readonly Dictionary _traitDict2; + private readonly Dictionary _traitDict3; + private readonly Dictionary _traitDict4; - public AllEntityQueryEnumerator(World world) + public AllEntityQueryEnumerator( + Dictionary traitDict, + Dictionary traitDict2, + Dictionary traitDict3, + Dictionary traitDict4) { - _world = world; - _chunkEnumerator = world.Query(new QueryDescription().WithAll()).ChunkIterator(world).GetEnumerator(); - if (_chunkEnumerator.MoveNext()) - { - _index = _chunkEnumerator.Current.Size; - } + _traitDict = traitDict.GetEnumerator(); + _traitDict2 = traitDict2; + _traitDict3 = traitDict3; + _traitDict4 = traitDict4; } public bool MoveNext(out EntityUid uid, [NotNullWhen(true)] out TComp1? comp1, [NotNullWhen(true)] out TComp2? comp2, [NotNullWhen(true)] out TComp3? comp3, [NotNullWhen(true)] out TComp4? comp4) { - uid = default; - comp1 = default; - comp2 = default; - comp3 = default; - comp4 = default; - - if (--_index < 0) + while (true) { - if (!_chunkEnumerator.MoveNext()) + if (!_traitDict.MoveNext()) { + uid = default; + comp1 = default; + comp2 = default; + comp3 = default; + comp4 = default; return false; } - _index = _chunkEnumerator.Current.Size - 1; + var current = _traitDict.Current; + + if (current.Value.Deleted) + { + continue; + } + + if (!_traitDict2.TryGetValue(current.Key, out var comp2Obj) || comp2Obj.Deleted) + { + continue; + } + + if (!_traitDict3.TryGetValue(current.Key, out var comp3Obj) || comp3Obj.Deleted) + { + continue; + } + + if (!_traitDict4.TryGetValue(current.Key, out var comp4Obj) || comp4Obj.Deleted) + { + continue; + } + + uid = current.Key; + comp1 = (TComp1)current.Value; + comp2 = (TComp2)comp2Obj; + comp3 = (TComp3)comp3Obj; + comp4 = (TComp4)comp4Obj; + return true; } - - var entity = _chunkEnumerator.Current.Entities[_index]; - var comps = _chunkEnumerator.Current.GetRow(_index); - - if (comps.t0.Deleted || comps.t1.Deleted || comps.t2.Deleted || comps.t3.Deleted) - return false; - - uid = _world.Reference(entity); - comp1 = comps.t0; - comp2 = comps.t1; - comp3 = comps.t2; - comp4 = comps.t3; - return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1883,6 +2179,11 @@ namespace Robust.Shared.GameObjects { return MoveNext(out _, out comp1, out comp2, out comp3, out comp4); } + + public void Dispose() + { + _traitDict.Dispose(); + } } #endregion diff --git a/Robust.Shared/GameObjects/EntityManager.Spawn.cs b/Robust.Shared/GameObjects/EntityManager.Spawn.cs index 8dcc79da3..088beeb44 100644 --- a/Robust.Shared/GameObjects/EntityManager.Spawn.cs +++ b/Robust.Shared/GameObjects/EntityManager.Spawn.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; -using Arch.Core.Extensions.Dangerous; using Robust.Shared.Containers; namespace Robust.Shared.GameObjects; @@ -41,16 +40,6 @@ public partial class EntityManager return ents; } - public EntityUid[] SpawnEntities(MapCoordinates coordinates, string? prototype, int count) - { - var ents = new EntityUid[count]; - for (var i = 0; i < count; i++) - { - ents[i] = Spawn(prototype, coordinates); - } - return ents; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public EntityUid[] SpawnEntitiesAttachedTo(EntityCoordinates coordinates, List protoNames) { diff --git a/Robust.Shared/GameObjects/EntityManager.cs b/Robust.Shared/GameObjects/EntityManager.cs index 16da67bb0..efb37583a 100644 --- a/Robust.Shared/GameObjects/EntityManager.cs +++ b/Robust.Shared/GameObjects/EntityManager.cs @@ -2,10 +2,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using Arch.Core; -using Arch.Core.Extensions; -using Arch.Core.Utils; -using Collections.Pooled; +using System.Runtime.CompilerServices; using Prometheus; using Robust.Shared.Log; using Robust.Shared.Map; @@ -16,8 +13,6 @@ using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Markdown.Mapping; using Robust.Shared.Timing; using Robust.Shared.Utility; -using System.Runtime.CompilerServices; -using ComponentRegistry = Robust.Shared.Prototypes.ComponentRegistry; namespace Robust.Shared.GameObjects { @@ -44,8 +39,6 @@ namespace Robust.Shared.GameObjects // positions on spawn.... private SharedTransformSystem _xforms = default!; - private QueryDescription _archMetaQuery = new QueryDescription().WithAll(); - public EntityQuery MetaQuery; public EntityQuery TransformQuery; @@ -69,8 +62,15 @@ namespace Robust.Shared.GameObjects private EntityDiffContext _context = new(); + /// + /// All entities currently stored in the manager. + /// + protected readonly HashSet Entities = new(); + private EntityEventBus _eventBus = null!; + protected int NextEntityUid = (int) EntityUid.FirstUid; + protected int NextNetworkId = (int) NetEntity.First; /// @@ -116,7 +116,7 @@ namespace Robust.Shared.GameObjects _eventBus = new EntityEventBus(this); - InitializeArch(); + InitializeComponents(); _metaReg = _componentFactory.GetRegistration(typeof(MetaDataComponent)); _xformReg = _componentFactory.GetRegistration(typeof(TransformComponent)); _xformName = _xformReg.Name; @@ -144,17 +144,15 @@ namespace Robust.Shared.GameObjects } var protoData = PrototypeManager.GetPrototypeData(prototype); - var comps = _world.GetAllComponents(uid); + var comps = _entCompIndex[uid]; // Fast check if the component counts match. // Note that transform and metadata are not included in the prototype data. - if (protoData.Count + 2 != comps.Length) + if (protoData.Count + 2 != comps.Count) return false; - foreach (var comp in comps) + foreach (var component in comps) { - var component = (IComponent)comp!; - if (component.Deleted) return false; @@ -210,7 +208,6 @@ namespace Robust.Shared.GameObjects FlushEntities(); _eventBus.ClearEventTables(); _entitySystemManager.Shutdown(); - ShutdownArch(); ClearComponents(); ShuttingDown = false; Started = false; @@ -218,12 +215,12 @@ namespace Robust.Shared.GameObjects public virtual void Cleanup() { + _componentFactory.ComponentAdded -= OnComponentAdded; ShuttingDown = true; FlushEntities(); _entitySystemManager.Clear(); _eventBus.Dispose(); _eventBus = null!; - ShutdownArch(); ClearComponents(); ShuttingDown = false; @@ -272,27 +269,28 @@ namespace Robust.Shared.GameObjects public EntityUid CreateEntityUninitialized(string? prototypeName, EntityUid euid, ComponentRegistry? overrides = null) { - return CreateEntity(prototypeName, out _, out _, overrides); + return CreateEntity(prototypeName, out _, overrides); } /// public virtual EntityUid CreateEntityUninitialized(string? prototypeName, ComponentRegistry? overrides = null) { - return CreateEntity(prototypeName, out _, out _, overrides); + return CreateEntity(prototypeName, out _, overrides); } /// public virtual EntityUid CreateEntityUninitialized(string? prototypeName, EntityCoordinates coordinates, ComponentRegistry? overrides = null) { - var newEntity = CreateEntity(prototypeName, out _, out var xform, overrides); - _xforms.SetCoordinates(newEntity, xform, coordinates, unanchor: false); + var newEntity = CreateEntity(prototypeName, out _, overrides); + _xforms.SetCoordinates(newEntity, TransformQuery.GetComponent(newEntity), coordinates, unanchor: false); return newEntity; } /// public virtual EntityUid CreateEntityUninitialized(string? prototypeName, MapCoordinates coordinates, ComponentRegistry? overrides = null) { - var newEntity = CreateEntity(prototypeName, out _, out var transform, overrides); + var newEntity = CreateEntity(prototypeName, out _, overrides); + var transform = TransformQuery.GetComponent(newEntity); if (coordinates.MapId == MapId.Nullspace) { @@ -322,19 +320,10 @@ namespace Robust.Shared.GameObjects } /// - public int EntityCount => _world.Size; + public int EntityCount => Entities.Count; /// - public IEnumerable GetEntities() - { - var ents = new List(); - _world.GetEntities(_archMetaQuery, ents); - - foreach (var entity in ents) - { - yield return EntityUid.FromArch(_world, entity); - } - } + public IEnumerable GetEntities() => Entities; /// public virtual void DirtyEntity(EntityUid uid, MetaDataComponent? metadata = null) @@ -386,7 +375,7 @@ namespace Robust.Shared.GameObjects /// Entity to remove public virtual void DeleteEntity(EntityUid? uid) { - if (uid == null || uid == EntityUid.Invalid) + if (uid == null) return; var e = uid.Value; @@ -411,9 +400,9 @@ namespace Robust.Shared.GameObjects } // Notify all entities they are being terminated prior to detaching & deleting - var xform = TransformQuery.GetComponent(e); - RecursiveFlagEntityTermination(e, meta, xform); + RecursiveFlagEntityTermination(e, meta); + var xform = TransformQuery.GetComponent(e); TransformComponent? parentXform = null; if (xform.ParentUid.IsValid()) TransformQuery.Resolve(xform.ParentUid, ref parentXform); @@ -424,14 +413,14 @@ namespace Robust.Shared.GameObjects private void RecursiveFlagEntityTermination( EntityUid uid, - MetaDataComponent metadata, - TransformComponent transform) + MetaDataComponent metadata) { + var transform = TransformQuery.GetComponent(uid); metadata.EntityLifeStage = EntityLifeStage.Terminating; try { - var ev = new EntityTerminatingEvent(uid, metadata); + var ev = new EntityTerminatingEvent(uid); EventBus.RaiseLocalEvent(uid, ref ev, true); } catch (Exception e) @@ -448,7 +437,7 @@ namespace Robust.Shared.GameObjects continue; } - RecursiveFlagEntityTermination(child, childMeta, TransformQuery.GetComponent(child)); + RecursiveFlagEntityTermination(child, childMeta); } } @@ -496,12 +485,8 @@ namespace Robust.Shared.GameObjects _sawmill.Error($"Failed to delete all children of entity: {ToPrettyString(uid)}"); // Shut down all components. - var objComps = _world.GetAllComponents(uid); - - foreach (var comp in objComps) + foreach (var component in InSafeOrder(_entCompIndex[uid])) { - var component = (IComponent)comp!; - if (component.Running) { try @@ -516,7 +501,7 @@ namespace Robust.Shared.GameObjects } // Dispose all my components, in a safe order so transform is available - DisposeComponents(uid, metadata); + DisposeComponents(uid); metadata.EntityLifeStage = EntityLifeStage.Deleted; try @@ -529,14 +514,14 @@ namespace Robust.Shared.GameObjects } _eventBus.OnEntityDeleted(uid); - DestroyArch(uid); + Entities.Remove(uid); // Need to get the ID above before MetadataComponent shutdown but only remove it after everything else is done. NetEntityLookup.Remove(metadata.NetEntity); } public virtual void QueueDeleteEntity(EntityUid? uid) { - if (uid == null || uid.Value == EntityUid.Invalid) + if (uid == null) return; if (!QueuedDeletionsSet.Add(uid.Value)) @@ -550,7 +535,7 @@ namespace Robust.Shared.GameObjects public bool EntityExists(EntityUid uid) { - return IsAlive(uid); + return MetaQuery.HasComponentInternal(uid); } public bool EntityExists(EntityUid? uid) @@ -569,26 +554,12 @@ namespace Robust.Shared.GameObjects public bool Deleted(EntityUid uid) { - return !IsAlive(uid) || !_world.TryGet(uid, out MetaDataComponent? comp) || comp!.EntityLifeStage > EntityLifeStage.Terminating; - } - - /// - /// Returns whether the entity is alive inside of the ECS world. - /// - internal bool IsAlive(EntityUid uid) - { - return ((EntityReference) uid).IsAlive(_world); - } - - internal bool TryAlive(EntityUid uid, out EntityReference entity) - { - entity = uid; - return entity.IsAlive(_world); + return !MetaQuery.TryGetComponentInternal(uid, out var comp) || comp.EntityDeleted; } public bool Deleted([NotNullWhen(false)] EntityUid? uid) { - return !uid.HasValue || Deleted(uid.Value); + return !uid.HasValue || !MetaQuery.TryGetComponentInternal(uid.Value, out var comp) || comp.EntityDeleted; } /// @@ -603,9 +574,7 @@ namespace Robust.Shared.GameObjects DeleteEntity(e); } - CleanupArch(); - - if (_world.Size > 0) + if (Entities.Count != 0) _sawmill.Error("Entities were spawned while flushing entities."); } @@ -614,10 +583,9 @@ namespace Robust.Shared.GameObjects /// private protected EntityUid AllocEntity( EntityPrototype? prototype, - out MetaDataComponent metadata, - out TransformComponent xform) + out MetaDataComponent metadata) { - var entity = AllocEntity(out metadata, out xform); + var entity = AllocEntity(out metadata); metadata._entityPrototype = prototype; Dirty(entity, metadata, metadata); return entity; @@ -626,9 +594,16 @@ namespace Robust.Shared.GameObjects /// /// Allocates an entity and stores it but does not load components or do initialization. /// - private EntityUid AllocEntity(out MetaDataComponent metadata, out TransformComponent xform) + private EntityUid AllocEntity(out MetaDataComponent metadata) { - SpawnEntityArch(out var uid); + var uid = GenerateEntityUid(); + +#if DEBUG + if (EntityExists(uid)) + { + throw new InvalidOperationException($"UID already taken: {uid}"); + } +#endif // we want this called before adding components EntityAdded?.Invoke(uid); @@ -645,15 +620,16 @@ namespace Robust.Shared.GameObjects SetNetEntity(uid, netEntity, metadata); + Entities.Add(uid); // add the required MetaDataComponent directly. - AddComponentInternal(uid, metadata, _metaReg, true, metadata); + AddComponentInternal(uid, metadata, _metaReg, false, true, metadata); // allocate the required TransformComponent - xform = Unsafe.As(_componentFactory.GetComponent(_xformReg)); + var xformComp = Unsafe.As(_componentFactory.GetComponent(_xformReg)); #pragma warning disable CS0618 // Type or member is obsolete - xform.Owner = uid; + xformComp.Owner = uid; #pragma warning restore CS0618 // Type or member is obsolete - AddComponentInternal(uid, xform, true, metadata); + AddComponentInternal(uid, xformComp, false, true, metadata); return uid; } @@ -661,26 +637,26 @@ namespace Robust.Shared.GameObjects /// /// Allocates an entity and loads components but does not do initialization. /// - private protected virtual EntityUid CreateEntity(string? prototypeName, out MetaDataComponent metadata, out TransformComponent xform, IEntityLoadContext? context = null) + private protected virtual EntityUid CreateEntity(string? prototypeName, out MetaDataComponent metadata, IEntityLoadContext? context = null) { if (prototypeName == null) - return AllocEntity(out metadata, out xform); + return AllocEntity(out metadata); if (!PrototypeManager.TryIndex(prototypeName, out var prototype)) throw new EntityCreationException($"Attempted to spawn an entity with an invalid prototype: {prototypeName}"); - return CreateEntity(prototype, out metadata, out xform, context); + return CreateEntity(prototype, out metadata, context); } /// /// Allocates an entity and loads components but does not do initialization. /// - private protected EntityUid CreateEntity(EntityPrototype prototype, out MetaDataComponent metadata, out TransformComponent xform, IEntityLoadContext? context = null) + private protected EntityUid CreateEntity(EntityPrototype prototype, out MetaDataComponent metadata, IEntityLoadContext? context = null) { - var entity = AllocEntity(prototype, out metadata, out xform); + var entity = AllocEntity(prototype, out metadata); try { - LoadEntity(metadata.EntityPrototype, entity, context); + EntityPrototype.LoadEntity(metadata.EntityPrototype, entity, ComponentFactory, this, _serManager, context); return entity; } catch (Exception e) @@ -694,105 +670,18 @@ namespace Robust.Shared.GameObjects private protected void LoadEntity(EntityUid entity, IEntityLoadContext? context) { - LoadEntity(MetaQuery.GetComponent(entity).EntityPrototype, entity, context); + EntityPrototype.LoadEntity(MetaQuery.GetComponent(entity).EntityPrototype, entity, ComponentFactory, this, _serManager, context); } private protected void LoadEntity(EntityUid entity, IEntityLoadContext? context, EntityPrototype? prototype) { - LoadEntity(prototype, entity, context); - } - - internal void LoadEntity(EntityPrototype? prototype, EntityUid entity, IEntityLoadContext? context) - { - var count = prototype?.Components.Count ?? 2; - // Lort forgiv - using var types = new PooledList(count); - using var comps = new PooledList(count); - using var compRegs = new PooledList(count); - Archetype arc; - var metadata = MetaQuery.GetComponent(entity); - -#if DEBUG - arc = _world.GetArchetype(entity); -#endif - - if (prototype != null) - { - foreach (var (name, entry) in prototype.Components) - { - if (context != null && context.ShouldSkipComponent(name)) - continue; - - var fullData = context != null && context.TryGetComponent(name, out var data) ? data : entry.Component; - - var comp = EntityPrototype.EnsureCompExistsAndDeserialize(entity, _componentFactory, this, _serManager, name, fullData, context as ISerializationContext, metadata); - var compType = comp.CompReg.Idx.Type; - - // Don't double add an existing component, just set data above. - if (!comp.Add) - { - continue; - } - - types.Add(compType); - comps.Add(comp.Comp); - compRegs.Add(comp.CompReg); - } - } - - if (context != null) - { - foreach (var name in context.GetExtraComponentTypes()) - { - if (prototype != null && prototype.Components.ContainsKey(name)) - { - // This component also exists in the prototype. - // This means that the previous step already caught both the prototype data AND map data. - // Meaning that re-running EnsureCompExistsAndDeserialize would wipe prototype data. - continue; - } - - if (!context.TryGetComponent(name, out var data)) - { - throw new InvalidOperationException( - $"{nameof(IEntityLoadContext)} provided component name {name} but refused to provide data"); - } - - var comp = EntityPrototype.EnsureCompExistsAndDeserialize(entity, _componentFactory, this, _serManager, name, data, context as ISerializationContext, metadata); - var compType = comp.CompReg.Idx.Type; - - // Don't double add an existing component, just set data above. - if (!comp.Add) - { - continue; - } - - types.Add(compType); - comps.Add(comp.Comp); - compRegs.Add(comp.CompReg); - } - } - - // Shouldn't be changing archetype above or we're having a bad time. - DebugTools.Assert(_world.GetArchetype(entity).Equals(arc)); - - // Yeah it can happen. - if (types.Count == 0) - return; - - _world.AddRange(entity, types); - - for (var i = 0; i < comps.Count; i++) - { - AddComponentInternal(entity, comps[i], compRegs[i], true, metadata: metadata); - } + EntityPrototype.LoadEntity(prototype, entity, ComponentFactory, this, _serManager, context); } public void InitializeAndStartEntity(EntityUid entity, MapId? mapId = null) { try { - // TODO: Pass this + transformcomp around var meta = MetaQuery.GetComponent(entity); InitializeEntity(entity, meta); StartEntity(entity); @@ -871,6 +760,14 @@ namespace Robust.Shared.GameObjects DebugTools.Assert("Why are you raising predictive events on the server?"); } + /// + /// Factory for generating a new EntityUid for an entity currently being created. + /// + internal EntityUid GenerateEntityUid() + { + return new EntityUid(NextEntityUid++); + } + /// /// Generates a unique network id and increments /// diff --git a/Robust.Shared/GameObjects/EntitySystem.Proxy.cs b/Robust.Shared/GameObjects/EntitySystem.Proxy.cs index ce2ba0bd5..45701bdc5 100644 --- a/Robust.Shared/GameObjects/EntitySystem.Proxy.cs +++ b/Robust.Shared/GameObjects/EntitySystem.Proxy.cs @@ -525,7 +525,7 @@ public partial class EntitySystem /// Retrieves whether the entity has the specified component or not. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool HasComp(EntityUid uid) where T : IComponent + protected bool HasComp(EntityUid uid) { return EntityManager.HasComponent(uid); } @@ -543,7 +543,7 @@ public partial class EntitySystem /// Retrieves whether the entity has the specified component or not. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected bool HasComp([NotNullWhen(true)] EntityUid? uid) where T : IComponent + protected bool HasComp([NotNullWhen(true)] EntityUid? uid) { return EntityManager.HasComponent(uid); } @@ -572,7 +572,7 @@ public partial class EntitySystem [MethodImpl(MethodImplOptions.AggressiveInlining)] protected void AddComp(EntityUid uid, T component, bool overwrite = false) where T : IComponent { - EntityManager.AddComponent(uid, component); + EntityManager.AddComponent(uid, component, overwrite); } /// @@ -614,6 +614,13 @@ public partial class EntitySystem return EntityManager.RemoveComponentDeferred(uid, type); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected void RemCompDeferred(EntityUid uid, Component component) + { + EntityManager.RemoveComponentDeferred(uid, component); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] protected void RemCompDeferred(EntityUid uid, IComponent component) @@ -656,6 +663,13 @@ public partial class EntitySystem return EntityManager.RemoveComponent(uid, type); } + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected void RemComp(EntityUid uid, Component component) + { + EntityManager.RemoveComponent(uid, component); + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] protected void RemComp(EntityUid uid, IComponent component) diff --git a/Robust.Shared/GameObjects/EntitySystemMessages/EntityTerminatingEvent.cs b/Robust.Shared/GameObjects/EntitySystemMessages/EntityTerminatingEvent.cs index a150c31d5..cf8f000ae 100644 --- a/Robust.Shared/GameObjects/EntitySystemMessages/EntityTerminatingEvent.cs +++ b/Robust.Shared/GameObjects/EntitySystemMessages/EntityTerminatingEvent.cs @@ -7,12 +7,10 @@ namespace Robust.Shared.GameObjects public readonly struct EntityTerminatingEvent { public readonly EntityUid Entity; - public readonly MetaDataComponent Metadata; - public EntityTerminatingEvent(EntityUid entity, MetaDataComponent metadata) + public EntityTerminatingEvent(EntityUid entity) { Entity = entity; - Metadata = metadata; } } } diff --git a/Robust.Shared/GameObjects/EntityUid.cs b/Robust.Shared/GameObjects/EntityUid.cs index c10545be9..3974fb4ee 100644 --- a/Robust.Shared/GameObjects/EntityUid.cs +++ b/Robust.Shared/GameObjects/EntityUid.cs @@ -1,7 +1,4 @@ using System; -using System.Runtime.CompilerServices; -using Arch.Core; -using Arch.Core.Extensions.Dangerous; using JetBrains.Annotations; using Robust.Shared.IoC; using Robust.Shared.Prototypes; @@ -12,7 +9,7 @@ using Robust.Shared.ViewVariables; namespace Robust.Shared.GameObjects { /// - /// This type contains a local identification number of an entity. + /// This type contains a network identification number of an entity. /// This can be used by the EntityManager to access an entity /// [CopyByRef] @@ -20,40 +17,22 @@ namespace Robust.Shared.GameObjects { public readonly int Id; - public readonly int Version; - /// /// An Invalid entity UID you can compare against. /// - public static readonly EntityUid Invalid = new(-1 + ArchUidOffset, -1 + ArchVersionOffset); + public static readonly EntityUid Invalid = new(0); /// /// The first entity UID the entityManager should use when the manager is initialized. /// - public static readonly EntityUid FirstUid = new(0 + ArchUidOffset, 1 + ArchVersionOffset); - - internal const int ArchUidOffset = 1; - internal const int ArchVersionOffset = 1; - - public EntityUid() - { - Id = Invalid.Id; - Version = Invalid.Version; - } - - internal EntityUid(EntityReference reference) - { - Id = reference.Entity.Id + ArchUidOffset; - Version = reference.Version + ArchVersionOffset; - } + public static readonly EntityUid FirstUid = new(1); /// /// Creates an instance of this structure, with the given network ID. /// - public EntityUid(int id, int version) + public EntityUid(int id) { Id = id; - Version = version; } public bool Valid => IsValid(); @@ -61,16 +40,16 @@ namespace Robust.Shared.GameObjects /// /// Creates an entity UID by parsing a string number. /// - public static EntityUid Parse(ReadOnlySpan uid, ReadOnlySpan version) + public static EntityUid Parse(ReadOnlySpan uid) { - return new EntityUid(int.Parse(uid), int.Parse(version)); + return new EntityUid(int.Parse(uid)); } - public static bool TryParse(ReadOnlySpan uid, ReadOnlySpan version, out EntityUid entityUid) + public static bool TryParse(ReadOnlySpan uid, out EntityUid entityUid) { try { - entityUid = Parse(uid, version); + entityUid = Parse(uid); return true; } catch (FormatException) @@ -80,15 +59,6 @@ namespace Robust.Shared.GameObjects } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EntityUid FromArch(in World world, in Entity entity) - { - return new EntityUid(entity.Id + ArchUidOffset, world.Reference(entity).Version + ArchVersionOffset); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetArchId() => Id - ArchUidOffset; - /// /// Checks if the ID value is valid. Does not check if it identifies /// a valid Entity. @@ -96,13 +66,13 @@ namespace Robust.Shared.GameObjects [Pure] public bool IsValid() { - return Id > Invalid.Id; + return Id > 0; } /// public bool Equals(EntityUid other) { - return Id == other.Id && Version == other.Version; + return Id == other.Id; } /// @@ -117,7 +87,9 @@ namespace Robust.Shared.GameObjects { unchecked { - return Id.GetHashCode() * 397 ^ Version.GetHashCode(); + // * 397 for whenever we get versioning back + // and avoid hashcode bugs in the interim. + return Id.GetHashCode() * 397; } } @@ -126,7 +98,7 @@ namespace Robust.Shared.GameObjects /// public static bool operator ==(EntityUid a, EntityUid b) { - return a.Id == b.Id && a.Version == b.Version; + return a.Id == b.Id; } /// @@ -146,21 +118,6 @@ namespace Robust.Shared.GameObjects return self.Id; } - public static implicit operator Entity(EntityUid self) - { - return DangerousEntityExtensions.CreateEntityStruct(self.Id - ArchUidOffset, 0); - } - - public static implicit operator EntityReference(EntityUid other) - { - return DangerousEntityExtensions.CreateEntityReferenceStruct(other.Id - ArchUidOffset, other.Version - ArchVersionOffset, 0); - } - - public static implicit operator EntityUid(EntityReference other) - { - return new EntityUid(other); - } - /// public override string ToString() { diff --git a/Robust.Shared/GameObjects/IEntityManager.Components.cs b/Robust.Shared/GameObjects/IEntityManager.Components.cs index fda0de0b9..82c8cbe74 100644 --- a/Robust.Shared/GameObjects/IEntityManager.Components.cs +++ b/Robust.Shared/GameObjects/IEntityManager.Components.cs @@ -71,7 +71,7 @@ namespace Robust.Shared.GameObjects /// Entity being modified. /// Component to add. /// Should it overwrite existing components? - void AddComponent(EntityUid uid, T component, MetaDataComponent? metadata = null) where T : IComponent; + void AddComponent(EntityUid uid, T component, bool overwrite = false, MetaDataComponent? metadata = null) where T : IComponent; /// /// Removes the component with the specified reference type, @@ -136,6 +136,14 @@ namespace Robust.Shared.GameObjects /// Component to remove. void RemoveComponentDeferred(EntityUid uid, IComponent component); + /// + /// Immediately shuts down a component, but defers the removal and deletion until the end of the tick. + /// Throws if the given component does not belong to the entity. + /// + /// Entity UID to modify. + /// Component to remove. + void RemoveComponentDeferred(EntityUid uid, Component component); + /// /// Removes all components from an entity, except the required components. /// @@ -156,7 +164,7 @@ namespace Robust.Shared.GameObjects /// Component reference type to check for. /// Entity UID to check. /// True if the entity has the component type, otherwise false. - bool HasComponent(EntityUid uid) where T : IComponent; + bool HasComponent(EntityUid uid); /// /// Checks if the entity has a component type. @@ -164,7 +172,7 @@ namespace Robust.Shared.GameObjects /// Component reference type to check for. /// Entity UID to check. /// True if the entity has the component type, otherwise false. - bool HasComponent(EntityUid? uid) where T : IComponent; + bool HasComponent(EntityUid? uid); /// /// Checks if the entity has a component type. @@ -273,7 +281,7 @@ namespace Robust.Shared.GameObjects /// Entity UID to check. /// Component of the specified type (if exists). /// If the component existed in the entity. - bool TryGetComponent(EntityUid uid, [NotNullWhen(true)] out T? component) where T : IComponent?; + bool TryGetComponent(EntityUid uid, [NotNullWhen(true)] out T? component); /// /// Returns the component of a specific type. @@ -282,7 +290,7 @@ namespace Robust.Shared.GameObjects /// Entity UID to check. /// Component of the specified type (if exists). /// If the component existed in the entity. - bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out T? component) where T : IComponent?; + bool TryGetComponent([NotNullWhen(true)] EntityUid? uid, [NotNullWhen(true)] out T? component); /// /// Returns the component of a specific type. @@ -497,7 +505,5 @@ namespace Robust.Shared.GameObjects /// Culls all components from the collection that are marked as deleted. This needs to be called often. /// void CullRemovedComponents(); - - void CleanupArch(); } } diff --git a/Robust.Shared/GameObjects/IEntityManager.Spawn.cs b/Robust.Shared/GameObjects/IEntityManager.Spawn.cs index 11b1d9edc..64874e54a 100644 --- a/Robust.Shared/GameObjects/IEntityManager.Spawn.cs +++ b/Robust.Shared/GameObjects/IEntityManager.Spawn.cs @@ -19,7 +19,6 @@ public partial interface IEntityManager EntityUid SpawnEntity(string? protoName, MapCoordinates coordinates, ComponentRegistry? overrides = null); EntityUid[] SpawnEntities(MapCoordinates coordinates, params string?[] protoNames); - EntityUid[] SpawnEntities(MapCoordinates coordinates, string? prototype, int count); EntityUid[] SpawnEntities(MapCoordinates coordinates, List protoNames); EntityUid[] SpawnEntitiesAttachedTo(EntityCoordinates coordinates, List protoNames); EntityUid[] SpawnEntitiesAttachedTo(EntityCoordinates coordinates, params string?[] protoNames); @@ -53,7 +52,7 @@ public partial interface IEntityManager EntityUid containerUid, string containerId, [NotNullWhen(true)] out EntityUid? uid, - ContainerManagerComponent? containerComp = null, + ContainerManagerComponent? containerComp = null, ComponentRegistry? overrides = null); /// @@ -65,7 +64,7 @@ public partial interface IEntityManager EntityUid containerUid, string containerId, TransformComponent? xform = null, - ContainerManagerComponent? containerComp = null, + ContainerManagerComponent? containerComp = null, ComponentRegistry? overrides = null); /// @@ -85,8 +84,8 @@ public partial interface IEntityManager /// instead attempt to spawn the entity next to the target's parent. /// EntityUid SpawnNextToOrDrop( - string? protoName, - EntityUid target, - TransformComponent? xform = null, + string? protoName, + EntityUid target, + TransformComponent? xform = null, ComponentRegistry? overrides = null); } diff --git a/Robust.Shared/GameObjects/Systems/EntityLookupSystem.cs b/Robust.Shared/GameObjects/Systems/EntityLookupSystem.cs index 996ac3948..6a858ad57 100644 --- a/Robust.Shared/GameObjects/Systems/EntityLookupSystem.cs +++ b/Robust.Shared/GameObjects/Systems/EntityLookupSystem.cs @@ -113,6 +113,7 @@ public sealed partial class EntityLookupSystem : EntitySystem SubscribeLocalEvent(OnBroadphaseTerminating); SubscribeLocalEvent(OnBroadphaseAdd); + SubscribeLocalEvent(OnGridAdd); SubscribeLocalEvent(OnMapChange); SubscribeLocalEvent(OnMove); @@ -191,6 +192,12 @@ public sealed partial class EntityLookupSystem : EntitySystem } } + private void OnGridAdd(GridAddEvent ev) + { + // Must be done before initialization as that's when broadphase data starts getting set. + EnsureComp(ev.EntityUid); + } + private void OnBroadphaseAdd(EntityUid uid, BroadphaseComponent component, ComponentAdd args) { component.StaticSundriesTree = new DynamicTree( @@ -432,7 +439,7 @@ public sealed partial class EntityLookupSystem : EntitySystem { DebugTools.Assert(!_container.IsEntityOrParentInContainer(uid)); DebugTools.Assert(xform.Broadphase == null || xform.Broadphase == new BroadphaseData(broadUid, default, false, staticBody)); - xform.Broadphase ??= new BroadphaseData(broadUid, EntityUid.Invalid, false, staticBody); + xform.Broadphase ??= new(broadUid, default, false, staticBody); (staticBody ? broadphase.StaticSundriesTree : broadphase.SundriesTree).AddOrUpdate(uid, aabb); } diff --git a/Robust.Shared/GameObjects/Systems/SharedMapSystem.Grid.cs b/Robust.Shared/GameObjects/Systems/SharedMapSystem.Grid.cs index 4b909e3fb..b309d0ea8 100644 --- a/Robust.Shared/GameObjects/Systems/SharedMapSystem.Grid.cs +++ b/Robust.Shared/GameObjects/Systems/SharedMapSystem.Grid.cs @@ -429,7 +429,8 @@ public abstract partial class SharedMapSystem private void OnGridInit(EntityUid uid, MapGridComponent component, ComponentInit args) { - var xform = _xformQuery.GetComponent(uid); + var xformQuery = GetEntityQuery(); + var xform = xformQuery.GetComponent(uid); // Force networkedmapmanager to send it due to non-ECS legacy code. var curTick = _timing.CurTick; @@ -442,7 +443,7 @@ public abstract partial class SharedMapSystem component.LastTileModifiedTick = curTick; if (xform.MapUid != null && xform.MapUid != uid) - _transform.SetParent(uid, xform, xform.MapUid.Value); + _transform.SetParent(uid, xform, xform.MapUid.Value, xformQuery); if (!HasComp(uid)) { diff --git a/Robust.Shared/GameObjects/Systems/SharedMapSystem.Map.cs b/Robust.Shared/GameObjects/Systems/SharedMapSystem.Map.cs index 5031594df..6fd034bff 100644 --- a/Robust.Shared/GameObjects/Systems/SharedMapSystem.Map.cs +++ b/Robust.Shared/GameObjects/Systems/SharedMapSystem.Map.cs @@ -10,6 +10,7 @@ public abstract partial class SharedMapSystem { private void InitializeMap() { + SubscribeLocalEvent(OnMapAdd); SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnMapRemoved); SubscribeLocalEvent(OnMapHandleState); @@ -42,6 +43,8 @@ public abstract partial class SharedMapSystem args.State = new MapComponentState(component.MapId, component.LightingEnabled, component.MapPaused); } + protected abstract void OnMapAdd(EntityUid uid, MapComponent component, ComponentAdd args); + private void OnMapInit(EntityUid uid, MapComponent component, ComponentInit args) { EnsureComp(uid); diff --git a/Robust.Shared/Localization/LocalizationManager.Entity.cs b/Robust.Shared/Localization/LocalizationManager.Entity.cs index b3ad73dd0..67983b074 100644 --- a/Robust.Shared/Localization/LocalizationManager.Entity.cs +++ b/Robust.Shared/Localization/LocalizationManager.Entity.cs @@ -25,7 +25,7 @@ namespace Robust.Shared.Localization private bool TryGetEntityLocAttrib(EntityUid entity, string attribute, [NotNullWhen(true)] out string? value) { - if (_entMan.TryGetComponent(entity, out GrammarComponent? grammar) && + if (_entMan.TryGetComponent(entity, out var grammar) && grammar.Attributes.TryGetValue(attribute, out value)) { return true; diff --git a/Robust.Shared/Localization/LocalizationManager.Functions.cs b/Robust.Shared/Localization/LocalizationManager.Functions.cs index 48e34bd95..baaa5c73d 100644 --- a/Robust.Shared/Localization/LocalizationManager.Functions.cs +++ b/Robust.Shared/Localization/LocalizationManager.Functions.cs @@ -174,7 +174,7 @@ namespace Robust.Shared.Localization { EntityUid entity = (EntityUid)entity0.Value; - if (_entMan.TryGetComponent(entity, out GrammarComponent? grammar) && grammar.Gender.HasValue) + if (_entMan.TryGetComponent(entity, out var grammar) && grammar.Gender.HasValue) { return new LocValueString(grammar.Gender.Value.ToString().ToLowerInvariant()); } @@ -307,7 +307,7 @@ namespace Robust.Shared.Localization { EntityUid entity = (EntityUid)entity0.Value; - if (_entMan.TryGetComponent(entity, out GrammarComponent? grammar) && grammar.ProperNoun.HasValue) + if (_entMan.TryGetComponent(entity, out var grammar) && grammar.ProperNoun.HasValue) { return new LocValueString(grammar.ProperNoun.Value.ToString().ToLowerInvariant()); } diff --git a/Robust.Shared/Map/EntityCoordinates.cs b/Robust.Shared/Map/EntityCoordinates.cs index 5d289ecbd..b0b461aa4 100644 --- a/Robust.Shared/Map/EntityCoordinates.cs +++ b/Robust.Shared/Map/EntityCoordinates.cs @@ -37,12 +37,6 @@ namespace Robust.Shared.Map /// public float Y => Position.Y; - public EntityCoordinates() - { - EntityId = EntityUid.Invalid; - Position = Vector2.Zero; - } - /// /// Constructs a new instance of . /// diff --git a/Robust.Shared/Map/MapManager.GridCollection.cs b/Robust.Shared/Map/MapManager.GridCollection.cs index 4c0e59c22..4d142a84b 100644 --- a/Robust.Shared/Map/MapManager.GridCollection.cs +++ b/Robust.Shared/Map/MapManager.GridCollection.cs @@ -4,8 +4,6 @@ using System.Diagnostics.CodeAnalysis; using Robust.Shared.GameObjects; using Robust.Shared.Map.Components; using Robust.Shared.Maths; -using Robust.Shared.Physics; -using Robust.Shared.Physics.Components; using Robust.Shared.Utility; // All the obsolete warnings about GridId are probably useless here. @@ -161,9 +159,6 @@ internal partial class MapManager var grid = EntityManager.AddComponent(gridEnt); grid.ChunkSize = chunkSize; - EntityManager.AddComponent(gridEnt); - EntityManager.AddComponent(gridEnt); - EntityManager.AddComponent(gridEnt); _sawmill.Debug($"Binding new grid {gridEnt}"); diff --git a/Robust.Shared/Map/MapManager.MapCollection.cs b/Robust.Shared/Map/MapManager.MapCollection.cs index ba4f74f20..f8bedd642 100644 --- a/Robust.Shared/Map/MapManager.MapCollection.cs +++ b/Robust.Shared/Map/MapManager.MapCollection.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using Robust.Shared.GameObjects; using Robust.Shared.Map.Components; -using Robust.Shared.Physics.Dynamics; using Robust.Shared.Utility; namespace Robust.Shared.Map; @@ -234,7 +233,6 @@ internal partial class MapManager var mapComp = EntityManager.AddComponent(newEnt); mapComp.MapId = actualId; - EntityManager.AddComponent(newEnt); var meta = EntityManager.GetComponent(newEnt); EntityManager.System().SetEntityName(newEnt, $"map {actualId}", meta); EntityManager.Dirty(newEnt, mapComp, meta); diff --git a/Robust.Shared/Map/MapSerializationContext.cs b/Robust.Shared/Map/MapSerializationContext.cs index 08a1a5ca6..5a67dd1d2 100644 --- a/Robust.Shared/Map/MapSerializationContext.cs +++ b/Robust.Shared/Map/MapSerializationContext.cs @@ -165,6 +165,6 @@ internal sealed class MapSerializationContext : ISerializationContext, IEntityLo bool skipHook, ISerializationContext? context = null) { - return new EntityUid(source.Id, source.Version); + return new((int)source); } } diff --git a/Robust.Shared/Physics/BroadphaseComponent.cs b/Robust.Shared/Physics/BroadphaseComponent.cs index 6365b077f..c62b761eb 100644 --- a/Robust.Shared/Physics/BroadphaseComponent.cs +++ b/Robust.Shared/Physics/BroadphaseComponent.cs @@ -1,33 +1,32 @@ using Robust.Shared.GameObjects; -using Robust.Shared.GameStates; using Robust.Shared.Physics.BroadPhase; -namespace Robust.Shared.Physics; - -/// -/// Stores the broadphase structure for the relevant grid / map. -/// -[RegisterComponent, NetworkedComponent] -public sealed partial class BroadphaseComponent : Component +namespace Robust.Shared.Physics { - /// - /// Stores all non-static bodies. + /// Stores the broadphase structure for the relevant grid / map. /// - public IBroadPhase DynamicTree = new DynamicTreeBroadPhase(); + [RegisterComponent] + public sealed partial class BroadphaseComponent : Component + { + /// + /// Stores all non-static bodies. + /// + public IBroadPhase DynamicTree = new DynamicTreeBroadPhase(); - /// - /// Stores all static bodies. - /// - public IBroadPhase StaticTree = new DynamicTreeBroadPhase(); + /// + /// Stores all static bodies. + /// + public IBroadPhase StaticTree = new DynamicTreeBroadPhase(); - /// - /// Stores all other non-static entities not in another tree. - /// - public DynamicTree SundriesTree = default!; + /// + /// Stores all other non-static entities not in another tree. + /// + public DynamicTree SundriesTree = default!; - /// - /// Stores all other static entities not in another tree. - /// - public DynamicTree StaticSundriesTree = default!; + /// + /// Stores all other static entities not in another tree. + /// + public DynamicTree StaticSundriesTree = default!; + } } diff --git a/Robust.Shared/Physics/Systems/SharedPhysicsSystem.Components.cs b/Robust.Shared/Physics/Systems/SharedPhysicsSystem.Components.cs index 6cd9566cf..5774d7deb 100644 --- a/Robust.Shared/Physics/Systems/SharedPhysicsSystem.Components.cs +++ b/Robust.Shared/Physics/Systems/SharedPhysicsSystem.Components.cs @@ -322,7 +322,7 @@ public partial class SharedPhysicsSystem body.AngularVelocity = value; if (dirty) - Dirty(uid, body); + Dirty(body); } /// @@ -347,7 +347,7 @@ public partial class SharedPhysicsSystem body.LinearVelocity = velocity; if (dirty) - Dirty(uid, body); + Dirty(body); } public void SetAngularDamping(PhysicsComponent body, float value, bool dirty = true) diff --git a/Robust.Shared/Physics/Systems/SharedPhysicsSystem.cs b/Robust.Shared/Physics/Systems/SharedPhysicsSystem.cs index af7847260..dbd4f550a 100644 --- a/Robust.Shared/Physics/Systems/SharedPhysicsSystem.cs +++ b/Robust.Shared/Physics/Systems/SharedPhysicsSystem.cs @@ -62,7 +62,6 @@ namespace Robust.Shared.Physics.Systems public bool MetricsEnabled { get; protected set; } - private EntityQuery _collideAnchorQuery; private EntityQuery _fixturesQuery; protected EntityQuery PhysicsQuery; private EntityQuery _xformQuery; @@ -71,12 +70,11 @@ namespace Robust.Shared.Physics.Systems { base.Initialize(); - _collideAnchorQuery = GetEntityQuery(); _fixturesQuery = GetEntityQuery(); PhysicsQuery = GetEntityQuery(); _xformQuery = GetEntityQuery(); - SubscribeLocalEvent(OnGridAdd); + SubscribeLocalEvent(OnGridAdd); SubscribeLocalEvent(OnWake); SubscribeLocalEvent(OnSleep); SubscribeLocalEvent(OnCollisionChange); @@ -180,12 +178,14 @@ namespace Robust.Shared.Physics.Systems /// private void HandleMapChange(EntityUid uid, TransformComponent xform, PhysicsComponent? body, MapId oldMapId, MapId newMapId) { + var bodyQuery = GetEntityQuery(); + var xformQuery = GetEntityQuery(); var jointQuery = GetEntityQuery(); TryComp(_mapManager.GetMapEntityId(oldMapId), out PhysicsMapComponent? oldMap); TryComp(_mapManager.GetMapEntityId(newMapId), out PhysicsMapComponent? newMap); - RecursiveMapUpdate(uid, xform, body, newMap, oldMap, jointQuery); + RecursiveMapUpdate(uid, xform, body, newMap, oldMap, bodyQuery, xformQuery, jointQuery); } /// @@ -197,6 +197,8 @@ namespace Robust.Shared.Physics.Systems PhysicsComponent? body, PhysicsMapComponent? newMap, PhysicsMapComponent? oldMap, + EntityQuery bodyQuery, + EntityQuery xformQuery, EntityQuery jointQuery) { DebugTools.Assert(!Deleted(uid)); @@ -220,15 +222,15 @@ namespace Robust.Shared.Physics.Systems var childEnumerator = xform.ChildEnumerator; while (childEnumerator.MoveNext(out var child)) { - if (_xformQuery.TryGetComponent(child, out var childXform)) + if (xformQuery.TryGetComponent(child, out var childXform)) { - PhysicsQuery.TryGetComponent(child, out var childBody); - RecursiveMapUpdate(child.Value, childXform, childBody, newMap, oldMap, jointQuery); + bodyQuery.TryGetComponent(child, out var childBody); + RecursiveMapUpdate(child.Value, childXform, childBody, newMap, oldMap, bodyQuery, xformQuery, jointQuery); } } } - private void OnGridAdd(GridInitializeEvent ev) + private void OnGridAdd(GridAddEvent ev) { var guid = ev.EntityUid; @@ -254,7 +256,7 @@ namespace Robust.Shared.Physics.Systems private void OnWake(ref PhysicsWakeEvent @event) { - var mapId = _xformQuery.GetComponent(@event.Entity).MapID; + var mapId = EntityManager.GetComponent(@event.Entity).MapID; if (mapId == MapId.Nullspace) return; @@ -265,7 +267,7 @@ namespace Robust.Shared.Physics.Systems private void OnSleep(ref PhysicsSleepEvent @event) { - var mapId = _xformQuery.GetComponent(@event.Entity).MapID; + var mapId = EntityManager.GetComponent(@event.Entity).MapID; if (mapId == MapId.Nullspace) return; @@ -280,7 +282,7 @@ namespace Robust.Shared.Physics.Systems if (MetaData(uid).EntityLifeStage >= EntityLifeStage.Terminating) return; // If this entity is only meant to collide when anchored, return early. - if (_collideAnchorQuery.TryGetComponent(uid, out var collideComp) && collideComp.Enable) + if (TryComp(uid, out CollideOnAnchorComponent? collideComp) && collideComp.Enable) return; WakeBody(uid, body: physics); diff --git a/Robust.Shared/Prototypes/EntityPrototype.cs b/Robust.Shared/Prototypes/EntityPrototype.cs index 2aa74423b..22c9b6b4d 100644 --- a/Robust.Shared/Prototypes/EntityPrototype.cs +++ b/Robust.Shared/Prototypes/EntityPrototype.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using Arch.Core.Utils; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; @@ -14,7 +12,6 @@ using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Markdown.Mapping; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; using Robust.Shared.ViewVariables; -using Component = Robust.Shared.GameObjects.Component; namespace Robust.Shared.Prototypes { @@ -196,37 +193,76 @@ namespace Robust.Shared.Prototypes return true; } - internal static (ComponentRegistration CompReg, IComponent Comp, bool Add) EnsureCompExistsAndDeserialize(EntityUid entity, + internal static void LoadEntity( + EntityPrototype? prototype, + EntityUid entity, + IComponentFactory factory, + IEntityManager entityManager, + ISerializationManager serManager, + IEntityLoadContext? context) //yeah officer this method right here + { + if (prototype != null) + { + foreach (var (name, entry) in prototype.Components) + { + if (context != null && context.ShouldSkipComponent(name)) + continue; + + var fullData = context != null && context.TryGetComponent(name, out var data) ? data : entry.Component; + + EnsureCompExistsAndDeserialize(entity, factory, entityManager, serManager, name, fullData, context as ISerializationContext); + } + } + + if (context != null) + { + foreach (var name in context.GetExtraComponentTypes()) + { + if (prototype != null && prototype.Components.ContainsKey(name)) + { + // This component also exists in the prototype. + // This means that the previous step already caught both the prototype data AND map data. + // Meaning that re-running EnsureCompExistsAndDeserialize would wipe prototype data. + continue; + } + + if (!context.TryGetComponent(name, out var data)) + { + throw new InvalidOperationException( + $"{nameof(IEntityLoadContext)} provided component name {name} but refused to provide data"); + } + + EnsureCompExistsAndDeserialize(entity, factory, entityManager, serManager, name, data, context as ISerializationContext); + } + } + } + + public static void EnsureCompExistsAndDeserialize(EntityUid entity, IComponentFactory factory, IEntityManager entityManager, ISerializationManager serManager, string compName, IComponent data, - ISerializationContext? context, - MetaDataComponent metadata) + ISerializationContext? context) { - // TODO optimize var compReg = factory.GetRegistration(compName); - var add = false; if (!entityManager.TryGetComponent(entity, compReg.Idx, out var component)) { var newComponent = factory.GetComponent(compName); - newComponent.Owner = entity; + entityManager.AddComponent(entity, newComponent); component = newComponent; - add = true; } if (context is not MapSerializationContext map) { serManager.CopyTo(data, ref component, context, notNullableOverride: true); - return (compReg, component, add); + return; } map.CurrentComponent = compName; serManager.CopyTo(data, ref component, context, notNullableOverride: true); map.CurrentComponent = null; - return (compReg, component, add); } public override string ToString() diff --git a/Robust.Shared/Robust.Shared.csproj b/Robust.Shared/Robust.Shared.csproj index 3e3bf02e3..6900ddda2 100644 --- a/Robust.Shared/Robust.Shared.csproj +++ b/Robust.Shared/Robust.Shared.csproj @@ -6,9 +6,8 @@ true - - + @@ -28,7 +27,6 @@ - diff --git a/Robust.Shared/Serialization/TypeSerializers/Implementations/ComponentRegistrySerializer.cs b/Robust.Shared/Serialization/TypeSerializers/Implementations/ComponentRegistrySerializer.cs index cad016350..fdc658611 100644 --- a/Robust.Shared/Serialization/TypeSerializers/Implementations/ComponentRegistrySerializer.cs +++ b/Robust.Shared/Serialization/TypeSerializers/Implementations/ComponentRegistrySerializer.cs @@ -12,6 +12,7 @@ using Robust.Shared.Serialization.Markdown.Sequence; using Robust.Shared.Serialization.Markdown.Validation; using Robust.Shared.Serialization.Markdown.Value; using Robust.Shared.Serialization.TypeSerializers.Interfaces; +using Robust.Shared.Utility; using static Robust.Shared.Prototypes.EntityPrototype; namespace Robust.Shared.Serialization.TypeSerializers.Implementations @@ -63,8 +64,8 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations var copy = componentMapping.Copy()!; copy.Remove("type"); - var reg = factory.GetRegistration(compType); - var read = (IComponent)serializationManager.Read(reg.Type, copy, hookCtx, context)!; + var type = factory.GetRegistration(compType).Type; + var read = (IComponent)serializationManager.Read(type, copy, hookCtx, context)!; components[compType] = new ComponentRegistryEntry(read, copy); } diff --git a/Robust.Shared/Toolshed/TypeParsers/EntityTypeParser.cs b/Robust.Shared/Toolshed/TypeParsers/EntityTypeParser.cs index 0248786d0..cad7a2f63 100644 --- a/Robust.Shared/Toolshed/TypeParsers/EntityTypeParser.cs +++ b/Robust.Shared/Toolshed/TypeParsers/EntityTypeParser.cs @@ -17,10 +17,9 @@ internal sealed class EntityTypeParser : TypeParser { var start = parser.Index; var word = parser.GetWord(ParserContext.IsToken); - var wordTwo = parser.GetWord(ParserContext.IsToken); error = null; - if (!EntityUid.TryParse(word, wordTwo, out var ent)) + if (!EntityUid.TryParse(word, out var ent)) { result = null; diff --git a/Robust.Shared/ViewVariables/ViewVariablesManager.Domains.cs b/Robust.Shared/ViewVariables/ViewVariablesManager.Domains.cs index e38eb8364..d244d9e3e 100644 --- a/Robust.Shared/ViewVariables/ViewVariablesManager.Domains.cs +++ b/Robust.Shared/ViewVariables/ViewVariablesManager.Domains.cs @@ -86,13 +86,13 @@ internal abstract partial class ViewVariablesManager var segments = path.Split('/'); - if (segments.Length < 2) + if (segments.Length == 0) return EmptyResolve; - if (!int.TryParse(segments[0], out var num) || num <= 0 || !int.TryParse(segments[1], out var numTwo) || numTwo < 0) + if (!int.TryParse(segments[0], out var num) || num <= 0) return EmptyResolve; - var uid = new EntityUid(num, numTwo); + var uid = new EntityUid(num); return (new ViewVariablesInstancePath(uid), segments[1..]); } diff --git a/Robust.UnitTesting/RobustIntegrationTest.cs b/Robust.UnitTesting/RobustIntegrationTest.cs index 2be2a7906..974f54978 100644 --- a/Robust.UnitTesting/RobustIntegrationTest.cs +++ b/Robust.UnitTesting/RobustIntegrationTest.cs @@ -915,13 +915,11 @@ namespace Robust.UnitTesting // use server side uids on the client and vice versa. This can sometimes accidentally work if the // entities get created in the same order. For that reason we arbitrarily increment the queued Uid by // some arbitrary quantity. - - /* TODO: End my suffering and fix this because entmanager hasn't started up yet. + var e = (EntityManager) EntMan; for (var i = 0; i < 10; i++) { - EntMan.SpawnEntity(null, MapCoordinates.Nullspace); + e.GenerateEntityUid(); } - */ return client; } diff --git a/Robust.UnitTesting/Server/GameObjects/ArchTests.cs b/Robust.UnitTesting/Server/GameObjects/ArchTests.cs deleted file mode 100644 index a53e36460..000000000 --- a/Robust.UnitTesting/Server/GameObjects/ArchTests.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Arch.Core.Extensions.Dangerous; -using NUnit.Framework; -using Robust.Shared.Console.Commands; -using Robust.Shared.GameObjects; -using Robust.Shared.Map; - -namespace Robust.UnitTesting.Server.GameObjects; - -/// -/// Tests engine integrations with Arch. -/// -[TestFixture] -public sealed class ArchTests -{ - /// - /// Asserts that EntityUids match the expected Arch EntityReference. - /// - [Test] - public void EntityTest() - { - var sim = RobustServerSimulation.NewSimulation().InitializeInstance(); - var entManager = sim.Resolve(); - - var entity = entManager.Spawn(null, MapCoordinates.Nullspace); - var entReference = DangerousEntityExtensions.CreateEntityReferenceStruct(0, 1, 0); - Assert.That(entity.Id, Is.EqualTo(entReference.Entity.Id + EntityUid.ArchUidOffset)); - Assert.That(entity.Version, Is.EqualTo(entReference.Version + EntityUid.ArchVersionOffset)); - - entManager.DeleteEntity(entity); - } - - /// - /// Asserts that deleted entities stay deleted despite entity recycling. - /// If we don't account for EntityReference / versions correctly old entities may return as being nopt deleted. - /// - [Test] - public void EntityVersionTest() - { - var sim = RobustServerSimulation.NewSimulation().InitializeInstance(); - var entManager = sim.Resolve(); - - var entity = entManager.Spawn(null, MapCoordinates.Nullspace); - entManager.DeleteEntity(entity); - Assert.That(entManager.Deleted(entity)); - Assert.That(!entManager.EntityExists(entity)); - - // Spawn a new entity and check it is a recycled ID. - var entity2 = entManager.Spawn(null, MapCoordinates.Nullspace); - Assert.That(entity.Id, Is.EqualTo(entity2.Id)); - Assert.That(entity.Version, Is.Not.EqualTo(entity2.Version)); - - // Assert the old entity still returns deleted but new one isn't. - Assert.That(entManager.Deleted(entity)); - Assert.That(!entManager.Deleted(entity2)); - Assert.That(!entManager.EntityExists(entity)); - Assert.That(entManager.EntityExists(entity2)); - entManager.DeleteEntity(entity2); - } -} diff --git a/Robust.UnitTesting/Server/GameObjects/Components/Container_Test.cs b/Robust.UnitTesting/Server/GameObjects/Components/Container_Test.cs index fede35512..de84c0d55 100644 --- a/Robust.UnitTesting/Server/GameObjects/Components/Container_Test.cs +++ b/Robust.UnitTesting/Server/GameObjects/Components/Container_Test.cs @@ -38,7 +38,7 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var entManager = sim.Resolve(); var containerSys = sim.Resolve().GetEntitySystem(); - var entity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var entity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container = containerSys.MakeContainer(entity, "dummy"); @@ -75,8 +75,8 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var entManager = sim.Resolve(); var containerSys = sim.Resolve().GetEntitySystem(); - var owner = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); - var inserted = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var owner = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); + var inserted = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var transform = entManager.GetComponent(inserted); var container = containerSys.MakeContainer(owner, "dummy"); @@ -105,10 +105,10 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var entManager = sim.Resolve(); var containerSys = sim.Resolve().GetEntitySystem(); - var owner = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); - var inserted = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var owner = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); + var inserted = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var transform = entManager.GetComponent(inserted); - var entity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var entity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container = containerSys.MakeContainer(owner, "dummy"); Assert.That(container.Insert(inserted), Is.True); @@ -133,7 +133,7 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var entMan = sim.Resolve(); var containerSys = sim.Resolve().GetEntitySystem(); - var coordinates = new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0)); + var coordinates = new EntityCoordinates(new EntityUid(1), new Vector2(0, 0)); var entityOne = sim.SpawnEntity(null, coordinates); var entityTwo = sim.SpawnEntity(null, coordinates); var entityThree = sim.SpawnEntity(null, coordinates); @@ -166,7 +166,7 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var sim = SimulationFactory(); var containerSys = sim.Resolve().GetEntitySystem(); - var entity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var entity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container = containerSys.MakeContainer(entity, "dummy"); Assert.That(container.Insert(entity), Is.False); @@ -179,8 +179,8 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var sim = SimulationFactory(); var containerSys = sim.Resolve().GetEntitySystem(); - var mapEnt = EntityUid.FirstUid; - var entity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var mapEnt = new EntityUid(1); + var entity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container = containerSys.MakeContainer(entity, "dummy"); Assert.That(container.Insert(mapEnt), Is.False); @@ -194,7 +194,7 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var containerSys = sim.Resolve().GetEntitySystem(); var grid = sim.Resolve().CreateGridEntity(new MapId(1)).Owner; - var entity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var entity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container = containerSys.MakeContainer(entity, "dummy"); Assert.That(container.Insert(grid), Is.False); @@ -208,9 +208,9 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var entManager = sim.Resolve(); var containerSys = sim.Resolve().GetEntitySystem(); - var containerEntity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var containerEntity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container = containerSys.MakeContainer(containerEntity, "dummy"); - var insertEntity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var insertEntity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var result = container.Insert(insertEntity); @@ -231,9 +231,9 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var sim = SimulationFactory(); var containerSys = sim.Resolve().GetEntitySystem(); - var containerEntity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var containerEntity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container = containerSys.MakeContainer(containerEntity, "dummy"); - var insertEntity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var insertEntity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var result = container.Remove(insertEntity); @@ -246,11 +246,11 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var sim = SimulationFactory(); var containerSys = sim.Resolve().GetEntitySystem(); - var entity1 = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var entity1 = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container1 = containerSys.MakeContainer(entity1, "dummy"); - var entity2 = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var entity2 = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container2 = containerSys.MakeContainer(entity2, "dummy"); - var transferEntity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var transferEntity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); container1.Insert(transferEntity); var result = container2.Insert(transferEntity); @@ -267,9 +267,9 @@ namespace Robust.UnitTesting.Server.GameObjects.Components var entManager = sim.Resolve(); var containerSys = entManager.System(); - var entity = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var entity = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); var container = containerSys.MakeContainer(entity, "dummy"); - var childEnt = sim.SpawnEntity(null, new EntityCoordinates(EntityUid.FirstUid, new Vector2(0, 0))); + var childEnt = sim.SpawnEntity(null, new EntityCoordinates(new EntityUid(1), new Vector2(0, 0))); container.OccludesLight = true; container.ShowContents = true; diff --git a/Robust.UnitTesting/Server/GameObjects/Components/Transform_Test.cs b/Robust.UnitTesting/Server/GameObjects/Components/Transform_Test.cs index bb91e6128..5272562cd 100644 --- a/Robust.UnitTesting/Server/GameObjects/Components/Transform_Test.cs +++ b/Robust.UnitTesting/Server/GameObjects/Components/Transform_Test.cs @@ -40,7 +40,7 @@ namespace Robust.UnitTesting.Server.GameObjects.Components private MapId MapB; private Entity GridB; - private static readonly EntityCoordinates InitialPos = new(EntityUid.FirstUid, new Vector2(0, 0)); + private static readonly EntityCoordinates InitialPos = new(new EntityUid(1), new Vector2(0, 0)); [OneTimeSetUp] public void Setup() diff --git a/Robust.UnitTesting/Shared/GameObjects/EntityEventBusTests.ComponentEvent.cs b/Robust.UnitTesting/Shared/GameObjects/EntityEventBusTests.ComponentEvent.cs index dfe3ac750..0bee356c5 100644 --- a/Robust.UnitTesting/Shared/GameObjects/EntityEventBusTests.ComponentEvent.cs +++ b/Robust.UnitTesting/Shared/GameObjects/EntityEventBusTests.ComponentEvent.cs @@ -16,7 +16,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var compFactory = new ComponentFactory(new DynamicTypeFactory(), new ReflectionManagerTest(), new LogManager()); // Arrange - var entUid = new EntityUid(7, -1); + var entUid = new EntityUid(7); var compInstance = new MetaDataComponent(); var entManMock = new Mock(); @@ -67,7 +67,7 @@ namespace Robust.UnitTesting.Shared.GameObjects public void UnsubscribeCompEvent() { // Arrange - var entUid = new EntityUid(7, -1); + var entUid = new EntityUid(7); var compInstance = new MetaDataComponent(); var entManMock = new Mock(); @@ -121,7 +121,7 @@ namespace Robust.UnitTesting.Shared.GameObjects public void SubscribeCompLifeEvent() { // Arrange - var entUid = new EntityUid(7, -1); + var entUid = new EntityUid(7); var compInstance = new MetaDataComponent(); var entManMock = new Mock(); @@ -176,7 +176,7 @@ namespace Robust.UnitTesting.Shared.GameObjects public void CompEventOrdered() { // Arrange - var entUid = new EntityUid(7, -1); + var entUid = new EntityUid(7); var entManMock = new Mock(); var compFacMock = new Mock(); diff --git a/Robust.UnitTesting/Shared/GameObjects/EntityManager_Components_Tests.cs b/Robust.UnitTesting/Shared/GameObjects/EntityManager_Components_Tests.cs index a95c94e89..ade838826 100644 --- a/Robust.UnitTesting/Shared/GameObjects/EntityManager_Components_Tests.cs +++ b/Robust.UnitTesting/Shared/GameObjects/EntityManager_Components_Tests.cs @@ -13,7 +13,7 @@ namespace Robust.UnitTesting.Shared.GameObjects [TestFixture, Parallelizable ,TestOf(typeof(EntityManager))] public sealed partial class EntityManager_Components_Tests { - private static readonly EntityCoordinates DefaultCoords = new(EntityUid.FirstUid, Vector2.Zero); + private static readonly EntityCoordinates DefaultCoords = new(new EntityUid(1), Vector2.Zero); [Test] public void AddComponentTest() @@ -48,7 +48,7 @@ namespace Robust.UnitTesting.Shared.GameObjects }; // Act - entMan.AddComponent(entity, component); + entMan.AddComponent(entity, component, true); // Assert var result = entMan.GetComponent(entity); @@ -82,7 +82,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var sim = SimulationFactory(); var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - entMan.AddComponent(entity); + IoCManager.Resolve().AddComponent(entity); // Act var result = entMan.HasComponent(entity); @@ -91,22 +91,6 @@ namespace Robust.UnitTesting.Shared.GameObjects Assert.That(result, Is.True); } - [Test] - public void HasComponentNoGenericTest() - { - // Arrange - var sim = SimulationFactory(); - var entMan = sim.Resolve(); - var entity = entMan.SpawnEntity(null, DefaultCoords); - entMan.AddComponent(entity); - - // Act - var result = entMan.HasComponent(entity, typeof(DummyComponent)); - - // Assert - Assert.That(result, Is.True); - } - [Test] public void HasNetComponentTest() { @@ -118,7 +102,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - entMan.AddComponent(entity); + IoCManager.Resolve().AddComponent(entity); // Act var result = entMan.HasComponent(entity, netId.Value); @@ -138,7 +122,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - var component = entMan.AddComponent(entity); + var component = IoCManager.Resolve().AddComponent(entity); // Act var result = entMan.GetComponent(entity, netId.Value); @@ -154,7 +138,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var sim = SimulationFactory(); var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - var component = entMan.AddComponent(entity); + var component = IoCManager.Resolve().AddComponent(entity); // Act var result = entMan.TryGetComponent(entity, out var comp); @@ -175,7 +159,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - var component = entMan.AddComponent(entity); + var component = IoCManager.Resolve().AddComponent(entity); // Act var result = entMan.TryGetComponent(entity, netId.Value, out var comp); @@ -192,7 +176,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var sim = SimulationFactory(); var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - var component = entMan.AddComponent(entity); + var component = IoCManager.Resolve().AddComponent(entity); // Act entMan.RemoveComponent(entity); @@ -230,7 +214,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - var component = entMan.AddComponent(entity); + var component = IoCManager.Resolve().AddComponent(entity); // Act entMan.RemoveComponent(entity, netId.Value); @@ -247,7 +231,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var sim = SimulationFactory(); var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - var component = entMan.AddComponent(entity); + var component = IoCManager.Resolve().AddComponent(entity); // Act var result = entMan.GetComponents(entity); @@ -265,7 +249,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var sim = SimulationFactory(); var entMan = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - var component = entMan.AddComponent(entity); + var component = IoCManager.Resolve().AddComponent(entity); // Act var result = entMan.EntityQuery(true); @@ -284,7 +268,7 @@ namespace Robust.UnitTesting.Shared.GameObjects var entMan = sim.Resolve(); var fac = sim.Resolve(); var entity = entMan.SpawnEntity(null, DefaultCoords); - var component = entMan.AddComponent(entity); + var component = IoCManager.Resolve().AddComponent(entity); // Act var result = entMan.GetComponents(entity); diff --git a/Robust.UnitTesting/Shared/GameObjects/Systems/TransformSystemTests.cs b/Robust.UnitTesting/Shared/GameObjects/Systems/TransformSystemTests.cs index 1b66e74ca..f52de2fdc 100644 --- a/Robust.UnitTesting/Shared/GameObjects/Systems/TransformSystemTests.cs +++ b/Robust.UnitTesting/Shared/GameObjects/Systems/TransformSystemTests.cs @@ -43,8 +43,8 @@ namespace Robust.UnitTesting.Shared.GameObjects.Systems void MoveEventHandler(ref MoveEvent ev) { calledCount++; - Assert.That(ev.OldPosition, Is.EqualTo(new EntityCoordinates(EntityUid.FirstUid, Vector2.Zero))); - Assert.That(ev.NewPosition, Is.EqualTo(new EntityCoordinates(EntityUid.FirstUid, Vector2.One))); + Assert.That(ev.OldPosition, Is.EqualTo(new EntityCoordinates(new EntityUid(1), Vector2.Zero))); + Assert.That(ev.NewPosition, Is.EqualTo(new EntityCoordinates(new EntityUid(1), Vector2.One))); } } diff --git a/Robust.UnitTesting/Shared/GameState/ComponentStateTests.cs b/Robust.UnitTesting/Shared/GameState/ComponentStateTests.cs index a11408109..1336833e7 100644 --- a/Robust.UnitTesting/Shared/GameState/ComponentStateTests.cs +++ b/Robust.UnitTesting/Shared/GameState/ComponentStateTests.cs @@ -248,7 +248,7 @@ public sealed partial class ComponentStateTests : RobustIntegrationTest var clientEntA = client.EntMan.GetEntity(serverNetA); var clientEntB = client.EntMan.GetEntity(serverNetB); Assert.That(client.EntMan.EntityExists(clientEntB), Is.True); - Assert.That(client.EntMan.EntityExists(clientEntA), Is.False); + Assert.That(client.EntMan.EntityExists(client.EntMan.GetEntity(serverNetA)), Is.False); Assert.That(client.EntMan.TryGetComponent(clientEntB, out UnknownEntityTestComponent? cmp)); Assert.That(cmp?.Other, Is.EqualTo(clientEntA)); diff --git a/Robust.UnitTesting/Shared/Map/GridSplit_Tests.cs b/Robust.UnitTesting/Shared/Map/GridSplit_Tests.cs index b94d3d0fb..aee9e4caf 100644 --- a/Robust.UnitTesting/Shared/Map/GridSplit_Tests.cs +++ b/Robust.UnitTesting/Shared/Map/GridSplit_Tests.cs @@ -160,9 +160,8 @@ public sealed class GridSplit_Tests grid.SetTile(new Vector2i(2, 0), Tile.Empty); Assert.That(mapManager.GetAllGrids(mapId).Count(), Is.EqualTo(2)); - var newGrid = mapManager.GetAllMapGrids(mapId).First(); - Assert.That(newGrid, Is.Not.EqualTo(grid)); - var newGridXform = entManager.GetComponent(newGrid.Owner); + var newGrid = mapManager.GetAllGrids(mapId).Last(); + var newGridXform = entManager.GetComponent(newGrid); Assert.Multiple(() => { diff --git a/Robust.UnitTesting/Shared/Map/MapManager_Tests.cs b/Robust.UnitTesting/Shared/Map/MapManager_Tests.cs index 1457e6b59..f8463e009 100644 --- a/Robust.UnitTesting/Shared/Map/MapManager_Tests.cs +++ b/Robust.UnitTesting/Shared/Map/MapManager_Tests.cs @@ -55,7 +55,7 @@ namespace Robust.UnitTesting.Shared.Map } /// - /// When entities are flushed check nullsapce is also culled. + /// When the map manager is restarted, Nullspace is recreated. /// [Test] public void Restart_NullspaceMap_IsEmptied() @@ -64,8 +64,9 @@ namespace Robust.UnitTesting.Shared.Map var entMan = sim.Resolve(); var oldEntity = entMan.CreateEntityUninitialized(null, MapCoordinates.Nullspace); entMan.InitializeComponents(oldEntity); - entMan.FlushEntities(); + entMan.Shutdown(); Assert.That(entMan.Deleted(oldEntity), Is.True); + } /// diff --git a/Robust.UnitTesting/Shared/Spawning/EntitySpawnHelpersTest.cs b/Robust.UnitTesting/Shared/Spawning/EntitySpawnHelpersTest.cs index 17cf58389..2e1135815 100644 --- a/Robust.UnitTesting/Shared/Spawning/EntitySpawnHelpersTest.cs +++ b/Robust.UnitTesting/Shared/Spawning/EntitySpawnHelpersTest.cs @@ -112,7 +112,6 @@ public abstract partial class EntitySpawnHelpersTest : RobustIntegrationTest public override IReadOnlyList ContainedEntities => _ents; protected override void InternalInsert(EntityUid toInsert, IEntityManager entMan) => _ents.Add(toInsert); protected override void InternalRemove(EntityUid toRemove, IEntityManager entMan) => _ents.Remove(toRemove); - public override bool Contains(EntityUid contained) => _ents.Contains(contained); protected override void InternalShutdown(IEntityManager entMan, bool isClient) { } protected internal override bool CanInsert(EntityUid toinsert, bool assumeEmpty, IEntityManager entMan) diff --git a/Robust.UnitTesting/Shared/Toolshed/ToolshedParserTest.cs b/Robust.UnitTesting/Shared/Toolshed/ToolshedParserTest.cs index ce4d38dd5..59c54c71e 100644 --- a/Robust.UnitTesting/Shared/Toolshed/ToolshedParserTest.cs +++ b/Robust.UnitTesting/Shared/Toolshed/ToolshedParserTest.cs @@ -42,7 +42,7 @@ public sealed partial class ToolshedParserTest : ToolshedTest { await Server.WaitAssertion(() => { - ParseCommand("ent 1 2"); + ParseCommand("ent 1"); // Clientside entities are a myth. ExpectError();