public static Color GetTileColor(Tile tile, Color background, bool showWall = true, bool showTile = true, bool showLiquid = true, bool showWire = true)
        {
            var c = new Color(0, 0, 0, 0);

            if (tile.Wall > 0 && showWall)
                if (World.WallProperties.Count > tile.Wall)
                    c = c.AlphaBlend(World.WallProperties[tile.Wall].Color);
                else
                    c = c.AlphaBlend(Color.Magenta); // Add out-of-range colors
            else
                c = background;

            if (tile.IsActive && showTile)
            {
                if (World.TileProperties.Count > tile.Type)
                    c = c.AlphaBlend(World.TileProperties[tile.Type].Color);
                else
                    c = c.AlphaBlend(Color.Magenta); // Add out-of-range colors
            }

            if (tile.Liquid > 0 && showLiquid)
                c = c.AlphaBlend(tile.IsLava ? World.GlobalColors["Lava"] : World.GlobalColors["Water"]);

            if (tile.HasWire && showWire)
                c = c.AlphaBlend(World.GlobalColors["Wire"]);

            return c;
        }
        public static int SaveTiles(Tile[,] tiles, int maxX, int maxY, BinaryWriter bw)
        {
            for (int x = 0; x < maxX; x++)
            {
                OnProgressChanged(null, new ProgressChangedEventArgs(x.ProgressPercentage(maxX), "Saving Tiles..."));


                for (int y = 0; y < maxY; y++)
                {
                    Tile tile = tiles[x, y];

                    int dataIndex;
                    int headerIndex;

                    byte[] tileData = SerializeTileData(tile, out dataIndex, out headerIndex);

                    // rle compression
                    byte header1 = tileData[headerIndex];

                    short rle = 0;
                    int nextY = y + 1;
                    int remainingY = maxY - y - 1;
                    while (remainingY > 0 && tile.Equals(tiles[x, nextY]))
                    {
                        rle = (short)(rle + 1);
                        remainingY--;
                        nextY++;
                    }

                    y = y + rle;

                    if (rle > 0)
                    {
                        tileData[dataIndex++] = (byte)(rle & 255);

                        if (rle <= 255)
                        {
                            // set bit[6] of header1 for byte size rle
                            header1 = (byte)(header1 | 64);
                        }
                        else
                        {
                            // set bit[7] of header1 for int16 size rle
                            header1 = (byte)(header1 | 128);

                            // grab the upper half of the int16 and stick it in tiledata
                            tileData[dataIndex++] = (byte)((rle & 65280) >> 8);
                        }
                    }

                    tileData[headerIndex] = header1;
                    // end rle compression

                    bw.Write(tileData, headerIndex, dataIndex - headerIndex);
                }
            }


            return (int)bw.BaseStream.Position;
        }
        private bool CheckTileMatch(ref Tile originTile, ref Tile nextTile)
        {
            switch (_wvm.TilePicker.PaintMode)
            {
                case PaintMode.TileAndWall:
                    if ((originTile.Type != nextTile.Type || originTile.IsActive != nextTile.IsActive) && _wvm.TilePicker.TileStyleActive)
                        return false;
                    if (originTile.Wall != nextTile.Wall && _wvm.TilePicker.WallStyleActive)
                        return false;
                    if (originTile.BrickStyle != nextTile.BrickStyle && _wvm.TilePicker.BrickStyleActive)
                        return false;
                    if (_wvm.TilePicker.TilePaintActive && (originTile.Type != nextTile.Type || originTile.IsActive != nextTile.IsActive))
                        return false;
                    if (_wvm.TilePicker.WallPaintActive && (originTile.Wall != nextTile.Wall || (originTile.IsActive && World.TileProperties[originTile.Type].IsSolid) ||
                        (nextTile.IsActive && World.TileProperties[nextTile.Type].IsSolid)))
                        return false;
                    if (_wvm.TilePicker.ExtrasActive)
                        return false;
                    break;
                case PaintMode.Wire:
                    return false;
                case PaintMode.Liquid:
                    if ((originTile.LiquidAmount > 0 != nextTile.LiquidAmount > 0) ||
                        originTile.LiquidType != nextTile.LiquidType ||
                        (originTile.IsActive && World.TileProperties[originTile.Type].IsSolid) ||
                        (nextTile.IsActive && World.TileProperties[nextTile.Type].IsSolid))
                        return false;
                    break;
            }

            return true;
        }
        public static void AppendTileFlagsFromByte(ref Tile tile, byte flags)
        {
            if ((flags & (byte)TileFlags.IsActive) == (byte)TileFlags.IsActive)
                tile.IsActive = true;

            if ((flags & (byte)TileFlags.IsLava) == (byte)TileFlags.IsLava)
                tile.IsLava = true;

            if ((flags & (byte)TileFlags.HasWire) == (byte)TileFlags.HasWire)
                tile.HasWire = true;

            if ((flags & (byte)TileFlags.IsHoney) == (byte)TileFlags.IsHoney)
                tile.IsHoney = true;

            if ((flags & (byte)TileFlags.HasWire2) == (byte)TileFlags.HasWire2)
                tile.HasWire2 = true;

            if ((flags & (byte)TileFlags.HasWire3) == (byte)TileFlags.HasWire3)
                tile.HasWire3 = true;

            if ((flags & (byte)TileFlags.Actuator) == (byte)TileFlags.Actuator)
                tile.Actuator = true;

            if ((flags & (byte)TileFlags.InActive) == (byte)TileFlags.InActive)
                tile.InActive = true;
        }
