From 572cc1d9abde8bfc8e05c6b739f2d015cb91da3f Mon Sep 17 00:00:00 2001 From: "[object Object]" <2634337+MikeJeffers@users.noreply.github.com> Date: Sun, 22 Aug 2021 17:26:31 -0400 Subject: [PATCH] Fitting fix (#383) * initial fix, pre-compute fitting limits, isolate optimizations * bring back in the optims, red herring * cancel token on exit, try/catch on accessing empty flocks * capture task cancellation logic into abstract base class * more context on warn --- .../Zone/Containers/EquipModule.cs | 7 +++++- .../Zone/Containers/RemoveModule.cs | 1 + .../Zone/Containers/ZoneChangeModule.cs | 3 +++ src/Perpetuum/Modules/Module.cs | 10 ++++++++ src/Perpetuum/Robots/Robot.Properties.cs | 23 +++++++++++++++---- src/Perpetuum/Robots/Robot.cs | 9 ++++++++ 6 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/Perpetuum.RequestHandlers/Zone/Containers/EquipModule.cs b/src/Perpetuum.RequestHandlers/Zone/Containers/EquipModule.cs index d26a65ceb..d0eaefcb3 100644 --- a/src/Perpetuum.RequestHandlers/Zone/Containers/EquipModule.cs +++ b/src/Perpetuum.RequestHandlers/Zone/Containers/EquipModule.cs @@ -14,11 +14,16 @@ public override void DoChange(IZoneRequest request, Player player, Container con var componentType = request.Data.GetOrDefault(k.robotComponent).ToEnum(); var component = player.GetRobotComponentOrThrow(componentType); var slot = request.Data.GetOrDefault(k.slot); - component.MakeSlotFree(slot, container); + component.GetModule(slot).ThrowIfNotNull(ErrorCodes.UsedSlot); //OPP: explicitly prohibit this to make this simpler + // component.MakeSlotFree(slot, container); // Big nope var moduleEid = request.Data.GetOrDefault(k.moduleEID); var module = (Module)container.GetItemOrThrow(moduleEid).Unstack(1); module.CheckEnablerExtensionsAndThrowIfFailed(player.Character); + + //Perform pre-fit check for fitting legality + player.CheckEnergySystemAndThrowIfFailed(module); + component.EquipModuleOrThrow(module, slot); } } diff --git a/src/Perpetuum.RequestHandlers/Zone/Containers/RemoveModule.cs b/src/Perpetuum.RequestHandlers/Zone/Containers/RemoveModule.cs index 6f391d9bf..74a5c23d2 100644 --- a/src/Perpetuum.RequestHandlers/Zone/Containers/RemoveModule.cs +++ b/src/Perpetuum.RequestHandlers/Zone/Containers/RemoveModule.cs @@ -10,6 +10,7 @@ public override void DoChange(IZoneRequest request, Player player, Container con { var moduleEid = request.Data.GetOrDefault(k.moduleEID); var module = player.GetModule(moduleEid).ThrowIfNull(ErrorCodes.ModuleNotFound); + player.CheckEnergySystemAndThrowIfFailed(module, true); module.Owner = player.Character.Eid; module.Unequip(container); } diff --git a/src/Perpetuum.RequestHandlers/Zone/Containers/ZoneChangeModule.cs b/src/Perpetuum.RequestHandlers/Zone/Containers/ZoneChangeModule.cs index ab68ab54c..e1345ca46 100644 --- a/src/Perpetuum.RequestHandlers/Zone/Containers/ZoneChangeModule.cs +++ b/src/Perpetuum.RequestHandlers/Zone/Containers/ZoneChangeModule.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Transactions; using Perpetuum.Accounting.Characters; @@ -77,6 +78,7 @@ private void EquipChange(IZoneRequest request, Player player, Container containe DoChange(request, player, container); player.OnEquipChange(); player.Initialize(character); + player.CheckEnergySystemAndThrowIfFailed(); // Apply ratios to prevent resetting values @@ -106,6 +108,7 @@ private MessageBuilder BuildMessage(IZoneRequest request, Player player, Contain private static void OnCompleted(Player player, MessageBuilder message) { + player.Initialize(player.Character); player.SendRefreshUnitPacket(); message.Send(); } diff --git a/src/Perpetuum/Modules/Module.cs b/src/Perpetuum/Modules/Module.cs index aae0d9711..3391793fb 100644 --- a/src/Perpetuum/Modules/Module.cs +++ b/src/Perpetuum/Modules/Module.cs @@ -139,5 +139,15 @@ public void ApplyRobotPropertyModifiers(ref ItemPropertyModifier modifier) ParentRobot?.GetPropertyModifier(m).Modify(ref modifier); } } + + public void SimulateRobotPropertyModifiers(Robot parent, ref ItemPropertyModifier modifier) + { + var modifiers = PropertyModifiers.GetOrEmpty(modifier.Field); + + foreach (var m in modifiers) + { + parent.GetPropertyModifier(m).Modify(ref modifier); + } + } } } \ No newline at end of file diff --git a/src/Perpetuum/Robots/Robot.Properties.cs b/src/Perpetuum/Robots/Robot.Properties.cs index 6d77b06a4..34f674e9a 100644 --- a/src/Perpetuum/Robots/Robot.Properties.cs +++ b/src/Perpetuum/Robots/Robot.Properties.cs @@ -133,14 +133,29 @@ public override ItemPropertyModifier GetPropertyModifier(AggregateField field) return modifier; } - public bool CheckPowerGridForModule(Module module) + public bool CheckPowerGridForModule(Module module, bool removing=false) { - return TotalPowerGridUsage + module.PowerGridUsage <= PowerGridMax; + return SimulateFitting(module, removing, PowerGridMax, TotalPowerGridUsage, AggregateField.powergrid_usage, AggregateField.powergrid_max_modifier); } - public bool CheckCpuForModule(Module module) + public bool CheckCpuForModule(Module module, bool removing = false) { - return TotalCpuUsage + module.CpuUsage <= CpuMax; + return SimulateFitting(module, removing, CpuMax, TotalCpuUsage, AggregateField.cpu_usage, AggregateField.cpu_max_modifier); + } + + private bool SimulateFitting(Module module, bool removing, double max, double current, AggregateField usageField, AggregateField maxModField) + { + double moduleUsageEstimate = 0; + var itemMod = module.BasePropertyModifiers.GetPropertyModifier(usageField); + module.SimulateRobotPropertyModifiers(this, ref itemMod); + itemMod.Modify(ref moduleUsageEstimate); + moduleUsageEstimate = removing ? -moduleUsageEstimate : moduleUsageEstimate; + if (removing && module.BasePropertyModifiers.GetPropertyModifier(maxModField).HasValue) + { + var mod = module.BasePropertyModifiers.GetPropertyModifier(maxModField).Value; + max /= Math.Max(mod, 1); + } + return current + moduleUsageEstimate <= max; } public double TotalPowerGridUsage diff --git a/src/Perpetuum/Robots/Robot.cs b/src/Perpetuum/Robots/Robot.cs index 2a603ce52..8804f83f3 100644 --- a/src/Perpetuum/Robots/Robot.cs +++ b/src/Perpetuum/Robots/Robot.cs @@ -354,6 +354,15 @@ public IEnumerable RobotComponents get { return _robotComponents.Value; } } + public void CheckEnergySystemAndThrowIfFailed(Module module, bool isRemoving=false) + { + if (!CheckPowerGridForModule(module, isRemoving)) + throw PerpetuumException.Create(ErrorCodes.OutOfPowergrid); + + if (!CheckCpuForModule(module, isRemoving)) + throw PerpetuumException.Create(ErrorCodes.OutOfCpu); + } + public void CheckEnergySystemAndThrowIfFailed() { if (PowerGrid < 0)