//TODO: Remove ScriptDocumentTab from here
        public override List <CompilerError> UpdateFunctionBarItems(ScriptDocumentTab tab, MemoryStream stream, ComboBox target)
        {
            List <CompilerError> result = new List <CompilerError>();

            if (stream == null)
            {
                return(result);
            }
            target.Items.Clear();

            AcsParserSE parser = new AcsParserSE {
                AddArgumentsToScriptNames = true, IsMapScriptsLump = tab is ScriptLumpDocumentTab, IgnoreErrors = true
            };
            DataLocation     dl   = new DataLocation(DataLocation.RESOURCE_DIRECTORY, Path.GetDirectoryName(string.IsNullOrEmpty(tab.Filename)? tab.Title : tab.Filename), false, false, false);
            TextResourceData data = new TextResourceData(stream, dl, (parser.IsMapScriptsLump ? "?SCRIPTS" : tab.Filename));

            if (parser.Parse(data, false))
            {
                target.Items.AddRange(parser.NamedScripts.ToArray());
                target.Items.AddRange(parser.NumberedScripts.ToArray());
                target.Items.AddRange(parser.Functions.ToArray());
            }

            if (parser.HasError)
            {
                result.Add(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
            }

            return(result);
        }
        //TODO: Remove ScriptDocumentTab from here
        public override List <CompilerError> UpdateFunctionBarItems(ScriptDocumentTab tab, MemoryStream stream, ComboBox target)
        {
            List <CompilerError> result = new List <CompilerError>();

            if (stream == null)
            {
                return(result);
            }
            target.Items.Clear();

            ModeldefParserSE parser = new ModeldefParserSE();
            TextResourceData data   = new TextResourceData(stream, new DataLocation(), "MODELDEF", false);

            if (parser.Parse(data, false))
            {
                target.Items.AddRange(parser.Models.ToArray());
            }

            if (parser.HasError)
            {
                result.Add(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
            }

            return(result);
        }
        //mxd
        protected bool AddTextResource(TextResourceData parsedata)
        {
            // Script Editor resources don't have actual path and should always be parsed
            if(string.IsNullOrEmpty(parsedata.SourceLocation.location))
            {
                if(parsedata.Trackable) throw new NotSupportedException("Trackable TextResource must have a valid path.");
                return true;
            }

            string path = Path.Combine(parsedata.SourceLocation.location, parsedata.Filename + (parsedata.LumpIndex != -1 ? "#" + parsedata.LumpIndex : ""));
            if(scriptresources.ContainsKey(path) || untrackedtextresources.Contains(path))
                return false;

            //mxd. Create TextResource for this file
            if(parsedata.Trackable)
            {
                textresourcepath = path;
                ScriptResource res = new ScriptResource(parsedata, this.ScriptType);
                scriptresources.Add(textresourcepath, res);
            }
            // Track the untrackable!
            else
            {
                untrackedtextresources.Add(path);
                textresourcepath = string.Empty;
            }

            return true;
        }
Beispiel #4
0
        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
            char[] space = { ' ', '\t' };
            while (SkipWhitespace(true))
            {
                string line = ReadLine();
                if (string.IsNullOrEmpty(line) || line.StartsWith("!"))
                {
                    continue;                                                                    // Skip comments
                }
                // "R G B Name with spaces"
                string[] parts = line.Split(space, StringSplitOptions.RemoveEmptyEntries);

                if (parts.Length < 4)
                {
                    ReportError("Incorrect X11R6RGB color assignment");
                    return(false);
                }

                // Parse colors
                byte r = 0, g = 0, b = 0;
                if (!ReadByte(parts[0], ref r))
                {
                    ReportError("Expected red color value in [0 .. 255] range");   return(false);
                }
                if (!ReadByte(parts[1], ref g))
                {
                    ReportError("Expected green color value in [0 .. 255] range"); return(false);
                }
                if (!ReadByte(parts[2], ref b))
                {
                    ReportError("Expected blue color value in [0 .. 255] range");  return(false);
                }

                // Assemble name
                string colorname = string.Join("", parts, 3, parts.Length - 3);

                // Add to collection
                knowncolors[colorname] = new PixelColor(255, r, g, b);
            }

            return(true);
        }
 override public bool Parse(TextResourceData data, bool clearerrors)
 {
     if (string.IsNullOrEmpty(mapname))
     {
         throw new NotSupportedException("Map name required!");
     }
     return(Parse(data, mapname, clearerrors));
 }
        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))
            {
                string token = ReadToken();
                if (string.IsNullOrEmpty(token) || token.ToUpperInvariant() != "MODEL")
                {
                    continue;
                }

                SkipWhitespace(true);
                int    startpos  = (int)datastream.Position;
                string modelname = ReadToken();

                SkipWhitespace(true);
                token = ReadToken();                 //this should be "{"

                if (token == "{")
                {
                    ScriptItem i = new ScriptItem(modelname, startpos, false);
                    models.Add(i);
                }

                while (SkipWhitespace(true))
                {
                    token = ReadToken();
                    if (string.IsNullOrEmpty(token) || token == "}")
                    {
                        break;
                    }
                }
            }

            // Sort nodes
            models.Sort(ScriptItem.SortByName);
            return(true);
        }
Beispiel #7
0
        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);
            }

            char[] dots  = { ':' };
            char[] brace = { '[' };

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                string token = ReadToken();

                if (!string.IsNullOrEmpty(token))
                {
                    // Sound sequence definition
                    if (token.StartsWith(":"))
                    {
                        string val = token.TrimStart(dots);
                        if (!string.IsNullOrEmpty(val) && !seqencenames.Contains(val.ToUpper()))
                        {
                            sequences.Add(val);
                            seqencenames.Add(val.ToUpper());
                        }
                    }
                    // Group definition
                    else if (token.StartsWith("["))
                    {
                        string val = token.TrimStart(brace);
                        if (!string.IsNullOrEmpty(val) && !seqencenames.Contains(val.ToUpper()))
                        {
                            sequencegroups.Add(val);
                            seqencenames.Add(val.ToUpper());
                        }
                    }
                }
            }

            return(true);
        }
        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))
            {
                string token = ReadToken();
                if (string.IsNullOrEmpty(token) || token.ToUpperInvariant() != "ACTOR")
                {
                    continue;
                }

                SkipWhitespace(true);
                int startpos = (int)datastream.Position;

                List <string> definition = new List <string>();

                do
                {
                    token = ReadToken(false);                     // Don't skip newline
                    if (string.IsNullOrEmpty(token) || token == "{" || token == "}")
                    {
                        break;
                    }
                    definition.Add(token);
                } while(SkipWhitespace(false));                 // Don't skip newline

                string name = string.Join(" ", definition.ToArray());
                if (!string.IsNullOrEmpty(name))
                {
                    actors.Add(new ScriptItem(name, startpos, false));
                }
            }

            // Sort nodes
            actors.Sort(ScriptItem.SortByName);
            return(true);
        }
Beispiel #9
0
        //mxd
        protected bool AddTextResource(TextResourceData parsedata)
        {
            // Script Editor resources don't have actual path and should always be parsed
            if (string.IsNullOrEmpty(parsedata.SourceLocation.location))
            {
                if (parsedata.Trackable)
                {
                    throw new NotSupportedException("Trackable TextResource must have a valid path.");
                }
                return(true);
            }

            string path = Path.Combine(parsedata.SourceLocation.location, parsedata.Filename + (parsedata.LumpIndex != -1 ? "#" + parsedata.LumpIndex : ""));

            if (textresources.ContainsKey(path) || untrackedtextresources.Contains(path))
            {
                return(false);
            }

            //mxd. Create TextResource for this file
            if (parsedata.Trackable)
            {
                textresourcepath = path;
                TextResource res = new TextResource
                {
                    Resource   = parsedata.Source,
                    Entries    = new HashSet <string>(StringComparer.OrdinalIgnoreCase),
                    Filename   = parsedata.Filename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar),
                    LumpIndex  = parsedata.LumpIndex,
                    ScriptType = this.ScriptType,
                };

                textresources.Add(textresourcepath, res);
            }
            // Track the untrackable!
            else
            {
                untrackedtextresources.Add(path);
                textresourcepath = string.Empty;
            }

            return(true);
        }
Beispiel #10
0
        public ScriptResource(TextResourceData source, ScriptType type)
        {
            resource            = source.Source;
            resourcepath        = resource.Location.location;
            resourcedisplayname = resource.Location.GetDisplayName();
            filename            = source.Filename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
            filepathname        = Path.Combine(resourcepath, filename);
            entries             = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            lumpindex           = source.LumpIndex;
            scripttype          = type;
            isreadonly          = resource.IsReadOnly;

            // Embedded resources require additional tender loving care...
            if (resource is WADReader)
            {
                WADReader wr = (WADReader)resource;
                if (wr.ParentResource is PK3Reader)
                {
                    parentresourcelocation = wr.ParentResource.Location.location;
                }
            }
        }
        //mxd. TODO: remove this
        internal ScriptType VerifyScriptType()
        {
            ScriptTypeParserSE parser = new ScriptTypeParserSE();
            TextResourceData   data   = new TextResourceData(new MemoryStream(editor.GetText()), new DataLocation(), config.Description);

            if (parser.Parse(data, false))
            {
                if (parser.ScriptType != ScriptType.UNKNOWN && config.ScriptType != parser.ScriptType)
                {
                    return(parser.ScriptType);
                }
            }

            if (parser.HasError)
            {
                panel.ShowErrors(new List <CompilerError> {
                    new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine)
                }, true);
            }

            return(ScriptType.UNKNOWN);
        }
