Add SOC parser for level headers, plus some cleanup

This commit is contained in:
spherallic 2023-10-10 14:05:59 +02:00
parent e2e7afa733
commit 24939e7de8
5 changed files with 146 additions and 16 deletions

View file

@ -312,6 +312,7 @@
<Compile Include="Rendering\Vector4.cs" />
<Compile Include="Rendering\VertexBuffer.cs" />
<Compile Include="Rendering\VisualSlopeHandle.cs" />
<Compile Include="SRB2\SOCLevelHeader.cs" />
<Compile Include="SRB2\SOCMobjStructure.cs" />
<Compile Include="SRB2\LuaMobjStructure.cs" />
<Compile Include="SRB2\SOCParser.cs" />

View file

@ -471,6 +471,11 @@ namespace CodeImp.DoomBuilder.Data
LoadInternalSprites();
LoadInternalTextures(); //mxd
// Load SRB2 map information from parsed level headers
string mapname = General.Map.Options.LevelName.ToLowerInvariant();
if (soc.MapHeaders.ContainsKey(mapname))
mapinfo = soc.MapHeaders[mapname];
//mxd. Load more stuff
LoadReverbs();
LoadSndSeq();
@ -1866,7 +1871,6 @@ namespace CodeImp.DoomBuilder.Data
data.Stream.Seek(0, SeekOrigin.Begin);
lua.Parse(data, true);
//mxd. DECORATE lumps are interdepandable. Can't carry on...
if (lua.HasError)
{
lua.LogError();
@ -1882,7 +1886,7 @@ namespace CodeImp.DoomBuilder.Data
lua.ClearActors();
}
// sphere: This loads things from SRB2 Lua files.
// sphere: This loads things and level headers from SRB2 SOC files.
private void LoadSOCThings()
{
// Create new parser
@ -1900,7 +1904,6 @@ namespace CodeImp.DoomBuilder.Data
data.Stream.Seek(0, SeekOrigin.Begin);
soc.Parse(data, true);
//mxd. DECORATE lumps are interdepandable. Can't carry on...
if (soc.HasError)
{
soc.LogError();
@ -1984,7 +1987,7 @@ namespace CodeImp.DoomBuilder.Data
ThingCategory cat = GetThingCategory(null, thingcategories, GetCategoryInfo(actor)); //mxd
// Add new thing
ThingTypeInfo t = new ThingTypeInfo(cat, actor); ;
ThingTypeInfo t = new ThingTypeInfo(cat, actor);
cat.AddThing(t);
thingtypes.Add(t.Index, t);

View file

@ -0,0 +1,87 @@
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.Types;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace CodeImp.DoomBuilder.ZDoom
{
public sealed class SOCLevelHeader
{
#region ================== Variables
private MapInfo mapinfo;
#endregion
#region ================== Properties
public MapInfo MapInfo { get { return mapinfo; } }
#endregion
#region ================== SOC level header parsing
internal SOCLevelHeader(ZDTextParser zdparser)
{
mapinfo = new MapInfo();
string levelname = "Unnamed map";
int actnum = 0;
bool nozone = false;
SOCParser parser = (SOCParser)zdparser;
// Now parse the contents of actor structure
string line = parser.ReadLine();
while (line != null)
{
line = parser.ReadLine();
if (string.IsNullOrEmpty(line) || line.StartsWith("\n")) break;
if (line.StartsWith("#")) continue;
line = line.Split(new char[] { '#' })[0];
string[] tokens = line.Split(new char[] { '=' });
if (tokens.Length != 2)
{
parser.ReportError("Invalid line");
return;
}
tokens[0] = tokens[0].Trim().ToLowerInvariant();
tokens[1] = tokens[1].Trim();
//mxd. Translate scale to xscale and yscale
switch (tokens[0])
{
case "levelname":
levelname = tokens[1];
break;
case "act":
actnum = int.Parse(tokens[1]);
break;
case "nozone":
string value = tokens[1].ToLowerInvariant();
nozone = (value.StartsWith("t") || value.StartsWith("y"));
break;
case "skynum":
mapinfo.Sky1 = "SKY" + tokens[1];
break;
default:
break;
}
}
mapinfo.Title = levelname + (nozone ? "" : " Zone") + (actnum > 0 ? ", Act " + actnum : "");
}
#endregion
}
}

View file

@ -12,7 +12,7 @@ namespace CodeImp.DoomBuilder.ZDoom
public sealed class SOCMobjStructure : ActorStructure
{
#region ================== SOC Actor Structure parsing
#region ================== SOC Mobj Structure parsing
internal SOCMobjStructure(ZDTextParser zdparser, string objname)
{

View file

@ -19,10 +19,9 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Types;
using CodeImp.DoomBuilder.GZBuilder.Data;
#endregion
@ -49,6 +48,7 @@ namespace CodeImp.DoomBuilder.ZDoom
// SRB2 mobjs
private Dictionary<int, ActorStructure> mobjs;
private Dictionary<string, MapInfo> mapheaders;
//mxd. Includes tracking
private HashSet<string> parsedlumps;
@ -67,6 +67,7 @@ namespace CodeImp.DoomBuilder.ZDoom
/// All mobjs that are supported by the current game.
/// </summary>
public ICollection<ActorStructure> Mobjs { get { return mobjs.Values; } }
public Dictionary<string, MapInfo> MapHeaders { get { return mapheaders; } }
#endregion
@ -87,7 +88,7 @@ namespace CodeImp.DoomBuilder.ZDoom
public void Dispose()
{
mobjs = null;
mapheaders = null;
isdisposed = true;
}
@ -124,9 +125,6 @@ namespace CodeImp.DoomBuilder.ZDoom
if (!string.IsNullOrEmpty(token))
{
string objname = null;
//General.WriteLogLine("token = " + token);
token = token.ToLowerInvariant();
// SOC object
@ -136,11 +134,9 @@ namespace CodeImp.DoomBuilder.ZDoom
token = ReadToken();
if (!token.ToUpper().StartsWith("MT_"))
{
continue;
}
objname = token;
string objname = token;
// Read actor structure
ActorStructure mobj = new SOCMobjStructure(this, objname);
@ -154,8 +150,15 @@ namespace CodeImp.DoomBuilder.ZDoom
SkipWhitespace(true, true);
token = ReadToken();
if (!(token.Length > 2))
General.WriteLogLine("Map token: MAP" + token);
string mapname = GetMapName(token);
if (mapname == null)
continue;
SOCLevelHeader levelheader = new SOCLevelHeader(this);
if (this.HasError) return false;
mapheaders[mapname.ToLowerInvariant()] = levelheader.MapInfo;
}
}
}
@ -178,9 +181,45 @@ namespace CodeImp.DoomBuilder.ZDoom
{
// Initialize
mobjs = new Dictionary<int, ActorStructure>();
mapheaders = new Dictionary<string, MapInfo>();
parsedlumps = new HashSet<string>(StringComparer.OrdinalIgnoreCase); //mxd
}
private string GetMapName(string number)
{
if (int.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out int n))
return ConvertToExtendedMapNum(n);
else
{
if (number.Length != 2 || number[0] < 'A' || number[0] > 'Z' || !((number[1] >= '0' && number[1] <= '9') || (number[1] >= 'A' && number[1] <= 'Z')))
{
//ReportError("Invalid level number");
return null;
}
return "MAP" + number;
}
}
private string ConvertToExtendedMapNum(int n)
{
if (n <= 0 || n > 1035)
{
//ReportError("Invalid level number");
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
}
}