Пример #1
0
        // Replaces "CheckTile" in modded TileHandler method.
        private bool TryGetTile(patch_TerrainType set, VirtualMap <char> mapData, int x, int y, Rectangle forceFill, char forceID, Behaviour behaviour, out char tile)
        {
            tile = '0';
            if (forceFill.Contains(x, y))
            {
                tile = forceID;
                return(true);
            }

            if (mapData == null)   // Not entirely sure how this should be handled best.
            {
                return(behaviour.EdgesExtend);
            }

            if (x >= 0 && y >= 0 && x < mapData.Columns && y < mapData.Rows)
            {
                tile = mapData[x, y];
                return(!IsEmpty(tile) && !set.Ignore(tile));
            }

            if (!behaviour.EdgesExtend)
            {
                return(false);
            }

            tile = mapData[Calc.Clamp(x, 0, mapData.Columns - 1), Calc.Clamp(y, 0, mapData.Rows - 1)];
            return(!IsEmpty(tile) && !set.Ignore(tile));
        }
Пример #2
0
        private void ReadInto(patch_TerrainType data, Tileset tileset, XmlElement xml)
        {
            orig_ReadInto(data, tileset, xml);

            if (xml.HasAttr("sound"))
            {
                SurfaceIndex.TileToIndex[xml.AttrChar("id")] = xml.AttrInt("sound");
            }
        }
Пример #3
0
        private int GetDepth(patch_TerrainType terrainType, VirtualMap <char> mapData, int x, int y, Rectangle forceFill, Behaviour behaviour, int depth)
        {
            int searchX = depth + terrainType.ScanWidth / 2;
            int searchY = depth + terrainType.ScanHeight / 2;

            if (CheckCross(terrainType, mapData, x, y, forceFill, behaviour, searchX, searchY) && depth < terrainType.CustomFills.Count)
            {
                return(GetDepth(terrainType, mapData, x, y, forceFill, behaviour, ++depth));
            }

            return(depth);
        }
Пример #4
0
 private bool CheckCross(patch_TerrainType terrainType, VirtualMap <char> mapData, int x, int y, Rectangle forceFill, Behaviour behaviour, int width, int height)
 {
     if (behaviour.PaddingIgnoreOutOfLevel)
     {
         return((CheckTile(terrainType, mapData, x - width, y, forceFill, behaviour) || !CheckForSameLevel(x, y, x - width, y)) &&
                (CheckTile(terrainType, mapData, x + width, y, forceFill, behaviour) || !CheckForSameLevel(x, y, x + width, y)) &&
                (CheckTile(terrainType, mapData, x, y - height, forceFill, behaviour) || !CheckForSameLevel(x, y, x, y - height)) &&
                (CheckTile(terrainType, mapData, x, y + height, forceFill, behaviour) || !CheckForSameLevel(x, y, x, y + height)));
     }
     else
     {
         return(CheckTile(terrainType, mapData, x - width, y, forceFill, behaviour) &&
                CheckTile(terrainType, mapData, x + width, y, forceFill, behaviour) &&
                CheckTile(terrainType, mapData, x, y - height, forceFill, behaviour) &&
                CheckTile(terrainType, mapData, x, y + height, forceFill, behaviour));
     }
 }
Пример #5
0
 private extern void orig_ReadInto(patch_TerrainType data, Tileset tileset, XmlElement xml);
Пример #6
0
        private void ReadInto(patch_TerrainType data, Tileset tileset, XmlElement xml)
        {
            if (xml.HasAttr("scanWidth"))
            {
                int scanWidth = xml.AttrInt("scanWidth");
                if (scanWidth <= 0 || scanWidth % 2 == 0)
                {
                    throw new Exception("Tileset scan width must be a positive, odd integer.");
                }

                data.ScanWidth = scanWidth;
            }
            else
            {
                data.ScanWidth = 3;
            }

            if (xml.HasAttr("scanHeight"))
            {
                int scanHeight = xml.AttrInt("scanHeight");

                if (scanHeight <= 0 || scanHeight % 2 == 0)
                {
                    throw new Exception("Tileset scan height must be a positive, odd integer.");
                }

                data.ScanHeight = scanHeight;
            }
            else
            {
                data.ScanHeight = 3;
            }

            XmlNodeList fills = xml.SelectNodes("set[starts-with(@mask, 'fill')]"); // Faster to ask for an attr on the tileset node, but this is cleaner & easier to use.

            if (fills != null && fills.Count > 0)
            {
                data.CustomFills = new List <patch_Tiles>();
                for (int i = 0; i < fills.Count; i++)
                {
                    data.CustomFills.Add(new patch_Tiles());
                }
            }

            if (data.CustomFills == null && data.ScanWidth == 3 && data.ScanHeight == 3 && !xml.HasChild("define")) // ReadIntoCustomTemplate can handle vanilla templates but meh
            {
                orig_ReadInto(data, tileset, xml);
            }
            else
            {
                Logger.Log(LogLevel.Debug, "Autotiler", $"Reading Tileset width scan height {data.ScanHeight} and scan width {data.ScanWidth}.");
                ReadIntoCustomTemplate(data, tileset, xml);
            }

            if (xml.HasAttr("sound"))
            {
                SurfaceIndex.TileToIndex[xml.AttrChar("id")] = xml.AttrInt("sound");
            }

            if (xml.HasAttr("debris"))
            {
                data.Debris = xml.Attr("debris");
            }
        }