Beispiel #12
0
        //mxd. This parses the given decorate stream. Returns false on errors
        public virtual bool Parse(TextResourceData parsedata, bool clearerrors)
        {
            // Clear error status?
            if (clearerrors)
            {
                ClearError();
            }

            // Integrity checks
            // INFO: MapManager.CompileLump() prepends lumpname with "?" to distinguish between temporary files and files compiled in place
            // We don't want this to show up in error messages
            if (parsedata.Stream == null)
            {
                ReportError("Unable to load \"" + parsedata.Filename.Replace("?", "") + "\"");
                return(false);
            }

            if (parsedata.Stream.Length == 0)
            {
                if (!string.IsNullOrEmpty(sourcename) && sourcename != parsedata.Filename)
                {
                    LogWarning("Include file \"" + parsedata.Filename.Replace("?", "") + "\" is empty");
                }
                else
                {
                    sourcename = parsedata.Filename;                     // LogWarning() needs "sourcename" property to properly log the warning...
                    LogWarning("File is empty");
                }
            }

            datastream      = parsedata.Stream;
            datareader      = new BinaryReader(parsedata.Stream, Encoding.ASCII);
            sourcename      = parsedata.Filename;
            sourcelumpindex = parsedata.LumpIndex;
            datalocation    = parsedata.SourceLocation;
            datastream.Seek(0, SeekOrigin.Begin);

            return(true);
        }
        // This parses the given decorate 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);
            }

            // [ZZ] For whatever reason, the parser is closely tied to the tokenizer, and to the general scripting lumps framework (see scripttype).
            //      For this reason I have to still inherit the old tokenizer while only using the new one.
            //ReportError("found zscript? :)");
            prevstreamposition = -1;
            tokenizer          = new ZScriptTokenizer(datareader);

            // region-as-category, ZScript ver
            List <DecorateCategoryInfo> regions = new List <DecorateCategoryInfo>();

            while (true)
            {
                ZScriptToken token = tokenizer.ExpectToken(ZScriptTokenType.Identifier, // const, enum, class, etc
                                                           ZScriptTokenType.Whitespace,
                                                           ZScriptTokenType.Newline,
                                                           ZScriptTokenType.BlockComment, ZScriptTokenType.LineComment,
                                                           ZScriptTokenType.Preprocessor);

                if (token == null) // EOF reached, whatever.
                {
                    break;
                }

                if (!token.IsValid)
                {
                    ReportError("Expected preprocessor statement, const, enum or class declaraction, got " + token);
                    return(false);
                }

                // toplevel tokens allowed are only Preprocessor and Identifier.
                switch (token.Type)
                {
                case ZScriptTokenType.Whitespace:
                case ZScriptTokenType.Newline:
                case ZScriptTokenType.BlockComment:
                    break;

                case ZScriptTokenType.LineComment:
                {
                    string cmtval = token.Value.TrimStart();
                    if (cmtval.Length <= 0 || cmtval[0] != '$')
                    {
                        break;
                    }
                    // check for $GZDB_SKIP
                    if (cmtval.Trim().ToLowerInvariant() == "$gzdb_skip")
                    {
                        return(true);
                    }
                    // if we are in a region, read property using function from ZScriptActorStructure
                    if (regions.Count > 0)
                    {
                        ZScriptActorStructure.ParseGZDBComment(regions.Last().Properties, cmtval);
                    }
                }
                break;

                case ZScriptTokenType.Preprocessor:
                {
                    tokenizer.SkipWhitespace();
                    ZScriptToken directive = tokenizer.ExpectToken(ZScriptTokenType.Identifier);
                    if (directive == null || !directive.IsValid)
                    {
                        ReportError("Expected preprocessor directive, got " + ((Object)directive ?? "<null>").ToString());
                        return(false);
                    }

                    string d_value = directive.Value.ToLowerInvariant();
                    if (d_value == "include")
                    {
                        tokenizer.SkipWhitespace();
                        ZScriptToken include_name = tokenizer.ExpectToken(ZScriptTokenType.Identifier, ZScriptTokenType.String, ZScriptTokenType.Name);
                        if (include_name == null || !include_name.IsValid)
                        {
                            ReportError("Cannot include: expected a string value, got " + ((Object)include_name ?? "<null>").ToString());
                            return(false);
                        }

                        if (!ParseInclude(include_name.Value))
                        {
                            return(false);
                        }
                    }
                    else if (d_value == "region")
                    {
                        // just read everything until newline.
                        string region_name = "";
                        while (true)
                        {
                            token = tokenizer.ReadToken();
                            if (token == null || token.Type == ZScriptTokenType.Newline)
                            {
                                break;
                            }
                            region_name += token.Value;
                        }
                        DecorateCategoryInfo region   = new DecorateCategoryInfo();
                        string[]             cattitle = region_name.Split(DataManager.CATEGORY_SPLITTER, StringSplitOptions.RemoveEmptyEntries);
                        if (regions.Count > 0)
                        {
                            region.Category.AddRange(regions.Last().Category);
                            region.Properties = new Dictionary <string, List <string> >(regions.Last().Properties, StringComparer.OrdinalIgnoreCase);
                        }
                        region.Category.AddRange(cattitle);
                        regions.Add(region);
                    }
                    else if (d_value == "endregion")
                    {
                        // read everything until newline too?
                        // - only if it causes problems
                        if (regions.Count > 0)
                        {
                            regions.RemoveAt(regions.Count - 1);         // remove last region from the list
                        }
                        else
                        {
                            LogWarning("Superfluous #endregion found without corresponding #region");
                        }
                    }
                    else
                    {
                        ReportError("Unknown preprocessor directive: " + directive.Value);
                        return(false);
                    }
                    break;
                }

                case ZScriptTokenType.Identifier:
                {
                    // identifier can be one of: class, enum, const, struct
                    // the only type that we really care about is class, as it's the one that has all actors.
                    switch (token.Value.ToLowerInvariant())
                    {
                    case "extend":
                        tokenizer.SkipWhitespace();
                        token = tokenizer.ExpectToken(ZScriptTokenType.Identifier);
                        if (token == null || !token.IsValid || ((token.Value.ToLowerInvariant() != "class") && (token.Value.ToLowerInvariant() != "struct")))
                        {
                            ReportError("Expected class or struct, got " + ((Object)token ?? "<null>").ToString());
                            return(false);
                        }
                        if (!ParseClassOrStruct((token.Value.ToLowerInvariant() == "struct"), true, (regions.Count > 0 ? regions.Last() : null)))
                        {
                            return(false);
                        }
                        break;

                    case "class":
                        // todo parse class
                        if (!ParseClassOrStruct(false, false, (regions.Count > 0 ? regions.Last() : null)))
                        {
                            return(false);
                        }
                        break;

                    case "struct":
                        // todo parse struct
                        if (!ParseClassOrStruct(true, false, null))
                        {
                            return(false);
                        }
                        break;

                    case "const":
                        if (!ParseConst())
                        {
                            return(false);
                        }
                        break;

                    case "enum":
                        if (!ParseEnum())
                        {
                            return(false);
                        }
                        break;

                    case "version":
                        // expect a string. do nothing about it.
                        tokenizer.SkipWhitespace();
                        token = tokenizer.ExpectToken(ZScriptTokenType.String);
                        if (token == null || !token.IsValid)
                        {
                            ReportError("Expected version string, got " + ((Object)token ?? "<null>").ToString());
                            return(false);
                        }
                        break;

                    default:
                        ReportError("Expected preprocessor statement, const, enum or class declaraction, got " + token);
                        return(false);
                    }
                    break;
                }
                }
            }

            return(true);
        }
        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
            string currentgametype = GameType.UNKNOWN;

            while (SkipWhitespace(true))
            {
                //INFO: For many commands, using * as the sound name will mean that
                //INFO: the command will apply to all sounds that do not specify otherwise.
                string token = StripTokenQuotes(ReadToken()).ToLowerInvariant();
                if (string.IsNullOrEmpty(token))
                {
                    continue;
                }

                // Skipping block for different game?
                if (currentgametype != GameType.UNKNOWN && currentgametype != General.Map.Config.BaseGame)
                {
                    // Should we stop skipping?
                    if (token == "$endif")
                    {
                        currentgametype = GameType.UNKNOWN;
                    }
                    continue;
                }

                switch (token)
                {
                // Must parse all commands to reliably get sound assignments...
                case "$alias": if (!ParseAlias())
                    {
                        return(false);
                    }
                    break;

                case "$ambient": if (!ParseAmbient())
                    {
                        return(false);
                    }
                    break;

                case "$archivepath": if (!SkipTokens(1))
                    {
                        return(false);
                    }
                    break;

                case "$attenuation": if (!ParseAttenuation())
                    {
                        return(false);
                    }
                    break;

                case "$edfoverride": break;

                case "$limit": if (!ParseLimit())
                    {
                        return(false);
                    }
                    break;

                case "$map": if (!SkipTokens(2))
                    {
                        return(false);
                    }
                    break;

                case "$mididevice": if (!ParseMidiDevice())
                    {
                        return(false);
                    }
                    break;

                case "$musicalias": if (!SkipTokens(2))
                    {
                        return(false);
                    }
                    break;

                case "$musicvolume": if (!SkipTokens(2))
                    {
                        return(false);
                    }
                    break;

                case "$pitchshift": if (!SkipTokens(2))
                    {
                        return(false);
                    }
                    break;

                case "$pitchshiftrange": if (!SkipTokens(1))
                    {
                        return(false);
                    }
                    break;

                case "$playeralias": if (!SkipTokens(4))
                    {
                        return(false);
                    }
                    break;

                case "$playercompat": if (!SkipTokens(4))
                    {
                        return(false);
                    }
                    break;

                case "$playersound": if (!SkipTokens(4))
                    {
                        return(false);
                    }
                    break;

                case "$playersounddup": if (!SkipTokens(4))
                    {
                        return(false);
                    }
                    break;

                case "$random": if (!ParseRandom())
                    {
                        return(false);
                    }
                    break;

                case "$registered": break;

                case "$rolloff": if (!ParseRolloff())
                    {
                        return(false);
                    }
                    break;

                case "$singular": if (!SkipTokens(1))
                    {
                        return(false);
                    }
                    break;

                case "$volume": if (!ParseVolume())
                    {
                        return(false);
                    }
                    break;

                // Game type blocks...
                case "$ifdoom": currentgametype = GameType.DOOM; break;

                case "$ifheretic": currentgametype = GameType.HERETIC; break;

                case "$ifhexen": currentgametype = GameType.HEXEN; break;

                case "$ifstrife": currentgametype = GameType.STRIFE; break;

                // Should be logicalname lumpname pair...
                default: if (!ParseSoundAssignment(token))
                    {
                        return(false);
                    }
                    break;
                }
            }

            return(true);
        }
