Files
Performance-Fish/Source/PerformanceFish/Planet/MothballOptimization.cs
T
bbradson ca9321add8 Lots of new optimizations utilizing prepatcher
To start, this mod now requires Prepatcher and Fishery.
New optimizations include: gene ticking improvements, world object improvements, hediff optimizations, world pawn gc optimizations, better mothballing, dds support, ContentFinder caching, additions and changes to reflection caching, as well as various other additions. Multiplayer support has been improved too, but should be considered highly experimental. The WorkGiver_DoBill bug is fixed in this build. Multiple patches aiming to improve RimWorld's load time have been added too.
2023-06-03 20:24:38 +02:00

106 lines
4.1 KiB
C#

// Copyright (c) 2023 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using PerformanceFish.Prepatching;
using RimWorld.Planet;
namespace PerformanceFish.Planet;
public class MothballOptimization : ClassWithFishPrepatches
{
public const string BASIC_DESCRIPTION
= "Mothballing means to \"take something out of operation but maintain it so that it can be used in the "
+ "future.\" RimWorld has this system for world pawns along with a number of conditions which can block it "
+ "from taking effect.";
public class WorldPawnsDefPreventingMothball : FishPrepatch
{
public override string? Description { get; }
= BASIC_DESCRIPTION + " This patch essentially serves as a whitelist to allow mothballing a lot more "
+ "pawns. Large performance impact, but not entirely side-effect free. Certain slowly progressing and not "
+ "lethal conditions like addictions or pregnancy do not progress on mothballed pawns.";
public static bool MothballEverything => FishSettings.MothballEverything;
public override MethodBase TargetMethodBase { get; }
= AccessTools.Method(typeof(WorldPawns), nameof(WorldPawns.DefPreventingMothball));
public override void Transpiler(ILProcessor ilProcessor, ModuleDefinition module)
{
var instructions = ilProcessor.instructions;
for (var i = 0; i < instructions.Count; i++)
{
if (instructions[i].Operand is not MethodReference { Name: "IsPermanent" })
continue;
ilProcessor.InsertAt(i++, OpCodes.Dup);
i++; // bool IsPermanent(hediff)
ilProcessor.InsertRange(i,
OpCodes.Ldarg_0,
OpCodes.Ldarg_1,
(OpCodes.Call, methodof(AllowMothball)));
break;
}
}
public static bool AllowMothball(Hediff hediff, bool isPermanent, WorldPawns worldPawns, Pawn pawn)
=> MothballEverything
|| isPermanent
|| !hediff.Visible
|| (/*IsLowPriority(worldPawns, pawn)
&&*/ AllowedDefs.Contains(hediff.def)
&& hediff is
{
CurStage.lifeThreatening: false, SummaryHealthPercentImpact: < 0.01f, Bleeding: false
}
&& (!HasBlockingComp(hediff) || !HasLifeThreateningStage(hediff.def)));
private static bool HasBlockingComp(Hediff hediff)
=> hediff.def.minSeverity <= 0f
&& hediff is HediffWithComps hediffWithComps
&& hediffWithComps.comps.ExistsAndNotNull(static comp
=> comp is HediffComp_TendDuration
&& comp.props is not HediffCompProperties_TendDuration { showTendQuality: false });
private static bool IsLowPriority(WorldPawns worldPawns, Pawn pawn)
=> WorldPawns.lowPrioritySituations.Contains(worldPawns.GetSituation(pawn));
}
public static HashSet<HediffDef> AllowedDefs => _allowedDefs ??= PrepareAllowedDefs();
[MethodImpl(MethodImplOptions.NoInlining)]
public static HashSet<HediffDef> PrepareAllowedDefs()
=> DefDatabase<HediffDef>.AllDefsListForReading.Where(static def
=> def.lethalSeverity < 0f
// && !def.displayWound
&& !CausesBleeding(def)
&& !LosesSeverityPerDay(def)
&& (!HasLifeThreateningStage(def) || !HasBlockingCompProperties(def)))
.ToHashSet();
private static bool HasBlockingCompProperties(HediffDef def)
=> def.minSeverity <= 0f
&& def.comps.ExistsAndNotNull(static props
=> (props.compClass?.IsAssignableTo(typeof(HediffComp_TendDuration)) ?? false)
&& props is not HediffCompProperties_TendDuration { showTendQuality: false });
private static bool LosesSeverityPerDay(HediffDef def)
=> def.minSeverity <= 0f
&& def.comps.ExistsAndNotNull(static props
=> props is HediffCompProperties_SeverityPerDay severityProps
&& (severityProps.severityPerDay <= -0.35f || severityProps.severityPerDayRange.max <= -0.35f));
private static bool HasLifeThreateningStage(HediffDef def)
=> def.stages.ExistsAndNotNull(static stage => stage.lifeThreatening);
private static bool CausesBleeding(HediffDef def) => def.injuryProps is { bleedRate: > 0.001f };
private static HashSet<HediffDef>? _allowedDefs;
}