Пример #7
0
 private extern bool CheckTile(patch_TerrainType set, VirtualMap <char> mapData, int x, int y, Rectangle forceFill, Behaviour behaviour);
Пример #8
0
        private void ReadIntoCustomTemplate(patch_TerrainType data, Tileset tileset, XmlElement xml)
        {
            foreach (XmlNode child in xml)
            {
                if (child is XmlElement node)
                {
                    if (node.Name == "set")   // Potential somewhat breaking change, although there is no reason for another name to have been used.
                    {
                        string      text = node.Attr("mask");
                        patch_Tiles tiles;
                        if (text == "center")
                        {
                            if (data.CustomFills != null)
                            {
                                Logger.Log(LogLevel.Warn, "Autotiler", "\"Center\" tiles will not be used if Custom Fills are present.");
                            }

                            tiles = data.Center;
                        }
                        else if (text == "padding")
                        {
                            if (data.CustomFills != null)
                            {
                                Logger.Log(LogLevel.Warn, "Autotiler", "\"Padding\" tiles will not be used if Custom Fills are present.");
                            }

                            tiles = data.Padded;
                        }
                        else if (text.StartsWith("fill"))
                        {
                            tiles = data.CustomFills[int.Parse(text.Substring(4))];
                        }
                        else
                        {
                            patch_Masked masked = new patch_Masked();
                            masked.Mask = new byte[data.ScanWidth * data.ScanHeight];
                            tiles       = masked.Tiles;

                            try {
                                // Allows for spacer characters like '-' in the xml
                                int i = 0;
                                foreach (char c in text)
                                {
                                    switch (c)
                                    {
                                    case '0':
                                        masked.Mask[i++] = 0;     // No tile
                                        break;

                                    case '1':
                                        masked.Mask[i++] = 1;     // Tile
                                        break;

                                    case 'x':
                                    case 'X':
                                        masked.Mask[i++] = 2;     // Any
                                        break;

                                    case 'y':
                                    case 'Y':
                                        masked.Mask[i++] = 3;     // Not this tile
                                        break;

                                    case 'z':
                                    case 'Z':
                                        break;   // Reserved

                                    default:     // Custom filters
                                        if (char.IsLetter(c))
                                        {
                                            masked.Mask[i++] = GetByteLookup(c);
                                        }
                                        break;

                                        /*
                                         * Error handling for characters that don't exist in a defined filter could be added,
                                         * but is slightly more likely to break old custom tilesets if someone has defined a mask that containes nonstandard spacers (usually '-')
                                         */
                                    }
                                }
                            } catch (IndexOutOfRangeException e) {
                                throw new IndexOutOfRangeException($"Mask size in tileset with id '{data.ID}' is greater than the size specified by scanWidth and scanHeight (defaults to 3x3).", e);
                            }
                            data.Masked.Add(masked);
                        }

                        foreach (string tile in node.Attr("tiles").Split(';'))
                        {
                            string[] subtexture = tile.Split(',');
                            int      x          = int.Parse(subtexture[0]);
                            int      y          = int.Parse(subtexture[1]);

                            try {
                                tiles.Textures.Add(tileset[x, y]);
                            } catch (IndexOutOfRangeException e) {
                                throw new IndexOutOfRangeException($"Tileset with id '{data.ID}' missing tile at ({x}, {y}).", e);
                            }
                        }

                        if (node.HasAttr("sprites"))
                        {
                            foreach (string sprites in node.Attr("sprites").Split(','))
                            {
                                tiles.OverlapSprites.Add(sprites);
                            }
                            tiles.HasOverlays = true;
                        }
                    }
                    else if (node.Name == "define")
                    {
                        byte   id     = GetByteLookup(node.AttrChar("id"));
                        string filter = node.Attr("filter");

                        if (node.AttrBool("ignore"))
                        {
                            data.blacklists[id] = filter;
                        }
                        else
                        {
                            data.whitelists[id] = filter;
                        }
                    }
                }
            }

            data.Masked.Sort((patch_Masked a, patch_Masked b) => {
                // Sorts the masks to give preference to more specific masks.
                // Order is Custom Filters -> "Not This" -> "Any" -> Everything else
                int aFilters = 0;
                int bFilters = 0;
                int aNots    = 0;
                int bNots    = 0;
                int aAnys    = 0;
                int bAnys    = 0;
                for (int i = 0; i < data.ScanWidth * data.ScanHeight; i++)
                {
                    if (a.Mask[i] >= 10)
                    {
                        aFilters++;
                    }
                    if (b.Mask[i] >= 10)
                    {
                        bFilters++;
                    }

                    if (a.Mask[i] == 3)
                    {
                        aNots++;
                    }
                    if (b.Mask[i] == 3)
                    {
                        bNots++;
                    }

                    if (a.Mask[i] == 2)
                    {
                        aAnys++;
                    }
                    if (b.Mask[i] == 2)
                    {
                        bAnys++;
                    }
                }
                if (aFilters > 0 || bFilters > 0)
                {
                    return(aFilters - bFilters);
                }

                if (aNots > 0 || bNots > 0)
                {
                    return(aNots - bNots);
                }

                return(aAnys - bAnys);
            });
        }