diff --git a/1.4/Assemblies/AchtungMod.dll b/1.4/Assemblies/AchtungMod.dll index ed12ae4..14c21c3 100644 Binary files a/1.4/Assemblies/AchtungMod.dll and b/1.4/Assemblies/AchtungMod.dll differ diff --git a/Source/ForcedExtensions.cs b/Source/ForcedExtensions.cs index c9e6094..79160a9 100644 --- a/Source/ForcedExtensions.cs +++ b/Source/ForcedExtensions.cs @@ -2,7 +2,6 @@ using System.Linq; using Verse.AI; using Verse; -using UnityEngine.VR; namespace AchtungMod { diff --git a/Source/ForcedJob.cs b/Source/ForcedJob.cs index 8f7ca1f..55134d9 100644 --- a/Source/ForcedJob.cs +++ b/Source/ForcedJob.cs @@ -14,6 +14,9 @@ public class ForcedJob : IExposable public HashSet targets = new(); public Pawn pawn = null; public List workgiverDefs = new(); + public List workgiverScanners = new(); + public static readonly QuotaCache getThingJobCache = new(10); + public static readonly QuotaCache getCellJobCache = new(10); public bool isThingJob = false; public bool reentranceFlag = false; public XY lastLocation = XY.Invalid; @@ -58,6 +61,7 @@ public class ForcedJob : IExposable public ForcedJob() { workgiverDefs = new List(); + workgiverScanners = new List(); targets = new HashSet(); buildSmart = Achtung.Settings.buildingSmartDefault; lastLocation = XY.Invalid; @@ -68,6 +72,7 @@ public ForcedJob(Pawn pawn, LocalTargetInfo item, List workgiverDe { this.pawn = pawn; this.workgiverDefs = workgiverDefs.Where(wgd => wgd?.giverClass != null).ToList(); + workgiverScanners = workgiverDefs.Select(wgd => wgd.Worker).OfType().ToList(); targets = new HashSet() { new ForcedTarget(item, MaterialScore(item)) }; buildSmart = Achtung.Settings.buildingSmartDefault; @@ -92,9 +97,6 @@ public IEnumerable AllCells(bool onlyValid = false) return validTargets.Select(target => target.XY); } - public IEnumerable WorkGiverScanners => workgiverDefs - .Select(wgd => wgd.Worker).OfType(); - public static int MaterialScore(LocalTargetInfo item) { var scoreThing = 0; @@ -195,7 +197,7 @@ public bool GetNextJob(out Job job) { job = null; - var workGiversByPrio = WorkGiverScanners.OrderBy(worker => + var workGiversByPrio = workgiverScanners.OrderBy(worker => { if (worker is WorkGiver_ConstructDeliverResourcesToBlueprints) return 1; @@ -314,13 +316,13 @@ public void ToggleSmartBuilding() buildSmart = !buildSmart; } - public bool HasJob(Thing thing) + public bool ThingHasJob(Thing thing) { try { lock (pawn.Map) { - return WorkGiverScanners.Any(scanner => thing.GetThingJob(pawn, scanner, true) != null); + return getThingJobCache.Get(thing, t => workgiverScanners.Any(scanner => t.GetThingJob(pawn, scanner, true) != null)); } } catch @@ -329,13 +331,13 @@ public bool HasJob(Thing thing) } } - public bool HasJob(XY cell) + public bool CellHasJob(XY cell) { try { lock (pawn.Map) { - return WorkGiverScanners.Any(scanner => ((IntVec3)cell).GetCellJob(pawn, scanner) != null); + return getCellJobCache.Get(cell, c => workgiverScanners.Any(scanner => ((IntVec3)c).GetCellJob(pawn, scanner) != null)); } } catch @@ -368,7 +370,7 @@ public IEnumerator ExpandThingTargets(Map map) for (var i = 0; i < newThings.Length && cancelled == false && maxCountVerifier(); i++) { var newThing = newThings[i]; - if (things.Contains(newThing) == false && HasJob(newThing)) + if (things.Contains(newThing) == false && ThingHasJob(newThing)) { LocalTargetInfo item = newThing; _ = targets.Add(new ForcedTarget(item, MaterialScore(item))); @@ -395,7 +397,7 @@ public IEnumerator ExpandCellTargets(Map map) for (var i = 0; i < newCells.Length && cancelled == false && maxCountVerifier(); i++) { var cell = newCells[i]; - if (HasJob(cell)) + if (CellHasJob(cell)) { LocalTargetInfo item = cell; _ = targets.Add(new ForcedTarget(item, 0)); @@ -419,8 +421,8 @@ public IEnumerator ContractTargets(Map map) for (var i = 0; i < cells.Length && cancelled == false; i++) { var cell = cells[i]; - if (cell.InBounds(map) && HasJob(cell) == false) - if (map.thingGrid.ThingsListAtFast(cell).All(thing => thing.Spawned == false || HasJob(thing) == false)) + if (cell.InBounds(map) && CellHasJob(cell) == false) + if (map.thingGrid.ThingsListAtFast(cell).All(thing => thing.Spawned == false || ThingHasJob(thing) == false)) _ = targets.RemoveWhere(target => target.XY == cell || (target.item.thingInt?.AllCells().Contains(cell) ?? false)); yield return null; } diff --git a/Source/Main.cs b/Source/Main.cs index 30c1f7b..e52693d 100644 --- a/Source/Main.cs +++ b/Source/Main.cs @@ -7,7 +7,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.IO.Ports; using System.Linq; using System.Reflection; using System.Reflection.Emit; diff --git a/Source/QuotaCache.cs b/Source/QuotaCache.cs new file mode 100644 index 0000000..b16e82e --- /dev/null +++ b/Source/QuotaCache.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +namespace AchtungMod +{ + public class QuotaCache + { + private readonly Dictionary cache = new(); + private readonly int maxRetrievals; + + public QuotaCache(int maxRetrievals) + { + this.maxRetrievals = maxRetrievals; + } + + private void Add(S key, T value) + { + cache[key] = (value, 0); + } + + public T Get(S key, Func fetchCallback) + { + if (!cache.ContainsKey(key) || cache[key].count >= maxRetrievals) + { + T newValue = fetchCallback(key); + Add(key, newValue); + } + + var (value, count) = cache[key]; + cache[key] = (value, count + 1); + + return value; + } + } +}