Exemplo n.º 1
0
        public void RemoveIncompatibleItems()
        {
            //Each item should be checked if it can be placed or not. This should help preventing situations when simulated scavenging removes things which anyway won't be placed.
            //For each placed item it's cost should be calculated
            if (blueprint.roofMap == null)
            {
                Debug.Log(Debug.BlueprintTransfer, "Trying to process blueprint with empty roof map");
            }
            if (map == null)
            {
                Debug.Log(Debug.BlueprintTransfer, "Trying to process blueprint but map is still null");
            }

            try {
                int totalItems   = 0;
                int removedItems = 0;
                for (int x = 0; x < blueprint.width; x++)
                {
                    for (int z = 0; z < blueprint.height; z++)
                    {
                        Debug.Extra(Debug.BlueprintTransfer, "Starting cell {0} {1}...", x, z);
                        if (blueprint.itemsMap[x, z] == null)
                        {
                            blueprint.itemsMap[x, z] = new List <ItemTile>();
                        }                                                                                         //to make thngs easier add empty list to every cell

                        IntVec3 mapLocation = new IntVec3(x + mapOriginX, 0, z + mapOriginZ);
                        if (!mapLocation.InBounds(map))
                        {
                            continue;
                        }

                        List <ItemTile> items      = blueprint.itemsMap[x, z];
                        TerrainTile     terrain    = blueprint.terrainMap[x, z];
                        TerrainDef      terrainDef = null;

                        if (terrain != null)
                        {
                            terrainDef = DefDatabase <TerrainDef> .GetNamed(terrain.defName, false);

                            if (terrainDef == null)
                            {
                                blueprint.terrainMap[x, z] = null; //no terrain def means terrain can't be generated.
                                terrain = null;
                            }
                        }

                        TerrainDef existingTerrain = map.terrainGrid?.TerrainAt(mapLocation);
                        if (existingTerrain != null && terrainDef != null &&
                            existingTerrain.affordances != null &&
                            terrainDef.terrainAffordanceNeeded != null && !existingTerrain.affordances.Contains(terrainDef.terrainAffordanceNeeded))
                        {
                            terrainDef = null;
                            blueprint.terrainMap[x, z] = null;  //erase terrain if underlying terrain can't support it.
                            blueprint.roofMap[x, z]    = false; //removing roof as well just in case
                        }

                        Debug.Extra(Debug.BlueprintTransfer, "Preprocessed cell {0} {1}, moving to items...", x, z);
                        List <ItemTile> itemsToRemove = new List <ItemTile>();
                        foreach (ItemTile item in items)
                        {
                            totalItems++;

                            ThingDef thingDef = DefDatabase <ThingDef> .GetNamed(item.defName, false);

                            if (thingDef == null)
                            {
                                itemsToRemove.Add(item);
                                continue;
                            }

                            Debug.Extra(Debug.BlueprintTransfer, "Making thorough check for thing {0}", item.defName);
                            if (!options.overwritesEverything && thingDef.terrainAffordanceNeeded != null)
                            {
                                if (thingDef.EverTransmitsPower && options.shouldKeepDefencesAndPower)
                                {
                                    continue;                                                                    //ignore affordances for power transmitters if we need to keep defence systems
                                }
                                if (terrainDef != null && terrainDef.terrainAffordanceNeeded != null && existingTerrain.affordances.Contains(terrainDef.terrainAffordanceNeeded))
                                {
                                    if (!terrainDef.affordances.Contains(thingDef.terrainAffordanceNeeded))   //if new terrain can be placed over existing terrain, checking if an item can be placed over a new terrain
                                    {
                                        itemsToRemove.Add(item);
                                        blueprint.roofMap[x, z] = false;
                                    }
                                }
                                else
                                {
                                    if (!(existingTerrain.affordances?.Contains(thingDef.terrainAffordanceNeeded) ?? true))  //otherwise checking if the item can be placed over the existing terrain.
                                    {
                                        itemsToRemove.Add(item);
                                        blueprint.roofMap[x, z] = false;
                                    }
                                }
                            }
                        }

                        foreach (ItemTile item in itemsToRemove)
                        {
                            if (item.isWall || item.isDoor)
                            {
                                blueprint.RemoveWall(item.location.x, item.location.z);
                            }

                            items.Remove(item);
                            removedItems++;
                        }
                    }
                }


                Debug.Extra(Debug.BlueprintTransfer, "Finished check, recalculating stats");
                blueprint.UpdateBlueprintStats(true);
                Debug.Log(Debug.BlueprintTransfer, "Blueprint transfer utility did remove {0}/{1} incompatible items. New cost: {2}", removedItems, totalItems, blueprint.totalCost);
            } catch (Exception e) {
                Debug.Error(Debug.BlueprintTransfer, "Exception while trying to cleanup blueprint details. This should not normally happen, so please report this case: {0}", e.ToString());
            }
        }