Beispiel #5
0
        public static Color GetTileColor(Tile tile, Color background, bool showWall = true, bool showTile = true, bool showLiquid = true, bool showRedWire = true, bool showBlueWire = true, bool showGreenWire = true, bool showYellowWire = true)
        {
            var c = new Color(0, 0, 0, 0);

            if (tile.Wall > 0 && showWall)
            {
                if (tile.WallColor > 0 && (!showTile || tile.TileColor == 0))
                    c = c.AlphaBlend(World.PaintProperties[tile.WallColor].Color);
                else if (World.WallProperties.Count > tile.Wall)
                {
                    if (World.WallProperties[tile.Wall].Color.A != 0)
                        c = c.AlphaBlend(World.WallProperties[tile.Wall].Color);
                    else
                        c = background;
                }
                else
                    c = c.AlphaBlend(Color.Magenta); // Add out-of-range colors
            }
            else
                c = background;

            if (tile.IsActive && showTile)
            {
                if (tile.TileColor > 0)
                    c = c.AlphaBlend(World.PaintProperties[tile.TileColor].Color);
                else if (World.TileProperties.Count > tile.Type)
                    c = c.AlphaBlend(World.TileProperties[tile.Type].Color);
                else
                    c = c.AlphaBlend(Color.Magenta); // Add out-of-range colors
            }

            if (tile.LiquidAmount > 0 && showLiquid)
            {
                if (tile.LiquidType == LiquidType.Lava) c = c.AlphaBlend(World.GlobalColors["Lava"]);
                else if (tile.LiquidType == LiquidType.Honey) c = c.AlphaBlend(World.GlobalColors["Honey"]);
                else c = c.AlphaBlend(World.GlobalColors["Water"]);
            }

            if (tile.WireRed && showRedWire)
            {
                c = c.AlphaBlend(World.GlobalColors["Wire"]);
            }
            if (tile.WireGreen && showGreenWire)
            {
                c = c.AlphaBlend(World.GlobalColors["Wire2"]);
            }
            if (tile.WireBlue && showBlueWire)
            {
                c = c.AlphaBlend(World.GlobalColors["Wire1"]);
            }
            if (tile.WireYellow && showYellowWire)
            {
                c = c.AlphaBlend(World.GlobalColors["Wire3"]);
            }

            return c;
        }
        public static void AppendTileFlagsFromByte(ref Tile tile, byte flags)
        {
            if ((flags & (byte)TileFlags.IsActive) == (byte)TileFlags.IsActive)
                tile.IsActive = true;

            if ((flags & (byte)TileFlags.IsLava) == (byte)TileFlags.IsLava)
                tile.IsLava = true;

            if ((flags & (byte)TileFlags.HasWire) == (byte)TileFlags.HasWire)
                tile.HasWire = true;
        }
        public void Add(Vector2Int32 location, Tile tile)
        {
            var undoTile = new UndoTile(location, tile);

            if (undoTile == null)
            {
                throw new Exception("Null undo?");
            }

            lock (UndoSaveLock)
            {
                UndoTiles.Add(undoTile);
                LastTile = undoTile;
            }
            if (UndoTiles.Count > FlushSize)
            {
                Flush();
            }
        }
 public void FixChand(int x, int y)
 {
     int newPosition = 0;
     int type = Tiles[x, y].Type;
     if (Tiles[x, y].IsActive)
     {
         if (type == 35)
         {
             newPosition = 1;
         }
         if (type == 36)
         {
             newPosition = 2;
         }
         if (type == 170)
         {
             newPosition = 3;
         }
         if (type == 171)
         {
             newPosition = 4;
         }
         if (type == 172)
         {
             newPosition = 5;
         }
     }
     if (newPosition > 0)
     {
         int xShift = x;
         int yShift = y;
         xShift = Tiles[x, y].U/18;
         while (xShift >= 3)
         {
             xShift = xShift - 3;
         }
         if (xShift >= 3)
         {
             xShift = xShift - 3;
         }
         xShift = x - xShift;
         yShift = yShift + Tiles[x, y].V/18*-1;
         for (int x1 = xShift; x1 < xShift + 3; x1++)
         {
             for (int y1 = yShift; y1 < yShift + 3; y1++)
             {
                 if (Tiles[x1, y1] == null)
                 {
                     Tiles[x1, y1] = new Tile();
                 }
                 if (Tiles[x1, y1].IsActive && Tiles[x1, y1].Type == type)
                 {
                     Tiles[x1, y1].Type = 34;
                     Tiles[x1, y1].V = (short) (Tiles[x1, y1].V + newPosition*54);
                 }
             }
         }
     }
 }
        /* Heathtech */
        //Pretty much overwrote this whole function.  The original part is still intact, but much more hidden
        private void DrawSprites()
        {
            Rectangle visibleBounds = GetViewingArea();
            TEditXna.Terraria.Objects.BlendRules blendRules = TEditXna.Terraria.Objects.BlendRules.Instance;
            if (visibleBounds.Height * visibleBounds.Width < 25000)
            {
                //Extended the viewing space to give tiles time to cache their UV's
                for (int y = visibleBounds.Top - 1; y < visibleBounds.Bottom + 2; y++)
                {
                    for (int x = visibleBounds.Left - 1; x < visibleBounds.Right + 2; x++)
                    {
                        if (x < 0 || y < 0 || x >= _wvm.CurrentWorld.TilesWide || y >= _wvm.CurrentWorld.TilesHigh)
                        {
                            continue;
                        }

                        var curtile = _wvm.CurrentWorld.Tiles[x, y];
                        var tileprop = World.TileProperties[curtile.Type];

                        //Neighbor tiles are often used when dynamically determining which UV position to render
                        int e = 0, n = 1, w = 2, s = 3, ne = 4, nw = 5, sw = 6, se = 7;
                        Tile[] neighborTile = new Tile[8];
                        neighborTile[e] = (x + 1) < _wvm.CurrentWorld.TilesWide ? _wvm.CurrentWorld.Tiles[x + 1, y] : null;
                        neighborTile[n] = (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x, y - 1] : null;
                        neighborTile[w] = (x - 1) > 0 ? _wvm.CurrentWorld.Tiles[x - 1, y] : null;
                        neighborTile[s] = (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + 1] : null;
                        neighborTile[ne] = (x + 1) < _wvm.CurrentWorld.TilesWide && (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x + 1, y - 1] : null;
                        neighborTile[nw] = (x - 1) > 0 && (y - 1) > 0 ? _wvm.CurrentWorld.Tiles[x - 1, y - 1] : null;
                        neighborTile[sw] = (x - 1) > 0 && (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x - 1, y + 1] : null;
                        neighborTile[se] = (x + 1) < _wvm.CurrentWorld.TilesWide && (y + 1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + 1] : null;

                        if (_wvm.ShowWalls)
                        {
                            if (curtile.Wall > 0)
                            {
                                var wallTex = _textureDictionary.GetWall(curtile.Wall);

                                if (wallTex != null)
                                {
                                    if (curtile.uvWallCache == 0xFFFF)
                                    {
                                        int sameStyle = 0x00000000;
                                        sameStyle |= (neighborTile[e] != null && neighborTile[e].Wall == curtile.Wall) ? 0x0001 : 0x0000;
                                        sameStyle |= (neighborTile[n] != null && neighborTile[n].Wall == curtile.Wall) ? 0x0010 : 0x0000;
                                        sameStyle |= (neighborTile[w] != null && neighborTile[w].Wall == curtile.Wall) ? 0x0100 : 0x0000;
                                        sameStyle |= (neighborTile[s] != null && neighborTile[s].Wall == curtile.Wall) ? 0x1000 : 0x0000;
                                        Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, 0x00000000, 0);
                                        curtile.uvWallCache = (ushort)((uvBlend.Y << 8) + uvBlend.X);
                                    }

                                    var texsize = new Vector2Int32(32, 32);
                                    var source = new Rectangle((curtile.uvWallCache & 0x00FF) * (texsize.X + 4), (curtile.uvWallCache >> 8) * (texsize.Y + 4), texsize.X, texsize.Y);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x - 0.5) * _zoom), 1 + (int)((_scrollPosition.Y + y - 0.5) * _zoom), (int)_zoom * 2, (int)_zoom * 2);

                                    _spriteBatch.Draw(wallTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 1);
                                }
                            }
                        }
                        if (_wvm.ShowTiles)
                        {
                            if (curtile.IsActive)
                            {
                                if (tileprop.IsFramed)
                                {
                                    Rectangle source = new Rectangle(), dest = new Rectangle();
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    bool isTree = false, isMushroom = false;
                                    bool isLeft = false, isBase = false, isRight = false;
                                    if (curtile.Type == 5 && curtile.U >= 22 && curtile.V >= 198)
                                    {
                                        isTree = true;
                                        switch (curtile.U)
                                        {
                                            case 22: isBase = true; break;
                                            case 44: isLeft = true; break;
                                            case 66: isRight = true; break;
                                        }
                                        //Abuse uvTileCache to remember what type of tree it is, since potentially scanning a hundred of blocks PER tree tile sounds slow
                                        int treeType = (curtile.uvTileCache & 0x000F);

                                        if (treeType > 4) //Tree type not yet set
                                        {
                                            //Check tree type
                                            treeType = 0; //Default to normal in case no grass grows beneath the tree
                                            int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0;
                                            for (int i = 0; i < 100; i++)
                                            {
                                                Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null;
                                                bool found = true;
                                                if (checkTile != null && checkTile.IsActive)
                                                {
                                                    switch (checkTile.Type)
                                                    {
                                                        case 2: treeType = 0; break; //Normal
                                                        case 23: treeType = 1; break; //Corruption
                                                        case 60: treeType = 2; break; //Jungle
                                                        case 109: treeType = 3; break; //Hallow
                                                        case 147: treeType = 4; break; //Snow
                                                        case 199: treeType = 5; break; //Crimson
                                                        default: found = false; break;
                                                    }
                                                    if (found == true)
                                                    {
                                                        curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeType);
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        if (isBase)
                                        {
                                            tileTex = (Texture2D)_textureDictionary.GetTreeTops(treeType);
                                        }
                                        else
                                        {
                                            tileTex = (Texture2D)_textureDictionary.GetTreeBranches(treeType);
                                        }
                                    }
                                    if (curtile.Type == 72 && curtile.U >= 36)
                                    {
                                        isMushroom = true;
                                        tileTex = (Texture2D)_textureDictionary.GetShroomTop(0);
                                    }

                                    if (tileTex != null)
                                    {
                                        if (!isTree && !isMushroom)
                                        {
                                            source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            if (source.Width <= 0)
                                                source.Width = 16;
                                            if (source.Height <= 0)
                                                source.Height = 16;

                                            if (source.Bottom > tileTex.Height)
                                                source.Height -= (source.Bottom - tileTex.Height);
                                            if (source.Right > tileTex.Width)
                                                source.Width -= (source.Right - tileTex.Width);

                                            if (source.Width <= 0 || source.Height <= 0)
                                                continue;

                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            var texsize = tileprop.TextureGrid;
                                            if (texsize.X != 16 || texsize.Y != 16)
                                            {
                                                dest.Width = (int)(texsize.X * (_zoom / 16));
                                                dest.Height = (int)(texsize.Y * (_zoom / 16));

                                                var frame = (tileprop.Frames.FirstOrDefault(f => f.UV == new Vector2Short(curtile.U, curtile.V)));
                                                var frameAnchor = FrameAnchor.None;
                                                if (frame != null)
                                                    frameAnchor = frame.Anchor;
                                                switch (frameAnchor)
                                                {
                                                    case FrameAnchor.None:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Left:
                                                        //position.X += (16 - texsize.X) / 2;
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Right:
                                                        dest.X += (int)((16 - texsize.X) * _zoom / 16);
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Top:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        //position.Y += (16 - texsize.Y);
                                                        break;
                                                    case FrameAnchor.Bottom:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        dest.Y += (int)((16 - texsize.Y) * _zoom / 16);
                                                        break;
                                                }
                                            }
                                        }
                                        else if (isTree)
                                        {
                                            source = new Rectangle(0, 0, 40, 40);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            FrameAnchor frameAnchor = FrameAnchor.None;

                                            int treeType = (curtile.uvTileCache & 0x000F);
                                            if (isBase)
                                            {
                                                switch (treeType)
                                                {
                                                    case 0:
                                                    case 1:
                                                    case 4:
                                                        source.Width = 80;
                                                        source.Height = 80;
                                                        break;
                                                    case 2:
                                                        source.Width = 114;
                                                        source.Height = 96;
                                                        break;
                                                    case 3:
                                                        source.X = (x % 3) * (82 * 3);
                                                        source.Width = 80;
                                                        source.Height = 140;
                                                        break;
                                                }
                                                source.X += ((curtile.V - 198) / 22) * (source.Width + 2);
                                                frameAnchor = FrameAnchor.Bottom;
                                            }
                                            else if (isLeft)
                                            {
                                                source.X = 0;
                                                switch (treeType)
                                                {
                                                    case 3:
                                                        source.Y = (x % 3) * (42 * 3);
                                                        break;
                                                }
                                                frameAnchor = FrameAnchor.Right;
                                                source.Y += ((curtile.V - 198) / 22) * (source.Height + 2);
                                            }
                                            else if (isRight)
                                            {
                                                source.X = 42;
                                                switch (treeType)
                                                {
                                                    case 3:
                                                        source.Y = (x % 3) * (42 * 3);
                                                        break;
                                                }
                                                frameAnchor = FrameAnchor.Left;
                                                source.Y += ((curtile.V - 198) / 22) * (source.Height + 2);
                                            }
                                            dest.Width = (int)(_zoom * source.Width / 16f);
                                            dest.Height = (int)(_zoom * source.Height / 16f);
                                            switch (frameAnchor)
                                            {
                                                case FrameAnchor.None:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Left:
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Right:
                                                    dest.X += (int)((16 - source.Width) * _zoom / 16);
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Top:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Bottom:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    dest.Y += (int)((16 - source.Height) * _zoom / 16);
                                                    break;
                                            }
                                        }
                                        else if (isMushroom)
                                        {
                                            source = new Rectangle(0, 0, 60, 42);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                            source.X = (curtile.V / 18) * 62;

                                            dest.Width = (int)(_zoom * source.Width / 16f);
                                            dest.Height = (int)(_zoom * source.Height / 16f);
                                            dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                            dest.Y += (int)((16 - source.Height) * _zoom / 16);
                                        }

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                    }
                                }
                                else if (tileprop.IsPlatform)
                                {
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if (tileTex != null)
                                    {
                                        Vector2Int32 uv;
                                        if (curtile.uvTileCache == 0xFFFF)
                                        {
                                            uv = new Vector2Int32(0, 0);
                                            byte state = 0x00;
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x01 : 0x00);
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsSolid && neighborTile[w].Type != curtile.Type) ? 0x02 : 0x00);
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x04 : 0x00);
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsSolid && neighborTile[e].Type != curtile.Type) ? 0x08 : 0x00);
                                            switch (state)
                                            {
                                                case 0x00:
                                                case 0x0A:
                                                    uv.X = 5;
                                                    break;
                                                case 0x01:
                                                    uv.X = 1;
                                                    break;
                                                case 0x02:
                                                    uv.X = 6;
                                                    break;
                                                case 0x04:
                                                    uv.X = 2;
                                                    break;
                                                case 0x05:
                                                    uv.X = 0;
                                                    break;
                                                case 0x06:
                                                    uv.X = 3;
                                                    break;
                                                case 0x08:
                                                    uv.X = 7;
                                                    break;
                                                case 0x09:
                                                    uv.X = 4;
                                                    break;
                                            }
                                            uv.Y = blendRules.randomVariation.Next(3);
                                            curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X);
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                    }
                                }
                                else if (tileprop.IsCactus)
                                {

                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if ((curtile.uvTileCache & 0x00FF) >= 16)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Evil_Cactus");
                                    }
                                    else if ((curtile.uvTileCache & 0x00FF) >= 8)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Good_Cactus");
                                    }

                                    if (tileTex != null)
                                    {
                                        Vector2Int32 uv;
                                        if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false)
                                        {
                                            bool isLeft = false, isRight = false, isBase = false;

                                            //Has this cactus been base-evaluated yet?
                                            int neighborX = (neighborTile[w].uvTileCache & 0x00FF) % 8; //Why % 8? If X >= 8, use hallow, If X >= 16, use corruption
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isRight = true;
                                            }
                                            neighborX = neighborTile[e].uvTileCache & 0x00FF;
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isLeft = true;
                                            }
                                            neighborX = curtile.uvTileCache & 0x00FF;
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isBase = true;
                                            }

                                            //Evaluate Base
                                            if (isLeft == false && isRight == false && isBase == false)
                                            {
                                                int length1 = 0;
                                                int length2 = 0;
                                                while (true)
                                                {
                                                    Tile checkTile = (y + length1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + length1] : null;
                                                    if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type)
                                                    {
                                                        break;
                                                    }
                                                    length1++;
                                                }
                                                if (x + 1 < _wvm.CurrentWorld.TilesWide)
                                                {
                                                    while (true)
                                                    {
                                                        Tile checkTile = (y + length2) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + length2] : null;
                                                        if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type)
                                                        {
                                                            break;
                                                        }
                                                        length2++;
                                                    }
                                                }
                                                int baseX = 0;
                                                int baseY = length1;
                                                isBase = true;
                                                if (length2 >= length1)
                                                {
                                                    baseX = 1;
                                                    baseY = length2;
                                                    isBase = false;
                                                    isLeft = true;
                                                }
                                                for (int cy = y; cy < y + baseY; cy++)
                                                {
                                                    if (_wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache == 0xFFFF)
                                                    {
                                                        if (cy == y)
                                                        {
                                                            _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x00 << 8 + 0x00;
                                                        }
                                                        else
                                                        {
                                                            _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x01 << 8 + 0x00;
                                                        }
                                                    }
                                                }
                                            }

                                            uv = new Vector2Int32(0, 0);
                                            byte state = 0x00;
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x01 : 0x00);
                                            state |= (byte)((neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == curtile.Type) ? 0x02 : 0x00);
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x04 : 0x00);
                                            state |= (byte)((neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == curtile.Type) ? 0x08 : 0x00);
                                            //state |= (byte)((neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == curtile.Type) ? 0x10 : 0x00);
                                            //state |= (byte)((neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == curtile.Type) ? 0x20 : 0x00);
                                            state |= (byte)((neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == curtile.Type) ? 0x40 : 0x00);
                                            state |= (byte)((neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == curtile.Type) ? 0x80 : 0x00);

                                            if (isLeft)
                                            {
                                                uv.X = 3;
                                                if ((state & 0x08) != 0x00) //s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 1;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.Y = 0;
                                                    }
                                                }
                                                else //!s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 2;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.X = 6;
                                                        uv.Y = 2;
                                                    }
                                                }
                                            }
                                            if (isRight)
                                            {
                                                uv.X = 2;
                                                if ((state & 0x08) != 0x00) //s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 1;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.Y = 0;
                                                    }
                                                }
                                                else //!s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 2;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.X = 6;
                                                        uv.Y = 1;
                                                    }
                                                }
                                            }
                                            if (isBase)
                                            {
                                                if ((state & 0x02) != 0x00) //n
                                                {
                                                    uv.Y = 2;
                                                    if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se)
                                                    {
                                                        uv.X = 4;
                                                    }
                                                    else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw)
                                                    {
                                                        uv.X = 1;
                                                    }
                                                    else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se
                                                    {
                                                        uv.X = 5;
                                                    }
                                                    else
                                                    {
                                                        uv.X = 0;
                                                        uv.Y = 1;
                                                    }
                                                }
                                                else //!n
                                                {
                                                    uv.Y = 0;
                                                    if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se)
                                                    {
                                                        uv.X = 4;
                                                    }
                                                    else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw)
                                                    {
                                                        uv.X = 1;
                                                    }
                                                    else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se
                                                    {
                                                        uv.X = 5;
                                                    }
                                                    else
                                                    {
                                                        uv.X = 0;
                                                        uv.Y = 0;
                                                    }
                                                }
                                            }

                                            //Check if cactus is good or evil
                                            for (int i = 0; i < 100; i++)
                                            {
                                                int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0;
                                                Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null;
                                                if (checkTile != null && checkTile.IsActive && checkTile.Type == 112) //Corruption
                                                {
                                                    uv.X += 16;
                                                    break;
                                                }
                                                else if (checkTile != null && checkTile.IsActive && checkTile.Type == 116) //Hallow
                                                {
                                                    uv.X += 8;
                                                    break;
                                                }
                                            }
                                            curtile.hasLazyChecked = true;

                                            curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X);
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle(((curtile.uvTileCache & 0x00FF) % 8) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                    }
                                }
                                else if (tileprop.CanBlend)
                                {
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if (tileTex != null)
                                    {
                                        if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false)
                                        {
                                            int sameStyle = 0x00000000;
                                            int mergeMask = 0x00000000;
                                            int strictness = 0;
                                            if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value == -1) //Basically for cobweb
                                            {
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive) ? 0x1000 : 0x0000;
                                            }
                                            else if (tileprop.IsStone) //Stone & Gems
                                            {
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsStone) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].IsStone) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsStone) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].IsStone) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].IsStone) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].IsStone) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].IsStone) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].IsStone) ? 0x10000000 : 0x00000000;
                                            }
                                            else //Everything else
                                            {
                                                //Join to nearby tiles if their merge type is this tile's type
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].MergeWith.HasValue && World.TileProperties[neighborTile[e].Type].MergeWith.Value == curtile.Type) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].MergeWith.HasValue && World.TileProperties[neighborTile[n].Type].MergeWith.Value == curtile.Type) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].MergeWith.HasValue && World.TileProperties[neighborTile[w].Type].MergeWith.Value == curtile.Type) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].MergeWith.HasValue && World.TileProperties[neighborTile[s].Type].MergeWith.Value == curtile.Type) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].MergeWith.HasValue && World.TileProperties[neighborTile[ne].Type].MergeWith.Value == curtile.Type) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[nw].Type].MergeWith.Value == curtile.Type) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[sw].Type].MergeWith.Value == curtile.Type) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].MergeWith.HasValue && World.TileProperties[neighborTile[se].Type].MergeWith.Value == curtile.Type) ? 0x10000000 : 0x00000000;
                                                //Join if nearby tiles have the same type as this tile's type
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && curtile.Type == neighborTile[e].Type) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && curtile.Type == neighborTile[n].Type) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && curtile.Type == neighborTile[w].Type) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && curtile.Type == neighborTile[s].Type) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && curtile.Type == neighborTile[ne].Type) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && curtile.Type == neighborTile[nw].Type) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && curtile.Type == neighborTile[sw].Type) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && curtile.Type == neighborTile[se].Type) ? 0x10000000 : 0x00000000;
                                            }
                                            if (curtile.hasLazyChecked == false)
                                            {
                                                bool lazyCheckReady = true;
                                                lazyCheckReady &= (neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[e].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[n].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[w].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[s].lazyMergeId != 0xFF);
                                                if (lazyCheckReady)
                                                {
                                                    sameStyle &= 0x11111110 | ((neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? 0x00000001 : ((neighborTile[e].lazyMergeId & 0x04) >> 2));
                                                    sameStyle &= 0x11111101 | ((neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? 0x00000010 : ((neighborTile[n].lazyMergeId & 0x08) << 1));
                                                    sameStyle &= 0x11111011 | ((neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? 0x00000100 : ((neighborTile[w].lazyMergeId & 0x01) << 8));
                                                    sameStyle &= 0x11110111 | ((neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? 0x00001000 : ((neighborTile[s].lazyMergeId & 0x02) << 11));
                                                    curtile.hasLazyChecked = true;
                                                }
                                            }
                                            if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value > -1) //Merges with a specific type
                                            {
                                                mergeMask |= (neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == tileprop.MergeWith.Value) ? 0x0001 : 0x0000;
                                                mergeMask |= (neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == tileprop.MergeWith.Value) ? 0x0010 : 0x0000;
                                                mergeMask |= (neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == tileprop.MergeWith.Value) ? 0x0100 : 0x0000;
                                                mergeMask |= (neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == tileprop.MergeWith.Value) ? 0x1000 : 0x0000;
                                                mergeMask |= (neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == tileprop.MergeWith.Value) ? 0x00010000 : 0x00000000;
                                                mergeMask |= (neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == tileprop.MergeWith.Value) ? 0x00100000 : 0x00000000;
                                                mergeMask |= (neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == tileprop.MergeWith.Value) ? 0x01000000 : 0x00000000;
                                                mergeMask |= (neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == tileprop.MergeWith.Value) ? 0x10000000 : 0x00000000;
                                                strictness = 1;
                                            }
                                            if (tileprop.IsGrass)
                                            {
                                                strictness = 2;
                                            }

                                            Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, (uint)mergeMask, strictness);
                                            curtile.uvTileCache = (ushort)((uvBlend.Y << 8) + uvBlend.X);
                                            curtile.lazyMergeId = blendRules.lazyMergeValidation[uvBlend.Y, uvBlend.X];
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                    }
                                }
                            }
                        }
                        if (_wvm.ShowWires)
                        {
                            if (curtile.HasWire)
                            {
                                var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires");

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire == true) ? 0x08 : 0x00);
                                    Vector2Int32 uv = new Vector2Int32(0, 0);
                                    switch (state)
                                    {
                                        case 0x00: uv.X = 0; uv.Y = 3; break;
                                        case 0x01: uv.X = 4; uv.Y = 2; break;
                                        case 0x02: uv.X = 2; uv.Y = 2; break;
                                        case 0x03: uv.X = 2; uv.Y = 1; break;
                                        case 0x04: uv.X = 3; uv.Y = 2; break;
                                        case 0x05: uv.X = 1; uv.Y = 0; break;
                                        case 0x06: uv.X = 3; uv.Y = 1; break;
                                        case 0x07: uv.X = 0; uv.Y = 1; break;
                                        case 0x08: uv.X = 1; uv.Y = 2; break;
                                        case 0x09: uv.X = 0; uv.Y = 2; break;
                                        case 0x0A: uv.X = 0; uv.Y = 0; break;
                                        case 0x0B: uv.X = 2; uv.Y = 0; break;
                                        case 0x0C: uv.X = 4; uv.Y = 1; break;
                                        case 0x0D: uv.X = 4; uv.Y = 0; break;
                                        case 0x0E: uv.X = 3; uv.Y = 0; break;
                                        case 0x0F: uv.X = 1; uv.Y = 1; break;
                                    }
                                    source.X = uv.X * (source.Width + 2);
                                    source.Y = uv.Y * (source.Height + 2);

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                }
                            }
                            if (curtile.HasWire2)
                            {
                                var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires2");

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire2 == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire2 == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire2 == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire2 == true) ? 0x08 : 0x00);
                                    Vector2Int32 uv = new Vector2Int32(0, 0);
                                    switch (state)
                                    {
                                        case 0x00: uv.X = 0; uv.Y = 3; break;
                                        case 0x01: uv.X = 4; uv.Y = 2; break;
                                        case 0x02: uv.X = 2; uv.Y = 2; break;
                                        case 0x03: uv.X = 2; uv.Y = 1; break;
                                        case 0x04: uv.X = 3; uv.Y = 2; break;
                                        case 0x05: uv.X = 1; uv.Y = 0; break;
                                        case 0x06: uv.X = 3; uv.Y = 1; break;
                                        case 0x07: uv.X = 0; uv.Y = 1; break;
                                        case 0x08: uv.X = 1; uv.Y = 2; break;
                                        case 0x09: uv.X = 0; uv.Y = 2; break;
                                        case 0x0A: uv.X = 0; uv.Y = 0; break;
                                        case 0x0B: uv.X = 2; uv.Y = 0; break;
                                        case 0x0C: uv.X = 4; uv.Y = 1; break;
                                        case 0x0D: uv.X = 4; uv.Y = 0; break;
                                        case 0x0E: uv.X = 3; uv.Y = 0; break;
                                        case 0x0F: uv.X = 1; uv.Y = 1; break;
                                    }
                                    source.X = uv.X * (source.Width + 2);
                                    source.Y = uv.Y * (source.Height + 2);

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                }
                            }
                            if (curtile.HasWire3)
                            {
                                var tileTex = (Texture2D)_textureDictionary.GetMisc("Wires3");

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].HasWire3 == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].HasWire3 == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].HasWire3 == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].HasWire3 == true) ? 0x08 : 0x00);
                                    Vector2Int32 uv = new Vector2Int32(0, 0);
                                    switch (state)
                                    {
                                        case 0x00: uv.X = 0; uv.Y = 3; break;
                                        case 0x01: uv.X = 4; uv.Y = 2; break;
                                        case 0x02: uv.X = 2; uv.Y = 2; break;
                                        case 0x03: uv.X = 2; uv.Y = 1; break;
                                        case 0x04: uv.X = 3; uv.Y = 2; break;
                                        case 0x05: uv.X = 1; uv.Y = 0; break;
                                        case 0x06: uv.X = 3; uv.Y = 1; break;
                                        case 0x07: uv.X = 0; uv.Y = 1; break;
                                        case 0x08: uv.X = 1; uv.Y = 2; break;
                                        case 0x09: uv.X = 0; uv.Y = 2; break;
                                        case 0x0A: uv.X = 0; uv.Y = 0; break;
                                        case 0x0B: uv.X = 2; uv.Y = 0; break;
                                        case 0x0C: uv.X = 4; uv.Y = 1; break;
                                        case 0x0D: uv.X = 4; uv.Y = 0; break;
                                        case 0x0E: uv.X = 3; uv.Y = 0; break;
                                        case 0x0F: uv.X = 1; uv.Y = 1; break;
                                    }
                                    source.X = uv.X * (source.Width + 2);
                                    source.Y = uv.Y * (source.Height + 2);

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, 0);
                                }
                            }
                        }
                        if (_wvm.ShowLiquid)
                        {
                            if (curtile.Liquid > 0)
                            {
                                Texture2D tileTex = null;
                                if (curtile.IsLava)
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(1);
                                }
                                else if (curtile.IsHoney)
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(11); // Not sure if yellow Desert water, or Honey, but looks fine.
                                }
                                else
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(0);
                                }

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                    float alpha = 1f;

                                    if (curtile.IsLava == false)
                                    {
                                        alpha = 0.5f;
                                    }
                                    else
                                    {
                                        alpha = 0.85f;
                                    }

                                    if (neighborTile[n] != null && neighborTile[n].Liquid > 0)
                                    {
                                        source.Y = 8;
                                        source.Height = 8;
                                    }
                                    else
                                    {
                                        source.Height = 4 + ((int)Math.Round(curtile.Liquid * 6f / 255f)) * 2;
                                        dest.Height = (int)(source.Height * _zoom / 16f);
                                        dest.Y = 1 + (int)((_scrollPosition.Y + y) * _zoom + ((16 - source.Height) * _zoom / 16f));
                                    }

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White * alpha, 0f, default(Vector2), SpriteEffects.None, 0);
                                }
                            }
                        }
                    }
                }
            }
        }
        /* Heathtech */
        //Pretty much overwrote this whole function.  The original part is still intact, but much more hidden
        private void DrawSprites()
        {
            Rectangle visibleBounds = GetViewingArea();
            TEditXna.Terraria.Objects.BlendRules blendRules = TEditXna.Terraria.Objects.BlendRules.Instance;
            var width  = _wvm.CurrentWorld.TilesWide;
            var height = _wvm.CurrentWorld.TilesHigh;


            if (visibleBounds.Height * visibleBounds.Width < 25000)
            {
                //Extended the viewing space to give tiles time to cache their UV's
                for (int y = visibleBounds.Top - 1; y < visibleBounds.Bottom + 2; y++)
                {
                    for (int x = visibleBounds.Left - 1; x < visibleBounds.Right + 2; x++)
                    {
                        if (x < 0 || y < 0 || x >= _wvm.CurrentWorld.TilesWide || y >= _wvm.CurrentWorld.TilesHigh)
                        {
                            continue;
                        }

                        var curtile = _wvm.CurrentWorld.Tiles[x, y];
                        var tileprop = World.TileProperties[curtile.Type];

                        //Neighbor tiles are often used when dynamically determining which UV position to render
                        int e = 0, n = 1, w = 2, s = 3, ne = 4, nw = 5, sw = 6, se = 7;
                        Tile[] neighborTile = new Tile[8];
                        neighborTile[ e] = (x + 1) < width                     ? _wvm.CurrentWorld.Tiles[x + 1, y    ] : null;
                        neighborTile[ n] = (y - 1) > 0                         ? _wvm.CurrentWorld.Tiles[x    , y - 1] : null;
                        neighborTile[ w] = (x - 1) > 0                         ? _wvm.CurrentWorld.Tiles[x - 1, y    ] : null;
                        neighborTile[ s] = (y + 1) < height                    ? _wvm.CurrentWorld.Tiles[x    , y + 1] : null;
                        neighborTile[ne] = (x + 1) < width && (y - 1) > 0      ? _wvm.CurrentWorld.Tiles[x + 1, y - 1] : null;
                        neighborTile[nw] = (x - 1) > 0     && (y - 1) > 0      ? _wvm.CurrentWorld.Tiles[x - 1, y - 1] : null;
                        neighborTile[sw] = (x - 1) > 0     && (y + 1) < height ? _wvm.CurrentWorld.Tiles[x - 1, y + 1] : null;
                        neighborTile[se] = (x + 1) < width && (y + 1) < height ? _wvm.CurrentWorld.Tiles[x + 1, y + 1] : null;

                        //draw background textures
                        if (y >= 80)
                        {
                            int[,] backstyle = {
                                {66, 67, 68, 69, 128, 125, 185},
                                {70, 71, 68, 72, 128, 125, 185},
                                {73, 74, 75, 76, 134, 125, 185},
                                {77, 78, 79, 82, 134, 125, 185},
                                {83, 84, 85, 86, 137, 125, 185},
                                {83, 87, 88, 89, 137, 125, 185},
                                {121, 122, 123, 124, 140, 125, 185},
                                {153, 147, 148, 149, 150, 125, 185},
                                {146, 154, 155, 156, 157, 125, 185}
                            };
                            int hellback = _wvm.CurrentWorld.HellBackStyle;
                            int backX = 0;
                            if (x <= _wvm.CurrentWorld.CaveBackX0)
                                backX = _wvm.CurrentWorld.CaveBackStyle0;
                            else if (x > _wvm.CurrentWorld.CaveBackX0 && x <= _wvm.CurrentWorld.CaveBackX1)
                                backX = _wvm.CurrentWorld.CaveBackStyle1;
                            else if (x > _wvm.CurrentWorld.CaveBackX1 && x <= _wvm.CurrentWorld.CaveBackX2)
                                backX = _wvm.CurrentWorld.CaveBackStyle2;
                            else if (x > _wvm.CurrentWorld.CaveBackX2)
                                backX = _wvm.CurrentWorld.CaveBackStyle3;
                            var source = new Rectangle(0, 0, 16, 16);
                            var backTex = _textureDictionary.GetBackground(0);
                            if (y < _wvm.CurrentWorld.GroundLevel)
                            {
                                backTex = _textureDictionary.GetBackground(0);
                                source.Y += (y - 80) * 16;
                            }
                            else if (y == _wvm.CurrentWorld.GroundLevel)
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 0]);
                                source.X += (x % 8) * 16;
                            }
                            else if (y > _wvm.CurrentWorld.GroundLevel && y < _wvm.CurrentWorld.RockLevel)
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 1]);
                                source.X += (x % 8) * 16;
                                source.Y += ((y - 1 - (int)_wvm.CurrentWorld.GroundLevel) % 6) * 16;
                            }
                            else if (y == _wvm.CurrentWorld.RockLevel)
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 2]);
                                source.X += (x % 8) * 16;
                            }
                            else if (y > _wvm.CurrentWorld.RockLevel && y < (_wvm.CurrentWorld.TilesHigh - 327))
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 3]);
                                source.X += (x % 8) * 16;
                                source.Y += ((y - 1 - (int)_wvm.CurrentWorld.RockLevel) % 6) * 16;
                            }
                            else if (y == (_wvm.CurrentWorld.TilesHigh - 327))
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 4] + hellback);
                                source.X += (x % 8) * 16;
                            }
                            else if (y > (_wvm.CurrentWorld.TilesHigh - 327) && y < (_wvm.CurrentWorld.TilesHigh - 200))
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 5] + hellback);
                                source.X += (x % 8) * 16;
                                source.Y += ((y - 1 - (int)_wvm.CurrentWorld.TilesHigh + 327) % 18) * 16;
                            }
                            else if (y == (_wvm.CurrentWorld.TilesHigh - 200))
                            {
                                backTex = _textureDictionary.GetBackground(backstyle[backX, 6] + hellback);
                                source.X += (x % 8) * 16;
                            }
                            else
                            {
                                backTex = _textureDictionary.GetUnderworld(4);
                                source.Y += (y - (int)_wvm.CurrentWorld.TilesHigh + 200) * 16;
                            }

                            var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                            _spriteBatch.Draw(backTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileBackgroundTextures);
                        }

                        if (_wvm.ShowWalls)
                        {
                            if (curtile.Wall > 0)
                            {
                                var wallTex = _textureDictionary.GetWall(curtile.Wall);

                                if (wallTex != null)
                                {
                                    if (curtile.uvWallCache == 0xFFFF)
                                    {
                                        int sameStyle = 0x00000000;
                                        sameStyle |= (neighborTile[e] != null && neighborTile[e].Wall > 0) ? 0x0001 : 0x0000;
                                        sameStyle |= (neighborTile[n] != null && neighborTile[n].Wall > 0) ? 0x0010 : 0x0000;
                                        sameStyle |= (neighborTile[w] != null && neighborTile[w].Wall > 0) ? 0x0100 : 0x0000;
                                        sameStyle |= (neighborTile[s] != null && neighborTile[s].Wall > 0) ? 0x1000 : 0x0000;

                                        Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, 0x00000000, 0);
                                        curtile.uvWallCache = (ushort)((uvBlend.Y << 8) + uvBlend.X);
                                    }

                                    var texsize = new Vector2Int32(32, 32);
                                    var source = new Rectangle((curtile.uvWallCache & 0x00FF) * (texsize.X + 4), (curtile.uvWallCache >> 8) * (texsize.Y + 4), texsize.X, texsize.Y);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x - 0.5) * _zoom), 1 + (int)((_scrollPosition.Y + y - 0.5) * _zoom), (int)_zoom * 2, (int)_zoom * 2);

                                    _spriteBatch.Draw(wallTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileWallTextures);
                                }
                            }
                        }
                        if (_wvm.ShowTiles)
                        {
                            if (curtile.IsActive)
                            {
                                if (tileprop.IsFramed)
                                {
                                    Rectangle source = new Rectangle(), dest = new Rectangle();
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    bool isTreeSpecial = false, isMushroom = false;
                                    bool isLeft = false, isBase = false, isRight = false;
                                    if (curtile.Type == (int)TileType.Tree)
                                    {
                                        int baseX = 0;
                                        if (curtile.U == 66 && curtile.V <= 45)
                                            ++baseX;
                                        if (curtile.U == 88 && curtile.V >= 66 && curtile.V <= 110)
                                            --baseX;
                                        if (curtile.U == 22 && curtile.V >= 132 && curtile.V < 198)
                                            --baseX;
                                        if (curtile.U == 44 && curtile.V >= 132 && curtile.V < 198)
                                            ++baseX;
                                        if (curtile.U >= 22 && curtile.V >= 198)
                                        {
                                            isTreeSpecial = true;
                                            switch (curtile.U)
                                            {
                                                case 22: isBase = true; break;
                                                case 44: isLeft = true; ++baseX; break;
                                                case 66: isRight = true; --baseX; break;
                                            }
                                        }

                                        //Check tree type
                                        int treeType = -1; //Default to normal in case no grass grows beneath the tree
                                        for (int i = 0; i < 100; i++)
                                        {
                                            Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null;
                                            if (checkTile != null && checkTile.IsActive)
                                            {
                                                bool found = true;
                                                switch (checkTile.Type)
                                                {
                                                    case 2: treeType = -1; break; //Normal
                                                    case 23: treeType = 0; break; //Corruption
                                                    case 60:
                                                        if (y <= _wvm.CurrentWorld.GroundLevel)
                                                        {
                                                            treeType = 1; break; // Jungle
                                                        }
                                                        treeType = 5; break; // Underground Jungle
                                                    case 70: treeType = 6; break; // Surface Mushroom
                                                    case 109: treeType = 2; break; // Hallow
                                                    case 147: treeType = 3; break; // Snow
                                                    case 199: treeType = 4; break; // Crimson
                                                    default: found = false; break;
                                                }
                                                if (found)
                                                    break;
                                            }
                                        }
                                        if (isTreeSpecial)
                                        {
                                            int treeStyle = 0; // default branches and tops
                                            switch (treeType)
                                            {
                                                case -1:
                                                    if (x <= _wvm.CurrentWorld.TreeX0)
                                                        treeStyle = _wvm.CurrentWorld.TreeStyle0;
                                                    else if (x <= _wvm.CurrentWorld.TreeX1)
                                                        treeStyle = _wvm.CurrentWorld.TreeStyle1;
                                                    else if (x <= _wvm.CurrentWorld.TreeX2)
                                                        treeStyle = _wvm.CurrentWorld.TreeStyle2;
                                                    else
                                                        treeStyle = _wvm.CurrentWorld.TreeStyle3;
                                                    if (treeStyle == 0)
                                                    {
                                                        break;
                                                    }
                                                    if (treeStyle == 5)
                                                    {
                                                        treeStyle = 10; break;
                                                    }
                                                    treeStyle = 5 + treeStyle; break;
                                                case 0:
                                                    treeStyle = 1; break;
                                                case 1:
                                                    treeStyle = 2;
                                                    if (_wvm.CurrentWorld.BgJungle == 1)
                                                        treeStyle = 11;
                                                    break;
                                                case 2:
                                                    treeStyle = 3; break;
                                                case 3:
                                                    treeStyle = 4;
                                                    if (_wvm.CurrentWorld.BgSnow == 0)
                                                    {
                                                        treeStyle = 12;
                                                        if (x % 10 == 0)
                                                            treeStyle = 18;
                                                    }
                                                    if (_wvm.CurrentWorld.BgSnow != 2 && _wvm.CurrentWorld.BgSnow != 3 && _wvm.CurrentWorld.BgSnow != 32 && _wvm.CurrentWorld.BgSnow != 4 && _wvm.CurrentWorld.BgSnow != 42)
                                                    {
                                                        break;
                                                    }
                                                    if (_wvm.CurrentWorld.BgSnow % 2 == 0)
                                                    {
                                                        if (x < _wvm.CurrentWorld.TilesWide / 2)
                                                        {
                                                            treeStyle = 16; break;
                                                        }
                                                        treeStyle = 17; break;
                                                    }
                                                    else
                                                    {
                                                        if (x > _wvm.CurrentWorld.TilesWide / 2)
                                                        {
                                                            treeStyle = 16; break;
                                                        }
                                                        treeStyle = 17; break;
                                                    }
                                                case 4:
                                                    treeStyle = 5; break;
                                                case 5:
                                                    treeStyle = 13; break;
                                                case 6:
                                                    treeStyle = 14; break;
                                            }
                                            //Abuse uvTileCache to remember what type of tree it is, since potentially scanning a hundred of blocks PER tree tile sounds slow
                                            curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeStyle);
                                            if (isBase)
                                            {
                                                tileTex = (Texture2D)_textureDictionary.GetTreeTops(treeStyle);
                                            }
                                            else
                                            {
                                                tileTex = (Texture2D)_textureDictionary.GetTreeBranches(treeStyle);
                                            }
                                        }
                                        else
                                        {
                                            tileTex = _textureDictionary.GetTree(treeType);
                                        }
                                    }
                                    if (curtile.Type == (int)TileType.MushroomTree && curtile.U >= 36)
                                    {
                                        isMushroom = true;
                                        tileTex = (Texture2D)_textureDictionary.GetShroomTop(0);
                                    }
                                    if (curtile.Type == 323)
                                    {
                                        if (curtile.U >= 88 && curtile.U <= 132)
                                        {
                                            isTreeSpecial = true;
                                            isBase = true;
                                            tileTex = (Texture2D)_textureDictionary.GetTreeTops(15);
                                        }
                                        int treeType = 0;
                                        for (int i = 0; i < 100; i++)
                                        {
                                            Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + i] : null;
                                            if (checkTile != null && checkTile.IsActive)
                                            {
                                                bool found = true;
                                                switch (checkTile.Type)
                                                {
                                                    case 53: treeType = 0; break; //Palm
                                                    case 112: treeType = 3; break; //Ebonsand Palm
                                                    case 116: treeType = 2; break; //Pearlsand Palm
                                                    case 234: treeType = 1; break; //Crimsand Palm
                                                    default: found = false; break;
                                                }
                                                if (found)
                                                    break;
                                            }
                                        }
                                        curtile.uvTileCache = (ushort)((0x00 << 8) + 0x01 * treeType);
                                    }

                                    if (tileTex != null)
                                    {
                                        if ((curtile.Type == 128 || curtile.Type == 269) && curtile.U >= 100)
                                        {
                                            int armor = curtile.U / 100;
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            switch (curtile.V / 18)
                                            {
                                                case 0:
                                                    tileTex = (Texture2D)_textureDictionary.GetArmorHead(armor);
                                                    source = new Rectangle (2, 0, 36, 36);
                                                    dest.Width = (int)(_zoom * source.Width / 16f);
                                                    dest.Height = (int)(_zoom * source.Height / 16f);
                                                    dest.Y += (int)(((16 - source.Height - 4) / 2F) * _zoom / 16);
                                                    dest.X -= (int)((2 * _zoom / 16));
                                                    break;
                                                case 1:
                                                    if (curtile.Type == 128)
                                                        tileTex = (Texture2D)_textureDictionary.GetArmorBody(armor);
                                                    else
                                                        tileTex = (Texture2D)_textureDictionary.GetArmorFemale(armor);
                                                    source = new Rectangle (2, 0, 36, 54);
                                                    dest.Width = (int)(_zoom * source.Width / 16f);
                                                    dest.Height = (int)(_zoom * source.Height / 16f);
                                                    dest.Y += (int)(((16 - source.Height - 18) / 2F) * _zoom / 16);
                                                    dest.X -= (int)((2 * _zoom / 16));
                                                    break;
                                                case 2:
                                                    tileTex = (Texture2D)_textureDictionary.GetArmorLegs(armor);
                                                    source = new Rectangle (2, 42, 36, 12);
                                                    dest.Width = (int)(_zoom * source.Width / 16f);
                                                    dest.Height = (int)(_zoom * source.Height / 16f);
                                                    dest.Y -= (int)((2 * _zoom / 16));
                                                    dest.X -= (int)((2 * _zoom / 16));
                                                    break;
                                            }
                                            if (curtile.U % 100 < 36)
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.FlipHorizontally, LayerTileTrack);
                                            else
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                            tileTex = _textureDictionary.GetTile(curtile.Type);
                                            source = new Rectangle((curtile.U % 100), curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                        }
                                        else if (curtile.Type == 334 && curtile.U >= 5000)
                                        {
                                            if (_wvm.CurrentWorld.Tiles[x + 1, y].U >= 5000)
                                            {
                                                int weapon = (curtile.U % 5000) - 100;
                                                tileTex = (Texture2D)_textureDictionary.GetItem(weapon);
                                                int flip = curtile.U / 5000;
                                                float scale = 1f;
                                                if (tileTex.Width > 40 || tileTex.Height > 40)
                                                {
                                                    if (tileTex.Width > tileTex.Height)
                                                        scale = 40f / (float)tileTex.Width;
                                                    else
                                                        scale = 40f / (float)tileTex.Height;
                                                }
                                                scale *= World.ItemProperties[weapon].Scale;
                                                source = new Rectangle(0, 0, tileTex.Width, tileTex.Height);
                                                SpriteEffects effect = SpriteEffects.None;
                                                if (flip >= 3)
                                                {
                                                    effect = SpriteEffects.FlipHorizontally;
                                                }
                                                _spriteBatch.Draw(tileTex, new Vector2(1 + (int)((_scrollPosition.X + x + 1.5) * _zoom) , 1 + (int)((_scrollPosition.Y + y + .5) * _zoom)), source, Color.White, 0f, new Vector2((float)(tileTex.Width / 2), (float)(tileTex.Height / 2)), scale * _zoom / 16f, effect, LayerTileTrack);
                                            }
                                            source = new Rectangle(((curtile.U / 5000) - 1) * 18, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            tileTex = _textureDictionary.GetTile(curtile.Type);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                        }
                                        else if (curtile.Type == 395 && curtile.V == 0 && curtile.U % 36 == 0)
                                        {
                                            TileEntity entity = _wvm.CurrentWorld.GetTileEntityAtTile(x, y);
                                            if (entity != null)
                                            {
                                                int item = entity.NetId;
                                                if (item > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetItem(item);
                                                    float scale = 1f;
                                                    if (tileTex.Width > 20 || tileTex.Height > 20)
                                                    {
                                                        if (tileTex.Width > tileTex.Height)
                                                            scale = 20f / (float)tileTex.Width;
                                                        else
                                                            scale = 20f / (float)tileTex.Height;
                                                    }
                                                    scale *= World.ItemProperties[item].Scale;
                                                    source = new Rectangle(0, 0, tileTex.Width, tileTex.Height);
                                                    _spriteBatch.Draw(tileTex, new Vector2(1 + (int)((_scrollPosition.X + x + 1) * _zoom) , 1 + (int)((_scrollPosition.Y + y + 1) * _zoom)), source, Color.White, 0f, new Vector2((float)(tileTex.Width / 2), (float)(tileTex.Height / 2)), scale * _zoom / 16f, SpriteEffects.FlipHorizontally, LayerTileTrack);
                                                }
                                            }
                                            source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            tileTex = _textureDictionary.GetTile(curtile.Type);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                        }
                                        else if (curtile.Type == 171) // Christmas Tree
                                        {
                                            if (curtile.U >= 10)
                                            {
                                                int star = curtile.V & 7;
                                                int garland = (curtile.V >> 3) & 7;
                                                int bulb = (curtile.V >> 6) & 0xf;
                                                int light = (curtile.V >> 10) & 0xf;
                                                source = new Rectangle(0, 0, 64, 128);
                                                dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom * 4, (int)_zoom * 8);
                                                if (star > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_3");
                                                    source.X = 66 * (star - 1);
                                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                                }
                                                if (garland > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_1");
                                                    source.X = 66 * (garland - 1);
                                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                                }
                                                if (bulb > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_2");
                                                    source.X = 66 * (bulb - 1);
                                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                                }
                                                if (light > 0)
                                                {
                                                    tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_4");
                                                    source.X = 66 * (light - 1);
                                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                                }
                                                source.X = 0;
                                                tileTex = (Texture2D)_textureDictionary.GetMisc("Xmas_0");
                                            }
                                        }
                                        else if (curtile.Type == 314)
                                        {
                                            source = new Rectangle(0, 0, 16, 16);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            if (curtile.V >= 0) // Switch Track, Y is back tile if not -1
                                            {
                                                Vector2Int32 uvback = TrackUV(curtile.V);
                                                source.X = uvback.X * (source.Width + 2);
                                                source.Y = uvback.Y * (source.Height + 2);
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrackBack);
                                            }
                                            if ((curtile.U >= 2 && curtile.U <= 3) || (curtile.U >= 10 && curtile.U <= 13))
                                            { // Adding regular endcap
                                                dest.Y = 1 + (int)((_scrollPosition.Y + y - 1) * _zoom);
                                                source.X = 0;
                                                source.Y = 126;
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                            }
                                            if (curtile.U >= 24 && curtile.U <= 29)
                                            { // Adding bumper endcap
                                                dest.Y = 1 + (int)((_scrollPosition.Y + y - 1) * _zoom);
                                                source.X = 18;
                                                source.Y = 126;
                                                _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTrack);
                                            }
                                            if (curtile.U == 4 || curtile.U == 9 || curtile.U == 10 || curtile.U == 16 || curtile.U == 26 || curtile.U == 33 || curtile.U == 35 || curtile.V == 4)
                                            { // Adding angle track bottom right
                                                dest.Y = 1 + (int)((_scrollPosition.Y + y + 1) * _zoom);
                                                source.X = 0;
                                                source.Y = 108;
                                                for (int slice = 0; slice < 6; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, 12 - slice * 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y);

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTrack);
                                                }
                                            }
                                            if (curtile.U == 5 || curtile.U == 8 || curtile.U == 11 || curtile.U == 17 || curtile.U == 27 || curtile.U == 32 || curtile.U == 34 || curtile.V == 5)
                                            { // Adding angle track bottom left
                                                dest.Y =  1 + (int)((_scrollPosition.Y + y + 1) * _zoom);
                                                source.X = 18;
                                                source.Y = 108;
                                                for (int slice = 2; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 - 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y);

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTrack);
                                                }
                                            }
                                            dest.Y =  1 + (int)((_scrollPosition.Y + y) * _zoom);
                                            Vector2Int32 uv = TrackUV(curtile.U);
                                            source.X = uv.X * (source.Width + 2);
                                            source.Y = uv.Y * (source.Height + 2);

                                        }
                                        else if (isTreeSpecial)
                                        {
                                            source = new Rectangle(0, 0, 40, 40);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            FrameAnchor frameAnchor = FrameAnchor.None;

                                            int treeStyle = (curtile.uvTileCache & 0x000F);
                                            if (isBase)
                                            {
                                                source.Width = 80;
                                                source.Height = 80;
                                                if (curtile.Type == 323)
                                                {
                                                    source.Y = treeStyle * (source.Height + 2);
                                                    source.X = ((curtile.U - 88) / 22) * (source.Width + 2);
                                                    dest.X += (int)(curtile.V * _zoom / 16);
                                                }
                                                else
                                                {
                                                    switch (treeStyle)
                                                    {
                                                        case 2:
                                                        case 11:
                                                        case 13:
                                                            source.Width = 114;
                                                            source.Height = 96;
                                                            break;
                                                        case 3:
                                                            source.X = (x % 3) * (82 * 3);
                                                            source.Height = 140;
                                                            break;
                                                    }
                                                    source.X += ((curtile.V - 198) / 22) * (source.Width + 2);
                                                }
                                                frameAnchor = FrameAnchor.Bottom;
                                            }
                                            else if (isLeft)
                                            {
                                                source.X = 0;
                                                switch (treeStyle)
                                                {
                                                    case 3:
                                                        source.Y = (x % 3) * (42 * 3);
                                                        break;
                                                }
                                                frameAnchor = FrameAnchor.Right;
                                                source.Y += ((curtile.V - 198) / 22) * (source.Height + 2);
                                            }
                                            else if (isRight)
                                            {
                                                source.X = 42;
                                                switch (treeStyle)
                                                {
                                                    case 3:
                                                        source.Y = (x % 3) * (42 * 3);
                                                        break;
                                                }
                                                frameAnchor = FrameAnchor.Left;
                                                source.Y += ((curtile.V - 198) / 22) * (source.Height + 2);
                                            }
                                            dest.Width = (int)(_zoom * source.Width / 16f);
                                            dest.Height = (int)(_zoom * source.Height / 16f);
                                            switch (frameAnchor)
                                            {
                                                case FrameAnchor.None:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Left:
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Right:
                                                    dest.X += (int)((16 - source.Width) * _zoom / 16);
                                                    dest.Y += (int)(((16 - source.Height) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Top:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    break;
                                                case FrameAnchor.Bottom:
                                                    dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                                    dest.Y += (int)((16 - source.Height) * _zoom / 16);
                                                    break;
                                            }
                                        }
                                        else if (isMushroom)
                                        {
                                            source = new Rectangle(0, 0, 60, 42);
                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                            source.X = (curtile.V / 18) * 62;

                                            dest.Width = (int)(_zoom * source.Width / 16f);
                                            dest.Height = (int)(_zoom * source.Height / 16f);
                                            dest.X += (int)(((16 - source.Width) / 2F) * _zoom / 16);
                                            dest.Y += (int)((16 - source.Height) * _zoom / 16);
                                        }
                                        else if ((curtile.Type >= 373 && curtile.Type <= 375) || curtile.Type == 461)
                                        {
                                          //skip rendering drips
                                        }
                                        else
                                        {
                                            source = new Rectangle(curtile.U, curtile.V, tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                            if (source.Width <= 0)
                                                source.Width = 16;
                                            if (source.Height <= 0)
                                                source.Height = 16;

                                            if (source.Bottom > tileTex.Height)
                                                source.Height -= (source.Bottom - tileTex.Height);
                                            if (source.Right > tileTex.Width)
                                                source.Width -= (source.Right - tileTex.Width);

                                            if (source.Width <= 0 || source.Height <= 0)
                                                continue;

                                            dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                            if (curtile.Type == 323)
                                            {
                                                dest.X += (int)(curtile.V * _zoom / 16);
                                                int treeType = (curtile.uvTileCache & 0x000F);
                                                source.Y = 22 * treeType;
                                            }
                                            var texsize = tileprop.TextureGrid;
                                            if (texsize.X != 16 || texsize.Y != 16)
                                            {
                                                dest.Width = (int)(texsize.X * (_zoom / 16));
                                                dest.Height = (int)(texsize.Y * (_zoom / 16));

                                                var frame = (tileprop.Frames.FirstOrDefault(f => f.UV == new Vector2Short(curtile.U, curtile.V)));
                                                var frameAnchor = FrameAnchor.None;
                                                if (frame != null)
                                                    frameAnchor = frame.Anchor;
                                                switch (frameAnchor)
                                                {
                                                    case FrameAnchor.None:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Left:
                                                        //position.X += (16 - texsize.X) / 2;
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Right:
                                                        dest.X += (int)((16 - texsize.X) * _zoom / 16);
                                                        dest.Y += (int)(((16 - texsize.Y) / 2F) * _zoom / 16);
                                                        break;
                                                    case FrameAnchor.Top:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        //position.Y += (16 - texsize.Y);
                                                        break;
                                                    case FrameAnchor.Bottom:
                                                        dest.X += (int)(((16 - texsize.X) / 2F) * _zoom / 16);
                                                        dest.Y += (int)((16 - texsize.Y) * _zoom / 16);
                                                        break;
                                                }
                                            }
                                        }

                                        _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                        // Actuator Overlay
                                        if (curtile.Actuator && _wvm.ShowActuators)
                                            _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator);

                                    }
                                }
                                else if (tileprop.IsPlatform)
                                {
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if (tileTex != null)
                                    {
                                        Vector2Int32 uv;
                                        if (curtile.uvTileCache == 0xFFFF)
                                        {
                                            uv = new Vector2Int32(0, 0);
                                            byte state = 0x00;
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x01 : 0x00);
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsSolid && neighborTile[w].Type != curtile.Type) ? 0x02 : 0x00);
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x04 : 0x00);
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsSolid && neighborTile[e].Type != curtile.Type) ? 0x08 : 0x00);
                                            switch (state)
                                            {
                                                case 0x00:
                                                case 0x0A:
                                                    uv.X = 5;
                                                    break;
                                                case 0x01:
                                                    uv.X = 1;
                                                    break;
                                                case 0x02:
                                                    uv.X = 6;
                                                    break;
                                                case 0x04:
                                                    uv.X = 2;
                                                    break;
                                                case 0x05:
                                                    uv.X = 0;
                                                    break;
                                                case 0x06:
                                                    uv.X = 3;
                                                    break;
                                                case 0x08:
                                                    uv.X = 7;
                                                    break;
                                                case 0x09:
                                                    uv.X = 4;
                                                    break;
                                            }
                                            uv.Y = blendRules.randomVariation.Next(3);
                                            curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X);
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                        // Actuator Overlay
                                        if (curtile.Actuator && _wvm.ShowActuators)
                                            _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator);

                                    }
                                }
                                else if (tileprop.IsCactus)
                                {

                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if ((curtile.uvTileCache & 0x00FF) >= 24)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Crimson_Cactus");
                                    }
                                    else if ((curtile.uvTileCache & 0x00FF) >= 16)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Evil_Cactus");
                                    }
                                    else if ((curtile.uvTileCache & 0x00FF) >= 8)
                                    {
                                        tileTex = (Texture2D)_textureDictionary.GetMisc("Good_Cactus");
                                    }

                                    if (tileTex != null)
                                    {
                                        Vector2Int32 uv;
                                        if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false)
                                        {
                                            bool isLeft = false, isRight = false, isBase = false;

                                            //Has this cactus been base-evaluated yet?
                                            int neighborX = (neighborTile[w].uvTileCache & 0x00FF) % 8; //Why % 8? If X >= 8, use hallow, If X >= 16, use corruption
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isRight = true;
                                            }
                                            neighborX = neighborTile[e].uvTileCache & 0x00FF;
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isLeft = true;
                                            }
                                            neighborX = curtile.uvTileCache & 0x00FF;
                                            if (neighborX == 0 || neighborX == 1 || neighborX == 4 || neighborX == 5)
                                            {
                                                isBase = true;
                                            }

                                            //Evaluate Base
                                            if (isLeft == false && isRight == false && isBase == false)
                                            {
                                                int length1 = 0;
                                                int length2 = 0;
                                                while (true)
                                                {
                                                    Tile checkTile = (y + length1) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x, y + length1] : null;
                                                    if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type)
                                                    {
                                                        break;
                                                    }
                                                    length1++;
                                                }
                                                if (x + 1 < _wvm.CurrentWorld.TilesWide)
                                                {
                                                    while (true)
                                                    {
                                                        Tile checkTile = (y + length2) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + 1, y + length2] : null;
                                                        if (checkTile == null || checkTile.IsActive == false || checkTile.Type != curtile.Type)
                                                        {
                                                            break;
                                                        }
                                                        length2++;
                                                    }
                                                }
                                                int baseX = 0;
                                                int baseY = length1;
                                                isBase = true;
                                                if (length2 >= length1)
                                                {
                                                    baseX = 1;
                                                    baseY = length2;
                                                    isBase = false;
                                                    isLeft = true;
                                                }
                                                for (int cy = y; cy < y + baseY; cy++)
                                                {
                                                    if (_wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache == 0xFFFF)
                                                    {
                                                        if (cy == y)
                                                        {
                                                            _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x00 << 8 + 0x00;
                                                        }
                                                        else
                                                        {
                                                            _wvm.CurrentWorld.Tiles[x + baseX, cy].uvTileCache = 0x01 << 8 + 0x00;
                                                        }
                                                    }
                                                }
                                            }

                                            uv = new Vector2Int32(0, 0);
                                            byte state = 0x00;
                                            state |= (byte)((neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == curtile.Type) ? 0x01 : 0x00);
                                            state |= (byte)((neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == curtile.Type) ? 0x02 : 0x00);
                                            state |= (byte)((neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == curtile.Type) ? 0x04 : 0x00);
                                            state |= (byte)((neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == curtile.Type) ? 0x08 : 0x00);
                                            //state |= (byte)((neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == curtile.Type) ? 0x10 : 0x00);
                                            //state |= (byte)((neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == curtile.Type) ? 0x20 : 0x00);
                                            state |= (byte)((neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == curtile.Type) ? 0x40 : 0x00);
                                            state |= (byte)((neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == curtile.Type) ? 0x80 : 0x00);

                                            if (isLeft)
                                            {
                                                uv.X = 3;
                                                if ((state & 0x08) != 0x00) //s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 1;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.Y = 0;
                                                    }
                                                }
                                                else //!s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 2;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.X = 6;
                                                        uv.Y = 2;
                                                    }
                                                }
                                            }
                                            if (isRight)
                                            {
                                                uv.X = 2;
                                                if ((state & 0x08) != 0x00) //s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 1;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.Y = 0;
                                                    }
                                                }
                                                else //!s
                                                {
                                                    if ((state & 0x02) != 0x00) //n
                                                    {
                                                        uv.Y = 2;
                                                    }
                                                    else //!n
                                                    {
                                                        uv.X = 6;
                                                        uv.Y = 1;
                                                    }
                                                }
                                            }
                                            if (isBase)
                                            {
                                                if ((state & 0x02) != 0x00) //n
                                                {
                                                    uv.Y = 2;
                                                    if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se)
                                                    {
                                                        uv.X = 4;
                                                    }
                                                    else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw)
                                                    {
                                                        uv.X = 1;
                                                    }
                                                    else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se
                                                    {
                                                        uv.X = 5;
                                                    }
                                                    else
                                                    {
                                                        uv.X = 0;
                                                        uv.Y = 1;
                                                    }
                                                }
                                                else //!n
                                                {
                                                    uv.Y = 0;
                                                    if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && ((state & 0x01) == 0x00 || (state & 0x80) != 0x00)) //w !sw (!e or se)
                                                    {
                                                        uv.X = 4;
                                                    }
                                                    else if ((state & 0x01) != 0x00 && (state & 0x80) == 0x00 && ((state & 0x04) == 0x00 || (state & 0x40) != 0x00)) //e !se (!w or sw)
                                                    {
                                                        uv.X = 1;
                                                    }
                                                    else if ((state & 0x04) != 0x00 && (state & 0x40) == 0x00 && (state & 0x01) != 0x00 && (state & 0x80) == 0x00) //w !sw e !se
                                                    {
                                                        uv.X = 5;
                                                    }
                                                    else
                                                    {
                                                        uv.X = 0;
                                                        uv.Y = 0;
                                                    }
                                                }
                                            }

                                            //Check if cactus is good or evil
                                            for (int i = 0; i < 100; i++)
                                            {
                                                int baseX = (isLeft) ? 1 : (isRight) ? -1 : 0;
                                                Tile checkTile = (y + i) < _wvm.CurrentWorld.TilesHigh ? _wvm.CurrentWorld.Tiles[x + baseX, y + i] : null;
                                                if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.CrimsandBlock) //Crimson
                                                {
                                                    uv.X += 24;
                                                    break;
                                                }
                                                if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.EbonsandBlock) //Corruption
                                                {
                                                    uv.X += 16;
                                                    break;
                                                }
                                                else if (checkTile != null && checkTile.IsActive && checkTile.Type == (int)TileType.PearlsandBlock) //Hallow
                                                {
                                                    uv.X += 8;
                                                    break;
                                                }
                                            }
                                            curtile.hasLazyChecked = true;

                                            curtile.uvTileCache = (ushort)((uv.Y << 8) + uv.X);
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle(((curtile.uvTileCache & 0x00FF) % 8) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                        _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                    }
                                }
                                else if (tileprop.CanBlend)
                                {
                                    var tileTex = _textureDictionary.GetTile(curtile.Type);

                                    if (tileTex != null)
                                    {
                                        if (curtile.uvTileCache == 0xFFFF || curtile.hasLazyChecked == false)
                                        {
                                            int sameStyle = 0x00000000;
                                            int mergeMask = 0x00000000;
                                            int strictness = 0;
                                            if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value == -1) //Basically for cobweb
                                            {
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive) ? 0x1000 : 0x0000;
                                            }
                                            else if (tileprop.IsStone) //Stone & Gems
                                            {
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].IsStone) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].IsStone) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].IsStone) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].IsStone) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].IsStone) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].IsStone) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].IsStone) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].IsStone) ? 0x10000000 : 0x00000000;
                                            }
                                            else //Everything else
                                            {
                                                //Join to nearby tiles if their merge type is this tile's type
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && World.TileProperties[neighborTile[e].Type].MergeWith.HasValue && World.TileProperties[neighborTile[e].Type].MergeWith.Value == curtile.Type) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && World.TileProperties[neighborTile[n].Type].MergeWith.HasValue && World.TileProperties[neighborTile[n].Type].MergeWith.Value == curtile.Type) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && World.TileProperties[neighborTile[w].Type].MergeWith.HasValue && World.TileProperties[neighborTile[w].Type].MergeWith.Value == curtile.Type) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && World.TileProperties[neighborTile[s].Type].MergeWith.HasValue && World.TileProperties[neighborTile[s].Type].MergeWith.Value == curtile.Type) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && World.TileProperties[neighborTile[ne].Type].MergeWith.HasValue && World.TileProperties[neighborTile[ne].Type].MergeWith.Value == curtile.Type) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && World.TileProperties[neighborTile[nw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[nw].Type].MergeWith.Value == curtile.Type) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && World.TileProperties[neighborTile[sw].Type].MergeWith.HasValue && World.TileProperties[neighborTile[sw].Type].MergeWith.Value == curtile.Type) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && World.TileProperties[neighborTile[se].Type].MergeWith.HasValue && World.TileProperties[neighborTile[se].Type].MergeWith.Value == curtile.Type) ? 0x10000000 : 0x00000000;
                                                //Join if nearby tiles have the same type as this tile's type
                                                sameStyle |= (neighborTile[e] != null && neighborTile[e].IsActive && curtile.Type == neighborTile[e].Type) ? 0x0001 : 0x0000;
                                                sameStyle |= (neighborTile[n] != null && neighborTile[n].IsActive && curtile.Type == neighborTile[n].Type) ? 0x0010 : 0x0000;
                                                sameStyle |= (neighborTile[w] != null && neighborTile[w].IsActive && curtile.Type == neighborTile[w].Type) ? 0x0100 : 0x0000;
                                                sameStyle |= (neighborTile[s] != null && neighborTile[s].IsActive && curtile.Type == neighborTile[s].Type) ? 0x1000 : 0x0000;
                                                sameStyle |= (neighborTile[ne] != null && neighborTile[ne].IsActive && curtile.Type == neighborTile[ne].Type) ? 0x00010000 : 0x00000000;
                                                sameStyle |= (neighborTile[nw] != null && neighborTile[nw].IsActive && curtile.Type == neighborTile[nw].Type) ? 0x00100000 : 0x00000000;
                                                sameStyle |= (neighborTile[sw] != null && neighborTile[sw].IsActive && curtile.Type == neighborTile[sw].Type) ? 0x01000000 : 0x00000000;
                                                sameStyle |= (neighborTile[se] != null && neighborTile[se].IsActive && curtile.Type == neighborTile[se].Type) ? 0x10000000 : 0x00000000;
                                            }
                                            if (curtile.hasLazyChecked == false)
                                            {
                                                bool lazyCheckReady = true;
                                                lazyCheckReady &= (neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[e].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[n].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[w].lazyMergeId != 0xFF);
                                                lazyCheckReady &= (neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? true : (neighborTile[s].lazyMergeId != 0xFF);
                                                if (lazyCheckReady)
                                                {
                                                    sameStyle &= 0x11111110 | ((neighborTile[e] == null || neighborTile[e].IsActive == false || World.TileProperties[neighborTile[e].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[e].Type].MergeWith.Value != curtile.Type) ? 0x00000001 : ((neighborTile[e].lazyMergeId & 0x04) >> 2));
                                                    sameStyle &= 0x11111101 | ((neighborTile[n] == null || neighborTile[n].IsActive == false || World.TileProperties[neighborTile[n].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[n].Type].MergeWith.Value != curtile.Type) ? 0x00000010 : ((neighborTile[n].lazyMergeId & 0x08) << 1));
                                                    sameStyle &= 0x11111011 | ((neighborTile[w] == null || neighborTile[w].IsActive == false || World.TileProperties[neighborTile[w].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[w].Type].MergeWith.Value != curtile.Type) ? 0x00000100 : ((neighborTile[w].lazyMergeId & 0x01) << 8));
                                                    sameStyle &= 0x11110111 | ((neighborTile[s] == null || neighborTile[s].IsActive == false || World.TileProperties[neighborTile[s].Type].MergeWith.HasValue == false || World.TileProperties[neighborTile[s].Type].MergeWith.Value != curtile.Type) ? 0x00001000 : ((neighborTile[s].lazyMergeId & 0x02) << 11));
                                                    curtile.hasLazyChecked = true;
                                                }
                                            }
                                            if (tileprop.MergeWith.HasValue && tileprop.MergeWith.Value > -1) //Merges with a specific type
                                            {
                                                mergeMask |= (neighborTile[e] != null && neighborTile[e].IsActive && neighborTile[e].Type == tileprop.MergeWith.Value) ? 0x0001 : 0x0000;
                                                mergeMask |= (neighborTile[n] != null && neighborTile[n].IsActive && neighborTile[n].Type == tileprop.MergeWith.Value) ? 0x0010 : 0x0000;
                                                mergeMask |= (neighborTile[w] != null && neighborTile[w].IsActive && neighborTile[w].Type == tileprop.MergeWith.Value) ? 0x0100 : 0x0000;
                                                mergeMask |= (neighborTile[s] != null && neighborTile[s].IsActive && neighborTile[s].Type == tileprop.MergeWith.Value) ? 0x1000 : 0x0000;
                                                mergeMask |= (neighborTile[ne] != null && neighborTile[ne].IsActive && neighborTile[ne].Type == tileprop.MergeWith.Value) ? 0x00010000 : 0x00000000;
                                                mergeMask |= (neighborTile[nw] != null && neighborTile[nw].IsActive && neighborTile[nw].Type == tileprop.MergeWith.Value) ? 0x00100000 : 0x00000000;
                                                mergeMask |= (neighborTile[sw] != null && neighborTile[sw].IsActive && neighborTile[sw].Type == tileprop.MergeWith.Value) ? 0x01000000 : 0x00000000;
                                                mergeMask |= (neighborTile[se] != null && neighborTile[se].IsActive && neighborTile[se].Type == tileprop.MergeWith.Value) ? 0x10000000 : 0x00000000;
                                                strictness = 1;
                                            }
                                            if (tileprop.IsGrass)
                                            {
                                                strictness = 2;
                                            }

                                            Vector2Int32 uvBlend = blendRules.GetUVForMasks((uint)sameStyle, (uint)mergeMask, strictness);
                                            curtile.uvTileCache = (ushort)((uvBlend.Y << 8) + uvBlend.X);
                                            curtile.lazyMergeId = blendRules.lazyMergeValidation[uvBlend.Y, uvBlend.X];
                                        }

                                        var texsize = new Vector2Int32(tileprop.TextureGrid.X, tileprop.TextureGrid.Y);
                                        if (texsize.X == 0 || texsize.Y == 0)
                                        {
                                            texsize = new Vector2Int32(16, 16);
                                        }
                                        var source = new Rectangle((curtile.uvTileCache & 0x00FF) * (texsize.X + 2), (curtile.uvTileCache >> 8) * (texsize.Y + 2), texsize.X, texsize.Y);
                                        var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);


                                        // hack for some slopes
                                        switch (curtile.BrickStyle)
                                        {

                                            case BrickStyle.HalfBrick:
                                                source.Height /= 2;
                                                dest.Y += (int)(_zoom * 0.5);
                                                dest.Height = (int)(_zoom / 2.0f);
                                                _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                                break;
                                            case BrickStyle.SlopeTopRight:

                                                for (int slice = 0; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, 16 - slice * 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), (int)(dest.Y + slice * _zoom / 8.0f));

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures);
                                                }

                                                break;
                                            case BrickStyle.SlopeTopLeft:
                                                for (int slice = 0; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 + 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), (int)(dest.Y + (7 - slice) * _zoom / 8.0f));

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures);
                                                }

                                                break;
                                            case BrickStyle.SlopeBottomRight:
                                                for (int slice = 0; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y + slice * 2, 2, 16 - slice * 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y);

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures);
                                                }

                                                break;
                                            case BrickStyle.SlopeBottomLeft:
                                                for (int slice = 0; slice < 8; slice++)
                                                {
                                                    Rectangle? sourceSlice = new Rectangle(source.X + slice * 2, source.Y, 2, slice * 2 + 2);
                                                    Vector2 destSlice = new Vector2((int)(dest.X + slice * _zoom / 8.0f), dest.Y);

                                                    _spriteBatch.Draw(tileTex, destSlice, sourceSlice, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), _zoom / 16, SpriteEffects.None, LayerTileTextures);
                                                }

                                                break;
                                            case BrickStyle.Full:
                                            default:
                                                _spriteBatch.Draw(tileTex, dest, source, curtile.InActive ? Color.Gray : Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileTextures);
                                                break;
                                        }


                                        // Actuator Overlay
                                        if (curtile.Actuator && _wvm.ShowActuators)
                                            _spriteBatch.Draw(_textureDictionary.Actuator, dest, _textureDictionary.ZeroSixteenRectangle, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerTileActuator);

                                    }
                                }
                            }
                        }
                        if (_wvm.ShowRedWires || _wvm.ShowBlueWires || _wvm.ShowGreenWires || _wvm.ShowYellowWires)
                        {
                            var tileTex = (Texture2D)_textureDictionary.GetMisc("WiresNew");
                            if (tileTex != null)
                            {
                                int voffset = 0;
                                if (curtile.Type == 424)
                                    voffset = (curtile.U / 18 + 1) * 72;
                                if (curtile.Type == 445)
                                    voffset = 72;
                                if (curtile.WireRed && _wvm.ShowRedWires)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].WireRed == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].WireRed == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].WireRed == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].WireRed == true) ? 0x08 : 0x00);
                                    source.X = state * 18;
                                    source.Y = voffset;

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerRedWires);
                                }
                                if (curtile.WireBlue && _wvm.ShowBlueWires)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].WireBlue == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].WireBlue == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].WireBlue == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].WireBlue == true) ? 0x08 : 0x00);
                                    source.X = state * 18;
                                    source.Y = 18 + voffset;

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerBlueWires);
                                }
                                if (curtile.WireGreen && _wvm.ShowGreenWires)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].WireGreen == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].WireGreen == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].WireGreen == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].WireGreen == true) ? 0x08 : 0x00);
                                    source.X = state * 18;
                                    source.Y = 36 + voffset;

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerGreenWires);
                                }
                                if (curtile.WireYellow && _wvm.ShowYellowWires)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);

                                    byte state = 0x00;
                                    state |= (byte)((neighborTile[n] != null && neighborTile[n].WireYellow == true) ? 0x01 : 0x00);
                                    state |= (byte)((neighborTile[e] != null && neighborTile[e].WireYellow == true) ? 0x02 : 0x00);
                                    state |= (byte)((neighborTile[s] != null && neighborTile[s].WireYellow == true) ? 0x04 : 0x00);
                                    state |= (byte)((neighborTile[w] != null && neighborTile[w].WireYellow == true) ? 0x08 : 0x00);
                                    source.X = state * 18;
                                    source.Y = 54 + voffset;

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White, 0f, default(Vector2), SpriteEffects.None, LayerYellowWires);
                                }
                            }
                        }
                        if (_wvm.ShowLiquid)
                        {
                            if (curtile.LiquidAmount > 0)
                            {
                                Texture2D tileTex = null;
                                if (curtile.LiquidType == LiquidType.Lava)
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(1);
                                }
                                else if (curtile.LiquidType == LiquidType.Honey)
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(11); // Not sure if yellow Desert water, or Honey, but looks fine.
                                }
                                else
                                {
                                    tileTex = (Texture2D)_textureDictionary.GetLiquid(0);
                                }

                                if (tileTex != null)
                                {
                                    var source = new Rectangle(0, 0, 16, 16);
                                    var dest = new Rectangle(1 + (int)((_scrollPosition.X + x) * _zoom), 1 + (int)((_scrollPosition.Y + y) * _zoom), (int)_zoom, (int)_zoom);
                                    float alpha = 1f;

                                    if (curtile.LiquidType != LiquidType.Lava)
                                    {
                                        alpha = 0.5f;
                                    }
                                    else
                                    {
                                        alpha = 0.85f;
                                    }

                                    if (neighborTile[n] != null && neighborTile[n].LiquidAmount > 0)
                                    {
                                        source.Y = 8;
                                        source.Height = 8;
                                    }
                                    else
                                    {
                                        source.Height = 4 + ((int)Math.Round(curtile.LiquidAmount * 6f / 255f)) * 2;
                                        dest.Height = (int)(source.Height * _zoom / 16f);
                                        dest.Y = 1 + (int)((_scrollPosition.Y + y) * _zoom + ((16 - source.Height) * _zoom / 16f));
                                    }

                                    _spriteBatch.Draw(tileTex, dest, source, Color.White * alpha, 0f, default(Vector2), SpriteEffects.None, LayerLiquid);
                                }
                            }
                        }
                    }
                }
            }
        }
 private void SetWall(Tile curTile, bool erase)
 {
     if (TilePicker.WallMaskMode == MaskMode.Off ||
         (TilePicker.WallMaskMode == MaskMode.Match && curTile.Wall == TilePicker.WallMask) ||
         (TilePicker.WallMaskMode == MaskMode.Empty && curTile.Wall == 0) ||
         (TilePicker.WallMaskMode == MaskMode.NotMatching && curTile.Wall != TilePicker.WallMask))
     {
         if (erase)
             SetPixelAutomatic(curTile, wall: 0);
         else
             SetPixelAutomatic(curTile, wall: TilePicker.Wall);
     }
 }
        private void SetPixelAutomatic(Tile curTile,
            int? tile = null,
            int? wall = null,
            byte? liquid = null,
            LiquidType? liquidType = null,
            bool? wire = null,
            short? u = null,
            short? v = null,
            bool? wire2 = null,
            bool? wire3 = null,
            BrickStyle? brickStyle = null,
            bool? actuator = null, bool? actuatorInActive = null,
            int? tileColor = null,
            int? wallColor = null)
        {
            // Set Tile Data
            if (u != null)
                curTile.U = (short)u;
            if (v != null)
                curTile.V = (short)v;

            if (tile != null)
            {
                if (tile == -1)
                {
                    curTile.Type = 0;
                    curTile.IsActive = false;
                }
                else
                {
                    curTile.Type = (ushort)tile;
                    curTile.IsActive = true;
                }
            }

            if (actuator != null && curTile.IsActive)
            {
                curTile.Actuator = (bool)actuator;
            }

            if (actuatorInActive != null && curTile.IsActive)
            {
                curTile.InActive = (bool)actuatorInActive;
            }

            if (brickStyle != null && TilePicker.BrickStyleActive)
            {
                curTile.BrickStyle = (BrickStyle)brickStyle;
            }

            if (wall != null)
                curTile.Wall = (byte)wall;

            if (liquid != null)
            {
                curTile.LiquidAmount = (byte)liquid;
            }

            if (liquidType != null)
            {
                curTile.LiquidType = (LiquidType)liquidType;
            }

            if (wire != null)
                curTile.WireRed = (bool)wire;

            if (wire2 != null)
                curTile.WireGreen = (bool)wire2;

            if (wire3 != null)
                curTile.WireBlue = (bool)wire3;

            if (tileColor != null)
            {
                if (curTile.IsActive)
                {
                    curTile.TileColor = (byte)tileColor;
                }
                else
                {
                    curTile.TileColor = (byte)0;
                }
            }

            if (wallColor != null)
            {
                if (curTile.Wall != 0)
                {
                    curTile.WallColor = (byte)wallColor;
                }
                else
                {
                    curTile.WallColor = (byte)0;
                }
            }

            if (curTile.IsActive)
                if (World.TileProperties[curTile.Type].IsSolid)
                    curTile.LiquidAmount = 0;
        }
 public bool Equals(Tile other)
 {
     if (ReferenceEquals(null, other)) return false;
     if (ReferenceEquals(this, other)) return true;
     return other.IsActive.Equals(IsActive) && other.Type == Type && other.Wall == Wall && other.Liquid == Liquid && other.IsLava.Equals(IsLava) && other.U == U && other.V == V && other.HasWire.Equals(HasWire);
 }
