예제 #1
0
        static public string PawnGCDebugResults(WorldPawnGC __instance)
        {
            Dictionary <Pawn, string> dictionary = new Dictionary <Pawn, string>();

            AccumulatePawnGCData(__instance, dictionary).ExecuteEnumerable();
            Dictionary <string, int> countReasons = new Dictionary <string, int>();

            foreach (Pawn current in Find.WorldPawns.AllPawnsAlive)
            {
                string reason;
                if (!dictionary.TryGetValue(current, out reason))
                {
                    reason = "Discarded";
                }
                int counter;
                if (!countReasons.TryGetValue(reason, out counter))
                {
                    counter = 0;
                }
                countReasons[reason] = ++counter;
            }
            return(GenText.ToLineList(from kvp in countReasons
                                      orderby kvp.Value descending
                                      select string.Format("{0}: {1}", kvp.Value, kvp.Key)));
        }
예제 #2
0
        static public void RunGC(WorldPawnGC __instance)
        {
            __instance.CancelGCPass();
            PerfLogger.Reset();
            PawnGCPass(__instance).ExecuteEnumerable();
            float num = PerfLogger.Duration() * 1000f;

            PerfLogger.Flush();
            Log.Message(string.Format("World pawn GC run complete in {0} ms", num));
        }
예제 #3
0
 static public void LogDotgraph(WorldPawnGC __instance)
 {
     logDotgraph                 = new StringBuilder();
     logDotgraphUniqueLinks      = new HashSet <string>();
     GUIUtility.systemCopyBuffer = "building log dot graph...";
     logDotgraph.AppendLine("digraph { rankdir=LR;");
     AccumulatePawnGCData(__instance, new Dictionary <Pawn, string>()).ExecuteEnumerable();
     logDotgraph.AppendLine("}");
     GUIUtility.systemCopyBuffer = logDotgraph.ToString();
     Log.Message("Dotgraph copied to clipboard");
     logDotgraph            = null;
     logDotgraphUniqueLinks = null;
 }
예제 #4
0
        static private IEnumerable AccumulatePawnGCData(WorldPawnGC __instance, Dictionary <Pawn, string> keptPawns)
        {
            GetCriticalPawnReasonType GetCriticalPawnReason = (GetCriticalPawnReasonType)Delegate.CreateDelegate(typeof(GetCriticalPawnReasonType), __instance,
                                                                                                                 typeof(WorldPawnGC).GetMethod("GetCriticalPawnReason", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance));

            foreach (Pawn current in PawnsFinder.AllMapsWorldAndTemporary_AliveOrDead)
            {
                string criticalPawnReason = GetCriticalPawnReason(current);
                if (!criticalPawnReason.NullOrEmpty())
                {
                    keptPawns[current] = criticalPawnReason;
                    if (logDotgraph != null)
                    {
                        logDotgraph.AppendLine(string.Format("{0} [label=<{0}<br/><font point-size=\"10\">{1}</font>> color=\"{2}\" shape=\"{3}\"];", new object[]
                        {
                            WorldPawnGC.DotgraphIdentifier(current),
                            criticalPawnReason,
                            (current.relations == null || !current.relations.everSeenByPlayer) ? "grey" : "black",
                            (!current.RaceProps.Humanlike) ? "box" : "oval"
                        }));
                    }
                }
                else if (logDotgraph != null)
                {
                    logDotgraph.AppendLine(string.Format("{0} [color=\"{1}\" shape=\"{2}\"];", WorldPawnGC.DotgraphIdentifier(current), (current.relations == null || !current.relations.everSeenByPlayer) ? "grey" : "black", (!current.RaceProps.Humanlike) ? "box" : "oval"));
                }
            }
            //This is for finding non spawned but alive raiders/visitors not tremendously usefull
            foreach (Pawn current2 in (from pawn in PawnsFinder.AllMapsWorldAndTemporary_Alive
                                       where pawn.RaceProps.Humanlike && !keptPawns.ContainsKey(pawn)
                                       orderby pawn.records.StoryRelevance descending select pawn).Take(20))
            {
                keptPawns[current2] = "StoryRelevant";
            }
            //We now have lets say 1000 keepers. Over the generations family trees grow wider and wider.
            //Not only do the trees grow wider over generations, male animals will breed with multiple females and as such multiple family trees get merged amplyfiing the problem.
            Pawn[] storyRelevantPawns = new Pawn[keptPawns.Count];
            keptPawns.Keys.CopyTo(storyRelevantPawns, 0);
            foreach (Pawn pawn in storyRelevantPawns)
            {
                AddAllRelationships(__instance, pawn, keptPawns);
                yield return(null);
            }
            foreach (Pawn pawn in storyRelevantPawns)
            {
                AddAllMemories(pawn, keptPawns);
            }
        }
