mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-29 07:01:55 +00:00
225 lines
5.1 KiB
C#
225 lines
5.1 KiB
C#
|
|
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
|
|
|
/*
|
|
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
|
* This program is released under GNU General Public License
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#endregion
|
|
|
|
#region ================== Namespaces
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using CodeImp.DoomBuilder.Config;
|
|
using CodeImp.DoomBuilder.Data;
|
|
using CodeImp.DoomBuilder.GZBuilder.Data;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.ZDoom
|
|
{
|
|
public sealed class SOCParser : ZDTextParser
|
|
{
|
|
#region ================== Delegates
|
|
|
|
public delegate void IncludeDelegate(LuaParser parser, string includefile);
|
|
|
|
public IncludeDelegate OnInclude;
|
|
|
|
#endregion
|
|
|
|
#region ================== Constants
|
|
|
|
#endregion
|
|
|
|
#region ================== Variables
|
|
|
|
//mxd. Script type
|
|
internal override ScriptType ScriptType { get { return ScriptType.SOC; } }
|
|
|
|
// SRB2 mobjs
|
|
private Dictionary<int, ActorStructure> mobjs;
|
|
private Dictionary<string, MapInfo> mapheaders;
|
|
|
|
//mxd. Includes tracking
|
|
private HashSet<string> parsedlumps;
|
|
|
|
//mxd. Disposing. Is that really needed?..
|
|
private bool isdisposed;
|
|
|
|
//
|
|
public bool NoWarnings = false;
|
|
|
|
#endregion
|
|
|
|
#region ================== Properties
|
|
|
|
/// <summary>
|
|
/// 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
|
|
|
|
#region ================== Constructor / Disposer
|
|
|
|
// Constructor
|
|
public SOCParser()
|
|
{
|
|
// Syntax
|
|
whitespace = "\n \t\r\u00A0"; //mxd. non-breaking space is also space :)
|
|
specialtokens = "=\n";
|
|
skipregions = false; //mxd
|
|
|
|
ClearActors();
|
|
}
|
|
|
|
// Disposer
|
|
public void Dispose()
|
|
{
|
|
mobjs = null;
|
|
mapheaders = null;
|
|
isdisposed = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Parsing
|
|
|
|
protected internal override void LogWarning(string message, int linenumber)
|
|
{
|
|
if (NoWarnings)
|
|
return;
|
|
base.LogWarning(message, linenumber);
|
|
}
|
|
|
|
// This parses the given SOC stream
|
|
// Returns false on errors
|
|
public override bool Parse(TextResourceData data, bool clearerrors)
|
|
{
|
|
//mxd. Already parsed?
|
|
if(!base.AddTextResource(data))
|
|
{
|
|
if(clearerrors) ClearError();
|
|
return true;
|
|
}
|
|
|
|
// Cannot process?
|
|
if(!base.Parse(data, clearerrors)) return false;
|
|
|
|
// Continue until at the end of the stream
|
|
while (SkipWhitespace(true, true))
|
|
{
|
|
// Read a token
|
|
string token = ReadToken(true, true);
|
|
|
|
if (!string.IsNullOrEmpty(token))
|
|
{
|
|
token = token.ToLowerInvariant();
|
|
|
|
// SOC object
|
|
if (token.StartsWith("thing") || token.EndsWith("mobj") || token.EndsWith("object"))
|
|
{
|
|
SkipWhitespace(true, true);
|
|
token = ReadToken(true, true);
|
|
|
|
if (!token.ToUpper().StartsWith("MT_"))
|
|
continue;
|
|
|
|
string objname = token;
|
|
|
|
// Read actor structure
|
|
ActorStructure mobj = new SOCMobjStructure(this, objname);
|
|
if (this.HasError) return false;
|
|
|
|
mobjs[mobj.DoomEdNum] = mobj;
|
|
}
|
|
// Level header
|
|
else if (token.Equals("level"))
|
|
{
|
|
SkipWhitespace(true, true);
|
|
token = ReadToken(true, true);
|
|
|
|
string mapname = GetMapName(token);
|
|
|
|
if (mapname == null)
|
|
continue;
|
|
|
|
SOCLevelHeader levelheader = new SOCLevelHeader(this);
|
|
if (this.HasError) return false;
|
|
|
|
mapheaders[mapname.ToLowerInvariant()] = levelheader.MapInfo;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Return true when no errors occurred
|
|
return (ErrorDescription == null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
public ActorStructure GetMobjByDoomEdNum(int doomednum)
|
|
{
|
|
return mobjs.ContainsKey(doomednum) ? mobjs[doomednum] : null;
|
|
}
|
|
|
|
internal void ClearActors()
|
|
{
|
|
// 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
|
|
}
|
|
}
|