Beispiel #14
0
        private void LinearFloodFill(ref int x, ref int y, ref Tile originTile)
        {
            int bitmapWidth = _wvm.CurrentWorld.TilesWide;
            int bitmapHeight = _wvm.CurrentWorld.TilesHigh;

            //FIND LEFT EDGE OF COLOR AREA
            int lFillLoc = x; //the location to check/fill on the left
            int tileIndex = (bitmapWidth * y) + x;
            while (true)
            {
                if (!_wvm.CheckTiles[tileIndex])
                {
                    _wvm.UndoManager.SaveTile(lFillLoc, y);
                    _wvm.SetPixel(lFillLoc, y);
                    _wvm.UpdateRenderPixel(lFillLoc, y);
                    _wvm.CheckTiles[tileIndex] = true;
                }

                lFillLoc--;
                tileIndex--;
                if (lFillLoc <= 0 || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[lFillLoc, y]) || !_wvm.Selection.IsValid(lFillLoc, y))
                    break; //exit loop if we're at edge of bitmap or color area

            }
            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, lFillLoc + 1, y, x - lFillLoc, 1);

            lFillLoc++;
            if (lFillLoc < _minX)
                _minX = lFillLoc;
            //FIND RIGHT EDGE OF COLOR AREA
            int rFillLoc = x; //the location to check/fill on the left
            tileIndex = (bitmapWidth * y) + x;
            while (true)
            {
                if (!_wvm.CheckTiles[tileIndex])
                {
                    _wvm.UndoManager.SaveTile(rFillLoc, y);
                    _wvm.SetPixel(rFillLoc, y);
                    _wvm.UpdateRenderPixel(rFillLoc, y);
                    _wvm.CheckTiles[tileIndex] = true;
                    BlendRules.ResetUVCache(_wvm, rFillLoc, y, 1, 1);
                }

                rFillLoc++;
                tileIndex++;
                if (rFillLoc >= bitmapWidth || _wvm.CheckTiles[tileIndex] || !CheckTileMatch(ref originTile, ref _wvm.CurrentWorld.Tiles[rFillLoc, y]) || !_wvm.Selection.IsValid(rFillLoc, y))
                    break; //exit loop if we're at edge of bitmap or color area
            }
            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, x, y, rFillLoc - x, 1);

            rFillLoc--;
            if (rFillLoc > _maxX)
                _maxX = rFillLoc;

            var r = new FloodFillRange(lFillLoc, rFillLoc, y);
            _ranges.Enqueue(ref r);
        }
        public static ClipboardBuffer Load2(string filename)
        {
            using (var stream = new FileStream(filename, FileMode.Open))
            {
                using (var reader = new BinaryReader(stream))
                {
                    string name = reader.ReadString();
                    int version = reader.ReadInt32();
                    int maxx = reader.ReadInt32();
                    int maxy = reader.ReadInt32();

                    var buffer = new ClipboardBuffer(new Vector2Int32(maxx, maxy));

                    buffer.Name = string.IsNullOrWhiteSpace(name) ? Path.GetFileNameWithoutExtension(filename) : name;

                    try
                    {
                        for (int x = 0; x < maxx; x++)
                        {
                            for (int y = 0; y < maxy; y++)
                            {
                                var curTile = new Tile();
                                curTile.IsActive = reader.ReadBoolean();

                                if (curTile.IsActive)
                                {
                                    curTile.Type = reader.ReadByte();
                                    if (curTile.Type == 19) // fix for platforms
                                    {
                                        curTile.U = 0;
                                        curTile.V = 0;
                                    }
                                    else if (World.TileProperties[curTile.Type].IsFramed)
                                    {
                                        curTile.U = reader.ReadInt16();
                                        curTile.V = reader.ReadInt16();

                                        if (curTile.Type == 144) //timer
                                            curTile.V = 0;
                                    }
                                    else
                                    {
                                        curTile.U = -1;
                                        curTile.V = -1;
                                    }
                                }

                                if (reader.ReadBoolean())
                                    curTile.Wall = reader.ReadByte();

                                if (reader.ReadBoolean())
                                {
                                    curTile.Liquid = reader.ReadByte();
                                    curTile.IsLava = reader.ReadBoolean();
                                }

                                curTile.HasWire = reader.ReadBoolean();
                                buffer.Tiles[x, y] = curTile;
                            }

                        }

                    }
                    catch (Exception)
                    {
                        for (int x = 0; x < buffer.Size.X; x++)
                        {
                            for (int y = 0; y < buffer.Size.Y; y++)
                            {
                                if (buffer.Tiles[x, y] == null)
                                    buffer.Tiles[x, y] = new Tile();
                            }
                        }
                        return buffer;
                    }

                    for (int chestIndex = 0; chestIndex < 1000; chestIndex++)
                    {
                        if (reader.ReadBoolean())
                        {
                            var chest = new Chest();
                            chest.X = reader.ReadInt32();
                            chest.Y = reader.ReadInt32();

                            for (int slot = 0; slot < 20; slot++)
                            {
                                byte stackSize = reader.ReadByte();
                                if (stackSize > 0)
                                {
                                    string itemName = reader.ReadString();
                                    chest.Items[slot].SetFromName(itemName);
                                    chest.Items[slot].StackSize = stackSize;
                                }
                            }

                            //Chests[chestIndex] = chest;
                            buffer.Chests.Add(chest);
                        }
                    }
                    for (int signIndex = 0; signIndex < 1000; signIndex++)
                    {
                        if (reader.ReadBoolean())
                        {
                            string signText = reader.ReadString();
                            int x = reader.ReadInt32();
                            int y = reader.ReadInt32();
                            if (buffer.Tiles[x, y].IsActive && (buffer.Tiles[x, y].Type == 55 || buffer.Tiles[x, y].Type == 85))
                            // validate tile location
                            {
                                var sign = new Sign(x, y, signText);
                                //Signs[signIndex] = sign;
                                buffer.Signs.Add(sign);
                            }
                        }
                    }
                    string checkName = reader.ReadString();
                    int checkversion = reader.ReadInt32();
                    int checkx = reader.ReadInt32();
                    int checky = reader.ReadInt32();

                    if (checkName != buffer.Name || checkversion != version || checkx != maxx || checky != maxy)
                        System.Windows.MessageBox.Show("Verification failed. Some schematic data may be missing.", "Legacy Schematic Version");

                    return buffer;

                }
            }
            #pragma warning disable 162
            return null;
            #pragma warning restore
        }
