//mxd. This rebuilds the WAD file, removing all "dead" entries // Tech info: WAD.Remove() doesn't remove lump data, so MapManager.TemporaryMapFile slowly gets bigger // with every map save/test, which leads to lumpsoffset overflowing when TemporaryMapFile size reaches // int.MaxValue bytes in size (that's ~2Gb). internal void Compress() { // No can't do... if (isreadonly) { return; } // Gather existing data int totaldatalength = 0; List <LumpCopyData> copydata = new List <LumpCopyData>(lumps.Count); for (int i = 0; i < lumps.Count; i++) { // Copy lump... LumpCopyData lcd = new LumpCopyData(); Lump l = lumps[i]; lcd.FixedName = l.FixedName; lcd.Index = i; lcd.Data = l.Stream.ReadAllBytes(); // Store data copydata.Add(lcd); // Track total length totaldatalength += l.Length; // Dispose lump l.Dispose(); } // Compression required? if (totaldatalength >= lumpsoffset + 12) { return; } // Set new file length file.SetLength(totaldatalength + lumps.Count * 16); // Reset lumpsoffset lumpsoffset = 12; // Reset lumps collection lumps = new List <Lump>(copydata.Count); numlumps = copydata.Count; // Recreate all lumps foreach (LumpCopyData lcd in copydata) { Lump l = new Lump(file, this, lcd.FixedName, lumpsoffset, lcd.Data.Length); l.Stream.Write(lcd.Data, 0, lcd.Data.Length); l.Stream.Seek(0, SeekOrigin.Begin); lumps.Insert(lcd.Index, l); lumpsoffset += lcd.Data.Length; } // Write new headers WriteHeaders(); }
// 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 LINEDEFS and SIDEDEFS from WAD file private void ReadLinedefs(MapSet map, int firstindex, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink) { MemoryStream linedefsmem, sidedefsmem; BinaryReader readline, readside; Lump linedefslump, sidedefslump; int num, numsides, i, offsetx, offsety, v1, v2; int s1, s2, flags, action, sc; int[] args = new int[Linedef.NUM_ARGS]; Dictionary <string, bool> stringflags; string thigh, tmid, tlow; Linedef l; Sidedef s; // Get the linedefs lump from wad file linedefslump = wad.FindLump("LINEDEFS", firstindex); if (linedefslump == null) { throw new Exception("Could not find required lump LINEDEFS!"); } // Get the sidedefs lump from wad file sidedefslump = wad.FindLump("SIDEDEFS", firstindex); if (sidedefslump == null) { throw new Exception("Could not find required lump SIDEDEFS!"); } // Prepare to read the items linedefsmem = new MemoryStream(linedefslump.Stream.ReadAllBytes()); sidedefsmem = new MemoryStream(sidedefslump.Stream.ReadAllBytes()); num = (int)linedefslump.Stream.Length / 16; numsides = (int)sidedefslump.Stream.Length / 30; readline = new BinaryReader(linedefsmem); readside = new BinaryReader(sidedefsmem); // Read items from the lump map.SetCapacity(0, map.Linedefs.Count + num, map.Sidedefs.Count + numsides, 0, 0); for (i = 0; i < num; i++) { // Read properties from stream v1 = readline.ReadUInt16(); v2 = readline.ReadUInt16(); flags = readline.ReadUInt16(); action = readline.ReadByte(); args[0] = readline.ReadByte(); args[1] = readline.ReadByte(); args[2] = readline.ReadByte(); args[3] = readline.ReadByte(); args[4] = readline.ReadByte(); s1 = readline.ReadUInt16(); s2 = readline.ReadUInt16(); // Make string flags stringflags = new Dictionary <string, bool>(); foreach (string f in manager.Config.SortedLinedefFlags) { int fnum; if (int.TryParse(f, out fnum)) { stringflags[f] = ((flags & fnum) == fnum); } } // Create new linedef if (vertexlink.ContainsKey(v1) && vertexlink.ContainsKey(v2)) { // Check if not zero-length if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) { l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); l.Update(stringflags, (flags & manager.Config.LinedefActivationsFilter), 0, action, args); l.UpdateCache(); // Line has a front side? if (s1 != ushort.MaxValue) { // Read front sidedef sidedefsmem.Seek(s1 * 30, SeekOrigin.Begin); if ((s1 * 30L) <= (sidedefsmem.Length - 30L)) { offsetx = readside.ReadInt16(); offsety = readside.ReadInt16(); thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); sc = readside.ReadUInt16(); // Create front sidedef if (sectorlink.ContainsKey(sc)) { s = map.CreateSidedef(l, true, sectorlink[sc]); s.Update(offsetx, offsety, thigh, tmid, tlow); } else { General.ErrorLogger.Add(ErrorType.Warning, "Sidedef " + s1 + " references invalid sector " + sc + ". Sidedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid sidedef " + s1 + ". Sidedef has been removed."); } } // Line has a back side? if (s2 != ushort.MaxValue) { // Read back sidedef sidedefsmem.Seek(s2 * 30, SeekOrigin.Begin); if ((s2 * 30L) <= (sidedefsmem.Length - 30L)) { offsetx = readside.ReadInt16(); offsety = readside.ReadInt16(); thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); sc = readside.ReadUInt16(); // Create back sidedef if (sectorlink.ContainsKey(sc)) { s = map.CreateSidedef(l, false, sectorlink[sc]); s.Update(offsetx, offsety, thigh, tmid, tlow); } else { General.ErrorLogger.Add(ErrorType.Warning, "Sidedef " + s2 + " references invalid sector " + sc + ". Sidedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid sidedef " + s2 + ". Sidedef has been removed."); } } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed."); } } // Done linedefsmem.Dispose(); sidedefsmem.Dispose(); }
// This reads the LINEDEFS and SIDEDEFS from WAD file private void ReadLinedefs(MapSet map, int firstindex, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink) { MemoryStream linedefsmem, sidedefsmem; BinaryReader readline, readside; Lump linedefslump, sidedefslump; int num, numsides, i, offsetx, offsety, v1, v2; int s1, s2, flags, action, tag, sc; Dictionary <string, bool> stringflags; string thigh, tmid, tlow; Linedef l; Sidedef s; // Get the linedefs lump from wad file linedefslump = wad.FindLump("LINEDEFS", firstindex); if (linedefslump == null) { throw new Exception("Could not find required lump LINEDEFS!"); } // Get the sidedefs lump from wad file sidedefslump = wad.FindLump("SIDEDEFS", firstindex); if (sidedefslump == null) { throw new Exception("Could not find required lump SIDEDEFS!"); } // Prepare to read the items linedefsmem = new MemoryStream(linedefslump.Stream.ReadAllBytes()); sidedefsmem = new MemoryStream(sidedefslump.Stream.ReadAllBytes()); num = (int)linedefslump.Stream.Length / 14; numsides = (int)sidedefslump.Stream.Length / 30; readline = new BinaryReader(linedefsmem); readside = new BinaryReader(sidedefsmem); // Read items from the lump // ano - heuristic to detect sidedef compression if (num > numsides) { // ano - set sidedefs to some larger amount than // numsides before resizing back down // because in the case of sidedef compression the // array will have to be resized a lot map.SetCapacity(0, map.Linedefs.Count + num, map.Sidedefs.Count + (num * 2), 0, 0); } else { // ano - + 32 as extra leniency for some amount of sidedef // compression that goes undetected by the prev check // note this wont be resized back down but 32 is a neglible amount map.SetCapacity(0, map.Linedefs.Count + num, map.Sidedefs.Count + num + 32, 0, 0); } for (i = 0; i < num; i++) { // Read properties from stream v1 = readline.ReadUInt16(); v2 = readline.ReadUInt16(); flags = readline.ReadUInt16(); action = readline.ReadUInt16(); tag = readline.ReadUInt16(); s1 = readline.ReadUInt16(); s2 = readline.ReadUInt16(); // Make string flags stringflags = new Dictionary <string, bool>(); foreach (string f in manager.Config.SortedLinedefFlags) { int fnum; if (int.TryParse(f, out fnum)) { stringflags[f] = ((flags & fnum) == fnum); } } // Create new linedef if (vertexlink.ContainsKey(v1) && vertexlink.ContainsKey(v2)) { // Check if not zero-length if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) { l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); l.Update(stringflags, 0, tag, action, new int[Linedef.NUM_ARGS]); l.UpdateCache(); // Line has a front side? if (s1 != ushort.MaxValue) { // Read front sidedef if ((s1 * 30L) <= (sidedefsmem.Length - 30L)) { sidedefsmem.Seek(s1 * 30, SeekOrigin.Begin); offsetx = readside.ReadInt16(); offsety = readside.ReadInt16(); thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); sc = readside.ReadUInt16(); // Create front sidedef if (sectorlink.ContainsKey(sc)) { s = map.CreateSidedef(l, true, sectorlink[sc]); s.Update(offsetx, offsety, thigh, tmid, tlow); } else { General.ErrorLogger.Add(ErrorType.Warning, "Sidedef " + s1 + " references invalid sector " + sc + ". Sidedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef references invalid sidedef " + s1 + ". Sidedef has been removed."); } } // Line has a back side? if (s2 != ushort.MaxValue) { // Read back sidedef if ((s2 * 30L) <= (sidedefsmem.Length - 30L)) { sidedefsmem.Seek(s2 * 30, SeekOrigin.Begin); offsetx = readside.ReadInt16(); offsety = readside.ReadInt16(); thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING); sc = readside.ReadUInt16(); // Create back sidedef if (sectorlink.ContainsKey(sc)) { s = map.CreateSidedef(l, false, sectorlink[sc]); s.Update(offsetx, offsety, thigh, tmid, tlow); } else { General.ErrorLogger.Add(ErrorType.Warning, "Sidedef " + s2 + " references invalid sector " + sc + ". Sidedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid sidedef " + s2 + ". Sidedef has been removed."); } } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed."); } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed."); } } if (num > numsides) { // ano - resize the arrays back down map.SetCapacity(0, map.Linedefs.Count, map.Sidedefs.Count, 0, 0); } // Done linedefsmem.Dispose(); sidedefsmem.Dispose(); }