Beispiel #15
0
        // Should be called after all decorate actors are parsed
        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);
            }

            // Keep local data
            Stream       localstream           = datastream;
            string       localsourcename       = sourcename;
            BinaryReader localreader           = datareader;
            DataLocation locallocation         = datalocation;     //mxd
            string       localtextresourcepath = textresourcepath; //mxd

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                string token = ReadToken();

                if (string.IsNullOrEmpty(token) || token.ToLowerInvariant() != "model")
                {
                    if (token != null && token.ToLowerInvariant() == "#include")
                    {
                        //INFO: ZDoom DECORATE include paths can't be relative ("../actor.txt")
                        //or absolute ("d:/project/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);
                        string filename = StripQuotes(ReadToken(false)); //mxd. Don't skip newline

                        //mxd. Sanity checks
                        if (string.IsNullOrEmpty(filename))
                        {
                            ReportError("Expected file name to include");
                            return(false);
                        }

                        //mxd. Check invalid path chars
                        if (!CheckInvalidPathChars(filename))
                        {
                            return(false);
                        }

                        //mxd. Absolute paths are not supported...
                        if (Path.IsPathRooted(filename))
                        {
                            ReportError("Absolute include paths are not supported by ZDoom");
                            return(false);
                        }

                        //mxd. Relative paths are not supported
                        if (filename.StartsWith(RELATIVE_PATH_MARKER) || filename.StartsWith(CURRENT_FOLDER_PATH_MARKER) ||
                            filename.StartsWith(ALT_RELATIVE_PATH_MARKER) || filename.StartsWith(ALT_CURRENT_FOLDER_PATH_MARKER))
                        {
                            ReportError("Relative include paths are not supported by ZDoom");
                            return(false);
                        }

                        //mxd. Backward slashes are not supported
                        if (filename.Contains("\\"))
                        {
                            ReportError("Only forward slashes are supported by ZDoom");
                            return(false);
                        }

                        //mxd. Already parsed?
                        if (parsedlumps.Contains(filename))
                        {
                            ReportError("Already parsed \"" + filename + "\". Check your include directives");
                            return(false);
                        }

                        //mxd. Add to collection
                        parsedlumps.Add(filename);

                        // Callback to parse this file now
                        if (OnInclude != null)
                        {
                            OnInclude(this, filename);
                        }

                        //mxd. Bail out on error
                        if (this.HasError)
                        {
                            return(false);
                        }

                        // Set our buffers back to continue parsing
                        datastream       = localstream;
                        datareader       = localreader;
                        sourcename       = localsourcename;
                        datalocation     = locallocation;         //mxd
                        textresourcepath = localtextresourcepath; //mxd
                    }

                    continue;
                }

                // Find classname
                SkipWhitespace(true);
                string classname = StripQuotes(ReadToken(ActorStructure.ACTOR_CLASS_SPECIAL_TOKENS));
                if (string.IsNullOrEmpty(classname))
                {
                    ReportError("Expected actor class");
                    return(false);
                }

                // Check if actor exists
                bool haveplaceableactor = actorsbyclass.ContainsKey(classname);
                if (!haveplaceableactor && (General.Map.Data.GetZDoomActor(classname) == null))
                {
                    LogWarning("DECORATE class \"" + classname + "\" does not exist");
                }

                // Now find opening brace
                if (!NextTokenIs("{"))
                {
                    return(false);
                }

                // Parse the structure
                ModeldefStructure mds = new ModeldefStructure();
                if (mds.Parse(this))
                {
                    // Fetch Actor info
                    if (haveplaceableactor)
                    {
                        ThingTypeInfo info = General.Map.Data.GetThingInfoEx(actorsbyclass[classname]);
                        if (info != null)
                        {
                            // Already have a voxel model?
                            if (General.Map.Data.ModeldefEntries.ContainsKey(info.Index) && General.Map.Data.ModeldefEntries[info.Index].IsVoxel)
                            {
                                LogWarning("Both voxel(s) and model(s) are defined for actor\"" + classname + "\". Consider using either former or latter");
                            }
                            // Actor has a valid sprite?
                            else if (!string.IsNullOrEmpty(info.Sprite) && !info.Sprite.ToLowerInvariant().StartsWith(DataManager.INTERNAL_PREFIX) &&
                                     (info.Sprite.Length == 6 || info.Sprite.Length == 8))
                            {
                                string targetsprite = info.Sprite.Substring(0, 5);
                                if (mds.Frames.ContainsKey(targetsprite))
                                {
                                    // Create model data
                                    ModelData md = new ModelData {
                                        InheritActorPitch = mds.InheritActorPitch, UseActorPitch = mds.UseActorPitch, UseActorRoll = mds.UseActorRoll, Path = mds.DataPath
                                    };

                                    // Things are complicated in GZDoom...
                                    Matrix moffset = Matrix.Translation(mds.Offset.Y, -mds.Offset.X, mds.Offset.Z);
                                    //Matrix mrotation = Matrix.RotationZ(Angle2D.DegToRad(mds.AngleOffset)) * Matrix.RotationY(-Angle2D.DegToRad(mds.RollOffset)) * Matrix.RotationX(-Angle2D.DegToRad(mds.PitchOffset));
                                    Matrix mrotation = Matrix.RotationY((float)-Angle2D.DegToRad(mds.RollOffset)) * Matrix.RotationX((float)-Angle2D.DegToRad(mds.PitchOffset)) * Matrix.RotationZ((float)Angle2D.DegToRad(mds.AngleOffset));
                                    md.SetTransform(mrotation, moffset, mds.Scale);

                                    // Add models
                                    int disabledframescount = 0;
                                    foreach (var fs in mds.Frames[targetsprite])
                                    {
                                        // Sanity checks
                                        if (string.IsNullOrEmpty(mds.ModelNames[fs.ModelIndex]))
                                        {
                                            LogWarning("Model definition \"" + classname + "\", frame \"" + fs.SpriteName + " " + fs.FrameName + "\" references undefined model index " + fs.ModelIndex);
                                            continue;
                                        }

                                        //INFO: setting frame index to a negative number disables model rendering in GZDoom
                                        if (fs.FrameIndex < 0)
                                        {
                                            disabledframescount++;
                                            continue;
                                        }

                                        // Texture name will be empty when skin path is embedded in the model
                                        string skinname = (!string.IsNullOrEmpty(mds.SkinNames[fs.ModelIndex]) ? mds.SkinNames[fs.ModelIndex].ToLowerInvariant() : string.Empty);

                                        md.SkinNames.Add(skinname);
                                        md.SurfaceSkinNames.Add(mds.SurfaceSkinNames[fs.ModelIndex]);
                                        md.ModelNames.Add(mds.ModelNames[fs.ModelIndex].ToLowerInvariant());
                                        md.FrameNames.Add(fs.FrameName);
                                        md.FrameIndices.Add(fs.FrameIndex);
                                    }

                                    // More sanity checks...
                                    if (md.ModelNames.Count == 0)
                                    {
                                        // Show warning only when frames were not delibeartely disabled
                                        if (mds.Frames[targetsprite].Count > 0 && disabledframescount < mds.Frames[targetsprite].Count)
                                        {
                                            LogWarning("Model definition \"" + classname + "\" has no defined models");
                                        }
                                    }
                                    else
                                    {
                                        // Add to collection
                                        entries[classname] = md;
                                    }
                                }
                            }
                        }
                    }
                }

                if (HasError)
                {
                    LogError();
                    ClearError();
                }
            }

            return(true);
        }
        public bool Parse(TextResourceData data, string mapname, bool clearerrors)
        {
            this.mapname = mapname.ToLowerInvariant();

            //mxd. Already parsed?
            if (!base.AddTextResource(data))
            {
                if (clearerrors)
                {
                    ClearError();
                }
                return(true);
            }

            // Cannot process?
            if (!base.Parse(data, clearerrors))
            {
                return(false);
            }

            // Keep local data
            Stream       localstream           = datastream;
            string       localsourcename       = sourcename;
            int          localsourcelumpindex  = sourcelumpindex;
            BinaryReader localreader           = datareader;
            DataLocation locallocation         = datalocation;
            string       localtextresourcepath = textresourcepath;

            // Classic format skip stoppers...
            HashSet <string> breakat = new HashSet <string> {
                "map", "defaultmap", "adddefaultmap"
            };

            while (SkipWhitespace(true))
            {
                string token = ReadToken().ToLowerInvariant();
                if (string.IsNullOrEmpty(token) || token == "$gzdb_skip")
                {
                    break;
                }

                switch (token)
                {
                case "adddefaultmap":
                    // Parse properties
                    if (!ParseMapBlock())
                    {
                        return(false);
                    }
                    break;

                case "defaultmap":
                    // Reset MapInfo
                    mapinfo = new MapInfo();

                    // Parse properties
                    if (!ParseMapBlock())
                    {
                        return(false);
                    }
                    break;

                case "map":
                    // Get map lump name
                    SkipWhitespace(true);
                    token = ReadToken().ToLowerInvariant();
                    if (token != this.mapname)
                    {
                        // Map number? Try to build map name from it...
                        int n;
                        if (int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out n))
                        {
                            token = ((n > 0 && n < 10) ? "map0" + n : "map" + n);
                        }

                        // Still no dice?
                        if (token != this.mapname)
                        {
                            SkipStructure(breakat);
                            continue;                                     // Not finished, search for next "map", "defaultmap" or "adddefaultmap" block
                        }
                    }

                    // Try to get map name
                    SkipWhitespace(true);
                    token = ReadToken();
                    if (token.ToLowerInvariant() == "lookup")
                    {
                        // No dice...
                        SkipWhitespace(true);
                        ReadToken();
                    }
                    else
                    {
                        mapinfo.Title = StripQuotes(token);
                    }

                    // Parse properties
                    if (!ParseMapBlock())
                    {
                        return(false);
                    }

                    // There is a map entry for current map, which makes it defined
                    mapinfo.IsDefined = true;
                    break;

                case "include":
                    if (!ParseInclude(clearerrors))
                    {
                        return(false);
                    }

                    // Set our buffers back to continue parsing
                    datastream       = localstream;
                    datareader       = localreader;
                    sourcename       = localsourcename;
                    sourcelumpindex  = localsourcelumpindex;
                    datalocation     = locallocation;
                    textresourcepath = localtextresourcepath;
                    break;

                case "gameinfo":
                    if (!ParseGameInfo())
                    {
                        return(false);
                    }
                    break;

                case "doomednums":
                    if (!ParseDoomEdNums())
                    {
                        return(false);
                    }
                    break;

                case "spawnnums":
                    if (!ParseSpawnNums())
                    {
                        return(false);
                    }
                    break;
                }
            }

            // Check values
            if (mapinfo.FogDensity > 0 && (mapinfo.FadeColor.Red > 0 || mapinfo.FadeColor.Green > 0 || mapinfo.FadeColor.Blue > 0))
            {
                mapinfo.HasFadeColor = true;
            }

            if (mapinfo.OutsideFogDensity > 0 && (mapinfo.OutsideFogColor.Red > 0 || mapinfo.OutsideFogColor.Green > 0 || mapinfo.OutsideFogColor.Blue > 0))
            {
                mapinfo.HasOutsideFogColor = true;
            }

            if (string.IsNullOrEmpty(mapinfo.Sky2) && mapinfo.DoubleSky)
            {
                LogWarning("\"doublesky\" flag is defined without \"Sky2\" property.");
                mapinfo.DoubleSky = false;
            }

            // All done
            return(!this.HasError);
        }
        /// <summary>
        /// Parses DECALDEF data
        /// </summary>
        /// <param name="data">The data to parse</param>
        /// <param name="clearerrors">If errors should be cleared</param>
        /// <returns>true if paring worked, otherwise false</returns>
        public override bool Parse(TextResourceData data, bool clearerrors)
        {
            if (!AddTextResource(data))
            {
                if (clearerrors)
                {
                    ClearError();
                }
                return(true);
            }

            // Cannot process?
            if (!base.Parse(data, clearerrors))
            {
                return(false);
            }

            while (SkipWhitespace(true))
            {
                string token = ReadToken().ToLowerInvariant();
                if (string.IsNullOrEmpty(token))
                {
                    continue;
                }

                switch (token)
                {
                case "decal":
                case "decalgroup":
                    DecalInfo.DecalType type = token == "decal" ? DecalInfo.DecalType.DECAL : DecalInfo.DecalType.DECALGROUP;
                    string decalname;
                    int    decalid = -1;

                    SkipWhitespace(false);
                    token = ReadToken();
                    if (!string.IsNullOrEmpty(token))
                    {
                        decalname = token;
                    }
                    else
                    {
                        ReportError("Expected decal name, got nothing");
                        return(false);
                    }

                    SkipWhitespace(false);

                    // Try to read the optional decal id
                    token = ReadToken();
                    if (!string.IsNullOrEmpty(token))
                    {
                        ReadSignedInt(token, ref decalid);
                    }

                    SkipWhitespace(true);

                    DecalInfo di = new DecalInfo(decalname, decalid, type);

                    if (!di.Parse(this))
                    {
                        return(false);
                    }

                    if (decals.ContainsKey(decalname))
                    {
                        // TODO: report problem

                        // Overwrite existing decal with new one (who knows if that's the correct way do handle duplicate entries?)
                        decals[decalname] = di;
                    }
                    else
                    {
                        decals.Add(decalname, di);
                    }

                    break;
                }
            }

            return(true);
        }
