diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index d0fda96..d47a359 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -182,6 +182,7 @@
+
diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs
index 081e918..77f8919 100644
--- a/Source/Core/Data/DataManager.cs
+++ b/Source/Core/Data/DataManager.cs
@@ -22,6 +22,7 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
+using System.Linq;
using System.Threading;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Config;
@@ -32,6 +33,7 @@ using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
+using CodeImp.DoomBuilder.SRB2;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.ZDoom;
using SlimDX;
@@ -2092,43 +2094,81 @@ namespace CodeImp.DoomBuilder.Data
//mxd. This loads (Z)MAPINFO
private void LoadMapInfo(out Dictionary spawnnums, out Dictionary doomednums)
{
- MapinfoParser parser = new MapinfoParser { OnInclude = ParseFromLocation };
-
- // Parse mapinfo
- foreach (DataReader dr in containers)
+ if (General.Map.SRB2)
{
- currentreader = dr;
+ SOCParser parser = new SOCParser { OnInclude = ParseFromLocation };
- Dictionary streams = dr.GetMapinfoData();
- foreach (KeyValuePair group in streams)
+ // Parse mapinfo
+ foreach (DataReader dr in containers)
{
- // Parse the data
- parser.Parse(group.Value, Path.Combine(dr.Location.location, group.Key), General.Map.Options.LevelName, false);
+ currentreader = dr;
- //MAPINFO lumps are interdependable. Can't carry on...
- if (parser.HasError)
+ Dictionary streams1 = dr.GetObjctcfgData();
+ Dictionary streams2 = dr.GetMaincfgData();
+ Dictionary streams3 = dr.GetSOCData();
+ Dictionary streams = streams1.Concat(streams2).Concat(streams3).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
+
+ foreach (KeyValuePair group in streams)
{
- parser.LogError();
- break;
+ // Parse the data
+ parser.Parse(group.Value, Path.Combine(dr.Location.location, group.Key), General.Map.Options.LevelName, false);
+
+ //MAPINFO lumps are interdependable. Can't carry on...
+ if (parser.HasError)
+ {
+ parser.LogError();
+ break;
+ }
}
}
- }
- if (!parser.HasError)
- {
- // Store parsed data
- spawnnums = parser.SpawnNums;
- doomednums = parser.DoomEdNums;
- mapinfo = parser.MapInfo;
+ if (!parser.HasError)
+ mapinfo = parser.MapInfo;
+ else
+ mapinfo = new MapInfo();
+
+ spawnnums = new Dictionary();
+ doomednums = new Dictionary();
}
else
{
- // No nulls allowed!
- spawnnums = new Dictionary();
- doomednums = new Dictionary();
- mapinfo = new MapInfo();
- }
+ MapinfoParser parser = new MapinfoParser { OnInclude = ParseFromLocation };
+ // Parse mapinfo
+ foreach (DataReader dr in containers)
+ {
+ currentreader = dr;
+
+ Dictionary streams = dr.GetMapinfoData();
+ foreach (KeyValuePair group in streams)
+ {
+ // Parse the data
+ parser.Parse(group.Value, Path.Combine(dr.Location.location, group.Key), General.Map.Options.LevelName, false);
+
+ //MAPINFO lumps are interdependable. Can't carry on...
+ if (parser.HasError)
+ {
+ parser.LogError();
+ break;
+ }
+ }
+ }
+
+ if (!parser.HasError)
+ {
+ // Store parsed data
+ spawnnums = parser.SpawnNums;
+ doomednums = parser.DoomEdNums;
+ mapinfo = parser.MapInfo;
+ }
+ else
+ {
+ // No nulls allowed!
+ spawnnums = new Dictionary();
+ doomednums = new Dictionary();
+ mapinfo = new MapInfo();
+ }
+ }
currentreader = null;
}
diff --git a/Source/Core/Data/DataReader.cs b/Source/Core/Data/DataReader.cs
index 98b97cc..7194598 100644
--- a/Source/Core/Data/DataReader.cs
+++ b/Source/Core/Data/DataReader.cs
@@ -161,8 +161,17 @@ namespace CodeImp.DoomBuilder.Data
//mxd. When implemented, this returns the MAPINFO lump
public abstract Dictionary GetMapinfoData(); // { return new Dictionary(); }
- //mxd. When implemented, this returns the GLDEFS lump
- public abstract Dictionary GetGldefsData(GameType gametype); // { return new Dictionary(); }
+ //mxd. When implemented, this returns the MAINCFG lump
+ public virtual Dictionary GetMaincfgData() { return new Dictionary(); }
+
+ //mxd. When implemented, this returns the OBJCTCFG lump
+ public virtual Dictionary GetObjctcfgData() { return new Dictionary(); }
+
+ //mxd. When implemented, this returns the SOC_ lumps
+ public virtual Dictionary GetSOCData() { return new Dictionary(); }
+
+ //mxd. When implemented, this returns the GLDEFS lump
+ public abstract Dictionary GetGldefsData(GameType gametype); // { return new Dictionary(); }
//mxd. When implemented, this returns the REVERBS lump
public abstract Dictionary GetReverbsData(); // { return new Dictionary(); }
diff --git a/Source/Core/Data/WADReader.cs b/Source/Core/Data/WADReader.cs
index ef1382f..434d01c 100644
--- a/Source/Core/Data/WADReader.cs
+++ b/Source/Core/Data/WADReader.cs
@@ -835,8 +835,53 @@ namespace CodeImp.DoomBuilder.Data
return streams;
}
- //mxd
- public override Dictionary GetGldefsData(GameType gameType)
+ public override Dictionary GetMaincfgData()
+ {
+ if (issuspended) throw new Exception("Data reader is suspended");
+
+ Dictionary streams = new Dictionary(StringComparer.Ordinal);
+ string src = "MAINCFG";
+
+ //should be only one entry per wad
+ int lumpindex = file.FindLumpIndex(src);
+
+ if (lumpindex != -1) streams.Add(src, file.Lumps[lumpindex].Stream);
+ return streams;
+ }
+
+ public override Dictionary GetObjctcfgData()
+ {
+ if (issuspended) throw new Exception("Data reader is suspended");
+
+ Dictionary streams = new Dictionary(StringComparer.Ordinal);
+ string src = "OBJCTCFG";
+
+ //should be only one entry per wad
+ int lumpindex = file.FindLumpIndex(src);
+
+ if (lumpindex != -1) streams.Add(src, file.Lumps[lumpindex].Stream);
+ return streams;
+ }
+
+ public override Dictionary GetSOCData()
+ {
+ if (issuspended) throw new Exception("Data reader is suspended");
+
+ Dictionary streams = new Dictionary(StringComparer.Ordinal);
+ string prefix = "SOC_";
+
+ foreach (Lump lump in file.Lumps)
+ {
+ if (lump.Name.StartsWith(prefix))
+ {
+ streams.Add(lump.Name, lump.Stream);
+ }
+ }
+ return streams;
+ }
+
+ //mxd
+ public override Dictionary GetGldefsData(GameType gameType)
{
if(issuspended) throw new Exception("Data reader is suspended");
diff --git a/Source/Core/SRB2/SOCParser.cs b/Source/Core/SRB2/SOCParser.cs
new file mode 100644
index 0000000..2a597b8
--- /dev/null
+++ b/Source/Core/SRB2/SOCParser.cs
@@ -0,0 +1,190 @@
+#region ================== Namespaces
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using CodeImp.DoomBuilder.ZDoom;
+using CodeImp.DoomBuilder.GZBuilder.Data;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.SRB2
+{
+ internal sealed class SOCParser : ZDTextParser
+ {
+ #region ================== Delegates
+
+ public delegate void IncludeDelegate(SOCParser parser, string includefile, bool clearerror);
+ public IncludeDelegate OnInclude;
+
+ #endregion
+
+ #region ================== Variables
+
+ private MapInfo mapinfo;
+ private string mapname;
+ private readonly HashSet parsedlumps;
+ private StreamReader streamreader;
+
+ #endregion
+
+ #region ================== Properties
+
+ public MapInfo MapInfo { get { return mapinfo; } }
+
+ #endregion
+
+ #region ================== Constructor
+
+ public SOCParser()
+ {
+ // Syntax
+ whitespace = "\n \t\r\u00A0";
+ specialtokens = "=\n";
+
+ mapinfo = new MapInfo();
+ parsedlumps = new HashSet(StringComparer.OrdinalIgnoreCase);
+ }
+
+ #endregion
+
+ #region ================== Parsing
+
+ override public bool Parse(Stream stream, string sourcefilename, bool clearerrors)
+ {
+ if (string.IsNullOrEmpty(mapname)) throw new NotSupportedException("Map name required!");
+ return Parse(stream, sourcefilename, mapname, clearerrors);
+ }
+
+ public bool Parse(Stream stream, string sourcefilename, string mapname, bool clearerrors)
+ {
+ this.mapname = mapname.ToUpperInvariant();
+ if (!base.Parse(stream, sourcefilename, clearerrors)) return false;
+
+ // Keep local data
+ streamreader = new StreamReader(stream, Encoding.ASCII);
+
+ while (!streamreader.EndOfStream)
+ {
+ string line = streamreader.ReadLine();
+ if (String.IsNullOrEmpty(line) || line.StartsWith("\n") || line.StartsWith("#")) continue;
+ string[] tokens = line.Split(new char[] { ' ' });
+ switch (tokens[0].ToUpperInvariant())
+ {
+ case "LEVEL":
+ if (tokens.Length < 2 || String.IsNullOrEmpty(tokens[1]))
+ {
+ ReportError("Level block is missing a level number.");
+ break;
+ }
+ if (GetMapName(tokens[1].ToUpperInvariant()) != mapname) break;
+ if (!ParseLevelHeader(mapname)) return false;
+ break;
+ }
+ }
+
+ // All done
+ return !this.HasError;
+ }
+
+ #endregion
+
+ #region ================== Map block parsing
+
+ private bool ParseLevelHeader(string mapname)
+ {
+ if (mapname == null) return false;
+ string levelname = "";
+ int act = 0;
+ bool zone = true;
+ while (!streamreader.EndOfStream)
+ {
+ string line = streamreader.ReadLine();
+ if (String.IsNullOrEmpty(line) || line.StartsWith("\n")) break;
+ if (line.StartsWith("#")) continue;
+ string[] tokens = line.Split(new char[] { '=' });
+ if (tokens.Length != 2)
+ {
+ ReportError("Invalid line.");
+ return false;
+ }
+ tokens[0] = tokens[0].Trim().ToUpperInvariant();
+ tokens[1] = tokens[1].Trim().ToUpperInvariant();
+ switch(tokens[0])
+ {
+ case "LEVELNAME":
+ levelname = tokens[1];
+ break;
+
+ case "ACT":
+ if (!int.TryParse(tokens[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out act) || act < 0 || act >= 20)
+ {
+ ReportError("Invalid act number.");
+ return false;
+ }
+ break;
+
+ case "NOZONE":
+ zone = tokens[1][0] == 'T' || tokens[1][0] == 'Y';
+ break;
+
+ case "SKYNUM":
+ int skyn;
+ if (!int.TryParse(tokens[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out skyn))
+ {
+ ReportError("Invalid sky number.");
+ return false;
+ }
+ mapinfo.Sky1 = "SKY" + skyn;
+ break;
+ }
+ }
+ mapinfo.Title = levelname + (zone ? " ZONE" : "") + (act > 0 ? " " + act : "");
+
+ return true;
+ }
+
+ private static string GetMapName(string number)
+ {
+ int n;
+ if (int.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n))
+ return ConvertToExtendedMapNum(n);
+ else
+ {
+ if (number.Length != 2 || number[0] < 'A' || number[0] > 'Z' || number[1] < '0' || number[1] > '9') return null;
+ return "MAP" + number;
+ }
+
+ }
+
+ private static string ConvertToExtendedMapNum(int n)
+ {
+ if (n <= 0 || n > 1035)
+ return null;
+ if (n < 10)
+ return "MAP0" + n;
+ if (n < 100)
+ return "MAP" + n.ToString();
+
+ int x = n - 100;
+ int p = x / 36;
+ int q = x % 36;
+ char a = (char)('A' + p);
+ char b = (q < 10) ? (char)('0' + q) : (char)('A' + q - 10);
+ return "MAP" + String.Concat(a, b);
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ protected override string GetLanguageType()
+ {
+ return "SOC";
+ }
+
+ #endregion
+ }
+}