/// <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); }
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); } } }
public LumpArchive(ILump lump) { if (lump == null) { throw new ArgumentNullException("lump"); } this.lump = lump; }
/// <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); } }
/// <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; }
/// <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); } } }
/// <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, })); }
/// <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, }); }
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); } } }
/// <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; }
/// <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; }
/// <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); }
/// <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; }
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);
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 LumpArchive(ILump lump) { if (lump == null) throw new ArgumentNullException("lump"); this.lump = lump; }