Esempio n. 1
0
        // This reads the linedefs and sidedefs
        private static void ReadLines(MapSet map, BinaryReader reader, Dictionary <int, Vertex> vertexlink, Dictionary <int, BuildSector> sectorlink, Dictionary <int, BuildWall> sidedeflink)
        {
            int count = reader.ReadInt32();

            // Go for all lines
            map.SetCapacity(0, map.Linedefs.Count + count, map.Sidedefs.Count + sidedeflink.Count, 0, 0);
            for (int i = 0; i < count; i++)
            {
                int v1 = reader.ReadInt32();
                int v2 = reader.ReadInt32();
                int s1 = reader.ReadInt32();
                int s2 = reader.ReadInt32();

                // 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();
                        l.UpdateCache();

                        // Connect walls to the line
                        if (s1 > -1)
                        {
                            if (s1 < sidedeflink.Count)
                            {
                                AddWall(map, sidedeflink[s1], l, true, sectorlink);
                            }
                            else
                            {
                                General.ErrorLogger.Add(ErrorType.Warning, "Line " + i + " references invalid front wall " + s1 + ". Wall has been removed.");
                            }
                        }

                        if (s2 > -1)
                        {
                            if (s2 < sidedeflink.Count)
                            {
                                AddWall(map, sidedeflink[s2], l, false, sectorlink);
                            }
                            else
                            {
                                General.ErrorLogger.Add(ErrorType.Warning, "Line " + i + " references invalid back wall " + s1 + ". Wall has been removed.");
                            }
                        }
                    }
                }
                else
                {
                    General.ErrorLogger.Add(ErrorType.Warning, "Line " + i + " is zero-length. Line has been removed.");
                }
            }
        }
Esempio n. 2
0
        // This splits this line by vertex v
        // Returns the new line resulting from the split, or null when it failed
        public Linedef Split(Vertex v)
        {
            Linedef nl;
            Sidedef nsd;

            if (v == null)
            {
                return(null);
            }

            // Copy linedef and change vertices
            nl = map.CreateLinedef(v, end);
            if (nl == null)
            {
                return(null);
            }
            CopyPropertiesTo(nl);
            SetEndVertex(v);
            nl.Selected = this.Selected;
            nl.marked   = this.marked;

            // Copy front sidedef if exists
            if (front != null)
            {
                nsd = map.CreateSidedef(nl, true, front.Sector);
                if (nsd == null)
                {
                    return(null);
                }
                front.CopyPropertiesTo(nsd);
                nsd.Marked = front.Marked;

                // Make texture offset adjustments
                nsd.OffsetX += (int)Vector2D.Distance(this.start.Position, this.end.Position);
            }

            // Copy back sidedef if exists
            if (back != null)
            {
                nsd = map.CreateSidedef(nl, false, back.Sector);
                if (nsd == null)
                {
                    return(null);
                }
                back.CopyPropertiesTo(nsd);
                nsd.Marked = back.Marked;

                // Make texture offset adjustments
                back.OffsetX += (int)Vector2D.Distance(nl.start.Position, nl.end.Position);
            }

            // Return result
            General.Map.IsChanged = true;
            return(nl);
        }
Esempio n. 3
0
        // This reads the LINEDEFS and SIDEDEFS from WAD file
        private void ReadLinedefs(MapSet map, int firstindex,
                                  Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink)
        {
            int[] args = new int[Linedef.NUM_ARGS];

            // Get the linedefs lump from wad file
            Lump linedefslump = wad.FindLump("LINEDEFS", firstindex);

            if (linedefslump == null)
            {
                throw new Exception("Could not find required lump LINEDEFS!");
            }

            // Get the sidedefs lump from wad file
            Lump sidedefslump = wad.FindLump("SIDEDEFS", firstindex);

            if (sidedefslump == null)
            {
                throw new Exception("Could not find required lump SIDEDEFS!");
            }

            // Prepare to read the items
            MemoryStream linedefsmem = new MemoryStream(linedefslump.Stream.ReadAllBytes());
            MemoryStream sidedefsmem = new MemoryStream(sidedefslump.Stream.ReadAllBytes());
            int          num         = (int)linedefslump.Stream.Length / 16;
            int          numsides    = (int)sidedefslump.Stream.Length / 30;
            BinaryReader readline    = new BinaryReader(linedefsmem);
            BinaryReader readside    = new BinaryReader(sidedefsmem);

            // Read items from the lump
            map.SetCapacity(0, map.Linedefs.Count + num, map.Sidedefs.Count + numsides, 0, 0);
            for (int i = 0; i < num; i++)
            {
                // Read properties from stream
                int v1     = readline.ReadUInt16();
                int v2     = readline.ReadUInt16();
                int flags  = readline.ReadUInt16();
                int action = readline.ReadByte();
                args[0] = readline.ReadByte();
                args[1] = readline.ReadByte();
                args[2] = readline.ReadByte();
                args[3] = readline.ReadByte();
                args[4] = readline.ReadByte();
                int s1 = readline.ReadUInt16();
                int s2 = readline.ReadUInt16();

                // Make string flags
                Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal);
                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)
                    {
                        Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
                        l.Update(stringflags, (flags & manager.Config.LinedefActivationsFilter), new List <int> {
                            0
                        }, action, args);
                        l.UpdateCache();

                        Sidedef s;
                        string  thigh, tmid, tlow;
                        int     offsetx, offsety, sc;

                        // 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();
        }