예제 #5
0
 public static bool WorldPawnGCTickPrefix(WorldPawnGC __instance)
 {
     if (lastSuccessfulGCTickGet(__instance) < Find.TickManager.TicksGame / 15000 * 15000)
     {
         if (activeGCProcessGet(__instance) == null)
         {
             activeGCProcessSet(__instance, PawnGCPass(__instance).GetEnumerator());
             //since we are faster we could amp up the speed, reducing the chance of an interrupt and thus overhead
             //currentGCRateSet(__instance,8);
             if (DebugViewSettings.logWorldPawnGC)
             {
                 Log.Message(string.Format("World pawn GC started at rate {0}", currentGCRateGet(__instance)));
             }
         }
     }
     return(true);
 }
예제 #6
0
        public static bool WorldPawnGCTick(WorldPawnGC __instance)
        {
            if (lastSuccessfulGCTickFieldRef(__instance) >= Find.TickManager.TicksGame / 15000 * 15000)
            {
                return(false);
            }

            //if (activeGCProcess == null)
            //{
            //activeGCProcess = PawnGCPass().GetEnumerator();
            if (DebugViewSettings.logWorldPawnGC)
            {
                Log.Message($"World pawn GC started at rate {currentGCRateFieldRef(__instance)}");
            }
            //}

            //if (activeGCProcess == null)
            //{
            //return false;
            //}

            bool flag = false;

            for (int i = 0; i < currentGCRateFieldRef(__instance); i++)
            {
                if (flag)
                {
                    break;
                }

                //flag = !activeGCProcess.MoveNext();
            }

            if (flag)
            {
                lastSuccessfulGCTickFieldRef(__instance) = Find.TickManager.TicksGame;
                currentGCRateFieldRef(__instance)        = 1;
                //activeGCProcess = null;
                if (DebugViewSettings.logWorldPawnGC)
                {
                    Log.Message("World pawn GC complete");
                }
            }
            return(false);
        }
예제 #7
0
        static IEnumerable PawnGCPass(WorldPawnGC __instance)
        {
            Dictionary <Pawn, string> keptPawns = new Dictionary <Pawn, string>();

            foreach (object _ in AccumulatePawnGCData(__instance, keptPawns))
            {
                yield return(null);
            }
            //since resets happen if pawns are added/removed we do not need to create the copy before we accumulate the data
            Pawn[] AllPawnsAliveOrDeadBuffered = Find.WorldPawns.AllPawnsAliveOrDead.ToArray <Pawn>();
            foreach (Pawn pawn in AllPawnsAliveOrDeadBuffered)
            {
                if (!keptPawns.ContainsKey(pawn))
                {
                    Find.WorldPawns.RemoveAndDiscardPawnViaGC(pawn);
                }
            }
        }
예제 #8
0
 static bool Prefix(WorldPawnGC __instance, out string __result)
 {
     __result = WorldPawnGCOptimized.PawnGCDebugResults(__instance);
     return(false);
 }
예제 #9
0
 static bool Prefix(WorldPawnGC __instance)
 {
     WorldPawnGCOptimized.LogDotgraph(__instance);
     return(false);
 }
예제 #10
0
 static bool Prefix(WorldPawnGC __instance)
 {
     WorldPawnGCOptimized.RunGC(__instance);
     return(false);
 }
