Skip to content

Commit f0eb068

Browse files
authored
Merge pull request #891 from zymex22/dronePerformence25
Drone Compatibility and slight performance improvements
2 parents d41549b + c6a6cb8 commit f0eb068

File tree

7 files changed

+182
-294
lines changed

7 files changed

+182
-294
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Collections.Generic;
2+
using System.Reflection.Emit;
3+
using HarmonyLib;
4+
using ProjectRimFactory.Drones;
5+
using RimWorld;
6+
7+
namespace ProjectRimFactory.Common.HarmonyPatches;
8+
9+
10+
[HarmonyPatch (typeof(JobGiver_Work), "PawnCanUseWorkGiver")]
11+
public class Patch_JobGiver_Work_PawnCanUseWorkGiver
12+
{
13+
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
14+
{
15+
bool foundMissingRequiredCapacity = false;
16+
bool foundColonySubhuman = false;
17+
int foundColonySubhumanCnt = 0;
18+
int counter = 0;
19+
object retPointer = null;
20+
object initialSkipPointer = null;
21+
foreach (var instruction in instructions)
22+
{
23+
if (initialSkipPointer is null && instruction.opcode == OpCodes.Brtrue_S)
24+
{
25+
initialSkipPointer = instruction.operand;
26+
}
27+
28+
if (!foundColonySubhuman && instruction.opcode == OpCodes.Callvirt &&
29+
instruction.operand.ToString() == "Boolean get_IsColonySubhuman()")
30+
{
31+
foundColonySubhuman = true;
32+
}
33+
34+
if (foundColonySubhuman) foundColonySubhumanCnt++;
35+
36+
if (foundColonySubhumanCnt == 3)
37+
{
38+
yield return new CodeInstruction(OpCodes.Ldarg_1);
39+
yield return new CodeInstruction(OpCodes.Isinst, typeof(Pawn_Drone));
40+
yield return new CodeInstruction(OpCodes.Ldnull);
41+
yield return new CodeInstruction(OpCodes.Cgt_Un);
42+
43+
yield return new CodeInstruction(OpCodes.Brtrue_S, initialSkipPointer);
44+
}
45+
46+
if (!foundMissingRequiredCapacity && instruction.opcode == OpCodes.Callvirt &&
47+
instruction.operand.ToString() == "Verse.PawnCapacityDef MissingRequiredCapacity(Verse.Pawn)")
48+
{
49+
foundMissingRequiredCapacity = true;
50+
}
51+
if (foundMissingRequiredCapacity) counter++;
52+
53+
if (counter == 8) // brfalse.s IL_0091
54+
{
55+
retPointer = instruction.operand;
56+
}
57+
58+
if (counter == 9) // ldarg.2
59+
{
60+
yield return new CodeInstruction(OpCodes.Ldarg_1);
61+
yield return new CodeInstruction(OpCodes.Isinst, typeof(Pawn_Drone));
62+
yield return new CodeInstruction(OpCodes.Ldnull);
63+
yield return new CodeInstruction(OpCodes.Cgt_Un);
64+
65+
yield return new CodeInstruction(OpCodes.Brfalse_S, retPointer);
66+
67+
68+
}
69+
70+
yield return instruction;
71+
}
72+
}
73+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Linq;
2+
using RimWorld;
3+
using Verse;
4+
5+
namespace ProjectRimFactory.Common;
6+
7+
[StaticConstructorOnStartup]
8+
public static class StaticEmergencyWorkTypes
9+
{
10+
public static readonly WorkTypeDef[] EmergencyWorkTypes;
11+
static StaticEmergencyWorkTypes()
12+
{
13+
EmergencyWorkTypes = DefDatabase<WorkGiverDef>.AllDefsListForReading
14+
.Where(def => def.emergency).Select(def => def.workType).Distinct().ToArray();
15+
}
16+
}

Source/ProjectRimFactory/Drones/AI/JobGiver_DroneMain.cs

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,28 @@ public class JobGiver_DroneMain : ThinkNode_JobGiver
1111
protected override Job TryGiveJob(Pawn pawn)
1212
{
1313
var drone = (Pawn_Drone)pawn;
14-
if (drone.BaseStation == null) return null;
14+
if (drone.BaseStation is not Building_WorkGiverDroneStation baseStation) return null;
1515
if (!drone.BaseStation.Spawned || drone.BaseStation.Map != pawn.Map)
16+
{
1617
return new Job(PRFDefOf.PRFDrone_SelfTerminate);
17-
Job result;
18-
if (drone.BaseStation is Building_WorkGiverDroneStation b)
18+
}
19+
20+
// Just in case. should not really occur
21+
if (pawn.workSettings is null)
1922
{
20-
if (drone.BaseStation.CachedSleepTimeList.Contains(GenLocalDate.HourOfDay(drone).ToString()))
21-
return new Job(PRFDefOf.PRFDrone_ReturnToStation, drone.BaseStation);
2223
pawn.workSettings = new Pawn_WorkSettings(pawn);
2324
pawn.workSettings.EnableAndInitialize();
2425
pawn.workSettings.DisableAll();
25-
26-
foreach (var def in b.WorkSettingsDict.Keys)
27-
{
28-
if (b.WorkSettingsDict[def])
29-
{
30-
pawn.workSettings.SetPriority(def, 3);
31-
}
32-
else
33-
{
34-
pawn.workSettings.SetPriority(def, 0);
35-
}
36-
}
37-
38-
39-
// So the station finds the best job for the pawn
40-
result = b.TryIssueJobPackageDrone(drone, default, true).Job
41-
?? b.TryIssueJobPackageDrone(drone, default,false).Job;
42-
4326
}
44-
else
27+
28+
// Drones should directly react the Changed Settings
29+
foreach (var def in baseStation.WorkSettingsDict.Keys)
4530
{
46-
result = drone.BaseStation.TryGiveJob(drone);
31+
pawn.workSettings.SetPriority(def, baseStation.WorkSettingsDict[def] ? 3 : 0);
4732
}
48-
49-
return result ?? new Job(PRFDefOf.PRFDrone_ReturnToStation, drone.BaseStation);
33+
34+
var result = baseStation.TryGiveJob(drone);
35+
return result ?? new Job(PRFDefOf.PRFDrone_ReturnToStation, baseStation);
5036
}
5137
}
5238
}

