PageRenderTime 231ms CodeModel.GetById 166ms app.highlight 55ms RepoModel.GetById 2ms app.codeStats 0ms

/WorldView/Structures/World.cs

#
C# | 2079 lines | 1627 code | 383 blank | 69 comment | 393 complexity | 9320b8e9ac930749697fdff674978f91 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1using System;
   2using System.Collections.Generic;
   3using System.IO;
   4using System.Drawing;
   5using System.ComponentModel;
   6using System.Timers;
   7using MoreTerra.Utilities;
   8using System.Text;
   9
  10namespace MoreTerra.Structures
  11{
  12	public class World
  13	{
  14		// All the parts of a Terraria world.
  15		private WorldHeader header;
  16		private Tile[,] tiles;
  17		private List<Chest> chests;
  18		private List<Sign> signs;
  19		private List<NPC> npcs;
  20		private Footer footer;
  21
  22		// Various file reading items.
  23		private BackwardsBinaryReader backReader;
  24		private BufferedBinaryReader buffReader;
  25		private BinaryReader reader;
  26		private FileStream stream;
  27
  28		// Quick lookup for the world sizes.
  29		private int MaxX, MaxY;
  30
  31		// Things to do with showing progress when reading/scanning.
  32		private int progress;
  33		private long progressPosition;
  34		private BackgroundWorker bw;
  35
  36		// Lookup table for important tiles.
  37		private Boolean[] tileImportant;
  38
  39		// Positions of each spot in the file.
  40		private Int64 posTiles;
  41		private Int64 posChests;
  42		private Int64 posSigns;
  43		private Int64 posNpcs;
  44		private Int64 posFooter;
  45		private Int64 posEnd;
  46
  47		private Single readWorldPerc = 50;
  48
  49        int[] sectionPointers;
  50
  51		// List generated from reading in chest tiles.
  52		private Dictionary<Point, ChestType> chestTypeList;
  53
  54		#region Structures
  55		// Helper structure for storing information for tile scanning.
  56		public class TileImportance
  57		{
  58			private Boolean[] tImportant;
  59			private Boolean[] tKnown;
  60
  61			public TileImportance()
  62			{
  63				Int32 i;
  64
  65				tImportant = new Boolean[256];
  66				tKnown = new Boolean[256];
  67
  68				for (i = 0; i < 256; i++)
  69				{
  70					tImportant[i] = false;
  71					tKnown[i] = false;
  72				}
  73			}
  74
  75			public TileImportance(TileImportance copyFrom)
  76			{
  77				Int32 i;
  78
  79				tImportant = new Boolean[256];
  80				tKnown = new Boolean[256];
  81
  82				for (i = 0; i < 256; i++)
  83				{
  84					tImportant[i] = copyFrom.tImportant[i];
  85					tKnown[i] = copyFrom.tKnown[i];
  86				}
  87			}
  88
  89			public Boolean isImportant(Byte i)
  90			{
  91				return tImportant[i];
  92			}
  93
  94			public void setImportant(Byte i, Boolean v)
  95			{
  96				tImportant[i] = v;
  97			}
  98
  99			public Boolean isKnown(Byte i)
 100			{
 101				return tKnown[i];
 102			}
 103
 104			public void setKnown(Byte i, Boolean v)
 105			{
 106				tKnown[i] = v;
 107			}
 108		}
 109
 110		// Helper structure for storing all the information
 111		// for each path when scanning for tiles.
 112		public class tileReader
 113		{
 114			public static Int32 nextId = 0;
 115			public Int32 id;
 116			public Int64 filePos;
 117			public TileImportance tileLookup;
 118			public Tile tile;
 119			public List<Byte> tileOrder;
 120			public Int32 tilesRead;
 121
 122			public Point startAt;
 123			public Byte splitAt;
 124
 125			public tileReader(Int64 fPos)
 126			{
 127				id = nextId;
 128				nextId++;
 129
 130				filePos = fPos;
 131
 132				tileLookup = new TileImportance();
 133				tile = new Tile();
 134				tileOrder = new List<Byte>();
 135
 136				tilesRead = 0;
 137			}
 138
 139			public tileReader(tileReader copy)
 140			{
 141				id = nextId;
 142				nextId++;
 143
 144				filePos = copy.filePos;
 145
 146				tileLookup = new TileImportance(copy.tileLookup);
 147				tile = new Tile(copy.tile);
 148				tileOrder = new List<Byte>();
 149
 150				tilesRead = copy.tilesRead;
 151
 152				foreach (Byte b in copy.tileOrder)
 153					tileOrder.Add(b);
 154			}
 155		}
 156		#endregion
 157
 158		#region Constructors
 159		public World()
 160		{
 161			Clear();
 162
 163			Initialize();
 164		}
 165		#endregion
 166
 167		private void Initialize()
 168		{
 169
 170		//	tileImportant = new Boolean[TileProperties.TYPES];
 171
 172		//	for (Int32 i = 0; i < TileProperties.TYPES; i++)
 173		//		tileImportant[i] = TileProperties.tileTypeDefs[i].IsImportant;
 174		}
 175
 176		public void Clear()
 177		{
 178			header = new WorldHeader();
 179			tiles = null;
 180			chests = null;
 181			signs = null;
 182			footer = null;
 183
 184			posChests = 0;
 185			posEnd = 0;
 186			posFooter = 0;
 187			posNpcs = 0;
 188			posSigns = 0;
 189			posTiles = 0;
 190
 191			MaxX = 0;
 192			MaxY = 0;
 193			progress = 0;
 194
 195			if (reader != null)
 196			{
 197				reader.Close();
 198				reader = null;
 199			}
 200
 201			if (stream != null)
 202				stream = null;
 203
 204			if (buffReader != null)
 205				buffReader = null;
 206
 207			if (bw != null)
 208				bw = null;
 209		}
 210
 211        #region ReadFunctions
 212
 213		public void ReadWorld(String world, BackgroundWorker worker = null)
 214		{
 215			Timer t = null;
 216#if (DEBUG == false)
 217			try
 218			{
 219#endif
 220				if (worker != null)
 221				{
 222					bw = worker;
 223					progressPosition = 0;
 224					t = new Timer(333);
 225					t.Elapsed += new ElapsedEventHandler(timer_ReadWorld);
 226					t.Start();
 227				}
 228
 229				readWorldPerc = 50;
 230
 231				stream = new FileStream(world, FileMode.Open, FileAccess.Read);
 232				reader = new BinaryReader(stream);
 233
 234				ReadHeader();
 235				ReadWorldTiles();
 236				ReadChests();
 237				ReadSigns();
 238				ReadNPCs();
 239				ReadFooter();
 240#if (DEBUG == false)
 241			}
 242			catch (Exception e)
 243			{
 244				if (bw != null)
 245				{
 246					t.Stop();
 247					bw = null;
 248				}
 249
 250				reader.Close();
 251
 252				throw e;
 253			}
 254#endif
 255
 256				if (bw != null)
 257			{
 258				t.Stop();
 259				bw = null;
 260			}
 261
 262			reader.Close();
 263		}
 264
 265		private void timer_ReadWorld(object sender, ElapsedEventArgs e)
 266		{
 267			progress = (Int32)(((Single)progressPosition / stream.Length) * readWorldPerc);
 268			bw.ReportProgress(progress);
 269		}
 270
 271		private void ReadHeader()
 272		{
 273            //reader.ReadBytes(8);
 274            //var hello = reader.ReadString();
 275            //byte[] bytes = reader.ReadBytes(10);
 276            //var test = Encoding.Unicode.GetString(bytes);
 277			int version = reader.ReadInt32();
 278            if (version < 94)
 279                throw new Exception("Must use version 1.2.3.1 or higher!");
 280            short sectionCount = reader.ReadInt16();
 281            sectionPointers = new int[sectionCount];
 282            for (int j = 0; j < sectionCount; j++)
 283            {
 284                sectionPointers[j] = reader.ReadInt32();
 285            }
 286            short tiletypeCount = reader.ReadInt16();
 287            tileImportant = new bool[tiletypeCount];
 288            byte flags = 0;
 289            byte mask = 0x80;
 290            
 291            for (int k = 0; k < tiletypeCount; k++)
 292            {
 293                if (mask == 0x80)
 294                {
 295                    flags = reader.ReadByte();
 296                    mask = 0x01;
 297                }
 298                else
 299                {
 300                    mask <<= 1;
 301                }
 302
 303                if ((flags & mask) == mask)
 304                    tileImportant[k] = true;
 305
 306
 307            }
 308			Int32 x, y, w, h;
 309			Int32 i;
 310
 311			if (bw != null)
 312				bw.ReportProgress((Int32)(((Single)progressPosition / stream.Length) * readWorldPerc)
 313					, "Reading Header");
 314
 315			header = new WorldHeader();
 316            header.sectionPointers = sectionPointers;
 317			header.ReleaseNumber = version;
 318			header.Name = reader.ReadString();
 319			header.Id = reader.ReadInt32();
 320			x = reader.ReadInt32();
 321			w = reader.ReadInt32();
 322			y = reader.ReadInt32();
 323			h = reader.ReadInt32();
 324
 325			header.WorldCoords = new Rect(x, w, y, h);
 326
 327	
 328            MaxY = reader.ReadInt32();
 329			MaxX = reader.ReadInt32();
 330		
 331			header.MaxTiles = new Point(MaxX, MaxY);
 332
 333			header.TreeX = new int[3];
 334			header.TreeStyle = new int[4];
 335			header.CaveBackX = new int[3];
 336			header.CaveBackStyle = new int[4];
 337			if (version >= 66)
 338			{
 339				header.MoonType = reader.ReadByte();
 340
 341				for (i = 0; i < 3; i++)
 342			{
 343					header.TreeX[i] = reader.ReadInt32();
 344				}
 345				for (i = 0; i < 4; i++)
 346				{
 347					header.TreeStyle[i] = reader.ReadInt32();
 348				}
 349				for (i = 0; i < 3; i++)
 350				{
 351					header.CaveBackX[i] = reader.ReadInt32();
 352			}
 353				for (i = 0; i < 4; i++)
 354				{
 355					header.CaveBackStyle[i] = reader.ReadInt32();
 356				}
 357				header.IceBackStyle = reader.ReadInt32();
 358				header.JungleBackStyle = reader.ReadInt32();
 359				header.HellBackStyle = reader.ReadInt32();
 360			}
 361
 362			header.SpawnPoint = new Point(reader.ReadInt32(), reader.ReadInt32());
 363			header.SurfaceLevel = reader.ReadDouble();
 364			header.RockLayer = reader.ReadDouble();
 365			header.TemporaryTime = reader.ReadDouble();
 366			header.IsDayTime = reader.ReadBoolean();
 367			header.MoonPhase = reader.ReadInt32();
 368			header.IsBloodMoon = reader.ReadBoolean();
 369            if (version >= 70)
 370                header.IsEclipse = reader.ReadBoolean();
 371
 372			header.DungeonPoint = new Point(reader.ReadInt32(), reader.ReadInt32());
 373			if (version >= 66)
 374			{
 375				header.Crimson = reader.ReadBoolean();
 376			}
 377			header.IsBoss1Dead = reader.ReadBoolean();
 378			header.IsBoss2Dead = reader.ReadBoolean();
 379			header.IsBoss3Dead = reader.ReadBoolean();
 380
 381			if (version >= 66)
 382			{
 383				header.IsQueenBeeDead = reader.ReadBoolean();
 384				header.IsMechBoss1Dead = reader.ReadBoolean();
 385				header.IsMechBoss2Dead = reader.ReadBoolean();
 386				header.IsMechBoss3Dead = reader.ReadBoolean();
 387				header.IsMechBossAnyDead = reader.ReadBoolean();
 388				header.IsPlantBossDead = reader.ReadBoolean();
 389				header.IsGolemBossDead = reader.ReadBoolean();
 390			}
 391			if (version >= 0x24)
 392			{
 393				header.IsGoblinSaved = reader.ReadBoolean();
 394				header.IsWizardSaved = reader.ReadBoolean();
 395				header.IsMechanicSaved = reader.ReadBoolean();
 396				header.IsGoblinArmyDefeated = reader.ReadBoolean();
 397				header.IsClownDefeated = reader.ReadBoolean();
 398			}
 399			if (version >= 0x25)
 400			{
 401				header.IsFrostDefeated = reader.ReadBoolean();
 402			}
 403			if (version >= 66)
 404			{
 405				header.IsPiratesDefeated = reader.ReadBoolean();
 406			}
 407			header.IsShadowOrbSmashed = reader.ReadBoolean();
 408			header.IsMeteorSpawned = reader.ReadBoolean();
 409			header.ShadowOrbsSmashed = reader.ReadByte();
 410
 411			if (version >= 0x24)
 412			{
 413				header.AltarsDestroyed = reader.ReadInt32();
 414				header.HardMode = reader.ReadBoolean();
 415			}
 416
 417			header.InvasionDelay = reader.ReadInt32();
 418			header.InvasionSize = reader.ReadInt32();
 419			header.InvasionType = reader.ReadInt32();
 420			header.InvasionPointX = reader.ReadDouble();
 421
 422			header.OreTiers = new int[3];
 423			header.Styles = new byte[8];
 424            if (version >= 66)
 425            {
 426                header.IsRaining = reader.ReadBoolean();
 427                header.RainTime = reader.ReadInt32();
 428                header.MaxRain = reader.ReadSingle();
 429
 430                for (i = 0; i < 3; i++)
 431                {
 432                    header.OreTiers[i] = reader.ReadInt32();
 433                }
 434
 435                for (i = 0; i < 8; i++)
 436                {
 437                    header.Styles[i] = reader.ReadByte();
 438                }
 439
 440                header.CloudsActive = reader.ReadInt32();
 441                header.NumClouds = reader.ReadInt16();
 442                header.WindSpeed = reader.ReadSingle();
 443                List<string> anglerWhoFinishedToday = new List<string>(); 
 444                for (int index = reader.ReadInt32(); index > 0; --index)
 445                    anglerWhoFinishedToday.Add(reader.ReadString());
 446                if (version < 99)
 447                    return;
 448                var savedAngler = reader.ReadBoolean();
 449                if (version < 101)
 450                    return;
 451                var anglerQuest = reader.ReadInt32();
 452            }
 453            else if (version >= 24)
 454            {
 455                if (header.AltarsDestroyed == 0)
 456                {
 457                    for (i = 0; i < 3; i++)
 458                    {
 459                        header.OreTiers[i] = -1;
 460                    }
 461                }
 462                else
 463                {
 464                    header.OreTiers[1] = 107;
 465                    header.OreTiers[1] = 108;
 466                    header.OreTiers[1] = 111;
 467                }
 468            }
 469				
 470			posTiles = stream.Position;
 471			progressPosition = stream.Position;
 472
 473			
 474		}
 475
 476		private void ReadWorldTiles()
 477		{
 478			Boolean theB;
 479			Byte theI;
 480			Tile theTile;
 481			Int32 i, j;
 482
 483			if (bw != null)
 484				bw.ReportProgress((Int32)(((Single)progressPosition / stream.Length) * readWorldPerc)
 485					, "Reading Tiles");
 486
 487			tiles = new Tile[MaxX, MaxY];
 488
 489			for (i = 0; i < MaxX; i++)
 490			{
 491				for (j = 0; j < MaxY; j++)
 492				{
 493					theTile = new Tile();
 494
 495					theB = reader.ReadBoolean();
 496
 497					theTile.Active = theB;
 498					if (theB == true)
 499					{
 500						theI = reader.ReadByte();
 501
 502						if (theI > 85)
 503							theTile.TileType = theI;
 504
 505						theTile.TileType = theI;
 506
 507						if (tileImportant[theI] == true)
 508						{
 509							theTile.Important = true;
 510							theTile.Frame = new PointInt16(reader.ReadInt16() ,reader.ReadInt16());
 511						}
 512						else
 513							theTile.Important = false;
 514					}
 515
 516					// /dev/null the Lighted Flag
 517					reader.ReadBoolean();
 518
 519					theB = reader.ReadBoolean();
 520
 521					theTile.Wall = theB;
 522					if (theB == true)
 523						theTile.WallType = reader.ReadByte();
 524
 525					if (theTile.WallType == 0 && theTile.Wall == true)
 526						theTile.Wall = true;
 527
 528					theB = reader.ReadBoolean();
 529
 530					if (theB == true)
 531					{
 532						theTile.LiquidLevel = reader.ReadByte();
 533						theTile.Lava = reader.ReadBoolean();
 534					}
 535
 536					tiles[i, j] = theTile;
 537				}
 538				progressPosition = stream.Position;
 539			}
 540
 541			posChests = stream.Position;
 542		}
 543
 544		private void ReadChests()
 545		{
 546			Boolean isChest;
 547			Int16 itemCount;
 548			Chest theChest = null;
 549			Item theItem;
 550			Int32 i, j;
 551            Int32 maxChests;
 552            int maxItems;
 553			chests = new List<Chest>();
 554
 555			if (bw != null)
 556				bw.ReportProgress((Int32)(((Single)progressPosition / stream.Length) * readWorldPerc)
 557					, "Reading Chests");
 558			
 559            
 560                maxChests = reader.ReadInt16();
 561                maxItems = reader.ReadInt16();
 562          
 563
 564			for (i = 0; i < maxChests; i++)
 565			{
 566
 567					theChest = new Chest();
 568					theChest.ChestId = i;
 569					theChest.Active = true;
 570
 571					theChest.Coordinates = new Point(reader.ReadInt32(), reader.ReadInt32());
 572
 573                    theChest.Name = reader.ReadString();
 574                   
 575
 576                    if (chestTypeList != null)
 577                    {
 578                        if (chestTypeList.ContainsKey(theChest.Coordinates))
 579                            theChest.Type = chestTypeList[theChest.Coordinates];
 580                    }
 581                    else
 582                    {
 583                        theChest.Type = ChestType.Chest;
 584                    }
 585
 586					for (j = 0; j < maxItems; j++)
 587					{
 588                        if (header.ReleaseNumber > 68)
 589						itemCount = reader.ReadInt16();
 590                        else
 591                            itemCount = reader.ReadByte();
 592
 593						if (itemCount > 0)
 594						{
 595							theItem = new Item();
 596							theItem.Id = j;
 597							theItem.Count = itemCount;
 598
 599							if (header.ReleaseNumber >= 0x26)
 600							{
 601								theItem.Name = Global.Instance.Info.GetItemName(reader.ReadInt32());
 602							}
 603							else
 604							{
 605								theItem.Name = reader.ReadString();
 606							}
 607
 608							if (header.ReleaseNumber >= 0x24)
 609								theItem.Prefix = reader.ReadByte();
 610
 611							theChest.Items.Add(theItem);
 612						}
 613					}
 614					chests.Add(theChest);
 615				
 616
 617				progressPosition = stream.Position;
 618			}
 619
 620			posSigns = stream.Position;
 621		}
 622
 623		private void ReadSigns()
 624		{
 625			Boolean isSign;
 626			Sign theSign;
 627			signs = new List<Sign>(1000);
 628
 629			if (bw != null)
 630				bw.ReportProgress((Int32)(((Single)progressPosition / stream.Length) * readWorldPerc)
 631					, "Reading Signs");
 632
 633            int maxSigns = reader.ReadInt16();
 634
 635			for (Int32 i = 0; i < maxSigns; i++)
 636			{
 637				//isSign = reader.ReadBoolean();
 638			
 639					theSign = new Sign();
 640					theSign.Id = i;
 641					theSign.Active = true;
 642				
 643					theSign.Text = reader.ReadString();
 644					theSign.Position = new Point(reader.ReadInt32(), reader.ReadInt32());
 645
 646					signs.Add(theSign);
 647				
 648
 649				progressPosition = stream.Position;
 650			}
 651
 652			posNpcs = stream.Position;
 653		}
 654
 655		private void ReadNPCs()
 656		{
 657			Boolean nextNPC;
 658			NPC theNPC;
 659			String nameCrunch;
 660			String[] nameArray;
 661			NPCType npcType;
 662			Int32 i;
 663
 664			npcs = new List<NPC>(20);
 665			i = 0;
 666
 667			if (bw != null)
 668				bw.ReportProgress((Int32)(((Single)progressPosition / stream.Length) * readWorldPerc)
 669					, "Reading NPCs");
 670
 671			nextNPC = reader.ReadBoolean();
 672			while (nextNPC == true)
 673			{
 674				theNPC = new NPC();
 675
 676				theNPC.Id = i;
 677
 678				theNPC.Active = nextNPC;
 679
 680                if (Enum.TryParse(reader.ReadString().Replace(" ", ""), true, out npcType))
 681                    theNPC.Type = npcType;
 682                else
 683                    theNPC.Type = NPCType.Unknown;
 684
 685				theNPC.Name = reader.ReadString();
 686				theNPC.Position = new PointSingle(reader.ReadSingle(), reader.ReadSingle());
 687				theNPC.Homeless = reader.ReadBoolean();
 688				theNPC.HomeTile = new Point(reader.ReadInt32(), reader.ReadInt32());
 689
 690					
 691				npcs.Add(theNPC);
 692				i++;
 693
 694				nextNPC = reader.ReadBoolean();
 695
 696				progressPosition = stream.Position;
 697			}
 698
 699			posFooter = stream.Position;
 700		}
 701
 702		private void ReadNPCNames()
 703		{
 704			if (header.ReleaseNumber >= 0x24)
 705			{
 706				header.MerchantsName = reader.ReadString();
 707				header.NursesName = reader.ReadString();
 708				header.ArmsDealersName = reader.ReadString();
 709				header.DryadsName = reader.ReadString();
 710				header.GuidesName = reader.ReadString();
 711				header.ClothiersName = reader.ReadString();
 712				header.DemolitionistsName = reader.ReadString();
 713				header.TinkerersName = reader.ReadString();
 714				header.WizardsName = reader.ReadString();
 715				header.MechanicsName = reader.ReadString();
 716                header.TrufflesName = reader.ReadString();
 717                header.SteamPunkersName = reader.ReadString();
 718                header.DyeTradersName = reader.ReadString();
 719                header.PartyGirlsName = reader.ReadString();
 720                header.CyborgsName = reader.ReadString();
 721                header.PaintersName = reader.ReadString();
 722                header.WitchDoctorsName = reader.ReadString();
 723                header.PiratesName = reader.ReadString();
 724			}
 725			else
 726			{
 727				header.MerchantsName = "Not set";
 728				header.NursesName = "Not Set";
 729				header.ArmsDealersName = "Not Set";
 730				header.DryadsName = "Not Set";
 731				header.GuidesName = "Not Set";
 732				header.ClothiersName = "Not Set";
 733				header.DemolitionistsName = "Not Set";
 734				header.TinkerersName = "Not Set";
 735				header.WizardsName = "Not Set";
 736				header.MechanicsName = "Not Set";
 737			}
 738		}
 739
 740		private void ReadFooter()
 741		{
 742			footer = new Footer();
 743
 744			if (bw != null)
 745				bw.ReportProgress((Int32)(((Single)progressPosition / stream.Length) * readWorldPerc)
 746					, "Reading Footer");
 747
 748			footer.Active = reader.ReadBoolean();
 749			footer.Name = reader.ReadString();
 750			footer.Id = reader.ReadInt32();
 751
 752			posEnd = stream.Position;
 753			progressPosition = stream.Position;
 754		}
 755
 756		public Int16[,] ReadAndProcessWorld(String worldPath, BackgroundWorker worker)
 757		{
 758
 759			Int16[,] retTiles;
 760			byte wallType;
 761			Timer t = null;
 762
 763
 764			try
 765			{
 766
 767				if (worker != null)
 768				{
 769					bw = worker;
 770					progressPosition = 0;
 771					t = new Timer(333);
 772					t.Elapsed += new ElapsedEventHandler(timer_ReadWorld);
 773					t.Start();
 774				}
 775
 776                
 777
 778				if (SettingsManager.Instance.ShowChestTypes == true)
 779					chestTypeList = new Dictionary<Point, ChestType>();
 780				else
 781					chestTypeList = null;
 782
 783				readWorldPerc = 45;
 784
 785				stream = new FileStream(worldPath, FileMode.Open, FileAccess.Read);
 786				reader = new BinaryReader(stream,Encoding.Default);
 787
 788                
 789
 790
 791				ReadHeader();
 792
 793				MaxX = header.MaxTiles.X;
 794				MaxY = header.MaxTiles.Y;
 795
 796				// Reset MapTile List
 797				retTiles = new Int16[MaxX, MaxY];
 798               // WorldFile wf = new WorldFile();
 799
 800                if (bw != null)
 801                    bw.ReportProgress(0, "Reading and Processing Tiles");
 802
 803                byte firstHeader, secondHeader, thirdHeader = 0;
 804                short ntileType = TileProperties.BackgroundOffset;
 805              //  reader.BaseStream.Seek(sectionPointers[1],SeekOrigin.Begin);
 806                int run = 0;
 807                chestTypeList = new Dictionary<Point, ChestType>();
 808                for (int ncolumn = 0; ncolumn < header.MaxTiles.X; ncolumn++)
 809                {
 810                    for (int nrow = 0; nrow < header.MaxTiles.Y; nrow++)
 811                    {
 812                        if (run > 0)
 813                        {
 814                            retTiles[ncolumn, nrow] = ntileType;
 815                            run--;
 816                            continue;
 817                        }
 818
 819
 820                        if (nrow < header.SurfaceLevel)
 821                            ntileType = TileProperties.BackgroundOffset;
 822                        else if (nrow == header.SurfaceLevel)
 823                            ntileType = (Int16)(TileProperties.BackgroundOffset + 1); // Dirt Transition
 824                        else if (nrow < (header.RockLayer + 38))
 825                            ntileType = (Int16)(TileProperties.BackgroundOffset + 2); // Dirt
 826                        else if (nrow == (header.RockLayer + 38))
 827                            ntileType = (Int16)(TileProperties.BackgroundOffset + 4); // Rock Transition
 828                        else if (nrow < (header.MaxTiles.Y - 202))
 829                            ntileType = (Int16)(TileProperties.BackgroundOffset + 3); // Rock 
 830                        else if (nrow == (header.MaxTiles.Y - 202))
 831                            ntileType = (Int16)(TileProperties.BackgroundOffset + 6); // Underworld Transition
 832                        else
 833                            ntileType = (Int16)(TileProperties.BackgroundOffset + 5); // Underworld
 834
 835                        secondHeader = 0;
 836                        thirdHeader = 0;
 837
 838                        firstHeader = reader.ReadByte();
 839                        if ((firstHeader & 1) == 1)
 840                        {
 841                            secondHeader = reader.ReadByte();
 842                            if((secondHeader & 1) == 1)
 843                                thirdHeader = reader.ReadByte();
 844                        }
 845
 846                        if ((firstHeader & 2) == 2)
 847                        {
 848                            if((firstHeader & 32) == 32)
 849                                ntileType = reader.ReadInt16();
 850                            else
 851                                ntileType = reader.ReadByte();
 852                            if (tileImportant[ntileType])
 853                            {
 854                                 var typeX = reader.ReadInt16();
 855                                 var typeY = reader.ReadInt16();
 856                                 if (ntileType == TileProperties.ExposedGems)
 857                                 {
 858                                     if (typeX == 0)
 859                                         ntileType = TileProperties.Amethyst;
 860                                     else if (typeX == 18)
 861                                         ntileType = TileProperties.Topaz;
 862                                     else if (typeX == 36)
 863                                         ntileType = TileProperties.Sapphire;
 864                                     else if (typeX == 54)
 865                                         ntileType = TileProperties.Emerald;
 866                                     else if (typeX == 72)
 867                                         ntileType = TileProperties.Ruby;
 868                                     else if (typeX == 90)
 869                                         ntileType = TileProperties.Diamond;
 870                                     else if (typeX == 108)
 871                                         ntileType = TileProperties.ExposedGems;
 872                                     // If it's 108 we keep it as ExposedGems so it get the Amber marker.
 873                                 }
 874                                 else if (ntileType == TileProperties.SmallDetritus)
 875                                 {
 876                                     if ((typeX % 36 == 0) && (typeY == 18))
 877                                     {
 878                                         int type = typeX / 36;
 879
 880                                         if (type == 16)
 881                                             ntileType = TileProperties.CopperCache;
 882                                         else if (type == 17)
 883                                             ntileType = TileProperties.SilverCache;
 884                                         else if (type == 18)
 885                                             ntileType = TileProperties.GoldCache;
 886                                         else if (type == 19)
 887                                             ntileType = TileProperties.Amethyst;
 888                                         else if (type == 20)
 889                                             ntileType = TileProperties.Topaz;
 890                                         else if (type == 21)
 891                                             ntileType = TileProperties.Sapphire;
 892                                         else if (type == 22)
 893                                             ntileType = TileProperties.Emerald;
 894                                         else if (type == 23)
 895                                             ntileType = TileProperties.Ruby;
 896                                         else if (type == 24)
 897                                             ntileType = TileProperties.Diamond;
 898                                     }
 899                                 }
 900                                 else if (ntileType == TileProperties.LargeDetritus)
 901                                 {
 902                                     if ((typeX % 54 == 0) && (typeY == 0))
 903                                     {
 904                                         int type = typeX / 54;
 905
 906                                         if (type == 16 || type == 17)
 907                                             ntileType = TileProperties.CopperCache;
 908                                         else if (type == 18 || type == 19)
 909                                             ntileType = TileProperties.SilverCache;
 910                                         else if (type == 20 || type == 21)
 911                                             ntileType = TileProperties.GoldCache;
 912                                     }
 913                                 }
 914                                 else if (ntileType == TileProperties.LargeDetritus2)
 915                                 {
 916                                     if ((typeX % 54 == 0) && (typeY == 0))
 917                                     {
 918                                         int type = typeX / 54;
 919
 920                                         if (type == 17)
 921                                             ntileType = TileProperties.EnchantedSword;
 922                                     }
 923                                 }
 924                                 if ((ntileType == TileProperties.Chest) && (typeX % 36 == 0) && (typeY == 0))
 925                                 {
 926                                     if ((typeX / 36) <= (Int32)ChestType.LockedFrozenChest)
 927                                         chestTypeList.Add(new Point(ncolumn, nrow), (ChestType)(typeX / 36));
 928                                     else
 929                                         chestTypeList.Add(new Point(ncolumn, nrow), ChestType.Unknown);
 930                                 }
 931
 932                            }
 933                            if ((thirdHeader & 8) == 8)
 934                                reader.ReadByte();
 935
 936                        }
 937                        if ((firstHeader & 4) == 4)
 938                        { 
 939                            wallType = reader.ReadByte();
 940                            if (ntileType >= TileProperties.Unknown)
 941                                ntileType = (Int16)(wallType + TileProperties.WallOffset);
 942                            if ((thirdHeader & 16) == 16)
 943                                reader.ReadByte();
 944                        }
 945                        if ((firstHeader & 8) == 8)
 946                        {
 947                            ntileType = TileProperties.Water;
 948                            reader.ReadByte();
 949                            
 950                        }
 951                        else if ((firstHeader & 16) == 16)
 952                        {
 953                            ntileType = TileProperties.Lava;
 954                            reader.ReadByte();
 955
 956                        }
 957
 958                        if ((firstHeader & 64) == 64)
 959                        {
 960                           run = reader.ReadByte();
 961                        
 962                        }
 963                         if ((firstHeader & 128) == 128)
 964                               run = reader.ReadInt16();
 965
 966                       
 967                        
 968                         retTiles[ncolumn, nrow] = ntileType;
 969                         
 970                    }
 971                    
 972                }
 973
 974				
 975
 976
 977              //  reader.BaseStream.Seek(sectionPointers[2], SeekOrigin.Begin);
 978				ReadChests();
 979				ReadSigns();
 980				ReadNPCs();
 981				//ReadNPCNames();
 982				ReadFooter();
 983
 984			}
 985			catch (Exception e)
 986			{
 987				if (bw != null)
 988				{
 989					t.Stop();
 990					bw = null;
 991				}
 992
 993				reader.Close();
 994				retTiles = null;
 995				throw e;
 996			}
 997
 998
 999			if (bw != null)
1000			{
1001				t.Stop();
1002				bw = null;
1003			}
1004
1005			reader.Close();
1006
1007			return retTiles;
1008		}
1009
1010		private void ScanPastWorldTiles()
1011		{
1012			Boolean theB;
1013			Byte theI;
1014			Int32 i, j;
1015			Int16 RLE = 0;
1016
1017			if (bw != null)
1018				bw.ReportProgress((Int32)(((Single)progressPosition / stream.Length) * readWorldPerc)
1019					, "Skipping Tiles");
1020
1021			if (header.ReleaseNumber < 0x24)
1022			{
1023				for (i = 0; i < MaxX; i++)
1024				{
1025					for (j = 0; j < MaxY; j++)
1026					{
1027						theB = reader.ReadBoolean();
1028
1029						if (theB == true)
1030						{
1031							theI = reader.ReadByte();
1032
1033							if (tileImportant[theI] == true)
1034							{
1035								reader.ReadInt16();
1036								reader.ReadInt16();
1037							}
1038						}
1039
1040						reader.ReadBoolean();
1041
1042						theB = reader.ReadBoolean();
1043
1044						if (theB == true)
1045							reader.ReadByte();
1046
1047						theB = reader.ReadBoolean();
1048
1049						if (theB == true)
1050						{
1051							reader.ReadByte();
1052							reader.ReadBoolean();
1053						}
1054					}
1055					progressPosition = stream.Position;
1056				}
1057			}
1058			else
1059			{
1060				for (i = 0; i < MaxX; i++)
1061				{
1062					for (j = 0; j < MaxY; j++)
1063					{
1064						if (RLE == 0)
1065						{
1066							theB = reader.ReadBoolean();
1067
1068							if (theB == true)
1069							{
1070								theI = reader.ReadByte();
1071
1072								if (tileImportant[theI] == true)
1073								{
1074									reader.ReadInt16();
1075									reader.ReadInt16();
1076								}
1077							}
1078
1079							theB = reader.ReadBoolean();
1080
1081							if (theB == true)
1082								reader.ReadByte();
1083
1084							theB = reader.ReadBoolean();
1085
1086							if (theB == true)
1087							{
1088								reader.ReadByte();
1089								reader.ReadBoolean();
1090							}
1091
1092							reader.ReadBoolean();
1093
1094							RLE = reader.ReadInt16();
1095						}
1096						else
1097						{
1098							RLE--;
1099						}
1100					}
1101					progressPosition = stream.Position;
1102				}
1103			}
1104			posChests = stream.Position;
1105		}
1106
1107
1108		// This is used to get only the chests from the file.  For the LoadInformation button.
1109		public List<Chest> GetChests(String world, BackgroundWorker worker = null)
1110		{
1111			Timer t = null;
1112			if (worker != null)
1113			{
1114				bw = worker;
1115				t = new Timer(333);
1116				t.Elapsed += new ElapsedEventHandler(timer_ReadWorld);
1117				t.Start();
1118				progressPosition = 0;
1119			}
1120
1121			readWorldPerc = 100;
1122
1123			stream = new FileStream(world, FileMode.Open, FileAccess.Read);
1124			reader = new BinaryReader(stream);
1125
1126#if (DEBUG == false)
1127			try
1128			{
1129#endif
1130				ReadHeader();
1131
1132				posChests = new BackwardsScanner(stream, header).SeekToChestsBackwards();
1133				
1134				if (posChests != 0)
1135				{
1136					ReadChests();
1137				}
1138				else
1139				{
1140					stream.Seek(posTiles, SeekOrigin.Begin);
1141					ScanPastWorldTiles();
1142					ReadChests();
1143				}
1144#if (DEBUG == false)
1145			}
1146			catch (Exception e)
1147			{
1148				if (bw != null)
1149				{
1150					t.Stop();
1151					bw = null;
1152				}
1153				throw e;
1154			}
1155#endif
1156
1157			reader.Close();
1158
1159
1160			if (bw != null)
1161			{
1162				t.Stop();
1163				bw = null;
1164			}
1165
1166			reader.Close();
1167
1168			return chests;
1169		}
1170#endregion
1171
1172		#region SaveFunctions
1173		public void SaveWorld(String world)
1174		{
1175			FileStream stream = new FileStream(world, FileMode.Create, FileAccess.Write);
1176			BinaryWriter writer = new BinaryWriter(stream);
1177
1178			SaveHeader(writer);
1179			SaveWorldTiles(writer);
1180			SaveChests(writer);
1181			SaveSigns(writer);
1182			SaveNPCs(writer);
1183			SaveFooter(writer);
1184
1185			writer.Close();
1186		}
1187
1188		private void SaveHeader(BinaryWriter writer)
1189		{
1190			writer.Write(header.ReleaseNumber);
1191			writer.Write(header.Name);
1192			writer.Write(header.Id);
1193			writer.Write(header.WorldCoords.TopLeft.X);
1194			writer.Write(header.WorldCoords.TopLeft.Y);
1195			writer.Write(header.WorldCoords.BottomRight.X);
1196			writer.Write(header.WorldCoords.BottomRight.Y);
1197			writer.Write(header.MaxTiles.Y);
1198			writer.Write(header.MaxTiles.X);
1199			writer.Write(header.SpawnPoint.X);
1200			writer.Write(header.SpawnPoint.Y);
1201			writer.Write(header.SurfaceLevel);
1202			writer.Write(header.RockLayer);
1203			writer.Write(header.TemporaryTime);
1204			writer.Write(header.IsDayTime);
1205			writer.Write(header.MoonPhase);
1206			writer.Write(header.IsBloodMoon);
1207			writer.Write(header.DungeonPoint.X);
1208			writer.Write(header.DungeonPoint.Y);
1209			writer.Write(header.IsBoss1Dead);
1210			writer.Write(header.IsBoss2Dead);
1211			writer.Write(header.IsBoss3Dead);
1212			writer.Write(header.IsShadowOrbSmashed);
1213			writer.Write(header.IsMeteorSpawned);
1214			writer.Write(header.ShadowOrbsSmashed);
1215			writer.Write(header.InvasionDelay);
1216			writer.Write(header.InvasionSize);
1217			writer.Write(header.InvasionType);
1218			writer.Write(header.InvasionPointX);
1219		}
1220
1221		private void SaveWorldTiles(BinaryWriter writer)
1222		{
1223			Tile theTile;
1224			Int32 i, j;
1225
1226			for (i = 0; i < MaxX; i++)
1227			{
1228				for (j = 0; j < MaxY; j++)
1229				{
1230					theTile = tiles[i, j];
1231
1232
1233					writer.Write(theTile.Active);
1234
1235					if (theTile.Active)
1236					{
1237						writer.Write(theTile.TileType);
1238
1239						if (tileImportant[theTile.TileType] == true)
1240						{
1241							writer.Write(theTile.Frame.X);
1242							writer.Write(theTile.Frame.Y);
1243						}
1244					}
1245
1246					writer.Write(theTile.Wall);
1247
1248					if (theTile.Wall)
1249						writer.Write(theTile.WallType);
1250
1251					if (theTile.LiquidLevel > 0)
1252					{
1253						writer.Write(true);
1254						writer.Write(theTile.LiquidLevel);
1255						writer.Write(theTile.Lava);
1256					}
1257					else
1258					{
1259						writer.Write(false);
1260					}
1261				}
1262			}
1263		}
1264
1265		private void SaveChests(BinaryWriter writer)
1266		{
1267			Chest nextChest;
1268			Item nextItem;
1269			Int32 i, j;
1270
1271			List<Item>.Enumerator iEnum;
1272			List<Chest>.Enumerator cEnum;
1273
1274			cEnum = chests.GetEnumerator();
1275
1276			cEnum.MoveNext();
1277			nextChest = cEnum.Current;
1278
1279			for (i = 0; i < 1000; i++)
1280			{
1281				if (nextChest != null && i == nextChest.ChestId)
1282				{
1283					writer.Write(nextChest.Active);
1284
1285					writer.Write(nextChest.Coordinates.X);
1286					writer.Write(nextChest.Coordinates.Y);
1287
1288					iEnum = nextChest.Items.GetEnumerator();
1289
1290					iEnum.MoveNext();
1291					nextItem = iEnum.Current;
1292
1293					for (j = 0; j < 20; j++)
1294					{
1295						if (nextItem != null && j == nextItem.Id)
1296						{
1297							writer.Write(nextItem.Count);
1298							writer.Write(nextItem.Name);
1299
1300							iEnum.MoveNext();
1301							nextItem = iEnum.Current;
1302						}
1303						else
1304						{
1305							writer.Write((Int16)0);
1306						}
1307					}
1308
1309					cEnum.MoveNext();
1310					nextChest = cEnum.Current;
1311				}
1312				else
1313				{
1314					writer.Write(false);
1315				}
1316			}
1317		}
1318
1319		private void SaveSigns(BinaryWriter writer)
1320		{
1321			Sign theSign;
1322			Int32 i;
1323
1324			for (i = 0; i < 1000; i++)
1325			{
1326				theSign = signs[i];
1327
1328				writer.Write(theSign.Active);
1329
1330				if (theSign.Active == true)
1331				{
1332					writer.Write(theSign.Text);
1333					writer.Write(theSign.Position.X);
1334					writer.Write(theSign.Position.Y);
1335				}
1336			}
1337		}
1338
1339		private void SaveNPCs(BinaryWriter writer)
1340		{
1341			Int32 i = 0;
1342			NPC theNPC = npcs[i];
1343
1344			while (theNPC != null)
1345			{
1346				writer.Write(theNPC.Active);
1347				writer.Write(theNPC.Name);
1348				writer.Write(theNPC.Position.X);
1349				writer.Write(theNPC.Position.Y);
1350				writer.Write(theNPC.Homeless);
1351				writer.Write(theNPC.HomeTile.X);
1352				writer.Write(theNPC.HomeTile.Y);
1353
1354				i++;
1355				theNPC = npcs[i];
1356			}
1357			writer.Write(false);
1358		}
1359
1360		private void SaveFooter(BinaryWriter writer)
1361		{
1362			writer.Write(footer.Active);
1363			writer.Write(footer.Name);
1364			writer.Write(footer.Id);
1365		}
1366		#endregion
1367
1368		#region ScanningFunctions
1369		// Helper function to help parse through the world loading a tile run at a time.
1370		// Lots of bounds checking to make sure we catch when the first errors happen.
1371		// Designed for 1.2.0.1
1372		public bool SanityCheckWorld(String world)
1373		{
1374			String error;
1375			int strictbool;
1376			int i,j;
1377            String byteStringOld;
1378			byte[] byteStreamOld;
1379			int byteStreamOldLength;
1380            String byteString;
1381			byte[] byteStream;
1382			int byteStreamPos;
1383			Tile curTile = new Tile();
1384			int RLEValue;
1385			byteStream = new byte[40];
1386			byteStreamPos = 0;
1387			byteStreamOld = new byte[40];
1388			byteStreamOldLength = 0;
1389            Int32 tilesRead = 0;
1390			stream = new FileStream(world, FileMode.Open, FileAccess.Read);
1391			reader = new BinaryReader(stream);
1392
1393			ReadHeader();
1394
1395			RLEValue = 0;
1396			for (i = 0; i < MaxX; i++)
1397			{
1398				for (j = 0; j < MaxY; j++)
1399				{
1400					if (RLEValue == 0)
1401					{
1402                        if (tilesRead == 1773)
1403                            tilesRead = 1773;
1404
1405						byteStreamPos = 0;
1406						curTile.Reset();
1407						strictbool = reader.ReadByte();
1408						byteStream[byteStreamPos] = (byte)strictbool;
1409						byteStreamPos++;
1410
1411						if (strictbool > 1)
1412						{
1413							error = String.Format("Failed on the Activate Boolean read: 0x{1:X2}", (byte)strictbool);
1414						}
1415
1416						curTile.Active = (strictbool == 0) ? false : true;
1417
1418						if (curTile.Active)
1419						{
1420                            curTile.TileType = reader.ReadByte();
1421                            byteStream[byteStreamPos] = curTile.TileType;
1422                            byteStreamPos++;
1423
1424                            if (curTile.TileType >= TileProperties.Unknown)
1425                            {
1426                                error = String.Format("Failed on the TileType Byte read: 0x{1:X2}", curTile.TileType);
1427                            }
1428
1429                            if (Global.Instance.Info.Tiles[(int)curTile.TileType].colorName == "FindImportant")
1430                            {
1431                                error = String.Format("TileType {0} has unknown importance.", curTile.TileType);
1432                            }
1433
1434                            if (TileProperties.tileTypeDefs[curTile.TileType].IsImportant)
1435                            {
1436                                curTile.Important = true;
1437
1438                                PointInt16 p = curTile.Frame;
1439                                p.X = reader.ReadInt16();
1440                                byteStream[byteStreamPos] = (byte)(p.X & 0xFF);
1441                                byteStreamPos++;
1442                                byteStream[byteStreamPos] = (byte)((p.X & 0xFF00) >> 8);
1443                                byteStreamPos++;
1444
1445                                p.Y = reader.ReadInt16();
1446                                byteStream[byteStreamPos] = (byte)(p.Y & 0xFF);
1447                                byteStreamPos++;
1448                                byteStream[byteStreamPos] = (byte)((p.Y & 0xFF00) >> 8);
1449                                byteStreamPos++;
1450
1451                                curTile.Frame = p;
1452                            }
1453                            else
1454                            {
1455                                curTile.Important = false;
1456                            }
1457
1458                            strictbool = reader.ReadByte();
1459                            byteStream[byteStreamPos] = (byte)strictbool;
1460                            byteStreamPos++;
1461
1462                            if (strictbool > 1)
1463                            {
1464                                error = String.Format("Failed on the Tile Color Boolean read: 0x{0:X2}", (byte)strictbool);
1465                            }
1466
1467                            if (strictbool >= 1)
1468                            {
1469                                curTile.TileColor = reader.ReadByte();
1470                                byteStream[byteStreamPos] = curTile.TileColor;
1471                                byteStreamPos++;
1472
1473                                if (curTile.TileColor == 0)
1474                                {
1475                                    error = String.Format("Failed on the Tile Color Byte read: 0x{0:X2}", curTile.TileColor);
1476                                }
1477                            }
1478						}
1479
1480                        strictbool = reader.ReadByte();
1481                        byteStream[byteStreamPos] = (byte)(strictbool);
1482                        byteStreamPos++;
1483
1484                        if (strictbool > 1)
1485                        {
1486                            error = String.Format("Failed in the Wall Active Boolean read: 0x{0:X2}", (byte)strictbool);
1487                        }
1488
1489                        if (strictbool >= 1)
1490                        {
1491                            curTile.WallType = reader.ReadByte();
1492                            byteStream[byteStreamPos] = curTile.WallType;
1493                            byteStreamPos++;
1494
1495                            if (curTile.WallType == 0 || curTile.WallType > Global.Instance.Info.Walls.Count)
1496                            {
1497                                error = String.Format("Failed in the Wall Type Byte read: 0x{0:X2}", curTile.WallType);
1498                            }
1499
1500                            strictbool = reader.ReadByte();
1501                            byteStream[byteStreamPos] = (byte)(strictbool);
1502                            byteStreamPos++;
1503
1504                            if (strictbool > 1)
1505                            {
1506                                error = String.Format("Failed in the Wall Color Boolean read: 0x{0:X2}", (byte)strictbool);
1507                            }
1508
1509                            if (strictbool >= 1)
1510                            {
1511                                curTile.WallColor = reader.ReadByte();
1512                                byteStream[byteStreamPos] = curTile.WallColor;
1513                                byteStreamPos++;
1514
1515                                if (curTile.WallColor == 0)
1516                                {
1517                                    error = String.Format("Failed in the Wall Color Byte read: 0x{0:X2}", (byte)strictbool);
1518                                }
1519                            }
1520                        }
1521
1522                        strictbool = reader.ReadByte();
1523                        byteStream[byteStreamPos] = (byte)(strictbool);
1524                        byteStreamPos++;
1525
1526                        if (strictbool > 1)
1527                        {
1528                            error = String.Format("Failed in the Liquid Active Boolean read: 0x{0:X2}", (byte)strictbool);
1529                        }
1530
1531                        if (strictbool >= 1)
1532                        {
1533                            curTile.LiquidLevel = reader.ReadByte();
1534                            byteStream[byteStreamPos] = curTile.LiquidLevel;
1535                            byteStreamPos++;
1536
1537                            strictbool = reader.ReadByte();
1538                            byteStream[byteStreamPos] = (byte)(strictbool);
1539                            byteStreamPos++;
1540
1541                            if (strictbool > 1)
1542                            {
1543                                error = String.Format("Failed in the IsLava Boolean read: 0x{0:X2}", (byte)strictbool);
1544                            }
1545
1546                            curTile.Lava = (strictbool == 0) ? false : true;
1547
1548                            strictbool = reader.ReadByte();
1549                            byteStream[byteStreamPos] = (byte)(strictbool);
1550                            byteStreamPos++;
1551
1552                            if (strictbool > 1)
1553                            {
1554                                error = String.Format("Failed in the IsHoney Boolean read: 0x{0:X2}", (byte)strictbool);
1555                            }
1556
1557                            curTile.Honey = (strictbool == 0) ? false : true;
1558                        }
1559
1560                        strictbool = reader.ReadByte();
1561                        byteStream[byteStreamPos] = (byte)(strictbool);
1562                        byteStreamPos++;
1563
1564                        if (strictbool > 1)
1565                        {
1566                            error = String.Format("Failed in the Red Wire Boolean read: 0x{0:X2}", (byte)strictbool);
1567                        }
1568
1569                        curTile.RedWire = (strictbool == 0) ? false : true;
1570
1571                        strictbool = reader.ReadByte();
1572                        byteStream[byteStreamPos] = (byte)(strictbool);
1573                        byteStreamPos++;
1574
1575                        if (strictbool > 1)
1576                        {
1577                            error = String.Format("Failed in the Blue Wire Boolean read: 0x{0:X2}", (byte)strictbool);
1578                        }
1579
1580                        curTile.BlueWire = (strictbool == 0) ? false : true;
1581
1582                        strictbool = reader.ReadByte();
1583                        byteStream[byteStreamPos] = (byte)(strictbool);
1584                        byteStreamPos++;
1585
1586                        if (strictbool > 1)
1587                        {
1588                            error = String.Format("Failed in the Halftile Boolean read: 0x{0:X2}", (byte)strictbool);
1589                        }
1590
1591                        curTile.GreenWire = (strictbool == 0) ? false : true;
1592
1593                        strictbool = reader.ReadByte();
1594                        byteStream[byteStreamPos] = (byte)(strictbool);
1595                        byteStreamPos++;
1596
1597                        if (strictbool > 1)
1598                        {
1599                            error = String.Format("Failed in the Halftile Boolean read: 0x{0:X2}", (byte)strictbool);
1600                        }
1601
1602                        curTile.Halftile = (strictbool == 0) ? false : true;
1603
1604                        curTile.Slope = reader.ReadByte();
1605
1606                        strictbool = reader.ReadByte();
1607                        byteStream[byteStreamPos] = (byte)(strictbool);
1608                        byteStreamPos++;
1609
1610                        if (strictbool > 1)
1611                        {
1612                            error = String.Format("Failed in the Actuator Boolean read: 0x{0:X2}", (byte)strictbool);
1613                        }
1614
1615                        curTile.Actuator = (strictbool == 0) ? false : true;
1616
1617                        strictbool = reader.ReadByte();
1618                        byteStream[byteStreamPos] = (byte)(strictbool);
1619                        byteStreamPos++;
1620
1621                        if (strictbool > 1)
1622                        {
1623                            error = String.Format("Failed in the Inactive Boolean read: 0x{0:X2}", (byte)strictbool);
1624                        }
1625
1626                        curTile.Inactive = (strictbool == 0) ? false : true;
1627
1628                        RLEValue = reader.ReadInt16();
1629                        byteStream[byteStreamPos] = (byte)(RLEValue & 0xFF);
1630                        byteStreamPos++;
1631                        byteStream[byteStreamPos] = (byte)((RLEValue & 0xFF00) >> 8);
1632                        byteStreamPos++;
1633
1634                        for (int k = byteStreamPos; k < byteStream.Length; k++)
1635                            byteStream[k] = 0;
1636
1637                        for (int k = 0; k < byteStream.Length; k++)
1638                            byteStreamOld[k] = byteStream[k];
1639
1640                        byteStreamOldLength = byteStreamPos;
1641
1642                        byteString = "";
1643                        for (int k = 0; k < byteStreamPos; k++)
1644                            byteString = byteString + String.Format("{0:X2} ", byteStream[k]);
1645
1646                        byteStringOld = byteString;
1647                        tilesRead++;
1648					}
1649					else
1650					{
1651						RLEValue--;
1652						continue;
1653					}
1654				}
1655			}
1656			ReadChests();
1657			ReadSigns();
1658			ReadNPCs();
1659			ReadNPCNames();
1660			ReadFooter();
1661			return true;
1662		}
1663
1664		// Ok so this is how this works.
1665		// It starts out by walking the file backwards to find the ending offset.
1666		// It then sets up the original path and starts scanning along the tiles.
1667		// When it finds an unknown tile type the program duplicates the current
1668		// path and makes one follow the path of it being non-important while
1669		// the other follows the path of being important.
1670		// When a path turns out not to fit the data it gets removed from the list.
1671		// All paths get checked in parallel.
1672		public TileImportance[] ScanWorld(String world, BackgroundWorker worker = null)
1673		{
1674			Timer t = null;
1675			TileImportance[] retList;
1676
1677			if (worker != null)
1678			{
1679				bw = worker;
1680				t = new Timer(333);
1681				t.Elapsed += new ElapsedEventHandler(timer_ScanWorld);
1682				t.Enabled = true;
1683				t.Start();
1684			}
1685
1686			stream = ne

Large files files are truncated, but you can click here to view the full file