context: 
  #region ================== Copyright (c) 2007 Pascal vd Heiden
  
  /*
   * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
   * This program is released under GNU General Public License
   * 
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   * 
   */
  
  #endregion
  
  #region ================== Namespaces
  
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Globalization;
  using System.Text;
  using System.IO;
  using CodeImp.DoomBuilder.Map;
  using CodeImp.DoomBuilder.Geometry;
  
  #endregion
  
  namespace CodeImp.DoomBuilder.IO
  {
  	internal class HexenMapSetIO : MapSetIO
  	{
  		#region ================== Constants
  
  		#endregion
  
  		#region ================== Constructor / Disposer
  
  		// Constructor
  		public HexenMapSetIO(WAD wad, MapManager manager) : base(wad, manager)
  		{
  		}
  
  		#endregion
  
  		#region ================== Properties
  
  		public override int MaxSidedefs { get { return ushort.MaxValue; } }
  		public override int MaxVertices { get { return ushort.MaxValue; } }
  		public override int MaxLinedefs { get { return ushort.MaxValue; } }
  		public override int MaxSectors { get { return ushort.MaxValue; } }
  		public override int MaxThings { get { return int.MaxValue; } }
  		public override int MinTextureOffset { get { return short.MinValue; } }
  		public override int MaxTextureOffset { get { return short.MaxValue; } }
  		public override int VertexDecimals { get { return 0; } }
          public override float MinLineLength { get { return 1f; } } // ano - related to VertexDecimals
          public override string DecimalsFormat { get { return "0"; } }
  		public override bool HasLinedefTag { get { return false; } }
  		public override bool HasThingTag { get { return true; } }
  		public override bool HasThingAction { get { return true; } }
  		public override bool HasCustomFields { get { return false; } }
  		public override bool HasThingHeight { get { return true; } }
  		public override bool HasActionArgs { get { return true; } }
  		public override bool HasMixedActivations { get { return false; } }
  		public override bool HasPresetActivations { get { return true; } }
  		public override bool HasBuiltInActivations { get { return false; } }
  		public override bool HasNumericLinedefFlags { get { return true; } }
  		public override bool HasNumericThingFlags { get { return true; } }
  		public override bool HasNumericLinedefActivations { get { return true; } }
  		public override int MaxTag { get { return ushort.MaxValue; } }
  		public override int MinTag { get { return ushort.MinValue; } }
  		public override int MaxAction { get { return byte.MaxValue; } }
  		public override int MinAction { get { return byte.MinValue; } }
  		public override int MaxArgument { get { return byte.MaxValue; } }
  		public override int MinArgument { get { return byte.MinValue; } }
  		public override int MaxEffect { get { return ushort.MaxValue; } }
  		public override int MinEffect { get { return ushort.MinValue; } }
  		public override int MaxBrightness { get { return short.MaxValue; } }
  		public override int MinBrightness { get { return short.MinValue; } }
  		public override int MaxThingType { get { return ushort.MaxValue; } }
  		public override int MinThingType { get { return ushort.MinValue; } }
  		public override double MaxCoordinate { get { return (double)short.MaxValue; } }
  		public override double MinCoordinate { get { return (double)short.MinValue; } }
  		public override int MaxThingAngle { get { return short.MaxValue; } }
  		public override int MinThingAngle { get { return short.MinValue; } }
  		
  		#endregion
  
  		#region ================== Reading
  
  		// This reads a map from the file and returns a MapSet
  		public override MapSet Read(MapSet map, string mapname)
  		{
  			int firstindex;
  			Dictionary<int, Vertex> vertexlink;
  			Dictionary<int, Sector> sectorlink;
  			
  			// Find the index where first map lump begins
  			firstindex = wad.FindLumpIndex(mapname) + 1;
  
  			// Read vertices
  			vertexlink = ReadVertices(map, firstindex);
  
  			// Read sectors
  			sectorlink = ReadSectors(map, firstindex);
  
  			// Read linedefs and sidedefs
  			ReadLinedefs(map, firstindex, vertexlink, sectorlink);
  
  			// Read things
  			ReadThings(map, firstindex);
  			
  			// Remove unused vertices
  			map.RemoveUnusedVertices();
  			
  			// Return result;
  			return map;
  		}
  
  		// This reads the THINGS from WAD file
  		private void ReadThings(MapSet map, int firstindex)
  		{
  			MemoryStream mem;
  			BinaryReader reader;
  			int num, i, tag, z, action, x, y, type, flags, angle;
  			int[] args = new int[Thing.NUM_ARGS];
  			Dictionary<string, bool> stringflags;
  			Thing t;
  			
  			// Get the lump from wad file
  			Lump lump = wad.FindLump("THINGS", firstindex);
  			if(lump == null) throw new Exception("Could not find required lump THINGS!");
  			
  			// Prepare to read the items
  			mem = new MemoryStream(lump.Stream.ReadAllBytes());
  			num = (int)lump.Stream.Length / 20;
  			reader = new BinaryReader(mem);
  			
  			// Read items from the lump
  			map.SetCapacity(0, 0, 0, 0, map.Things.Count + num);
  			for(i = 0; i < num; i++)
  			{
  				// Read properties from stream
  				tag = reader.ReadUInt16();
  				x = reader.ReadInt16();
  				y = reader.ReadInt16();
  				z = reader.ReadInt16();
  				angle = reader.ReadInt16();
  				type = reader.ReadUInt16();
  				flags = reader.ReadUInt16();
  				action = reader.ReadByte();
  				args[0] = reader.ReadByte();
  				args[1] = reader.ReadByte();
  				args[2] = reader.ReadByte();
  				args[3] = reader.ReadByte();
  				args[4] = reader.ReadByte();
  
  				// Make string flags
  				stringflags = new Dictionary<string, bool>();
  				foreach(KeyValuePair<string, string> f in manager.Config.ThingFlags)
  				{
  					int fnum;
  					if(int.TryParse(f.Key, out fnum)) stringflags[f.Key] = ((flags & fnum) == fnum);
  				}
  				
  				// Create new item
  				t = map.CreateThing();
  				t.Update(type, x, y, z, angle, stringflags, tag, action, args);
  			}
  
  			// Done
  			mem.Dispose();
  		}
  
  		// This reads the VERTICES from WAD file
  		// Returns a lookup table with indices
  		private Dictionary<int, Vertex> ReadVertices(MapSet map, int firstindex)
  		{
  			MemoryStream mem;
  			Dictionary<int, Vertex> link;
  			BinaryReader reader;
  			int num, i, x, y;
  			Vertex v;
  			
  			// Get the lump from wad file
  			Lump lump = wad.FindLump("VERTEXES", firstindex);
  			if(lump == null) throw new Exception("Could not find required lump VERTEXES!");
  
  			// Prepare to read the items
  			mem = new MemoryStream(lump.Stream.ReadAllBytes());
  			num = (int)lump.Stream.Length / 4;
  			reader = new BinaryReader(mem);
  
  			// Create lookup table
  			link = new Dictionary<int, Vertex>(num);
  
  			// Read items from the lump
  			map.SetCapacity(map.Vertices.Count + num, 0, 0, 0, 0);
  			for(i = 0; i < num; i++)
  			{
  				// Read properties from stream
  				x = reader.ReadInt16();
  				y = reader.ReadInt16();
  
  				// Create new item
  				v = map.CreateVertex(new Vector2D((float)x, (float)y));
  				
  				// Add it to the lookup table
  				link.Add(i, v);
  			}
  
  			// Done
  			mem.Dispose();
  
  			// Return lookup table
  			return link;
  		}
  
  		// This reads the SECTORS from WAD file
  		// Returns a lookup table with indices
  		private Dictionary<int, Sector> ReadSectors(MapSet map, int firstindex)
  		{
  			MemoryStream mem;
  			Dictionary<int, Sector> link;
  			BinaryReader reader;
  			int num, i, hfloor, hceil, bright, special, tag;
  			string tfloor, tceil;
  			Sector s;
  
  			// Get the lump from wad file
  			Lump lump = wad.FindLump("SECTORS", firstindex);
  			if(lump == null) throw new Exception("Could not find required lump SECTORS!");
  
  			// Prepare to read the items
  			mem = new MemoryStream(lump.Stream.ReadAllBytes());
  			num = (int)lump.Stream.Length / 26;
  			reader = new BinaryReader(mem);
  
  			// Create lookup table
  			link = new Dictionary<int, Sector>(num);
  
  			// Read items from the lump
  			map.SetCapacity(0, 0, 0, map.Sectors.Count + num, 0);
  			for(i = 0; i < num; i++)
  			{
  				// Read properties from stream
  				hfloor = reader.ReadInt16();
  				hceil = reader.ReadInt16();
  				tfloor = Lump.MakeNormalName(reader.ReadBytes(8), WAD.ENCODING);
  				tceil = Lump.MakeNormalName(reader.ReadBytes(8), WAD.ENCODING);
  
gt: 				bright = reader.ReadInt16();