Beispiel #1
0
        /// <summary>
        /// Add a lump to the set. The lumps must be loaded into memory for this to work.
        /// </summary>
        /// <param name="name">The name of the entry</param>
        /// <param name="lump">The lump to add</param>
        /// <returns>The entry of the lump that was added</returns>
        public Entry AddLump(string name, ILump lump)
        {
            Entry e = new Entry(name, lump.Type);

            _lumps[e] = lump;
            return(e);
        }
Beispiel #2
0
        public BspFile(Stream stream)
        {
            using (BinaryReader br = new BinaryReader(stream, Encoding.ASCII, true))
            {
                // Read the version number
                // More recent formats have a "magic" number when different engines forked
                Magic magic = (Magic)br.ReadUInt32();
                switch (magic)
                {
                case Magic.Ibsp:
                case Magic.Vbsp:
                    Version = (Version)((br.ReadUInt32() << 32) + magic);
                    break;

                default:
                    Version = (Version)magic;
                    break;
                }

                // Initialise the reader
                IBspReader reader = _readers.First(x => x.SupportedVersion == Version);

                reader.StartHeader(this, br);

                // Read the blobs
                Blobs = new List <Blob>();
                for (int i = 0; i < reader.NumLumps; i++)
                {
                    Blob blob = reader.ReadBlob(br);
                    blob.Index = i;
                    Blobs.Add(blob);
                }

                reader.EndHeader(this, br);

                Lumps = new List <ILump>();
                foreach (Blob blob in Blobs)
                {
                    ILump lump = reader.GetLump(blob);
                    if (lump == null)
                    {
                        continue;
                    }

                    long pos = br.BaseStream.Position;
                    br.BaseStream.Seek(blob.Offset, SeekOrigin.Begin);

                    lump.Read(br, blob, Version);
                    Lumps.Add(lump);

                    br.BaseStream.Seek(pos, SeekOrigin.Begin);
                }

                foreach (ILump lump in Lumps)
                {
                    lump.PostReadProcess(this);
                }
            }
        }
Beispiel #3
0
 public LumpArchive(ILump lump)
 {
     if (lump == null)
     {
         throw new ArgumentNullException("lump");
     }
     this.lump = lump;
 }
Beispiel #4
0
 /// <summary>
 /// Load all lumps into memory. This is done already if <code>loadLumps</code> is true in the constructor.
 /// </summary>
 /// <param name="stream">The stream to load from</param>
 public void LoadLumps(Stream stream)
 {
     _lumps = new Dictionary <Entry, ILump>();
     foreach (Entry entry in Entries.OrderBy(x => x.Offset))
     {
         ILump lump = LoadLump(stream, entry);
         _lumps.Add(entry, lump);
     }
 }
Beispiel #5
0
        /// <summary>
        /// Creates a new <see cref="Leaf"/> object from a <c>byte</c> array.
        /// </summary>
        /// <param name="data"><c>byte</c> array to parse.</param>
        /// <param name="parent">The <see cref="ILump"/> this <see cref="Leaf"/> came from.</param>
        /// <exception cref="ArgumentNullException"><paramref name="data"/> was <c>null</c>.</exception>
        public Leaf(byte[] data, ILump parent = null)
        {
            if (data == null)
            {
                throw new ArgumentNullException();
            }

            Data   = data;
            Parent = parent;
        }
        /// <summary>
        /// Creates a new <see cref="DisplacementVertex"/> object from a <c>byte</c> array.
        /// </summary>
        /// <param name="data"><c>byte</c> array to parse.</param>
        /// <param name="parent">The <see cref="ILump"/> this <see cref="DisplacementVertex"/> came from.</param>
        /// <exception cref="ArgumentNullException"><paramref name="data"/> was <c>null</c>.</exception>
        public DisplacementVertex(byte[] data, ILump parent = null)
        {
            if (data == null)
            {
                throw new ArgumentNullException();
            }

            Data   = data;
            Parent = parent;
        }
