public string GetTileName(Tile tile, out string wall)
        {
            string tilename = String.Empty;
            wall = Settings.Walls[tile.Wall].Name;

            if (!tile.IsActive)
                return "[empty]";

            if (tile.Liquid > 0)
            {
                if (tile.IsLava)
                    tilename = String.Format("Lava({0})", tile.Liquid);
                else
                    tilename = String.Format("Water({0})", tile.Liquid);
            }
            else
            {
                tilename = Settings.Tiles[tile.Type].Name;
            }

            return tilename;
        }
Beispiel #2
0
 private static bool matchFields(Tile a, Tile other)
 {
     return a.IsActive == other.IsActive &&
            a.Type == other.Type &&
            a.Wall == other.Wall &&
            a.IsLighted == other.IsLighted &&
            a.Liquid == other.Liquid &&
            a.IsLava == other.IsLava &&
            a.Frame == other.Frame;
 }
        public void Load(string filename)
        {
            CanUseFileIO = false;
            string ext = Path.GetExtension(filename);
            if (!string.Equals(ext, ".wld", StringComparison.CurrentCultureIgnoreCase))
                throw new ApplicationException("Invalid file");

            ClearWorld();

            using (var stream = new FileStream(filename, FileMode.Open))
            {
                using (var reader = new BinaryReader(stream))
                {
                    int version = reader.ReadInt32();
                    if (version > CompatableVersion)
                    {
                        // handle version
                    }
                    Header.FileVersion = version;
                    Header.FileName = filename;
                    Header.WorldName = reader.ReadString();
                    Header.WorldId = reader.ReadInt32();
                    Header.WorldBounds = new RectF(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(),
                                                   reader.ReadInt32());
                    int maxy = reader.ReadInt32();
                    int maxx = reader.ReadInt32();
                    Header.MaxTiles = new PointInt32(maxx, maxy);
                    ClearWorld();
                    Header.SpawnTile = new PointInt32(reader.ReadInt32(), reader.ReadInt32());
                    Header.WorldSurface = reader.ReadDouble();
                    Header.WorldRockLayer = reader.ReadDouble();
                    Header.Time = reader.ReadDouble();
                    Header.IsDayTime = reader.ReadBoolean();
                    Header.MoonPhase = reader.ReadInt32();
                    Header.IsBloodMoon = reader.ReadBoolean();
                    Header.DungeonEntrance = new PointInt32(reader.ReadInt32(), reader.ReadInt32());
                    Header.IsBossDowned1 = reader.ReadBoolean();
                    Header.IsBossDowned2 = reader.ReadBoolean();
                    Header.IsBossDowned3 = reader.ReadBoolean();
                    Header.IsShadowOrbSmashed = reader.ReadBoolean();
                    Header.IsSpawnMeteor = reader.ReadBoolean();
                    Header.ShadowOrbCount = reader.ReadByte();
                    Header.InvasionDelay = reader.ReadInt32();
                    Header.InvasionSize = reader.ReadInt32();
                    Header.InvasionType = reader.ReadInt32();
                    Header.InvasionX = reader.ReadDouble();

                    for (int x = 0; x < Header.MaxTiles.X; x++)
                    {
                        OnProgressChanged(this,
                                          new ProgressChangedEventArgs((int) ((double) x/Header.MaxTiles.X*100.0),
                                                                       "Loading Tiles"));

                        for (int y = 0; y < Header.MaxTiles.Y; y++)
                        {
                            var tile = new Tile();

                            tile.IsActive = reader.ReadBoolean();

                            if (tile.IsActive)
                            {
                                tile.Type = reader.ReadByte();
                                if (TileProperties.TileFrameImportant[tile.Type])
                                    tile.Frame = new PointShort(reader.ReadInt16(), reader.ReadInt16());
                                else
                                    tile.Frame = new PointShort(-1, -1);
                            }

                            tile.IsLighted = reader.ReadBoolean();

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

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

                            Tiles[x, y] = tile;
                        }
                    }

                    for (int chestIndex = 0; chestIndex < MaxChests; chestIndex++)
                    {
                        OnProgressChanged(this,
                                          new ProgressChangedEventArgs((int) ((double) chestIndex/MaxChests*100.0),
                                                                       "Loading Chest Data"));

                        if (reader.ReadBoolean())
                        {
                            var chest = new Chest();
                            chest.Location = new PointInt32(reader.ReadInt32(), reader.ReadInt32());

                            for (int slot = 0; slot < Chest.MaxItems; slot++)
                            {
                                var item = new Item();
                                byte stackSize = reader.ReadByte();
                                if (stackSize > 0)
                                {
                                    string itemName = reader.ReadString();
                                    item.Name = itemName;
                                    item.StackSize = stackSize;
                                }
                                chest.Items.Add(item);
                            }

                            //Chests[chestIndex] = chest;
                            Chests.Add(chest);
                        }
                    }
                    for (int signIndex = 0; signIndex < MaxSigns; signIndex++)
                    {
                        OnProgressChanged(this,
                                          new ProgressChangedEventArgs((int) ((double) signIndex/MaxSigns*100.0),
                                                                       "Loading Sign Data"));

                        if (reader.ReadBoolean())
                        {
                            string signText = reader.ReadString();
                            int x = reader.ReadInt32();
                            int y = reader.ReadInt32();
                            if (Tiles[x, y].IsActive && (Tiles[x, y].Type == 55 || Tiles[x, y].Type == 85))
                                // validate tile location
                            {
                                var sign = new Sign();
                                sign.Location = new PointInt32(x, y);
                                sign.Text = signText;

                                //Signs[signIndex] = sign;
                                Signs.Add(sign);
                            }
                        }
                    }

                    bool isNpcActive = reader.ReadBoolean();
                    for (int npcIndex = 0; isNpcActive; npcIndex++)
                    {
                        OnProgressChanged(this, new ProgressChangedEventArgs(100, "Loading NPCs"));
                        var npc = new NPC();

                        npc.Name = reader.ReadString();
                        npc.Position = new PointFloat(reader.ReadSingle(), reader.ReadSingle());
                        npc.IsHomeless = reader.ReadBoolean();
                        npc.HomeTile = new PointInt32(reader.ReadInt32(), reader.ReadInt32());

                        //Npcs[npcIndex] = npc;
                        Npcs.Add(npc);
                        isNpcActive = reader.ReadBoolean();
                    }

                    if (Header.FileVersion > 7)
                    {
                        OnProgressChanged(this, new ProgressChangedEventArgs(100, "Checking format"));
                        bool test = reader.ReadBoolean();
                        string worldNameCheck = reader.ReadString();
                        int worldIdCheck = reader.ReadInt32();
                        if (!(test && string.Equals(worldNameCheck, Header.WorldName) && worldIdCheck == Header.WorldId))
                        {
                            // Test FAILED!
                            throw new ApplicationException("Invalid World File");
                        }
                    }

                    reader.Close();
                }
            }
            CanUseFileIO = true;
            OnProgressChanged(this, new ProgressChangedEventArgs(0, ""));
        }
        private Color GetTileColor(int y, Tile tile)
        {
            Color c;

            if (tile.Wall > 0)
            {
                c = WorldSettings.Walls[tile.Wall].Color;
            }
            else
            {
                if (y >= _world.Header.WorldBounds.Bottom - 192)
                    c = WorldSettings.GlobalColors["Hell"].Color;
                else if (y > _world.Header.WorldRockLayer && tile.Wall == 0)
                    c = WorldSettings.GlobalColors["Rock"].Color;
                else if (y > _world.Header.WorldSurface && tile.Wall == 0)
                    c = WorldSettings.GlobalColors["Earth"].Color;
                else
                    c = WorldSettings.GlobalColors["Sky"].Color;
            }

            if (tile.IsActive)
                c = c.AlphaBlend(WorldSettings.Tiles[tile.Type].Color);

            if (tile.Liquid > 0)
            {
                if (tile.IsLava)
                    c = c.AlphaBlend(WorldSettings.GlobalColors["Lava"].Color);
                else
                    c = c.AlphaBlend(WorldSettings.GlobalColors["Water"].Color);
            }
            return c;
        }
