Esempio n. 1
0
 // parse route for data
 private static void ParseRouteForData(string FileName, bool IsRW, System.Text.Encoding Encoding, Expression[] Expressions, string TrainPath, string ObjectPath, string SoundPath, double[] UnitOfLength, ref RouteData Data, bool PreviewOnly)
 {
     System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
     string Section = ""; bool SectionAlwaysPrefix = false;
     int BlockIndex = 0;
     int BlocksUsed = Data.Blocks.Length;
     Game.Stations = new Game.Station[] { };
     int CurrentStation = -1;
     int CurrentStop = -1;
     bool DepartureSignalUsed = false;
     int CurrentSection = 0;
     bool ValueBasedSections = false;
     double progressFactor = Expressions.Length == 0 ? 0.3333 : 0.3333 / (double)Expressions.Length;
     // process non-track namespaces
     for (int j = 0; j < Expressions.Length; j++) {
         Loading.RouteProgress = (double)j * progressFactor;
         if ((j & 255) == 0) {
             System.Threading.Thread.Sleep(1);
             if (Loading.Cancel) return;
         }
         if (Expressions[j].Text.StartsWith("[") & Expressions[j].Text.EndsWith("]")) {
             Section = Expressions[j].Text.Substring(1, Expressions[j].Text.Length - 2).Trim();
             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
             int Equals = Expressions[j].Text.IndexOf('=');
             if (Equals >= 0) {
                 // handle RW cycle syntax
                 string t = Expressions[j].Text.Substring(0, Equals);
                 if (Section.ToLowerInvariant() == "cycle" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Ground(" + t + ")";
                     }
                 } else if (Section.ToLowerInvariant() == "signal" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Void(" + t + ")";
                     }
                 }
                 // convert RW style into CSV style
                 Expressions[j].Text = t + " " + Expressions[j].Text.Substring(Equals + 1);
             }
             // separate command and arguments
             string Command, ArgumentSequence;
             SeparateCommandsAndArguments(Expressions[j], out Command, out ArgumentSequence, Culture, Expressions[j].File, j, false);
             // process command
             double Number;
             bool NumberCheck = !IsRW || string.Compare(Section, "track", StringComparison.OrdinalIgnoreCase) == 0;
             if (NumberCheck && Interface.TryParseDouble(Command, UnitOfLength, out Number)) {
                 // track position (ignored)
             } else {
                 // split arguments
                 string[] Arguments;
                 {
                     int n = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             n++;
                         } else if (ArgumentSequence[k] == ';') {
                             n++;
                         }
                     }
                     Arguments = new string[n + 1];
                     int a = 0, h = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         } else if (ArgumentSequence[k] == ';') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         }
                     }
                     if (ArgumentSequence.Length - a > 0) {
                         Arguments[h] = ArgumentSequence.Substring(a).Trim();
                         h++;
                     }
                     Array.Resize<string>(ref Arguments, h);
                 }
                 // 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();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.x" + Command.Substring(18, Command.Length - 20).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.aspect" + Command.Substring(18, Command.Length - 25).TrimEnd();
                     } else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.x" + Command.Substring(14, Command.Length - 16).TrimEnd();
                     } else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.aspect" + Command.Substring(14, Command.Length - 21).TrimEnd();
                     } else if (Command.StartsWith("cycle", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".params", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 7).TrimEnd();
                     } else if (Command.StartsWith("signal", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("train.run", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     } else if (Command.StartsWith("train.flange", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     } 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();
                     } 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();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".day", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.day" + Command.Substring(15, Command.Length - 19).Trim();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".night", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.night" + Command.Substring(15, Command.Length - 21).Trim();
                     } else if (Command.StartsWith("route.signal", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     }
                 }
                 // handle indices
                 int CommandIndex1 = 0, CommandIndex2 = 0;
                 if (Command != null && Command.EndsWith(")")) {
                     for (int k = Command.Length - 2; k >= 0; k--) {
                         if (Command[k] == '(') {
                             string Indices = Command.Substring(k + 1, Command.Length - k - 2).TrimStart();
                             Command = Command.Substring(0, k).TrimEnd();
                             int h = Indices.IndexOf(";");
                             if (h >= 0) {
                                 string a = Indices.Substring(0, h).TrimEnd();
                                 string b = Indices.Substring(h + 1).TrimStart();
                                 if (a.Length > 0 && !Interface.TryParseIntVb6(a, out CommandIndex1)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid first index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 } else if (b.Length > 0 && !Interface.TryParseIntVb6(b, out CommandIndex2)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid second index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 }
                             } else {
                                 if (Indices.Length > 0 && !Interface.TryParseIntVb6(Indices, out CommandIndex1)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 }
                             }
                             break;
                         }
                     }
                 }
                 // process command
                 if (Command != null && Command.Length != 0) {
                     switch (Command.ToLowerInvariant()) {
                             // options
                         case "options.blocklength":
                             {
                                 double length = 25.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out length)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Length is invalid in Options.BlockLength at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     length = 25.0;
                                 }
                                 Data.BlockInterval = length;
                             } break;
                         case "options.unitoflength":
                         case "options.unitofspeed":
                         case "options.objectvisibility":
                             break;
                         case "options.sectionbehavior":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 int a;
                                 if (!Interface.TryParseIntVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a != 0 & a != 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     ValueBasedSections = a == 1;
                                 }
                             } break;
                         case "options.cantbehavior":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 int a;
                                 if (!Interface.TryParseIntVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a != 0 & a != 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Data.SignedCant = a == 1;
                                 }
                             } break;
                         case "options.fogbehavior":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 int a;
                                 if (!Interface.TryParseIntVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a != 0 & a != 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Data.FogTransitionMode = a == 1;
                                 }
                             } break;
                             // route
                         case "route.comment":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 Game.RouteComment = Arguments[0];
                             } break;
                         case "route.image":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 string f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), Arguments[0]);
                                 if (!System.IO.File.Exists(f)) {
                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteImage = f;
                                 }
                             } break;
                         case "route.timetable":
                             if (!PreviewOnly) {
                                 if (Arguments.Length < 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "" + Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Timetable.DefaultTimetableDescription = Arguments[0];
                                 }
                             } break;
                         case "route.change":
                             if (!PreviewOnly) {
                                 int change = 0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out change)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     change = 0;
                                 } else if (change < -1 | change > 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Mode is expected to be -1, 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     change = 0;
                                 }
                                 Game.TrainStart = (Game.TrainStartMode)change;
                             } break;
                         case "route.gauge":
                         case "train.gauge":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInMillimeters is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInMillimeters is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteRailGauge = 0.001 * a;
                                 }
                             } break;
                         case "route.signal":
                             if (!PreviewOnly) {
                                 if (Arguments.Length < 1) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     double a;
                                     if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (CommandIndex1 < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "AspectIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (a < 0.0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Speed is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.SignalSpeeds.Length) {
                                                 int n = Data.SignalSpeeds.Length;
                                                 Array.Resize<double>(ref Data.SignalSpeeds, CommandIndex1 + 1);
                                                 for (int i = n; i < CommandIndex1; i++) {
                                                     Data.SignalSpeeds[i] = double.PositiveInfinity;
                                                 }
                                             }
                                             Data.SignalSpeeds[CommandIndex1] = a * Data.UnitOfSpeed;
                                         }
                                     }
                                 }
                             } break;
                         case "route.runinterval":
                         case "train.interval":
                             {
                                 if (!PreviewOnly) {
                                     double[] intervals = new double[Arguments.Length];
                                     for (int k = 0; k < Arguments.Length; k++) {
                                         if (!Interface.TryParseDoubleVb6(Arguments[k], out intervals[k])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Interval" + k.ToString(Culture) + " is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                     }
                                     Array.Sort<double>(intervals);
                                     Game.PrecedingTrainTimeDeltas = intervals;
                                 }
                             } break;
                         case "train.velocity":
                             {
                                 if (!PreviewOnly) {
                                     double limit = 0.0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out limit)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in Train.Velocity at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         limit = 0.0;
                                     }
                                     Game.PrecedingTrainSpeedLimit = limit <= 0.0 ? double.PositiveInfinity : Data.UnitOfSpeed * limit;
                                 }
                             } break;
                         case "route.accelerationduetogravity":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteAccelerationDueToGravity = a;
                                 }
                             } break;
                         case "route.elevation":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Height is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteInitialElevation = a;
                                 }
                             } break;
                         case "route.temperature":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInCelsius is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a <= -273.15) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInCelsius is expected to be greater than to -273.15 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteInitialAirTemperature = a + 273.15;
                                 }
                             } break;
                         case "route.pressure":
                             if (Arguments.Length < 1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 double a;
                                 if (!Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInKPa is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (a <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInKPa is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else {
                                     Game.RouteInitialAirPressure = 1000.0 * a;
                                 }
                             } break;
                         case "route.ambientlight":
                             {
                                 int r = 255, g = 255, b = 255;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out r)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (r < 0 | r > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     r = r < 0 ? 0 : 255;
                                 }
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out g)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (g < 0 | g > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     g = g < 0 ? 0 : 255;
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out b)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (b < 0 | b > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     b = b < 0 ? 0 : 255;
                                 }
                                 Renderer.OptionAmbientColor = new Color24((byte)r, (byte)g, (byte)b);
                             } break;
                         case "route.directionallight":
                             {
                                 int r = 255, g = 255, b = 255;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out r)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (r < 0 | r > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     r = r < 0 ? 0 : 255;
                                 }
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out g)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (g < 0 | g > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     g = g < 0 ? 0 : 255;
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out b)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 } else if (b < 0 | b > 255) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     b = b < 0 ? 0 : 255;
                                 }
                                 Renderer.OptionDiffuseColor = new Color24((byte)r, (byte)g, (byte)b);
                             }
                             break;
                         case "route.lightdirection":
                             {
                                 double theta = 60.0, phi = -26.565051177078;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out theta)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Theta is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 }
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out phi)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Phi is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                 }
                                 theta *= 0.0174532925199433;
                                 phi *= 0.0174532925199433;
                                 double dx = Math.Cos(theta) * Math.Sin(phi);
                                 double dy = -Math.Sin(theta);
                                 double dz = Math.Cos(theta) * Math.Cos(phi);
                                 Renderer.OptionLightPosition = new World.Vector3Df((float)-dx, (float)-dy, (float)-dz);
                             } break;
                             // train
                         case "train.folder":
                         case "train.file":
                             {
                                 if (PreviewOnly) {
                                     if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FolderName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Game.TrainName = Arguments[0];
                                         }
                                     }
                                 }
                             } break;
                         case "train.run":
                         case "train.rail":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailTypeIndex is out of range in "+Command+" at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         int val = 0;
                                         if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out val)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RunSoundIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             val = 0;
                                         }
                                         if (val < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RunSoundIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             val = 0;
                                         }
                                         if (CommandIndex1 >= Data.Structure.Run.Length) {
                                             Array.Resize<int>(ref Data.Structure.Run, CommandIndex1 + 1);
                                         }
                                         Data.Structure.Run[CommandIndex1] = val;
                                     }
                                 }
                             } break;
                         case "train.flange":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailTypeIndex is out of range in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         int val = 0;
                                         if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out val)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FlangeSoundIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             val = 0;
                                         }
                                         if (val < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FlangeSoundIndex expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             val = 0;
                                         }
                                         if (CommandIndex1 >= Data.Structure.Flange.Length) {
                                             Array.Resize<int>(ref Data.Structure.Flange, CommandIndex1 + 1);
                                         }
                                         Data.Structure.Flange[CommandIndex1] = val;
                                     }
                                 }
                             } break;
                         case "train.timetable.day":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "TimetableIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             while (CommandIndex1 >= Data.TimetableDaytime.Length) {
                                                 int n = Data.TimetableDaytime.Length;
                                                 Array.Resize<Textures.Texture>(ref Data.TimetableDaytime, n << 1);
                                                 for (int i = n; i < Data.TimetableDaytime.Length; i++) {
                                                     Data.TimetableDaytime[i] = null;
                                                 }
                                             }
                                             string f = OpenBveApi.Path.CombineFile(TrainPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             }
                                             if (System.IO.File.Exists(f)) {
                                                 Textures.RegisterTexture(f, out Data.TimetableDaytime[CommandIndex1]);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "train.timetable.night":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "TimetableIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             while (CommandIndex1 >= Data.TimetableNighttime.Length) {
                                                 int n = Data.TimetableNighttime.Length;
                                                 Array.Resize<Textures.Texture>(ref Data.TimetableNighttime, n << 1);
                                                 for (int i = n; i < Data.TimetableNighttime.Length; i++) {
                                                     Data.TimetableNighttime[i] = null;
                                                 }
                                             }
                                             string f = OpenBveApi.Path.CombineFile(TrainPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             }
                                             if (System.IO.File.Exists(f)) {
                                                 Textures.RegisterTexture(f, out Data.TimetableNighttime[CommandIndex1]);
                                             }
                                         }
                                     }
                                 }
                             } break;
                             // structure
                         case "structure.rail":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.Rail.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.Rail, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.Rail[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.beacon":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BeaconStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.Beacon.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.Beacon, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.Beacon[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.pole":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "AdditionalRailsCovered is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (CommandIndex2 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "PoleStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.Poles.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject[]>(ref Data.Structure.Poles, CommandIndex1 + 1);
                                             }
                                             if (Data.Structure.Poles[CommandIndex1] == null) {
                                                 Data.Structure.Poles[CommandIndex1] = new ObjectManager.UnifiedObject[CommandIndex2 + 1];
                                             } else if (CommandIndex2 >= Data.Structure.Poles[CommandIndex1].Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.Poles[CommandIndex1], CommandIndex2 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.Poles[CommandIndex1][CommandIndex2] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.ground":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GroundStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.Ground.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.Ground, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.Ground[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.walll":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.WallL.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.WallL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.WallL[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.wallr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.WallR.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.WallR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.WallR[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.dikel":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.DikeL.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.DikeL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.DikeL[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.diker":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.DikeR.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.DikeR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.DikeR[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.forml":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FormL.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.FormL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FormL[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.formr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FormR.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.FormR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FormR[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.formcl":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FormCL.Length) {
                                                 Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.FormCL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FormCL[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.formcr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FormCR.Length) {
                                                 Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.FormCR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FormCR[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.roofl":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 == 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex was omitted or is 0 in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 CommandIndex1 = 1;
                                             }
                                             if (CommandIndex1 < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (CommandIndex1 >= Data.Structure.RoofL.Length) {
                                                     Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.RoofL, CommandIndex1 + 1);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Structure.RoofL[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.roofr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 == 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex was omitted or is 0 in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 CommandIndex1 = 1;
                                             }
                                             if (CommandIndex1 < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (CommandIndex1 >= Data.Structure.RoofR.Length) {
                                                     Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.RoofR, CommandIndex1 + 1);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Structure.RoofR[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.roofcl":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 == 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex was omitted or is 0 in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 CommandIndex1 = 1;
                                             }
                                             if (CommandIndex1 < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (CommandIndex1 >= Data.Structure.RoofCL.Length) {
                                                     Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.RoofCL, CommandIndex1 + 1);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Structure.RoofCL[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.roofcr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 == 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex was omitted or is 0 in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 CommandIndex1 = 1;
                                             }
                                             if (CommandIndex1 < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is expected to be non-negativ in " + Command + " argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (CommandIndex1 >= Data.Structure.RoofCR.Length) {
                                                     Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.RoofCR, CommandIndex1 + 1);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Structure.RoofCR[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.crackl":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.CrackL.Length) {
                                                 Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.CrackL, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.CrackL[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.crackr":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.CrackR.Length) {
                                                 Array.Resize<ObjectManager.StaticObject>(ref Data.Structure.CrackR, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.CrackR[CommandIndex1] = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, true, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "structure.freeobj":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FreeObjStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Arguments.Length < 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Structure.FreeObj.Length) {
                                                 Array.Resize<ObjectManager.UnifiedObject>(ref Data.Structure.FreeObj, CommandIndex1 + 1);
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " could not be found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Data.Structure.FreeObj[CommandIndex1] = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                             }
                                         }
                                     }
                                 }
                             } break;
                             // signal
                         case "signal":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have between 1 and 2 arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (CommandIndex1 >= Data.SignalData.Length) {
                                             Array.Resize<SignalData>(ref Data.SignalData, CommandIndex1 + 1);
                                         }
                                         if (Arguments[0].EndsWith(".animated", StringComparison.OrdinalIgnoreCase)) {
                                             if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "AnimatedObjectFile contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (Arguments.Length > 1) {
                                                     Interface.AddMessage(Interface.MessageType.Warning, false, Command + " is expected to have exactly 1 argument when using animated objects at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 }
                                                 string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                                 if (!System.IO.File.Exists(f)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "SignalFileWithoutExtension " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     ObjectManager.UnifiedObject Object = ObjectManager.LoadObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                     if (Object is ObjectManager.AnimatedObjectCollection) {
                                                         AnimatedObjectSignalData Signal = new AnimatedObjectSignalData();
                                                         Signal.Objects = (ObjectManager.AnimatedObjectCollection)Object;
                                                         Data.SignalData[CommandIndex1] = Signal;
                                                     } else {
                                                         Interface.AddMessage(Interface.MessageType.Error, true, "GlowFileWithoutExtension " + f + " is not a valid animated object in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     }
                                                 }
                                             }
                                         } else {
                                             if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "SignalFileWithoutExtension contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 if (Arguments.Length > 2) {
                                                     Interface.AddMessage(Interface.MessageType.Warning, false, Command + " is expected to have between 1 and 2 arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 }
                                                 string f = System.IO.Path.Combine(ObjectPath, Arguments[0]);
                                                 Bve4SignalData Signal = new Bve4SignalData();
                                                 Signal.BaseObject = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                 Signal.GlowObject = null;
                                                 string Folder = System.IO.Path.GetDirectoryName(f);
                                                 if (!System.IO.Directory.Exists(Folder)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, true, "The folder " + Folder + " could not be found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Signal.SignalTextures = LoadAllTextures(f, false);
                                                     Signal.GlowTextures = new Textures.Texture[] { };
                                                     if (Arguments.Length >= 2 && Arguments[1].Length != 0) {
                                                         if (Interface.ContainsInvalidPathChars(Arguments[1])) {
                                                             Interface.AddMessage(Interface.MessageType.Error, false, "GlowFileWithoutExtension contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                         } else {
                                                             f = System.IO.Path.Combine(ObjectPath, Arguments[1]);
                                                             Signal.GlowObject = ObjectManager.LoadStaticObject(f, Encoding, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                                             if (Signal.GlowObject != null) {
                                                                 Signal.GlowTextures = LoadAllTextures(f, true);
                                                                 for (int p = 0; p < Signal.GlowObject.Mesh.Materials.Length; p++) {
                                                                     Signal.GlowObject.Mesh.Materials[p].BlendMode = World.MeshMaterialBlendMode.Additive;
                                                                     Signal.GlowObject.Mesh.Materials[p].GlowAttenuationData = World.GetGlowAttenuationData(200.0, World.GlowAttenuationMode.DivisionExponent4);
                                                                 }
                                                             }
                                                         }
                                                     }
                                                     Data.SignalData[CommandIndex1] = Signal;
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                             // texture
                         case "texture.background":
                         case "structure.back":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is expected to be non-negative at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (CommandIndex1 >= Data.Backgrounds.Length) {
                                                 int a = Data.Backgrounds.Length;
                                                 Array.Resize<World.Background>(ref Data.Backgrounds, CommandIndex1 + 1);
                                                 for (int k = a; k <= CommandIndex1; k++) {
                                                     Data.Backgrounds[k] = new World.Background(null, 6, false);
                                                 }
                                             }
                                             string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 Textures.RegisterTexture(f, out Data.Backgrounds[CommandIndex1].Texture);
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "texture.background.x":
                         case "structure.back.x":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is expected to be non-negative at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false,  Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (CommandIndex1 >= Data.Backgrounds.Length) {
                                             int a = Data.Backgrounds.Length;
                                             Array.Resize<World.Background>(ref Data.Backgrounds, CommandIndex1 + 1);
                                             for (int k = a; k <= CommandIndex1; k++) {
                                                 Data.Backgrounds[k] = new World.Background(null, 6, false);
                                             }
                                         }
                                         int x;
                                         if (!Interface.TryParseIntVb6(Arguments[0], out x)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (x == 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RepetitionCount is expected to be non-zero in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Data.Backgrounds[CommandIndex1].Repetition = x;
                                         }
                                     }
                                 }
                             } break;
                         case "texture.background.aspect":
                         case "structure.back.aspect":
                             {
                                 if (!PreviewOnly) {
                                     if (CommandIndex1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is expected to be non-negative at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false,  Command + " is expected to have one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (CommandIndex1 >= Data.Backgrounds.Length) {
                                             int a = Data.Backgrounds.Length;
                                             Array.Resize<World.Background>(ref Data.Backgrounds, CommandIndex1 + 1);
                                             for (int k = a; k <= CommandIndex1; k++) {
                                                 Data.Backgrounds[k] = new World.Background(null, 6, false);
                                             }
                                         }
                                         int aspect;
                                         if (!Interface.TryParseIntVb6(Arguments[0], out aspect)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (aspect != 0 & aspect != 1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Value is expected to be either 0 or 1 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Data.Backgrounds[CommandIndex1].KeepAspectRatio = aspect == 1;
                                         }
                                     }
                                 }
                             } break;
                             // cycle
                         case "cycle.ground":
                             if (!PreviewOnly) {
                                 if (CommandIndex1 >= Data.Structure.Cycle.Length) {
                                     Array.Resize<int[]>(ref Data.Structure.Cycle, CommandIndex1 + 1);
                                 }
                                 Data.Structure.Cycle[CommandIndex1] = new int[Arguments.Length];
                                 for (int k = 0; k < Arguments.Length; k++) {
                                     int ix = 0;
                                     if (Arguments[k].Length > 0 && !Interface.TryParseIntVb6(Arguments[k], out ix)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GroundStructureIndex" + (k + 1).ToString(Culture) + " is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         ix = 0;
                                     }
                                     if (ix < 0 | ix >= Data.Structure.Ground.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GroundStructureIndex" + (k + 1).ToString(Culture) + " is out of range in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         ix = 0;
                                     }
                                     Data.Structure.Cycle[CommandIndex1][k] = ix;
                                 }
                             } break;
                     }
                 }
             }
         }
     }
     // process track namespace
     for (int j = 0; j < Expressions.Length; j++) {
         Loading.RouteProgress = 0.3333 + (double)j * progressFactor;
         if ((j & 255) == 0) {
             System.Threading.Thread.Sleep(1);
             if (Loading.Cancel) return;
         }
         if (Expressions[j].Text.StartsWith("[") & Expressions[j].Text.EndsWith("]")) {
             Section = Expressions[j].Text.Substring(1, Expressions[j].Text.Length - 2).Trim();
             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
             int Equals = Expressions[j].Text.IndexOf('=');
             if (Equals >= 0) {
                 // handle RW cycle syntax
                 string t = Expressions[j].Text.Substring(0, Equals);
                 if (Section.ToLowerInvariant() == "cycle" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Ground(" + t + ")";
                     }
                 } else if (Section.ToLowerInvariant() == "signal" & SectionAlwaysPrefix) {
                     double b; if (Interface.TryParseDoubleVb6(t, out b)) {
                         t = ".Void(" + t + ")";
                     }
                 }
                 // convert RW style into CSV style
                 Expressions[j].Text = t + " " + Expressions[j].Text.Substring(Equals + 1);
             }
             // separate command and arguments
             string Command, ArgumentSequence;
             SeparateCommandsAndArguments(Expressions[j], out Command, out ArgumentSequence, Culture, Expressions[j].File, j, false);
             // process command
             double Number;
             bool NumberCheck = !IsRW || string.Compare(Section, "track", StringComparison.OrdinalIgnoreCase) == 0;
             if (NumberCheck && Interface.TryParseDouble(Command, UnitOfLength, out Number)) {
                 // track position
                 if (ArgumentSequence.Length != 0) {
                     Interface.AddMessage(Interface.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);
                 } else if (Number < 0.0) {
                     Interface.AddMessage(Interface.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 {
                     Data.TrackPosition = Number;
                     BlockIndex = (int)Math.Floor(Number / Data.BlockInterval + 0.001);
                     if (Data.FirstUsedBlock == -1) Data.FirstUsedBlock = BlockIndex;
                     CreateMissingBlocks(ref Data, ref BlocksUsed, BlockIndex, PreviewOnly);
                 }
             } else {
                 // split arguments
                 string[] Arguments;
                 {
                     int n = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             n++;
                         } else if (ArgumentSequence[k] == ';') {
                             n++;
                         }
                     }
                     Arguments = new string[n + 1];
                     int a = 0, h = 0;
                     for (int k = 0; k < ArgumentSequence.Length; k++) {
                         if (IsRW & ArgumentSequence[k] == ',') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         } else if (ArgumentSequence[k] == ';') {
                             Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim();
                             a = k + 1; h++;
                         }
                     }
                     if (ArgumentSequence.Length - a > 0) {
                         Arguments[h] = ArgumentSequence.Substring(a).Trim();
                         h++;
                     }
                     Array.Resize<string>(ref Arguments, h);
                 }
                 // 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();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.x" + Command.Substring(18, Command.Length - 20).TrimEnd();
                     } else if (Command.StartsWith("texture.background", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.aspect" + Command.Substring(18, Command.Length - 25).TrimEnd();
                     } else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".x", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.x" + Command.Substring(14, Command.Length - 16).TrimEnd();
                     } else if (Command.StartsWith("structure.back", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".aspect", StringComparison.OrdinalIgnoreCase)) {
                         Command = "texture.background.aspect" + Command.Substring(14, Command.Length - 21).TrimEnd();
                     } else if (Command.StartsWith("cycle", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".params", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 7).TrimEnd();
                     } else if (Command.StartsWith("signal", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".load", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 5).TrimEnd();
                     } else if (Command.StartsWith("train.run", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     } else if (Command.StartsWith("train.flange", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     } 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();
                     } 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();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".day", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.day" + Command.Substring(15, Command.Length - 19).Trim();
                     } else if (Command.StartsWith("train.timetable", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".night", StringComparison.OrdinalIgnoreCase)) {
                         Command = "train.timetable.night" + Command.Substring(15, Command.Length - 21).Trim();
                     } else if (Command.StartsWith("route.signal", StringComparison.OrdinalIgnoreCase) & Command.EndsWith(".set", StringComparison.OrdinalIgnoreCase)) {
                         Command = Command.Substring(0, Command.Length - 4).TrimEnd();
                     }
                 }
                 // handle indices
                 int CommandIndex1 = 0, CommandIndex2 = 0;
                 if (Command != null && Command.EndsWith(")")) {
                     for (int k = Command.Length - 2; k >= 0; k--) {
                         if (Command[k] == '(') {
                             string Indices = Command.Substring(k + 1, Command.Length - k - 2).TrimStart();
                             Command = Command.Substring(0, k).TrimEnd();
                             int h = Indices.IndexOf(";");
                             if (h >= 0) {
                                 string a = Indices.Substring(0, h).TrimEnd();
                                 string b = Indices.Substring(h + 1).TrimStart();
                                 if (a.Length > 0 && !Interface.TryParseIntVb6(a, out CommandIndex1)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid first index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 } else if (b.Length > 0 && !Interface.TryParseIntVb6(b, out CommandIndex2)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid second index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 }
                             } else {
                                 if (Indices.Length > 0 && !Interface.TryParseIntVb6(Indices, out CommandIndex1)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Invalid index appeared at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File + ".");
                                     Command = null; break;
                                 }
                             }
                             break;
                         }
                     }
                 }
                 // process command
                 if (Command != null && Command.Length != 0) {
                     switch (Command.ToLowerInvariant()) {
                             // non-track
                         case "options.blocklength":
                         case "options.unitoflength":
                         case "options.unitofspeed":
                         case "options.objectvisibility":
                         case "options.sectionbehavior":
                         case "options.fogbehavior":
                         case "options.cantbehavior":
                         case "route.comment":
                         case "route.image":
                         case "route.timetable":
                         case "route.change":
                         case "route.gauge":
                         case "train.gauge":
                         case "route.signal":
                         case "route.runinterval":
                         case "train.interval":
                         case "route.accelerationduetogravity":
                         case "route.elevation":
                         case "route.temperature":
                         case "route.pressure":
                         case "route.ambientlight":
                         case "route.directionallight":
                         case "route.lightdirection":
                         case "route.developerid":
                         case "train.folder":
                         case "train.file":
                         case "train.run":
                         case "train.rail":
                         case "train.flange":
                         case "train.timetable.day":
                         case "train.timetable.night":
                         case "train.velocity":
                         case "train.acceleration":
                         case "train.station":
                         case "structure.rail":
                         case "structure.beacon":
                         case "structure.pole":
                         case "structure.ground":
                         case "structure.walll":
                         case "structure.wallr":
                         case "structure.dikel":
                         case "structure.diker":
                         case "structure.forml":
                         case "structure.formr":
                         case "structure.formcl":
                         case "structure.formcr":
                         case "structure.roofl":
                         case "structure.roofr":
                         case "structure.roofcl":
                         case "structure.roofcr":
                         case "structure.crackl":
                         case "structure.crackr":
                         case "structure.freeobj":
                         case "signal":
                         case "texture.background":
                         case "structure.back":
                         case "structure.back.x":
                         case "structure.back.aspect":
                         case "texture.background.x":
                         case "texture.background.aspect":
                         case "cycle.ground":
                             break;
                             // track
                         case "track.railstart":
                         case "track.rail":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be positive in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (string.Compare(Command, "track.railstart", StringComparison.OrdinalIgnoreCase) == 0) {
                                             if (idx < Data.Blocks[BlockIndex].Rail.Length && Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is required to reference a non-existing rail in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                         }
                                         if (Data.Blocks[BlockIndex].Rail.Length <= idx) {
                                             Array.Resize<Rail>(ref Data.Blocks[BlockIndex].Rail, idx + 1);
                                         }
                                         if (Data.Blocks[BlockIndex].Rail[idx].RailStartRefreshed) {
                                             Data.Blocks[BlockIndex].Rail[idx].RailEnd = true;
                                         }
                                         {
                                             Data.Blocks[BlockIndex].Rail[idx].RailStart = true;
                                             Data.Blocks[BlockIndex].Rail[idx].RailStartRefreshed = true;
                                             if (Arguments.Length >= 2) {
                                                 if (Arguments[1].Length > 0) {
                                                     double x;
                                                     if (!Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out x)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                         x = 0.0;
                                                     }
                                                     Data.Blocks[BlockIndex].Rail[idx].RailStartX = x;
                                                 }
                                                 if (!Data.Blocks[BlockIndex].Rail[idx].RailEnd) {
                                                     Data.Blocks[BlockIndex].Rail[idx].RailEndX = Data.Blocks[BlockIndex].Rail[idx].RailStartX;
                                                 }
                                             }
                                             if (Arguments.Length >= 3) {
                                                 if (Arguments[2].Length > 0) {
                                                     double y;
                                                     if (!Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out y)) {
                                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                         y = 0.0;
                                                     }
                                                     Data.Blocks[BlockIndex].Rail[idx].RailStartY = y;
                                                 }
                                                 if (!Data.Blocks[BlockIndex].Rail[idx].RailEnd) {
                                                     Data.Blocks[BlockIndex].Rail[idx].RailEndY = Data.Blocks[BlockIndex].Rail[idx].RailStartY;
                                                 }
                                             }
                                             if (Data.Blocks[BlockIndex].RailType.Length <= idx) {
                                                 Array.Resize<int>(ref Data.Blocks[BlockIndex].RailType, idx + 1);
                                             }
                                             if (Arguments.Length >= 4 && Arguments[3].Length != 0) {
                                                 int sttype;
                                                 if (!Interface.TryParseIntVb6(Arguments[3], out sttype)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     sttype = 0;
                                                 }
                                                 if (sttype < 0) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else if (sttype >= Data.Structure.Rail.Length || Data.Structure.Rail[sttype] == null) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex references an object not loaded in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 } else {
                                                     Data.Blocks[BlockIndex].RailType[idx] = sttype;
                                                 }
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "track.railend":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0 || idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex references a non-existing rail in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Data.Blocks[BlockIndex].RailType.Length <= idx) {
                                             Array.Resize<Rail>(ref Data.Blocks[BlockIndex].Rail, idx + 1);
                                         }
                                         Data.Blocks[BlockIndex].Rail[idx].RailStart = false;
                                         Data.Blocks[BlockIndex].Rail[idx].RailStartRefreshed = false;
                                         Data.Blocks[BlockIndex].Rail[idx].RailEnd = true;
                                         if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                             double x;
                                             if (!Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out x)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 x = 0.0;
                                             }
                                             Data.Blocks[BlockIndex].Rail[idx].RailEndX = x;
                                         }
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0) {
                                             double y;
                                             if (!Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out y)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 y = 0.0;
                                             }
                                             Data.Blocks[BlockIndex].Rail[idx].RailEndY = y;
                                         }
                                     }
                                 }
                             } break;
                         case "track.railtype":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     int sttype = 0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         if (sttype < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex is expected to be non-negativ in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (sttype >= Data.Structure.Rail.Length || Data.Structure.Rail[sttype] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailStructureIndex references an object not loaded in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (Data.Blocks[BlockIndex].RailType.Length <= idx) {
                                                 Array.Resize<int>(ref Data.Blocks[BlockIndex].RailType, idx + 1);
                                             }
                                             Data.Blocks[BlockIndex].RailType[idx] = sttype;
                                         }
                                     }
                                 }
                             } break;
                         case "track.accuracy":
                             {
                                 double r = 2.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out r)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     r = 2.0;
                                 }
                                 if (r < 0.0) {
                                     r = 0.0;
                                 } else if (r > 4.0) {
                                     r = 4.0;
                                 }
                                 Data.Blocks[BlockIndex].Accuracy = r;
                             } break;
                         case "track.pitch":
                             {
                                 double p = 0.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out p)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ValueInPermille is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     p = 0.0;
                                 }
                                 Data.Blocks[BlockIndex].Pitch = 0.001 * p;
                             } break;
                         case "track.curve":
                             {
                                 double radius = 0.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out radius)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Radius is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     radius = 0.0;
                                 }
                                 double cant = 0.0;
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out cant)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "CantInMillimeters is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     cant = 0.0;
                                 } else {
                                     cant *= 0.001;
                                 }
                                 if (Data.SignedCant) {
                                     if (radius != 0.0) {
                                         cant *= (double)Math.Sign(radius);
                                     }
                                 } else {
                                     cant = Math.Abs(cant) * (double)Math.Sign(radius);
                                 }
                                 Data.Blocks[BlockIndex].CurrentTrackState.CurveRadius = radius;
                                 Data.Blocks[BlockIndex].CurrentTrackState.CurveCant = cant;
                                 Data.Blocks[BlockIndex].CurrentTrackState.CurveCantTangent = 0.0;
                             } break;
                         case "track.turn":
                             {
                                 double s = 0.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out s)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Ratio is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     s = 0.0;
                                 }
                                 Data.Blocks[BlockIndex].Turn = s;
                             } break;
                         case "track.adhesion":
                             {
                                 double a = 100.0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out a)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     a = 100.0;
                                 }
                                 if (a < 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Value is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     a = 100.0;
                                 }
                                 Data.Blocks[BlockIndex].AdhesionMultiplier = 0.01 * a;
                             } break;
                         case "track.brightness":
                             {
                                 if (!PreviewOnly) {
                                     float value = 255.0f;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseFloatVb6(Arguments[0], out value)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         value = 255.0f;
                                     }
                                     value /= 255.0f;
                                     if (value < 0.0f) value = 0.0f;
                                     if (value > 1.0f) value = 1.0f;
                                     int n = Data.Blocks[BlockIndex].Brightness.Length;
                                     Array.Resize<Brightness>(ref Data.Blocks[BlockIndex].Brightness, n + 1);
                                     Data.Blocks[BlockIndex].Brightness[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Brightness[n].Value = value;
                                 }
                             } break;
                         case "track.fog":
                             {
                                 if (!PreviewOnly) {
                                     double start = 0.0, end = 0.0;
                                     int r = 128, g = 128, b = 128;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out start)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "StartingDistance is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         start = 0.0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out end)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "EndingDistance is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         end = 0.0;
                                     }
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out r)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         r = 128;
                                     } else if (r < 0 | r > 255) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RedValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         r = r < 0 ? 0 : 255;
                                     }
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out g)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         g = 128;
                                     } else if (g < 0 | g > 255) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "GreenValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         g = g < 0 ? 0 : 255;
                                     }
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseIntVb6(Arguments[4], out b)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         b = 128;
                                     } else if (b < 0 | b > 255) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BlueValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         b = b < 0 ? 0 : 255;
                                     }
                                     if (start < end) {
                                         Data.Blocks[BlockIndex].Fog.Start = (float)start;
                                         Data.Blocks[BlockIndex].Fog.End = (float)end;
                                     } else {
                                         Data.Blocks[BlockIndex].Fog.Start = Game.NoFogStart;
                                         Data.Blocks[BlockIndex].Fog.End = Game.NoFogEnd;
                                     }
                                     Data.Blocks[BlockIndex].Fog.Color = new Color24((byte)r, (byte)g, (byte)b);
                                     Data.Blocks[BlockIndex].FogDefined = true;
                                 }
                             } break;
                         case "track.section":
                         case "track.sections":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length == 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "At least one argument is required in " + Command + "at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         int[] aspects = new int[Arguments.Length];
                                         for (int i = 0; i < Arguments.Length; i++) {
                                             if (!Interface.TryParseIntVb6(Arguments[i], out aspects[i])) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Aspect" + i.ToString(Culture) + " is invalid in " + Command + "at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 aspects[i] = -1;
                                             } else if (aspects[i] < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Aspect" + i.ToString(Culture) + " is expected to be non-negative in " + Command + "at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 aspects[i] = -1;
                                             }
                                         }
                                         bool valueBased = ValueBasedSections | string.Equals(Command, "Track.SectionS", StringComparison.OrdinalIgnoreCase);
                                         if (valueBased) {
                                             Array.Sort<int>(aspects);
                                         }
                                         int n = Data.Blocks[BlockIndex].Section.Length;
                                         Array.Resize<Section>(ref Data.Blocks[BlockIndex].Section, n + 1);
                                         Data.Blocks[BlockIndex].Section[n].TrackPosition = Data.TrackPosition;
                                         Data.Blocks[BlockIndex].Section[n].Aspects = aspects;
                                         Data.Blocks[BlockIndex].Section[n].Type = valueBased ? Game.SectionType.ValueBased : Game.SectionType.IndexBased;
                                         Data.Blocks[BlockIndex].Section[n].DepartureStationIndex = -1;
                                         if (CurrentStation >= 0 && Game.Stations[CurrentStation].ForceStopSignal) {
                                             if (CurrentStation >= 0 & CurrentStop >= 0 & !DepartureSignalUsed) {
                                                 Data.Blocks[BlockIndex].Section[n].DepartureStationIndex = CurrentStation;
                                                 DepartureSignalUsed = true;
                                             }
                                         }
                                         CurrentSection++;
                                     }
                                 }
                             } break;
                         case "track.sigf":
                             {
                                 if (!PreviewOnly) {
                                     int objidx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out objidx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "SignalIndex is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         objidx = 0;
                                     }
                                     if (objidx >= 0 & objidx < Data.SignalData.Length && Data.SignalData[objidx] != null) {
                                         int section = 0;
                                         if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out section)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Section is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             section = 0;
                                         }
                                         double x = 0.0, y = 0.0;
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out x)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             x = 0.0;
                                         }
                                         if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out y)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             y = 0.0;
                                         }
                                         double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                         if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out yaw)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             yaw = 0.0;
                                         }
                                         if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out pitch)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             pitch = 0.0;
                                         }
                                         if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out roll)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             roll = 0.0;
                                         }
                                         int n = Data.Blocks[BlockIndex].Signal.Length;
                                         Array.Resize<Signal>(ref Data.Blocks[BlockIndex].Signal, n + 1);
                                         Data.Blocks[BlockIndex].Signal[n].TrackPosition = Data.TrackPosition;
                                         Data.Blocks[BlockIndex].Signal[n].Section = CurrentSection + section;
                                         Data.Blocks[BlockIndex].Signal[n].SignalCompatibilityObjectIndex = -1;
                                         Data.Blocks[BlockIndex].Signal[n].SignalObjectIndex = objidx;
                                         Data.Blocks[BlockIndex].Signal[n].X = x;
                                         Data.Blocks[BlockIndex].Signal[n].Y = y < 0.0 ? 4.8 : y;
                                         Data.Blocks[BlockIndex].Signal[n].Yaw = 0.0174532925199433 * yaw;
                                         Data.Blocks[BlockIndex].Signal[n].Pitch = 0.0174532925199433 * pitch;
                                         Data.Blocks[BlockIndex].Signal[n].Roll = 0.0174532925199433 * roll;
                                         Data.Blocks[BlockIndex].Signal[n].ShowObject = true;
                                         Data.Blocks[BlockIndex].Signal[n].ShowPost = y < 0.0;
                                         Data.Blocks[BlockIndex].Signal[n].GameSignalIndex = -1;
                                     } else {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "SignalIndex references a signal object not loaded in Track.SigF at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     }
                                 }
                             } break;
                         case "track.signal":
                         case "track.sig":
                             {
                                 if (!PreviewOnly) {
                                     int num = -2;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out num)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Aspects is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         num = -2;
                                     }
                                     if (num != -2 & num != 2 & num != 3 & num != -4 & num != 4 & num != -5 & num != 5 & num != 6) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Aspects has an unsupported value in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         num = num == -3 | num == -6 ? -num : -4;
                                     }
                                     double x = 0.0, y = 0.0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out x)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         x = 0.0;
                                     }
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out y)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         y = 0.0;
                                     }
                                     double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out yaw)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         yaw = 0.0;
                                     }
                                     if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out pitch)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         pitch = 0.0;
                                     }
                                     if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out roll)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         roll = 0.0;
                                     }
                                     int[] aspects; int comp;
                                     switch (num) {
                                             case 2: aspects = new int[] { 0, 2 }; comp = 0; break;
                                             case -2: aspects = new int[] { 0, 4 }; comp = 1; break;
                                             case 3: aspects = new int[] { 0, 2, 4 }; comp = 2; break;
                                             case 4: aspects = new int[] { 0, 1, 2, 4 }; comp = 3; break;
                                             case -4: aspects = new int[] { 0, 2, 3, 4 }; comp = 4; break;
                                             case 5: aspects = new int[] { 0, 1, 2, 3, 4 }; comp = 5; break;
                                             case -5: aspects = new int[] { 0, 2, 3, 4, 5 }; comp = 6; break;
                                             case 6: aspects = new int[] { 0, 1, 2, 3, 4, 5 }; comp = 7; break;
                                             default: aspects = new int[] { 0, 2 }; comp = 0; break;
                                     }
                                     int n = Data.Blocks[BlockIndex].Section.Length;
                                     Array.Resize<Section>(ref Data.Blocks[BlockIndex].Section, n + 1);
                                     Data.Blocks[BlockIndex].Section[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Section[n].Aspects = aspects;
                                     Data.Blocks[BlockIndex].Section[n].DepartureStationIndex = -1;
                                     Data.Blocks[BlockIndex].Section[n].Invisible = x == 0.0;
                                     Data.Blocks[BlockIndex].Section[n].Type = Game.SectionType.ValueBased;
                                     if (CurrentStation >= 0 && Game.Stations[CurrentStation].ForceStopSignal) {
                                         if (CurrentStation >= 0 & CurrentStop >= 0 & !DepartureSignalUsed) {
                                             Data.Blocks[BlockIndex].Section[n].DepartureStationIndex = CurrentStation;
                                             DepartureSignalUsed = true;
                                         }
                                     }
                                     CurrentSection++;
                                     n = Data.Blocks[BlockIndex].Signal.Length;
                                     Array.Resize<Signal>(ref Data.Blocks[BlockIndex].Signal, n + 1);
                                     Data.Blocks[BlockIndex].Signal[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Signal[n].Section = CurrentSection;
                                     Data.Blocks[BlockIndex].Signal[n].SignalCompatibilityObjectIndex = comp;
                                     Data.Blocks[BlockIndex].Signal[n].SignalObjectIndex = -1;
                                     Data.Blocks[BlockIndex].Signal[n].X = x;
                                     Data.Blocks[BlockIndex].Signal[n].Y = y < 0.0 ? 4.8 : y;
                                     Data.Blocks[BlockIndex].Signal[n].Yaw = 0.0174532925199433 * yaw;
                                     Data.Blocks[BlockIndex].Signal[n].Pitch = 0.0174532925199433 * pitch;
                                     Data.Blocks[BlockIndex].Signal[n].Roll = 0.0174532925199433 * roll;
                                     Data.Blocks[BlockIndex].Signal[n].ShowObject = x != 0.0;
                                     Data.Blocks[BlockIndex].Signal[n].ShowPost = x != 0.0 & y < 0.0;
                                     Data.Blocks[BlockIndex].Signal[n].GameSignalIndex = -1;
                                 }
                             } break;
                         case "track.relay":
                             {
                                 if (!PreviewOnly) {
                                     double x = 0.0, y = 0.0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out x)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         x = 0.0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out y)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         y = 0.0;
                                     }
                                     double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], out yaw)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         yaw = 0.0;
                                     }
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], out pitch)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         pitch = 0.0;
                                     }
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out roll)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in Track.Relay at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         roll = 0.0;
                                     }
                                     int n = Data.Blocks[BlockIndex].Signal.Length;
                                     Array.Resize<Signal>(ref Data.Blocks[BlockIndex].Signal, n + 1);
                                     Data.Blocks[BlockIndex].Signal[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Signal[n].Section = CurrentSection + 1;
                                     Data.Blocks[BlockIndex].Signal[n].SignalCompatibilityObjectIndex = 8;
                                     Data.Blocks[BlockIndex].Signal[n].SignalObjectIndex = -1;
                                     Data.Blocks[BlockIndex].Signal[n].X = x;
                                     Data.Blocks[BlockIndex].Signal[n].Y = y < 0.0 ? 4.8 : y;
                                     Data.Blocks[BlockIndex].Signal[n].Yaw = yaw * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Signal[n].Pitch = pitch * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Signal[n].Roll = roll * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Signal[n].ShowObject = x != 0.0;
                                     Data.Blocks[BlockIndex].Signal[n].ShowPost = x != 0.0 & y < 0.0;
                                 }
                             } break;
                         case "track.beacon":
                             {
                                 if (!PreviewOnly) {
                                     int type = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out type)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Type is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         type = 0;
                                     }
                                     if (type < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Type is expected to be non-positive in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         int structure = 0, section = 0, optional = 0;
                                         if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out structure)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BeaconStructureIndex is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             structure = 0;
                                         }
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out section)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Section is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             section = 0;
                                         }
                                         if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out optional)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Data is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             optional = 0;
                                         }
                                         if (structure < -1) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BeaconStructureIndex is expected to be non-negative or -1 in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             structure = -1;
                                         } else if (structure >= 0 && (structure >= Data.Structure.Beacon.Length || Data.Structure.Beacon[structure] == null)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "BeaconStructureIndex references an object not loaded in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             structure = -1;
                                         }
                                         if (section == -1) {
                                             //section = (int)TrackManager.TransponderSpecialSection.NextRedSection;
                                         } else if (section < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Section is expected to be non-negative or -1 in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             section = CurrentSection + 1;
                                         } else {
                                             section += CurrentSection;
                                         }
                                         double x = 0.0, y = 0.0;
                                         double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                         if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], UnitOfLength, out x)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             x = 0.0;
                                         }
                                         if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], UnitOfLength, out y)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             y = 0.0;
                                         }
                                         if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out yaw)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             yaw = 0.0;
                                         }
                                         if (Arguments.Length >= 8 && Arguments[7].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[7], out pitch)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             pitch = 0.0;
                                         }
                                         if (Arguments.Length >= 9 && Arguments[8].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[8], out roll)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in Track.Beacon at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             roll = 0.0;
                                         }
                                         int n = Data.Blocks[BlockIndex].Transponder.Length;
                                         Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                         Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                         Data.Blocks[BlockIndex].Transponder[n].Type = type;
                                         Data.Blocks[BlockIndex].Transponder[n].Data = optional;
                                         Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = structure;
                                         Data.Blocks[BlockIndex].Transponder[n].Section = section;
                                         Data.Blocks[BlockIndex].Transponder[n].ShowDefaultObject = false;
                                         Data.Blocks[BlockIndex].Transponder[n].X = x;
                                         Data.Blocks[BlockIndex].Transponder[n].Y = y;
                                         Data.Blocks[BlockIndex].Transponder[n].Yaw = yaw * 0.0174532925199433;
                                         Data.Blocks[BlockIndex].Transponder[n].Pitch = pitch * 0.0174532925199433;
                                         Data.Blocks[BlockIndex].Transponder[n].Roll = roll * 0.0174532925199433;
                                     }
                                 }
                             } break;
                         case "track.transponder":
                         case "track.tr":
                             {
                                 if (!PreviewOnly) {
                                     int type = 0, oversig = 0, work = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out type)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Type is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         type = 0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out oversig)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Signals is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         oversig = 0;
                                     }
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out work)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "SwitchSystems is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         work = 0;
                                     }
                                     if (oversig < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Signals is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         oversig = 0;
                                     }
                                     double x = 0.0, y = 0.0;
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out x)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         x = 0.0;
                                     }
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], UnitOfLength, out y)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         y = 0.0;
                                     }
                                     double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                     if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out yaw)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         yaw = 0.0;
                                     }
                                     if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out pitch)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         pitch = 0.0;
                                     }
                                     if (Arguments.Length >= 8 && Arguments[7].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[7], out roll)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         roll = 0.0;
                                     }
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Transponder[n].Type = type;
                                     Data.Blocks[BlockIndex].Transponder[n].Data = work;
                                     Data.Blocks[BlockIndex].Transponder[n].ShowDefaultObject = true;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].X = x;
                                     Data.Blocks[BlockIndex].Transponder[n].Y = y;
                                     Data.Blocks[BlockIndex].Transponder[n].Yaw = yaw * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Transponder[n].Pitch = pitch * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Transponder[n].Roll = roll * 0.0174532925199433;
                                     Data.Blocks[BlockIndex].Transponder[n].Section = CurrentSection + oversig + 1;
                                 }
                             } break;
                         case "track.atssn":
                             {
                                 if (!PreviewOnly) {
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Transponder[n].Type = 0;
                                     Data.Blocks[BlockIndex].Transponder[n].Data = 0;
                                     Data.Blocks[BlockIndex].Transponder[n].ShowDefaultObject = true;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].Section = CurrentSection + 1;
                                 }
                             } break;
                         case "track.atsp":
                             {
                                 if (!PreviewOnly) {
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Transponder[n].Type = 3;
                                     Data.Blocks[BlockIndex].Transponder[n].Data = 0;
                                     Data.Blocks[BlockIndex].Transponder[n].ShowDefaultObject = true;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].Section = CurrentSection + 1;
                                 }
                             } break;
                         case "track.pattern":
                             {
                                 if (!PreviewOnly) {
                                     int type = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out type)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Type is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         type = 0;
                                     }
                                     double speed = 0.0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out speed)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         speed = 0.0;
                                     }
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     if (type == 0) {
                                         Data.Blocks[BlockIndex].Transponder[n].Type = TrackManager.SpecialTransponderTypes.InternalAtsPTemporarySpeedLimit;
                                         Data.Blocks[BlockIndex].Transponder[n].Data = speed == 0.0 ? int.MaxValue : (int)Math.Round(speed * Data.UnitOfSpeed * 3.6);
                                     } else {
                                         Data.Blocks[BlockIndex].Transponder[n].Type = TrackManager.SpecialTransponderTypes.AtsPPermanentSpeedLimit;
                                         Data.Blocks[BlockIndex].Transponder[n].Data = speed == 0.0 ? int.MaxValue : (int)Math.Round(speed * Data.UnitOfSpeed * 3.6);
                                     }
                                     Data.Blocks[BlockIndex].Transponder[n].Section = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                 }
                             } break;
                         case "track.plimit":
                             {
                                 if (!PreviewOnly) {
                                     double speed = 0.0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out speed)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         speed = 0.0;
                                     }
                                     int n = Data.Blocks[BlockIndex].Transponder.Length;
                                     Array.Resize<Transponder>(ref Data.Blocks[BlockIndex].Transponder, n + 1);
                                     Data.Blocks[BlockIndex].Transponder[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].Transponder[n].Type = TrackManager.SpecialTransponderTypes.AtsPPermanentSpeedLimit;
                                     Data.Blocks[BlockIndex].Transponder[n].Data = speed == 0.0 ? int.MaxValue : (int)Math.Round(speed * Data.UnitOfSpeed * 3.6);
                                     Data.Blocks[BlockIndex].Transponder[n].Section = -1;
                                     Data.Blocks[BlockIndex].Transponder[n].BeaconStructureIndex = -1;
                                 }
                             } break;
                         case "track.limit":
                             {
                                 double limit = 0.0;
                                 int direction = 0, cource = 0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], out limit)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in Track.Limit at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     limit = 0.0;
                                 }
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out direction)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Direction is invalid in Track.Limit at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     direction = 0;
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out cource)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Cource is invalid in Track.Limit at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     cource = 0;
                                 }
                                 int n = Data.Blocks[BlockIndex].Limit.Length;
                                 Array.Resize<Limit>(ref Data.Blocks[BlockIndex].Limit, n + 1);
                                 Data.Blocks[BlockIndex].Limit[n].TrackPosition = Data.TrackPosition;
                                 Data.Blocks[BlockIndex].Limit[n].Speed = limit <= 0.0 ? double.PositiveInfinity : Data.UnitOfSpeed * limit;
                                 Data.Blocks[BlockIndex].Limit[n].Direction = direction;
                                 Data.Blocks[BlockIndex].Limit[n].Cource = cource;
                             } break;
                         case "track.stop":
                             if (CurrentStation == -1) {
                                 Interface.AddMessage(Interface.MessageType.Error, false, "A stop without a station is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                             } else {
                                 int dir = 0;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out dir)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Direction is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     dir = 0;
                                 }
                                 double backw = 5.0, forw = 5.0;
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out backw)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BackwardTolerance is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     backw = 5.0;
                                 } else if (backw <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "BackwardTolerance is expected to be positive in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     backw = 5.0;
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out forw)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ForwardTolerance is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     forw = 5.0;
                                 } else if (forw <= 0.0) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ForwardTolerance is expected to be positive in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     forw = 5.0;
                                 }
                                 int cars = 0;
                                 if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out cars)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "Cars is invalid in Track.Stop at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     cars = 0;
                                 }
                                 int n = Data.Blocks[BlockIndex].Stop.Length;
                                 Array.Resize<Stop>(ref Data.Blocks[BlockIndex].Stop, n + 1);
                                 Data.Blocks[BlockIndex].Stop[n].TrackPosition = Data.TrackPosition;
                                 Data.Blocks[BlockIndex].Stop[n].Station = CurrentStation;
                                 Data.Blocks[BlockIndex].Stop[n].Direction = dir;
                                 Data.Blocks[BlockIndex].Stop[n].ForwardTolerance = forw;
                                 Data.Blocks[BlockIndex].Stop[n].BackwardTolerance = backw;
                                 Data.Blocks[BlockIndex].Stop[n].Cars = cars;
                                 CurrentStop = cars;
                             } break;
                         case "track.sta":
                             {
                                 CurrentStation++;
                                 Array.Resize<Game.Station>(ref Game.Stations, CurrentStation + 1);
                                 Game.Stations[CurrentStation].Name = string.Empty;
                                 Game.Stations[CurrentStation].StopMode = Game.StationStopMode.AllStop;
                                 Game.Stations[CurrentStation].StationType = Game.StationType.Normal;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0) {
                                     Game.Stations[CurrentStation].Name = Arguments[0];
                                 }
                                 double arr = -1.0, dep = -1.0;
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                     if (string.Equals(Arguments[1], "P", StringComparison.OrdinalIgnoreCase) | string.Equals(Arguments[1], "L", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.AllPass;
                                     } else if (string.Equals(Arguments[1], "B", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerPass;
                                     } else if (Arguments[1].StartsWith("B:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerPass;
                                         if (!Interface.TryParseTime(Arguments[1].Substring(2).TrimStart(), out arr)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             arr = -1.0;
                                         }
                                     } else if (string.Equals(Arguments[1], "S", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerStop;
                                     } else if (Arguments[1].StartsWith("S:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerStop;
                                         if (!Interface.TryParseTime(Arguments[1].Substring(2).TrimStart(), out arr)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             arr = -1.0;
                                         }
                                     } else if (!Interface.TryParseTime(Arguments[1], out arr)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         arr = -1.0;
                                     }
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0) {
                                     if (string.Equals(Arguments[2], "T", StringComparison.OrdinalIgnoreCase) | string.Equals(Arguments[2], "=", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.Terminal;
                                     } else if (Arguments[2].StartsWith("T:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.Terminal;
                                         if (!Interface.TryParseTime(Arguments[2].Substring(2).TrimStart(), out dep)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             dep = -1.0;
                                         }
                                     } else if (string.Equals(Arguments[2], "C", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.ChangeEnds;
                                     } else if (Arguments[2].StartsWith("C:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.ChangeEnds;
                                         if (!Interface.TryParseTime(Arguments[2].Substring(2).TrimStart(), out dep)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             dep = -1.0;
                                         }
                                     } else if (!Interface.TryParseTime(Arguments[2], out dep)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         dep = -1.0;
                                     }
                                 }
                                 int passalarm = 0;
                                 if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out passalarm)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "PassAlarm is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     passalarm = 0;
                                 }
                                 int door = 0;
                                 bool doorboth = false;
                                 if (Arguments.Length >= 5 && Arguments[4].Length != 0) {
                                     switch (Arguments[4].ToUpperInvariant()) {
                                         case "L":
                                             door = -1;
                                             break;
                                         case "R":
                                             door = 1;
                                             break;
                                         case "N":
                                             door = 0;
                                             break;
                                         case "B":
                                             doorboth = true;
                                             break;
                                         default:
                                             if (!Interface.TryParseIntVb6(Arguments[4], out door)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Doors is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 door = 0;
                                             }
                                             break;
                                     }
                                 }
                                 int stop = 0;
                                 if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseIntVb6(Arguments[5], out stop)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ForcedRedSignal is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     stop = 0;
                                 }
                                 int device = 0;
                                 if (Arguments.Length >= 7 && Arguments[6].Length > 0) {
                                     if (string.Compare(Arguments[6], "ats", StringComparison.OrdinalIgnoreCase) == 0) {
                                         device = 0;
                                     } else if (string.Compare(Arguments[6], "atc", StringComparison.OrdinalIgnoreCase) == 0) {
                                         device = 1;
                                     } else if (!Interface.TryParseIntVb6(Arguments[6], out device)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "System is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         device = 0;
                                     }
                                     if (device != 0 & device != 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "System is not supported in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         device = 0;
                                     }
                                 }
                                 Sounds.SoundBuffer arrsnd = null;
                                 Sounds.SoundBuffer depsnd = null;
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 8 && Arguments[7].Length > 0) {
                                         if (Interface.ContainsInvalidPathChars(Arguments[7])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalSound contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[7]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "ArrivalSound " + f + " not found in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 const double radius = 30.0;
                                                 arrsnd = Sounds.RegisterBuffer(f, radius);
                                             }
                                         }
                                     }
                                 }
                                 double halt = 15.0;
                                 if (Arguments.Length >= 9 && Arguments[8].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[8], out halt)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "StopDuration is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     halt = 15.0;
                                 } else if (halt < 5.0) {
                                     halt = 5.0;
                                 }
                                 double jam = 100.0;
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 10 && Arguments[9].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[9], out jam)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "PassengerRatio is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         jam = 100.0;
                                     } else if (jam < 0.0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "PassengerRatio is expected to be non-negative in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         jam = 100.0;
                                     }
                                 }
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 11 && Arguments[10].Length > 0) {
                                         if (Interface.ContainsInvalidPathChars(Arguments[10])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureSound contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[10]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "DepartureSound " + f + " not found in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 const double radius = 30.0;
                                                 depsnd = Sounds.RegisterBuffer(f, radius);
                                             }
                                         }
                                     }
                                 }
                                 int ttidx = -1;
                                 Textures.Texture tdt = null, tnt = null;
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 12 && Arguments[11].Length > 0) {
                                         if (!Interface.TryParseIntVb6(Arguments[11], out ttidx)) {
                                             ttidx = -1;
                                         } else {
                                             if (ttidx < 0) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "TimetableIndex is expected to be non-negative in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 ttidx = -1;
                                             } else if (ttidx >= Data.TimetableDaytime.Length & ttidx >= Data.TimetableNighttime.Length) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "TimetableIndex references textures not loaded in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 ttidx = -1;
                                             }
                                             tdt = ttidx >= 0 & ttidx < Data.TimetableDaytime.Length ? Data.TimetableDaytime[ttidx] : null;
                                             tnt = ttidx >= 0 & ttidx < Data.TimetableNighttime.Length ? Data.TimetableNighttime[ttidx] : null;
                                             ttidx = 0;
                                         }
                                     } else {
                                         ttidx = -1;
                                     }
                                     if (ttidx == -1) {
                                         if (CurrentStation > 0) {
                                             tdt = Game.Stations[CurrentStation - 1].TimetableDaytimeTexture;
                                             tnt = Game.Stations[CurrentStation - 1].TimetableNighttimeTexture;
                                         } else if (Data.TimetableDaytime.Length > 0 & Data.TimetableNighttime.Length > 0) {
                                             tdt = Data.TimetableDaytime[0];
                                             tnt = Data.TimetableNighttime[0];
                                         } else {
                                             tdt = null;
                                             tnt = null;
                                         }
                                     }
                                 }
                                 if (Game.Stations[CurrentStation].Name.Length == 0 & (Game.Stations[CurrentStation].StopMode == Game.StationStopMode.PlayerStop | Game.Stations[CurrentStation].StopMode == Game.StationStopMode.AllStop)) {
                                     Game.Stations[CurrentStation].Name = "Station " + (CurrentStation + 1).ToString(Culture) + ")";
                                 }
                                 Game.Stations[CurrentStation].ArrivalTime = arr;
                                 Game.Stations[CurrentStation].ArrivalSoundBuffer = arrsnd;
                                 Game.Stations[CurrentStation].DepartureTime = dep;
                                 Game.Stations[CurrentStation].DepartureSoundBuffer = depsnd;
                                 Game.Stations[CurrentStation].StopTime = halt;
                                 Game.Stations[CurrentStation].ForceStopSignal = stop == 1;
                                 Game.Stations[CurrentStation].OpenLeftDoors = door < 0.0 | doorboth;
                                 Game.Stations[CurrentStation].OpenRightDoors = door > 0.0 | doorboth;
                                 Game.Stations[CurrentStation].SafetySystem = device == 1 ? Game.SafetySystem.Atc : Game.SafetySystem.Ats;
                                 Game.Stations[CurrentStation].Stops = new Game.StationStop[] { };
                                 Game.Stations[CurrentStation].PassengerRatio = 0.01 * jam;
                                 Game.Stations[CurrentStation].TimetableDaytimeTexture = tdt;
                                 Game.Stations[CurrentStation].TimetableNighttimeTexture = tnt;
                                 Game.Stations[CurrentStation].DefaultTrackPosition = Data.TrackPosition;
                                 Data.Blocks[BlockIndex].Station = CurrentStation;
                                 Data.Blocks[BlockIndex].StationPassAlarm = passalarm == 1;
                                 CurrentStop = -1;
                                 DepartureSignalUsed = false;
                             } break;
                         case "track.station":
                             {
                                 CurrentStation++;
                                 Array.Resize<Game.Station>(ref Game.Stations, CurrentStation + 1);
                                 Game.Stations[CurrentStation].Name = string.Empty;
                                 Game.Stations[CurrentStation].StopMode = Game.StationStopMode.AllStop;
                                 Game.Stations[CurrentStation].StationType = Game.StationType.Normal;
                                 if (Arguments.Length >= 1 && Arguments[0].Length > 0) {
                                     Game.Stations[CurrentStation].Name = Arguments[0];
                                 }
                                 double arr = -1.0, dep = -1.0;
                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                     if (string.Equals(Arguments[1], "P", StringComparison.OrdinalIgnoreCase) | string.Equals(Arguments[1], "L", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.AllPass;
                                     } else if (string.Equals(Arguments[1], "B", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerPass;
                                     } else if (Arguments[1].StartsWith("B:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerPass;
                                         if (!Interface.TryParseTime(Arguments[1].Substring(2).TrimStart(), out arr)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             arr = -1.0;
                                         }
                                     } else if (string.Equals(Arguments[1], "S", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerStop;
                                     } else if (Arguments[1].StartsWith("S:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StopMode = Game.StationStopMode.PlayerStop;
                                         if (!Interface.TryParseTime(Arguments[1].Substring(2).TrimStart(), out arr)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             arr = -1.0;
                                         }
                                     } else if (!Interface.TryParseTime(Arguments[1], out arr)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "ArrivalTime is invalid in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         arr = -1.0;
                                     }
                                 }
                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0) {
                                     if (string.Equals(Arguments[2], "T", StringComparison.OrdinalIgnoreCase) | string.Equals(Arguments[2], "=", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.Terminal;
                                     } else if (Arguments[2].StartsWith("T:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.Terminal;
                                         if (!Interface.TryParseTime(Arguments[2].Substring(2).TrimStart(), out dep)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             dep = -1.0;
                                         }
                                     } else if (string.Equals(Arguments[2], "C", StringComparison.OrdinalIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.ChangeEnds;
                                     } else if (Arguments[2].StartsWith("C:", StringComparison.InvariantCultureIgnoreCase)) {
                                         Game.Stations[CurrentStation].StationType = Game.StationType.ChangeEnds;
                                         if (!Interface.TryParseTime(Arguments[2].Substring(2).TrimStart(), out dep)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Sta at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             dep = -1.0;
                                         }
                                     } else if (!Interface.TryParseTime(Arguments[2], out dep)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DepartureTime is invalid in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         dep = -1.0;
                                     }
                                 }
                                 int stop = 0;
                                 if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out stop)) {
                                     Interface.AddMessage(Interface.MessageType.Error, false, "ForcedRedSignal is invalid in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     stop = 0;
                                 }
                                 int device = 0;
                                 if (Arguments.Length >= 5 && Arguments[4].Length > 0) {
                                     if (string.Compare(Arguments[4], "ats", StringComparison.OrdinalIgnoreCase) == 0) {
                                         device = 0;
                                     } else if (string.Compare(Arguments[4], "atc", StringComparison.OrdinalIgnoreCase) == 0) {
                                         device = 1;
                                     } else if (!Interface.TryParseIntVb6(Arguments[4], out device)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "System is invalid in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         device = 0;
                                     } else if (device != 0 & device != 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "System is not supported in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         device = 0;
                                     }
                                 }
                                 Sounds.SoundBuffer depsnd = null;
                                 if (!PreviewOnly) {
                                     if (Arguments.Length >= 6 && Arguments[5].Length != 0) {
                                         if (Interface.ContainsInvalidPathChars(Arguments[5])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "DepartureSound contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[5]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "DepartureSound " + f + " not found in Track.Station at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 const double radius = 30.0;
                                                 depsnd = Sounds.RegisterBuffer(f, radius);
                                             }
                                         }
                                     }
                                 }
                                 if (Game.Stations[CurrentStation].Name.Length == 0 & (Game.Stations[CurrentStation].StopMode == Game.StationStopMode.PlayerStop | Game.Stations[CurrentStation].StopMode == Game.StationStopMode.AllStop)) {
                                     Game.Stations[CurrentStation].Name = "Station " + (CurrentStation + 1).ToString(Culture) + ")";
                                 }
                                 Game.Stations[CurrentStation].ArrivalTime = arr;
                                 Game.Stations[CurrentStation].ArrivalSoundBuffer = null;
                                 Game.Stations[CurrentStation].DepartureTime = dep;
                                 Game.Stations[CurrentStation].DepartureSoundBuffer = depsnd;
                                 Game.Stations[CurrentStation].StopTime = 15.0;
                                 Game.Stations[CurrentStation].ForceStopSignal = stop == 1;
                                 Game.Stations[CurrentStation].OpenLeftDoors = true;
                                 Game.Stations[CurrentStation].OpenRightDoors = true;
                                 Game.Stations[CurrentStation].SafetySystem = device == 1 ? Game.SafetySystem.Atc : Game.SafetySystem.Ats;
                                 Game.Stations[CurrentStation].Stops = new Game.StationStop[] { };
                                 Game.Stations[CurrentStation].PassengerRatio = 1.0;
                                 Game.Stations[CurrentStation].TimetableDaytimeTexture = null;
                                 Game.Stations[CurrentStation].TimetableNighttimeTexture = null;
                                 Game.Stations[CurrentStation].DefaultTrackPosition = Data.TrackPosition;
                                 Data.Blocks[BlockIndex].Station = CurrentStation;
                                 Data.Blocks[BlockIndex].StationPassAlarm = false;
                                 CurrentStop = -1;
                                 DepartureSignalUsed = false;
                             } break;
                         case "track.buffer":
                             {
                                 if (!PreviewOnly) {
                                     int n = Game.BufferTrackPositions.Length;
                                     Array.Resize<double>(ref Game.BufferTrackPositions, n + 1);
                                     Game.BufferTrackPositions[n] = Data.TrackPosition;
                                 }
                             } break;
                         case "track.form":
                             {
                                 if (!PreviewOnly) {
                                     int idx1 = 0, idx2 = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx1)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is invalid in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx1 = 0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                         if (string.Compare(Arguments[1], "L", StringComparison.OrdinalIgnoreCase) == 0) {
                                             idx2 = Form.SecondaryRailL;
                                         } else if (string.Compare(Arguments[1], "R", StringComparison.OrdinalIgnoreCase) == 0) {
                                             idx2 = Form.SecondaryRailR;
                                         } else if (IsRW && string.Compare(Arguments[1], "9X", StringComparison.OrdinalIgnoreCase) == 0) {
                                             idx2 = int.MaxValue;
                                         } else if (!Interface.TryParseIntVb6(Arguments[1], out idx2)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is invalid in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             idx2 = 0;
                                         }
                                     }
                                     if (IsRW) {
                                         if (idx2 == int.MaxValue) {
                                             idx2 = 9;
                                         } else if (idx2 == -9) {
                                             idx2 = Form.SecondaryRailL;
                                         } else if (idx2 == 9) {
                                             idx2 = Form.SecondaryRailR;
                                         }
                                     }
                                     if (idx1 < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is expected to be non-negative in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (idx2 < 0 & idx2 != Form.SecondaryRailStub & idx2 != Form.SecondaryRailL & idx2 != Form.SecondaryRailR) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is expected to be greater or equal to -2 in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx1 >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx1].RailStart) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex1 could be out of range in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         if (idx2 != Form.SecondaryRailStub & idx2 != Form.SecondaryRailL & idx2 != Form.SecondaryRailR && (idx2 >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx2].RailStart)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex2 could be out of range in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         int roof = 0, pf = 0;
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out roof)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex is invalid in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             roof = 0;
                                         }
                                         if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseIntVb6(Arguments[3], out pf)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex is invalid in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             pf = 0;
                                         }
                                         if (roof != 0 & (roof < 0 || (roof >= Data.Structure.RoofL.Length || Data.Structure.RoofL[roof] == null) || (roof >= Data.Structure.RoofR.Length || Data.Structure.RoofR[roof] == null))) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RoofStructureIndex references an object not loaded in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (pf < 0 | (pf >= Data.Structure.FormL.Length || Data.Structure.FormL[pf] == null) & (pf >= Data.Structure.FormR.Length || Data.Structure.FormR[pf] == null)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "FormStructureIndex references an object not loaded in Track.Form at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             int n = Data.Blocks[BlockIndex].Form.Length;
                                             Array.Resize<Form>(ref Data.Blocks[BlockIndex].Form, n + 1);
                                             Data.Blocks[BlockIndex].Form[n].PrimaryRail = idx1;
                                             Data.Blocks[BlockIndex].Form[n].SecondaryRail = idx2;
                                             Data.Blocks[BlockIndex].Form[n].FormType = pf;
                                             Data.Blocks[BlockIndex].Form[n].RoofType = roof;
                                         }
                                     }
                                 }
                             } break;
                         case "track.pole":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         if (idx >= Data.Blocks[BlockIndex].RailPole.Length) {
                                             Array.Resize<Pole>(ref Data.Blocks[BlockIndex].RailPole, idx + 1);
                                             Data.Blocks[BlockIndex].RailPole[idx].Mode = 0;
                                             Data.Blocks[BlockIndex].RailPole[idx].Location = 0;
                                             Data.Blocks[BlockIndex].RailPole[idx].Interval = 2.0 * Data.BlockInterval;
                                             Data.Blocks[BlockIndex].RailPole[idx].Type = 0;
                                         }
                                         int typ = Data.Blocks[BlockIndex].RailPole[idx].Mode;
                                         int sttype = Data.Blocks[BlockIndex].RailPole[idx].Type;
                                         if (Arguments.Length >= 2 && Arguments[1].Length > 0) {
                                             if (!Interface.TryParseIntVb6(Arguments[1], out typ)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "AdditionalRailsCovered is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 typ = 0;
                                             }
                                         }
                                         if (Arguments.Length >= 3 && Arguments[2].Length > 0) {
                                             double loc;
                                             if (!Interface.TryParseDoubleVb6(Arguments[2], out loc)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Location is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 loc = 0.0;
                                             }
                                             Data.Blocks[BlockIndex].RailPole[idx].Location = loc;
                                         }
                                         if (Arguments.Length >= 4 && Arguments[3].Length > 0) {
                                             double dist;
                                             if (!Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out dist)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Interval is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 dist = Data.BlockInterval;
                                             }
                                             Data.Blocks[BlockIndex].RailPole[idx].Interval = dist;
                                         }
                                         if (Arguments.Length >= 5 && Arguments[4].Length > 0) {
                                             if (!Interface.TryParseIntVb6(Arguments[4], out sttype)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "PoleStructureIndex is invalid in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 sttype = 0;
                                             }
                                         }
                                         if (typ < 0 || typ >= Data.Structure.Poles.Length || Data.Structure.Poles[typ] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "PoleStructureIndex references an object not loaded in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (sttype < 0 || sttype >= Data.Structure.Poles[typ].Length || Data.Structure.Poles[typ][sttype] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "PoleStructureIndex references an object not loaded in Track.Pole at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Data.Blocks[BlockIndex].RailPole[idx].Mode = typ;
                                             Data.Blocks[BlockIndex].RailPole[idx].Type = sttype;
                                             Data.Blocks[BlockIndex].RailPole[idx].Exists = true;
                                         }
                                     }
                                 }
                             } break;
                         case "track.poleend":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.PoleEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0 | idx >= Data.Blocks[BlockIndex].RailPole.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex does not reference an existing pole in Track.PoleEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || (!Data.Blocks[BlockIndex].Rail[idx].RailStart & !Data.Blocks[BlockIndex].Rail[idx].RailEnd)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.PoleEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         Data.Blocks[BlockIndex].RailPole[idx].Exists = false;
                                     }
                                 }
                             } break;
                         case "track.wall":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be a non-negative integer in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     int dir = 0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out dir)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Direction is invalid in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         dir = 0;
                                     }
                                     int sttype = 0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex is invalid in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (sttype < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex is expected to be a non-negative integer in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (dir <= 0 && (sttype >= Data.Structure.WallL.Length || Data.Structure.WallL[sttype] == null) ||
                                         dir >= 0 && (sttype >= Data.Structure.WallR.Length || Data.Structure.WallR[sttype] == null)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "WallStructureIndex references an object not loaded in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             if (idx >= Data.Blocks[BlockIndex].RailWall.Length) {
                                                 Array.Resize<WallDike>(ref Data.Blocks[BlockIndex].RailWall, idx + 1);
                                             }
                                             Data.Blocks[BlockIndex].RailWall[idx].Exists = true;
                                             Data.Blocks[BlockIndex].RailWall[idx].Type = sttype;
                                             Data.Blocks[BlockIndex].RailWall[idx].Direction = dir;
                                         }
                                     }
                                 }
                             } break;
                         case "track.wallend":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.WallEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0 | idx >= Data.Blocks[BlockIndex].RailWall.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex does not reference an existing wall in Track.WallEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || (!Data.Blocks[BlockIndex].Rail[idx].RailStart & !Data.Blocks[BlockIndex].Rail[idx].RailEnd)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.WallEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         Data.Blocks[BlockIndex].RailWall[idx].Exists = false;
                                     }
                                 }
                             } break;
                         case "track.dike":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be a non-negative integer in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     int dir = 0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out dir)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Direction is invalid in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         dir = 0;
                                     }
                                     int sttype = 0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex is invalid in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (sttype < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex is expected to be a non-negative integer in Track.Wall at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (dir <= 0 && (sttype >= Data.Structure.DikeL.Length || Data.Structure.DikeL[sttype] == null) ||
                                         dir >= 0 && (sttype >= Data.Structure.DikeR.Length || Data.Structure.DikeR[sttype] == null)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "DikeStructureIndex references an object not loaded in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.Dike at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             if (idx >= Data.Blocks[BlockIndex].RailDike.Length) {
                                                 Array.Resize<WallDike>(ref Data.Blocks[BlockIndex].RailDike, idx + 1);
                                             }
                                             Data.Blocks[BlockIndex].RailDike[idx].Exists = true;
                                             Data.Blocks[BlockIndex].RailDike[idx].Type = sttype;
                                             Data.Blocks[BlockIndex].RailDike[idx].Direction = dir;
                                         }
                                     }
                                 }
                             } break;
                         case "track.dikeend":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.DikeEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0 | idx >= Data.Blocks[BlockIndex].RailDike.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex does not reference an existing dike in Track.DikeEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= Data.Blocks[BlockIndex].Rail.Length || (!Data.Blocks[BlockIndex].Rail[idx].RailStart & !Data.Blocks[BlockIndex].Rail[idx].RailEnd)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.DikeEnd at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         Data.Blocks[BlockIndex].RailDike[idx].Exists = false;
                                     }
                                 }
                             } break;
                         case "track.marker":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length < 1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Track.Marker is expected to have at least one argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         string f = OpenBveApi.Path.CombineFile(ObjectPath, Arguments[0]);
                                         if (!System.IO.File.Exists(f)) {
                                             Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in Track.Marker at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             double dist = Data.BlockInterval;
                                             if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out dist)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Distance is invalid in Track.Marker at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 dist = Data.BlockInterval;
                                             }
                                             double start, end;
                                             if (dist < 0.0) {
                                                 start = Data.TrackPosition;
                                                 end = Data.TrackPosition - dist;
                                             } else {
                                                 start = Data.TrackPosition - dist;
                                                 end = Data.TrackPosition;
                                             }
                                             if (start < 0.0) start = 0.0;
                                             if (end < 0.0) end = 0.0;
                                             if (end <= start) end = start + 0.01;
                                             int n = Data.Markers.Length;
                                             Array.Resize<Marker>(ref Data.Markers, n + 1);
                                             Data.Markers[n].StartingPosition = start;
                                             Data.Markers[n].EndingPosition = end;
                                             Textures.RegisterTexture(f, new OpenBveApi.Textures.TextureParameters(null, new Color24(64, 64, 64)), out Data.Markers[n].Texture);
                                         }
                                     }
                                 }
                             } break;
                         case "track.height":
                             {
                                 if (!PreviewOnly) {
                                     double h = 0.0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[0], UnitOfLength, out h)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Height is invalid in Track.Height at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         h = 0.0;
                                     }
                                     Data.Blocks[BlockIndex].Height = IsRW ? h + 0.3 : h;
                                 }
                             } break;
                         case "track.ground":
                             {
                                 if (!PreviewOnly) {
                                     int cytype = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out cytype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CycleIndex is invalid in Track.Ground at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         cytype = 0;
                                     }
                                     if (cytype < Data.Structure.Cycle.Length && Data.Structure.Cycle[cytype] != null) {
                                         Data.Blocks[BlockIndex].Cycle = Data.Structure.Cycle[cytype];
                                     } else {
                                         if (cytype >= Data.Structure.Ground.Length || Data.Structure.Ground[cytype] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "CycleIndex references an object not loaded in Track.Ground at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             Data.Blocks[BlockIndex].Cycle = new int[] { cytype };
                                         }
                                     }
                                 }
                             } break;
                         case "track.crack":
                             {
                                 if (!PreviewOnly) {
                                     int idx1 = 0, idx2 = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx1)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is invalid in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx1 = 0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out idx2)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is invalid in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx2 = 0;
                                     }
                                     int sttype = 0;
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseIntVb6(Arguments[2], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex is invalid in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (sttype < 0 || (sttype >= Data.Structure.CrackL.Length || Data.Structure.CrackL[sttype] == null) || (sttype >= Data.Structure.CrackR.Length || Data.Structure.CrackR[sttype] == null)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "CrackStructureIndex references an object not loaded in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx1 < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is expected to be non-negative in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (idx2 < 0) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex2 is expected to be non-negative in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else if (idx1 == idx2) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex1 is expected to be unequal to Index2 in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             if (idx1 >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx1].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex1 could be out of range in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             if (idx2 >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx2].RailStart) {
                                                 Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex2 could be out of range in Track.Crack at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             }
                                             int n = Data.Blocks[BlockIndex].Crack.Length;
                                             Array.Resize<Crack>(ref Data.Blocks[BlockIndex].Crack, n + 1);
                                             Data.Blocks[BlockIndex].Crack[n].PrimaryRail = idx1;
                                             Data.Blocks[BlockIndex].Crack[n].SecondaryRail = idx2;
                                             Data.Blocks[BlockIndex].Crack[n].Type = sttype;
                                         }
                                     }
                                 }
                             } break;
                         case "track.freeobj":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0, sttype = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseIntVb6(Arguments[1], out sttype)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FreeObjStructureIndex is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         sttype = 0;
                                     }
                                     if (idx < -1) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative or -1 in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (sttype < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "FreeObjStructureIndex is expected to be non-negative in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (idx >= 0 && (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart)) {
                                             Interface.AddMessage(Interface.MessageType.Warning, false, "RailIndex could be out of range in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         if (sttype >= Data.Structure.FreeObj.Length || Data.Structure.FreeObj[sttype] == null || Data.Structure.FreeObj[sttype] == null) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FreeObjStructureIndex references an object not loaded in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             double x = 0.0, y = 0.0;
                                             double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                             if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out x)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 x = 0.0;
                                             }
                                             if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], UnitOfLength, out y)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 y = 0.0;
                                             }
                                             if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out yaw)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 yaw = 0.0;
                                             }
                                             if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out pitch)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 pitch = 0.0;
                                             }
                                             if (Arguments.Length >= 7 && Arguments[6].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[6], out roll)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in Track.FreeObj at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                 roll = 0.0;
                                             }
                                             if (idx == -1) {
                                                 int n;
                                                 n = Data.Blocks[BlockIndex].GroundFreeObj.Length;
                                                 Array.Resize<FreeObj>(ref Data.Blocks[BlockIndex].GroundFreeObj, n + 1);
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].TrackPosition = Data.TrackPosition;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Type = sttype;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].X = x;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Y = y;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Yaw = yaw * 0.0174532925199433;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Pitch = pitch * 0.0174532925199433;
                                                 Data.Blocks[BlockIndex].GroundFreeObj[n].Roll = roll * 0.0174532925199433;
                                             } else {
                                                 if (idx >= Data.Blocks[BlockIndex].RailFreeObj.Length) {
                                                     Array.Resize<FreeObj[]>(ref Data.Blocks[BlockIndex].RailFreeObj, idx + 1);
                                                 }
                                                 int n;
                                                 if (Data.Blocks[BlockIndex].RailFreeObj[idx] == null) {
                                                     Data.Blocks[BlockIndex].RailFreeObj[idx] = new FreeObj[1];
                                                     n = 0;
                                                 } else {
                                                     n = Data.Blocks[BlockIndex].RailFreeObj[idx].Length;
                                                     Array.Resize<FreeObj>(ref Data.Blocks[BlockIndex].RailFreeObj[idx], n + 1);
                                                 }
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].TrackPosition = Data.TrackPosition;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Type = sttype;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].X = x;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Y = y;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Yaw = yaw * 0.0174532925199433;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Pitch = pitch * 0.0174532925199433;
                                                 Data.Blocks[BlockIndex].RailFreeObj[idx][n].Roll = roll * 0.0174532925199433;
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "track.back":
                             {
                                 if (!PreviewOnly) {
                                     int typ = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out typ)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         typ = 0;
                                     }
                                     if (typ < 0 | typ >= Data.Backgrounds.Length) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex references a texture not loaded in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else if (Data.Backgrounds[typ].Texture == null) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "BackgroundTextureIndex has not been loaded via Texture.Background in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         Data.Blocks[BlockIndex].Background = typ;
                                     }
                                 }
                             } break;
                         case "track.announce":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length == 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have between 1 and 2 arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 double speed = 0.0;
                                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], out speed)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     speed = 0.0;
                                                 }
                                                 int n = Data.Blocks[BlockIndex].Sound.Length;
                                                 Array.Resize<Sound>(ref Data.Blocks[BlockIndex].Sound, n + 1);
                                                 Data.Blocks[BlockIndex].Sound[n].TrackPosition = Data.TrackPosition;
                                                 const double radius = 15.0;
                                                 Data.Blocks[BlockIndex].Sound[n].SoundBuffer = Sounds.RegisterBuffer(f, radius);
                                                 Data.Blocks[BlockIndex].Sound[n].Type = speed == 0.0 ? SoundType.TrainStatic : SoundType.TrainDynamic;
                                                 Data.Blocks[BlockIndex].Sound[n].Speed = speed * Data.UnitOfSpeed;
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "track.doppler":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length == 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have between 1 and 3 arguments at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         if (Interface.ContainsInvalidPathChars(Arguments[0])) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "FileName contains illegal characters in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         } else {
                                             string f = OpenBveApi.Path.CombineFile(SoundPath, Arguments[0]);
                                             if (!System.IO.File.Exists(f)) {
                                                 Interface.AddMessage(Interface.MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             } else {
                                                 double x = 0.0, y = 0.0;
                                                 if (Arguments.Length >= 2 && Arguments[1].Length > 0 & !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out x)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     x = 0.0;
                                                 }
                                                 if (Arguments.Length >= 3 && Arguments[2].Length > 0 & !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out y)) {
                                                     Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                                     y = 0.0;
                                                 }
                                                 int n = Data.Blocks[BlockIndex].Sound.Length;
                                                 Array.Resize<Sound>(ref Data.Blocks[BlockIndex].Sound, n + 1);
                                                 Data.Blocks[BlockIndex].Sound[n].TrackPosition = Data.TrackPosition;
                                                 const double radius = 15.0;
                                                 Data.Blocks[BlockIndex].Sound[n].SoundBuffer = Sounds.RegisterBuffer(f, radius);
                                                 Data.Blocks[BlockIndex].Sound[n].Type = SoundType.World;
                                                 Data.Blocks[BlockIndex].Sound[n].X = x;
                                                 Data.Blocks[BlockIndex].Sound[n].Y = y;
                                                 Data.Blocks[BlockIndex].Sound[n].Radius = radius;
                                             }
                                         }
                                     }
                                 }
                             } break;
                         case "track.pretrain":
                             {
                                 if (!PreviewOnly) {
                                     if (Arguments.Length == 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, Command + " is expected to have exactly 1 argument at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     } else {
                                         double time = 0.0;
                                         if (Arguments[0].Length > 0 & !Interface.TryParseTime(Arguments[0], out time)) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Time is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                             time = 0.0;
                                         }
                                         int n = Game.BogusPretrainInstructions.Length;
                                         if (n != 0 && Game.BogusPretrainInstructions[n - 1].Time >= time) {
                                             Interface.AddMessage(Interface.MessageType.Error, false, "Time is expected to be in ascending order between successive " + Command + " commands at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         }
                                         Array.Resize<Game.BogusPretrainInstruction>(ref Game.BogusPretrainInstructions, n + 1);
                                         Game.BogusPretrainInstructions[n].TrackPosition = Data.TrackPosition;
                                         Game.BogusPretrainInstructions[n].Time = time;
                                     }
                                 }
                             } break;
                         case "track.pointofinterest":
                         case "track.poi":
                             {
                                 if (!PreviewOnly) {
                                     int idx = 0;
                                     if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !Interface.TryParseIntVb6(Arguments[0], out idx)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx < 0) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex is expected to be non-negative in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         idx = 0;
                                     }
                                     if (idx >= 0 && (idx >= Data.Blocks[BlockIndex].Rail.Length || !Data.Blocks[BlockIndex].Rail[idx].RailStart)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "RailIndex references a non-existing rail in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                     }
                                     double x = 0.0, y = 0.0;
                                     if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[1], UnitOfLength, out x)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "X is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         x = 0.0;
                                     }
                                     if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[2], UnitOfLength, out y)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Y is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         y = 0.0;
                                     }
                                     double yaw = 0.0, pitch = 0.0, roll = 0.0;
                                     if (Arguments.Length >= 4 && Arguments[3].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[3], out yaw)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Yaw is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         yaw = 0.0;
                                     }
                                     if (Arguments.Length >= 5 && Arguments[4].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[4], out pitch)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Pitch is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         pitch = 0.0;
                                     }
                                     if (Arguments.Length >= 6 && Arguments[5].Length > 0 && !Interface.TryParseDoubleVb6(Arguments[5], out roll)) {
                                         Interface.AddMessage(Interface.MessageType.Error, false, "Roll is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                         roll = 0.0;
                                     }
                                     string text = null;
                                     if (Arguments.Length >= 7 && Arguments[6].Length != 0) {
                                         text = Arguments[6];
                                     }
                                     int n = Data.Blocks[BlockIndex].PointsOfInterest.Length;
                                     Array.Resize<PointOfInterest>(ref Data.Blocks[BlockIndex].PointsOfInterest, n + 1);
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].TrackPosition = Data.TrackPosition;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].RailIndex = idx;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].X = x;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Y = y;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Yaw = 0.0174532925199433 * yaw;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Pitch = 0.0174532925199433 * pitch;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Roll = 0.0174532925199433 * roll;
                                     Data.Blocks[BlockIndex].PointsOfInterest[n].Text = text;
                                 }
                             } break;
                         default:
                             Interface.AddMessage(Interface.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;
                     }
                 }
             }
         }
     }
     if (!PreviewOnly) {
         // timetable
         Timetable.CustomTextures = new Textures.Texture[Data.TimetableDaytime.Length + Data.TimetableNighttime.Length];
         int n = 0;
         for (int i = 0; i < Data.TimetableDaytime.Length; i++) {
             if (Data.TimetableDaytime[i] != null) {
                 Timetable.CustomTextures[n] = Data.TimetableDaytime[i];
                 n++;
             }
         }
         for (int i = 0; i < Data.TimetableNighttime.Length; i++) {
             if (Data.TimetableNighttime[i] != null) {
                 Timetable.CustomTextures[n] = Data.TimetableNighttime[i];
                 n++;
             }
         }
         Array.Resize<Textures.Texture>(ref Timetable.CustomTextures, n);
     }
     // blocks
     Array.Resize<Block>(ref Data.Blocks, BlocksUsed);
 }