Beispiel #7
0
        /// <summary>
        /// Creates a new <see cref="TextureInfo"/> object from a <c>byte</c> array.
        /// </summary>
        /// <param name="data"><c>byte</c> array to parse.</param>
        /// <param name="parent">The <see cref="ILump"/> this <see cref="TextureInfo"/> came from.</param>
        /// <exception cref="ArgumentNullException"><paramref name="data"/> was <c>null</c>.</exception>
        public TextureInfo(byte[] data, ILump parent = null)
        {
            if (data == null)
            {
                throw new ArgumentNullException();
            }

            Data     = data;
            Parent   = parent;
            scale    = new Vector2(1, 1);
            rotation = 0;
        }
        /// <summary>
        /// Enumerates over the DOOM 2 maps.
        /// </summary>
        /// <param name="wadFile">The IWAD file.</param>
        /// <returns>The list of maps.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="wadFile" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="FormatException">
        /// <paramref name="wadFile" /> has an invalid value in <see cref="IWADFile.Format" />.
        /// </exception>
        public static IEnumerable <IWADFile> EnumerateDOOM2Maps(this IWADFile wadFile)
        {
            if (wadFile == null)
            {
                throw new ArgumentNullException("wadFile");
            }

            if (wadFile.Format != WADFormat.Default)
            {
                throw new FormatException("wadFile");
            }

            using (var stream = wadFile.GetStream())
            {
                ILump         mapLump    = null;
                IList <ILump> lumpsOfMap = null;
                foreach (var lump in wadFile.EnumerateLumps())
                {
                    if ((lump.Name ?? string.Empty).ToUpper().Trim().StartsWith("MAP"))
                    {
                        if (lumpsOfMap != null)
                        {
                            using (var builder = new WADFileBuilder(true))
                            {
                                builder.AddRange(lumpsOfMap);

                                yield return(builder.Build(mapLump.Name, WADFormat.Default));
                            }
                        }

                        mapLump    = lump;
                        lumpsOfMap = new List <ILump>();

                        continue;
                    }

                    if (mapLump == null)
                    {
                        continue;
                    }

                    lumpsOfMap.Add(lump);
                }
            }
        }
Beispiel #9
0
        /// <summary>
        /// Adds a lump.
        /// </summary>
        /// <param name="lump">The lump to add.</param>
        /// <returns>That instance.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="lump" /> is <see langword="null" />.
        /// </exception>
        public WADFileBuilder Add(ILump lump)
        {
            if (lump == null)
            {
                throw new ArgumentNullException("lump");
            }

            return(this.InvokeForDisposable(
                       func: (obj, state) =>
            {
                var builder = (WADFileBuilder)obj;
                builder._LUMPS.Add(state.Lump);

                return builder;
            },
                       funcState: new
            {
                Lump = lump,
            }));
        }
Beispiel #10
0
        /// <summary>
        /// Adds a lump.
        /// </summary>
        /// <param name="lump">The lump to add.</param>
        /// <returns>That instance.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="lump" /> is <see langword="null" />.
        /// </exception>
        public WADFileBuilder Add(ILump lump)
        {
            if (lump == null)
            {
                throw new ArgumentNullException("lump");
            }

            return this.InvokeForDisposable(
                func: (obj, state) =>
                    {
                        var builder = (WADFileBuilder)obj;
                        builder._LUMPS.Add(state.Lump);

                        return builder;
                    },
                funcState: new
                    {
                        Lump = lump,
                    });
        }