Beispiel #16
0
        public static void WriteTileDataToStream(Tile curTile, BinaryWriter bw)
        {
            if (curTile.Type == 127)
                curTile.IsActive = false;

            bw.Write(curTile.IsActive);
            if (curTile.IsActive)
            {
                bw.Write(curTile.Type);
                if (TileProperties[curTile.Type].IsFramed)
                {
                    bw.Write(curTile.U);
                    bw.Write(curTile.V);
                }

                if (curTile.Color > 0)
                {
                    bw.Write(true);
                    bw.Write(curTile.Color);
                }
                else
                    bw.Write(false);
            }
            if ((int)curTile.Wall > 0)
            {
                bw.Write(true);
                bw.Write(curTile.Wall);

                if (curTile.WallColor > 0)
                {
                    bw.Write(true);
                    bw.Write(curTile.WallColor);
                }
                else
                    bw.Write(false);
            }
            else
                bw.Write(false);

            if ((int)curTile.Liquid > 0)
            {
                bw.Write(true);
                bw.Write(curTile.Liquid);
                bw.Write(curTile.IsLava);
                bw.Write(curTile.IsHoney);
            }
            else
                bw.Write(false);

            bw.Write(curTile.HasWire);
            bw.Write(curTile.HasWire2);
            bw.Write(curTile.HasWire3);
            bw.Write(curTile.HalfBrick);
            bw.Write(curTile.Slope);
            bw.Write(curTile.Actuator);
            bw.Write(curTile.InActive);
        }
        public static ClipboardBuffer Load3(string filename, bool frame19 = false)
        {
            bool failed = false;
            try
            {
                using (var stream = new FileStream(filename, FileMode.Open))
                {
                    using (var br = new BinaryReader(stream))
                    {
                        string name = br.ReadString();
                        int version = br.ReadInt32();

                        int sizeX = br.ReadInt32();
                        int sizeY = br.ReadInt32();
                        var buffer = new ClipboardBuffer(new Vector2Int32(sizeX, sizeY));
                        buffer.Name = name;

                        for (int x = 0; x < sizeX; x++)
                        {
                            for (int y = 0; y < sizeY; y++)
                            {
                                var curTile = new Tile();
                                curTile.IsActive = br.ReadBoolean();

                                if (curTile.IsActive)
                                {
                                    curTile.Type = br.ReadByte();
                                    if (curTile.Type == 19) // fix for platforms
                                    {

                                        curTile.U = 0;
                                        curTile.V = 0;
                                        if (frame19)
                                        {
                                            curTile.U = br.ReadInt16();
                                            curTile.V = br.ReadInt16();
                                        }
                                    }
                                    else if (World.TileProperties[curTile.Type].IsFramed)
                                    {
                                        curTile.U = br.ReadInt16();
                                        curTile.V = br.ReadInt16();

                                        if (curTile.Type == 144) //timer
                                            curTile.V = 0;
                                    }
                                    else
                                    {
                                        curTile.U = -1;
                                        curTile.V = -1;
                                    }
                                }

                                if (br.ReadBoolean())
                                    curTile.Wall = br.ReadByte();

                                if (br.ReadBoolean())
                                {
                                    curTile.Liquid = br.ReadByte();
                                    curTile.IsLava = br.ReadBoolean();
                                }

                                curTile.HasWire = br.ReadBoolean();
                                buffer.Tiles[x, y] = curTile;
                            }
                        }
                        for (int chestIndex = 0; chestIndex < 1000; chestIndex++)
                        {
                            if (br.ReadBoolean())
                            {
                                var curChest = new Chest(br.ReadInt32(), br.ReadInt32());
                                for (int j = 0; j < 20; ++j)
                                {
                                    curChest.Items[j].StackSize = br.ReadByte();

                                    if (curChest.Items[j].StackSize > 0)
                                    {
                                        if (version >= 3)
                                            curChest.Items[j].NetId = br.ReadInt32();
                                        else
                                            curChest.Items[j].SetFromName(br.ReadString());
                                        curChest.Items[j].Prefix = br.ReadByte();
                                    }
                                    else
                                    {
                                        curChest.Items[j].SetFromName("[empty]");
                                    }

                                }
                                buffer.Chests.Add(curChest);
                            }
                        }
                        for (int signIndex = 0; signIndex < 1000; signIndex++)
                        {
                            if (br.ReadBoolean())
                            {
                                string text = br.ReadString();
                                int x = br.ReadInt32();
                                int y = br.ReadInt32();
                                buffer.Signs.Add(new Sign(x, y, text));
                            }
                        }

                        if (buffer.Name != br.ReadString() || version != br.ReadInt32() || buffer.Size.X != br.ReadInt32() || buffer.Size.Y != br.ReadInt32())
                        {
                            if (!frame19)
                            {
                                br.Close();
                                return Load3(filename, true);
                            }
                            else
                                System.Windows.MessageBox.Show("Verification failed. Some schematic data may be missing.", "Legacy Schematic Version");
                        }

                        br.Close();
                        return buffer;
                    }
                }
            }
            catch (Exception)
            {
                failed = true;
            }

            if (failed && !frame19)
            {
                return Load3(filename, true);
            }

            return null;
        }