예제 #11
0
 static bool Prefix(WorldPawnGC __instance)
 {
     return(WorldPawnGCOptimized.WorldPawnGCTickPrefix(__instance));
 }
예제 #12
0
 static private void AddAllMemories(Pawn pawn, Dictionary <Pawn, string> keptPawns)
 {
     if (pawn.needs == null || pawn.needs.mood == null || pawn.needs.mood.thoughts == null || pawn.needs.mood.thoughts.memories == null)
     {
         return;
     }
     foreach (Thought_Memory current in pawn.needs.mood.thoughts.memories.Memories)
     {
         if (current.otherPawn != null)
         {
             if (logDotgraph != null)
             {
                 string text = string.Format("{0}->{1} [label=<{2}> color=\"orange\"];", WorldPawnGC.DotgraphIdentifier(pawn), WorldPawnGC.DotgraphIdentifier(current.otherPawn), current.def);
                 if (!logDotgraphUniqueLinks.Contains(text))
                 {
                     logDotgraphUniqueLinks.Add(text);
                     logDotgraph.AppendLine(text);
                 }
             }
             if (!keptPawns.ContainsKey(current.otherPawn))
             {
                 keptPawns[current.otherPawn] = "Memory";
             }
         }
     }
 }
예제 #13
0
        static private void AddAllRelationships(WorldPawnGC __instance, Pawn pawn, Dictionary <Pawn, string> keptPawns)
        {
            if (pawn.relations == null || !pawn.relations.RelatedToAnyoneOrAnyoneRelatedToMe || !pawn.RaceProps.IsFlesh)
            {
                return;
            }
            Stack <Pawn>   stack   = null;
            HashSet <Pawn> visited = null;

            try {
                stack = SimplePool <Stack <Pawn> > .Get();

                visited = SimplePool <HashSet <Pawn> > .Get();

                stack.Push(pawn);
                visited.Add(pawn);
                while (stack.Count > 0)
                {
                    Pawn p = stack.Pop();
                    foreach (Pawn otherPawn in p.relations.DirectRelations.Select(r => r.otherPawn).Concat <Pawn>(
                                 (HashSet <Pawn>) typeof(Pawn_RelationsTracker).GetField("pawnsWithDirectRelationsWithMe",
                                                                                         BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(p.relations)))
                    {
                        if (!visited.Contains(otherPawn))
                        {
                            if (otherPawn.RaceProps.IsFlesh)
                            {
                                PawnRelationDef relation = AllAllowedRelationDefs.FirstOrDefault(def => def.Worker.InRelation(pawn, otherPawn));
                                if (relation != default(PawnRelationDef))
                                {
                                    if (logDotgraph != null)
                                    {
                                        string text = string.Format("{0}->{1} [label=<{2}> color=\"purple\"];", WorldPawnGC.DotgraphIdentifier(pawn),
                                                                    WorldPawnGC.DotgraphIdentifier(otherPawn), relation.ToString());
                                        if (!logDotgraphUniqueLinks.Contains(text))
                                        {
                                            logDotgraphUniqueLinks.Add(text);
                                            logDotgraph.AppendLine(text);
                                        }
                                    }
                                    if (!keptPawns.ContainsKey(otherPawn))
                                    {
                                        keptPawns[otherPawn] = "Relationship";
                                        //Not correct to have it here if the pairing between two pawns is filtered but if we allow all relations this is correct.
                                        //The pursuit of animal family trees if a human is bonded with an animal is pointless.
                                        if (relation != PawnRelationDefOf.Bond)
                                        {
                                            stack.Push(otherPawn);
                                        }
                                    }
                                }
                            }
                            visited.Add(otherPawn);
                        }
                    }
                }
            } finally {
                if (stack != null)
                {
                    stack.Clear();
                    stack.TrimExcess();
                    SimplePool <Stack <Pawn> > .Return(stack);
                }
                if (visited != null)
                {
                    visited.Clear();
                    stack.TrimExcess();
                    SimplePool <HashSet <Pawn> > .Return(visited);
                }
            }
        }