Beispiel #18
0
        // This runs the compiler
        public override bool Run()
        {
            Process process;
            int     line      = 0;
            string  sourcedir = Path.GetDirectoryName(sourcefile);

            // Preprocess the file
            parser = new AcsParserSE
            {
                IsMapScriptsLump = SourceIsMapScriptsLump,
                OnInclude        = delegate(AcsParserSE se, string includefile, AcsParserSE.IncludeType includetype)
                {
                    TextResourceData data = General.Map.Data.GetTextResourceData(includefile);
                    if (data == null)
                    {
                        se.ReportError("Unable to find include file \"" + includefile + "\".");
                        return(false);                        // Fial
                    }

                    return(se.Parse(data, true, includetype, false));
                }
            };

            string inputfilepath = Path.Combine(this.tempdir.FullName, inputfile);

            using (FileStream stream = File.OpenRead(inputfilepath))
            {
                // Map SCRIPTS lump is empty. Abort the process without generating any warnings or errors.
                if (SourceIsMapScriptsLump && stream.Length == 0)
                {
                    return(false);
                }

                DataLocation dl = new DataLocation(DataLocation.RESOURCE_DIRECTORY, Path.GetDirectoryName(inputfilepath), false, false, false);
                //mxd. TextResourceData must point to temp path when compiling WAD lumps for lump to be recognized as map lump when reporting errors...
                TextResourceData data = new TextResourceData(stream, dl, (SourceIsMapScriptsLump ? inputfile : sourcefile));
                if (!parser.Parse(data, info.Files, true, AcsParserSE.IncludeType.NONE, false))
                {
                    // Check for errors
                    if (parser.HasError)
                    {
                        ReportError(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
                    }
                    return(true);
                }
            }

            //mxd. External lumps should be libraries
            if (!SourceIsMapScriptsLump && !parser.IsLibrary)
            {
                ReportError(new CompilerError("External ACS files can only be compiled as libraries.", sourcefile));
                return(true);
            }

            //mxd. Update script names if we are compiling the map SCRIPTS lump
            if (SourceIsMapScriptsLump)
            {
                General.Map.UpdateScriptNames(parser);
            }

            //xabis
            // Copy includes from the resources into the compiler's folder, preserving relative pathing and naming
            HashSet <string> includes = parser.GetIncludes();            //mxd

            foreach (string include in includes)
            {
                // Grab the script text from the resources
                TextResourceData data = General.Map.Data.GetTextResourceData(include);
                if (data != null && data.Stream != null)
                {
                    // Pull the pk3 or directory sub folder out if applicable
                    FileInfo fi = new FileInfo(Path.Combine(this.tempdir.FullName, include));

                    // Do not allow files to be overwritten, either accidentally or maliciously
                    if (!fi.Exists)
                    {
                        General.WriteLogLine("Copying script include: " + include);

                        // Create the directory path as needed
                        if (!string.IsNullOrEmpty(fi.DirectoryName))
                        {
                            Directory.CreateDirectory(fi.DirectoryName);
                        }

                        // Dump the script into the target file
                        BinaryReader reader = new BinaryReader(data.Stream);
                        File.WriteAllBytes(fi.FullName, reader.ReadBytes((int)data.Stream.Length));
                    }
                }
            }

            // Create parameters
            string args = this.parameters;

            args = args.Replace("%FI", inputfile);
            args = args.Replace("%FO", outputfile);
            args = args.Replace("%FS", sourcefile);
            args = args.Replace("%PT", this.tempdir.FullName);
            args = args.Replace("%PS", sourcedir);
            args = args.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);             //mxd. This fixes include path when the map is in a root directory

            // Setup process info
            ProcessStartInfo processinfo = new ProcessStartInfo();

            processinfo.Arguments        = args;
            processinfo.FileName         = Path.Combine(info.Path, info.ProgramFile);     //mxd
            processinfo.CreateNoWindow   = false;
            processinfo.ErrorDialog      = false;
            processinfo.UseShellExecute  = true;
            processinfo.WindowStyle      = ProcessWindowStyle.Hidden;
            processinfo.WorkingDirectory = this.workingdir;

            // Output info
            General.WriteLogLine("Running compiler...");
            General.WriteLogLine("Program:    " + processinfo.FileName);
            General.WriteLogLine("Arguments:  " + processinfo.Arguments);

            try
            {
                // Start the compiler
                process = Process.Start(processinfo);
            }
            catch (Exception e)
            {
                // Unable to start the compiler
                General.ShowErrorMessage("Unable to start the compiler (" + info.Name + "). " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK);
                return(false);
            }

            // Wait for compiler to complete
            process.WaitForExit();
            TimeSpan deltatime = TimeSpan.FromTicks(process.ExitTime.Ticks - process.StartTime.Ticks);

            General.WriteLogLine("Compiler process has finished.");
            General.WriteLogLine("Compile time: " + deltatime.TotalSeconds.ToString("########0.00") + " seconds");

            // Now find the error file
            string errfile = Path.Combine(this.workingdir, ACS_ERROR_FILE);

            if (File.Exists(errfile))
            {
                try
                {
                    // Regex to find error lines
                    Regex errlinematcher = new Regex(":[0-9]+: ", RegexOptions.Compiled | RegexOptions.CultureInvariant);

                    // Read all lines
                    bool     erroradded = false;                                                          //mxd
                    string[] errlines   = File.ReadAllLines(errfile);
                    string   temppath   = this.tempdir.FullName + Path.DirectorySeparatorChar.ToString(); //mxd. Need trailing slash..
                    while (line < errlines.Length)
                    {
                        // Check line
                        string linestr = errlines[line];
                        Match  match   = errlinematcher.Match(linestr);
                        if (match.Success && (match.Index > 0))
                        {
                            CompilerError err = new CompilerError();

                            // The match without spaces and semicolon is the line number
                            string linenr = match.Value.Replace(":", "").Trim();
                            if (!int.TryParse(linenr, out err.linenumber))
                            {
                                err.linenumber = CompilerError.NO_LINE_NUMBER;
                            }
                            else
                            {
                                err.linenumber--;
                            }

                            // Everything before the match is the filename
                            err.filename = linestr.Substring(0, match.Index).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

                            //mxd. Get rid of temp directory path
                            if (err.filename.StartsWith(temppath))
                            {
                                err.filename = err.filename.Replace(temppath, string.Empty);
                            }

                            if (!Path.IsPathRooted(err.filename))
                            {
                                //mxd. If the error is in an include file, try to find it in loaded resources
                                if (includes.Contains(err.filename))
                                {
                                    foreach (DataReader dr in General.Map.Data.Containers)
                                    {
                                        if (dr is DirectoryReader && dr.FileExists(err.filename))
                                        {
                                            err.filename = Path.Combine(dr.Location.location, err.filename);
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    // Add working directory to filename, so it could be recognized as map namespace lump in MapManager.CompileLump()
                                    err.filename = Path.Combine(processinfo.WorkingDirectory, err.filename);
                                }
                            }

                            // Everything after the match is the description
                            err.description = linestr.Substring(match.Index + match.Length).Trim();

                            // Report the error
                            ReportError(err);
                            erroradded = true;                             //mxd
                        }

                        // Next line
                        line++;
                    }

                    //mxd. Some ACC errors are not properly formatted. If that's the case, threat the whole acs.err as an error...
                    if (!erroradded && errlines.Length > 0)
                    {
                        ReportError(new CompilerError(string.Join(Environment.NewLine, errlines)));
                    }
                }
                catch (Exception e)
                {
                    // Error reading errors (ironic, isn't it)
                    ReportError(new CompilerError("Failed to retrieve compiler error report. " + e.GetType().Name + ": " + e.Message));
                }
            }

            return(true);
        }
Beispiel #19
0
        // This parses the given 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);
            }

            //mxd. Make vitrual path from filename
            string virtualpath;

            if (data.LumpIndex != -1)            // It's TEXTURES lump
            {
                virtualpath = data.Filename;
            }
            else             // If it's actual filename, try to use extension(s) as virtualpath
            {
                virtualpath = Path.GetFileName(data.Filename);
                if (!string.IsNullOrEmpty(virtualpath))
                {
                    virtualpath = virtualpath.Substring(8).TrimStart(pathtrimchars);
                }
                if (!string.IsNullOrEmpty(virtualpath) && virtualpath.ToLowerInvariant() == "txt")
                {
                    virtualpath = string.Empty;
                }
                if (string.IsNullOrEmpty(virtualpath))
                {
                    virtualpath = "[TEXTURES]";
                }
            }

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                // Read a token
                string objdeclaration = ReadToken();
                if (!string.IsNullOrEmpty(objdeclaration))
                {
                    objdeclaration = objdeclaration.ToLowerInvariant();
                    switch (objdeclaration)
                    {
                    case "texture":
                    {
                        // Read texture structure
                        TextureStructure tx = new TextureStructure(this, "texture", virtualpath);
                        if (this.HasError)
                        {
                            return(false);
                        }

                        // if a limit for the texture name length is set make sure that it's not exceeded
                        if (tx.Name.Length > General.Map.Config.MaxTextureNameLength)
                        {
                            ReportError("Texture name \"" + tx.Name + "\" too long. Texture names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
                            return(false);
                        }

                        //mxd. Can't load image without name
                        if (string.IsNullOrEmpty(tx.Name))
                        {
                            ReportError("Can't load an unnamed texture. Please consider giving names to your resources");
                            return(false);
                        }

                        // Add the texture
                        textures[tx.Name] = tx;
                        if (!General.Map.Config.MixTexturesFlats)
                        {
                            flats[tx.Name] = tx;                                                                      //mxd. If MixTexturesFlats is set, textures and flats will be mixed in DataManager anyway
                        }
                    }
                    break;

                    case "sprite":
                    {
                        // Read sprite structure
                        TextureStructure tx = new TextureStructure(this, "sprite", virtualpath);
                        if (this.HasError)
                        {
                            return(false);
                        }

                        //mxd. Sprite name length must be either 6 or 8 chars
                        if (tx.Name.Length != 6 && tx.Name.Length != 8)
                        {
                            ReportError("Sprite name \"" + tx.Name + "\" is incorrect. Sprite names must have a length of 6 or 8 characters");
                            return(false);
                        }

                        //mxd. Can't load image without name
                        if (string.IsNullOrEmpty(tx.Name))
                        {
                            ReportError("Can't load an unnamed sprite. Please consider giving names to your resources");
                            return(false);
                        }

                        // Add the sprite
                        sprites[tx.Name] = tx;
                    }
                    break;

                    case "walltexture":
                    {
                        // Read walltexture structure
                        TextureStructure tx = new TextureStructure(this, "walltexture", virtualpath);
                        if (this.HasError)
                        {
                            return(false);
                        }

                        // if a limit for the walltexture name length is set make sure that it's not exceeded
                        if (tx.Name.Length > General.Map.Config.MaxTextureNameLength)
                        {
                            ReportError("WallTexture name \"" + tx.Name + "\" too long. WallTexture names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
                            return(false);
                        }

                        //mxd. Can't load image without name
                        if (string.IsNullOrEmpty(tx.Name))
                        {
                            ReportError("Can't load an unnamed WallTexture. Please consider giving names to your resources");
                            return(false);
                        }

                        // Add the walltexture
                        if (!textures.ContainsKey(tx.Name) || (textures[tx.Name].TypeName != "texture"))
                        {
                            textures[tx.Name] = tx;
                        }
                    }
                    break;

                    case "flat":
                    {
                        // Read flat structure
                        TextureStructure tx = new TextureStructure(this, "flat", virtualpath);
                        if (this.HasError)
                        {
                            return(false);
                        }

                        // if a limit for the flat name length is set make sure that it's not exceeded
                        if (tx.Name.Length > General.Map.Config.MaxTextureNameLength)
                        {
                            ReportError("Flat name \"" + tx.Name + "\" too long. Flat names must have a length of " + General.Map.Config.MaxTextureNameLength + " characters or less");
                            return(false);
                        }

                        //mxd. Can't load image without name
                        if (string.IsNullOrEmpty(tx.Name))
                        {
                            ReportError("Can't load an unnamed flat. Please consider giving names to your resources");
                            return(false);
                        }

                        // Add the flat
                        if (!flats.ContainsKey(tx.Name) || (flats[tx.Name].TypeName != "texture"))
                        {
                            flats[tx.Name] = tx;
                        }
                    }
                    break;

                    case "$gzdb_skip": return(!this.HasError);

                    default:
                    {
                        // Unknown structure!
                        // Best we can do now is just find the first { and then
                        // follow the scopes until the matching } is found
                        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);
                    }
                    break;
                    }
                }
            }

            // Return true when no errors occurred
            return(ErrorDescription == null);
        }