Beispiel #18
0
        private bool CheckTileMatch(ref Tile originTile, ref Tile nextTile)
        {
            switch (_wvm.TilePicker.PaintMode)
            {
                case PaintMode.Tile:
                    if (originTile.Type != nextTile.Type || originTile.IsActive != nextTile.IsActive)
                        return false;
                    break;
                case PaintMode.Wall:
                    if (originTile.Wall != nextTile.Wall)
                        return false;
                    break;
                case PaintMode.TileAndWall:
                    if (originTile.Type != nextTile.Type || originTile.IsActive != nextTile.IsActive || originTile.Wall != nextTile.Wall)
                        return false;
                    break;
                case PaintMode.Wire:
                    return false;
                case PaintMode.Liquid:
                    if ((originTile.Liquid > 0 != nextTile.Liquid > 0) ||
                        originTile.IsLava != nextTile.IsLava ||
                        originTile.IsHoney != nextTile.IsHoney ||
                        (originTile.IsActive && World.TileProperties[originTile.Type].IsSolid) ||
                        (nextTile.IsActive && World.TileProperties[nextTile.Type].IsSolid))
                        return false;

                    break;
            }

            return true;
        }
        public static ClipboardBuffer Load4(string filename)
        {
            using (var stream = new FileStream(filename, FileMode.Open))
            {
                using (var b = new BinaryReader(stream))
                {

                    string name = b.ReadString();
                    int version = b.ReadInt32();

                    int sizeX = b.ReadInt32();
                    int sizeY = b.ReadInt32();
                    var buffer = new ClipboardBuffer(new Vector2Int32(sizeX, sizeY));
                    buffer.Name = name;

                    for (int x = 0; x < sizeX; ++x)
                    {
                        for (int y = 0; y < sizeY; y++)
                        {
                            var tile = new Tile();

                            tile.IsActive = b.ReadBoolean();

                            TileProperty tileProperty = null;
                            if (tile.IsActive)
                            {
                                tile.Type = b.ReadByte();
                                tileProperty = World.TileProperties[tile.Type];

                                if (tile.Type == 127)
                                    tile.IsActive = false;

                                if (tileProperty.IsFramed)
                                {
                                    tile.U = b.ReadInt16();
                                    tile.V = b.ReadInt16();

                                    if (tile.Type == 144) //timer
                                        tile.V = 0;
                                }
                                else
                                {
                                    tile.U = -1;
                                    tile.V = -1;
                                }

                                if (b.ReadBoolean())
                                {
                                    tile.Color = b.ReadByte();
                                }
                            }

                            if (b.ReadBoolean())
                            {
                                tile.Wall = b.ReadByte();
                                if (b.ReadBoolean())
                                    tile.WallColor = b.ReadByte();
                            }

                            if (b.ReadBoolean())
                            {
                                tile.Liquid = b.ReadByte();
                                tile.IsLava = b.ReadBoolean();
                                tile.IsHoney = b.ReadBoolean();
                            }

                            tile.HasWire = b.ReadBoolean();
                            tile.HasWire2 = b.ReadBoolean();
                            tile.HasWire3 = b.ReadBoolean();
                            tile.HalfBrick = b.ReadBoolean();

                            if (tileProperty == null || !tileProperty.IsSolid)
                                tile.HalfBrick = false;

                            tile.Slope = b.ReadByte();
                            if (tileProperty == null || !tileProperty.IsSolid)
                                tile.Slope = 0;

                            tile.Actuator = b.ReadBoolean();
                            tile.InActive = b.ReadBoolean();

                            // read complete, start compression
                            buffer.Tiles[x, y] = tile;

                            int rle = b.ReadInt16();
                            if (rle < 0)
                                throw new ApplicationException("Invalid Tile Data!");

                            if (rle > 0)
                            {
                                for (int k = y + 1; k < y + rle + 1; k++)
                                {
                                    var tcopy = (Tile)tile.Clone();
                                    buffer.Tiles[x, k] = tcopy;
                                }
                                y = y + rle;
                            }
                        }
                    }
                    for (int i = 0; i < 1000; i++)
                    {
                        if (b.ReadBoolean())
                        {
                            var chest = new Chest(b.ReadInt32(), b.ReadInt32());
                            for (int slot = 0; slot < Chest.MaxItems; slot++)
                            {
                                if (slot < Chest.MaxItems)
                                {
                                    int stackSize = (int)b.ReadInt16();
                                    chest.Items[slot].StackSize = stackSize;

                                    if (chest.Items[slot].StackSize > 0)
                                    {
                                        chest.Items[slot].NetId = b.ReadInt32();
                                        chest.Items[slot].StackSize = stackSize;
                                        chest.Items[slot].Prefix = b.ReadByte();
                                    }
                                }
                            }
                            buffer.Chests.Add(chest);
                        }
                    }

                    for (int i = 0; i < 1000; i++)
                    {
                        if (b.ReadBoolean())
                        {
                            Sign sign = new Sign();
                            sign.Text = b.ReadString();
                            sign.X = b.ReadInt32();
                            sign.Y = b.ReadInt32();

                            if (buffer.Tiles[sign.X, sign.Y].IsActive && (int)buffer.Tiles[sign.X, sign.Y].Type == 55 && (int)buffer.Tiles[sign.X, sign.Y].Type == 85)
                                buffer.Signs.Add(sign);
                        }
                    }

                    string verifyName = b.ReadString();
                    int verifyVersion = b.ReadInt32();
                    int verifyX = b.ReadInt32();
                    int verifyY = b.ReadInt32();
                    if (buffer.Name == verifyName &&
                        version == verifyVersion &&
                        buffer.Size.X == verifyX &&
                        buffer.Size.Y == verifyY)
                    {
                        // valid;
                        return buffer;
                    }
                    b.Close();
                    return null;
                }
            }
        }
        public static UndoBuffer Read(string filename)
        {
            var buffer = new UndoBuffer();

            using (var stream = new FileStream(filename, FileMode.Open))
            {
                using (var br = new BinaryReader(stream))
                {
                    var tilecount = br.ReadInt32();
                    for (int i = 0; i < tilecount; i++)
                    {
                        int x = br.ReadInt32();
                        int y = br.ReadInt32();
                        var curTile = new Tile();
                        curTile.IsActive = br.ReadBoolean();

                        if (curTile.IsActive)
                        {
                            curTile.Type = br.ReadByte();
                            if (World.TileProperties[curTile.Type].IsFramed)
                            {
                                curTile.U = br.ReadInt16();
                                curTile.V = br.ReadInt16();
                            }
                        }

                        if (br.ReadBoolean())
                            curTile.Wall = br.ReadByte();

                        if (br.ReadBoolean())
                        {
                            curTile.Liquid = br.ReadByte();
                            curTile.IsLava = br.ReadBoolean();
                        }

                        curTile.HasWire = br.ReadBoolean();
                        buffer.Tiles.Add(new UndoTile(new Vector2Int32(x,y), curTile));
                    }

                    for (int chestIndex = 0; chestIndex < 1000; chestIndex++)
                    {
                        if (br.ReadBoolean())
                        {
                            var curChest = new Chest(br.ReadInt32(), br.ReadInt32());
                            for (int j = 0; j < Chest.MaxItems; ++j)
                            {
                                curChest.Items[j].StackSize = br.ReadByte();

                                if (curChest.Items[j].StackSize > 0)
                                {
                                    curChest.Items[j].NetId = br.ReadInt32();
                                    curChest.Items[j].Prefix = br.ReadByte();
                                }
                                else
                                {
                                    curChest.Items[j].NetId = 0;
                                }
                            }

                            buffer.Chests.Add(curChest);
                        }
                    }
                    for (int signIndex = 0; signIndex < 1000; signIndex++)
                    {
                        if (br.ReadBoolean())
                        {
                            string text = br.ReadString();
                            int x = br.ReadInt32();
                            int y = br.ReadInt32();
                            buffer.Signs.Add(new Sign(x, y, text));
                        }
                    }
                }
            }
            return buffer;
        }
        public static ClipboardBuffer LoadOld(string filename)
        {
            using (var stream = new FileStream(filename, FileMode.Open))
            {
                using (var reader = new BinaryReader(stream))
                {
                    string name = reader.ReadString();
                    int version = reader.ReadInt32();
                    int maxx = reader.ReadInt32();
                    int maxy = reader.ReadInt32();

                    var buffer = new ClipboardBuffer(new Vector2Int32(maxx, maxy));

                    buffer.Name = string.IsNullOrWhiteSpace(name) ? Path.GetFileNameWithoutExtension(filename) : name;

                    try
                    {
                        for (int x = 0; x < buffer.Size.X; x++)
                        {
                            for (int y = 0; y < buffer.Size.Y; y++)
                            {
                                var tile = new Tile();

                                tile.IsActive = reader.ReadBoolean();

                                if (tile.IsActive)
                                {
                                    tile.Type = reader.ReadByte();

                                    if (tile.Type == 19)
                                    {
                                        tile.U = 0;
                                        tile.V = 0;
                                    }
                                    else if (World.TileProperties[tile.Type].IsFramed)
                                    {
                                        tile.U = reader.ReadInt16();
                                        tile.V = reader.ReadInt16();
                                    }
                                    else
                                    {
                                        tile.U = -1;
                                        tile.V = -1;
                                    }
                                }

                                // trash old lighted value
                                reader.ReadBoolean();

                                if (reader.ReadBoolean())
                                {
                                    tile.Wall = reader.ReadByte();
                                }

                                if (reader.ReadBoolean())
                                {
                                    tile.Liquid = reader.ReadByte();
                                    tile.IsLava = reader.ReadBoolean();
                                }

                                buffer.Tiles[x, y] = tile;
                            }
                        }

                    }
                    catch (Exception)
                    {
                        for (int x = 0; x < buffer.Size.X; x++)
                        {
                            for (int y = 0; y < buffer.Size.Y; y++)
                            {
                                if (buffer.Tiles[x, y] == null)
                                    buffer.Tiles[x, y] = new Tile();
                            }
                        }
                        return buffer;
                    }

                    for (int chestIndex = 0; chestIndex < 1000; chestIndex++)
                    {
                        if (reader.ReadBoolean())
                        {
                            var chest = new Chest();
                            chest.X = reader.ReadInt32();
                            chest.Y = reader.ReadInt32();

                            for (int slot = 0; slot < 20; slot++)
                            {
                                byte stackSize = reader.ReadByte();
                                if (stackSize > 0)
                                {
                                    string itemName = reader.ReadString();
                                    chest.Items[slot].SetFromName(itemName);
                                    chest.Items[slot].StackSize = stackSize;
                                }
                            }

                            //Chests[chestIndex] = chest;
                            buffer.Chests.Add(chest);
                        }
                    }
                    for (int signIndex = 0; signIndex < 1000; signIndex++)
                    {
                        if (reader.ReadBoolean())
                        {
                            string signText = reader.ReadString();
                            int x = reader.ReadInt32();
                            int y = reader.ReadInt32();
                            if (buffer.Tiles[x, y].IsActive && (buffer.Tiles[x, y].Type == 55 || buffer.Tiles[x, y].Type == 85))
                            // validate tile location
                            {
                                var sign = new Sign(x, y, signText);
                                //Signs[signIndex] = sign;
                                buffer.Signs.Add(sign);
                            }
                        }
                    }

                    int checkx = reader.ReadInt32();
                    int checky = reader.ReadInt32();

                    if (checkx == maxx && checky == maxy)
                        return buffer;

                }
            }

            return null;
        }
 private void SetTile(Tile curTile, bool erase)
 {
     if (TilePicker.TileMaskMode == MaskMode.Off ||
         (TilePicker.TileMaskMode == MaskMode.Match && curTile.Type == TilePicker.TileMask && curTile.IsActive) ||
         (TilePicker.TileMaskMode == MaskMode.Empty && !curTile.IsActive) ||
         (TilePicker.TileMaskMode == MaskMode.NotMatching && (curTile.Type != TilePicker.TileMask || !curTile.IsActive)))
     {
         if (erase)
             SetPixelAutomatic(curTile, tile: -1);
         else
             SetPixelAutomatic(curTile, tile: TilePicker.Tile);
     }
 }
 public byte TileArgsToByte(Tile tile)
 {
     byte b = 0;
     if (tile.IsActive)
         b |= (byte)TileFlags.IsActive;
     if (tile.IsLava)
         b |= (byte)TileFlags.IsLava;
     if (tile.HasWire)
         b |= (byte)TileFlags.HasWire;
     if (tile.IsHoney)
         b |= (byte)TileFlags.IsHoney;
     if (tile.HasWire2)
         b |= (byte)TileFlags.HasWire2;
     if (tile.HasWire3)
         b |= (byte)TileFlags.HasWire3;
     if (tile.Actuator)
         b |= (byte)TileFlags.Actuator;
     if (tile.InActive)
         b |= (byte)TileFlags.InActive;
     return b;
 }
 protected void ClearTile(Tile tile)
 {
     tile.Type = 0;
     tile.IsActive = false;
     tile.U = 0;
     tile.V = 0;
 }
        private static Tile TileFromColor(int color)
        {
            byte a = (byte)(color >> 24);
            byte r = (byte)(color >> 16);
            byte g = (byte)(color >> 8);
            byte b = (byte)(color >> 0);
            var tile = new Tile();

            // try and find a matching brick
            var tileProperty = World.GetBrickFromColor(a, r, g, b);
            if (tileProperty != null && !tileProperty.IsFramed)
            {
                tile.IsActive = true;
                tile.Type = (byte)tileProperty.Id;
            }

            // try and find a matching wall
            var wallproperty = World.GetWallFromColor(a, r, g, b);
            if (wallproperty != null && !tile.IsActive)
            {
                tile.Wall = (byte)wallproperty.Id;
            }
            return tile;
        }
 protected bool Equals(Tile other)
 {
     return IsActive.Equals(other.IsActive) &&
         Type == other.Type &&
         TileColor == other.TileColor &&
         U == other.U && V == other.V &&
         LiquidType.Equals(other.LiquidType) &&
         LiquidAmount == other.LiquidAmount &&
         Wall == other.Wall &&
         WallColor == other.WallColor &&
         WireRed.Equals(other.WireRed) &&
         WireGreen.Equals(other.WireGreen) &&
         WireBlue.Equals(other.WireBlue) &&
         BrickStyle.Equals(other.BrickStyle) &&
         BrickStyle == other.BrickStyle &&
         Actuator.Equals(other.Actuator) &&
         InActive.Equals(other.InActive);
 }
        private static Tile TileFromFalseColor(int color)
        {
            byte a = (byte)(color >> 24);
            byte r = (byte)(color >> 16);
            byte g = (byte)(color >> 8);
            byte b = (byte)(color >> 0);
            var tile = new Tile();

            AppendTileFlagsFromByte(ref tile, a);
            // try and find a matching brick

            var tileProperty = World.TileProperties.FirstOrDefault(t => t.Id == r);
            if (tileProperty != null && !tileProperty.IsFramed)
            {
                tile.Type = (byte)tileProperty.Id;
            }
            else
            {
                // disable missing and framed tiles
                tile.IsActive = false;
            }

            // try and find a matching wall
            var wallproperty = World.WallProperties[g];
            if (wallproperty != null && !tile.IsActive)
            {
                tile.Wall = (byte)wallproperty.Id;
            }

            tile.Liquid = b;

            return tile;
        }
 public UndoTile(Vector2Int32 location, Tile tile)
 {
     Location = location;
     Tile = tile;
 }
