Ejemplo n.º 1
0
        // parse route for data
        private void ParseRouteForData(string FileName, System.Text.Encoding Encoding, Expression[] Expressions, double[] UnitOfLength, ref RouteData Data, bool PreviewOnly)
        {
            CurrentStation = -1;
            CurrentStop    = -1;
            CurrentSection = 0;

            string Section = ""; bool SectionAlwaysPrefix = false;
            int    BlockIndex = 0;

            CurrentRoute.Stations = new RouteStation[] { };
            Data.RequestStops     = new StopRequest[] { };
            double progressFactor = Expressions.Length == 0 ? 0.3333 : 0.3333 / Expressions.Length;

            // process non-track namespaces
            //Check for any special-cased fixes we might need
            CheckForAvailablePatch(FileName, ref Data, ref Expressions, PreviewOnly);
            //Apply parameters to object loaders
            if (!PreviewOnly)
            {
                for (int i = 0; i < Plugin.CurrentHost.Plugins.Length; i++)
                {
                    if (Plugin.CurrentHost.Plugins[i].Object != null)
                    {
                        EnabledHacks.BveTsHacks        = Plugin.CurrentOptions.EnableBveTsHacks;
                        EnabledHacks.BlackTransparency = true;
                        Plugin.CurrentHost.Plugins[i].Object.SetCompatibilityHacks(EnabledHacks);
                        //Remember that these will be ignored if not the correct plugin
                        Plugin.CurrentHost.Plugins[i].Object.SetObjectParser(Plugin.CurrentOptions.CurrentXParser);
                        Plugin.CurrentHost.Plugins[i].Object.SetObjectParser(Plugin.CurrentOptions.CurrentObjParser);
                    }
                }
            }

            for (int j = 0; j < Expressions.Length; j++)
            {
                Plugin.CurrentProgress = j * progressFactor;
                if ((j & 255) == 0)
                {
                    System.Threading.Thread.Sleep(1);
                    if (Plugin.Cancel)
                    {
                        Plugin.IsLoading = false;
                        return;
                    }
                }
                if (Expressions[j].Text.StartsWith("[") && Expressions[j].Text.EndsWith("]"))
                {
                    Section = Expressions[j].Text.Substring(1, Expressions[j].Text.Length - 2).Trim(new char[] { });
                    if (string.Compare(Section, "object", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        Section = "Structure";
                    }
                    else if (string.Compare(Section, "railway", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        Section = "Track";
                    }
                    SectionAlwaysPrefix = true;
                }
                else
                {
                    // find equals
                    if (IsRW)
                    {
                        Expressions[j].ConvertRwToCsv(Section, SectionAlwaysPrefix);
                    }

                    // separate command and arguments
                    string Command, ArgumentSequence;
                    Expressions[j].SeparateCommandsAndArguments(out Command, out ArgumentSequence, Culture, false, IsRW, Section);
                    // process command
                    bool NumberCheck = !IsRW || string.Compare(Section, "track", StringComparison.OrdinalIgnoreCase) == 0;
                    if (NumberCheck && NumberFormats.IsValidDouble(Command, UnitOfLength))
                    {
                        // track position (ignored)
                    }
                    else
                    {
                        string[] Arguments = SplitArguments(ArgumentSequence);

                        // preprocess command
                        if (Command.ToLowerInvariant() == "with")
                        {
                            if (Arguments.Length >= 1)
                            {
                                Section             = Arguments[0];
                                SectionAlwaysPrefix = false;
                            }
                            else
                            {
                                Section             = "";
                                SectionAlwaysPrefix = false;
                            }
                            Command = null;
                        }
                        else
                        {
                            if (Command.StartsWith("."))
                            {
                                Command = Section + Command;
                            }
                            else if (SectionAlwaysPrefix)
                            {
                                Command = Section + "." + Command;
                            }
                            Command = Command.Replace(".Void", "");
                            if (Command.StartsWith("structure", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = Command.Substring(0, Command.Length - 5).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = Command.Substring(0, Command.Length - 5).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "texture.backgroundx" + Command.Substring(18, Command.Length - 20).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "texture.backgroundaspect" + Command.Substring(18, Command.Length - 25).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "texture.backgroundx" + Command.Substring(14, Command.Length - 16).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "texture.backgroundaspect" + Command.Substring(14, Command.Length - 21).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("cycle", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".params", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = Command.Substring(0, Command.Length - 7).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("signal", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = Command.Substring(0, Command.Length - 5).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("train.run", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = Command.Substring(0, Command.Length - 4).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("train.flange", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = Command.Substring(0, Command.Length - 4).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".day.load", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "train.timetable.day" + Command.Substring(15, Command.Length - 24).Trim(new char[] { });
                            }
                            else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".night.load", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "train.timetable.night" + Command.Substring(15, Command.Length - 26).Trim(new char[] { });
                            }
                            else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".day", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "train.timetable.day" + Command.Substring(15, Command.Length - 19).Trim(new char[] { });
                            }
                            else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".night", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "train.timetable.night" + Command.Substring(15, Command.Length - 21).Trim(new char[] { });
                            }
                            else if (Command.StartsWith("route.signal", StringComparison.OrdinalIgnoreCase) && Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = Command.Substring(0, Command.Length - 4).TrimEnd(new char[] { });
                            }
                            else if (Command.StartsWith("route.runinterval", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "train.interval" + Command.Substring(17, Command.Length - 17);
                            }
                            else if (Command.StartsWith("train.gauge", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "route.gauge" + Command.Substring(11, Command.Length - 11);
                            }
                            else if (Command.StartsWith("texture.", StringComparison.OrdinalIgnoreCase))
                            {
                                Command = "structure." + Command.Substring(8, Command.Length - 8);
                            }
                            //Needed after the initial processing to make the enum parse work
                            Command = Command.Replace("timetable.day", "timetableday");
                            Command = Command.Replace("timetable.night", "timetablenight");
                        }

                        int[] commandIndices = FindIndices(ref Command, Expressions[j]);

                        // process command
                        if (!string.IsNullOrEmpty(Command))
                        {
                            int    period    = Command.IndexOf('.');
                            string nameSpace = string.Empty;
                            if (period != -1)
                            {
                                nameSpace = Command.Substring(0, period).ToLowerInvariant();
                                Command   = Command.Substring(period + 1);
                            }
                            Command = Command.ToLowerInvariant();

                            switch (nameSpace)
                            {
                            case "options":
                                OptionsCommand parsedOptionCommand;
                                if (Enum.TryParse(Command, true, out parsedOptionCommand))
                                {
                                    ParseOptionCommand(parsedOptionCommand, Arguments, UnitOfLength, Expressions[j], ref Data, PreviewOnly);
                                }
                                else
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Unrecognised command " + Command + " encountered in the Options namespace at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                }
                                break;

                            case "route":
                                RouteCommand parsedRouteCommand;
                                if (Enum.TryParse(Command, true, out parsedRouteCommand))
                                {
                                    ParseRouteCommand(parsedRouteCommand, Arguments, commandIndices[0], FileName, UnitOfLength, Expressions[j], ref Data, PreviewOnly);
                                }
                                else
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Unrecognised command " + Command + " encountered in the Route namespace at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                }
                                break;

                            case "train":
                                TrainCommand parsedTrainCommand;
                                if (Enum.TryParse(Command.Split(' ')[0], true, out parsedTrainCommand))
                                {
                                    ParseTrainCommand(parsedTrainCommand, Arguments, commandIndices[0], Expressions[j], ref Data, PreviewOnly);
                                }
                                else
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Unrecognised command " + Command + " encountered in the Train namespace at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                }
                                break;

                            case "structure":
                            case "texture":
                                StructureCommand parsedStructureCommand;
                                if (Enum.TryParse(Command, true, out parsedStructureCommand))
                                {
                                    ParseStructureCommand(parsedStructureCommand, Arguments, commandIndices, Encoding, Expressions[j], ref Data, PreviewOnly);
                                }
                                else
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Unrecognised command " + Command + " encountered in the Structure namespace at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                }
                                break;

                            case "":
                                ParseSignalCommand(Command, Arguments, commandIndices[0], Encoding, Expressions[j], ref Data, PreviewOnly);
                                break;

                            case "cycle":
                                CycleCommand parsedCycleCommand;
                                if (Enum.TryParse(Command, true, out parsedCycleCommand))
                                {
                                    ParseCycleCommand(parsedCycleCommand, Arguments, commandIndices[0], Expressions[j], ref Data, PreviewOnly);
                                }
                                else
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Unrecognised command " + Command + " encountered in the Cycle namespace at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                }
                                break;

                            case "track":
                                break;

                            // ReSharper disable once RedundantEmptySwitchSection
                            default:
                                /*
                                 * This needs an unrecognised command at some stage
                                 */
                                break;
                            }
                        }
                    }
                }
            }

            // process track namespace
            for (int j = 0; j < Expressions.Length; j++)
            {
                Plugin.CurrentProgress = 0.3333 + j * progressFactor;
                if ((j & 255) == 0)
                {
                    System.Threading.Thread.Sleep(1);
                    if (Plugin.Cancel)
                    {
                        Plugin.IsLoading = false;
                        return;
                    }
                }
                if (Data.LineEndingFix)
                {
                    if (Expressions[j].Text.EndsWith("_"))
                    {
                        Expressions[j].Text = Expressions[j].Text.Substring(0, Expressions[j].Text.Length - 1).Trim(new char[] { });
                    }
                }
                if (Expressions[j].Text.StartsWith("[") && Expressions[j].Text.EndsWith("]"))
                {
                    Section = Expressions[j].Text.Substring(1, Expressions[j].Text.Length - 2).Trim(new char[] { });
                    if (string.Compare(Section, "object", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        Section = "Structure";
                    }
                    else if (string.Compare(Section, "railway", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        Section = "Track";
                    }
                    SectionAlwaysPrefix = true;
                }
                else
                {
                    if (IsRW)
                    {
                        Expressions[j].ConvertRwToCsv(Section, SectionAlwaysPrefix);
                    }
                    // separate command and arguments
                    string Command, ArgumentSequence;
                    Expressions[j].SeparateCommandsAndArguments(out Command, out ArgumentSequence, Culture, false, IsRW, Section);
                    // process command
                    double currentTrackPosition;
                    bool   NumberCheck = !IsRW || string.Compare(Section, "track", StringComparison.OrdinalIgnoreCase) == 0;
                    if (NumberCheck && NumberFormats.TryParseDouble(Command, UnitOfLength, out currentTrackPosition))
                    {
                        // track position
                        if (ArgumentSequence.Length != 0)
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "A track position must not contain any arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                            if (AllowTrackPositionArguments)
                            {
                                Data.TrackPosition = currentTrackPosition;
                                BlockIndex         = (int)Math.Floor(currentTrackPosition / Data.BlockInterval + 0.001);
                                if (Data.FirstUsedBlock == -1)
                                {
                                    Data.FirstUsedBlock = BlockIndex;
                                }
                                Data.CreateMissingBlocks(BlockIndex, PreviewOnly);
                            }
                        }
                        else if (currentTrackPosition < 0.0)
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Negative track position encountered at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                        }
                        else
                        {
                            if (Plugin.CurrentOptions.EnableBveTsHacks && IsRW && currentTrackPosition == 4535545100)
                            {
                                //WMATA Red line has an erroneous track position causing an out of memory cascade
                                currentTrackPosition = 45355;
                            }
                            Data.TrackPosition = currentTrackPosition;
                            BlockIndex         = (int)Math.Floor(currentTrackPosition / Data.BlockInterval + 0.001);
                            if (Data.FirstUsedBlock == -1)
                            {
                                Data.FirstUsedBlock = BlockIndex;
                            }
                            Data.CreateMissingBlocks(BlockIndex, PreviewOnly);
                        }
                    }
                    else
                    {
                        string[] Arguments = SplitArguments(ArgumentSequence);

                        // preprocess command
                        if (Command.ToLowerInvariant() == "with")
                        {
                            if (Arguments.Length >= 1)
                            {
                                Section             = Arguments[0];
                                SectionAlwaysPrefix = false;
                            }
                            else
                            {
                                Section             = "";
                                SectionAlwaysPrefix = false;
                            }
                            Command = null;
                        }
                        else
                        {
                            if (Command.StartsWith("."))
                            {
                                Command = Section + Command;
                            }
                            else if (SectionAlwaysPrefix)
                            {
                                Command = Section + "." + Command;
                            }
                            Command = Command.Replace(".Void", "");
                        }

                        // process command
                        if (!string.IsNullOrEmpty(Command))
                        {
                            int    period    = Command.IndexOf('.');
                            string nameSpace = string.Empty;
                            if (period != -1)
                            {
                                nameSpace = Command.Substring(0, period).ToLowerInvariant();
                                Command   = Command.Substring(period + 1);
                            }
                            if (nameSpace.StartsWith("signal", StringComparison.InvariantCultureIgnoreCase))
                            {
                                nameSpace = "";
                            }
                            Command = Command.ToLowerInvariant();

                            switch (nameSpace)
                            {
                            case "track":
                                TrackCommand parsedCommand;
                                if (Enum.TryParse(Command, true, out parsedCommand))
                                {
                                    ParseTrackCommand(parsedCommand, Arguments, FileName, UnitOfLength, Expressions[j], ref Data, BlockIndex, PreviewOnly);
                                }
                                else
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Unrecognised command " + Command + " encountered in the Route namespace at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                }
                                break;

                            case "options":
                            case "route":
                            case "train":
                            case "structure":
                            case "texture":
                            case "":
                            case "cycle":
                                break;

                            default:
                                Plugin.CurrentHost.AddMessage(MessageType.Warning, false, "The command " + Command + " is not supported at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                break;
                            }
                        }
                    }
                }
            }
        }