Source/ProjectRimFactory/Drones/Building_DroneStation.cs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace ProjectRimFactory.Drones
1616
public abstract class Building_DroneStation : Building, IPowerSupplyMachineHolder, IDroneSeetingsITab, IPRF_SettingsContentLink
1717
{
1818
//Sleep Time List (Loaded on Spawn)
19-
public string[] CachedSleepTimeList;
19+
protected int[] CachedSleepTimeList;
2020

2121
protected CompRefuelable RefuelableComp;
2222

@@ -37,6 +37,7 @@ private int DroneRange
3737
}
3838

3939
private CompPowerWorkSetting compPowerWorkSetting;
40+
internal ModExtension_Skills ModExtensionDroneSkills;
4041

4142
private IEnumerable<IntVec3> StationRangeCells
4243
{
@@ -104,7 +105,7 @@ private void Update_droneAllowedArea_forDrones(Area dr)
104105

105106
private static readonly Texture2D Cancel = ContentFinder<Texture2D>.Get("UI/Designators/Cancel");
106107
private bool lockdown;
107-
private string droneAreaSelectorLable = "PRFDroneStationSelectArea".Translate("PRFDroneStationUnrestricted".Translate());
108+
private string droneAreaSelectorLabel = "PRFDroneStationSelectArea".Translate("PRFDroneStationUnrestricted".Translate());
108109
protected DefModExtension_DroneStation DefModExtensionDroneStation;
109110
protected List<Pawn_Drone> SpawnedDrones = [];
110111

@@ -121,8 +122,7 @@ public Dictionary<WorkTypeDef, bool> GetWorkSettings
121122
}
122123

123124
public List<SkillRecord> DroneSettingsSkillDefs => GetDroneSkillsRecord;
124-
125-
public string[] GetSleepTimeList => CachedSleepTimeList;
125+
public string[] GetSleepTimeList { get; private set; }
126126

127127
public CompRefuelable CompRefuelable => RefuelableComp;
128128

@@ -151,6 +151,7 @@ public override void SpawnSetup(Map map, bool respawningAfterLoad)
151151
RefuelableComp = GetComp<CompRefuelable>();
152152
compPowerTrader = GetComp<CompPowerTrader>();
153153
DefModExtensionDroneStation = def.GetModExtension<DefModExtension_DroneStation>();
154+
ModExtensionDroneSkills = def.GetModExtension<ModExtension_Skills>();
154155
compPowerWorkSetting = GetComp<CompPowerWorkSetting>();
155156
stationRangeCellsOld = StationRangeCells;
156157
//Setup Allowed Area
@@ -161,7 +162,8 @@ public override void SpawnSetup(Map map, bool respawningAfterLoad)
161162
Update_droneAllowedArea_forDrones(DroneAllowedArea);
162163
}
163164
//Load the SleepTimes from XML
164-
CachedSleepTimeList = DefModExtensionDroneStation.Sleeptimes.Split(',');
165+
CachedSleepTimeList = DefModExtensionDroneStation.GetSleepTimesInt();
166+
GetSleepTimeList = DefModExtensionDroneStation.GetSleepTimesString();
165167