Beispiel #29
0
        public static Tile ReadTileDataFromStream(BinaryReader b, uint version)
        {
            Tile tile = new Tile();

            tile.IsActive = b.ReadBoolean();

            TileProperty tileProperty = null;

            if (tile.IsActive)
            {
                tile.Type = b.ReadByte();
                tileProperty = TileProperties[tile.Type];

                if (tile.Type == 127)
                    tile.IsActive = false;

                if (version < 72 && (tile.Type == 35 || tile.Type == 36 || tile.Type == 170 || tile.Type == 171 || tile.Type == 172))
                {
                    tile.U = b.ReadInt16();
                    tile.V = b.ReadInt16();
                }
                else if (!tileProperty.IsFramed)
                {
                    tile.U = -1;
                    tile.V = -1;
                }
                else if (version < 28 && tile.Type == 4)
                {
                    // torches didn't have extra in older versions.
                    tile.U = 0;
                    tile.V = 0;
                }
                else if (version < 40 && tile.Type == 19)
                {
                    tile.U = 0;
                    tile.V = 0;
                }
                else
                {
                    tile.U = b.ReadInt16();
                    tile.V = b.ReadInt16();

                    if (tile.Type == 144) //timer
                        tile.V = 0;

                }

                if (version >= 48 && b.ReadBoolean())
                {
                    tile.Color = b.ReadByte();
                }
            }

            //skip obsolete hasLight
            if (version <= 25)
                b.ReadBoolean();

            if (b.ReadBoolean())
            {
                tile.Wall = b.ReadByte();
                if (version >= 48 && b.ReadBoolean())
                    tile.WallColor = b.ReadByte();
            }

            if (b.ReadBoolean())
            {
                tile.Liquid = b.ReadByte();
                tile.IsLava = b.ReadBoolean();
                if (version >= 51)
                {
                    tile.IsHoney = b.ReadBoolean();
                }
            }

            if (version >= 33)
            {
                tile.HasWire = b.ReadBoolean();
            }
            if (version >= 43)
            {
                tile.HasWire2 = b.ReadBoolean();
                tile.HasWire3 = b.ReadBoolean();
            }

            if (version >= 41)
            {
                tile.HalfBrick = b.ReadBoolean();

                if (tileProperty == null || !tileProperty.IsSolid)
                    tile.HalfBrick = false;

                if (version >= 49)
                {
                    tile.Slope = b.ReadByte();

                    if (tileProperty == null || !tileProperty.IsSolid)
                        tile.Slope = 0;
                }
            }
            if (version >= 42)
            {
                tile.Actuator = b.ReadBoolean();
                tile.InActive = b.ReadBoolean();
            }
            return tile;
        }
        private void NewWorld()
        {
            NewWorldView nwDialog = new NewWorldView();
            if ((bool)nwDialog.ShowDialog())
            {
                _loadTimer.Reset();
                _loadTimer.Start();
                _saveTimer.Stop();
                Task.Factory.StartNew(() =>
                                          {
                                              var w = nwDialog.NewWorld;
                                              w.SpawnX = w.TilesWide / 2;
                                              w.SpawnY = (int)Math.Max(0, w.GroundLevel - 10);
                                              w.GroundLevel = (int)w.GroundLevel;
                                              w.RockLevel = (int)w.RockLevel;
                                              w.BottomWorld = w.TilesHigh * 16;
                                              w.RightWorld = w.TilesWide * 16;
                                              w.Tiles = new Tile[w.TilesWide, w.TilesHigh];
                                              Tile cloneTile = new Tile();
                                              for (int y = 0; y < w.TilesHigh; y++)
                                              {
                                                  OnProgressChanged(w, new ProgressChangedEventArgs(BCCL.Utility.Calc.ProgressPercentage(y, w.TilesHigh), "Generating World..."));

                                                  if (y == (int)w.GroundLevel - 10)
                                                      cloneTile = new Tile { HasWire = false, IsActive = true, IsLava = false, Liquid = 0, Type = 2, U = -1, V = -1, Wall = 2 };
                                                  if (y == (int)w.GroundLevel - 9)
                                                      cloneTile = new Tile { HasWire = false, IsActive = true, IsLava = false, Liquid = 0, Type = 0, U = -1, V = -1, Wall = 2 };
                                                  else if (y == (int)w.GroundLevel + 1)
                                                      cloneTile = new Tile { HasWire = false, IsActive = true, IsLava = false, Liquid = 0, Type = 0, U = -1, V = -1, Wall = 0 };
                                                  else if (y == (int)w.RockLevel)
                                                      cloneTile = new Tile { HasWire = false, IsActive = true, IsLava = false, Liquid = 0, Type = 1, U = -1, V = -1, Wall = 0 };
                                                  else if (y == w.TilesHigh - 182)
                                                      cloneTile = new Tile();
                                                  for (int x = 0; x < w.TilesWide; x++)
                                                  {
                                                      w.Tiles[x, y] = (Tile)cloneTile.Clone();
                                                  }
                                              }
                                              return w;
                                          })
                .ContinueWith(t => CurrentWorld = t.Result, TaskFactoryHelper.UiTaskScheduler)
                .ContinueWith(t => RenderEntireWorld())
                .ContinueWith(t =>
                                  {
                                      CurrentFile = null;
                                      PixelMap = t.Result;
                                      UpdateTitle();
                                      Points.Clear();
                                      Points.Add("Spawn");
                                      Points.Add("Dungeon");
                                      foreach (var npc in CurrentWorld.NPCs)
                                      {
                                          Points.Add(npc.Name);
                                      }
                                      _loadTimer.Stop();
                                      OnProgressChanged(this, new ProgressChangedEventArgs(0, string.Format("World loaded in {0} seconds.", _loadTimer.Elapsed.TotalSeconds)));
                                      _saveTimer.Start();
                                  }, TaskFactoryHelper.UiTaskScheduler);

            }
        }
