2016-04-13 14:11:35 +00:00
|
|
|
|
#region ================== Namespaces
|
|
|
|
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Globalization;
|
2021-03-06 21:51:22 +00:00
|
|
|
|
using System.IO;
|
2016-04-13 14:11:35 +00:00
|
|
|
|
using CodeImp.DoomBuilder.Config;
|
|
|
|
|
using CodeImp.DoomBuilder.Data;
|
|
|
|
|
using CodeImp.DoomBuilder.Rendering;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
namespace CodeImp.DoomBuilder.ZDoom
|
|
|
|
|
{
|
|
|
|
|
internal sealed class CvarInfoParser : ZDTextParser
|
|
|
|
|
{
|
|
|
|
|
#region ================== Variables
|
|
|
|
|
|
|
|
|
|
private CvarsCollection cvars;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Properties
|
|
|
|
|
|
|
|
|
|
internal override ScriptType ScriptType { get { return ScriptType.CVARINFO; } }
|
|
|
|
|
|
|
|
|
|
public CvarsCollection Cvars { get { return cvars; } }
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Constructor
|
|
|
|
|
|
|
|
|
|
internal CvarInfoParser()
|
|
|
|
|
{
|
|
|
|
|
cvars = new CvarsCollection();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Parsing
|
|
|
|
|
|
|
|
|
|
public override bool Parse(TextResourceData data, bool clearerrors)
|
|
|
|
|
{
|
|
|
|
|
// 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
|
|
|
|
|
HashSet<string> knowntypes = new HashSet<string> { "int", "float", "color", "bool", "string" };
|
2021-03-06 21:51:22 +00:00
|
|
|
|
HashSet<string> flags = new HashSet<string> { "noarchive", "cheat", "latch" };
|
2016-04-13 14:11:35 +00:00
|
|
|
|
while(SkipWhitespace(true))
|
|
|
|
|
{
|
|
|
|
|
string token = ReadToken().ToLowerInvariant();
|
|
|
|
|
if(string.IsNullOrEmpty(token)) continue;
|
|
|
|
|
|
2021-03-06 21:51:22 +00:00
|
|
|
|
//<scope> [noarchive] [cheat] [latch] <type> <name> [= <defaultvalue>];
|
2016-04-13 14:11:35 +00:00
|
|
|
|
switch(token)
|
|
|
|
|
{
|
2021-03-06 22:07:04 +00:00
|
|
|
|
case "user":
|
|
|
|
|
case "server":
|
|
|
|
|
case "nosave":
|
2021-03-06 21:51:22 +00:00
|
|
|
|
// read (skip) flags
|
|
|
|
|
while(true)
|
2016-04-13 14:11:35 +00:00
|
|
|
|
{
|
2021-03-06 21:51:22 +00:00
|
|
|
|
string flagtoken;
|
|
|
|
|
|
2016-04-13 14:11:35 +00:00
|
|
|
|
SkipWhitespace(true);
|
2021-03-06 21:51:22 +00:00
|
|
|
|
flagtoken = ReadToken().ToLowerInvariant();
|
|
|
|
|
|
|
|
|
|
if(!flags.Contains(flagtoken))
|
|
|
|
|
{
|
|
|
|
|
DataStream.Seek(-flagtoken.Length - 1, SeekOrigin.Current);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-04-13 14:11:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-06 21:51:22 +00:00
|
|
|
|
// Type
|
|
|
|
|
SkipWhitespace(true);
|
|
|
|
|
string type = ReadToken().ToLowerInvariant();
|
|
|
|
|
|
2016-04-13 14:11:35 +00:00
|
|
|
|
if(!knowntypes.Contains(type))
|
|
|
|
|
{
|
|
|
|
|
ReportError("Unknown cvar type");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Name
|
|
|
|
|
SkipWhitespace(true);
|
|
|
|
|
string name = ReadToken();
|
|
|
|
|
|
|
|
|
|
if(string.IsNullOrEmpty(name))
|
|
|
|
|
{
|
|
|
|
|
ReportError("Expected cvar name");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Either "=" or ";"
|
|
|
|
|
SkipWhitespace(true);
|
|
|
|
|
token = ReadToken();
|
|
|
|
|
|
|
|
|
|
switch(token)
|
|
|
|
|
{
|
|
|
|
|
case "=":
|
|
|
|
|
SkipWhitespace(true);
|
|
|
|
|
string value = ReadToken();
|
|
|
|
|
|
|
|
|
|
if(string.IsNullOrEmpty(value))
|
|
|
|
|
{
|
|
|
|
|
ReportError("Expected \"" + name + "\" cvar value");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add to collection
|
|
|
|
|
if(!AddValue(name, type, value)) return false;
|
|
|
|
|
|
|
|
|
|
// Next should be ";"
|
|
|
|
|
if(!NextTokenIs(";")) return false;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ";":
|
|
|
|
|
if(!AddValue(name, type, string.Empty)) return false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
ReportError("Unknown keyword");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool AddValue(string name, string type, string value)
|
|
|
|
|
{
|
|
|
|
|
switch(type)
|
|
|
|
|
{
|
|
|
|
|
case "int":
|
|
|
|
|
int iv = 0;
|
2016-04-19 20:40:42 +00:00
|
|
|
|
if(!string.IsNullOrEmpty(value) && !ReadSignedInt(value, ref iv))
|
2016-04-13 14:11:35 +00:00
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" has invalid integer value: \"" + value + "\"");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if(!cvars.AddValue(name, iv))
|
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" is double defined");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "float":
|
|
|
|
|
float fv = 0f;
|
2016-04-19 20:40:42 +00:00
|
|
|
|
if(!string.IsNullOrEmpty(value) && !ReadSignedFloat(value, ref fv))
|
2016-04-13 14:11:35 +00:00
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" has invalid decimal value: \"" + value + "\"");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if(!cvars.AddValue(name, fv))
|
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" is double defined");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "color":
|
|
|
|
|
PixelColor cv = new PixelColor();
|
2018-02-04 03:16:52 +00:00
|
|
|
|
if(!string.IsNullOrEmpty(value) && !GetColorFromString(value, out cv))
|
2016-04-13 14:11:35 +00:00
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" has invalid color value: \"" + value + "\"");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if(!cvars.AddValue(name, cv))
|
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" is double defined");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "bool":
|
|
|
|
|
bool bv = false;
|
|
|
|
|
if(!string.IsNullOrEmpty(value))
|
|
|
|
|
{
|
|
|
|
|
string sv = value.ToLowerInvariant();
|
|
|
|
|
if(sv != "true" && sv != "false")
|
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" has invalid boolean value: \"" + value + "\"");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bv = (sv == "true");
|
|
|
|
|
}
|
|
|
|
|
if(!cvars.AddValue(name, bv))
|
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" is double defined");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "string":
|
|
|
|
|
if(!cvars.AddValue(name, StripQuotes(value)))
|
|
|
|
|
{
|
|
|
|
|
ReportError("Cvar \"" + name + "\" is double defined");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|