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 ChestEditorPopup(Chest chest) { InitializeComponent(); DataContext = chest.Items; }
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, "")); }
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."); }
public void Validate() { List<string> log = new List<string>(); IsUsingIo = true; var wb = Header.WorldBounds; short[,] deadSpace = new short[wb.Width, wb.Height]; for (int y = wb.Top; y <= wb.Bottom; y++) { OnProgressChanged(this, y, wb.Bottom, "Validating Tiles..."); for (int x = wb.Left; x <= wb.Right; x++) { // skip anything in the dead space if (deadSpace[x,y] > 0) { x += deadSpace[x,y] - 1; continue; } // TODO: Need Frames support // // (All tiles have the size/placement properties, but this may change in the future...) // var tile = Tiles[x, y]; if (!tile.IsActive) continue; // immediate short-circuit var type = tile.Type; var prop = WorldSettings.Tiles[type]; var place = prop.Placement; if (prop.AttachesTo.Count > 0) continue; // can't really handle these yet... if (!ValidatePlacement(new PointInt32(x,y), prop.Size, place)) // validation found a problem { log.Add(string.Format("Tile [{2}] at [{0},{1}] must be placed on {3} {4}", x, y, prop.Name, place.Has(FP.MustHaveAll) ? "all of:" : (place.IsSingular() ? "a" : "any of:"), place.Remove(FP.MustHaveAll))); } // validate chest/sign/NPC entries exist switch (type) { case 21: // Validate Chest if (GetChestAtTile(x, y) == null) { var c = new Chest(new PointInt32(x, y)); for (int i = 0; i < 20; i++) c.Items.Add(new Item(0, "[empty]")); Chests.Add(c); log.Add(string.Format("added empty chest content [{0},{1}]", x, y)); } break; case 55: case 85: // Validate Sign/Tombstone if (GetSignAtTile(x, y) == null) { Signs.Add(new Sign("", new PointInt32(x, y))); log.Add(string.Format("added blank sign text [{0},{1}]", x, y)); } break; } // TODO: validate the frame exists completely // // assuming the left-right scan, it should hit the top-left corner first // thus, we skip around the rest of the frame for the x-axis // y-axis is a little bit more difficult... (and it requires that x stay put for a bit) if (prop.Size.Y > 1) { for (int s = 1; s < prop.Size.Y; s++) { deadSpace[x,y+s] = prop.Size.X; } } if (prop.Size.X > 1) x += prop.Size.X - 1; } } var p = 0; OnProgressChanged(this, "Validating Chests..."); foreach (var chest in Chests.ToList()) { var loc = chest.Location; int locType = Tiles[loc.X, loc.Y].Type; if (locType != 21) { Chests.Remove(chest); log.Add(string.Format("removed missing chest {0}", loc)); } OnProgressChanged(this, ++p, Chests.Count); } p = 0; OnProgressChanged(this, "Validating Signs..."); foreach (var sign in Signs.ToList()) { var loc = sign.Location; int locType = Tiles[loc.X, loc.Y].Type; if (locType != 55 && locType != 85) { Signs.Remove(sign); log.Add(string.Format("removed missing sign {0}", loc)); } OnProgressChanged(this, ++p, Signs.Count); } foreach (NPC npc in Npcs) { // no validation yet... // (SS: Okay, this is now in the XML; just need to port that stuff over) } IsUsingIo = false; OnProgressChanged(this, 100, 100, "Validation Complete."); log.Add("FINISHED with Validation!"); ErrorLogging.Log(string.Join(Environment.NewLine, log.ToArray())); }
public ChestsContentsPopup(Chest chest) { InitializeComponent(); this.DataContext = chest.Items; }
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."); }
public void Validate() { List <string> log = new List <string>(); IsUsingIo = true; var wb = Header.WorldBounds; short[,] deadSpace = new short[wb.Width, wb.Height]; for (int y = wb.Top; y <= wb.Bottom; y++) { OnProgressChanged(this, y, wb.Bottom, "Validating Tiles..."); for (int x = wb.Left; x <= wb.Right; x++) { // skip anything in the dead space if (deadSpace[x, y] > 0) { x += deadSpace[x, y] - 1; continue; } // TODO: Need Frames support // // (All tiles have the size/placement properties, but this may change in the future...) // var tile = Tiles[x, y]; if (!tile.IsActive) { continue; // immediate short-circuit } var type = tile.Type; var prop = WorldSettings.Tiles[type]; var place = prop.Placement; if (prop.AttachesTo.Count > 0) { continue; // can't really handle these yet... } if (!ValidatePlacement(new PointInt32(x, y), prop.Size, place)) // validation found a problem { log.Add(string.Format("Tile [{2}] at [{0},{1}] must be placed on {3} {4}", x, y, prop.Name, place.Has(FP.MustHaveAll) ? "all of:" : (place.IsSingular() ? "a" : "any of:"), place.Remove(FP.MustHaveAll))); } // validate chest/sign/NPC entries exist switch (type) { case 21: // Validate Chest if (GetChestAtTile(x, y) == null) { var c = new Chest(new PointInt32(x, y)); for (int i = 0; i < 20; i++) { c.Items.Add(new Item(0, "[empty]")); } Chests.Add(c); log.Add(string.Format("added empty chest content [{0},{1}]", x, y)); } break; case 55: case 85: // Validate Sign/Tombstone if (GetSignAtTile(x, y) == null) { Signs.Add(new Sign("", new PointInt32(x, y))); log.Add(string.Format("added blank sign text [{0},{1}]", x, y)); } break; } // TODO: validate the frame exists completely // // assuming the left-right scan, it should hit the top-left corner first // thus, we skip around the rest of the frame for the x-axis // y-axis is a little bit more difficult... (and it requires that x stay put for a bit) if (prop.Size.Y > 1) { for (int s = 1; s < prop.Size.Y; s++) { deadSpace[x, y + s] = prop.Size.X; } } if (prop.Size.X > 1) { x += prop.Size.X - 1; } } } var p = 0; OnProgressChanged(this, "Validating Chests..."); foreach (var chest in Chests.ToList()) { var loc = chest.Location; int locType = Tiles[loc.X, loc.Y].Type; if (locType != 21) { Chests.Remove(chest); log.Add(string.Format("removed missing chest {0}", loc)); } OnProgressChanged(this, ++p, Chests.Count); } p = 0; OnProgressChanged(this, "Validating Signs..."); foreach (var sign in Signs.ToList()) { var loc = sign.Location; int locType = Tiles[loc.X, loc.Y].Type; if (locType != 55 && locType != 85) { Signs.Remove(sign); log.Add(string.Format("removed missing sign {0}", loc)); } OnProgressChanged(this, ++p, Signs.Count); } foreach (NPC npc in Npcs) { // no validation yet... // (SS: Okay, this is now in the XML; just need to port that stuff over) } IsUsingIo = false; OnProgressChanged(this, 100, 100, "Validation Complete."); log.Add("FINISHED with Validation!"); ErrorLogging.Log(string.Join(Environment.NewLine, log.ToArray())); }