Beispiel #31
0
        public void Validate()
        {
            for (int x = 0; x < TilesWide; x++)
            {
                OnProgressChanged(this,
                    new ProgressChangedEventArgs((int) (x/(float) TilesWide*100.0), "Validating World..."));

                for (int y = 0; y < TilesHigh; y++)
                {
                    Tile curTile = Tiles[x, y];

                    if (curTile.Type == 127)
                        curTile.IsActive = false;

                    // TODO: Let Validate handle these
                    //validate chest entry exists
                    if (curTile.Type == 21)
                    {
                        if (GetChestAtTile(x, y) == null)
                        {
                            Chests.Add(new Chest(x, y));
                        }
                    }
                        //validate sign entry exists
                    else if (curTile.Type == 55 || curTile.Type == 85)
                    {
                        if (GetSignAtTile(x, y) == null)
                        {
                            Signs.Add(new Sign(x, y, string.Empty));
                        }
                    }
                }
            }

            foreach (Chest chest in Chests.ToArray())
            {
                bool removed = false;
                for (int x = chest.X; x < chest.X+1; x++)
                {
                    for (int y = chest.Y; y < chest.Y + 1; y++)
                    {
                        if (!Tiles[x, y].IsActive || Tiles[x, y].Type != 21)
                        {
                            Chests.Remove(chest);
                            removed = true;
                            break;
                        }
                    }
                    if (removed) break;
                }
            }

            foreach (Sign sign in Signs.ToArray())
            {
                if (sign.Text == null)
                {
                    Signs.Remove(sign);
                    continue;
                }

                bool removed = false;
                for (int x = sign.X; x < sign.X + 1; x++)
                {
                    for (int y = sign.Y; y < sign.Y + 1; y++)
                    {
                        if (!Tiles[x, y].IsActive || (Tiles[x, y].Type != 55 && Tiles[x, y].Type != 85))
                        {
                            Signs.Remove(sign);
                            removed = true;
                            break;
                        }
                    }
                    if (removed) break;
                }
            }
        }