UltimateZoneBuilder/Source/Core/ZDoom/LockDefsParser.cs

207 lines
5.1 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Rendering;
namespace CodeImp.DoomBuilder.ZDoom
{
internal sealed class LockDefsParser :ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.LOCKDEFS; } }
private Dictionary<int, string> locks;
private Dictionary<int, PixelColor> mapcolors;
public Dictionary<int, PixelColor> MapColors { get { return mapcolors; } }
public LockDefsParser()
{
locks = new Dictionary<int, string>();
mapcolors = new Dictionary<int, PixelColor>();
}
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
int locknum = -1;
string locktitle = string.Empty;
string game = string.Empty;
int bracelevel = 0;
long lockstartpos = -1;
PixelColor mapcolor = new PixelColor();
while(SkipWhitespace(true))
{
string token = ReadToken().ToLowerInvariant();
if(string.IsNullOrEmpty(token)) continue;
switch(token)
{
case "clearlocks":
if(bracelevel == 0)
{
locks.Clear();
}
else
{
ReportError("Unexpected \"CLEARLOCKS\" keyword");
return false;
}
break;
// LOCK locknumber [game]
case "lock":
SkipWhitespace(false);
if(!ReadSignedInt(ref locknum))
{
ReportError("Expected lock number");
return false;
}
//wiki: The locknumber must be in the 1-to-255 range
if(locknum < 1 || locknum > 255)
{
ReportError("The locknumber must be in the [1 .. 255] range, but is " + locknum);
return false;
}
// Store position
lockstartpos = datastream.Position;
SkipWhitespace(true);
token = ReadToken().ToLowerInvariant();
if(!string.IsNullOrEmpty(token))
{
if(token == "{")
{
bracelevel++;
}
//Should be game
else if(!GameType.GameTypes.Contains(token))
{
LogWarning("Lock " + locknum + " is defined for unknown game \"" + token + "\"");
}
else
{
game = token;
}
}
break;
case "$title":
SkipWhitespace(false);
locktitle = StripQuotes(ReadToken(false));
break;
// Mapcolor r g b
case "mapcolor":
int r = 0;
int g = 0;
int b = 0;
SkipWhitespace(false);
if(!ReadSignedInt(ref r))
{
ReportError("Expected Mapcolor Red value");
return false;
}
if(r < 0 || r > 255)
{
ReportError("Mapcolor Red value must be in [0 .. 255] range, but is " + r);
return false;
}
SkipWhitespace(false);
if(!ReadSignedInt(ref g))
{
ReportError("Expected Mapcolor Green value");
return false;
}
if(g < 0 || g > 255)
{
ReportError("Mapcolor Green value must be in [0 .. 255] range, but is " + g);
return false;
}
SkipWhitespace(false);
if(!ReadSignedInt(ref b))
{
ReportError("Expected Mapcolor Blue value");
return false;
}
if(b < 0 || b > 255)
{
ReportError("Mapcolor Blue value must be in [0 .. 255] range, but is " + b);
return false;
}
mapcolor = new PixelColor(255, (byte)r, (byte)g, (byte)b);
break;
case "{":
bracelevel++;
break;
case "}":
if(--bracelevel > 0) continue;
// Add to collection?
if(locknum > 0 && (string.IsNullOrEmpty(game) || General.Map.Config.BaseGame == game))
{
// No custom title given?
if(string.IsNullOrEmpty(locktitle))
{
locktitle = "Lock " + locknum;
}
// Lock already defined?
if(locks.ContainsKey(locknum))
{
// Do some stream poition hacking to make the warning point to the correct line
long curpos = datastream.Position;
if(lockstartpos != -1) datastream.Position = lockstartpos;
LogWarning("Lock " + locknum + " is double-defined as \"" + locks[locknum] + "\" and \"" + locktitle + "\"");
datastream.Position = curpos;
}
// Add to collections
locks[locknum] = locktitle;
if(mapcolor.a == 255) mapcolors[locknum] = mapcolor;
}
// Reset values
locknum = -1;
locktitle = string.Empty;
game = string.Empty;
mapcolor = new PixelColor();
lockstartpos = -1;
break;
}
}
return true;
}
public EnumList GetLockDefs()
{
EnumList result = new EnumList(locks.Count);
foreach(KeyValuePair<int, string> group in locks)
result.Add(new EnumItem(group.Key.ToString(), group.Value));
return result;
}
}
}