From ef751f68dc732737aaba4108464f8b4476dd754e Mon Sep 17 00:00:00 2001 From: Tyler Young Date: Thu, 6 Feb 2020 08:50:52 -0500 Subject: [PATCH] Faster Power (#596) uses SnapGridComponent to select nearby wires instead of entity list (only marginally faster if entity queries are using DynamicTree) TheoreticalLoad double dipping property setter, reduced to one update minor refactoring Co-authored-by: Tyler Young --- .../Components/Power/PowerDevice.cs | 16 +++++--- .../Components/Power/PowerNodeComponent.cs | 27 ++++++++------ .../Power/PowerProviderComponent.cs | 9 ++--- .../Power/PowerTransferComponent.cs | 37 ++++++++++--------- 4 files changed, 49 insertions(+), 40 deletions(-) diff --git a/Content.Server/GameObjects/Components/Power/PowerDevice.cs b/Content.Server/GameObjects/Components/Power/PowerDevice.cs index 870805c9f9..45c508f6d8 100644 --- a/Content.Server/GameObjects/Components/Power/PowerDevice.cs +++ b/Content.Server/GameObjects/Components/Power/PowerDevice.cs @@ -26,7 +26,7 @@ namespace Content.Server.GameObjects.Components.Power protected override void Startup() { base.Startup(); - if (_drawType != DrawTypes.Node) + if (DrawType != DrawTypes.Node) { var componentMgr = IoCManager.Resolve(); AvailableProviders = componentMgr.GetAllComponents().Where(x => x.CanServiceDevice(this)).ToList(); @@ -40,12 +40,16 @@ namespace Content.Server.GameObjects.Components.Power /// The method of draw we will try to use to place our load set via component parameter, defaults to using power providers /// [ViewVariables] - public virtual DrawTypes DrawType + public DrawTypes DrawType { - get => _drawType; + get => _drawType ?? DefaultDrawType; protected set => _drawType = value; } - private DrawTypes _drawType = DrawTypes.Provider; + + private DrawTypes? _drawType; + + protected virtual DrawTypes DefaultDrawType => DrawTypes.Provider; + /// /// The power draw method we are currently connected to and using @@ -206,7 +210,9 @@ namespace Content.Server.GameObjects.Components.Power { base.ExposeData(serializer); - serializer.DataField(ref _drawType, "drawtype", DrawTypes.Provider); + var drawType = DrawType; + serializer.DataField(ref drawType, "drawtype", DefaultDrawType); + DrawType = drawType; serializer.DataField(ref _priority, "priority", Powernet.Priority.Medium); if (SaveLoad) diff --git a/Content.Server/GameObjects/Components/Power/PowerNodeComponent.cs b/Content.Server/GameObjects/Components/Power/PowerNodeComponent.cs index c629a82aa0..48d515b10d 100644 --- a/Content.Server/GameObjects/Components/Power/PowerNodeComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerNodeComponent.cs @@ -2,6 +2,7 @@ using System.Linq; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.Interfaces.GameObjects.Components; using Robust.Shared.IoC; using Robust.Shared.ViewVariables; @@ -60,19 +61,21 @@ namespace Content.Server.GameObjects.Components.Power { return; } - var _emanager = IoCManager.Resolve(); - var position = Owner.GetComponent().WorldPosition; - var wires = _emanager.GetEntitiesIntersecting(Owner) - .Where(x => x.HasComponent()) - .OrderByDescending(x => (x.GetComponent().WorldPosition - position).Length); - var choose = wires.FirstOrDefault(); - if (choose != null) + + var position = Owner.Transform.WorldPosition; + + var sgc = Owner.GetComponent(); + var wire = sgc.GetCardinalNeighborCells() + .SelectMany(x => x.GetLocal()).Distinct() + .Select(x => x.TryGetComponent(out var c) ? c : null) + .Where(x => x != null).Distinct() + .ToArray() + .OrderByDescending(x => (x.Owner.Transform.WorldPosition - position).Length) + .FirstOrDefault(); + + if (wire?.Parent != null) { - var transfer = choose.GetComponent(); - if (transfer.Parent != null) - { - ConnectToPowernet(transfer.Parent); - } + ConnectToPowernet(wire.Parent); } } diff --git a/Content.Server/GameObjects/Components/Power/PowerProviderComponent.cs b/Content.Server/GameObjects/Components/Power/PowerProviderComponent.cs index cb48fd4b2d..81acd15457 100644 --- a/Content.Server/GameObjects/Components/Power/PowerProviderComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerProviderComponent.cs @@ -23,7 +23,7 @@ namespace Content.Server.GameObjects.Components.Power public override string Name => "PowerProvider"; /// - public override DrawTypes DrawType { get; protected set; } = DrawTypes.Node; + protected override DrawTypes DefaultDrawType => DrawTypes.Node; protected override bool SaveLoad => false; @@ -198,9 +198,9 @@ namespace Content.Server.GameObjects.Components.Power base.PowernetConnect(sender, eventarg); //Find devices within range to take under our control - var _emanager = IoCManager.Resolve(); + var entMgr = IoCManager.Resolve(); var position = Owner.GetComponent().WorldPosition; - var entities = _emanager.GetEntitiesInRange(Owner, PowerRange) + var entities = entMgr.GetEntitiesInRange(Owner, PowerRange) .Where(x => x.HasComponent()); @@ -252,8 +252,7 @@ namespace Content.Server.GameObjects.Components.Power { if (DeviceLoadList.Contains(device)) { - TheoreticalLoad -= oldLoad; - TheoreticalLoad += device.Load; + TheoreticalLoad = TheoreticalLoad - oldLoad + device.Load; } } diff --git a/Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs b/Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs index 754d007ef2..541b4f2f5a 100644 --- a/Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerTransferComponent.cs @@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Stack; using Content.Server.GameObjects.EntitySystems; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects.Components; using Robust.Shared.IoC; @@ -51,20 +52,22 @@ namespace Content.Server.GameObjects.Components.Power /// public void SpreadPowernet() { - var _emanager = IoCManager.Resolve(); - var position = Owner.GetComponent().WorldPosition; - var wires = _emanager.GetEntitiesInRange(Owner, 1.1f) //arbitrarily low, just scrape things //wip - .Where(x => x.HasComponent()); + var entMgr = IoCManager.Resolve(); + var sgc = Owner.GetComponent(); + var wires = sgc.GetCardinalNeighborCells() + .SelectMany(x => x.GetLocal()).Distinct() + .Select(x => x.TryGetComponent(out var c) ? c : null) + .Where(x => x != null).Distinct() + .ToArray(); //we have no parent so lets find a partner we can join his powernet if (Parent == null || Regenerating) { foreach (var wire in wires) { - var ptc = wire.GetComponent(); - if (ptc.CanConnectTo()) + if (wire.CanConnectTo()) { - ConnectToPowernet(ptc.Parent); + ConnectToPowernet(wire.Parent); break; } } @@ -72,15 +75,14 @@ namespace Content.Server.GameObjects.Components.Power //we couldn't find a partner so none must have spread yet, lets make our own powernet to spread if (Parent == null || Regenerating) { - var powernew = new Powernet(); - ConnectToPowernet(powernew); + ConnectToPowernet(new Powernet()); } } //Find nodes intersecting us and if not already assigned to a powernet assign them to us - var nodes = _emanager.GetEntitiesIntersecting(Owner) - .Where(x => x.HasComponent()) - .Select(x => x.GetComponent()); + var nodes = entMgr.GetEntitiesIntersecting(Owner) + .Select(x => x.TryGetComponent(out PowerNodeComponent pnc) ? pnc : null) + .Where(x => x != null); foreach (var node in nodes) { @@ -97,15 +99,14 @@ namespace Content.Server.GameObjects.Components.Power //spread powernet to nearby wires which haven't got one yet, and tell them to spread as well foreach (var wire in wires) { - var ptc = wire.GetComponent(); - if (ptc.Parent == null || Regenerating) + if (wire.Parent == null || Regenerating) { - ptc.ConnectToPowernet(Parent); - ptc.SpreadPowernet(); + wire.ConnectToPowernet(Parent); + wire.SpreadPowernet(); } - else if (ptc.Parent != Parent && !ptc.Parent.Dirty) + else if (wire.Parent != Parent && !wire.Parent.Dirty) { - Parent.MergePowernets(ptc.Parent); + Parent.MergePowernets(wire.Parent); } } }