public void FlipY(ClipboardBuffer buffer)
 {
     Flip(buffer, false);
 }
        public ClipboardBuffer GetSelectionBuffer()
        {
            World world = _wvm.CurrentWorld;

            XNA.Rectangle area   = _wvm.Selection.SelectionArea;
            var           buffer = new ClipboardBuffer(new Vector2Int32(area.Width, area.Height));

            for (int x = 0; x < area.Width; x++)
            {
                for (int y = 0; y < area.Height; y++)
                {
                    Tile curTile = (Tile)world.Tiles[x + area.X, y + area.Y].Clone();

                    if (Tile.IsChest(curTile.Type))
                    {
                        if (buffer.GetChestAtTile(x, y) == null)
                        {
                            var anchor = world.GetAnchor(x + area.X, y + area.Y);
                            if (anchor.X == x + area.X && anchor.Y == y + area.Y)
                            {
                                var data = world.GetChestAtTile(x + area.X, y + area.Y);
                                if (data != null)
                                {
                                    var newChest = data.Copy();
                                    newChest.X = x;
                                    newChest.Y = y;
                                    buffer.Chests.Add(newChest);
                                }
                            }
                        }
                    }
                    if (Tile.IsSign(curTile.Type))
                    {
                        if (buffer.GetSignAtTile(x, y) == null)
                        {
                            var anchor = world.GetAnchor(x + area.X, y + area.Y);
                            if (anchor.X == x + area.X && anchor.Y == y + area.Y)
                            {
                                var data = world.GetSignAtTile(x + area.X, y + area.Y);
                                if (data != null)
                                {
                                    var newSign = data.Copy();
                                    newSign.X = x;
                                    newSign.Y = y;
                                    buffer.Signs.Add(newSign);
                                }
                            }
                        }
                    }
                    if (Tile.IsTileEntity(curTile.Type))
                    {
                        if (buffer.GetTileEntityAtTile(x, y) == null)
                        {
                            var anchor = world.GetAnchor(x + area.X, y + area.Y);
                            if (anchor.X == x + area.X && anchor.Y == y + area.Y)
                            {
                                var data = world.GetTileEntityAtTile(x + area.X, y + area.Y);
                                if (data != null)
                                {
                                    var newEntity = data.Copy();
                                    newEntity.PosX = (short)x;
                                    newEntity.PosY = (short)y;
                                    buffer.TileEntities.Add(newEntity);
                                }
                            }
                        }
                    }
                    buffer.Tiles[x, y] = curTile;
                }
            }

            buffer.RenderBuffer();
            return(buffer);
        }
        // Reverse the buffer along the x- or y- axis
        public void Flip(ClipboardBuffer buffer, bool flipX)
        {
            ClipboardBuffer flippedBuffer = new ClipboardBuffer(buffer.Size);
            //var sprites = new Dictionary<Vector2Int32, Sprite>();
            var spriteSizes = new Dictionary <Vector2Int32, Vector2Short>();
            int maxX        = buffer.Size.X - 1;
            int maxY        = buffer.Size.Y - 1;

            for (int x = 0; x <= maxX; x++)
            {
                for (int y = 0; y <= maxY; y++)
                {
                    int bufferX;
                    int bufferY;

                    if (flipX)
                    {
                        bufferX = maxX - x;
                        bufferY = y;
                    }
                    else
                    {
                        bufferX = x;
                        bufferY = maxY - y;
                    }

                    Tile tile           = (Tile)buffer.Tiles[x, y].Clone();
                    var  tileProperties = World.TileProperties[tile.Type];


                    // locate all the sprites and make a list
                    if (tileProperties.IsFramed)
                    {
                        var loc = new Vector2Int32(x, y);
                        if (tileProperties.IsOrigin(tile.GetUV()))
                        {
                            Vector2Short tileSize = tileProperties.GetFrameSize(tile.V);
                            spriteSizes[loc] = tileSize;
                        }
                    }
                    else
                    {
                        if (flipX)
                        {
                            //  Ignore multi-width objects when flipping on x-axis

                            // Flip brick-style
                            switch (tile.BrickStyle)
                            {
                            case BrickStyle.SlopeTopRight:
                                tile.BrickStyle = BrickStyle.SlopeTopLeft;
                                break;

                            case BrickStyle.SlopeTopLeft:
                                tile.BrickStyle = BrickStyle.SlopeTopRight;
                                break;

                            case BrickStyle.SlopeBottomRight:
                                tile.BrickStyle = BrickStyle.SlopeBottomLeft;
                                break;

                            case BrickStyle.SlopeBottomLeft:
                                tile.BrickStyle = BrickStyle.SlopeBottomRight;
                                break;
                            }
                        }

                        else
                        {
                            //  Ignore multi-height tiles when flipping on y-axis

                            // Flip brick-style
                            switch (tile.BrickStyle)
                            {
                            case BrickStyle.SlopeTopRight:
                                tile.BrickStyle = BrickStyle.SlopeBottomRight;
                                break;

                            case BrickStyle.SlopeTopLeft:
                                tile.BrickStyle = BrickStyle.SlopeBottomLeft;
                                break;

                            case BrickStyle.SlopeBottomRight:
                                tile.BrickStyle = BrickStyle.SlopeTopRight;
                                break;

                            case BrickStyle.SlopeBottomLeft:
                                tile.BrickStyle = BrickStyle.SlopeTopLeft;
                                break;
                            }
                        }

                        flippedBuffer.Tiles[bufferX, bufferY] = (Tile)tile;
                    }
                }
            }

            foreach (var item in spriteSizes)
            {
                var flipOrigin = FlipFramed(buffer.Size, item.Key, item.Value, flipX);

                for (int y = 0; y < item.Value.Y; y++)
                {
                    int sourceY = y + item.Key.Y;
                    int targetY = y + flipOrigin.Y;

                    for (int x = 0; x < item.Value.X; x++)
                    {
                        try
                        {
                            int sourceX = x + item.Key.X;
                            int targetX = x + flipOrigin.X;

                            Tile tile = (Tile)buffer.Tiles[sourceX, sourceY].Clone();
                            flippedBuffer.Tiles[targetX, targetY] = (Tile)tile;
                        }
                        catch (Exception)
                        {
                        }
                    }
                }
            }

            foreach (var chest in buffer.Chests)
            {
                var flipOrigin = FlipFramed(buffer.Size, new Vector2Int32(chest.X, chest.Y), new Vector2Short(2, 2), flipX);
                chest.X = flipOrigin.X;
                chest.Y = flipOrigin.Y;
                flippedBuffer.Chests.Add(chest);
            }

            foreach (var sign in buffer.Signs)
            {
                var flipOrigin = FlipFramed(buffer.Size, new Vector2Int32(sign.X, sign.Y), new Vector2Short(2, 2), flipX);
                sign.X = flipOrigin.X;
                sign.Y = flipOrigin.Y;
                flippedBuffer.Signs.Add(sign);
            }

            foreach (var te in buffer.TileEntities)
            {
                var          tileProperties = World.TileProperties[(int)te.TileType];
                Vector2Short tileSize       = tileProperties.FrameSize[0];

                var flipOrigin = FlipFramed(buffer.Size, new Vector2Int32(te.PosX, te.PosY), tileSize, flipX);
                te.PosX = (short)flipOrigin.X;
                te.PosY = (short)flipOrigin.Y;
                flippedBuffer.TileEntities.Add(te);
            }

            // Replace the existing buffer with the new one
            int bufferIndex = LoadedBuffers.IndexOf(buffer);

            if (bufferIndex > -1)
            {
                LoadedBuffers.Insert(bufferIndex, flippedBuffer);
                LoadedBuffers.RemoveAt(bufferIndex + 1);
            }

            flippedBuffer.RenderBuffer();

            if (Buffer == buffer)
            {
                Buffer = flippedBuffer;
                _wvm.PreviewChange();
            }
        }
 public void FlipX(ClipboardBuffer buffer)
 {
     Flip(buffer, true);
 }
        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 == (int)TileType.Platform)
                                    {
                                        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.LiquidType   = LiquidType.Water;
                                    tile.LiquidAmount = reader.ReadByte();
                                    if (reader.ReadBoolean()) // lava
                                    {
                                        tile.LiquidType = LiquidType.Lava;
                                    }
                                }

                                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 && Tile.IsSign(buffer.Tiles[x, y].Type))
                            // 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);
        }
        public void PasteBufferIntoWorld(Vector2Int32 anchor)
        {
            if (Buffer == null)
            {
                return;
            }
            _wvm.Selection.IsActive = false; // clear selection when pasting to prevent "unable to use pencil" issue
            World           world  = _wvm.CurrentWorld;
            ClipboardBuffer buffer = _wvm.Clipboard.Buffer;

            for (int x = 0; x < buffer.Size.X; x++)
            {
                for (int y = 0; y < buffer.Size.Y; y++)
                {
                    int worldX = x + anchor.X;
                    int worldY = y + anchor.Y;

                    if (world.ValidTileLocation(new Vector2Int32(x + anchor.X, y + anchor.Y)))
                    {
                        //HistMan.AddTileToBuffer(x + anchor.X, y + anchor.Y, ref world.UndoTiles[x + anchor.X, y + anchor.Y]);

                        Tile curTile;

                        if (PasteTiles)
                        {
                            curTile           = (Tile)buffer.Tiles[x, y].Clone();
                            curTile.TileColor = buffer.Tiles[x, y].TileColor;
                        }
                        else
                        {
                            // if pasting tiles is disabled, use the existing tile with buffer's wall & extras
                            curTile              = (Tile)world.Tiles[worldX, worldY].Clone();
                            curTile.Wall         = buffer.Tiles[x, y].Wall;
                            curTile.WallColor    = buffer.Tiles[x, y].WallColor;
                            curTile.LiquidAmount = buffer.Tiles[x, y].LiquidAmount;
                            curTile.LiquidType   = buffer.Tiles[x, y].LiquidType;
                            curTile.WireRed      = buffer.Tiles[x, y].WireRed;
                            curTile.WireGreen    = buffer.Tiles[x, y].WireGreen;
                            curTile.WireBlue     = buffer.Tiles[x, y].WireBlue;
                            curTile.WireYellow   = buffer.Tiles[x, y].WireYellow;
                            curTile.Actuator     = buffer.Tiles[x, y].Actuator;
                            curTile.InActive     = buffer.Tiles[x, y].InActive;
                        }

                        if (!PasteEmpty && (curTile.LiquidAmount == 0 && !curTile.IsActive && curTile.Wall == 0 && !curTile.WireRed && !curTile.WireBlue && !curTile.WireGreen && !curTile.WireYellow))
                        {
                            // skip tiles that are empty if paste empty is not true
                            continue;
                        }
                        if (!PasteWalls)
                        {
                            // if pasting walls is disabled, use the existing wall
                            curTile.Wall      = world.Tiles[worldX, worldY].Wall;
                            curTile.WallColor = world.Tiles[worldX, worldY].WallColor;
                        }
                        if (!PasteLiquids)
                        {
                            // if pasting liquids is disabled, use any existing liquid
                            curTile.LiquidAmount = world.Tiles[worldX, worldY].LiquidAmount;
                            curTile.LiquidType   = world.Tiles[worldX, worldY].LiquidType;
                        }
                        if (!PasteWires)
                        {
                            // if pasting wires is disabled, use any existing wire
                            Tile worldTile = world.Tiles[worldX, worldY];
                            curTile.WireRed    = worldTile.WireRed;
                            curTile.WireGreen  = worldTile.WireGreen;
                            curTile.WireBlue   = worldTile.WireBlue;
                            curTile.WireYellow = worldTile.WireYellow;
                            curTile.Actuator   = worldTile.Actuator;
                            curTile.InActive   = worldTile.InActive;
                        }
                        //  Update chest/sign data only if we've pasted tiles
                        if (PasteTiles)
                        {
                            // Remove overwritten chests data
                            if (Tile.IsChest(world.Tiles[x + anchor.X, y + anchor.Y].Type))
                            {
                                var data = world.GetChestAtTile(x + anchor.X, y + anchor.Y);
                                if (data != null)
                                {
                                    _wvm.UndoManager.Buffer.Chests.Add(data);
                                    world.Chests.Remove(data);
                                }
                            }

                            // Remove overwritten sign data
                            if (Tile.IsSign(world.Tiles[x + anchor.X, y + anchor.Y].Type))
                            {
                                var data = world.GetSignAtTile(x + anchor.X, y + anchor.Y);
                                if (data != null)
                                {
                                    _wvm.UndoManager.Buffer.Signs.Add(data);
                                    world.Signs.Remove(data);
                                }
                            }

                            // Remove overwritten tile entity data
                            if (Tile.IsTileEntity(world.Tiles[x + anchor.X, y + anchor.Y].Type))
                            {
                                var data = world.GetTileEntityAtTile(x + anchor.X, y + anchor.Y);
                                if (data != null)
                                {
                                    //    add this function to UndoManager
                                    //    _wvm.UndoManager.Buffer.TileEntities.Add(data);
                                    world.TileEntities.Remove(data);
                                }
                            }


                            // Add new chest data
                            if (Tile.IsChest(curTile.Type))
                            {
                                if (world.GetChestAtTile(x + anchor.X, y + anchor.Y) == null)
                                {
                                    var data = buffer.GetChestAtTile(x, y);
                                    if (data != null) // allow? chest copying may not work...
                                    {
                                        // Copied chest
                                        var newChest = data.Copy();
                                        newChest.X = x + anchor.X;
                                        newChest.Y = y + anchor.Y;
                                        world.Chests.Add(newChest);
                                    }
                                }
                            }

                            // Add new sign data
                            if (Tile.IsSign(curTile.Type))
                            {
                                if (world.GetSignAtTile(x + anchor.X, y + anchor.Y) == null)
                                {
                                    var data = buffer.GetSignAtTile(x, y);
                                    if (data != null)
                                    {
                                        // Copied sign
                                        var newSign = data.Copy();
                                        newSign.X = x + anchor.X;
                                        newSign.Y = y + anchor.Y;
                                        world.Signs.Add(newSign);
                                    }
                                }
                            }

                            // Add new tile entity data
                            if (Tile.IsTileEntity(curTile.Type))
                            {
                                if (world.GetTileEntityAtTile(x + anchor.X, y + anchor.Y) == null)
                                {
                                    var data = buffer.GetTileEntityAtTile(x, y);
                                    if (data != null)
                                    {
                                        // Copied sign
                                        var newEntity = data.Copy();
                                        newEntity.PosX = (short)(x + anchor.X);
                                        newEntity.PosY = (short)(y + anchor.Y);
                                        world.TileEntities.Add(newEntity);
                                    }
                                }
                            }
                        }
                        _wvm.UndoManager.SaveTile(x + anchor.X, y + anchor.Y);
                        world.Tiles[x + anchor.X, y + anchor.Y] = curTile;
                    }
                }
            }
            _wvm.UndoManager.SaveUndo();
            _wvm.CurrentWorld.UpgradeLegacyTileEntities();
            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, anchor.X, anchor.Y, buffer.Size.X, buffer.Size.Y);
        }
        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 == (int)TileType.Platform)
                                    {
                                        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 == (int)TileType.Timer)
                                        {
                                            curTile.V = 0;
                                        }
                                    }
                                    else
                                    {
                                        curTile.U = -1;
                                        curTile.V = -1;
                                    }
                                }

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

                                if (br.ReadBoolean())
                                {
                                    curTile.LiquidType   = LiquidType.Water;
                                    curTile.LiquidAmount = br.ReadByte();
                                    if (br.ReadBoolean()) // lava byte
                                    {
                                        curTile.LiquidType = LiquidType.Lava;
                                    }
                                }

                                curTile.WireRed    = 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);
        }
        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 == (int)TileType.Platform)
                                    {
                                        curTile.U = 0;
                                        curTile.V = 0;
                                    }
                                    else if (World.TileProperties[curTile.Type].IsFramed)
                                    {
                                        curTile.U = reader.ReadInt16();
                                        curTile.V = reader.ReadInt16();

                                        if (curTile.Type == (int)TileType.Timer)
                                        {
                                            curTile.V = 0;
                                        }
                                    }
                                    else
                                    {
                                        curTile.U = -1;
                                        curTile.V = -1;
                                    }
                                }

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

                                if (reader.ReadBoolean())
                                {
                                    curTile.LiquidAmount = reader.ReadByte();
                                    bool lava = reader.ReadBoolean();
                                    curTile.LiquidType = lava ? LiquidType.Lava : LiquidType.Water;
                                }

                                curTile.WireRed    = 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 && Tile.IsSign(buffer.Tiles[x, y].Type))
                            // 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);
                }
            }
        }
        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 == (int)TileType.IceByRod)
                                {
                                    tile.IsActive = false;
                                }

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

                                    if (tile.Type == (int)TileType.Timer)
                                    {
                                        tile.V = 0;
                                    }
                                }
                                else
                                {
                                    tile.U = -1;
                                    tile.V = -1;
                                }

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

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

                            if (b.ReadBoolean())
                            {
                                tile.LiquidType = LiquidType.Water;

                                tile.LiquidAmount = b.ReadByte();
                                bool IsLava = b.ReadBoolean();
                                if (IsLava)
                                {
                                    tile.LiquidType = LiquidType.Lava;
                                }
                                bool IsHoney = b.ReadBoolean();
                                if (IsHoney)
                                {
                                    tile.LiquidType = LiquidType.Honey;
                                }
                            }

                            tile.WireRed   = b.ReadBoolean();
                            tile.WireGreen = b.ReadBoolean();
                            tile.WireBlue  = b.ReadBoolean();

                            bool isHalfBrick = b.ReadBoolean();


                            var brickByte = b.ReadByte();
                            if (tileProperty == null || !tileProperty.IsSolid)
                            {
                                tile.BrickStyle = 0;
                            }
                            else
                            {
                                tile.BrickStyle = (BrickStyle)brickByte;
                            }

                            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 && Tile.IsSign(buffer.Tiles[sign.X, sign.Y].Type))
                            {
                                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);
                }
            }
        }
        private static ClipboardBuffer Load5(BinaryReader b, string name, uint tVersion, int version)
        {
            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 = World.ReadTileDataFromStreamV1(b, tVersion);
                    // 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;
                    }
                }
            }
            buffer.Chests.Clear();
            buffer.Chests.AddRange(World.ReadChestDataFromStreamV1(b, tVersion));

            buffer.Signs.Clear();
            foreach (Sign sign in World.ReadSignDataFromStreamV1(b))
            {
                if (buffer.Tiles[sign.X, sign.Y].IsActive && Tile.IsSign(buffer.Tiles[sign.X, sign.Y].Type))
                {
                    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);
        }
        // Reverse the buffer along the x- or y- axis
        public void Flip(ClipboardBuffer buffer, bool flipX)
        {
            ClipboardBuffer flippedBuffer = new ClipboardBuffer(buffer.Size);
            var             sprites       = new Dictionary <Vector2Int32, Sprite>();

            for (int x = 0, maxX = buffer.Size.X - 1; x <= maxX; x++)
            {
                for (int y = 0, maxY = buffer.Size.Y - 1; y <= maxY; y++)
                {
                    int bufferX;
                    int bufferY;

                    if (flipX)
                    {
                        bufferX = maxX - x;
                        bufferY = y;
                    }
                    else
                    {
                        bufferX = x;
                        bufferY = maxY - y;
                    }

                    Tile         tile           = (Tile)buffer.Tiles[x, y].Clone();
                    var          tileProperties = World.TileProperties[tile.Type];
                    Vector2Short tileSize       = tileProperties.FrameSize;

                    // locate all the sprites and make a list
                    if (tileProperties.IsFramed)
                    {
                        var loc = new Vector2Int32(x, y);
                        var uv  = tile.GetUV();
                        if (tileProperties.IsOrigin(uv, out var frame))
                        {
                            var sprite = World.Sprites.FirstOrDefault(s => s.Tile == tile.Type && s.Origin == uv);
                            sprites[loc] = sprite;
                        }
                    }

                    if (flipX)
                    {
                        //  Ignore multi-width objects when flipping on x-axis
                        if (tileSize.X > 1)
                        {
                            ClearTile(tile);
                        }
                        // Flip brick-style
                        switch (tile.BrickStyle)
                        {
                        case BrickStyle.SlopeTopRight:
                            tile.BrickStyle = BrickStyle.SlopeTopLeft;
                            break;

                        case BrickStyle.SlopeTopLeft:
                            tile.BrickStyle = BrickStyle.SlopeTopRight;
                            break;

                        case BrickStyle.SlopeBottomRight:
                            tile.BrickStyle = BrickStyle.SlopeBottomLeft;
                            break;

                        case BrickStyle.SlopeBottomLeft:
                            tile.BrickStyle = BrickStyle.SlopeBottomRight;
                            break;
                        }
                    }

                    else
                    {
                        //  Ignore multi-height tiles when flipping on y-axis
                        if (tileSize.Y > 1)
                        {
                            ClearTile(tile);
                        }
                        // Flip brick-style
                        switch (tile.BrickStyle)
                        {
                        case BrickStyle.SlopeTopRight:
                            tile.BrickStyle = BrickStyle.SlopeBottomRight;
                            break;

                        case BrickStyle.SlopeTopLeft:
                            tile.BrickStyle = BrickStyle.SlopeBottomLeft;
                            break;

                        case BrickStyle.SlopeBottomRight:
                            tile.BrickStyle = BrickStyle.SlopeTopRight;
                            break;

                        case BrickStyle.SlopeBottomLeft:
                            tile.BrickStyle = BrickStyle.SlopeTopLeft;
                            break;
                        }
                    }

                    flippedBuffer.Tiles[bufferX, bufferY] = (Tile)tile;
                }
            }

            foreach (var sprite in sprites)
            {
                var flipOrigin = FlipSprite(buffer.Size, sprite.Key, sprite.Value.Size, flipX);
                Sprite.PlaceSprite(flipOrigin.X, flipOrigin.Y, sprite.Value, flippedBuffer);
            }

            foreach (var chest in buffer.Chests)
            {
                var flipOrigin = FlipSprite(buffer.Size, new Vector2Int32(chest.X, chest.Y), new Vector2Short(2, 2), flipX);
                chest.X = flipOrigin.X;
                chest.Y = flipOrigin.Y;
                flippedBuffer.Chests.Add(chest);
            }

            foreach (var sign in buffer.Signs)
            {
                var flipOrigin = FlipSprite(buffer.Size, new Vector2Int32(sign.X, sign.Y), new Vector2Short(2, 2), flipX);
                sign.X = flipOrigin.X;
                sign.Y = flipOrigin.Y;
                flippedBuffer.Signs.Add(sign);
            }

            foreach (var te in buffer.TileEntities)
            {
                var          tileProperties = World.TileProperties[(int)te.TileType];
                Vector2Short tileSize       = tileProperties.FrameSize;

                var flipOrigin = FlipSprite(buffer.Size, new Vector2Int32(te.PosX, te.PosY), tileSize, flipX);
                te.PosX = (short)flipOrigin.X;
                te.PosY = (short)flipOrigin.Y;
                flippedBuffer.TileEntities.Add(te);
            }

            // Replace the existing buffer with the new one
            int bufferIndex = LoadedBuffers.IndexOf(buffer);

            if (bufferIndex > -1)
            {
                LoadedBuffers.Insert(bufferIndex, flippedBuffer);
                LoadedBuffers.RemoveAt(bufferIndex + 1);
            }

            flippedBuffer.RenderBuffer();

            if (Buffer == buffer)
            {
                Buffer = flippedBuffer;
                _wvm.PreviewChange();
            }
        }
        public void PasteBufferIntoWorld(Vector2Int32 anchor)
        {
            if (Buffer == null)
            {
                return;
            }
            if (!PasteTiles && !PasteLiquids && !PasteWalls && !PasteWires)
            {
                return;
            }

            ErrorLogging.TelemetryClient?.TrackEvent("Paste");

            _wvm.Selection.IsActive = false; // clear selection when pasting to prevent "unable to use pencil" issue
            World           world  = _wvm.CurrentWorld;
            ClipboardBuffer buffer = _wvm.Clipboard.Buffer;

            for (int x = 0; x < buffer.Size.X; x++)
            {
                for (int y = 0; y < buffer.Size.Y; y++)
                {
                    int worldX = x + anchor.X;
                    int worldY = y + anchor.Y;

                    if (!world.ValidTileLocation(new Vector2Int32(worldX, worldY)))
                    {
                        continue;
                    }

                    //HistMan.AddTileToBuffer(worldX, worldY, ref world.UndoTiles[worldX, worldY]);
                    Tile worldTile = world.Tiles[worldX, worldY];
                    Tile curTile   = (Tile)buffer.Tiles[x, y].Clone();

                    if (!PasteTiles)
                    {
                        curTile.IsActive   = worldTile.IsActive;
                        curTile.Type       = worldTile.Type;
                        curTile.TileColor  = worldTile.TileColor;
                        curTile.U          = worldTile.U;
                        curTile.V          = worldTile.V;
                        curTile.BrickStyle = worldTile.BrickStyle;
                    }

                    if (!PasteEmpty && curTile.IsEmpty)
                    {
                        // skip tiles that are empty if paste empty is not true
                        continue;
                    }

                    if (!PasteWalls)
                    {
                        // if pasting walls is disabled, use the existing wall
                        curTile.Wall      = worldTile.Wall;
                        curTile.WallColor = worldTile.WallColor;
                    }

                    if (!PasteLiquids)
                    {
                        // if pasting liquids is disabled, use any existing liquid
                        curTile.LiquidAmount = worldTile.LiquidAmount;
                        curTile.LiquidType   = worldTile.LiquidType;
                    }

                    if (!PasteWires)
                    {
                        // if pasting wires is disabled, use any existing wire
                        curTile.WireRed    = worldTile.WireRed;
                        curTile.WireGreen  = worldTile.WireGreen;
                        curTile.WireBlue   = worldTile.WireBlue;
                        curTile.WireYellow = worldTile.WireYellow;
                        curTile.Actuator   = worldTile.Actuator;
                        curTile.InActive   = worldTile.InActive;
                    }

                    // save undo
                    _wvm.UndoManager.SaveTile(worldX, worldY);

                    // update world tile
                    world.Tiles[worldX, worldY] = curTile;

                    //  Update chest/sign data only if we've pasted tiles
                    if (PasteTiles)
                    {
                        // Add new chest data
                        if (Tile.IsChest(curTile.Type))
                        {
                            var existingChest = world.GetChestAtTile(worldX, worldY);
                            if (existingChest != null)
                            {
                                world.Chests.Remove(existingChest);
                            }

                            var data = buffer.GetChestAtTile(x, y);
                            if (data != null) // allow? chest copying may not work...
                            {
                                // Copied chest
                                var newChest = data.Copy();
                                newChest.X = worldX;
                                newChest.Y = worldY;
                                world.Chests.Add(newChest);
                            }
                        }

                        // Add new sign data
                        if (Tile.IsSign(curTile.Type))
                        {
                            if (world.GetSignAtTile(worldX, worldY) == null)
                            {
                                var data = buffer.GetSignAtTile(x, y);
                                if (data != null)
                                {
                                    // Copied sign
                                    var newSign = data.Copy();
                                    newSign.X = worldX;
                                    newSign.Y = worldY;
                                    world.Signs.Add(newSign);
                                }
                            }
                        }

                        // Add new tile entity data
                        if (Tile.IsTileEntity(curTile.Type))
                        {
                            if (world.GetTileEntityAtTile(worldX, worldY) == null)
                            {
                                var data = buffer.GetTileEntityAtTile(x, y);
                                if (data != null)
                                {
                                    // Copied sign
                                    var newEntity = data.Copy();
                                    newEntity.PosX = (short)(worldX);
                                    newEntity.PosY = (short)(worldY);
                                    world.TileEntities.Add(newEntity);
                                }
                            }
                        }
                    }
                }
            }

            _wvm.UndoManager.SaveUndo();
            _wvm.CurrentWorld.UpgradeLegacyTileEntities();

            /* Heathtech */
            BlendRules.ResetUVCache(_wvm, anchor.X, anchor.Y, buffer.Size.X, buffer.Size.Y);
        }