166168
CashedGetCoverageCells = StationRangeCells.ToList();
167169

@@ -200,11 +202,11 @@ private void update_droneAreaSelectorLabel(Area area)
200202
{
201203
if (area is null)
202204
{
203-
droneAreaSelectorLable = "PRFDroneStationSelectArea".Translate("PRFDroneStationUnrestricted".Translate());
205+
droneAreaSelectorLabel = "PRFDroneStationSelectArea".Translate("PRFDroneStationUnrestricted".Translate());
204206
return;
205207
}
206208

207-
droneAreaSelectorLable = "PRFDroneStationSelectArea".Translate(area.Label);
209+
droneAreaSelectorLabel = "PRFDroneStationSelectArea".Translate(area.Label);
208210
}
209211

210212
public override void DynamicDrawPhaseAt(DrawPhase phase, Vector3 drawLoc, bool flip = false)
@@ -266,33 +268,29 @@ protected override void Tick()
266268
//Return if not Spawned
267269
if (!Spawned) return;
268270

269-
270-
//Should not draw much performance...
271-
//To enhance performance we could add "this.IsHashIntervalTick(60)"
271+
272272
if (SpawnedDrones.Count > 0 && compPowerTrader?.PowerOn == false)
273273
{
274274
for (var i = SpawnedDrones.Count - 1; i >= 0; i--)
275275
{
276276
SpawnedDrones[i].jobs.StartJob(new Job(PRFDefOf.PRFDrone_ReturnToStation, this), JobCondition.InterruptForced);
277277
}
278-
//return as there is nothing to do if its off....
278+
//return as there is nothing to do if it's off....
279279
return;
280280
}
281-
282-
283-
//Update the Allowed Area Range on Power Change
281+
282+
//Update the Allowed Area
284283
if (this.IsHashIntervalTick(60))
285284
{
286285
//Update the Range
287286
Update_droneAllowedArea_forDrones(DroneAllowedArea);
288-
289-
//TODO add cell calc
287+
290288
CashedGetCoverageCells = StationRangeCells.ToList();
291289
}
292290

293-
//Search for Job
291+
//Check if we should search for a Job
294292
if (!this.IsHashIntervalTick(60 + additionJobSearchTickDelay) || DronesLeft <= 0 || lockdown || compPowerTrader?.PowerOn == false) return;
295-
//The issue appears to be 100% with TryGiveJob
293+
296294
var drone = MakeDrone();
297295
GenSpawn.Spawn(drone, Position, Map);
298296

@@ -301,7 +299,7 @@ protected override void Tick()
301299
if (job != null)
302300
{
303301
additionJobSearchTickDelay = 0; //Reset to 0 - found a job -> may find more
304-
job.playerForced = true; // Why is that here? (included since the very beginning)
302+
job.playerForced = true; // Allow higher Danger for the Job
305303
//MakeDrone takes about 1ms
306304

307305
drone.jobs.StartJob(job);
@@ -310,15 +308,15 @@ protected override void Tick()
310308
{
311309
drone.Destroy();
312310
Notify_DroneGained();
313-
//Experimental Delay
314-
//Add delay (limit to 300) i am well aware that this can be higher that 300 with the current code
311+
//Add delay (limit to 300) effective limit is 510
315312
if (additionJobSearchTickDelay < 300)
316313
{
317314
//Exponential delay
318315
additionJobSearchTickDelay = (additionJobSearchTickDelay + 1) * 2;
319316
}
320317
}
321318
}
319+
322320
public void Notify_DroneMayBeLost(Pawn_Drone drone)
323321
{
324322
if (!SpawnedDrones.Contains(drone)) return;
@@ -460,7 +458,7 @@ public override IEnumerable<Gizmo> GetGizmos()
460458
yield return new DroneAreaSelector()
461459
{
462460
icon = ContentFinder<Texture2D>.Get("UI/Designators/AreaAllowedExpand"),
463-
defaultLabel = droneAreaSelectorLable,
461+
defaultLabel = droneAreaSelectorLabel,
464462
SelectAction = (a) =>
465463
{
466464
Update_droneAllowedArea_forDrones(a);

0 commit comments

Comments
 (0)