public void StartJob(Job newJob, JobCondition lastJobEndCondition = JobCondition.None, ThinkNode jobGiver = null, bool resumeCurJobAfterwards = false, bool cancelBusyStances = true, ThinkTreeDef thinkTree = null, JobTag?tag = null, bool fromQueue = false) { this.startingNewJob = true; try { if (!fromQueue && (!Find.TickManager.Paused || this.lastJobGivenAtFrame == RealTime.frameCount)) { this.jobsGivenThisTick++; this.jobsGivenThisTickTextual = this.jobsGivenThisTickTextual + "(" + newJob.ToString() + ") "; } this.lastJobGivenAtFrame = RealTime.frameCount; if (this.jobsGivenThisTick > 10) { string text = this.jobsGivenThisTickTextual; this.jobsGivenThisTick = 0; this.jobsGivenThisTickTextual = ""; this.startingNewJob = false; this.pawn.ClearReservationsForJob(newJob); JobUtility.TryStartErrorRecoverJob(this.pawn, string.Concat(new string[] { this.pawn.ToStringSafe <Pawn>(), " started 10 jobs in one tick. newJob=", newJob.ToStringSafe <Job>(), " jobGiver=", jobGiver.ToStringSafe <ThinkNode>(), " jobList=", text }), null, null); } else { if (this.debugLog) { this.DebugLogEvent(string.Concat(new object[] { "StartJob [", newJob, "] lastJobEndCondition=", lastJobEndCondition, ", jobGiver=", jobGiver, ", cancelBusyStances=", cancelBusyStances })); } if (cancelBusyStances && this.pawn.stances.FullBodyBusy) { this.pawn.stances.CancelBusyStanceHard(); } if (this.curJob != null) { if (lastJobEndCondition == JobCondition.None) { Log.Warning(string.Concat(new object[] { this.pawn, " starting job ", newJob, " from JobGiver ", this.pawn.mindState.lastJobGiver, " while already having job ", this.curJob, " without a specific job end condition." }), false); lastJobEndCondition = JobCondition.InterruptForced; } if (resumeCurJobAfterwards && this.curJob.def.suspendable) { this.jobQueue.EnqueueFirst(this.curJob, null); if (this.debugLog) { this.DebugLogEvent(" JobQueue EnqueueFirst curJob: " + this.curJob); } this.CleanupCurrentJob(lastJobEndCondition, false, cancelBusyStances); } else { this.CleanupCurrentJob(lastJobEndCondition, true, cancelBusyStances); } } if (newJob == null) { Log.Warning(this.pawn + " tried to start doing a null job.", false); } else { newJob.startTick = Find.TickManager.TicksGame; if (this.pawn.Drafted || newJob.playerForced) { newJob.ignoreForbidden = true; newJob.ignoreDesignations = true; } this.curJob = newJob; this.pawn.mindState.lastJobGiver = jobGiver; this.pawn.mindState.lastJobGiverThinkTree = thinkTree; this.curDriver = this.curJob.MakeDriver(this.pawn); if (this.curDriver.TryMakePreToilReservations()) { Job job = this.TryOpportunisticJob(newJob); if (job != null) { this.jobQueue.EnqueueFirst(newJob, null); this.curJob = null; this.curDriver = null; this.StartJob(job, JobCondition.None, null, false, true, null, null, false); } else { if (tag != null) { this.pawn.mindState.lastJobTag = tag.Value; } this.curDriver.SetInitialPosture(); this.curDriver.Notify_Starting(); this.curDriver.SetupToils(); this.curDriver.ReadyForNextToil(); } } else if (fromQueue) { this.EndCurrentJob(JobCondition.QueuedNoLongerValid, true); } else { Log.Warning("TryMakePreToilReservations() returned false for a non-queued job right after StartJob(). This should have been checked before. curJob=" + this.curJob.ToStringSafe <Job>(), false); this.EndCurrentJob(JobCondition.Errored, true); } } } } finally { this.startingNewJob = false; } }
public void StartJob(Job newJob, JobCondition lastJobEndCondition = JobCondition.None, ThinkNode jobGiver = null, bool resumeCurJobAfterwards = false, bool cancelBusyStances = true, ThinkTreeDef thinkTree = null, JobTag?tag = null, bool fromQueue = false, bool canReturnCurJobToPool = false) { startingNewJob = true; try { if (!fromQueue && (!Find.TickManager.Paused || lastJobGivenAtFrame == RealTime.frameCount)) { jobsGivenThisTick++; if (Prefs.DevMode) { jobsGivenThisTickTextual = jobsGivenThisTickTextual + "(" + newJob.ToString() + ") "; } } lastJobGivenAtFrame = RealTime.frameCount; if (jobsGivenThisTick > 10) { string text = jobsGivenThisTickTextual; jobsGivenThisTick = 0; jobsGivenThisTickTextual = ""; startingNewJob = false; pawn.ClearReservationsForJob(newJob); JobUtility.TryStartErrorRecoverJob(pawn, pawn.ToStringSafe() + " started 10 jobs in one tick. newJob=" + newJob.ToStringSafe() + " jobGiver=" + jobGiver.ToStringSafe() + " jobList=" + text); return; } if (debugLog) { DebugLogEvent(string.Concat("StartJob [", newJob, "] lastJobEndCondition=", lastJobEndCondition, ", jobGiver=", jobGiver, ", cancelBusyStances=", cancelBusyStances.ToString())); } if (cancelBusyStances && pawn.stances.FullBodyBusy) { pawn.stances.CancelBusyStanceHard(); } if (curJob != null) { if (lastJobEndCondition == JobCondition.None) { Log.Warning(string.Concat(pawn, " starting job ", newJob, " from JobGiver ", newJob.jobGiver, " while already having job ", curJob, " without a specific job end condition.")); lastJobEndCondition = JobCondition.InterruptForced; } if (resumeCurJobAfterwards && curJob.def.suspendable) { jobQueue.EnqueueFirst(curJob); if (debugLog) { DebugLogEvent(" JobQueue EnqueueFirst curJob: " + curJob); } CleanupCurrentJob(lastJobEndCondition, releaseReservations: false, cancelBusyStances); } else { CleanupCurrentJob(lastJobEndCondition, releaseReservations: true, cancelBusyStances, canReturnCurJobToPool); } } if (newJob == null) { Log.Warning(string.Concat(pawn, " tried to start doing a null job.")); return; } newJob.startTick = Find.TickManager.TicksGame; if (pawn.Drafted || newJob.playerForced) { newJob.ignoreForbidden = true; newJob.ignoreDesignations = true; } curJob = newJob; curJob.jobGiverThinkTree = thinkTree; curJob.jobGiver = jobGiver; curDriver = curJob.MakeDriver(pawn); bool flag = fromQueue; if (curDriver.TryMakePreToilReservations(!flag)) { Job job = TryOpportunisticJob(newJob); if (job != null) { jobQueue.EnqueueFirst(newJob); curJob = null; curDriver = null; StartJob(job); return; } if (tag.HasValue) { pawn.mindState.lastJobTag = tag.Value; } curDriver.SetInitialPosture(); curDriver.Notify_Starting(); curDriver.SetupToils(); curDriver.ReadyForNextToil(); } else if (flag) { EndCurrentJob(JobCondition.QueuedNoLongerValid); } else { Log.Warning("TryMakePreToilReservations() returned false for a non-queued job right after StartJob(). This should have been checked before. curJob=" + curJob.ToStringSafe()); EndCurrentJob(JobCondition.Errored); } } finally { startingNewJob = false; } }