static public void PostAffixCleanup(this CompLootAffixableThing comp, bool fixLabel = true)
        {
            ThingWithComps thing = comp.parent;

            comp.ClearAffixCaches();

            if (fixLabel)
            {
                comp.affixRules.Clear();
                comp.fullStuffLabel = null;
                string name = thing.LabelNoCount;
                name = comp.TransformLabel(name);
            }

            thing.def.SpecialDisplayStats(StatRequest.For(thing));

            foreach (LootAffixDef affix in comp.affixes)
            {
                affix.PostApplyAffix(thing);
            }
        }
        static public string GetSetFullStuffLabel(this CompLootAffixableThing comp, string label)
        {
            List <LootAffixDef> affixes    = comp.affixes;
            List <Rule>         affixRules = comp.affixRules;
            ThingWithComps      thing      = comp.parent;

            // Make sure we're not saving color tag information
            label = label.StripTags();

            // Short-circuit: No affixes
            if (comp.AffixCount == 0)
            {
                return(label);
            }

            // Short-circuit: Already calculated the full label and no replacement required
            string stuffLabel = GenLabel.ThingLabel(thing.def, thing.Stuff, 1).StripTags();

            if (comp.fullStuffLabel != null && stuffLabel == label)
            {
                return(comp.fullStuffLabel);
            }

            // Short-circuit: Still have the calculated full label
            string preExtra  = "";
            string postExtra = "";
            int    pos       = label.IndexOf(stuffLabel);

            if (pos >= 0)
            {
                preExtra  = label.Substring(0, pos);
                postExtra = label.Substring(pos + stuffLabel.Length);
            }

            if (comp.fullStuffLabel != null)
            {
                return(preExtra + comp.fullStuffLabel + postExtra);
            }

            // Need the calculate the label then...
            var namerDef = DefDatabase <LootAffixNamerRulePackDef> .GetNamed("RimLoot_LootAffixNamer");

            GrammarRequest request = new GrammarRequest();

            request.Includes.Add(namerDef);

            // Word class counter set-up
            Dictionary <string, int> maxWordClasses = namerDef.maxWordClasses;
            Dictionary <string, int> curWordClasses = new Dictionary <string, int> ();

            for (int i = 0; i < 5; i++)
            {
                curWordClasses = maxWordClasses.ToDictionary(k => k.Key, v => 0);    // shallow clone to k=0

                // Add in the affixes
                foreach (LootAffixDef affix in affixes)
                {
                    foreach (Rule rule in affix.PickAffixRulesForLabeling(curWordClasses, maxWordClasses))
                    {
                        if (rule.keyword.StartsWith("AFFIX_"))
                        {
                            comp.affixRules.Add(rule);
                        }
                        request.Rules.Add(rule);
                        if (rule.keyword.StartsWith("AFFIXPROP_"))
                        {
                            request.Constants.Add(rule.keyword, rule.Generate());
                        }
                    }
                }

                // Double-check we didn't hit one of those disallowed combinations
                if (namerDef.IsWordClassComboAllowed(affixRules))
                {
                    break;
                }
                else
                {
                    affixRules.Clear();
                    continue;
                }
            }

            if (affixRules.Count != comp.AffixCount)
            {
                Log.Error("Chosen affix words for " + thing + " don't match the number of affixes:\n" + string.Join(
                              "\nvs.\n",
                              string.Join(" | ", affixRules),
                              string.Join(", ", affixes)
                              ));
            }

            // Add a few types of labels for maximum language flexibility
            request.Rules.Add(new Rule_String("STUFF_label", thing.Stuff != null ? thing.Stuff.LabelAsStuff : ""));
            request.Rules.Add(new Rule_String("THING_defLabel", thing.def.label));
            request.Rules.Add(new Rule_String("THING_stuffLabel", stuffLabel));

            string rootKeyword = "r_affix" + comp.AffixCount;

            comp.fullStuffLabel = NameGenerator.GenerateName(request, null, false, rootKeyword, rootKeyword);

            // It's possible we might end up hitting this later than we expected, and run into affixes/word
            // desyncs, so clear the cache, just in case.
            comp.ClearAffixCaches();

            return(preExtra + comp.fullStuffLabel + postExtra);
        }