From f86bc370d9b4e4f1c5049f40bc17bcfce90bd72a Mon Sep 17 00:00:00 2001 From: MaxED Date: Sun, 27 Dec 2015 00:13:31 +0000 Subject: [PATCH] Fixed, GLDEFS parser: in some cases the parser was unable to detect the end of "Glow" block, which resulted in skipping the rest of the file. --- Source/Core/GZBuilder/GZDoom/GldefsParser.cs | 1142 +++++++++-------- Source/Core/GZBuilder/GZDoom/MapinfoParser.cs | 10 +- Source/Core/ZDoom/DecorateParser.cs | 9 +- 3 files changed, 593 insertions(+), 568 deletions(-) diff --git a/Source/Core/GZBuilder/GZDoom/GldefsParser.cs b/Source/Core/GZBuilder/GZDoom/GldefsParser.cs index 3bc2abdb..8426aaf1 100644 --- a/Source/Core/GZBuilder/GZDoom/GldefsParser.cs +++ b/Source/Core/GZBuilder/GZDoom/GldefsParser.cs @@ -92,459 +92,515 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom while(SkipWhitespace(true)) { string token = StripTokenQuotes(ReadToken()).ToLowerInvariant(); //Quotes can be anywhere! ANYWHERE!!! And GZDoom will still parse data correctly - if(!string.IsNullOrEmpty(token)) + if(string.IsNullOrEmpty(token)) break; + + //got light structure + if(token == GldefsLightType.POINT || token == GldefsLightType.PULSE || token == GldefsLightType.FLICKER + || token == GldefsLightType.FLICKER2 || token == GldefsLightType.SECTOR) { - //got light structure - if(token == GldefsLightType.POINT || token == GldefsLightType.PULSE || token == GldefsLightType.FLICKER - || token == GldefsLightType.FLICKER2 || token == GldefsLightType.SECTOR) + string lightType = token; + DynamicLightData light = new DynamicLightData { Type = GldefsLightType.GLDEFS_TO_GZDOOM_LIGHT_TYPE[lightType] }; + + //find classname + SkipWhitespace(true); + string lightName = StripTokenQuotes(ReadToken()).ToLowerInvariant(); + + if(string.IsNullOrEmpty(lightName)) { - string lightType = token; + ReportError("Expected " + token + " name"); + return false; + } - DynamicLightData light = new DynamicLightData(); - light.Type = GldefsLightType.GLDEFS_TO_GZDOOM_LIGHT_TYPE[lightType]; + //now find opening brace + if(!NextTokenIs("{", false)) + { + ReportError("Expected opening brace"); + return false; + } - //find classname - SkipWhitespace(true); - string lightName = StripTokenQuotes(ReadToken()).ToLowerInvariant(); - - if(!string.IsNullOrEmpty(lightName)) + //read gldefs light structure + while(SkipWhitespace(true)) + { + token = ReadToken().ToLowerInvariant(); + if(!string.IsNullOrEmpty(token)) { - //now find opening brace - if(!NextTokenIs("{")) continue; - - //read gldefs light structure - while(SkipWhitespace(true)) - { - token = ReadToken(); - if(!string.IsNullOrEmpty(token)) - { - token = token.ToLowerInvariant(); //color - if(token == "color") - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red)) - { - // Not numeric! - ReportError("Expected Red color value, but got '" + token + "'"); - return false; - } - - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green)) - { - // Not numeric! - ReportError("Expected Green color value, but got '" + token + "'"); - return false; - } - - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Blue)) - { - // Not numeric! - ReportError("Expected Blue color value, but got '" + token + "'"); - return false; - } -//size - } - else if(token == "size") - { - if(lightType != GldefsLightType.SECTOR) - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius)) - { - // Not numeric! - ReportError("Expected Size value, but got '" + token + "'"); - return false; - } - light.PrimaryRadius *= 2; - - } - else - { - ReportError("'" + token + "' is not valid property for " + lightType); - return false; - } -//offset - } - else if(token == "offset") - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - if(!ReadSignedFloat(token, ref light.Offset.X)) - { - // Not numeric! - ReportError("Expected Offset X value, but got '" + token + "'"); - return false; - } - - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - if(!ReadSignedFloat(token, ref light.Offset.Z)) - { - // Not numeric! - ReportError("Expected Offset Y value, but got '" + token + "'"); - return false; - } - - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - if(!ReadSignedFloat(token, ref light.Offset.Y)) - { - // Not numeric! - ReportError("Expected Offset Z value, but got '" + token + "'"); - return false; - } -//subtractive - } - else if(token == "subtractive") - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - int i; - if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) - { - // Not numeric! - ReportError("expected Subtractive value, but got '" + token + "'"); - return false; - } - - light.Subtractive = i == 1; -//dontlightself - } - else if(token == "dontlightself") - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - int i; - if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) - { - // Not numeric! - ReportError("Expected DontLightSelf value, but got '" + token + "'"); - return false; - } - - light.DontLightSelf = (i == 1); -//interval - } - else if(token == "interval") - { - if(lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2) - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - float interval; - if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval)) - { - // Not numeric! - ReportError("Expected Interval value, but got '" + token + "'"); - return false; - } - - if(interval == 0) LogWarning("Interval value should be greater than zero"); - - //I wrote logic for dynamic lights animation first, so here I modify gldefs settings to fit in existing logic - if(lightType == GldefsLightType.PULSE) - { - light.Interval = (int)(interval * 35); //measured in tics (35 per second) in PointLightPulse, measured in seconds in gldefs' PulseLight - } - else //FLICKER2. Seems like PointLightFlickerRandom to me - { - light.Interval = (int)(interval * 350); //0.1 is one second for FlickerLight2 - } - } - else - { - ReportError("'" + token + "' is not valid property for " + lightType); - return false; - } -//secondarysize - } - else if(token == "secondarysize") - { - if(lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2) - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius)) - { - // Not numeric! - ReportError("Expected SecondarySize value, but got '" + token + "'"); - return false; - } - light.SecondaryRadius *= 2; - } - else - { - ReportError("'" + token + "' is not valid property for " + lightType); - return false; - } -//chance - } - else if(token == "chance") - { - if(lightType == GldefsLightType.FLICKER) - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - float chance; - if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance)) - { - // Not numeric! - ReportError("Expected Chance value, but got '" + token + "'"); - return false; - } - - //transforming from 0.0 .. 1.0 to 0 .. 359 to fit in existing logic - light.Interval = (int)(chance * 359.0f); - } - else - { - ReportError("'" + token + "' is not valid property for " + lightType); - return false; - } -//scale - } - else if(token == "scale") - { - if(lightType == GldefsLightType.SECTOR) - { - SkipWhitespace(true); - - token = StripTokenQuotes(ReadToken()); - float scale; - if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale)) - { - // Not numeric! - ReportError("Expected Scale value, but got '" + token + "'"); - return false; - } - - if(scale > 1.0f) - { - ReportError("Scale must be in 0.0 - 1.0 range, but is " + scale); - return false; - } - - //sector light doesn't have animation, so we will store it's size in Interval - //transforming from 0.0 .. 1.0 to 0 .. 10 to preserve value. - light.Interval = (int)(scale * 10.0f); - } - else - { - ReportError("'" + token + "' is not valid property for " + lightType); - return false; - } - } - //end of structure - else if(token == "}") - { - bool skip = false; - - //general checks - if(light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f) - { - LogWarning("'" + lightName + "' light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom"); - skip = true; - } - - //light-type specific checks - if(light.Type == DynamicLightType.NORMAL && light.PrimaryRadius == 0) - { - LogWarning("'" + lightName + "' light Size is 0. It won't be shown in GZDoom"); - skip = true; - } - - if(light.Type == DynamicLightType.FLICKER || light.Type == DynamicLightType.PULSE || light.Type == DynamicLightType.RANDOM) - { - if(light.PrimaryRadius == 0 && light.SecondaryRadius == 0) - { - LogWarning("'" + lightName + "' light Size and SecondarySize are 0. This light won't be shown in GZDoom"); - skip = true; - } - } - - //offset it slightly to avoid shading glitches - if(light.Offset.Z == 0.0f) light.Offset.Z = 0.1f; - - // Add to the collection? - if(!skip) lightsByName[lightName] = light; - - //break out of this parsing loop - break; - } - } - } - } - } - else if(token == "object") - { - SkipWhitespace(true); - - //read object class - string objectClass = StripTokenQuotes(ReadToken()).ToLowerInvariant(); - - if(!string.IsNullOrEmpty(objectClass)) - { - //now find opening brace - if(!NextTokenIs("{")) continue; - - int bracesCount = 1; - bool foundLight = false; - bool foundFrame = false; - - //read frames structure - while(SkipWhitespace(true)) + if(token == "color") { - token = ReadToken(); - if(!string.IsNullOrEmpty(token)) + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red)) { - token = StripTokenQuotes(token).ToLowerInvariant(); - if(!foundLight && !foundFrame && token == "frame") - { - SkipWhitespace(true); - token = ReadToken().ToLowerInvariant(); //should be frame name + // Not numeric! + ReportError("Expected Red color value, but got '" + token + "'"); + return false; + } - //use this frame if it's 4 characters long or it's the first frame - foundFrame = (token.Length == 4 || (token.Length > 4 && token[4] == 'a')); - } - else if(!foundLight && foundFrame && token == "light") //just use first light and be done with it - { - SkipWhitespace(true); - token = ReadToken().ToLowerInvariant(); //should be light name + SkipWhitespace(true); - if(!string.IsNullOrEmpty(token)) - { - if(lightsByName.ContainsKey(token)) - { - objects[objectClass] = token; - foundLight = true; - } - else - { - LogWarning("Light declaration not found for light '" + token + "'"); - } - } - } - else if(token == "{") //continue in this loop until object structure ends - { - bracesCount++; - } - else if(token == "}") + token = StripTokenQuotes(ReadToken()); + if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green)) + { + // Not numeric! + ReportError("Expected Green color value, but got '" + token + "'"); + return false; + } + + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + if (!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Blue)) + { + // Not numeric! + ReportError("Expected Blue color value, but got '" + token + "'"); + return false; + } +//size + } + else if(token == "size") + { + if(lightType != GldefsLightType.SECTOR) + { + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius)) { - if(--bracesCount < 1) break; //This was Cave Johnson. And we are done here. + // Not numeric! + ReportError("Expected Size value, but got '" + token + "'"); + return false; + } + light.PrimaryRadius *= 2; + + } + else + { + ReportError("'" + token + "' is not valid property for " + lightType); + return false; + } +//offset + } + else if(token == "offset") + { + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + if(!ReadSignedFloat(token, ref light.Offset.X)) + { + // Not numeric! + ReportError("Expected Offset X value, but got '" + token + "'"); + return false; + } + + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + if(!ReadSignedFloat(token, ref light.Offset.Z)) + { + // Not numeric! + ReportError("Expected Offset Y value, but got '" + token + "'"); + return false; + } + + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + if(!ReadSignedFloat(token, ref light.Offset.Y)) + { + // Not numeric! + ReportError("Expected Offset Z value, but got '" + token + "'"); + return false; + } +//subtractive + } + else if(token == "subtractive") + { + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + int i; + if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) + { + // Not numeric! + ReportError("expected Subtractive value, but got '" + token + "'"); + return false; + } + + light.Subtractive = i == 1; +//dontlightself + } + else if(token == "dontlightself") + { + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + int i; + if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) + { + // Not numeric! + ReportError("Expected DontLightSelf value, but got '" + token + "'"); + return false; + } + + light.DontLightSelf = (i == 1); +//interval + } + else if(token == "interval") + { + if(lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER2) + { + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + float interval; + if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval)) + { + // Not numeric! + ReportError("Expected Interval value, but got '" + token + "'"); + return false; + } + + if(interval == 0) LogWarning("Interval value should be greater than zero"); + + //I wrote logic for dynamic lights animation first, so here I modify gldefs settings to fit in existing logic + if(lightType == GldefsLightType.PULSE) + { + light.Interval = (int)(interval * 35); //measured in tics (35 per second) in PointLightPulse, measured in seconds in gldefs' PulseLight + } + else //FLICKER2. Seems like PointLightFlickerRandom to me + { + light.Interval = (int)(interval * 350); //0.1 is one second for FlickerLight2 + } + } + else + { + ReportError("'" + token + "' is not valid property for " + lightType); + return false; + } +//secondarysize + } + else if(token == "secondarysize") + { + if(lightType == GldefsLightType.PULSE || lightType == GldefsLightType.FLICKER || lightType == GldefsLightType.FLICKER2) + { + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius)) + { + // Not numeric! + ReportError("Expected SecondarySize value, but got '" + token + "'"); + return false; + } + light.SecondaryRadius *= 2; + } + else + { + ReportError("'" + token + "' is not valid property for " + lightType); + return false; + } +//chance + } + else if(token == "chance") + { + if(lightType == GldefsLightType.FLICKER) + { + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + float chance; + if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance)) + { + // Not numeric! + ReportError("Expected Chance value, but got '" + token + "'"); + return false; + } + + //transforming from 0.0 .. 1.0 to 0 .. 359 to fit in existing logic + light.Interval = (int)(chance * 359.0f); + } + else + { + ReportError("'" + token + "' is not valid property for " + lightType); + return false; + } +//scale + } + else if(token == "scale") + { + if(lightType == GldefsLightType.SECTOR) + { + SkipWhitespace(true); + + token = StripTokenQuotes(ReadToken()); + float scale; + if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale)) + { + // Not numeric! + ReportError("Expected Scale value, but got '" + token + "'"); + return false; + } + + if(scale > 1.0f) + { + ReportError("Scale must be in 0.0 - 1.0 range, but is " + scale); + return false; + } + + //sector light doesn't have animation, so we will store it's size in Interval + //transforming from 0.0 .. 1.0 to 0 .. 10 to preserve value. + light.Interval = (int)(scale * 10.0f); + } + else + { + ReportError("'" + token + "' is not valid property for " + lightType); + return false; + } + } + //end of structure + else if(token == "}") + { + bool skip = false; + + //general checks + if(light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f) + { + LogWarning("'" + lightName + "' light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom"); + skip = true; + } + + //light-type specific checks + if(light.Type == DynamicLightType.NORMAL && light.PrimaryRadius == 0) + { + LogWarning("'" + lightName + "' light Size is 0. It won't be shown in GZDoom"); + skip = true; + } + + if(light.Type == DynamicLightType.FLICKER || light.Type == DynamicLightType.PULSE || light.Type == DynamicLightType.RANDOM) + { + if(light.PrimaryRadius == 0 && light.SecondaryRadius == 0) + { + LogWarning("'" + lightName + "' light Size and SecondarySize are 0. This light won't be shown in GZDoom"); + skip = true; } } + + //offset it slightly to avoid shading glitches + if(light.Offset.Z == 0.0f) light.Offset.Z = 0.1f; + + // Add to the collection? + if(!skip) lightsByName[lightName] = light; + + //break out of this parsing loop + break; } } } - //Glowing flats block start - else if(token == "glow") + } + else if(token == "object") + { + SkipWhitespace(true); + + //read object class + string objectClass = StripTokenQuotes(ReadToken()).ToLowerInvariant(); + + if(string.IsNullOrEmpty(objectClass)) { - // Next sould be opening brace - if(!NextTokenIs("{")) continue; + ReportError("Expected object class"); + return false; + } - // Parse inner blocks - while(SkipWhitespace(true)) + //now find opening brace + if(!NextTokenIs("{", false)) + { + ReportError("Expected opening brace"); + return false; + } + + int bracesCount = 1; + bool foundLight = false; + bool foundFrame = false; + + //read frames structure + while(SkipWhitespace(true)) + { + token = ReadToken(); + if(!string.IsNullOrEmpty(token)) { - token = ReadToken().ToLowerInvariant(); - if(token == "flats" || token == "walls") + token = StripTokenQuotes(token).ToLowerInvariant(); + if(!foundLight && !foundFrame && token == "frame") { - // Next sould be opening brace - if(!NextTokenIs("{")) break; + SkipWhitespace(true); + token = ReadToken().ToLowerInvariant(); //should be frame name - // Read flat names - while(SkipWhitespace(true)) + //use this frame if it's 4 characters long or it's the first frame + foundFrame = (token.Length == 4 || (token.Length > 4 && token[4] == 'a')); + } + else if(!foundLight && foundFrame && token == "light") //just use first light and be done with it + { + SkipWhitespace(true); + token = ReadToken().ToLowerInvariant(); //should be light name + + if(!string.IsNullOrEmpty(token)) { - token = ReadToken(); - if(token == "}") break; - - // Add glow data - glowingflats[General.Map.Data.GetFullLongFlatName(Lump.MakeLongName(token, General.Map.Options.UseLongTextureNames))] = new GlowingFlatData { - Height = DEFAULT_GLOW_HEIGHT * 2, - Fullbright = true, - Color = new PixelColor(255, 255, 255, 255), - CalculateTextureColor = true - }; + if(lightsByName.ContainsKey(token)) + { + objects[objectClass] = token; + foundLight = true; + } + else + { + LogWarning("Light declaration not found for light '" + token + "'"); + } } } - // GLOOME subtractive flats - else if(token == "subflats" || token == "subwalls") + else if(token == "{") //continue in this loop until object structure ends + { + bracesCount++; + } + else if(token == "}") { - // Next sould be opening brace - if(!NextTokenIs("{")) break; - - // Read flat names - while(SkipWhitespace(true)) - { - token = ReadToken(); - if(token == "}") break; - - // Add glow data - glowingflats[General.Map.Data.GetFullLongFlatName(Lump.MakeLongName(token, General.Map.Options.UseLongTextureNames))] = new GlowingFlatData { - Height = DEFAULT_GLOW_HEIGHT * 2, - Fullblack = true, - Subtractive = true, - Color = new PixelColor(255, 0, 0, 0), - CalculateTextureColor = false - }; - } + if(--bracesCount < 1) break; //This was Cave Johnson. And we are done here. } - else if(token == "texture" || token == "subtexture") - { - int color; - int glowheight = DEFAULT_GLOW_HEIGHT; - bool subtractivetexture = (token == "subtexture"); - string texturename = StripTokenQuotes(ReadToken(false)); + } + } + } + //Glowing flats block start + else if(token == "glow") + { + // Next sould be opening brace + if(!NextTokenIs("{", false)) + { + ReportError("Expected opening brace"); + return false; + } - if(string.IsNullOrEmpty(texturename)) + // Parse inner blocks + while(SkipWhitespace(true)) + { + token = ReadToken().ToLowerInvariant(); + if(token == "}") + { + // End of Glow structure + break; + } + else if(token == "flats" || token == "walls") + { + // Next sould be opening brace + if(!NextTokenIs("{", false)) + { + ReportError("Expected opening brace"); + return false; + } + + // Read flat names + while(SkipWhitespace(true)) + { + token = ReadToken(); + if(token == "}") break; + + // Add glow data + glowingflats[General.Map.Data.GetFullLongFlatName(Lump.MakeLongName(token, General.Map.Options.UseLongTextureNames))] = new GlowingFlatData { + Height = DEFAULT_GLOW_HEIGHT * 2, + Fullbright = true, + Color = new PixelColor(255, 255, 255, 255), + CalculateTextureColor = true + }; + } + } + // GLOOME subtractive flats + else if(token == "subflats" || token == "subwalls") + { + // Next sould be opening brace + if(!NextTokenIs("{", false)) + { + ReportError("Expected opening brace"); + return false; + } + + // Read flat names + while(SkipWhitespace(true)) + { + token = ReadToken(); + if(token == "}") break; + + // Add glow data + glowingflats[General.Map.Data.GetFullLongFlatName(Lump.MakeLongName(token, General.Map.Options.UseLongTextureNames))] = new GlowingFlatData { + Height = DEFAULT_GLOW_HEIGHT * 2, + Fullblack = true, + Subtractive = true, + Color = new PixelColor(255, 0, 0, 0), + CalculateTextureColor = false + }; + } + } + else if(token == "texture" || token == "subtexture") + { + int color; + int glowheight = DEFAULT_GLOW_HEIGHT; + bool subtractivetexture = (token == "subtexture"); + string texturename = StripTokenQuotes(ReadToken(false)); + + if(string.IsNullOrEmpty(texturename)) + { + ReportError("expected " + token + " name"); + return false; + } + + // Now we should find a comma + if(!NextTokenIs(",", false)) + { + ReportError("Expected a comma"); + return false; + } + + // Next is color + SkipWhitespace(true); + token = ReadToken(); + + if(!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out color)) + { + //probably it's a color name? + Color c = Color.FromName(token); //should be similar to C++ color name detection, I suppose + if(c.IsKnownColor) { - ReportError("expected " + token + " name"); + color = PixelColor.FromColor(c).ToInt(); + } + else + { + ReportError("expected glow color value, but got '" + token + "'"); return false; } + } + + // The glow data is valid at thispoint. Let's get texture hash + long texturehash = General.Map.Data.GetFullLongFlatName(Lump.MakeLongName(texturename, General.Map.Options.UseLongTextureNames)); + + // Now we can find a comma + if(!NextTokenIs(",", false)) + { + // Add glow data + glowingflats[texturehash] = new GlowingFlatData { + Height = glowheight * 2, + Subtractive = subtractivetexture, + Color = PixelColor.FromInt(color).WithAlpha(255), + CalculateTextureColor = false + }; + + continue; + } + + // Can be glow height + SkipWhitespace(true); + token = ReadToken(); + + int h; + if(int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out h)) + { + // Can't pass glowheight directly cause TryParse will unconditionally set it to 0 + glowheight = h; - // Now we should find a comma - if(!NextTokenIs(",")) break; - - // Next is color - SkipWhitespace(true); - token = ReadToken(); - - if(!int.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out color)) - { - //probably it's a color name? - Color c = Color.FromName(token); //should be similar to C++ color name detection, I suppose - if(c.IsKnownColor) - { - color = PixelColor.FromColor(c).ToInt(); - } - else - { - ReportError("expected glow color value, but got '" + token + "'"); - return false; - } - } - - // The glow data is valid at thispoint. Let's get texture hash - long texturehash = General.Map.Data.GetFullLongFlatName(Lump.MakeLongName(texturename, General.Map.Options.UseLongTextureNames)); - // Now we can find a comma if(!NextTokenIs(",", false)) { @@ -559,155 +615,123 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom continue; } - // Can be glow height + // Read the flag SkipWhitespace(true); - token = ReadToken(); - - int h; - if(int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out h)) - { - // Can't pass glowheight directly cause TryParse will unconditionally set it to 0 - glowheight = h; - - // Now we can find a comma - if(!NextTokenIs(",", false)) - { - // Add glow data - glowingflats[texturehash] = new GlowingFlatData { - Height = glowheight * 2, - Subtractive = subtractivetexture, - Color = PixelColor.FromInt(color).WithAlpha(255), - CalculateTextureColor = false - }; - - continue; - } - - // Read the flag - SkipWhitespace(true); - token = ReadToken().ToLowerInvariant(); - } - - // Next is "fullbright" or "fullblack" flag - bool fullbright = (token == "fullbright"); - bool fullblack = (!subtractivetexture && token == "fullblack"); - - if(!fullblack && !fullbright) - { - string expectedflags = (subtractivetexture ? "'fullbright'" : "'fullbright' or 'fullblack'"); - ReportError("expected " + expectedflags + " flag, but got '" + token + "'"); - return false; - } - - // Add glow data - glowingflats[texturehash] = new GlowingFlatData { - Height = glowheight * 2, - Fullbright = fullbright, - Fullblack = fullblack, - Subtractive = subtractivetexture, - Color = PixelColor.FromInt(color).WithAlpha(255), - CalculateTextureColor = false - }; + token = ReadToken().ToLowerInvariant(); } - } - // Now find closing brace - while(SkipWhitespace(true)) - { - token = ReadToken(); - if(string.IsNullOrEmpty(token) || token == "}") break; + // Next is "fullbright" or "fullblack" flag + bool fullbright = (token == "fullbright"); + bool fullblack = (!subtractivetexture && token == "fullblack"); + + if(!fullblack && !fullbright) + { + string expectedflags = (subtractivetexture ? "'fullbright'" : "'fullbright' or 'fullblack'"); + ReportError("expected " + expectedflags + " flag, but got '" + token + "'"); + return false; + } + + // Add glow data + glowingflats[texturehash] = new GlowingFlatData { + Height = glowheight * 2, + Fullbright = fullbright, + Fullblack = fullblack, + Subtractive = subtractivetexture, + Color = PixelColor.FromInt(color).WithAlpha(255), + CalculateTextureColor = false + }; } } - else if(token == "#include") + } + else if(token == "#include") + { + //INFO: ZDoom GLDEFS include paths can't be relative ("../glstuff.txt") + //or absolute ("d:/project/glstuff.txt") + //or have backward slashes ("info\glstuff.txt") + //include paths are relative to the first parsed entry, not the current one + //also include paths may or may not be quoted + SkipWhitespace(true); + string includelump = StripTokenQuotes(ReadToken(false)); // Don't skip newline + + // Sanity checks + if(string.IsNullOrEmpty(includelump)) { - //INFO: ZDoom GLDEFS include paths can't be relative ("../glstuff.txt") - //or absolute ("d:/project/glstuff.txt") - //or have backward slases ("info\glstuff.txt") - //include paths are relative to the first parsed entry, not the current one - //also include paths may or may not be quoted - SkipWhitespace(true); - string includelump = StripTokenQuotes(ReadToken(false)); // Don't skip newline - - // Sanity checks - if(string.IsNullOrEmpty(includelump)) - { - ReportError("Expected file name to include"); - return false; - } - - // Absolute paths are not supported... - if(Path.IsPathRooted(includelump)) - { - ReportError("Absolute include paths are not supported by ZDoom"); - return false; - } - - // Relative paths are not supported - if(includelump.StartsWith(RELATIVE_PATH_MARKER) || includelump.StartsWith(CURRENT_FOLDER_PATH_MARKER) || - includelump.StartsWith(ALT_RELATIVE_PATH_MARKER) || includelump.StartsWith(ALT_CURRENT_FOLDER_PATH_MARKER)) - { - ReportError("Relative include paths are not supported by ZDoom"); - return false; - } - - // Backward slases are not supported - if(includelump.Contains(Path.DirectorySeparatorChar.ToString())) - { - ReportError("Only forward slases are supported by ZDoom"); - return false; - } - - // Already parsed? - if(parsedlumps.Contains(includelump)) - { - ReportError("Already parsed '" + includelump + "'. Check your #include directives"); - return false; - } - - // Add to collection - parsedlumps.Add(includelump); - - // Callback to parse this file - if(OnInclude != null) OnInclude(this, includelump, clearerrors); - - // Bail out on error - if(this.HasError) return false; - - // Set our buffers back to continue parsing - datastream = localstream; - datareader = localreader; - sourcename = localsourcename; - } - else if(token == "$gzdb_skip") //mxd - { - break; + ReportError("Expected file name to include"); + return false; } - else + + // Absolute paths are not supported... + if(Path.IsPathRooted(includelump)) { - // Unknown structure! - string token2; - do - { - if(!SkipWhitespace(true)) break; - token2 = ReadToken(); - if(string.IsNullOrEmpty(token2)) break; - } - while (token2 != "{"); - int scopelevel = 1; - do - { - if(!SkipWhitespace(true)) break; - token2 = ReadToken(); - if(string.IsNullOrEmpty(token2)) break; - if(token2 == "{") scopelevel++; - if(token2 == "}") scopelevel--; - } - while(scopelevel > 0); + ReportError("Absolute include paths are not supported by ZDoom"); + return false; } + + // Relative paths are not supported + if(includelump.StartsWith(RELATIVE_PATH_MARKER) || includelump.StartsWith(CURRENT_FOLDER_PATH_MARKER) || + includelump.StartsWith(ALT_RELATIVE_PATH_MARKER) || includelump.StartsWith(ALT_CURRENT_FOLDER_PATH_MARKER)) + { + ReportError("Relative include paths are not supported by ZDoom"); + return false; + } + + // Backward slashes are not supported + if(includelump.Contains(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture))) + { + ReportError("Only forward slashes are supported by ZDoom"); + return false; + } + + // Already parsed? + if(parsedlumps.Contains(includelump)) + { + ReportError("Already parsed '" + includelump + "'. Check your #include directives"); + return false; + } + + // Add to collection + parsedlumps.Add(includelump); + + // Callback to parse this file + if(OnInclude != null) OnInclude(this, includelump, clearerrors); + + // Bail out on error + if(this.HasError) return false; + + // Set our buffers back to continue parsing + datastream = localstream; + datareader = localreader; + sourcename = localsourcename; + } + else if(token == "$gzdb_skip") //mxd + { + break; + } + else + { + // Unknown structure! + string token2; + do + { + if(!SkipWhitespace(true)) break; + token2 = ReadToken(); + if(string.IsNullOrEmpty(token2)) break; + } + while (token2 != "{"); + int scopelevel = 1; + do + { + if(!SkipWhitespace(true)) break; + token2 = ReadToken(); + if(string.IsNullOrEmpty(token2)) break; + if(token2 == "{") scopelevel++; + if(token2 == "}") scopelevel--; + } + while(scopelevel > 0); } } - return objects.Count > 0; + return !this.HasError; } #endregion diff --git a/Source/Core/GZBuilder/GZDoom/MapinfoParser.cs b/Source/Core/GZBuilder/GZDoom/MapinfoParser.cs index d7318589..7589d3dc 100644 --- a/Source/Core/GZBuilder/GZDoom/MapinfoParser.cs +++ b/Source/Core/GZBuilder/GZDoom/MapinfoParser.cs @@ -137,7 +137,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom //should be sky texture name token = StripTokenQuotes(ReadToken()); - bool gotComma = (token.IndexOf(",") != -1); + bool gotComma = (token.IndexOf(",", StringComparison.Ordinal) != -1); if(gotComma) token = token.Replace(",", ""); string skyTexture = StripTokenQuotes(token).ToLowerInvariant(); @@ -359,7 +359,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom //INFO: ZDoom MAPINFO include paths can't be relative ("../mapstuff.txt") //or absolute ("d:/project/mapstuff.txt") - //or have backward slases ("info\mapstuff.txt") + //or have backward slashes ("info\mapstuff.txt") //include paths are relative to the first parsed entry, not the current one //also include paths may or may not be quoted if(!string.IsNullOrEmpty(includelump)) @@ -379,10 +379,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom return false; } - // Backward slases are not supported - if(includelump.Contains(Path.DirectorySeparatorChar.ToString())) + // Backward slashes are not supported + if(includelump.Contains(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture))) { - ReportError("Only forward slases are supported by ZDoom"); + ReportError("Only forward slashes are supported by ZDoom"); return false; } diff --git a/Source/Core/ZDoom/DecorateParser.cs b/Source/Core/ZDoom/DecorateParser.cs index fd098d32..47f1d4f9 100644 --- a/Source/Core/ZDoom/DecorateParser.cs +++ b/Source/Core/ZDoom/DecorateParser.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; #endregion @@ -154,7 +155,7 @@ namespace CodeImp.DoomBuilder.ZDoom { //INFO: ZDoom DECORATE include paths can't be relative ("../actor.txt") //or absolute ("d:/project/actor.txt") - //or have backward slases ("info\actor.txt") + //or have backward slashes ("info\actor.txt") //include paths are relative to the first parsed entry, not the current one //also include paths may or may not be quoted SkipWhitespace(true); @@ -182,10 +183,10 @@ namespace CodeImp.DoomBuilder.ZDoom return false; } - //mxd. Backward slases are not supported - if(filename.Contains(Path.DirectorySeparatorChar.ToString())) + //mxd. Backward slashes are not supported + if(filename.Contains(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture))) { - ReportError("Only forward slases are supported by ZDoom"); + ReportError("Only forward slashes are supported by ZDoom"); return false; }