Beispiel #20
0
        public bool Parse(TextResourceData data, HashSet <string> configincludes, bool processincludes, IncludeType includetype, bool clearerrors)
        {
            string source = data.Filename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

            //INFO: files included or imported inside a library are not visible to the code outside it
            //and must be included/imported separately

            // Includes tracking. "Regular" includes go to "SCRIPTS" group, library includes are tracked per-library
            string includecategory = (processincludes && includetype == IncludeType.LIBRARY ? source : "SCRIPTS");

            if (!includes.ContainsKey(includecategory))
            {
                includes.Add(includecategory, new HashSet <string>(StringComparer.OrdinalIgnoreCase));
            }

            includestoskip = configincludes;
            int bracelevel = 0;

            // Already parsed?
            if (!base.AddTextResource(data))
            {
                if (clearerrors)
                {
                    ClearError();
                }
                return(true);
            }

            // Cannot process?
            if (!base.Parse(data, clearerrors))
            {
                return(false);
            }

            // Keep local data
            Stream       localstream          = datastream;
            string       localsourcename      = sourcename;
            int          localsourcelumpindex = sourcelumpindex;
            BinaryReader localreader          = datareader;
            DataLocation locallocation        = datalocation;
            string       localincludecategory = includecategory;

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                string token = ReadToken().ToLowerInvariant();
                if (string.IsNullOrEmpty(token))
                {
                    continue;
                }

                // Ignore inner scope stuff
                if (token == "{")
                {
                    bracelevel++; continue;
                }
                if (token == "}")
                {
                    bracelevel--; continue;
                }
                if (bracelevel > 0)
                {
                    continue;
                }

                switch (token)
                {
                case "script":
                {
                    SkipWhitespace(true);
                    int startpos = (int)datastream.Position;
                    token = ReadToken();

                    // Is this a named script?
                    if (token.IndexOf('"') != -1)
                    {
                        startpos += 1;
                        string scriptname = StripQuotes(token);

                        // Try to parse argument names
                        List <KeyValuePair <string, string> > args = ParseArgs();
                        List <string> argnames = new List <string>();
                        foreach (KeyValuePair <string, string> group in args)
                        {
                            argnames.Add(group.Value);
                        }

                        // Make full name
                        if (AddArgumentsToScriptNames)
                        {
                            scriptname += " " + GetArgumentNames(args);
                        }

                        // Add to collection
                        namedscripts.Add(new ScriptItem(scriptname, argnames, startpos, includetype != IncludeType.NONE));
                    }
                    // Should be numbered script
                    else
                    {
                        int n;
                        if (int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out n))
                        {
                            // Try to parse argument names
                            List <KeyValuePair <string, string> > args = ParseArgs();

                            // Now find the opening brace
                            do
                            {
                                if (!SkipWhitespace(true))
                                {
                                    break;
                                }
                                token = ReadToken();
                            } while(!string.IsNullOrEmpty(token) && token != "{");

                            token = ReadLine();
                            string name = "";
                            bracelevel = 1;

                            if (!string.IsNullOrEmpty(token))
                            {
                                int commentstart = token.IndexOf("//", StringComparison.Ordinal);
                                if (commentstart != -1)                                        // Found comment
                                {
                                    commentstart += 2;
                                    name          = token.Substring(commentstart, token.Length - commentstart).Trim();
                                }
                            }

                            bool customname = (name.Length > 0);
                            name = (customname ? name + " [Script " + n + "]" : "Script " + n);

                            List <string> argnames = new List <string>();
                            foreach (KeyValuePair <string, string> group in args)
                            {
                                argnames.Add(group.Value);
                            }

                            // Make full name
                            if (AddArgumentsToScriptNames)
                            {
                                name += " " + GetArgumentNames(args);
                            }

                            // Add to collection
                            numberedscripts.Add(new ScriptItem(n, name, argnames, startpos, includetype != IncludeType.NONE, customname));
                        }
                    }
                }
                break;

                case "function":
                {
                    SkipWhitespace(true);
                    string funcname = ReadToken();                             // Read return type
                    SkipWhitespace(true);
                    int startpos = (int)datastream.Position;
                    funcname += " " + ReadToken();                             // Read function name

                    // Try to parse argument names
                    List <KeyValuePair <string, string> > args = ParseArgs();
                    List <string> argnames = new List <string>();
                    foreach (KeyValuePair <string, string> group in args)
                    {
                        argnames.Add(group.Value);
                    }

                    // Make full name
                    if (AddArgumentsToScriptNames)
                    {
                        funcname += GetArgumentNames(args);
                    }

                    // Add to collection
                    functions.Add(new ScriptItem(funcname, argnames, startpos, includetype != IncludeType.NONE));
                }
                break;

                case "#library":
                    if (IsMapScriptsLump)
                    {
                        if (!IgnoreErrors)
                        {
                            ReportError("SCRIPTS lump can't be compiled as library.");
                        }
                        return(IgnoreErrors);
                    }

                    SkipWhitespace(true);
                    string libname = ReadToken(false);                             // Don't skip newline

                    if (!libname.StartsWith("\"") || !libname.EndsWith("\""))
                    {
                        if (!IgnoreErrors)
                        {
                            ReportError("#library name should be quoted.");
                        }
                        return(IgnoreErrors);
                    }

                    libname = StripQuotes(libname);

                    if (string.IsNullOrEmpty(libname))
                    {
                        if (!IgnoreErrors)
                        {
                            ReportError("Expected library name.");
                        }
                        return(IgnoreErrors);
                    }

                    // Store only when the script compiling was executed for is library
                    if (includetype == IncludeType.NONE)
                    {
                        libraryname = libname;
                        includetype = IncludeType.LIBRARY;
                    }

                    break;

                default:
                    if (processincludes && (token == "#include" || token == "#import"))
                    {
                        //INFO: ZDoom ACC include paths can be absolute ("d:\stuff\coollib.acs"), relative ("../coollib.acs")
                        //and can use forward and backward slashes ("acs\map01/script.acs")
                        //also include paths must be quoted
                        //long filenames are supported

                        SkipWhitespace(true);
                        string includelump = ReadToken(false);                                 // Don't skip newline

                        if (!includelump.StartsWith("\"") || !includelump.EndsWith("\""))
                        {
                            if (!IgnoreErrors)
                            {
                                ReportError(token + " filename should be quoted.");
                            }
                            return(IgnoreErrors);
                        }

                        includelump = StripQuotes(includelump);

                        if (string.IsNullOrEmpty(includelump))
                        {
                            if (!IgnoreErrors)
                            {
                                ReportError("Expected file name to " + token + ".");
                            }
                            return(IgnoreErrors);
                        }

                        includelump = includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

                        // Compiler files? Track them, but don't parse them
                        if (includestoskip.Contains(includelump))
                        {
                            // These can also be included several times...
                            if (includes[includecategory].Contains(includelump))
                            {
                                if (!IgnoreErrors)
                                {
                                    ReportError("Already parsed \"" + includelump + "\". Check your " + token + " directives.");
                                }
                                return(IgnoreErrors);
                            }

                            // Add to collection
                            includes[includecategory].Add(includelump);
                            continue;
                        }

                        // Convert to a path we can use
                        string includelumppath = GetRootedPath(source, includelump);

                        // Rooting succeeded?
                        if (this.HasError || string.IsNullOrEmpty(includelumppath))
                        {
                            return(IgnoreErrors);
                        }

                        // Already parsed?
                        if (includes[includecategory].Contains(includelumppath))
                        {
                            if (!IgnoreErrors)
                            {
                                ReportError("Already parsed \"" + includelump + "\". Check your " + token + " directives.");
                            }
                            return(IgnoreErrors);
                        }

                        // Add to collection
                        includes[includecategory].Add(includelumppath);

                        // Callback to parse this file
                        if (OnInclude != null)
                        {
                            IsMapScriptsLump = false;
                            if (!OnInclude(this, includelumppath, (token == "#import" ? IncludeType.LIBRARY : IncludeType.INCLUDE)))
                            {
                                return(IgnoreErrors);                                        // Bail out on errors
                            }
                        }

                        // Bail out on error
                        if (this.HasError)
                        {
                            return(IgnoreErrors);
                        }

                        // Set our buffers back to continue parsing
                        datastream      = localstream;
                        datareader      = localreader;
                        sourcename      = localsourcename;
                        sourcelumpindex = localsourcelumpindex;
                        datalocation    = locallocation;
                        includecategory = localincludecategory;
                    }
                    break;
                }
            }
            return(true);
        }