Beispiel #5
0
        public bool Equals(Tile p)
        {
            // If parameter is null return false:
            if ((object)p == null)
            {
                return false;
            }

            // Return true if the fields match:
            return matchFields(this, p);
        }
        public void NewWorld(int width, int height, int seed = -1)
        {
            var genRand = seed <= 0 ? new Random((int)DateTime.Now.Ticks) : new Random(seed);
            IsValid = false;
            IsUsingIo = true;
            IsSaved = false;

            Header.FileVersion = CompatableVersion;
            Header.FileName = "";
            Header.WorldName = "TEdit World";
            Header.WorldId = genRand.Next(int.MaxValue);

            Header.WorldBounds = new RectI(0, width - 1, 0, height - 1);
            var wb = Header.WorldBounds;

            ClearWorld();
            Header.SpawnTile = new PointInt32(width / 2, height / 3);
            Header.WorldSurface = height / 3;
            Header.WorldRockLayer = 2 * height / 3;
            Header.Time = 13500;
            Header.IsDayTime = true;
            Header.MoonPhase = 0;
            Header.IsBloodMoon = false;
            Header.DungeonEntrance = new PointInt32(width / 5, height / 3);
            Header.IsBossDowned1 = false;
            Header.IsBossDowned2 = false;
            Header.IsBossDowned3 = false;
            Header.IsShadowOrbSmashed = false;
            Header.IsSpawnMeteor = false;
            Header.ShadowOrbCount = 0;
            Header.InvasionDelay = 0;
            Header.InvasionSize = 0;
            Header.InvasionType = 0;
            Header.InvasionX = 0;
            ClearWorld();
            ResetTime();

            for (int x = wb.Left; x <= wb.Right; x++) {
                OnProgressChanged(this, x, wb.Right, "Loading Tiles...");

                for (int y = wb.Top; y <= wb.Bottom; y++) {
                    Tiles[x, y] = new Tile();
                }
            }
            IsValid = true;
            IsUsingIo = false;
        }
        private BytePixels GetTextureLayer(string layerType, int y, Tile tile)
        {
            var size   = 8;
            var sizeI  = new SizeInt32(size, size);
            var pixels = new BytePixels(sizeI, 4);
            var rect00 = new RectI(0, 0, sizeI);
            string key = String.Empty;

            switch (layerType)
            {
                case "TilePixel":
                    Color c = GetTileColor(y, tile);

                    var b = new byte[4];
                    b[0] = c.B;
                    b[1] = c.G;
                    b[2] = c.R;
                    b[3] = c.A;
                    pixels = new BytePixels(1, 1, b);
                    break;

                case "Wall":
                    key = GetTileKey(y, tile, 'W');
                    if (textureCache.Contains(key)) return (BytePixels)textureCache.Get(key);

                    // FIXME: A complete wall is actually 16x16 big, with 3x3 variations, depending how many tiles exist //
                    if (tile.Wall > 0)
                        pixels = WorldSettings.Walls[tile.Wall].Texture.GetData(new RectI(166, 58, sizeI));  // tile with most coverage (will be eventually replaced per FIXME)
                    else {
                        // FIXME: These are actually pretty large bitmaps //
                        // Might need to go on a WallsBack layer... //

                        if (y >= _world.Header.WorldBounds.Bottom - 192)
                            pixels = WorldSettings.GlobalColors["Hell"].Texture.GetData(rect00);
                        else if (y > _world.Header.WorldRockLayer)
                            pixels = WorldSettings.GlobalColors["Rock"].Texture.GetData(rect00);
                        else if (y > _world.Header.WorldSurface)
                            pixels = WorldSettings.GlobalColors["Earth"].Texture.GetData(rect00);
                        else
                            pixels = WorldSettings.GlobalColors["Sky"].Texture.GetData(rect00);
                    }
                    break;

                case "TileBack":
                    key = GetTileKey(y, tile, 'T');
                    if (textureCache.Contains(key)) return (BytePixels)textureCache.Get(key);

                    // FIXME: Need XML property for larger than 8x8 sizes
                    if (tile.IsActive && !WorldSettings.Tiles[tile.Type].IsSolid) {
                        var rect = (WorldSettings.Tiles[tile.Type].IsFramed) ?
                            new RectI(tile.Frame.X / 2, tile.Frame.Y / 2, sizeI) :
                            rect00;
                        pixels = WorldSettings.Tiles[tile.Type].Texture.GetData(rect);
                    }
                    break;

                // FIXME: NPC layer would go here... //

                case "TileFront":
                    key = GetTileKey(y, tile, 'T');
                    if (textureCache.Contains(key)) return (BytePixels)textureCache.Get(key);

                    // FIXME: Need XML property for larger than 8x8 sizes
                    if (tile.IsActive && WorldSettings.Tiles[tile.Type].IsSolid) {
                        var rect = (WorldSettings.Tiles[tile.Type].IsFramed) ?
                            new RectI(tile.Frame.X / 2, tile.Frame.Y / 2, sizeI) :
                            rect00;
                        pixels = WorldSettings.Tiles[tile.Type].Texture.GetData(rect);
                    }
                    break;

                case "Liquid":
                    key = GetTileKey(y, tile, 'L');
                    if (textureCache.Contains(key)) return (BytePixels)textureCache.Get(key);

                    if (tile.Liquid > 0) {
                        // Should use Liquid levels to determine final height //
                        // Actually, bottom 4x4 should be for 255, and top 4x4 for anything else //
                        if (tile.IsLava)
                            pixels = WorldSettings.GlobalColors["Lava"].Texture.GetData(rect00);
                        else
                            pixels = WorldSettings.GlobalColors["Water"].Texture.GetData(rect00);
                    }
                    break;
            }

            // Cache policy for new cache items
            var cachePolicy = new CacheItemPolicy();
            cachePolicy.SlidingExpiration = new TimeSpan(0, 5, 0);  // 5 minute duration if not used
            if (shortKeyRegEx.IsMatch(key)) cachePolicy.Priority = CacheItemPriority.NotRemovable;  // single unframed tiles and walls get perma-cached

            textureCache.Add(key, pixels, cachePolicy);
            return pixels;
        }
 public ClipboardBuffer(PointInt32 size)
 {
     Size = size;
     Tiles = new Tile[size.X, size.Y];
 }
        public string GetTileKey(int y, Tile tile, char type = '*')
        {
            string key = String.Empty;

            // Walls
            if (type == '*' || type == 'W') {
                key += "W";
                if (tile.Wall > 0) key += tile.Wall;
                else {  // FIXME: These are actually pretty large bitmaps with multiple 8x8 spans //
                    if (y >= _world.Header.WorldBounds.Bottom - 192) key += "h";
                    else if (y > _world.Header.WorldRockLayer && tile.Wall == 0) key += "r";
                    else if (y > _world.Header.WorldSurface   && tile.Wall == 0) key += "e";
                    else key += "s";
                }
            }

            if (type == '*' || type == 'T') {
                // Tiles
                if (tile.IsActive) key += "T" + tile.Type;

                // Frames
                if (WorldSettings.Tiles[tile.Type].IsFramed) key += "F" + tile.Frame.X + "," + tile.Frame.Y;
            }

            // FIXME: NPC layer would go here... //

            // Liquid
            if ((type == '*' || type == 'L') && tile.Liquid > 0) {
                key += "L";

                if (tile.IsLava) key += "l" + tile.Liquid;
                else             key += "w" + tile.Liquid;
            }

            return key;
        }