Beispiel #11
0
        public override void ParseFromBuffer(BinaryReader reader)
        {
            // This is a custom parser implementation for the TF2 gamestats format
            // TF2 has extra "version" and "end tag" lumps before and after the map ones

            byte version = 0x00;
            byte magic   = 0x00;

            string currentMapName = null;
            ILump  currentVersion = null;

            // Read lumps until the stream is empty
            while (reader.BaseStream.Position != reader.BaseStream.Length)
            {
                var lump = DynamicReadLump(reader, version);
                if (lump == null)
                {
                    continue;
                }

                // Start parsing a new lump if we find a version descriptor
                if (lump.LumpId == (int)Tf2GameStatsLumpIds.Version)
                {
                    if (!(lump.Children.FirstOrDefault() is IVersion versionLump))
                    {
                        throw new InvalidOperationException();
                    }

                    version = versionLump.Version;
                    magic   = versionLump.Magic;

                    // DON'T add this lump to the list until we get a map name
                    currentVersion = lump;
                    continue;
                }

                if (lump.LumpId == (int)Tf2GameStatsLumpIds.MapHeader)
                {
                    if (!(lump.Children.FirstOrDefault() is ILevelHeader header))
                    {
                        throw new InvalidOperationException();
                    }

                    // We're on to a new lump
                    if (header.MapName != currentMapName)
                    {
                        var map = new Tf2LevelStats
                        {
                            Name = header.MapName
                        };

                        // Add the map
                        currentMapName = header.MapName;
                        Children.Add(map);

                        // Add the version lump before the map lump, so it's at the top
                        if (currentVersion != null)
                        {
                            map.Children.Add(currentVersion);
                        }
                    }
                }

                // End parsing the lump if we find an end tag
                if (lump.LumpId == (int)Tf2GameStatsLumpIds.EndTag)
                {
                    if (!(lump.Children.FirstOrDefault() is IVersion versionLump))
                    {
                        throw new InvalidOperationException();
                    }

                    // Sanity checking
                    if (version != versionLump.Version || magic != versionLump.Magic)
                    {
                        throw new InvalidOperationException("Header and end tag version and magic values did not match!");
                    }

                    currentVersion = null;
                }

                if (currentMapName == null)
                {
                    continue;
                }

                // Add the current lump to the map entity
                var currentMap = Children.FirstOrDefault(m => ((ILevelStats)m).Name == currentMapName);
                currentMap?.Children.Add(lump);

                // Run post-lump reading
                if (currentMap is ICustomLevelStats customMap)
                {
                    customMap.PostReadLumps(reader);
                }
            }
        }
Beispiel #12
0
 /// <summary>
 /// Initializes a new instance of an <see cref="Entity"/> object, copying the attributes, connections and brushes of the passed <see cref="Entity"/>.
 /// </summary>
 /// <param name="copy">The <see cref="Entity"/> to copy.</param>
 public Entity(Entity copy, ILump parent = null) : base(copy, StringComparer.InvariantCultureIgnoreCase)
 {
     connections = new List <EntityConnection>(copy.connections);
     brushes     = new List <MAPBrush>(copy.brushes);
     Parent      = parent;
 }
Beispiel #13
0
 /// <summary>
 /// Initializes a new instance of an <see cref="Entity"/> object with no initial properties.
 /// </summary>
 public Entity(ILump parent = null) : base(StringComparer.InvariantCultureIgnoreCase)
 {
     Parent = parent;
 }
Beispiel #14
0
 /// <summary>
 /// Initializes a new instance of an <see cref="Entity"/> with the given classname.
 /// </summary>
 /// <param name="className">Classname of the new <see cref="Entity"/>.</param>
 public Entity(string className, ILump parent = null) : this(parent) {
     Add("classname", className);
 }
Beispiel #15
0
 /// <summary>
 /// Initializes a new instance of an <see cref="Entity"/>, parsing the given <c>byte</c> array into an <see cref="Entity"/> structure.
 /// </summary>
 /// <param name="data">Array to parse.</param>
 /// <param name="type">The map type.</param>
 /// <param name="version">The version of this lump.</param>
 public Entity(byte[] data, ILump parent = null)
 {
     Parent = parent;
     Data   = data;
 }