Esempio n. 2
0
        private void ParseSignalCommand(string Command, string[] Arguments, int Index, Encoding Encoding, Expression Expression, ref RouteData Data, bool PreviewOnly)
        {
            switch (Command)
            {
            case "signal":
                if (!PreviewOnly)
                {
                    if (Arguments.Length < 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have between 1 and 2 arguments at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        if (Arguments[0].EndsWith(".animated", StringComparison.OrdinalIgnoreCase))
                        {
                            if (Path.ContainsInvalidChars(Arguments[0]))
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "AnimatedObjectFile contains illegal characters in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            }
                            else
                            {
                                if (Arguments.Length > 1)
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Warning, false, Command + " is expected to have exactly 1 argument when using animated objects at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                }

                                string f = Path.CombineFile(ObjectPath, Arguments[0]);
                                if (!System.IO.File.Exists(f))
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, true, "SignalFileWithoutExtension " + f + " not found in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                }
                                else
                                {
                                    UnifiedObject obj;
                                    Plugin.CurrentHost.LoadObject(f, Encoding, out obj);
                                    if (obj is AnimatedObjectCollection)
                                    {
                                        AnimatedObjectSignalData Signal = new AnimatedObjectSignalData(obj);
                                        Data.Signals[Index] = Signal;
                                    }
                                    else
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, true, "GlowFileWithoutExtension " + f + " is not a valid animated object in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (Path.ContainsInvalidChars(Arguments[0]))
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "SignalFileWithoutExtension contains illegal characters in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            }
                            else
                            {
                                if (Arguments.Length > 2)
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Warning, false, Command + " is expected to have between 1 and 2 arguments at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                }

                                string f = Arguments[0];
                                try
                                {
                                    if (!LocateObject(ref f, ObjectPath))
                                    {
                                        string testPath = Path.CombineFile(ObjectPath, f);

                                        if (Plugin.CurrentHost.DetermineStaticObjectExtension(ref testPath))
                                        {
                                            f = testPath;
                                        }
                                        else
                                        {
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "SignalFileWithoutExtension does not exist in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                            break;
                                        }
                                    }
                                }
                                catch
                                {
                                    //NYCT-1 line has a comment containing SIGNAL, which is then misinterpreted by the parser here
                                    //Really needs commenting fixing, rather than hacks like this.....
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "SignalFileWithoutExtension does not contain a valid path in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                    break;
                                }

                                Bve4SignalData Signal = new Bve4SignalData
                                {
                                    BaseObject = LoadStaticObject(f, Encoding, false),
                                    GlowObject = null
                                };
                                string Folder = System.IO.Path.GetDirectoryName(f);
                                if (!System.IO.Directory.Exists(Folder))
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, true, "The folder " + Folder + " could not be found in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                }
                                else
                                {
                                    Signal.SignalTextures = LoadAllTextures(f, false);
                                    Signal.GlowTextures   = new OpenBveApi.Textures.Texture[] { };
                                    if (Arguments.Length >= 2 && Arguments[1].Length != 0)
                                    {
                                        if (Path.ContainsInvalidChars(Arguments[1]))
                                        {
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "GlowFileWithoutExtension contains illegal characters in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                        }
                                        else
                                        {
                                            f = Arguments[1];
                                            bool glowFileFound = false;
                                            if (!System.IO.File.Exists(f) && System.IO.Path.HasExtension(f))
                                            {
                                                string ext = System.IO.Path.GetExtension(f);

                                                if (Plugin.CurrentHost.SupportedStaticObjectExtensions.Contains(ext.ToLowerInvariant()))
                                                {
                                                    Plugin.CurrentHost.AddMessage(MessageType.Warning, false, "GlowFileWithoutExtension should not supply a file extension in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                                    f             = Path.CombineFile(ObjectPath, f);
                                                    glowFileFound = true;
                                                }
                                                else if (Plugin.CurrentHost.SupportedAnimatedObjectExtensions.Contains(ext.ToLowerInvariant()))
                                                {
                                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "GlowFileWithoutExtension must be a static object in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                                }
                                                else
                                                {
                                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "GlowFileWithoutExtension is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                                }
                                            }

                                            if (!System.IO.File.Exists(f) && !System.IO.Path.HasExtension(f))
                                            {
                                                string testPath = Path.CombineFile(ObjectPath, f);

                                                if (Plugin.CurrentHost.DetermineStaticObjectExtension(ref testPath))
                                                {
                                                    f             = testPath;
                                                    glowFileFound = true;
                                                }
                                                else
                                                {
                                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "GlowFileWithoutExtension does not exist in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                                                    break;
                                                }
                                            }

                                            if (glowFileFound)
                                            {
                                                Plugin.CurrentHost.LoadStaticObject(f, Encoding, false, out Signal.GlowObject);
                                                if (Signal.GlowObject != null)
                                                {
                                                    Signal.GlowTextures = LoadAllTextures(f, true);
                                                    for (int p = 0; p < Signal.GlowObject.Mesh.Materials.Length; p++)
                                                    {
                                                        Signal.GlowObject.Mesh.Materials[p].BlendMode           = MeshMaterialBlendMode.Additive;
                                                        Signal.GlowObject.Mesh.Materials[p].GlowAttenuationData = Glow.GetAttenuationData(200.0, GlowAttenuationMode.DivisionExponent4);
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    Data.Signals.Add(Index, Signal);
                                }
                            }
                        }
                    }
                }

                break;
            }
        }