// This reads the vertices private Dictionary <int, Vertex> ReadVertices(MapSet map, UniversalParser textmap) { Dictionary <int, Vertex> link; // Get list of entries List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "vertex"); // Create lookup table link = new Dictionary <int, Vertex>(collections.Count); // Go for all collections map.SetCapacity(map.Vertices.Count + collections.Count, 0, 0, 0, 0); for (int i = 0; i < collections.Count; i++) { // Read fields UniversalCollection c = collections[i]; string where = "vertex " + i; float x = GetCollectionEntry <float>(c, "x", true, 0.0f, where); float y = GetCollectionEntry <float>(c, "y", true, 0.0f, where); // Create new item Vertex v = map.CreateVertex(new Vector2D(x, y)); if (v != null) { // Custom fields ReadCustomFields(c, v, "vertex"); // Add it to the lookup table link.Add(i, v); } } // Return lookup table return(link); }
// This reads from a stream public void Read(MapSet map, Stream stream) { StreamReader reader = new StreamReader(stream, Encoding.ASCII); UniversalParser textmap = new UniversalParser(); textmap.StrictChecking = strictchecking; // Read UDMF from stream List <string> data = new List <string>(1000); while (!reader.EndOfStream) { data.Add(reader.ReadLine()); } // Parse it textmap.InputConfiguration(data.ToArray()); // Check for errors if (textmap.ErrorResult != 0) { //mxd. Throw parse error throw new Exception("Error on line " + textmap.ErrorLine + " while parsing UDMF map data:\n" + textmap.ErrorDescription); } // Read the map Dictionary <int, Vertex> vertexlink = ReadVertices(map, textmap); Dictionary <int, Sector> sectorlink = ReadSectors(map, textmap); ReadLinedefs(map, textmap, vertexlink, sectorlink); ReadThings(map, textmap); }
// This adds vertices private void WriteVertices(ICollection <Vertex> vertices, UniversalParser textmap) { // Go for all vertices foreach (Vertex v in vertices) { // Make collection UniversalCollection coll = new UniversalCollection(); coll.Add("x", v.Position.x); coll.Add("y", v.Position.y); if (!float.IsNaN(v.ZCeiling)) { coll.Add("zceiling", v.ZCeiling); //mxd } if (!float.IsNaN(v.ZFloor)) { coll.Add("zfloor", v.ZFloor); //mxd } coll.Comment = v.Index.ToString(); // Add custom fields AddCustomFields(v, "vertex", coll); // Store textmap.Root.Add("vertex", coll); } }
// ano - this returns all the unidentified data for preservation private void ReadUnidentifiedEntries(MapSet map, UniversalParser textmap) { UniversalCollection root = textmap.Root; UniversalCollection unidentified = new UniversalCollection(); foreach (UniversalEntry e in root) { switch (e.Key) { case "namespace": case "vertex": case "thing": case "linedef": case "sector": case "sidedef": break; default: unidentified.Add(e); break; } // switch } // foreach map.UnidentifiedUDMF = unidentified; } // ReadUnidentifiedEntries
// This adds sectors private void WriteSectors(ICollection <Sector> sectors, UniversalParser textmap) { // Go for all sectors foreach (Sector s in sectors) { // Make collection UniversalCollection coll = new UniversalCollection(); coll.Add("heightfloor", s.FloorHeight); coll.Add("heightceiling", s.CeilHeight); coll.Add("texturefloor", s.FloorTexture); coll.Add("textureceiling", s.CeilTexture); coll.Add("lightlevel", s.Brightness); if (s.Effect != 0) { coll.Add("special", s.Effect); } if (s.Tag != 0) { coll.Add("id", s.Tag); } coll.Comment = s.Index.ToString(); // Add custom fields AddCustomFields(s, "sector", coll); // Store textmap.Root.Add("sector", coll); } }
// This writes the structures to a stream // NOTE: writenamespace may be null to omit writing the namespace to the stream. // NOTE: The given structures must be complete, with the exception of the sidedefs. // If there are missing sidedefs, their reference will be removed from the linedefs. public void Write(ICollection <Vertex> vertices, ICollection <Linedef> linedefs, ICollection <Sidedef> sidedefs, ICollection <Sector> sectors, ICollection <Thing> things, Stream stream, string writenamespace) { UniversalParser textmap = new UniversalParser(); // Begin with fields that must be at the top if (writenamespace != null) { textmap.Root.Add("namespace", writenamespace); } Dictionary <Vertex, int> vertexids = new Dictionary <Vertex, int>(vertices.Count); //mxd Dictionary <Sidedef, int> sidedefids = new Dictionary <Sidedef, int>(sidedefs.Count); //mxd Dictionary <Sector, int> sectorids = new Dictionary <Sector, int>(sectors.Count); //mxd // Index the elements in the data structures int counter = 0; //mxd foreach (Vertex v in vertices) { vertexids.Add(v, counter++); } counter = 0; //mxd foreach (Sidedef sd in sidedefs) { sidedefids.Add(sd, counter++); } counter = 0; //mxd foreach (Sector s in sectors) { sectorids.Add(s, counter++); } // If we write the custom field types again, then forget // all previous field types (this gets rid of unused field types) if (remembercustomtypes) { General.Map.Options.ForgetUniversalFieldTypes(); } // Write the data structures to textmap WriteVertices(vertices, textmap); WriteLinedefs(linedefs, textmap, sidedefids, vertexids); WriteSidedefs(sidedefs, textmap, sectorids); WriteSectors(sectors, textmap); WriteThings(things, textmap); // Get the textmap as string string textmapstr = textmap.OutputConfiguration(); // Write to stream StreamWriter writer = new StreamWriter(stream, Encoding.ASCII); writer.Write(textmapstr); writer.Flush(); }
// This reads the sectors private Dictionary <int, Sector> ReadSectors(MapSet map, UniversalParser textmap) { Dictionary <int, Sector> link; // Get list of entries List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector"); // Create lookup table link = new Dictionary <int, Sector>(collections.Count); // Go for all collections map.SetCapacity(0, 0, 0, map.Sectors.Count + collections.Count, 0); for (int i = 0; i < collections.Count; i++) { // Read fields UniversalCollection c = collections[i]; string where = "sector " + i; int[] colors = new int[Sector.NUM_COLORS]; int hfloor = GetCollectionEntry <int>(c, "heightfloor", false, 0, where); int hceil = GetCollectionEntry <int>(c, "heightceiling", false, 0, where); string tfloor = GetCollectionEntry <string>(c, "texturefloor", true, "-", where); string tceil = GetCollectionEntry <string>(c, "textureceiling", true, "-", where); int bright = GetCollectionEntry <int>(c, "lightlevel", false, 160, where); int special = GetCollectionEntry <int>(c, "special", false, 0, where); int tag = GetCollectionEntry <int>(c, "id", false, 0, where); // villsa 9/14/11 (builder64) colors[0] = GetCollectionEntry <int>(c, "color1", false, 0, where); colors[1] = GetCollectionEntry <int>(c, "color2", false, 0, where); colors[2] = GetCollectionEntry <int>(c, "color3", false, 0, where); colors[3] = GetCollectionEntry <int>(c, "color4", false, 0, where); colors[4] = GetCollectionEntry <int>(c, "color5", false, 0, where); // villsa 9/13/11 - Flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(); foreach (KeyValuePair <string, string> flag in General.Map.Config.SectorFlags) { stringflags[flag.Key] = GetCollectionEntry <bool>(c, flag.Key, false, false, where); } // Create new item Sector s = map.CreateSector(); if (s != null) { s.Update(stringflags, hfloor, hceil, tfloor, tceil, special, tag, colors); // Custom fields ReadCustomFields(c, s, "sector"); // Add it to the lookup table link.Add(i, s); } } // Return lookup table return(link); }
// This reads the things private void ReadThings(MapSet map, UniversalParser textmap) { // Get list of entries List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "thing"); // Go for all collections map.SetCapacity(0, 0, 0, 0, map.Things.Count + collections.Count); for (int i = 0; i < collections.Count; i++) { // Read fields UniversalCollection c = collections[i]; int[] args = new int[Linedef.NUM_ARGS]; string where = "thing " + i; float x = GetCollectionEntry <float>(c, "x", true, 0.0f, where); float y = GetCollectionEntry <float>(c, "y", true, 0.0f, where); float height = GetCollectionEntry <float>(c, "height", false, 0.0f, where); int tag = GetCollectionEntry <int>(c, "id", false, 0, where); int angledeg = GetCollectionEntry <int>(c, "angle", false, 0, where); int type = GetCollectionEntry <int>(c, "type", true, 0, where); int special = GetCollectionEntry <int>(c, "special", false, 0, where); args[0] = GetCollectionEntry <int>(c, "arg0", false, 0, where); args[1] = GetCollectionEntry <int>(c, "arg1", false, 0, where); args[2] = GetCollectionEntry <int>(c, "arg2", false, 0, where); args[3] = GetCollectionEntry <int>(c, "arg3", false, 0, where); args[4] = GetCollectionEntry <int>(c, "arg4", false, 0, where); // Flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(); foreach (KeyValuePair <string, string> flag in General.Map.Config.ThingFlags) { stringflags[flag.Key] = GetCollectionEntry <bool>(c, flag.Key, false, false, where); } foreach (FlagTranslation ft in General.Map.Config.ThingFlagsTranslation) { foreach (string field in ft.Fields) { stringflags[field] = GetCollectionEntry <bool>(c, field, false, false, where); } } // Create new item Thing t = map.CreateThing(); if (t != null) { t.Update(type, x, y, height, angledeg, stringflags, tag, special, args); // Custom fields ReadCustomFields(c, t, "thing"); } } }
// This adds sectors private void WriteSectors(ICollection <Sector> sectors, UniversalParser textmap) { // Go for all sectors foreach (Sector s in sectors) { // Make collection UniversalCollection coll = new UniversalCollection(); coll.Add("heightfloor", s.FloorHeight); coll.Add("heightceiling", s.CeilHeight); coll.Add("texturefloor", s.FloorTexture); coll.Add("textureceiling", s.CeilTexture); coll.Add("lightlevel", s.Brightness); if (s.Effect != 0) { coll.Add("special", s.Effect); } if (s.Tag != 0) { coll.Add("id", s.Tag); } // villsa 9/14/11 (builder64) coll.Add("color1", s.FloorColor.color.ToInt()); coll.Add("color2", s.CeilColor.color.ToInt()); coll.Add("color3", s.ThingColor.color.ToInt()); coll.Add("color4", s.TopColor.color.ToInt()); coll.Add("color5", s.LowerColor.color.ToInt()); // villsa 9/13/11 - Flags foreach (KeyValuePair <string, bool> flag in s.Flags) { if (flag.Value) { coll.Add(flag.Key, flag.Value); } } coll.Comment = s.Index.ToString(); // Add custom fields AddCustomFields(s, "sector", coll); // Store textmap.Root.Add("sector", coll); } }
// This adds sidedefs private void WriteSidedefs(ICollection <Sidedef> sidedefs, UniversalParser textmap, IDictionary <Sector, int> sectorids) { // Go for all sidedefs foreach (Sidedef s in sidedefs) { // Make collection UniversalCollection coll = new UniversalCollection(); if (s.OffsetX != 0) { coll.Add("offsetx", s.OffsetX); } if (s.OffsetY != 0) { coll.Add("offsety", s.OffsetY); } if (s.LongHighTexture != MapSet.EmptyLongName) { coll.Add("texturetop", s.HighTexture); } if (s.LongLowTexture != MapSet.EmptyLongName) { coll.Add("texturebottom", s.LowTexture); } if (s.LongMiddleTexture != MapSet.EmptyLongName) { coll.Add("texturemiddle", s.MiddleTexture); } coll.Add("sector", sectorids[s.Sector]); coll.Comment = s.Index.ToString(); //mxd. Flags foreach (KeyValuePair <string, bool> flag in s.Flags) { if (flag.Value) { coll.Add(flag.Key, flag.Value); } } // Add custom fields AddCustomFields(s, "sidedef", coll); // Store textmap.Root.Add("sidedef", coll); } }
// This reads the vertices private Dictionary <int, Vertex> ReadVertices(MapSet map, UniversalParser textmap) { // Get list of entries List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "vertex"); // Create lookup table Dictionary <int, Vertex> link = new Dictionary <int, Vertex>(collections.Count); // Go for all collections map.SetCapacity(map.Vertices.Count + collections.Count, 0, 0, 0, 0); for (int i = 0; i < collections.Count; i++) { // Read fields UniversalCollection c = collections[i]; string where = "vertex " + i; float x = GetCollectionEntry(c, "x", true, 0.0f, where); float y = GetCollectionEntry(c, "y", true, 0.0f, where); // [ZZ] Correct location if it's NaN. Note that there cannot be any meaningful value here, so I just reset it to 0,0 to avoid triggering the NaN exception // TODO: remove once the cause of NaN is reported if (float.IsNaN(x) || float.IsNaN(y)) { x = y = 0f; General.ErrorLogger.Add(ErrorType.Warning, string.Format("Vertex {0} has NaN coordinates, resetting to 0,0", i)); } // Create new item Vertex v = map.CreateVertex(new Vector2D(x, y)); if (v != null) { //mxd. zoffsets v.ZCeiling = GetCollectionEntry(c, "zceiling", false, float.NaN, where); //mxd v.ZFloor = GetCollectionEntry(c, "zfloor", false, float.NaN, where); //mxd // Custom fields ReadCustomFields(c, v, "vertex"); // Add it to the lookup table link.Add(i, v); } } // Return lookup table return(link); }
// This adds vertices private void WriteVertices(ICollection <Vertex> vertices, UniversalParser textmap) { // Go for all vertices foreach (Vertex v in vertices) { // Make collection UniversalCollection coll = new UniversalCollection(); coll.Add("x", v.Position.x); coll.Add("y", v.Position.y); coll.Comment = v.Index.ToString(); // Add custom fields AddCustomFields(v, "vertex", coll); // Store textmap.Root.Add("vertex", coll); } }
// This reads the sectors private Dictionary <int, Sector> ReadSectors(MapSet map, UniversalParser textmap) { Dictionary <int, Sector> link; // Get list of entries List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector"); // Create lookup table link = new Dictionary <int, Sector>(collections.Count); // Go for all collections map.SetCapacity(0, 0, 0, map.Sectors.Count + collections.Count, 0); for (int i = 0; i < collections.Count; i++) { // Read fields UniversalCollection c = collections[i]; string where = "sector " + i; int hfloor = GetCollectionEntry <int>(c, "heightfloor", false, 0, where); int hceil = GetCollectionEntry <int>(c, "heightceiling", false, 0, where); string tfloor = GetCollectionEntry <string>(c, "texturefloor", true, "-", where); string tceil = GetCollectionEntry <string>(c, "textureceiling", true, "-", where); int bright = GetCollectionEntry <int>(c, "lightlevel", false, 160, where); int special = GetCollectionEntry <int>(c, "special", false, 0, where); int tag = GetCollectionEntry <int>(c, "id", false, 0, where); // Create new item Sector s = map.CreateSector(); if (s != null) { s.Update(hfloor, hceil, tfloor, tceil, special, tag, bright); // Custom fields ReadCustomFields(c, s, "sector"); // Add it to the lookup table link.Add(i, s); } } // Return lookup table return(link); }
// This reads from a stream public MapSet Read(MapSet map, Stream stream) { StreamReader reader = new StreamReader(stream, Encoding.ASCII); Dictionary <int, Vertex> vertexlink; Dictionary <int, Sector> sectorlink; UniversalParser textmap = new UniversalParser(); textmap.StrictChecking = strictchecking; try { // Read UDMF from stream textmap.InputConfiguration(reader.ReadToEnd()); // Check for errors if (textmap.ErrorResult != 0) { // Show parse error General.ShowErrorMessage("Error on line " + textmap.ErrorLine + " while parsing UDMF map data:\n" + textmap.ErrorDescription, MessageBoxButtons.OK); } else { // Read the map vertexlink = ReadVertices(map, textmap); sectorlink = ReadSectors(map, textmap); ReadLinedefs(map, textmap, vertexlink, sectorlink); ReadThings(map, textmap); ReadUnidentifiedEntries(map, textmap); // ano } } catch (Exception e) { General.ShowErrorMessage("Unexpected error reading UDMF map data. " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK); } return(map); }
// This adds things private void WriteThings(ICollection <Thing> things, UniversalParser textmap) { // Go for all things foreach (Thing t in things) { // Make collection UniversalCollection coll = new UniversalCollection(); if (t.Tag != 0) { coll.Add("id", t.Tag); } coll.Add("x", t.Position.x); coll.Add("y", t.Position.y); if (t.Position.z != 0.0f) { coll.Add("height", (float)t.Position.z); } coll.Add("angle", t.AngleDoom); coll.Add("type", t.Type); if (t.Action != 0) { coll.Add("special", t.Action); } if (t.Args[0] != 0) { coll.Add("arg0", t.Args[0]); } if (t.Args[1] != 0) { coll.Add("arg1", t.Args[1]); } if (t.Args[2] != 0) { coll.Add("arg2", t.Args[2]); } if (t.Args[3] != 0) { coll.Add("arg3", t.Args[3]); } if (t.Args[4] != 0) { coll.Add("arg4", t.Args[4]); } coll.Comment = t.Index.ToString(); // Flags foreach (KeyValuePair <string, bool> flag in t.Flags) { if (flag.Value) { coll.Add(flag.Key, flag.Value); } } // Add custom fields AddCustomFields(t, "thing", coll); // Store textmap.Root.Add("thing", coll); } }
// This reads the linedefs and sidedefs private void ReadLinedefs(MapSet map, UniversalParser textmap, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink) { // Get list of entries List <UniversalCollection> linescolls = GetNamedCollections(textmap.Root, "linedef"); List <UniversalCollection> sidescolls = GetNamedCollections(textmap.Root, "sidedef"); // Go for all lines map.SetCapacity(0, map.Linedefs.Count + linescolls.Count, map.Sidedefs.Count + sidescolls.Count, 0, 0); for (int i = 0; i < linescolls.Count; i++) { // Read fields UniversalCollection lc = linescolls[i]; int[] args = new int[Linedef.NUM_ARGS]; string where = "linedef " + i; int tag = GetCollectionEntry <int>(lc, "id", false, 0, where); int v1 = GetCollectionEntry <int>(lc, "v1", true, 0, where); int v2 = GetCollectionEntry <int>(lc, "v2", true, 0, where); int special = GetCollectionEntry <int>(lc, "special", false, 0, where); int acti = GetCollectionEntry <int>(lc, "activate", false, 0, where); // villsa 9/13/11 int switchmask = GetCollectionEntry <int>(lc, "switchmask", false, 0, where); // villsa 9/13/11 args[0] = GetCollectionEntry <int>(lc, "arg0", false, 0, where); args[1] = GetCollectionEntry <int>(lc, "arg1", false, 0, where); args[2] = GetCollectionEntry <int>(lc, "arg2", false, 0, where); args[3] = GetCollectionEntry <int>(lc, "arg3", false, 0, where); args[4] = GetCollectionEntry <int>(lc, "arg4", false, 0, where); int s1 = GetCollectionEntry <int>(lc, "sidefront", true, -1, where); int s2 = GetCollectionEntry <int>(lc, "sideback", false, -1, where); // Flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(); foreach (KeyValuePair <string, string> flag in General.Map.Config.LinedefFlags) { stringflags[flag.Key] = GetCollectionEntry <bool>(lc, flag.Key, false, false, where); } foreach (FlagTranslation ft in General.Map.Config.LinedefFlagsTranslation) { foreach (string field in ft.Fields) { stringflags[field] = GetCollectionEntry <bool>(lc, field, false, false, where); } } // Activations foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates) { stringflags[activate.Key] = GetCollectionEntry <bool>(lc, activate.Key, false, false, where); } // 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) { Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); if (l != null) { l.Update(stringflags, acti, tag, special, switchmask, args); l.UpdateCache(); // Custom fields ReadCustomFields(lc, l, "linedef"); // Read sidedefs and connect them to the line if (s1 > -1) { if (s1 < sidescolls.Count) { ReadSidedef(map, sidescolls[s1], l, true, sectorlink, s1); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed."); } } if (s2 > -1) { if (s2 < sidescolls.Count) { ReadSidedef(map, sidescolls[s2], l, false, sectorlink, s2); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". 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."); } } }
// This adds linedefs private void WriteLinedefs(ICollection <Linedef> linedefs, UniversalParser textmap, IDictionary <Sidedef, int> sidedefids, IDictionary <Vertex, int> vertexids) { // Go for all linedefs foreach (Linedef l in linedefs) { // Make collection UniversalCollection coll = new UniversalCollection(); if (l.Tag != 0) { coll.Add("id", l.Tag); } coll.Add("v1", vertexids[l.Start]); coll.Add("v2", vertexids[l.End]); coll.Comment = l.Index.ToString(); // Sidedef references if ((l.Front != null) && sidedefids.ContainsKey(l.Front)) { coll.Add("sidefront", sidedefids[l.Front]); } else { coll.Add("sidefront", -1); } if ((l.Back != null) && sidedefids.ContainsKey(l.Back)) { coll.Add("sideback", sidedefids[l.Back]); } else { coll.Add("sideback", -1); } // Special if (l.Action != 0) { coll.Add("special", l.Action); } if (l.Args[0] != 0) { coll.Add("arg0", l.Args[0]); } if (l.Args[1] != 0) { coll.Add("arg1", l.Args[1]); } if (l.Args[2] != 0) { coll.Add("arg2", l.Args[2]); } if (l.Args[3] != 0) { coll.Add("arg3", l.Args[3]); } if (l.Args[4] != 0) { coll.Add("arg4", l.Args[4]); } // Flags foreach (KeyValuePair <string, bool> flag in l.Flags) { if (flag.Value) { coll.Add(flag.Key, flag.Value); } } // Add custom fields AddCustomFields(l, "linedef", coll); // Store textmap.Root.Add("linedef", coll); } }
// This adds sectors private void WriteSectors(ICollection <Sector> sectors, UniversalParser textmap) { // Go for all sectors foreach (Sector s in sectors) { // Make collection UniversalCollection coll = new UniversalCollection(); coll.Add("heightfloor", s.FloorHeight); coll.Add("heightceiling", s.CeilHeight); coll.Add("texturefloor", s.FloorTexture); coll.Add("textureceiling", s.CeilTexture); coll.Add("lightlevel", s.Brightness); if (s.Effect != 0) { coll.Add("special", s.Effect); } if (s.Tag != 0) { coll.Add("id", s.Tag); } coll.Comment = s.Index.ToString(); //mxd. MoreIDs if (s.Tags.Count > 1) //first entry is saved as "id" { string[] moreidscol = new string[s.Tags.Count - 1]; for (int i = 1; i < s.Tags.Count; i++) { moreidscol[i - 1] = s.Tags[i].ToString(); } coll.Add("moreids", string.Join(" ", moreidscol)); } //mxd. Slopes if (s.FloorSlope.GetLengthSq() > 0) { coll.Add("floorplane_a", Math.Round(s.FloorSlope.x, Sector.SLOPE_DECIMALS)); coll.Add("floorplane_b", Math.Round(s.FloorSlope.y, Sector.SLOPE_DECIMALS)); coll.Add("floorplane_c", Math.Round(s.FloorSlope.z, Sector.SLOPE_DECIMALS)); coll.Add("floorplane_d", (float.IsNaN(s.FloorSlopeOffset) ? 0f : Math.Round(s.FloorSlopeOffset, Sector.SLOPE_DECIMALS))); } if (s.CeilSlope.GetLengthSq() > 0) { coll.Add("ceilingplane_a", Math.Round(s.CeilSlope.x, Sector.SLOPE_DECIMALS)); coll.Add("ceilingplane_b", Math.Round(s.CeilSlope.y, Sector.SLOPE_DECIMALS)); coll.Add("ceilingplane_c", Math.Round(s.CeilSlope.z, Sector.SLOPE_DECIMALS)); coll.Add("ceilingplane_d", (float.IsNaN(s.CeilSlopeOffset) ? 0f : Math.Round(s.CeilSlopeOffset, Sector.SLOPE_DECIMALS))); } //mxd. Flags foreach (KeyValuePair <string, bool> flag in s.Flags) { if (flag.Value) { coll.Add(flag.Key, flag.Value); } } // Add custom fields AddCustomFields(s, "sector", coll); // Store textmap.Root.Add("sector", coll); } }
// This reads the linedefs and sidedefs private void ReadLinedefs(MapSet map, UniversalParser textmap, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink) { // Get list of entries List <UniversalCollection> linescolls = GetNamedCollections(textmap.Root, "linedef"); List <UniversalCollection> sidescolls = GetNamedCollections(textmap.Root, "sidedef"); // Go for all lines map.SetCapacity(0, map.Linedefs.Count + linescolls.Count, map.Sidedefs.Count + sidescolls.Count, 0, 0); char[] splitter = { ' ' }; //mxd for (int i = 0; i < linescolls.Count; i++) { // Read fields UniversalCollection lc = linescolls[i]; int[] args = new int[Linedef.NUM_ARGS]; string where = "linedef " + i; int v1 = GetCollectionEntry(lc, "v1", true, 0, where); int v2 = GetCollectionEntry(lc, "v2", true, 0, where); if (!vertexlink.ContainsKey(v1) || !vertexlink.ContainsKey(v2)) { //mxd General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed."); continue; } int tag = GetCollectionEntry(lc, "id", false, 0, where); int special = GetCollectionEntry(lc, "special", false, 0, where); args[0] = GetCollectionEntry(lc, "arg0", false, 0, where); args[1] = GetCollectionEntry(lc, "arg1", false, 0, where); args[2] = GetCollectionEntry(lc, "arg2", false, 0, where); args[3] = GetCollectionEntry(lc, "arg3", false, 0, where); args[4] = GetCollectionEntry(lc, "arg4", false, 0, where); int s1 = GetCollectionEntry(lc, "sidefront", false, -1, where); int s2 = GetCollectionEntry(lc, "sideback", false, -1, where); //mxd. MoreIDs List <int> tags = new List <int> { tag }; string moreids = GetCollectionEntry(lc, "moreids", false, string.Empty, where); if (!string.IsNullOrEmpty(moreids)) { string[] moreidscol = moreids.Split(splitter, StringSplitOptions.RemoveEmptyEntries); foreach (string sid in moreidscol) { int id; if (int.TryParse(sid.Trim(), out id) && id != 0 && !tags.Contains(id)) { tags.Add(id); } } } if (tag == 0 && tags.Count > 1) { tags.RemoveAt(0); } // Flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); foreach (KeyValuePair <string, string> flag in General.Map.Config.LinedefFlags) { stringflags[flag.Key] = GetCollectionEntry(lc, flag.Key, false, false, where); } foreach (FlagTranslation ft in General.Map.Config.LinedefFlagsTranslation) { foreach (string field in ft.Fields) { stringflags[field] = GetCollectionEntry(lc, field, false, false, where); } } // Activations foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates) { stringflags[activate.Key] = GetCollectionEntry(lc, activate.Key, false, false, where); } // Check if not zero-length if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) { // Create new linedef Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]); if (l != null) { l.Update(stringflags, 0, tags, special, args); l.UpdateCache(); // Custom fields ReadCustomFields(lc, l, "linedef"); // Read sidedefs and connect them to the line if (s1 > -1) { if (s1 < sidescolls.Count) { ReadSidedef(map, sidescolls[s1], l, true, sectorlink, s1); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed."); } } if (s2 > -1) { if (s2 < sidescolls.Count) { ReadSidedef(map, sidescolls[s2], l, false, sectorlink, s2); } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed."); } } } } else { General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed."); } } }
// This reads the sectors private Dictionary <int, Sector> ReadSectors(MapSet map, UniversalParser textmap) { // Get list of entries List <UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector"); // Create lookup table Dictionary <int, Sector> link = new Dictionary <int, Sector>(collections.Count); // Go for all collections map.SetCapacity(0, 0, 0, map.Sectors.Count + collections.Count, 0); char[] splitter = new[] { ' ' }; //mxd for (int i = 0; i < collections.Count; i++) { // Read fields UniversalCollection c = collections[i]; string where = "sector " + i; int hfloor = GetCollectionEntry(c, "heightfloor", false, 0, where); int hceil = GetCollectionEntry(c, "heightceiling", false, 0, where); string tfloor = GetCollectionEntry(c, "texturefloor", true, "-", where); string tceil = GetCollectionEntry(c, "textureceiling", true, "-", where); int bright = GetCollectionEntry(c, "lightlevel", false, 160, where); int special = GetCollectionEntry(c, "special", false, 0, where); int tag = GetCollectionEntry(c, "id", false, 0, where); //mxd. MoreIDs List <int> tags = new List <int> { tag }; string moreids = GetCollectionEntry(c, "moreids", false, string.Empty, where); if (!string.IsNullOrEmpty(moreids)) { string[] moreidscol = moreids.Split(splitter, StringSplitOptions.RemoveEmptyEntries); foreach (string sid in moreidscol) { int id; if (int.TryParse(sid.Trim(), out id) && id != 0 && !tags.Contains(id)) { tags.Add(id); } } } if (tag == 0 && tags.Count > 1) { tags.RemoveAt(0); } //mxd. Read slopes float fslopex = GetCollectionEntry(c, "floorplane_a", false, 0.0f, where); float fslopey = GetCollectionEntry(c, "floorplane_b", false, 0.0f, where); float fslopez = GetCollectionEntry(c, "floorplane_c", false, 0.0f, where); float foffset = GetCollectionEntry(c, "floorplane_d", false, float.NaN, where); float cslopex = GetCollectionEntry(c, "ceilingplane_a", false, 0.0f, where); float cslopey = GetCollectionEntry(c, "ceilingplane_b", false, 0.0f, where); float cslopez = GetCollectionEntry(c, "ceilingplane_c", false, 0.0f, where); float coffset = GetCollectionEntry(c, "ceilingplane_d", false, float.NaN, where); //mxd. Read flags Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal); foreach (KeyValuePair <string, string> flag in General.Map.Config.SectorFlags) { stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where); } foreach (KeyValuePair <string, string> flag in General.Map.Config.CeilingPortalFlags) { stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where); } foreach (KeyValuePair <string, string> flag in General.Map.Config.FloorPortalFlags) { stringflags[flag.Key] = GetCollectionEntry(c, flag.Key, false, false, where); } // Create new item Sector s = map.CreateSector(); if (s != null) { s.Update(hfloor, hceil, tfloor, tceil, special, stringflags, tags, bright, foffset, new Vector3D(fslopex, fslopey, fslopez).GetNormal(), coffset, new Vector3D(cslopex, cslopey, cslopez).GetNormal()); // Custom fields ReadCustomFields(c, s, "sector"); // Add it to the lookup table link.Add(i, s); } } // Return lookup table return(link); }