public static void GenerateRoomFromLayout(List <string> layoutList, CellRect roomRect, Map map, StructureLayoutDef rld, bool generateConduit = true)
        {
            bool parentFaction = map.ParentFaction != null;

            if (rld.roofGrid != null)
            {
                GenerateRoofGrid(rld.roofGrid, roomRect, map);
            }

            List <string> allSymbList = new List <string>();

            foreach (string str in layoutList)
            {
                allSymbList.AddRange(str.Split(','));
            }

            int l = 0;

            foreach (IntVec3 cell in roomRect)
            {
                if (l < allSymbList.Count && allSymbList[l] != ".")
                {
                    SymbolDef temp = DefDatabase <SymbolDef> .GetNamedSilentFail(allSymbList[l]);

                    Thing thing;
                    if (temp != null)
                    {
                        if (temp.isTerrain && temp.terrainDef != null)
                        {
                            GenerateTerrainAt(map, cell, temp.terrainDef);
                        }
                        else if (temp.pawnKindDefNS != null && CGO.factionSettlement?.shouldRuin == false)
                        {
                            if (temp.lordJob != null)
                            {
                                Lord lord = CreateNewLord(temp.lordJob, map, cell);
                                for (int i = 0; i < temp.numberToSpawn; i++)
                                {
                                    Pawn pawn = temp.spawnPartOfFaction ? PawnGenerator.GeneratePawn(temp.pawnKindDefNS, map.ParentFaction) : PawnGenerator.GeneratePawn(temp.pawnKindDefNS);
                                    if (pawn != null)
                                    {
                                        if (temp.isSlave && parentFaction)
                                        {
                                            pawn.guest.SetGuestStatus(map.ParentFaction, GuestStatus.Prisoner);
                                        }

                                        GenSpawn.Spawn(pawn, cell, map, WipeMode.FullRefund);
                                        lord.AddPawn(pawn);
                                    }
                                }
                            }
                            else
                            {
                                for (int i = 0; i < temp.numberToSpawn; i++)
                                {
                                    Pawn pawn = temp.spawnPartOfFaction ? PawnGenerator.GeneratePawn(temp.pawnKindDefNS, map.ParentFaction) : PawnGenerator.GeneratePawn(temp.pawnKindDefNS);
                                    if (pawn != null)
                                    {
                                        if (temp.isSlave && parentFaction)
                                        {
                                            pawn.guest.SetGuestStatus(map.ParentFaction, GuestStatus.Prisoner);
                                        }
                                        GenSpawn.Spawn(pawn, cell, map, WipeMode.FullRefund);
                                    }
                                }
                            }
                        }
                        else if (temp.thingDef?.category == ThingCategory.Item && cell.Walkable(map))
                        {
                            thing            = ThingMaker.MakeThing(temp.thingDef, temp.stuffDef ?? (temp.thingDef.stuffCategories?.Count > 0 ? GenStuff.RandomStuffFor(temp.thingDef) : null));
                            thing.stackCount = Mathf.Clamp(Rand.RangeInclusive(1, temp.thingDef.stackLimit), 1, 75);

                            CompQuality quality = thing.TryGetComp <CompQuality>();
                            quality?.SetQuality(QualityUtility.GenerateQualityBaseGen(), ArtGenerationContext.Outsider);

                            GenSpawn.Spawn(thing, cell, map, WipeMode.FullRefund);
                            thing.SetForbidden(true, false);
                        }
                        else if (temp.thingDef != null)
                        {
                            thing = ThingMaker.MakeThing(temp.thingDef, temp.thingDef.CostStuffCount > 0 ? (temp.stuffDef ?? temp.thingDef.defaultStuff ?? ThingDefOf.WoodLog) : null);

                            CompRefuelable refuelable = thing.TryGetComp <CompRefuelable>();
                            refuelable?.Refuel(refuelable.Props.fuelCapacity);

                            CompPowerBattery battery = thing.TryGetComp <CompPowerBattery>();
                            battery?.AddEnergy(battery.Props.storedEnergyMax);

                            if (thing is Building_CryptosleepCasket cryptosleepCasket && Rand.Value < temp.chanceToContainPawn)
                            {
                                Pawn pawn = GeneratePawnForContainer(temp, map);
                                if (!cryptosleepCasket.TryAcceptThing(pawn))
                                {
                                    pawn.Destroy();
                                }
                            }
                            else if (thing is Building_CorpseCasket corpseCasket && Rand.Value < temp.chanceToContainPawn)
                            {
                                Pawn pawn = GeneratePawnForContainer(temp, map);
                                if (!corpseCasket.TryAcceptThing(pawn))
                                {
                                    pawn.Destroy();
                                }
                            }
                            else if (thing is Building_Crate crate)
                            {
                                List <Thing> thingList = new List <Thing>();
                                if (map.ParentFaction == Faction.OfPlayer && temp.thingSetMakerDefForPlayer != null)
                                {
                                    thingList = temp.thingSetMakerDefForPlayer.root.Generate(new ThingSetMakerParams());
                                }
                                else if (temp.thingSetMakerDef != null)
                                {
                                    thingList = temp.thingSetMakerDef.root.Generate(new ThingSetMakerParams());
                                }

                                foreach (Thing t in thingList)
                                {
                                    t.stackCount = Math.Min((int)(t.stackCount * temp.crateStackMultiplier), t.def.stackLimit);
                                }

                                thingList.ForEach(t =>
                                {
                                    if (!crate.TryAcceptThing(t, false))
                                    {
                                        t.Destroy();
                                    }
                                });
                            }

                            if (thing.def.category == ThingCategory.Pawn && CGO.factionSettlement?.shouldRuin == true)
                            {
                                l++;
                                continue;
                            }
                            else if (cell.GetFirstMineable(map) is Mineable m && thing.def.designationCategory == DesignationCategoryDefOf.Security)
                            {
                                l++;
                                continue;
                            }
                            else if (thing.def.category == ThingCategory.Plant && cell.GetTerrain(map).fertility > 0.5 && cell.Walkable(map)) // If it's a plant
                            {
                                Plant plant = thing as Plant;
                                plant.Growth = temp.plantGrowth; // apply the growth
                                GenSpawn.Spawn(plant, cell, map, WipeMode.VanishOrMoveAside);
                            }
                            else if (thing.def.category == ThingCategory.Building)
                            {
                                if (!cell.GetTerrain(map).affordances.Contains(TerrainAffordanceDefOf.Heavy))
                                {
                                    if (thing.def.building.isNaturalRock)
                                    {
                                        TerrainDef t = DefDatabase <TerrainDef> .GetNamedSilentFail($"{thing.def.defName}_Rough");

                                        map.terrainGrid.SetTerrain(cell, t ?? TerrainDefOf.Soil);
                                        foreach (IntVec3 intVec3 in CellRect.CenteredOn(cell, 1))
                                        {
                                            if (!intVec3.GetTerrain(map).BuildableByPlayer)
                                            {
                                                map.terrainGrid.SetTerrain(intVec3, t ?? TerrainDefOf.Soil);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        map.terrainGrid.SetTerrain(cell, TerrainDefOf.Bridge);
                                    }
                                }

                                if (thing.def.rotatable)
                                {
                                    GenSpawn.Spawn(thing, cell, map, new Rot4(temp.rotation.AsInt), WipeMode.VanishOrMoveAside);
                                }
                                else
                                {
                                    GenSpawn.Spawn(thing, cell, map, WipeMode.VanishOrMoveAside);
                                }

                                if (parentFaction)
                                {
                                    thing.SetFactionDirect(map.ParentFaction);
                                }
                            }

                            if (generateConduit && rld.spawnConduits && !thing.def.mineable && (thing.def.passability == Traversability.Impassable || thing.def.IsDoor) && map.ParentFaction?.def.techLevel >= TechLevel.Industrial) // Add power cable under all impassable
                            {
                                Thing c = ThingMaker.MakeThing(ThingDefOf.PowerConduit);
                                if (parentFaction)
                                {
                                    c.SetFactionDirect(map.ParentFaction);
                                }
                                GenSpawn.Spawn(c, cell, map, WipeMode.FullRefund);
                            }
                            // Handle mortar and mortar pawns
                            if (thing?.def?.building?.buildingTags?.Count > 0)
                            {
                                if (thing.def.building.IsMortar && thing.def.category == ThingCategory.Building && thing.def.building.buildingTags.Contains("Artillery_MannedMortar") && thing.def.HasComp(typeof(CompMannable)) && parentFaction)
                                {
                                    // Spawn pawn
                                    Lord singlePawnLord          = LordMaker.MakeNewLord(map.ParentFaction, new LordJob_ManTurrets(), map, null);
                                    PawnGenerationRequest value  = new PawnGenerationRequest(map.ParentFaction.RandomPawnKind(), map.ParentFaction, PawnGenerationContext.NonPlayer, map.Tile, mustBeCapableOfViolence: true, inhabitant: true);
                                    ResolveParams         rpPawn = new ResolveParams
                                    {
                                        faction = map.ParentFaction,
                                        singlePawnGenerationRequest = new PawnGenerationRequest?(value),
                                        rect           = CellRect.SingleCell(thing.InteractionCell),
                                        singlePawnLord = singlePawnLord
                                    };
                                    BaseGen.symbolStack.Push("pawn", rpPawn);
                                    // Spawn shells
                                    ThingDef shellDef = TurretGunUtility.TryFindRandomShellDef(thing.def, false, true, map.ParentFaction.def.techLevel, false, 250f);
                                    if (shellDef != null)
                                    {
                                        ResolveParams rpShell = new ResolveParams
                                        {
                                            faction               = map.ParentFaction,
                                            singleThingDef        = shellDef,
                                            singleThingStackCount = Rand.RangeInclusive(8, Math.Min(12, shellDef.stackLimit))
                                        };
                                        BaseGen.symbolStack.Push("thing", rpShell);
                                    }
                                }
                            }
                        }
        public float GetEnergyStored(float currentEnergyOtherSide)
        {
            if (thisBattery.PowerNet == null)
            {
                //Logger.MessageFormat(this, "No PowerNet found.");
                reloadedEnergyCalculated = true;

                oldDuplicateEnergy = duplicateEnergy = 1.0f;
                return(0.0f);
            }

            List <CompPowerBattery> networkBatteries = this.AvailableBatteries();

            oldNetworkEnergy   = networkEnergy;
            oldDuplicateEnergy = duplicateEnergy;
            duplicateEnergy    = currentEnergyOtherSide;
            float duplicateEnergyChange = duplicateEnergy - oldDuplicateEnergy;

            networkEnergy = networkBatteries.Select(x => x.StoredEnergy).DefaultIfEmpty(0.0f).Sum();
            float networkMaxEnergy = networkBatteries.Select(x => x.Props.storedEnergyMax).DefaultIfEmpty(0.0f).Sum();

            energyGained   = networkEnergy - oldNetworkEnergy;
            energyReturned = duplicateEnergyChange;

            //Logger.MessageFormat(this, "{0}, Old duplicate energy: {1}, new duplicate energy: {2}, Duplicate energy change: {3}, network: {4}/{5}", this.parent.GetType().ToString(), oldDuplicateEnergy, duplicateEnergy, duplicateEnergyChange, networkEnergy, networkMaxEnergy);

            if (reloadedEnergyCalculated && duplicateEnergyChange != 0.0f)
            {
                float networkEnergyPlusDuplicate = networkEnergy + duplicateEnergyChange;

                // If more energy lost in duplicate battery than available in duplicated network
                if (networkEnergyPlusDuplicate < 0.0f)
                {
                    if (networkEnergy > 0.0f)
                    {
                        // Drain the whole thing
                        foreach (CompPowerBattery battery in networkBatteries)
                        {
                            battery.SetStoredEnergyPct(0.0f);
                        }

                        networkEnergy = 0.0f;

                        //Logger.MessageFormat(this, "Network drained");
                    }
                }
                // If more energy gained in duplicate battery than the network can hold
                else if (networkEnergyPlusDuplicate > networkMaxEnergy)
                {
                    if (networkEnergy < networkMaxEnergy)
                    {
                        // Max the whole thing
                        foreach (CompPowerBattery battery in networkBatteries)
                        {
                            battery.SetStoredEnergyPct(1.0f);
                        }

                        networkEnergy = networkMaxEnergy;

                        //Logger.MessageFormat(this, "Network filled");
                    }
                }
                else if (oldDuplicateEnergy > 0.0f)
                {
                    if (duplicateEnergyChange > 0.0f)
                    {
                        List <CompPowerBattery> shuffledBatteries = new List <CompPowerBattery>();
                        shuffledBatteries.AddRange(networkBatteries);
                        float totalEnergyToGive = duplicateEnergyChange;
                        int   i = 0;
                        while (totalEnergyToGive > 0.0f && i < shuffledBatteries.Count)
                        {
                            CompPowerBattery compPowerBattery = shuffledBatteries[i];
                            float            energyCanRecieve = (compPowerBattery.Props.storedEnergyMax - compPowerBattery.StoredEnergy);
                            float            energyToGive     = Mathf.Min(totalEnergyToGive, energyCanRecieve);

                            compPowerBattery.AddEnergy(energyToGive / compPowerBattery.Props.efficiency);

                            totalEnergyToGive -= energyToGive;
                            ++i;
                        }
                    }
                    else if (duplicateEnergyChange < 0.0f)
                    {
                        List <CompPowerBattery> shuffledBatteries = new List <CompPowerBattery>();
                        shuffledBatteries.AddRange(networkBatteries);
                        float totalEnergyToGive = -duplicateEnergyChange;
                        int   i = 0;
                        while (totalEnergyToGive > 0.0f && i < shuffledBatteries.Count)
                        {
                            CompPowerBattery compPowerBattery = shuffledBatteries[i];
                            float            energyCanRemove  = compPowerBattery.StoredEnergy;
                            float            energyToRemove   = Mathf.Min(totalEnergyToGive, energyCanRemove);

                            compPowerBattery.DrawPower(energyToRemove);

                            totalEnergyToGive -= energyToRemove;
                            ++i;
                        }
                    }

                    //Logger.MessageFormat(this, "Duplicate energy change: {0}, energy returned to network: {1}", energyGained, energyReturned);
                }
            }

            reloadedEnergyCalculated = true;

            // Add in any extra energy stored in the sharer
            if (currentEnergyOtherSide > networkMaxEnergy)
            {
                networkEnergy += (currentEnergyOtherSide - networkMaxEnergy);
            }

            duplicateEnergy = networkEnergy;
            return(networkEnergy);
        }