Beispiel #10
0
        private void LinearFloodFill(ref int x, ref int y, ref TilePicker tp, ref Tile originTile)
        {
            int bitmapWidth = _world.Header.MaxTiles.X;
            int bitmapHeight = _world.Header.MaxTiles.Y;

            //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 (HistMan.SaveHistory)
                    HistMan.AddTileToBuffer(lFillLoc, y, ref _world.Tiles[x, y]);
                _world.SetTileXY(ref lFillLoc, ref y, ref tp, ref _selection);
                tilesChecked[tileIndex] = true;

                lFillLoc--;
                tileIndex--;
                if (lFillLoc <= 0 || tilesChecked[tileIndex] || !CheckTileMatch(ref originTile, ref _world.Tiles[lFillLoc, y], ref tp) || !_selection.IsValid(new PointInt32(lFillLoc, y)))
                    break;			 	 //exit loop if we're at edge of bitmap or color area

            }
            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 (HistMan.SaveHistory)
                    HistMan.AddTileToBuffer(rFillLoc, y, ref _world.Tiles[x, y]);
                _world.SetTileXY(ref rFillLoc, ref y, ref tp, ref _selection);
                tilesChecked[tileIndex] = true;

                rFillLoc++;
                tileIndex++;
                if (rFillLoc >= bitmapWidth || tilesChecked[tileIndex] || !CheckTileMatch(ref originTile, ref _world.Tiles[rFillLoc, y], ref tp) || !_selection.IsValid(new PointInt32(rFillLoc, y)))
                    break;			 	 //exit loop if we're at edge of bitmap or color area

            }
            rFillLoc--;
            if (rFillLoc > maxX)
                maxX = rFillLoc;

            FloodFillRange r = new FloodFillRange(lFillLoc, rFillLoc, y);
            ranges.Enqueue(ref r);
        }
        public void NewWorld(int width, int height, int seed = -1)
        {
            var genRand = seed <= 0 ? new Random((int)DateTime.Now.Ticks) : new Random(seed);

            Header.FileVersion = CompatableVersion;
            Header.FileName = "";
            Header.WorldName = "TEdit World";
            Header.WorldId = genRand.Next(int.MaxValue);

            Header.WorldBounds = new RectF(0, width, 0, height);
            Header.MaxTiles = new PointInt32(width, height);
            ClearWorld();
            Header.SpawnTile = new PointInt32(width / 2, height / 3);
            Header.WorldSurface = height / 3;
            Header.WorldRockLayer = 2 * height / 3;
            Header.Time = 13500;
            Header.IsDayTime = true;
            Header.MoonPhase = 0;
            Header.IsBloodMoon = false;
            Header.DungeonEntrance = new PointInt32(width / 5, height / 3);
            Header.IsBossDowned1 = false;
            Header.IsBossDowned2 = false;
            Header.IsBossDowned3 = false;
            Header.IsShadowOrbSmashed = false;
            Header.IsSpawnMeteor = false;
            Header.ShadowOrbCount = 0;
            Header.InvasionDelay = 0;
            Header.InvasionSize = 0;
            Header.InvasionType = 0;
            Header.InvasionX = 0;
            ClearWorld();
            ResetTime();

            for (int x = 0; x < Header.MaxTiles.X; x++)
            {
                OnProgressChanged(this,
                                  new ProgressChangedEventArgs((int)((double)x / Header.MaxTiles.X * 100.0),
                                                               "Loading Tiles"));

                for (int y = 0; y < Header.MaxTiles.Y; y++)
                {
                    Tiles[x, y] = new Tile();
                }
            }
        }