Beispiel #16
0
        private void UpdateLumpDetails(ILump lump)
        {
            try
            {
                this.SplitContainer_LumpDetails.Panel2.Tag = lump;
                this.SplitContainer_LumpDetails.Panel2.Visible = false;

                if (lump == null)
                {
                    return;
                }

                this.RichTextBox_LumpDetails.Text = "";

                using (var stream = lump.GetStream())
                {
                    const int LINE_SIZE = 8;

                    var lines = new List<IList<byte>>();

                    IList<byte> currentLine = null;
                    for (var i = 0L; i < stream.Length; i++)
                    {
                        var @byte = (byte)stream.ReadByte();

                        if (i % LINE_SIZE == 0)
                        {
                            currentLine = new List<byte>();
                            lines.Add(currentLine);
                        }

                        currentLine.Add(@byte);
                    }

                    var sb = new StringBuilder();

                    using (var writer = new StringWriter(sb))
                    {
                        writer.WriteLine(string.Format("Name: {0}", lump.Name));
                        writer.WriteLine(string.Format("Position: {0}", lump.Position));
                        writer.WriteLine(string.Format("Size: {0}", lump.Size));

                        writer.WriteLine();
                        writer.WriteLine();

                        foreach (var l in lines)
                        {
                            foreach (var @byte in l)
                            {
                                writer.Write(string.Format("{0:X2} ", @byte));
                            }

                            for (var i = 0; i < (LINE_SIZE - l.Count); i++)
                            {
                                writer.Write("   ");
                            }

                            writer.Write("      ");

                            var str = Encoding.ASCII.GetString(l.ToArray());
                            foreach (var @char in str)
                            {
                                var charToWrite = @char.ToString();
                                if (char.IsLetterOrDigit(@char))
                                {
                                    charToWrite = @char + " ";
                                }
                                else
                                {
                                    charToWrite = "  ";
                                }

                                writer.Write(string.Format("{0} ",
                                                           charToWrite.PadLeft(2, ' ')));
                            }

                            writer.WriteLine();
                        }

                        writer.Flush();
                        writer.Close();
                    }

                    this.RichTextBox_LumpDetails.Text = sb.ToString();
                }

                this.SplitContainer_LumpDetails.Panel2.Visible = true;
            }
            catch (Exception ex)
            {
                this.ShowError(ex);
            }
        }
 public void Append(ILump lump) => _lumps.Add(lump);
Beispiel #18
0
        private void UpdateLumpDetails(ILump lump)
        {
            try
            {
                this.SplitContainer_LumpDetails.Panel2.Tag     = lump;
                this.SplitContainer_LumpDetails.Panel2.Visible = false;

                if (lump == null)
                {
                    return;
                }

                this.RichTextBox_LumpDetails.Text = "";

                using (var stream = lump.GetStream())
                {
                    const int LINE_SIZE = 8;

                    var lines = new List <IList <byte> >();

                    IList <byte> currentLine = null;
                    for (var i = 0L; i < stream.Length; i++)
                    {
                        var @byte = (byte)stream.ReadByte();

                        if (i % LINE_SIZE == 0)
                        {
                            currentLine = new List <byte>();
                            lines.Add(currentLine);
                        }

                        currentLine.Add(@byte);
                    }

                    var sb = new StringBuilder();

                    using (var writer = new StringWriter(sb))
                    {
                        writer.WriteLine(string.Format("Name: {0}", lump.Name));
                        writer.WriteLine(string.Format("Position: {0}", lump.Position));
                        writer.WriteLine(string.Format("Size: {0}", lump.Size));

                        writer.WriteLine();
                        writer.WriteLine();

                        foreach (var l in lines)
                        {
                            foreach (var @byte in l)
                            {
                                writer.Write(string.Format("{0:X2} ", @byte));
                            }

                            for (var i = 0; i < (LINE_SIZE - l.Count); i++)
                            {
                                writer.Write("   ");
                            }

                            writer.Write("      ");

                            var str = Encoding.ASCII.GetString(l.ToArray());
                            foreach (var @char in str)
                            {
                                var charToWrite = @char.ToString();
                                if (char.IsLetterOrDigit(@char))
                                {
                                    charToWrite = @char + " ";
                                }
                                else
                                {
                                    charToWrite = "  ";
                                }

                                writer.Write(string.Format("{0} ",
                                                           charToWrite.PadLeft(2, ' ')));
                            }

                            writer.WriteLine();
                        }

                        writer.Flush();
                        writer.Close();
                    }

                    this.RichTextBox_LumpDetails.Text = sb.ToString();
                }

                this.SplitContainer_LumpDetails.Panel2.Visible = true;
            }
            catch (Exception ex)
            {
                this.ShowError(ex);
            }
        }
Beispiel #19
0
 public LumpArchive(ILump lump)
 {
     if (lump == null)
         throw new ArgumentNullException("lump");
     this.lump = lump;
 }