Beispiel #21
0
        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))
            {
                string token = ReadToken();
                long   cpos  = datastream.Position;

                if (!string.IsNullOrEmpty(token))
                {
                    token = token.ToUpperInvariant();

                    if (token == "MODEL")
                    {
                        SkipWhitespace(true);
                        ReadToken();                         //should be model name
                        SkipWhitespace(true);
                        token = ReadToken();                 //should be opening brace

                        if (token == "{")
                        {
                            scripttype = ScriptType.MODELDEF;
                            return(true);
                        }
                    }
                    else if (token == "SCRIPT")
                    {
                        SkipWhitespace(true);
                        ReadToken();                         //should be script name or number
                        SkipWhitespace(true);
                        ReadToken();                         //should be script parameters/type
                        SkipWhitespace(true);
                        token = ReadToken();                 //should be opening brace

                        if (token == "{")
                        {
                            scripttype = ScriptType.ACS;
                            return(true);
                        }
                    }
                    else if (token == "ACTOR")                    // [ZZ] note: by the looks of it, this doesn't handle the case when we write actor with DoomEdNum.
                    {
                        SkipWhitespace(true);
                        ReadToken();                         //should be actor name

                        SkipWhitespace(true);
                        token = ReadToken();

                        // [ZZ] note: original code compared token to REPLACES without doing ToUpper
                        if (token == ":" || token == "{" || (token != null && token.ToUpperInvariant() == "REPLACES"))
                        {
                            scripttype = ScriptType.DECORATE;
                            return(true);
                        }

                        SkipWhitespace(true);
                        token = ReadToken();                         //should be actor name

                        // [ZZ]
                        if (token != "{") // actor bla : bla2 10666 {
                        {
                            SkipWhitespace(true);
                            token = ReadToken();
                        }

                        if (token == "{")
                        {
                            scripttype = ScriptType.DECORATE;
                            return(true);
                        }
                    }
                    else if (token == "CLASS" || token == "STRUCT" || token == "ENUM" || token == "EXTEND")
                    {
                        if (token == "EXTEND")
                        {
                            SkipWhitespace(true);
                            token = ReadToken();
                            if (!string.IsNullOrEmpty(token))
                            {
                                token = token.ToUpperInvariant();
                            }
                        }

                        string otoken = token; // original token

                        SkipWhitespace(true);
                        ReadToken(); //should be actor name

                        SkipWhitespace(true);
                        token = ReadToken();

                        if ((otoken != "ENUM" && token == ":") || token == "{" || (otoken == "CLASS" && (token != null && token.ToUpperInvariant() == "REPLACES")))
                        {
                            scripttype = ScriptType.ZSCRIPT;
                            return(true);
                        }

                        SkipWhitespace(true);
                        token = ReadToken(); //should be actor name

                        if (token == "{")
                        {
                            scripttype = ScriptType.ZSCRIPT;
                            return(true);
                        }
                        return(true);
                    }
                }

                datastream.Position = cpos; // [ZZ] read next token, not whatever is left after possibly unsuccessful parsing.
            }

            return(false);
        }
        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
            while (SkipWhitespace(true))
            {
                string token = ReadToken();
                if (string.IsNullOrEmpty(token) || string.Compare(token, "CAMERATEXTURE", true) != 0)
                {
                    continue;
                }

                // Texture name
                SkipWhitespace(true);
                string texturename = StripQuotes(ReadToken(false));
                if (string.IsNullOrEmpty(texturename))
                {
                    ReportError("Expected camera texture name");
                    return(false);
                }

                /*
                 *              // Camera texture names are limited to 8 chars
                 *              if(texturename.Length > DataManager.CLASIC_IMAGE_NAME_LENGTH)
                 *              {
                 *                      ReportError("Camera texture names must be no longer than " + DataManager.CLASIC_IMAGE_NAME_LENGTH + " chars");
                 *                      return false;
                 *              }*/
                // [ZZ] not really. I've successfully tried it with >8 chars and it works.

                // Width
                int width = -1;
                SkipWhitespace(true);
                if (!ReadSignedInt(ref width) || width < 1)
                {
                    ReportError("Expected camera texture width");
                    return(false);
                }

                // Height
                int height = -1;
                SkipWhitespace(true);
                if (!ReadSignedInt(ref height) || height < 1)
                {
                    ReportError("Expected camera texture height");
                    return(false);
                }

                // "Fit" keyword?
                bool  worldpanning = false;
                bool  fit          = false;
                float scalex       = 1.0f;
                float scaley       = 1.0f;

                if (NextTokenIs("fit", false))
                {
                    fit = true;
                    int fitwidth  = width;
                    int fitheight = height;

                    // Fit width
                    SkipWhitespace(true);
                    if (!ReadSignedInt(ref fitwidth) || fitwidth < 1)
                    {
                        ReportError("Expected camera texture fit width");
                        return(false);
                    }

                    // Fit height
                    SkipWhitespace(true);
                    if (!ReadSignedInt(ref fitheight) || fitheight < 1)
                    {
                        ReportError("Expected camera texture fit height");
                        return(false);
                    }

                    // Update scale
                    scalex = (float)fitwidth / width;
                    scaley = (float)fitheight / height;

                    // WorldPanning
                    worldpanning = NextTokenIs("worldpanning", false);
                }
                else if (NextTokenIs("worldpanning", false))
                {
                    worldpanning = true;
                }

                // Check results
                if (cameratextures.ContainsKey(texturename.ToUpperInvariant()))
                {
                    ReportError("Camera texture \"" + texturename + "\" is defined more than once");
                    return(false);
                }

                // Store results
                texturename = texturename.ToUpperInvariant();
                cameratextures[texturename] = new CameraTextureData {
                    Name         = texturename, Width = width, Height = height,
                    ScaleX       = scalex, ScaleY = scaley,
                    WorldPanning = worldpanning, FitTexture = fit
                };
            }

            return(true);
        }
        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"
            };
            HashSet <string> flags = new HashSet <string> {
                "noarchive", "cheat", "latch"
            };

            while (SkipWhitespace(true))
            {
                string token = ReadToken().ToLowerInvariant();
                if (string.IsNullOrEmpty(token))
                {
                    continue;
                }

                //<scope> [noarchive] [cheat] [latch] <type> <name> [= <defaultvalue>];
                switch (token)
                {
                case "user":
                case "server":
                case "nosave":
                    // read (skip) flags
                    while (true)
                    {
                        string flagtoken;

                        SkipWhitespace(true);
                        flagtoken = ReadToken().ToLowerInvariant();

                        if (!flags.Contains(flagtoken))
                        {
                            DataStream.Seek(-flagtoken.Length - 1, SeekOrigin.Current);
                            break;
                        }
                    }

                    // Type
                    SkipWhitespace(true);
                    string type = ReadToken().ToLowerInvariant();

                    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);
        }
