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