Beispiel #12
0
        private static bool CheckTileMatch(ref Tile originTile, ref Tile nextTile, ref TilePicker tp)
        {
            if ((tp.Tile.IsActive) && (originTile.Type != nextTile.Type))
                return false;
            if ((tp.Tile.IsActive) && (originTile.IsActive != nextTile.IsActive))
                return false;

            if ((tp.Tile.IsActive) && (originTile.IsActive != nextTile.IsActive))
                return false;

            if ((tp.Wall.IsActive) && (originTile.Wall != nextTile.Wall))
                return false;

            if (tp.Liquid.IsActive)
            {
                if ((originTile.Liquid > 0) != (nextTile.Liquid > 0))
                    return false;

                if (originTile.IsLava != nextTile.IsLava)
                    return false;

                if (originTile.Type != nextTile.Type)
                    return false;

                if (originTile.IsActive != nextTile.IsActive)
                    return false;
            }

            return true;
        }
 public void AddTileToBuffer(int x, int y, ref Tile tile)
 {
     // pass by ref to avoid as much garbage
     if (_SaveHistory)
         buffer.Enqueue(new HistoryTile(new PointInt32(x, y), (Tile)tile.Clone()));
 }
Beispiel #14
0
        public void Load(string filename)
        {
            string ext = Path.GetExtension(filename);
            if (!(string.Equals(ext, ".wld", StringComparison.CurrentCultureIgnoreCase) ||
                  string.Equals(ext, ".bak", StringComparison.CurrentCultureIgnoreCase) ||
                  string.Equals(ext, ".Tedit", StringComparison.CurrentCultureIgnoreCase)))
                throw new ApplicationException("Invalid file");

            IsUsingIo = true;
            IsValid = false;
            ClearWorld();

            using (var stream = new FileStream(filename, FileMode.Open))
            {
                using (var reader = new BinaryReader(stream))
                {
                    int version = reader.ReadInt32();
                    if (version > CompatableVersion)
                    {
                        // handle version
                    }
                    Header.FileVersion = version;
                    Header.FileName = filename;
                    Header.WorldName = reader.ReadString();
                    Header.WorldId = reader.ReadInt32();

                    // WorldBounds (within the file) is measured in frame units (1/2 of a pixel), while MaxTiles is measured in tiles
                    // We force everything into whole tiles, and ditch the redundant MaxTiles
                    // (Also, WorldBounds actually uses W/H, so it is really -1 for right/bottom, in an inclusive-based XY system.)
                    Header.WorldBounds = new RectI(reader.ReadInt32(), reader.ReadInt32() - 1, reader.ReadInt32(), reader.ReadInt32() - 1)
                                       / new RectI(16, 16, new SizeInt32(16, 16));
                    reader.ReadInt32();  // max Y
                    reader.ReadInt32();  // max X
                    var wb = Header.WorldBounds;

                    ClearWorld();
                    Header.SpawnTile = new PointInt32(reader.ReadInt32(), reader.ReadInt32());
                    Header.WorldSurface = reader.ReadDouble();
                    Header.WorldRockLayer = reader.ReadDouble();
                    Header.Time = reader.ReadDouble();
                    Header.IsDayTime = reader.ReadBoolean();
                    Header.MoonPhase = reader.ReadInt32();
                    Header.IsBloodMoon = reader.ReadBoolean();
                    Header.DungeonEntrance = new PointInt32(reader.ReadInt32(), reader.ReadInt32());
                    Header.IsBossDowned1 = reader.ReadBoolean();
                    Header.IsBossDowned2 = reader.ReadBoolean();
                    Header.IsBossDowned3 = reader.ReadBoolean();
                    Header.IsShadowOrbSmashed = reader.ReadBoolean();
                    Header.IsSpawnMeteor = reader.ReadBoolean();
                    Header.ShadowOrbCount = reader.ReadByte();
                    Header.InvasionDelay = reader.ReadInt32();
                    Header.InvasionSize = reader.ReadInt32();
                    Header.InvasionType = reader.ReadInt32();
                    Header.InvasionX = reader.ReadDouble();

                    for (int x = wb.Left; x <= wb.Right; x++) {
                        OnProgressChanged(this, x, wb.Right, "Loading Tiles...");

                        for (int y = wb.Top; y <= wb.Bottom; y++) {
                            var tile = new Tile();

                            tile.IsActive = reader.ReadBoolean();

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

                                if (WorldSettings.Tiles[tile.Type].IsFramed)
                                    tile.Frame = new PointShort(reader.ReadInt16(), reader.ReadInt16());
                                else
                                    tile.Frame = new PointShort(-1, -1);
                            }
                            tile.IsLighted = reader.ReadBoolean();
                            if (reader.ReadBoolean())
                            {
                                tile.Wall = reader.ReadByte();
                            }

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

                            Tiles[x, y] = tile;
                        }
                    }

                    for (int chestIndex = 0; chestIndex < MaxChests; chestIndex++)
                    {
                        OnProgressChanged(this, chestIndex, MaxChests, "Loading Chest Data...");

                        if (reader.ReadBoolean())
                        {
                            var chest = new Chest();
                            chest.Location = new PointInt32(reader.ReadInt32(), reader.ReadInt32());

                            for (int slot = 0; slot < Chest.MaxItems; slot++)
                            {
                                var item = new Item();
                                byte stackSize = reader.ReadByte();
                                if (stackSize > 0)
                                {
                                    string itemName = reader.ReadString();
                                    item.ItemName = itemName;
                                    item.StackSize = stackSize;
                                }
                                chest.Items.Add(item);
                            }

                            Chests.Add(chest);
                        }
                    }
                    for (int signIndex = 0; signIndex < MaxSigns; signIndex++)
                    {
                        OnProgressChanged(this, signIndex, MaxSigns, "Loading Sign Data...");

                        if (reader.ReadBoolean())
                        {
                            string signText = reader.ReadString();
                            int x = reader.ReadInt32();
                            int y = reader.ReadInt32();
                            if (Tiles[x, y].IsActive && (Tiles[x, y].Type == 55 || Tiles[x, y].Type == 85))
                            // validate tile location
                            {
                                var sign = new Sign();
                                sign.Location = new PointInt32(x, y);
                                sign.Text = signText;

                                Signs.Add(sign);
                            }
                        }
                    }

                    bool isNpcActive = reader.ReadBoolean();
                    for (int npcIndex = 0; isNpcActive; npcIndex++)
                    {
                        OnProgressChanged(this, npcIndex, MaxNpcs, "Loading NPCs...");
                        var npc = new NPC();

                        npc.Name = reader.ReadString();
                        npc.Position = new PointFloat(reader.ReadSingle(), reader.ReadSingle());
                        npc.IsHomeless = reader.ReadBoolean();
                        npc.HomeTile = new PointInt32(reader.ReadInt32(), reader.ReadInt32());

                        Npcs.Add(npc);
                        isNpcActive = reader.ReadBoolean();
                    }

                    if (Header.FileVersion > 7)
                    {
                        OnProgressChanged(this, 100, 100, "Checking format...");
                        bool test = reader.ReadBoolean();
                        string worldNameCheck = reader.ReadString();
                        int worldIdCheck = reader.ReadInt32();
                        if (!(test && string.Equals(worldNameCheck, Header.WorldName) && worldIdCheck == Header.WorldId))
                        {
                            // Test FAILED!
                            IsUsingIo = false;
                            reader.Close();
                            throw new ApplicationException("Invalid World File");
                        }
                    }

                    reader.Close();
                }
            }
            IsValid = true;
            IsUsingIo = false;
            IsSaved = true;
            OnProgressChanged(this, 100, 100, "Loading Complete.");
        }
        private Color GetTileColor(int y, Tile tile, bool isHell = false)
        {
            Color c;

            if (isHell)
                c = Settings.Walls[13].Color;
            else if (y > _world.Header.WorldRockLayer && tile.Wall == 0)
                c = Settings.Walls[1].Color;
            else if (y > _world.Header.WorldSurface && tile.Wall == 0)
                c = Settings.Walls[2].Color;
            else
                c = Settings.Walls[tile.Wall].Color;

            if (tile.IsActive)
                c = AlphaBlend(c, Settings.Tiles[tile.Type].Color);

            if (tile.Liquid > 0)
            {
                if (tile.IsLava)
                    c = AlphaBlend(c, Settings.Lava);
                else
                    c = AlphaBlend(c, Settings.Water);
            }
            return c;
        }
        private BytePixels GetTexture(int y, Tile tile)
        {
            var key = GetTileKey(y, tile);
            if (textureCache.Contains(key)) return (BytePixels)textureCache.Get(key);

            // Cache the new item with properties
            var cachePolicy = new CacheItemPolicy();
            cachePolicy.SlidingExpiration = new TimeSpan(0, 1, 0);  // 60 second duration if not used
            if (shortKeyRegEx.IsMatch(key)) cachePolicy.Priority = CacheItemPriority.NotRemovable;  // single unframed tiles and walls get perma-cached

            // Texture blending
            var pixels = GetTextureLayer("Wall", y, tile);
            if (tile.IsActive)
                pixels = pixels.AlphaBlend( GetTextureLayer(WorldSettings.Tiles[tile.Type].IsSolid ? "TileFront" : "TileBack", y, tile) );  // FIXME: NPCs go in-between here
            if (tile.Liquid > 0)
                pixels = pixels.AlphaBlend( GetTextureLayer("Liquid", y, tile) );

            textureCache.Add(key, pixels, cachePolicy);
            return pixels;
        }
        public static ClipboardBuffer Load(string filename)
        {
            using (var stream = new FileStream(filename, FileMode.Open))
            {
                using (var reader = new BinaryReader(stream))
                {
                    int maxx = reader.ReadInt32();
                    int maxy = reader.ReadInt32();

                    var buffer = new ClipboardBuffer(new PointInt32(maxx, maxy));
                    buffer.Name = Path.GetFileNameWithoutExtension(filename);

                    for (int x = 0; x < buffer.Size.W; x++)
                    {
                        for (int y = 0; y < buffer.Size.H; y++)
                        {
                            var tile = new Tile();

                            tile.IsActive = reader.ReadBoolean();

                            if (tile.IsActive)
                            {
                                tile.Type = reader.ReadByte();
                                if (WorldSettings.Tiles[tile.Type].IsFramed)
                                    tile.Frame = new PointShort(reader.ReadInt16(), reader.ReadInt16());
                                else
                                    tile.Frame = new PointShort(-1, -1);
                            }

                            tile.IsLighted = 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;
                        }
                    }

                    for (int chestIndex = 0; chestIndex < World.MaxChests; chestIndex++)
                    {
                        if (reader.ReadBoolean())
                        {
                            var chest = new Chest();
                            chest.Location = new PointInt32(reader.ReadInt32(), reader.ReadInt32());

                            for (int slot = 0; slot < Chest.MaxItems; slot++)
                            {
                                var item = new Item();
                                byte stackSize = reader.ReadByte();
                                if (stackSize > 0)
                                {
                                    string itemName = reader.ReadString();
                                    item.ItemName = itemName;
                                    item.StackSize = stackSize;
                                }
                                chest.Items.Add(item);
                            }

                            //Chests[chestIndex] = chest;
                            buffer.Chests.Add(chest);
                        }
                    }
                    for (int signIndex = 0; signIndex < World.MaxSigns; 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();
                                sign.Location = new PointInt32(x, y);
                                sign.Text = 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 ClipboardBuffer(SizeInt32 size)
 {
     Size = size;
     Tiles = new Tile[size.W, size.H];
 }