Beispiel #24
0
        public override bool Parse(TextResourceData data, bool clearerrors)
        {
            entries = new Dictionary <string, ModelData>(StringComparer.Ordinal);

            //mxd. Already parsed?
            if (!base.AddTextResource(data))
            {
                if (clearerrors)
                {
                    ClearError();
                }
                return(true);
            }

            // Cannot process?
            if (!base.Parse(data, clearerrors))
            {
                return(false);
            }

            List <string> spriteNames = new List <string>();
            string        modelName   = string.Empty;
            string        prevToken   = string.Empty;

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                string token = ReadToken().ToLowerInvariant();
                if (string.IsNullOrEmpty(token))
                {
                    continue;
                }

                if (token == ",")                //previous token was a sprite name
                {
                    if (!string.IsNullOrEmpty(prevToken) && !spriteNames.Contains(prevToken))
                    {
                        spriteNames.Add(prevToken);
                    }
                    prevToken = StripQuotes(token).ToUpperInvariant();
                }
                else if (token == "=")                //next token should be a voxel model name
                {
                    if (!string.IsNullOrEmpty(prevToken) && !spriteNames.Contains(prevToken))
                    {
                        spriteNames.Add(prevToken);
                    }

                    SkipWhitespace(true);
                    token = ReadToken();

                    if (string.IsNullOrEmpty(token))
                    {
                        ReportError("Expected voxel name");
                        return(false);
                    }

                    modelName = StripQuotes(token).ToUpperInvariant();
                }
                else if (token == "{")                //read the settings
                {
                    ModelData mde = new ModelData {
                        IsVoxel = true
                    };
                    float scale = 1.0f;

                    while (SkipWhitespace(true))
                    {
                        token = ReadToken().ToLowerInvariant();
                        if (string.IsNullOrEmpty(token))
                        {
                            continue;
                        }

                        if (token == "}")                        //store data
                        {
                            if (!string.IsNullOrEmpty(modelName) && spriteNames.Count > 0)
                            {
                                mde.ModelNames.Add(modelName);
                                mde.SetTransform(Matrix.RotationZ((float)Angle2D.DegToRad(mde.AngleOffset)), Matrix.Identity, new Vector3f(scale));

                                foreach (string s in spriteNames)
                                {
                                    //TODO: is this the proper behaviour?
                                    entries[s] = mde;
                                }

                                //reset local data
                                modelName = string.Empty;
                                prevToken = string.Empty;
                                spriteNames.Clear();
                            }

                            break;
                        }
                        else if (token == "overridepalette")
                        {
                            mde.OverridePalette = true;
                        }
                        else if (token == "angleoffset")
                        {
                            if (!NextTokenIs("="))
                            {
                                return(false);
                            }

                            token = ReadToken();
                            if (!ReadSignedFloat(token, ref mde.AngleOffset))
                            {
                                // Not numeric!
                                ReportError("Expected AngleOffset value, but got \"" + token + "\"");
                                return(false);
                            }
                        }
                        else if (token == "scale")
                        {
                            if (!NextTokenIs("="))
                            {
                                return(false);
                            }

                            token = ReadToken();
                            if (!ReadSignedFloat(token, ref scale))
                            {
                                // Not numeric!
                                ReportError("Expected Scale value, but got \"" + token + "\"");
                                return(false);
                            }
                        }

                        prevToken = StripQuotes(token).ToUpperInvariant();
                    }
                }
                else
                {
                    prevToken = StripQuotes(token).ToUpperInvariant();
                }
            }

            return(entries.Count > 0);
        }
Beispiel #25
0
 public bool Parse(TextResourceData data, bool processincludes, IncludeType includetype, bool clearerrors)
 {
     return(Parse(data, includestoskip, processincludes, includetype, clearerrors));
 }
        // This parses the given decorate 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);
            }

            //mxd. Region-as-category stuff...
            List <DecorateCategoryInfo> regions = new List <DecorateCategoryInfo>();           //mxd

            // Keep local data
            Stream       localstream           = datastream;
            string       localsourcename       = sourcename;
            BinaryReader localreader           = datareader;
            DataLocation locallocation         = datalocation;     //mxd
            string       localtextresourcepath = textresourcepath; //mxd

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                // Read a token
                string objdeclaration = ReadToken();
                if (!string.IsNullOrEmpty(objdeclaration))
                {
                    objdeclaration = objdeclaration.ToLowerInvariant();
                    if (objdeclaration == "$gzdb_skip")
                    {
                        break;
                    }
                    switch (objdeclaration)
                    {
                    case "actor":
                    {
                        // Read actor structure
                        ActorStructure actor = new ActorStructure(this, (regions.Count > 0 ? regions[regions.Count - 1] : null));
                        if (this.HasError)
                        {
                            return(false);
                        }

                        // Add the actor
                        archivedactors[actor.ClassName.ToLowerInvariant()] = actor;
                        if (actor.CheckActorSupported())
                        {
                            actors[actor.ClassName.ToLowerInvariant()] = actor;
                        }

                        // Replace an actor?
                        if (actor.ReplacesClass != null)
                        {
                            if (GetArchivedActorByName(actor.ReplacesClass) != null)
                            {
                                archivedactors[actor.ReplacesClass.ToLowerInvariant()] = actor;
                            }
                            else
                            {
                                LogWarning("Unable to find \"" + actor.ReplacesClass + "\" class to replace, while parsing \"" + actor.ClassName + "\"");
                            }

                            if (actor.CheckActorSupported() && GetActorByName(actor.ReplacesClass) != null)
                            {
                                actors[actor.ReplacesClass.ToLowerInvariant()] = actor;
                            }
                        }

                        //mxd. Add to current text resource
                        if (!textresources[textresourcepath].Entries.Contains(actor.ClassName))
                        {
                            textresources[textresourcepath].Entries.Add(actor.ClassName);
                        }
                    }
                    break;

                    case "#include":
                    {
                        //INFO: ZDoom DECORATE include paths can't be relative ("../actor.txt")
                        //or absolute ("d:/project/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);
                        string filename = StripQuotes(ReadToken(false));                                 //mxd. Don't skip newline

                        //mxd. Sanity checks
                        if (string.IsNullOrEmpty(filename))
                        {
                            ReportError("Expected file name to include");
                            return(false);
                        }

                        //mxd. Check invalid path chars
                        if (!CheckInvalidPathChars(filename))
                        {
                            return(false);
                        }

                        //mxd. Absolute paths are not supported...
                        if (Path.IsPathRooted(filename))
                        {
                            ReportError("Absolute include paths are not supported by ZDoom");
                            return(false);
                        }

                        //mxd. Relative paths are not supported
                        if (filename.StartsWith(RELATIVE_PATH_MARKER) || filename.StartsWith(CURRENT_FOLDER_PATH_MARKER) ||
                            filename.StartsWith(ALT_RELATIVE_PATH_MARKER) || filename.StartsWith(ALT_CURRENT_FOLDER_PATH_MARKER))
                        {
                            ReportError("Relative include paths are not supported by ZDoom");
                            return(false);
                        }

                        //mxd. Backward slashes are not supported
                        if (filename.Contains(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture)))
                        {
                            ReportError("Only forward slashes are supported by ZDoom");
                            return(false);
                        }

                        //mxd. Already parsed?
                        if (parsedlumps.Contains(filename))
                        {
                            ReportError("Already parsed \"" + filename + "\". Check your include directives");
                            return(false);
                        }

                        //mxd. Add to collection
                        parsedlumps.Add(filename);

                        // Callback to parse this file now
                        if (OnInclude != null)
                        {
                            OnInclude(this, filename);
                        }

                        //mxd. Bail out on error
                        if (this.HasError)
                        {
                            return(false);
                        }

                        // Set our buffers back to continue parsing
                        datastream       = localstream;
                        datareader       = localreader;
                        sourcename       = localsourcename;
                        datalocation     = locallocation;                             //mxd
                        textresourcepath = localtextresourcepath;                     //mxd
                    }
                    break;

                    case "damagetype":                             //mxd
                        // Get DamageType name
                        SkipWhitespace(true);
                        string damagetype = StripQuotes(ReadToken(false));
                        if (string.IsNullOrEmpty(damagetype))
                        {
                            ReportError("Expected DamageType name");
                            return(false);
                        }

                        // Next should be "{"
                        SkipWhitespace(true);
                        if (!NextTokenIs("{"))
                        {
                            return(false);
                        }

                        // Skip the structure
                        while (SkipWhitespace(true))
                        {
                            string t = ReadToken();
                            if (string.IsNullOrEmpty(t) || t == "}")
                            {
                                break;
                            }
                        }

                        // Add to collection
                        if (!damagetypes.Contains(damagetype))
                        {
                            damagetypes.Add(damagetype);
                        }
                        break;

                    case "enum":
                    case "native":
                    case "const":
                        while (SkipWhitespace(true))
                        {
                            string t = ReadToken();
                            if (string.IsNullOrEmpty(t) || t == ";")
                            {
                                break;
                            }
                        }
                        break;

                    //mxd. Region-as-category handling
                    case "#region":
                        SkipWhitespace(false);
                        string cattitle = ReadLine();
                        if (!string.IsNullOrEmpty(cattitle))
                        {
                            // Make new category info
                            string[] parts = cattitle.Split(DataManager.CATEGORY_SPLITTER, StringSplitOptions.RemoveEmptyEntries);

                            DecorateCategoryInfo info = new DecorateCategoryInfo();
                            if (regions.Count > 0)
                            {
                                // Preserve nesting
                                info.Category.AddRange(regions[regions.Count - 1].Category);
                                info.Properties = new Dictionary <string, List <string> >(regions[regions.Count - 1].Properties);
                            }
                            info.Category.AddRange(parts);

                            // Add to collection
                            regions.Add(info);
                        }
                        break;

                    //mxd. Region-as-category handling
                    case "#endregion":
                        if (regions.Count > 0)
                        {
                            regions.RemoveAt(regions.Count - 1);
                        }
                        else
                        {
                            LogWarning("Unexpected #endregion token");
                        }
                        break;

                    default:
                    {
                        //mxd. In some special cases (like the whole actor commented using "//") our special comments will be detected here...
                        if (objdeclaration.StartsWith("$"))
                        {
                            if (regions.Count > 0)
                            {
                                // Store region property
                                regions[regions.Count - 1].Properties[objdeclaration] = new List <string> {
                                    (SkipWhitespace(false) ? ReadLine() : "")
                                };
                            }
                            else
                            {
                                // Skip the whole line, then carry on
                                ReadLine();
                            }
                            break;
                        }

                        // Unknown structure!
                        // Best we can do now is just find the first { and then
                        // follow the scopes until the matching } is found
                        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);
                    }
                    break;
                    }
                }
            }

            // Return true when no errors occurred
            return(ErrorDescription == null);
        }