Esempio n. 13
0
        // Reverse the buffer along the x- or y- axis
        public void Flip(ClipboardBuffer buffer, bool flipX)
        {
            ClipboardBuffer flippedBuffer = new ClipboardBuffer(buffer.Size);

            for (int x = 0, maxX = buffer.Size.X - 1; x <= maxX; x++)
            {
                for (int y = 0, maxY = buffer.Size.Y - 1; y <= maxY; y++)
                {
                    int bufferX;
                    int bufferY;

                    if (flipX)
                    {
                        bufferX = maxX - x;
                        bufferY = y;
                    }
                    else
                    {
                        bufferX = x;
                        bufferY = maxY - y;
                    }

                    Tile tile = (Tile)buffer.Tiles[x, y].Clone();

                    Vector2Short tileSize = World.TileProperties[tile.Type].FrameSize;

                    if (flipX)
                    {
                        //  Ignore multi-width objects when flipping on x-axis
                        if (tileSize.X > 1)
                        {
                            ClearTile(tile);
                        }
                        // Flip brick-style
                        switch (tile.BrickStyle)
                        {
                        case BrickStyle.SlopeTopRight:
                            tile.BrickStyle = BrickStyle.SlopeTopLeft;
                            break;

                        case BrickStyle.SlopeTopLeft:
                            tile.BrickStyle = BrickStyle.SlopeTopRight;
                            break;

                        case BrickStyle.SlopeBottomRight:
                            tile.BrickStyle = BrickStyle.SlopeBottomLeft;
                            break;

                        case BrickStyle.SlopeBottomLeft:
                            tile.BrickStyle = BrickStyle.SlopeBottomRight;
                            break;
                        }
                    }

                    else
                    {
                        //  Ignore multi-height tiles when flipping on y-axis
                        if (tileSize.Y > 1)
                        {
                            ClearTile(tile);
                        }
                        // Flip brick-style
                        switch (tile.BrickStyle)
                        {
                        case BrickStyle.SlopeTopRight:
                            tile.BrickStyle = BrickStyle.SlopeBottomRight;
                            break;

                        case BrickStyle.SlopeTopLeft:
                            tile.BrickStyle = BrickStyle.SlopeBottomLeft;
                            break;

                        case BrickStyle.SlopeBottomRight:
                            tile.BrickStyle = BrickStyle.SlopeTopRight;
                            break;

                        case BrickStyle.SlopeBottomLeft:
                            tile.BrickStyle = BrickStyle.SlopeTopLeft;
                            break;
                        }
                    }

                    flippedBuffer.Tiles[bufferX, bufferY] = (Tile)tile;
                }
            }

            // Replace the existing buffer with the new one
            int bufferIndex = LoadedBuffers.IndexOf(buffer);

            if (bufferIndex > -1)
            {
                LoadedBuffers.Insert(bufferIndex, flippedBuffer);
                LoadedBuffers.RemoveAt(bufferIndex + 1);
            }

            flippedBuffer.RenderBuffer();

            if (Buffer == buffer)
            {
                Buffer = flippedBuffer;
                _wvm.PreviewChange();
            }
        }