Exemplo n.º 2
0
        private void LoadBlueprint()
        {
            Debug.Log(Debug.BlueprintTransfer, "Loading blueprint at path {0}", snapshotName);

            string deflatedName = snapshotName;

            if (Path.GetExtension(snapshotName).Equals(".bp"))
            {
                deflatedName = snapshotName + ".xml";
                if (!File.Exists(deflatedName))
                {
                    string data = Compressor.UnzipFile(snapshotName);
                    File.WriteAllText(deflatedName, data);
                }
            }

            XmlDocument snapshot = new XmlDocument();

            snapshot.Load(deflatedName);

            XmlNodeList elemList         = snapshot.GetElementsByTagName("cell");
            int         blueprintWidth   = int.Parse(snapshot.FirstChild.Attributes["width"].Value);
            int         blueprintHeight  = int.Parse(snapshot.FirstChild.Attributes["height"].Value);
            Version     blueprintVersion = new Version(snapshot.FirstChild?.Attributes["version"]?.Value ?? "0.0.0.0");

            blueprint = new Blueprint(blueprintWidth, blueprintHeight, blueprintVersion);

            //Snapshot year is an in-game year when snapshot was taken. Thus, all corpse ages, death times, art events and so on are in between of 5500 and [snapshotYear]
            blueprint.snapshotYear = int.Parse(snapshot.FirstChild.Attributes["inGameYear"]?.Value ?? "5600");
            //To prevent artifacts from future we need to shift all dates by some number to the past by _at_least_ (snaphotYear - 5500) years


            int itemNodes    = 0;
            int terrainNodes = 0;

            foreach (XmlNode cellNode in elemList)
            {
                int x = int.Parse(cellNode.Attributes["x"].Value);
                int z = int.Parse(cellNode.Attributes["z"].Value);
                blueprint.itemsMap[x, z] = new List <ItemTile>();

                foreach (XmlNode cellElement in cellNode.ChildNodes)
                {
                    try {
                        if (cellElement.Name.Equals("terrain"))
                        {
                            terrainNodes++;
                            TerrainTile terrain = new TerrainTile(cellElement);
                            terrain.location           = new IntVec3(x, 0, z);
                            blueprint.terrainMap[x, z] = terrain;
                        }
                        else if (cellElement.Name.Equals("item"))
                        {
                            itemNodes++;
                            ItemTile tile = new ItemTile(cellElement);

                            //replace all collapsed rocks with walls
                            if (tile.defName == ThingDefOf.CollapsedRocks.defName)
                            {
                                tile = ItemTile.WallReplacementItemTile(tile.location);
                            }

                            if (tile.defName == ThingDefOf.MinifiedThing.defName && (tile.innerItems?.Count() ?? 0) == 0)
                            {
                                continue; //skip minified things with no inner items
                            }

                            //Trying to load corresponding definition to check if the object is accessible
                            ThingDef thingDef = DefDatabase <ThingDef> .GetNamed(tile.defName, false);

                            if (thingDef != null)
                            {
                                if (thingDef.fillPercent == 1.0f || tile.isWall || tile.isDoor)
                                {
                                    blueprint.wallMap[x, z] = -1;                                 //place wall
                                }
                                tile.stackCount = Math.Min(thingDef.stackLimit, tile.stackCount); //limit stack to max stack size to correctly calculate weight and cost later
                                tile.location   = new IntVec3(x, 0, z);
                                blueprint.itemsMap[x, z].Add(tile);                               //save item if it's def is valid.
                            }
                            else
                            {
                                if (tile.isDoor)   //replacing unavailable door with abstract default door
                                {
                                    tile.defName  = ThingDefOf.Door.defName;
                                    tile.location = new IntVec3(x, 0, z);
                                    blueprint.itemsMap[x, z].Add(tile);                          //replacement door is ok
                                }
                                else if (tile.isWall || tile.defName.ToLower().Contains("wall")) //replacing unavailable impassable 100% filling block (which was likely a wall) with a wall
                                {
                                    tile.defName  = ThingDefOf.Wall.defName;
                                    tile.location = new IntVec3(x, 0, z);
                                    blueprint.itemsMap[x, z].Add(tile); //now it's a wall
                                }
                                else if (tile.defName == "Corpse")
                                {
                                    tile.location = new IntVec3(x, 0, z);
                                    blueprint.itemsMap[x, z].Add(tile); // corpse is ok
                                }
                            }
                        }
                        else if (cellElement.Name.Equals("roof"))
                        {
                            blueprint.roofMap[x, z] = true;
                        }
                    } catch (Exception) {
                        //ignore invalid or unloadable cells
                    }
                }
            }
        }
        public void RemoveIncompatibleItems()
        {
            //Each item should be checked if it can be placed or not. This should help preventing situations when simulated scavenging removes things which anyway won't be placed.
            //For each placed item it's cost should be calculated
            int totalItems   = 0;
            int removedItems = 0;

            for (int x = 0; x < blueprint.width; x++)
            {
                for (int z = 0; z < blueprint.height; z++)
                {
                    if (blueprint.itemsMap[x, z] == null)
                    {
                        blueprint.itemsMap[x, z] = new List <ItemTile>();
                    }                                                                                         //to make thngs easier add empty list to every cell

                    IntVec3 mapLocation = new IntVec3(x + mapOriginX, 0, z + mapOriginZ);
                    if (!mapLocation.InBounds(map))
                    {
                        continue;
                    }

                    List <ItemTile> items      = blueprint.itemsMap[x, z];
                    TerrainTile     terrain    = blueprint.terrainMap[x, z];
                    TerrainDef      terrainDef = null;

                    if (terrain != null)
                    {
                        terrainDef = DefDatabase <TerrainDef> .GetNamed(terrain.defName, false);

                        if (terrainDef == null)
                        {
                            blueprint.terrainMap[x, z] = null; //no terrain def means terrain can't be generated.
                            terrain = null;
                        }
                    }

                    TerrainDef existingTerrain = map.terrainGrid.TerrainAt(mapLocation);
                    if (terrainDef != null && terrainDef.terrainAffordanceNeeded != null && !existingTerrain.affordances.Contains(terrainDef.terrainAffordanceNeeded))
                    {
                        terrainDef = null;
                        blueprint.terrainMap[x, z] = null;  //erase terrain if underlying terrain can't support it.
                        blueprint.roofMap[x, z]    = false; //removing roof as well just in case
                    }

                    List <ItemTile> itemsToRemove = new List <ItemTile>();
                    foreach (ItemTile item in items)
                    {
                        totalItems++;

                        ThingDef thingDef = DefDatabase <ThingDef> .GetNamed(item.defName, false);

                        if (thingDef == null)
                        {
                            itemsToRemove.Add(item);
                            continue;
                        }

                        if (!options.overwritesEverything && thingDef.terrainAffordanceNeeded != null)
                        {
                            if (thingDef.EverTransmitsPower && options.shouldKeepDefencesAndPower)
                            {
                                continue;                                                                    //ignore affordances for power transmitters if we need to keep defence systems
                            }
                            if (terrainDef != null && terrainDef.terrainAffordanceNeeded != null && existingTerrain.affordances.Contains(terrainDef.terrainAffordanceNeeded))
                            {
                                if (!terrainDef.affordances.Contains(thingDef.terrainAffordanceNeeded))   //if new terrain can be placed over existing terrain, checking if an item can be placed over a new terrain
                                {
                                    itemsToRemove.Add(item);
                                    blueprint.roofMap[x, z] = false;
                                }
                            }
                            else
                            {
                                if (!existingTerrain.affordances.Contains(thingDef.terrainAffordanceNeeded))  //otherwise checking if the item can be placed over the existing terrain.
                                {
                                    itemsToRemove.Add(item);
                                    blueprint.roofMap[x, z] = false;
                                }
                            }
                        }
                    }

                    foreach (ItemTile item in itemsToRemove)
                    {
                        if (item.isWall || item.isDoor)
                        {
                            blueprint.RemoveWall(item.location.x, item.location.z);
                        }

                        items.Remove(item);
                        removedItems++;
                    }
                }
            }

            blueprint.UpdateBlueprintStats(true);
            //Debug.Message("Blueprint transfer utility did remove {0}/{1} incompatible items. New cost: {2}", removedItems, totalItems, blueprint.totalCost);
        }