Beispiel #27
0
 public override bool Parse(TextResourceData data, bool clearerrors)
 {
     return(Parse(data, new HashSet <string>(), false, IncludeType.NONE, clearerrors));
 }
Beispiel #28
0
        // Should be called after all decorate actors are parsed
        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
            while (SkipWhitespace(true))
            {
                string token = ReadToken();
                if (string.IsNullOrEmpty(token) || token.ToLowerInvariant() != "model")
                {
                    continue;
                }

                // Find classname
                SkipWhitespace(true);
                string classname = StripQuotes(ReadToken(ActorStructure.ACTOR_CLASS_SPECIAL_TOKENS));
                if (string.IsNullOrEmpty(classname))
                {
                    ReportError("Expected actor class");
                    return(false);
                }

                // Check if actor exists
                bool haveplaceableactor = actorsbyclass.ContainsKey(classname);
                if (!haveplaceableactor && (General.Map.Data.GetZDoomActor(classname) == null))
                {
                    LogWarning("DECORATE class \"" + classname + "\" does not exist");
                }

                // Now find opening brace
                if (!NextTokenIs("{"))
                {
                    return(false);
                }

                // Parse the structure
                ModeldefStructure mds = new ModeldefStructure();
                if (mds.Parse(this))
                {
                    // Fetch Actor info
                    if (haveplaceableactor)
                    {
                        ThingTypeInfo info = General.Map.Data.GetThingInfoEx(actorsbyclass[classname]);
                        if (info != null)
                        {
                            // Already have a voxel model?
                            if (General.Map.Data.ModeldefEntries.ContainsKey(info.Index) && General.Map.Data.ModeldefEntries[info.Index].IsVoxel)
                            {
                                LogWarning("Both voxel(s) and model(s) are defined for actor\"" + classname + "\". Consider using either former or latter");
                            }
                            // Actor has a valid sprite?
                            else if (!string.IsNullOrEmpty(info.Sprite) && !info.Sprite.ToLowerInvariant().StartsWith(DataManager.INTERNAL_PREFIX) &&
                                     (info.Sprite.Length == 6 || info.Sprite.Length == 8))
                            {
                                string targetsprite = info.Sprite.Substring(0, 5);
                                if (mds.Frames.ContainsKey(targetsprite))
                                {
                                    // Create model data
                                    ModelData md = new ModelData {
                                        InheritActorPitch = mds.InheritActorPitch, UseActorPitch = mds.UseActorPitch, UseActorRoll = mds.UseActorRoll
                                    };

                                    // Things are complicated in GZDoom...
                                    Matrix moffset   = Matrix.Translation(mds.Offset.Y, -mds.Offset.X, mds.Offset.Z);
                                    Matrix mrotation = Matrix.RotationY(-Angle2D.DegToRad(mds.RollOffset)) * Matrix.RotationX(-Angle2D.DegToRad(mds.PitchOffset)) * Matrix.RotationZ(Angle2D.DegToRad(mds.AngleOffset));
                                    md.SetTransform(mrotation, moffset, mds.Scale);

                                    // Add models
                                    int disabledframescount = 0;
                                    foreach (var fs in mds.Frames[targetsprite])
                                    {
                                        // Sanity checks
                                        if (string.IsNullOrEmpty(mds.ModelNames[fs.ModelIndex]))
                                        {
                                            LogWarning("Model definition \"" + classname + "\", frame \"" + fs.SpriteName + " " + fs.FrameName + "\" references undefiend model index " + fs.ModelIndex);
                                            continue;
                                        }

                                        //INFO: setting frame index to a negative number disables model rendering in GZDoom
                                        if (fs.FrameIndex < 0)
                                        {
                                            disabledframescount++;
                                            continue;
                                        }

                                        // Texture name will be empty when skin path is embedded in the model
                                        string skinname = (!string.IsNullOrEmpty(mds.SkinNames[fs.ModelIndex]) ? mds.SkinNames[fs.ModelIndex].ToLowerInvariant() : string.Empty);

                                        md.SkinNames.Add(skinname);
                                        md.SurfaceSkinNames.Add(mds.SurfaceSkinNames[fs.ModelIndex]);
                                        md.ModelNames.Add(mds.ModelNames[fs.ModelIndex].ToLowerInvariant());
                                        md.FrameNames.Add(fs.FrameName);
                                        md.FrameIndices.Add(fs.FrameIndex);
                                    }

                                    // More sanity checks...
                                    if (md.ModelNames.Count == 0)
                                    {
                                        // Show warning only when frames were not delibeartely disabled
                                        if (mds.Frames[targetsprite].Count > 0 && disabledframescount < mds.Frames[targetsprite].Count)
                                        {
                                            LogWarning("Model definition \"" + classname + "\" has no defined models");
                                        }
                                    }
                                    else
                                    {
                                        // Add to collection
                                        entries[classname] = md;
                                    }
                                }
                            }
                        }
                    }
                }

                if (HasError)
                {
                    LogError();
                    ClearError();
                }
            }

            return(true);
        }
        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
            bool skipdefinitions = false;

            while (SkipWhitespace(true))
            {
                string token = ReadToken().ToLowerInvariant();
                if (string.IsNullOrEmpty(token))
                {
                    continue;
                }

                if (skipdefinitions)
                {
                    do
                    {
                        SkipWhitespace(true);
                        token = ReadToken();
                    } while(!string.IsNullOrEmpty(token) && token != "endif");

                    skipdefinitions = false;
                    continue;
                }

                switch (token)
                {
                case "ifheretic":
                    skipdefinitions = (General.Map.Config.BaseGame != GameType.HERETIC);
                    break;

                case "ifhexen":
                    skipdefinitions = (General.Map.Config.BaseGame != GameType.HEXEN);
                    break;

                case "ifstrife":
                    skipdefinitions = (General.Map.Config.BaseGame != GameType.STRIFE);
                    break;

                case "ifdoom":                         // TODO: is it even a thing?..
                    skipdefinitions = (General.Map.Config.BaseGame != GameType.DOOM);
                    break;

                case "terrain":
                    SkipWhitespace(true);
                    token = ReadToken();
                    if (string.IsNullOrEmpty(token))
                    {
                        ReportError("Expected terrain name");
                        return(false);
                    }

                    // Add to collection
                    if (!terrainnames.Contains(token))
                    {
                        terrainnames.Add(token);
                    }
                    break;

                case "{":
                    // Skip inner properties
                    do
                    {
                        SkipWhitespace(true);
                        token = ReadToken();
                    } while(!string.IsNullOrEmpty(token) && token != "}");
                    break;
                }
            }

            return(true);
        }
        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);
            }

            // Keep local data
            Stream       localstream           = datastream;
            string       localsourcename       = sourcename;
            int          localsourcelumpindex  = sourcelumpindex;
            BinaryReader localreader           = datareader;
            DataLocation locallocation         = datalocation;
            string       localtextresourcepath = textresourcepath;

            // Continue until at the end of the stream
            while (SkipWhitespace(true))
            {
                string token = ReadToken().ToLowerInvariant();
                if (string.IsNullOrEmpty(token))
                {
                    continue;
                }

                switch (token)
                {
                case GldefsLightType.POINT:
                case GldefsLightType.PULSE:
                case GldefsLightType.SECTOR:
                case GldefsLightType.FLICKER:
                case GldefsLightType.FLICKER2:
                    if (!ParseLight(token))
                    {
                        return(false);
                    }
                    break;

                case "object":
                    if (!ParseObject())
                    {
                        return(false);
                    }
                    break;

                case "glow":
                    if (!ParseGlowingFlats())
                    {
                        return(false);
                    }
                    break;

                case "skybox":
                    if (!ParseSkybox())
                    {
                        return(false);
                    }
                    break;

                case "#include":
                    if (!ParseInclude(clearerrors))
                    {
                        return(false);
                    }

                    // Set our buffers back to continue parsing
                    datastream       = localstream;
                    datareader       = localreader;
                    sourcename       = localsourcename;
                    sourcelumpindex  = localsourcelumpindex;
                    datalocation     = locallocation;
                    textresourcepath = localtextresourcepath;
                    break;

                case "$gzdb_skip": return(!this.HasError);

                default:
                    // Unknown structure!
                    SkipStructure();
                    break;
                }
            }

            // All done
            return(!this.HasError);
        }