Esempio n. 4
0
        // This reads the linedefs and sidedefs
        private static void ReadLinedefs(MapSet map, BinaryReader reader, Dictionary <int, Vertex> vertexlink, Dictionary <int, Sector> sectorlink, Dictionary <int, SidedefData> sidedeflink)
        {
            int count = reader.ReadInt32();

            // Go for all lines
            map.SetCapacity(0, map.Linedefs.Count + count, map.Sidedefs.Count + sidedeflink.Count, 0, 0);
            for (int i = 0; i < count; i++)
            {
                int[] args    = new int[Linedef.NUM_ARGS];
                int   v1      = reader.ReadInt32();
                int   v2      = reader.ReadInt32();
                int   s1      = reader.ReadInt32();
                int   s2      = reader.ReadInt32();
                int   special = reader.ReadInt32();
                for (int a = 0; a < Linedef.NUM_ARGS; a++)
                {
                    args[a] = reader.ReadInt32();
                }
                int        numtags = reader.ReadInt32();          //mxd
                List <int> tags    = new List <int>(numtags);     //mxd
                for (int a = 0; a < numtags; a++)
                {
                    tags.Add(reader.ReadInt32());                                              //mxd
                }
                //flags
                Dictionary <string, bool> stringflags = new Dictionary <string, bool>(StringComparer.Ordinal);
                int numFlags = reader.ReadInt32();
                for (int f = 0; f < numFlags; f++)
                {
                    stringflags.Add(ReadString(reader), reader.ReadBoolean());
                }

                //add missing flags
                foreach (KeyValuePair <string, string> flag in General.Map.Config.LinedefFlags)
                {
                    if (stringflags.ContainsKey(flag.Key))
                    {
                        continue;
                    }
                    stringflags.Add(flag.Key, false);
                }

                //add missing activations
                foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
                {
                    if (stringflags.ContainsKey(activate.Key))
                    {
                        continue;
                    }
                    stringflags.Add(activate.Key, false);
                }

                // Read custom fields
                Dictionary <string, UniValue> fields = ReadCustomFields(reader);

                // 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();

                        // Add custom fields
                        l.Fields.BeforeFieldsChange();
                        foreach (KeyValuePair <string, UniValue> group in fields)
                        {
                            l.Fields.Add(group.Key, group.Value);
                        }

                        // Connect sidedefs to the line
                        if (s1 > -1)
                        {
                            if (s1 < sidedeflink.Count)
                            {
                                AddSidedef(map, sidedeflink[s1], l, true, sectorlink);
                            }
                            else
                            {
                                General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed.");
                            }
                        }

                        if (s2 > -1)
                        {
                            if (s2 < sidedeflink.Count)
                            {
                                AddSidedef(map, sidedeflink[s2], l, false, sectorlink);
                            }
                            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.");
                }
            }
        }
Esempio n. 5
0
        // 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.");
                }
            }
        }
Esempio n. 6
0
        private static void CreateWalls(MapSet map, List <BuildWall> walls, List <BuildSector> sectors)
        {
            // Count how many lines and walls we will actually create...
            int numwalls            = walls.Count;
            int numdoublesidedwalls = 0;

            foreach (BuildWall w in walls)
            {
                if (w == null)
                {
                    numwalls--;
                }
                else if (w.OtherWallIndex > -1)
                {
                    numdoublesidedwalls++;
                }
            }

            int numlines = numwalls - (numdoublesidedwalls / 2);

            // Walls are stored per-sector
            map.SetCapacity(0, map.Linedefs.Count + numlines, map.Sidedefs.Count + numwalls, 0, 0);
            Dictionary <int, Linedef> newlines = new Dictionary <int, Linedef>();           // <wall index, line>

            int walloffset = 0;

            foreach (BuildSector bs in sectors)
            {
                for (int i = walloffset; i < walloffset + bs.WallsCount; i++)
                {
                    BuildWall w = walls[i];
                    if (w == null)
                    {
                        continue;
                    }

                    // Line already created?
                    if (w.OtherWallIndex > -1 && newlines.ContainsKey(w.OtherWallIndex))
                    {
                        // Add back side
                        Sidedef back = map.CreateSidedef(newlines[w.OtherWallIndex], false, bs.Sector);
                        back.Update(w);
                        w.Side = back;
                    }
                    else
                    {
                        // Create line
                        Linedef l = map.CreateLinedef(w.Start, w.End);
                        l.Update();
                        l.UpdateCache();

                        // Add front side
                        Sidedef front = map.CreateSidedef(l, true, bs.Sector);
                        front.Update(w);
                        w.Side = front;

                        // Add to collection
                        newlines[i] = l;
                    }
                }

                walloffset += bs.WallsCount;
            }

            // Set Sector FirstWalls
            for (int i = 0; i < sectors.Count; i++)
            {
                int wallindex = sectors[i].FirstWallIndex;
                if (wallindex < 0 || wallindex >= walls.Count)
                {
                    General.ErrorLogger.Add(ErrorType.Error, "Failed to set First Wall " + wallindex + " of sector " + i + ": corresponding wall does not exist!");
                }
                else
                {
                    sectors[i].Sector.FirstWall = walls[wallindex].Side;
                }
            }
        }
        // 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.");
                }
            }
        }
Esempio n. 8
0
        // 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();
        }