RimWorld

RimWorld

Fireflies
Null fireflies, default biomes, and other C# recommendations
While debugging for another mod, I noticed that the FireflyGroup.Tick() method is giving me endless null reference errors, so I decided to jump into the code and see what could be improved. EDIT: I through the entire thing in code brackets bec

First, the main problem and solution: the spawn method can give null fireflies, which are added to the fireflies list. By checking if GenSpawn.Spawn actually gives you a firefly, you can prevent further errors, but I went a step further (for people that already have null fireflies in a save file) and added a null check to Tick.

Why the "DespawnNow" method? Well, that's coming up.

// In FireflyGroup public void SpawnGroupAround(IntVec3 c, Map map, int groups) { var pawnKind = FFDefOf.FF_FireflyKind; int randomInRange = pawnKind.wildGroupSize.RandomInRange / groups; int radius = Mathf.CeilToInt(Mathf.Sqrt((float)pawnKind.wildGroupSize.max)); for (int i = 0; i < randomInRange; i++) { IntVec3 loc2 = CellFinder.RandomClosewalkCellNear(c, map, radius, null); var ff = (Firefly) GenSpawn.Spawn(PawnGenerator.GeneratePawn(pawnKind, null), loc2, map, WipeMode.Vanish); if (ff != null) fireflies.Add(ff); } } public void Tick() { if (!IsDisappearing) return; if (Find.TickManager.TicksGame % FireflySettingsDef.Def.despawnInterval == 0) { var ff = fireflies.RandomElement(); if (ff != null && ff.Spawned) { ff.DeSpawn(); } fireflies.Remove(ff); } } public void DespawnGroupNow() { if (!ShouldBeGone) { for (int i = 0; i < fireflies.Count; i++) { fireflies?.DeSpawn();
}
fireflies.Clear();
}
}[/code]
Last edited by ハグ / Ian_Suffix; 7 Oct, 2021 @ 10:35pm
< >
Showing 1-3 of 3 comments
You can relieve the map of a very small tick burden by adding this method to the MapComponent, which allows it to excuse itself if it will never spawn any fireflies in this biome, which could be any unknown mod biome or if the group count has been decreased for places they are unlikely to be (tundra, ice, etc). This uses DespawnGroupNow to help potentially bugged saves.

// In MapComp_Fireflies public override void FinalizeInit() { // Don't bother ticking a component that does nothing if (Settings.MaxGroupCount(map.Biome) <= 0) { // Safety measure for between-version folks curGroup?.DespawnGroupNow(); map.components.Remove(this); } }
Finally, the last problem I encountered: unknown biomes giving null errors. I fixed this by forgoing the use of the .Find method and lazily initializing a dictionary from the maxGroupsByBiome list.

public class FireflySettingsDef : Def { public List<AnimalBiomeRecord> maxGroupsByBiome; public IntRange spawnHours = new IntRange(18, 22); public IntRange despawnHours = new IntRange(6, 10); public int despawnInterval = 250; public static FireflySettingsDef Def => FFDefOf.FireflySettings; protected Dictionary<string, int> _maxGroupsByBiomeName = new Dictionary<string, int>(); public IReadOnlyDictionary<string, int> MaxGroupsByBiomeName { get { if (_maxGroupsByBiomeName.NullOrEmpty()) _maxGroupsByBiomeName = maxGroupsByBiome.ToDictionary(abr => abr.biome.defName, abr => UnityEngine.Mathf.FloorToInt(abr.commonality)); return _maxGroupsByBiomeName as IReadOnlyDictionary<string, int>; } } public int MaxGroupCount(BiomeDef forBiome) { if (maxGroupsByBiome.NullOrEmpty() || !MaxGroupsByBiomeName.ContainsKey(forBiome.defName)) return 0; return MaxGroupsByBiomeName[forBiome.defName]; } }
:steamthis: Issue resolved.
< >
Showing 1-3 of 3 comments
Per page: 1530 50