Exemple #1
0
        //Parses an XML background definition
        public static BackgroundHandle ReadBackgroundXML(string fileName)
        {
            List <StaticBackground> Backgrounds = new List <StaticBackground>();
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

            //Load the object's XML file
            currentXML.Load(fileName);
            string Path = System.IO.Path.GetDirectoryName(fileName);

            double[] UnitOfLength = { 1.0 };
            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Background");
                //Check this file actually contains OpenBVE light definition nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode n in DocumentNodes)
                    {
                        if (n.ChildNodes.OfType <XmlElement>().Any())
                        {
                            double DisplayTime = -1;
                            //The time to transition between backgrounds in seconds
                            double TransitionTime = 0.8;
                            //The texture to use (if static)
                            Texture t = null;
                            //The object to use (if object based)
                            StaticObject o = null;
                            //The transition mode between backgrounds
                            BackgroundTransitionMode mode = BackgroundTransitionMode.FadeIn;
                            //The number of times the texture is repeated around the viewing frustrum (if appropriate)
                            double repetitions = 6;
                            foreach (XmlNode c in n.ChildNodes)
                            {
                                string[] Arguments = c.InnerText.Split(',');
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "mode":
                                    switch (c.InnerText.ToLowerInvariant())
                                    {
                                    case "fadein":
                                        mode = BackgroundTransitionMode.FadeIn;
                                        break;

                                    case "fadeout":
                                        mode = BackgroundTransitionMode.FadeOut;
                                        break;

                                    case "none":
                                        mode = BackgroundTransitionMode.None;
                                        break;

                                    default:
                                        Interface.AddMessage(MessageType.Error, true, c.InnerText + "is not a valid background fade mode in file " + fileName);
                                        break;
                                    }
                                    break;

                                case "object":
                                    string f;
                                    try
                                    {
                                        f = OpenBveApi.Path.CombineFile(System.IO.Path.GetDirectoryName(fileName), c.InnerText);
                                    }
                                    catch
                                    {
                                        Interface.AddMessage(MessageType.Error, true, "BackgroundObject FileName is malformed in file " + fileName);
                                        break;
                                    }
                                    if (!System.IO.File.Exists(f))
                                    {
                                        Interface.AddMessage(MessageType.Error, true, "FileName " + f + " not found in file " + fileName);
                                    }
                                    else
                                    {
                                        UnifiedObject b = ObjectManager.LoadObject(f, System.Text.Encoding.Default, false);
                                        o = (StaticObject)b;
                                    }
                                    break;

                                case "repetitions":
                                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], UnitOfLength, out repetitions))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid number of repetitions in " + fileName);
                                    }
                                    break;

                                case "texture":
                                    string file;
                                    try
                                    {
                                        file = OpenBveApi.Path.CombineFile(Path, c.InnerText);
                                    }
                                    catch
                                    {
                                        Interface.AddMessage(MessageType.Error, true, "BackgroundTexture FileName is malformed in file " + fileName);
                                        break;
                                    }
                                    if (!System.IO.File.Exists(file))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The background texture file " + c.InnerText + " does not exist in " + fileName);
                                    }
                                    else
                                    {
                                        Program.CurrentHost.RegisterTexture(file, new TextureParameters(null, null), out t);
                                    }
                                    break;

                                case "time":
                                    if (!Interface.TryParseTime(Arguments[0].Trim(), out DisplayTime))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid time in file " + fileName);
                                    }
                                    break;

                                case "transitiontime":
                                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], UnitOfLength, out TransitionTime))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, c.InnerText + " is not a valid background transition time in " + fileName);
                                    }
                                    break;
                                }
                            }
                            //Create background if texture is not null
                            if (t != null && o == null)
                            {
                                Backgrounds.Add(new StaticBackground(t, repetitions, false, TransitionTime, mode, DisplayTime));
                            }
                            if (t == null && o != null)
                            {
                                //All other parameters are ignored if an object has been defined
                                //TODO: Error message stating they have been ignored
                                return(new BackgroundObject(o));
                            }
                        }
                    }
                    if (Backgrounds.Count == 1)
                    {
                        return(Backgrounds[0]);
                    }
                    if (Backgrounds.Count > 1)
                    {
                        //Sort list- Not worried about when they start or end, so use simple LINQ
                        Backgrounds = Backgrounds.OrderBy(o => o.Time).ToList();
                        //If more than 2 backgrounds, convert to array and return a new dynamic background
                        return(new DynamicBackground(Backgrounds.ToArray()));
                    }
                }
            }
            //We couldn't find any valid XML, so return false
            throw new InvalidDataException();
        }
Exemple #2
0
        private static void ParseCarNode(XmlNode Node, string fileName, int Car, ref TrainManager.Train Train, ref UnifiedObject[] CarObjects, ref UnifiedObject[] BogieObjects, ref bool visibleFromInterior)
        {
            string interiorFile = string.Empty;
            ReadhesionDeviceType readhesionDevice = Train.Cars[0].Specs.ReAdhesionDevice.DeviceType;

            foreach (XmlNode c in Node.ChildNodes)
            {
                //Note: Don't use the short-circuiting operator, as otherwise we need another if
                switch (c.Name.ToLowerInvariant())
                {
                case "camerarestriction":
                    Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.Restricted3D;
                    foreach (XmlNode cc in c.ChildNodes)
                    {
                        switch (cc.Name.ToLowerInvariant())
                        {
                        case "backwards":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.BottomLeft.Z))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid backwards camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "forwards":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.TopRight.Z))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid forwards camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "left":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.BottomLeft.X))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid left camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "right":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.TopRight.X))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid right camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "down":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.BottomLeft.Y))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid down camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;

                        case "up":
                            if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].CameraRestriction.TopRight.Y))
                            {
                                Interface.AddMessage(MessageType.Warning, false, "Invalid up camera restriction defined for Car " + Car + " in XML file " + fileName);
                            }
                            break;
                        }
                    }
                    break;

                case "brake":
                    Train.Cars[Car].CarBrake.brakeType = BrakeType.Auxiliary;
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        ParseBrakeNode(c, fileName, Car, ref Train);
                    }
                    else if (!String.IsNullOrEmpty(c.InnerText))
                    {
                        try
                        {
                            string      childFile = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                            XmlDocument childXML  = new XmlDocument();
                            childXML.Load(childFile);
                            XmlNodeList childNodes = childXML.DocumentElement.SelectNodes("/openBVE/Brake");
                            //We need to save and restore the current path to make relative paths within the child file work correctly
                            string savedPath = currentPath;
                            currentPath = System.IO.Path.GetDirectoryName(childFile);
                            ParseBrakeNode(childNodes[0], fileName, Car, ref Train);
                            currentPath = savedPath;
                        }
                        catch
                        {
                            Interface.AddMessage(MessageType.Error, false, "Failed to load the child Brake XML file specified in " + c.InnerText);
                        }
                    }
                    break;

                case "length":
                    double l;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out l) | l <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid length defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Length = l;
                    break;

                case "width":
                    double w;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out w) | w <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid width defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Width = w;
                    break;

                case "height":
                    double h;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out h) | h <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid height defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Height = h;
                    break;

                case "motorcar":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        Train.Cars[Car].Specs.IsMotorCar         = true;
                        Train.Cars[Car].Specs.AccelerationCurves = new AccelerationCurve[AccelerationCurves.Length];
                        for (int i = 0; i < AccelerationCurves.Length; i++)
                        {
                            Train.Cars[Car].Specs.AccelerationCurves[i] = AccelerationCurves[i].Clone(AccelerationCurves[i].Multiplier);
                        }
                    }
                    else
                    {
                        Train.Cars[Car].Specs.AccelerationCurves = new AccelerationCurve[] { };
                        Train.Cars[Car].Specs.IsMotorCar         = false;
                    }
                    break;

                case "mass":
                    double m;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out m) | m <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid mass defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].EmptyMass = m;
                    Train.Cars[Car].CargoMass = 0;
                    break;

                case "frontaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].FrontAxle.Position))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid front axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "rearaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].RearAxle.Position))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid rear axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "object":
                    if (string.IsNullOrEmpty(c.InnerText))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid object path for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    string f = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (System.IO.File.Exists(f))
                    {
                        Program.CurrentHost.LoadObject(f, System.Text.Encoding.Default, out CarObjects[Car]);
                    }
                    break;

                case "reversed":
                    int n;
                    NumberFormats.TryParseIntVb6(c.InnerText, out n);
                    if (n == 1 || c.InnerText.ToLowerInvariant() == "true")
                    {
                        CarObjectsReversed[Car] = true;
                    }
                    break;

                case "loadingsway":
                    int nm;
                    NumberFormats.TryParseIntVb6(c.InnerText, out nm);
                    if (nm == 1 || c.InnerText.ToLowerInvariant() == "true")
                    {
                        Train.Cars[Car].EnableLoadingSway = true;
                    }
                    else
                    {
                        Train.Cars[Car].EnableLoadingSway = false;
                    }
                    break;

                case "frontbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid front bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid front bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                if (string.IsNullOrEmpty(cc.InnerText))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid front bogie object path for Car " + Car + " in XML file " + fileName);
                                    break;
                                }
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    Program.CurrentHost.LoadObject(fb, System.Text.Encoding.Default, out BogieObjects[Car * 2]);
                                }
                                break;

                            case "reversed":
                                int nn;
                                NumberFormats.TryParseIntVb6(cc.InnerText, out nn);
                                if (cc.InnerText.ToLowerInvariant() == "true" || nn == 1)
                                {
                                    BogieObjectsReversed[Car * 2] = true;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "rearbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid rear bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid rear bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                if (string.IsNullOrEmpty(cc.InnerText))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid rear bogie object path for Car " + Car + " in XML file " + fileName);
                                    break;
                                }
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    Program.CurrentHost.LoadObject(fb, System.Text.Encoding.Default, out BogieObjects[Car * 2 + 1]);
                                }
                                break;

                            case "reversed":
                                int nn;
                                NumberFormats.TryParseIntVb6(cc.InnerText, out nn);
                                if (cc.InnerText.ToLowerInvariant() == "true" || nn == 1)
                                {
                                    BogieObjectsReversed[Car * 2 + 1] = true;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "driverposition":
                    string[] splitText = c.InnerText.Split(new char[] { ',' });
                    if (splitText.Length != 3)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position must have three arguments for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Driver = new Vector3();
                    double driverZ;
                    if (!NumberFormats.TryParseDoubleVb6(splitText[0], out Train.Cars[Car].Driver.X))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[1], out Train.Cars[Car].Driver.Y))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position Y was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[2], out driverZ))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    Train.Cars[Car].Driver.Z = 0.5 * Train.Cars[Car].Length + driverZ;
                    break;

                case "interiorview":
                    if (!Train.IsPlayerTrain)
                    {
                        break;
                    }
                    Train.Cars[Car].HasInteriorView = true;
                    Train.Cars[Car].CarSections     = new CarSection[1];
                    Train.Cars[Car].CarSections[0]  = new CarSection(Program.CurrentHost, ObjectType.Overlay);

                    string cv = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (!System.IO.File.Exists(cv))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Interior view file was invalid for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    interiorFile = cv;
                    break;

                case "readhesiondevice":
                    switch (c.InnerText.ToLowerInvariant())
                    {
                    case "typea":
                    case "a":
                        readhesionDevice = ReadhesionDeviceType.TypeA;
                        break;

                    case "typeb":
                    case "b":
                        readhesionDevice = ReadhesionDeviceType.TypeB;
                        break;

                    case "typec":
                    case "c":
                        readhesionDevice = ReadhesionDeviceType.TypeC;
                        break;

                    case "typed":
                    case "d":
                        readhesionDevice = ReadhesionDeviceType.TypeD;
                        break;

                    default:
                        readhesionDevice = ReadhesionDeviceType.NotFitted;
                        break;
                    }
                    break;

                case "visiblefrominterior":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        visibleFromInterior = true;
                    }
                    break;
                }
            }

            /*
             * As there is no set order for XML tags to be presented in, these must be
             * done after the end of the loop			 *
             */
            //Assign interior view
            if (interiorFile != String.Empty)
            {
                if (interiorFile.ToLowerInvariant().EndsWith(".xml"))
                {
                    XDocument CurrentXML = XDocument.Load(interiorFile, LoadOptions.SetLineInfo);

                    // Check for null
                    if (CurrentXML.Root == null)
                    {
                        // We couldn't find any valid XML, so return false
                        throw new System.IO.InvalidDataException();
                    }
                    IEnumerable <XElement> DocumentElements = CurrentXML.Root.Elements("PanelAnimated");
                    if (DocumentElements != null && DocumentElements.Count() != 0)
                    {
                        PanelAnimatedXmlParser.ParsePanelAnimatedXml(interiorFile, currentPath, Train, Car);
                        if (Train.Cars[Car].CameraRestrictionMode != CameraRestrictionMode.Restricted3D)
                        {
                            Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.NotAvailable;
                        }
                        return;
                    }
                    DocumentElements = CurrentXML.Root.Elements("Panel");
                    if (DocumentElements != null && DocumentElements.Count() != 0)
                    {
                        PanelXmlParser.ParsePanelXml(interiorFile, currentPath, Train, Car);
                        Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.On;
                        return;
                    }
                }
                else if (interiorFile.ToLowerInvariant().EndsWith(".cfg"))
                {
                    //Only supports panel2.cfg format
                    Panel2CfgParser.ParsePanel2Config(System.IO.Path.GetFileName(interiorFile), System.IO.Path.GetDirectoryName(interiorFile), Train.Cars[Train.DriverCar]);
                    Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.On;
                }
                else if (interiorFile.ToLowerInvariant().EndsWith(".animated"))
                {
                    UnifiedObject currentObject;
                    Program.CurrentHost.LoadObject(interiorFile, Encoding.UTF8, out currentObject);
                    var a = currentObject as AnimatedObjectCollection;
                    if (a != null)
                    {
                        try
                        {
                            for (int i = 0; i < a.Objects.Length; i++)
                            {
                                Program.CurrentHost.CreateDynamicObject(ref a.Objects[i].internalObject);
                            }
                            Train.Cars[Car].CarSections[0].Groups[0].Elements = a.Objects;
                            if (Train.Cars[Car].CameraRestrictionMode != CameraRestrictionMode.Restricted3D)
                            {
                                Train.Cars[Car].CameraRestrictionMode = CameraRestrictionMode.NotAvailable;
                            }
                        }
                        catch
                        {
                            Program.RestartArguments = " ";
                            Loading.Cancel           = true;
                        }
                    }
                }
                else
                {
                    Interface.AddMessage(MessageType.Warning, false, "Interior view file is not supported for Car " + Car + " in XML file " + fileName);
                }
            }
            Train.Cars[Car].Specs.ReAdhesionDevice = new TrainManager.CarReAdhesionDevice(Train.Cars[Car], readhesionDevice);
        }
Exemple #3
0
        private void ParseTrainCommand(string Command, string[] Arguments, int Index, Expression Expression, ref RouteData Data, bool PreviewOnly)
        {
            switch (Command)
            {
            case "interval":
            {
                if (!PreviewOnly)
                {
                    List <double> intervals = new List <double>();
                    for (int k = 0; k < Arguments.Length; k++)
                    {
                        double o;
                        if (!NumberFormats.TryParseDoubleVb6(Arguments[k], out o))
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Interval " + k.ToString(Culture) + " is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            continue;
                        }

                        if (o == 0)
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Interval " + k.ToString(Culture) + " must be non-zero in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            continue;
                        }

                        if (o > 43200 && Plugin.CurrentOptions.EnableBveTsHacks)
                        {
                            //Southern Blighton- Treston park has a runinterval of well over 24 hours, and there are likely others
                            //Discard this
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Interval " + k.ToString(Culture) + " is greater than 12 hours in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            continue;
                        }

                        if (o < 120 && Plugin.CurrentOptions.EnableBveTsHacks)
                        {
                            /*
                             * An AI train follows the same schedule / rules as the player train
                             * ==>
                             * x Waiting time before departure at the first station (30s to 1min is 'normal')
                             * x Time to accelerate to linespeed
                             * x Time to clear (as a minimum) the protecting signal on station exit
                             *
                             * When the runinterval is below ~2minutes, on large numbers of routes, this
                             * shows up as a train overlapping the player train (bad....)
                             */
                            o = 120;
                        }

                        intervals.Add(o);
                    }

                    intervals.Sort();
                    if (intervals.Count > 0)
                    {
                        CurrentRoute.PrecedingTrainTimeDeltas = intervals.ToArray();
                    }
                }
            }
            break;

            case "velocity":
            {
                if (!PreviewOnly)
                {
                    double limit = 0.0;
                    if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[0], out limit))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Speed is invalid in Train.Velocity at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        limit = 0.0;
                    }

                    Plugin.CurrentOptions.PrecedingTrainSpeedLimit = limit <= 0.0 ? double.PositiveInfinity : Data.UnitOfSpeed * limit;
                }
            }
            break;

            case "folder":
            case "file":
            {
                if (PreviewOnly)
                {
                    if (Arguments.Length < 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument 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, "FolderName contains illegal characters in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        }
                        else
                        {
                            Plugin.CurrentOptions.TrainName = Arguments[0];
                        }
                    }
                }
            }
            break;

            case "run":
            case "rail":
            {
                if (!PreviewOnly)
                {
                    if (Index < 0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RailTypeIndex is out of range in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        int val = 0;
                        if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out val))
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RunSoundIndex is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            val = 0;
                        }

                        if (val < 0)
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RunSoundIndex is expected to be non-negative in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            val = 0;
                        }

                        if (Index >= Data.Structure.Run.Length)
                        {
                            Array.Resize(ref Data.Structure.Run, Index + 1);
                        }

                        Data.Structure.Run[Index] = val;
                    }
                }
                else
                {
                    railtypeCount++;
                }
            }
            break;

            case "flange":
            {
                if (!PreviewOnly)
                {
                    if (Index < 0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RailTypeIndex is out of range in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        int val = 0;
                        if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out val))
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FlangeSoundIndex is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            val = 0;
                        }

                        if (val < 0)
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "FlangeSoundIndex expected to be non-negative in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            val = 0;
                        }

                        if (Index >= Data.Structure.Flange.Length)
                        {
                            Array.Resize(ref Data.Structure.Flange, Index + 1);
                        }

                        Data.Structure.Flange[Index] = val;
                    }
                }
            }
            break;

            case "timetable.day":
            {
                if (!PreviewOnly)
                {
                    if (Index < 0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "TimetableIndex is expected to be non-negative 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.Error, false, Command + " is expected to have one argument 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, "FileName " + Arguments[0] + " contains illegal characters in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        }
                        else
                        {
                            while (Index >= Data.TimetableDaytime.Length)
                            {
                                int n = Data.TimetableDaytime.Length;
                                Array.Resize(ref Data.TimetableDaytime, n << 1);
                                for (int i = n; i < Data.TimetableDaytime.Length; i++)
                                {
                                    Data.TimetableDaytime[i] = null;
                                }
                            }

                            string f = string.Empty;
                            if (!string.IsNullOrEmpty(TrainPath))
                            {
                                f = Path.CombineFile(TrainPath, Arguments[0]);
                            }

                            if (!System.IO.File.Exists(f))
                            {
                                f = Path.CombineFile(ObjectPath, Arguments[0]);
                            }

                            if (System.IO.File.Exists(f))
                            {
                                Plugin.CurrentHost.RegisterTexture(f, new TextureParameters(null, null), out Data.TimetableDaytime[Index]);
                            }
                            else
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "DaytimeTimetable " + Index + " with FileName " + Arguments[0] + " was not found in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            }
                        }
                    }
                }
            }
            break;

            case "timetable.night":
            {
                if (!PreviewOnly)
                {
                    if (Index < 0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "TimetableIndex is expected to be non-negative 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.Error, false, Command + " is expected to have one argument 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, "FileName " + Arguments[0] + " contains illegal characters in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        }
                        else
                        {
                            while (Index >= Data.TimetableNighttime.Length)
                            {
                                int n = Data.TimetableNighttime.Length;
                                Array.Resize(ref Data.TimetableNighttime, n << 1);
                                for (int i = n; i < Data.TimetableNighttime.Length; i++)
                                {
                                    Data.TimetableNighttime[i] = null;
                                }
                            }

                            string f = string.Empty;
                            if (!string.IsNullOrEmpty(TrainPath))
                            {
                                f = Path.CombineFile(TrainPath, Arguments[0]);
                            }

                            if (!System.IO.File.Exists(f))
                            {
                                f = Path.CombineFile(ObjectPath, Arguments[0]);
                            }

                            if (System.IO.File.Exists(f))
                            {
                                Plugin.CurrentHost.RegisterTexture(f, new TextureParameters(null, null), out Data.TimetableNighttime[Index]);
                            }
                            else
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "DaytimeTimetable " + Index + " with FileName " + Arguments[0] + " was not found in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            }
                        }
                    }
                }
            }
            break;

            case "destination":
            {
                if (!PreviewOnly)
                {
                    if (Arguments.Length < 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        if (!NumberFormats.TryParseIntVb6(Arguments[0], out Plugin.CurrentOptions.InitialDestination))
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Destination is expected to be an Integer in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        }
                    }
                }
            }
            break;
            }
        }
Exemple #4
0
        internal static void Process(MainForm form)
        {
            mainForm = form;

            if (!System.IO.File.Exists(FileName))
            {
                MessageBox.Show("The selected folder does not contain a valid train.dat \r\n Please retry.", "CarXML Convertor", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            string[] Lines = System.IO.File.ReadAllLines(FileName);
            for (int i = 0; i < Lines.Length; i++)

            {
                int n = 0;
                switch (Lines[i].ToLowerInvariant())
                {
                case "#cockpit":
                case "#cab":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0: ConvertSoundCfg.DriverPosition.X = 0.001 * a; break;

                            case 1: ConvertSoundCfg.DriverPosition.Y = 0.001 * a; break;

                            case 2: ConvertSoundCfg.DriverPosition.Z = 0.001 * a; break;

                            case 3: DriverCar = (int)Math.Round(a); break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#car":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0:
                                if (!(a <= 0.0))
                                {
                                    MotorCarMass = a * 1000.0;
                                }
                                break;

                            case 1:
                                if (!(a <= 0.0))
                                {
                                    NumberOfMotorCars = (int)Math.Round(a);
                                }
                                break;

                            case 2:
                                if (!(a <= 0.0))
                                {
                                    TrailerCarMass = a * 1000.0;
                                }
                                break;

                            case 3:
                                if (!(a <= 0.0))
                                {
                                    NumberOfTrailerCars = (int)Math.Round(a);
                                }
                                break;

                            case 4:
                                if (!(a <= 0.0))
                                {
                                    CarLength = a;
                                }
                                break;

                            case 5:
                                FrontCarIsMotorCar = a == 1.0;
                                break;

                            case 6:
                                if (!(a <= 0.0))
                                {
                                    CarWidth = a;
                                }
                                break;

                            case 7:
                                if (!(a <= 0.0))
                                {
                                    CarHeight = a;
                                }
                                break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#brake":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        int a; if (NumberFormats.TryParseIntVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0: BrakeType = a; break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#move":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 4: BrakeCylinderEmergencyRate = a * 1000.0; break;

                            case 5: BrakeCylinderReleaseRate = a * 1000.0; break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#pressure":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "BrakeCylinderServiceMaximumPressure is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    BrakeCylinderServiceMaximumPressure = a * 1000.0;
                                } break;

                            case 1:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "BrakeCylinderEmergencyMaximumPressure is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    BrakeCylinderEmergencyMaximumPressure = a * 1000.0;
                                } break;

                            case 2:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "MainReservoirMinimumPressure is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    MainReservoirMinimumPressure = a * 1000.0;
                                } break;

                            case 3:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "MainReservoirMaximumPressure is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    MainReservoirMaximumPressure = a * 1000.0;
                                } break;

                            case 4:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "BrakePipePressue is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    BrakePipePressure = a * 1000.0;
                                } break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                default:
                {
                    i++;
                    while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        i++; n++;
                    }
                    i--;
                }
                break;
                }
            }

            if (BrakePipePressure <= 0.0)
            {
                if (BrakeType == 2)                 //Automatic air brake
                {
                    BrakePipePressure = BrakeCylinderEmergencyMaximumPressure + 0.75 * (MainReservoirMinimumPressure - BrakeCylinderEmergencyMaximumPressure);
                    if (BrakePipePressure > MainReservoirMinimumPressure)
                    {
                        BrakePipePressure = MainReservoirMinimumPressure;
                    }
                }
                else
                {
                    if (BrakeCylinderEmergencyMaximumPressure <480000.0& MainReservoirMinimumPressure> 500000.0)
                    {
                        BrakePipePressure = 490000.0;
                    }
                    else
                    {
                        BrakePipePressure = BrakeCylinderEmergencyMaximumPressure + 0.75 * (MainReservoirMinimumPressure - BrakeCylinderEmergencyMaximumPressure);
                    }
                }
            }

            NumberOfCars = NumberOfMotorCars + NumberOfTrailerCars;
            MotorCars    = new bool[NumberOfCars];
            if (NumberOfMotorCars == 1)
            {
                if (FrontCarIsMotorCar | NumberOfTrailerCars == 0)
                {
                    MotorCars[0] = true;
                }
                else
                {
                    MotorCars[NumberOfCars - 1] = true;
                }
            }
            else if (NumberOfMotorCars == 2)
            {
                if (FrontCarIsMotorCar | NumberOfTrailerCars == 0)
                {
                    MotorCars[0] = true;
                    MotorCars[NumberOfCars - 1] = true;
                }
                else if (NumberOfTrailerCars == 1)
                {
                    MotorCars[1] = true;
                    MotorCars[2] = true;
                }
                else
                {
                    int i = (int)Math.Ceiling(0.25 * (double)(NumberOfCars - 1));
                    int j = (int)Math.Floor(0.75 * (double)(NumberOfCars - 1));
                    MotorCars[i] = true;
                    MotorCars[j] = true;
                }
            }
            else if (NumberOfMotorCars > 0)
            {
                if (FrontCarIsMotorCar)
                {
                    MotorCars[0] = true;
                    double t = 1.0 + (double)NumberOfTrailerCars / (double)(NumberOfMotorCars - 1);
                    double r = 0.0;
                    double x = 0.0;
                    while (true)
                    {
                        double y = x + t - r;
                        x = Math.Ceiling(y);
                        r = x - y;
                        int i = (int)x;
                        if (i >= NumberOfCars)
                        {
                            break;
                        }
                        MotorCars[i] = true;
                    }
                }
                else
                {
                    MotorCars[1] = true;
                    double t = 1.0 + (double)(NumberOfTrailerCars - 1) / (double)(NumberOfMotorCars - 1);
                    double r = 0.0;
                    double x = 1.0;
                    while (true)
                    {
                        double y = x + t - r;
                        x = Math.Ceiling(y);
                        r = x - y;
                        int i = (int)x;
                        if (i >= NumberOfCars)
                        {
                            break;
                        }
                        MotorCars[i] = true;
                    }
                }
            }
        }
Exemple #5
0
        internal static void Process(MainForm form)
        {
            mainForm = form;

            if (!System.IO.File.Exists(FileName))
            {
                MessageBox.Show("The selected folder does not contain a valid train.dat \r\n Please retry.", "CarXML Convertor", MessageBoxButtons.OK, MessageBoxIcon.Information);
                mainForm.terminateEarly = true;
                return;
            }
            string[] Lines = System.IO.File.ReadAllLines(FileName);

            int currentVersion = ParseFormat(Lines);

            for (int i = 0; i < Lines.Length; i++)

            {
                int n = 0;
                switch (Lines[i].ToLowerInvariant())
                {
                case "#cockpit":
                case "#cab":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0:
                                ConvertSoundCfg.DriverPosition.X = 0.001 * a;
                                break;

                            case 1:
                                ConvertSoundCfg.DriverPosition.Y = 0.001 * a;
                                break;

                            case 2:
                                ConvertSoundCfg.DriverPosition.Z = 0.001 * a;
                                break;

                            case 3:
                                DriverCar = (int)Math.Round(a);
                                break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#car":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0:
                                if (!(a <= 0.0))
                                {
                                    MotorCarMass = a * 1000.0;
                                }
                                break;

                            case 1:
                                if (!(a <= 0.0))
                                {
                                    NumberOfMotorCars = (int)Math.Round(a);
                                }
                                break;

                            case 2:
                                if (!(a <= 0.0))
                                {
                                    TrailerCarMass = a * 1000.0;
                                }
                                break;

                            case 3:
                                if (!(a <= 0.0))
                                {
                                    NumberOfTrailerCars = (int)Math.Round(a);
                                }
                                break;

                            case 4:
                                if (!(a <= 0.0))
                                {
                                    CarLength = a;
                                }
                                break;

                            case 5:
                                FrontCarIsMotorCar = a == 1.0;
                                break;

                            case 6:
                                if (!(a <= 0.0))
                                {
                                    CarWidth = a;
                                }
                                break;

                            case 7:
                                if (!(a <= 0.0))
                                {
                                    CarHeight = a;
                                }
                                break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#brake":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        int a; if (NumberFormats.TryParseIntVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0: BrakeType = a; break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#move":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 4: BrakeCylinderEmergencyRate = a * 1000.0; break;

                            case 5: BrakeCylinderReleaseRate = a * 1000.0; break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#pressure":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "BrakeCylinderServiceMaximumPressure is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    BrakeCylinderServiceMaximumPressure = a * 1000.0;
                                } break;

                            case 1:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "BrakeCylinderEmergencyMaximumPressure is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    BrakeCylinderEmergencyMaximumPressure = a * 1000.0;
                                } break;

                            case 2:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "MainReservoirMinimumPressure is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    MainReservoirMinimumPressure = a * 1000.0;
                                } break;

                            case 3:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "MainReservoirMaximumPressure is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    MainReservoirMaximumPressure = a * 1000.0;
                                } break;

                            case 4:
                                if (a <= 0.0)
                                {
                                    mainForm.updateLogBoxText += "BrakePipePressue is expected to be positive at line " + (i + 1).ToString(CultureInfo.InvariantCulture) + " in " + FileName;
                                }
                                else
                                {
                                    BrakePipePressure = a * 1000.0;
                                } break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#device":
                    i++;
                    while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 5: ReadhesionDeviceType = (int)a; break;
                            }
                        }
                        i++; n++;
                    }
                    i--;
                    break;

                case "#acceleration":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        AccelerationCurve curve = new AccelerationCurve();
                        string            t     = Lines[i] + ",";
                        int m = 0;
                        while (true)
                        {
                            int j = t.IndexOf(',');
                            if (j == -1)
                            {
                                break;
                            }
                            string s = t.Substring(0, j).Trim();
                            t = t.Substring(j + 1);
                            if (NumberFormats.TryParseDoubleVb6(s, out var a))
                            {
                                switch (m)
                                {
                                case 0:
                                    if (a <= 0.0)
                                    {
                                    }
                                    else
                                    {
                                        curve.StageZeroAcceleration = a;
                                    } break;

                                case 1:
                                    if (a <= 0.0)
                                    {
                                    }
                                    else
                                    {
                                        curve.StageOneAcceleration = a;
                                    } break;

                                case 2:
                                    if (a <= 0.0)
                                    {
                                    }
                                    else
                                    {
                                        curve.StageOneSpeed = a;
                                    } break;

                                case 3:
                                    if (a <= 0.0)
                                    {
                                    }
                                    else
                                    {
                                        curve.StageTwoSpeed = a;
                                        if (curve.StageTwoSpeed < curve.StageOneSpeed)
                                        {
                                            curve.StageTwoSpeed = curve.StageOneSpeed;
                                        }
                                    } break;

                                case 4:
                                {
                                    if (currentVersion < 2000000)
                                    {
                                        if (a <= 0.0)
                                        {
                                            curve.StageTwoExponent = 1.0;
                                        }
                                        else
                                        {
                                            const double c = 4.439346232277577;
                                            curve.StageTwoExponent = 1.0 - Math.Log(a) * curve.StageTwoSpeed * c;
                                            if (curve.StageTwoExponent <= 0.0)
                                            {
                                                curve.StageTwoExponent = 1.0;
                                            }
                                            else if (curve.StageTwoExponent > 4.0)
                                            {
                                                curve.StageTwoExponent = 4.0;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        curve.StageTwoExponent = a;
                                        if (curve.StageTwoExponent <= 0.0)
                                        {
                                            curve.StageTwoExponent = 1.0;
                                        }
                                    }
                                } break;
                                }
                            }
                            m++;
                        }
                        i++; n++;
                        AccelerationCurves.Add(curve);
                    }
                    i--; break;

                default:
                {
                    i++;
                    while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        i++; n++;
                    }
                    i--;
                }
                break;
                }
            }

            if (BrakePipePressure <= 0.0)
            {
                if (BrakeType == 2)                 //Automatic air brake
                {
                    BrakePipePressure = BrakeCylinderEmergencyMaximumPressure + 0.75 * (MainReservoirMinimumPressure - BrakeCylinderEmergencyMaximumPressure);
                    if (BrakePipePressure > MainReservoirMinimumPressure)
                    {
                        BrakePipePressure = MainReservoirMinimumPressure;
                    }
                }
                else
                {
                    if (BrakeCylinderEmergencyMaximumPressure <480000.0& MainReservoirMinimumPressure> 500000.0)
                    {
                        BrakePipePressure = 490000.0;
                    }
                    else
                    {
                        BrakePipePressure = BrakeCylinderEmergencyMaximumPressure + 0.75 * (MainReservoirMinimumPressure - BrakeCylinderEmergencyMaximumPressure);
                    }
                }
            }

            NumberOfCars = NumberOfMotorCars + NumberOfTrailerCars;
            MotorCars    = new bool[NumberOfCars];
            if (NumberOfMotorCars == 1)
            {
                if (FrontCarIsMotorCar | NumberOfTrailerCars == 0)
                {
                    MotorCars[0] = true;
                }
                else
                {
                    MotorCars[NumberOfCars - 1] = true;
                }
            }
            else if (NumberOfMotorCars == 2)
            {
                if (FrontCarIsMotorCar | NumberOfTrailerCars == 0)
                {
                    MotorCars[0] = true;
                    MotorCars[NumberOfCars - 1] = true;
                }
                else if (NumberOfTrailerCars == 1)
                {
                    MotorCars[1] = true;
                    MotorCars[2] = true;
                }
                else
                {
                    int i = (int)Math.Ceiling(0.25 * (NumberOfCars - 1));
                    int j = (int)Math.Floor(0.75 * (NumberOfCars - 1));
                    MotorCars[i] = true;
                    MotorCars[j] = true;
                }
            }
            else if (NumberOfMotorCars > 0)
            {
                if (FrontCarIsMotorCar)
                {
                    MotorCars[0] = true;
                    double t = 1.0 + (double)NumberOfTrailerCars / (double)(NumberOfMotorCars - 1);
                    double r = 0.0;
                    double x = 0.0;
                    while (true)
                    {
                        double y = x + t - r;
                        x = Math.Ceiling(y);
                        r = x - y;
                        int i = (int)x;
                        if (i >= NumberOfCars)
                        {
                            break;
                        }
                        MotorCars[i] = true;
                    }
                }
                else
                {
                    MotorCars[1] = true;
                    double t = 1.0 + (double)(NumberOfTrailerCars - 1) / (double)(NumberOfMotorCars - 1);
                    double r = 0.0;
                    double x = 1.0;
                    while (true)
                    {
                        double y = x + t - r;
                        x = Math.Ceiling(y);
                        r = x - y;
                        int i = (int)x;
                        if (i >= NumberOfCars)
                        {
                            break;
                        }
                        MotorCars[i] = true;
                    }
                }
            }
            ConvertSoundCfg.DriverPosition.Z = 0.5 * CarLength + ConvertSoundCfg.DriverPosition.Z;
        }
Exemple #6
0
        //Parses an XML dynamic lighting definition
        public static bool ReadLightingXML(string fileName)
        {
            //Prep
            Plugin.CurrentRoute.LightDefinitions = new LightDefinition[0];
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

            //Load the object's XML file
            try
            {
                currentXML.Load(fileName);
            }
            catch
            {
                return(false);
            }

            bool defined = false;

            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Brightness");
                //Check this file actually contains OpenBVE light definition nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode n in DocumentNodes)
                    {
                        LightDefinition currentLight = new LightDefinition();
                        if (n.ChildNodes.OfType <XmlElement>().Any())
                        {
                            bool   tf = false, al = false, dl = false, ld = false, cb = false;
                            string ts = null;
                            foreach (XmlNode c in n.ChildNodes)
                            {
                                string[] Arguments = c.InnerText.Split(new[] { ',' });
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "cablighting":
                                    double b;
                                    if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out b))
                                    {
                                        cb = true;
                                    }
                                    if (b > 255 || b < 0)
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " is not a valid brightness value in file " + fileName);
                                        currentLight.CabBrightness = 255;
                                        break;
                                    }
                                    currentLight.CabBrightness = b;
                                    break;

                                case "time":
                                    double t;
                                    if (Parser.TryParseTime(Arguments[0].Trim(new char[] { }), out t))
                                    {
                                        currentLight.Time = (int)t;
                                        tf = true;
                                        //Keep back for error report later
                                        ts = Arguments[0];
                                    }
                                    else
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid time in file " + fileName);
                                    }
                                    break;

                                case "ambientlight":
                                    if (Arguments.Length == 3)
                                    {
                                        double R, G, B;
                                        if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out R) && NumberFormats.TryParseDoubleVb6(Arguments[1].Trim(new char[] { }), out G) && NumberFormats.TryParseDoubleVb6(Arguments[2].Trim(new char[] { }), out B))
                                        {
                                            currentLight.AmbientColor = new Color24((byte)R, (byte)G, (byte)B);
                                            al = true;
                                        }
                                        else
                                        {
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid color in file " + fileName);
                                        }
                                    }
                                    else
                                    {
                                        if (Arguments.Length == 1)
                                        {
                                            if (Color24.TryParseHexColor(Arguments[0], out currentLight.AmbientColor))
                                            {
                                                al = true;
                                                break;
                                            }
                                        }
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not contain three arguments in file " + fileName);
                                    }
                                    break;

                                case "directionallight":
                                    if (Arguments.Length == 3)
                                    {
                                        double R, G, B;
                                        if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out R) && NumberFormats.TryParseDoubleVb6(Arguments[1].Trim(new char[] { }), out G) && NumberFormats.TryParseDoubleVb6(Arguments[2].Trim(new char[] { }), out B))
                                        {
                                            currentLight.DiffuseColor = new Color24((byte)R, (byte)G, (byte)B);
                                            dl = true;
                                        }
                                        else
                                        {
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid color in file " + fileName);
                                        }
                                    }
                                    else
                                    {
                                        if (Arguments.Length == 1)
                                        {
                                            if (Color24.TryParseHexColor(Arguments[0], out currentLight.DiffuseColor))
                                            {
                                                dl = true;
                                                break;
                                            }
                                        }
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not contain three arguments in file " + fileName);
                                    }
                                    break;

                                case "cartesianlightdirection":
                                case "lightdirection":
                                    if (Arguments.Length == 3)
                                    {
                                        double X, Y, Z;
                                        if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out X) && NumberFormats.TryParseDoubleVb6(Arguments[1].Trim(new char[] { }), out Y) && NumberFormats.TryParseDoubleVb6(Arguments[2].Trim(new char[] { }), out Z))
                                        {
                                            currentLight.LightPosition = new Vector3(X, Y, Z);
                                            ld = true;
                                        }
                                        else
                                        {
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid direction in file " + fileName);
                                        }
                                    }
                                    else
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not contain three arguments in file " + fileName);
                                    }
                                    break;

                                case "sphericallightdirection":
                                    if (Arguments.Length == 2)
                                    {
                                        double theta, phi;
                                        if (NumberFormats.TryParseDoubleVb6(Arguments[0].Trim(new char[] { }), out theta) && NumberFormats.TryParseDoubleVb6(Arguments[1].Trim(new char[] { }), out phi))
                                        {
                                            currentLight.LightPosition = new Vector3(Math.Cos(theta) * Math.Sin(phi), -Math.Sin(theta), Math.Cos(theta) * Math.Cos(phi));
                                            ld = true;
                                        }
                                        else
                                        {
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not parse to a valid direction in file " + fileName);
                                        }
                                    }
                                    else
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, c.InnerText + " does not contain two arguments in file " + fileName);
                                    }
                                    break;
                                }
                            }
                            //We want to be able to add a completely default light element,  but not one that's not been defined in the XML properly
                            if (tf || al || ld || dl || cb)
                            {
                                //HACK: No way to break out of the first loop and continue with the second, so we've got to use a variable
                                bool Break = false;
                                int  l     = Plugin.CurrentRoute.LightDefinitions.Length;
                                for (int i = 0; i < l; i++)
                                {
                                    if (Plugin.CurrentRoute.LightDefinitions[i].Time == currentLight.Time)
                                    {
                                        Break = true;
                                        if (ts == null)
                                        {
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Multiple undefined times were encountered in file " + fileName);
                                        }
                                        else
                                        {
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Duplicate time found: " + ts + " in file " + fileName);
                                        }
                                        break;
                                    }
                                }
                                if (Break)
                                {
                                    continue;
                                }
                                //We've got there, so now figure out where to add the new light into our list of light definitions
                                int t = 0;
                                if (l == 1)
                                {
                                    t = currentLight.Time > Plugin.CurrentRoute.LightDefinitions[0].Time ? 1 : 0;
                                }
                                else if (l > 1)
                                {
                                    for (int i = 1; i < l; i++)
                                    {
                                        t = i + 1;
                                        if (currentLight.Time > Plugin.CurrentRoute.LightDefinitions[i - 1].Time && currentLight.Time < Plugin.CurrentRoute.LightDefinitions[i].Time)
                                        {
                                            break;
                                        }
                                    }
                                }
                                //Resize array
                                defined = true;
                                Array.Resize(ref Plugin.CurrentRoute.LightDefinitions, l + 1);
                                if (t == l)
                                {
                                    //Straight insert at the end of the array
                                    Plugin.CurrentRoute.LightDefinitions[l] = currentLight;
                                }
                                else
                                {
                                    for (int u = t; u < l; u++)
                                    {
                                        //Otherwise, shift all elements to compensate
                                        Plugin.CurrentRoute.LightDefinitions[u + 1] = Plugin.CurrentRoute.LightDefinitions[u];
                                    }
                                    Plugin.CurrentRoute.LightDefinitions[t] = currentLight;
                                }
                            }
                        }
                    }
                }
            }
            //We couldn't find any valid XML, so return false
            return(defined);
        }
Exemple #7
0
        private static void ParsePanelAnimatedNode(XElement Element, string FileName, string TrainPath, TrainManager.Train Train, int Car, TrainManager.CarSection CarSection, int GroupIndex)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;

            int    currentSectionElement   = 0;
            int    numberOfSectionElements = Element.Elements().Count();
            double invfac = numberOfSectionElements == 0 ? Loading.TrainProgressCurrentWeight : Loading.TrainProgressCurrentWeight / (double)numberOfSectionElements;

            foreach (XElement SectionElement in Element.Elements())
            {
                Loading.TrainProgress = Loading.TrainProgressCurrentSum + invfac * (double)currentSectionElement;
                if ((currentSectionElement & 4) == 0)
                {
                    System.Threading.Thread.Sleep(1);
                    if (Loading.Cancel)
                    {
                        return;
                    }
                }

                string Section = SectionElement.Name.LocalName;

                switch (SectionElement.Name.LocalName.ToLowerInvariant())
                {
                case "group":
                    if (GroupIndex == 0)
                    {
                        int n = 0;

                        foreach (XElement KeyNode in SectionElement.Elements())
                        {
                            string Key        = KeyNode.Name.LocalName;
                            string Value      = KeyNode.Value;
                            int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                            switch (Key.ToLowerInvariant())
                            {
                            case "number":
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out n))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;
                            }
                        }

                        if (n + 1 >= CarSection.Groups.Length)
                        {
                            Array.Resize(ref CarSection.Groups, n + 2);
                            CarSection.Groups[n + 1] = new TrainManager.ElementsGroup
                            {
                                Elements = new ObjectManager.AnimatedObject[] { },
                                Overlay  = true
                            };
                        }

                        ParsePanelAnimatedNode(SectionElement, FileName, TrainPath, Train, Car, CarSection, n + 1);
                    }
                    break;

                case "touch":
                    if (GroupIndex > 0)
                    {
                        Vector3 Position             = Vector3.Zero;
                        Vector3 Size                 = Vector3.Zero;
                        int     JumpScreen           = GroupIndex - 1;
                        int     SoundIndex           = -1;
                        Translations.Command Command = Translations.Command.None;
                        int CommandOption            = 0;

                        foreach (XElement KeyNode in SectionElement.Elements())
                        {
                            string Key        = KeyNode.Name.LocalName;
                            string Value      = KeyNode.Value;
                            int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                            switch (Key.ToLowerInvariant())
                            {
                            case "position":
                            {
                                string[] s = Value.Split(',');
                                if (s.Length == 3)
                                {
                                    if (s[0].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[0], out Position.X))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "X is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                    if (s[1].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[1], out Position.Y))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                    if (s[2].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[2], out Position.Z))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Z is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Three arguments are expected in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                            }
                            break;

                            case "size":
                            {
                                string[] s = Value.Split(',');
                                if (s.Length == 3)
                                {
                                    if (s[0].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[0], out Size.X))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "X is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                    if (s[1].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[1], out Size.Y))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Y is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                    if (s[2].Length != 0 && !NumberFormats.TryParseDoubleVb6(s[2], out Size.Z))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "Z is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    }
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Three arguments are expected in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                            }
                            break;

                            case "jumpscreen":
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out JumpScreen))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;

                            case "soundindex":
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out SoundIndex))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;

                            case "command":
                            {
                                int i;
                                for (i = 0; i < Translations.CommandInfos.Length; i++)
                                {
                                    if (string.Compare(Value, Translations.CommandInfos[i].Name, StringComparison.OrdinalIgnoreCase) == 0)
                                    {
                                        break;
                                    }
                                }
                                if (i == Translations.CommandInfos.Length || Translations.CommandInfos[i].Type != Translations.CommandType.Digital)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                else
                                {
                                    Command = Translations.CommandInfos[i].Command;
                                }
                            }
                            break;

                            case "commandoption":
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out CommandOption))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;
                            }
                        }
                        CreateTouchElement(CarSection.Groups[GroupIndex], Position, Size, JumpScreen, SoundIndex, Command, CommandOption);
                    }
                    break;

                case "include":
                {
                    foreach (XElement KeyNode in SectionElement.Elements())
                    {
                        string Key        = KeyNode.Name.LocalName;
                        string Value      = KeyNode.Value;
                        int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                        switch (Key.ToLowerInvariant())
                        {
                        case "filename":
                        {
                            string File = OpenBveApi.Path.CombineFile(TrainPath, Value);
                            if (System.IO.File.Exists(File))
                            {
                                System.Text.Encoding e = TextEncoding.GetSystemEncodingFromFile(File);
                                ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(File, e);
                                if (a != null)
                                {
                                    for (int i = 0; i < a.Objects.Length; i++)
                                    {
                                        a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                                    }
                                    CarSection.Groups[GroupIndex].Elements = a.Objects;
                                }
                                else
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                            }
                        }
                        break;
                        }
                    }
                }
                break;
                }
            }
        }
Exemple #8
0
        private void ParseRouteCommand(RouteCommand Command, string[] Arguments, int Index, string FileName, double[] UnitOfLength, Expression Expression, ref RouteData Data, bool PreviewOnly)
        {
            switch (Command)
            {
            case RouteCommand.DeveloperID:
                //Unused by OpenBVE
                break;

            case RouteCommand.Comment:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    CurrentRoute.Comment = Arguments[0];
                }

                break;

            case RouteCommand.Image:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    string f = Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), Arguments[0]);
                    if (!System.IO.File.Exists(f))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        CurrentRoute.Image = f;
                    }
                }

                break;

            case RouteCommand.TimeTable:
                if (!PreviewOnly)
                {
                    if (Arguments.Length < 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "" + Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        CurrentRoute.Information.DefaultTimetableDescription = Arguments[0];
                    }
                }

                break;

            case RouteCommand.Change:
                if (!PreviewOnly)
                {
                    int change = 0;
                    if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out change))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        change = 0;
                    }
                    else if (change < -1 | change > 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Mode is expected to be -1, 0 or 1 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        change = 0;
                    }

                    Plugin.CurrentOptions.TrainStart = (TrainStartMode)change;
                }

                break;

            case RouteCommand.Gauge:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    double a;
                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], out a))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ValueInMillimeters is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a <= 0.0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ValueInMillimeters is expected to be positive in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        for (int tt = 0; tt < CurrentRoute.Tracks.Count; tt++)
                        {
                            int t = CurrentRoute.Tracks.ElementAt(tt).Key;
                            CurrentRoute.Tracks[t].RailGauge = 0.001 * a;
                        }
                    }
                }
                break;

            case RouteCommand.Signal:
                if (!PreviewOnly)
                {
                    if (Arguments.Length < 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        double a;
                        if (!NumberFormats.TryParseDoubleVb6(Arguments[0], out a))
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Speed is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        }
                        else
                        {
                            if (Index < 0)
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "AspectIndex is expected to be non-negative in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            }
                            else if (a < 0.0)
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Speed is expected to be non-negative in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            }
                            else
                            {
                                if (Index >= Data.SignalSpeeds.Length)
                                {
                                    int n = Data.SignalSpeeds.Length;
                                    Array.Resize(ref Data.SignalSpeeds, Index + 1);
                                    for (int i = n; i < Index; i++)
                                    {
                                        Data.SignalSpeeds[i] = double.PositiveInfinity;
                                    }
                                }

                                Data.SignalSpeeds[Index] = a * Data.UnitOfSpeed;
                            }
                        }
                    }
                }
                break;

            case RouteCommand.AccelerationDueToGravity:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    double a;
                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], out a))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Value is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a <= 0.0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Value is expected to be positive in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        CurrentRoute.Atmosphere.AccelerationDueToGravity = a;
                    }
                }
                break;

            case RouteCommand.StartTime:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    double t;
                    if (!TryParseTime(Arguments[0], out t))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, Arguments[0] + " does not parse to a valid time in command " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        if (CurrentRoute.InitialStationTime == -1)
                        {
                            CurrentRoute.InitialStationTime = t;
                        }
                    }
                }
                break;

            case RouteCommand.LoadingScreen:
                if (PreviewOnly)
                {
                    return;
                }

                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    string f = Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), Arguments[0]);
                    if (!System.IO.File.Exists(f))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        Texture t = new Texture(f, new TextureParameters(null, null), Plugin.CurrentHost);
                        CurrentRoute.Information.LoadingScreenBackground = t;
                    }
                }

                break;

            case RouteCommand.DisplaySpeed:
                if (PreviewOnly)
                {
                    return;
                }

                if (Arguments.Length == 1 && Arguments[0].IndexOf(',') != -1)
                {
                    Arguments = Arguments[0].Split(',');
                }
                if (Arguments.Length != 2)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have two arguments at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    break;
                }
                Plugin.CurrentOptions.UnitOfSpeed = Arguments[0];
                if (!double.TryParse(Arguments[1], NumberStyles.Float, Culture, out Plugin.CurrentOptions.SpeedConversionFactor))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Speed conversion factor is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    Plugin.CurrentOptions.UnitOfSpeed = "km/h";
                }
                break;

            case RouteCommand.Briefing:
                if (PreviewOnly)
                {
                    return;
                }

                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    string f = Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), Arguments[0]);
                    if (!System.IO.File.Exists(f))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, true, "FileName " + f + " not found in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        CurrentRoute.Information.RouteBriefing = f;
                    }
                }
                break;

            case RouteCommand.Elevation:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    double a;
                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], UnitOfLength, out a))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Height is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        CurrentRoute.Atmosphere.InitialElevation = a;
                    }
                }
                break;

            case RouteCommand.Temperature:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    double a;
                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], out a))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ValueInCelsius is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a <= -273.15)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ValueInCelsius is expected to be greater than -273.15 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a >= 100.0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ValueInCelsius is expected to be less than 100.0 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        CurrentRoute.Atmosphere.InitialAirTemperature = a + 273.15;
                    }
                }
                break;

            case RouteCommand.Pressure:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    double a;
                    if (!NumberFormats.TryParseDoubleVb6(Arguments[0], out a))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ValueInKPa is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a <= 0.0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ValueInKPa is expected to be positive in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a >= 120.0)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ValueInKPa is expected to be less than 120.0 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        CurrentRoute.Atmosphere.InitialAirPressure = 1000.0 * a;
                    }
                }
                break;

            case RouteCommand.AmbientLight:
            {
                if (Plugin.CurrentRoute.DynamicLighting)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Warning, false, "Dynamic lighting is enabled- Route.AmbientLight will be ignored");
                    break;
                }

                int r = 255, g = 255, b = 255;
                if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out r))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RedValue is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else if (r < 0 | r > 255)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RedValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    r = r < 0 ? 0 : 255;
                }

                if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[1], out g))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "GreenValue is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else if (g < 0 | g > 255)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "GreenValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    g = g < 0 ? 0 : 255;
                }

                if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[2], out b))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "BlueValue is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else if (b < 0 | b > 255)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "BlueValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    b = b < 0 ? 0 : 255;
                }

                Plugin.CurrentRoute.Atmosphere.AmbientLightColor = new Color24((byte)r, (byte)g, (byte)b);
            }
            break;

            case RouteCommand.DirectionalLight:
            {
                if (Plugin.CurrentRoute.DynamicLighting)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Warning, false, "Dynamic lighting is enabled- Route.DirectionalLight will be ignored");
                    break;
                }

                int r = 255, g = 255, b = 255;
                if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out r))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RedValue is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else if (r < 0 | r > 255)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "RedValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    r = r < 0 ? 0 : 255;
                }

                if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[1], out g))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "GreenValue is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else if (g < 0 | g > 255)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "GreenValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    g = g < 0 ? 0 : 255;
                }

                if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[2], out b))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "BlueValue is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else if (b < 0 | b > 255)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "BlueValue is required to be within the range from 0 to 255 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    b = b < 0 ? 0 : 255;
                }

                Plugin.CurrentRoute.Atmosphere.DiffuseLightColor = new Color24((byte)r, (byte)g, (byte)b);
            }
            break;

            case RouteCommand.LightDirection:
            {
                if (Plugin.CurrentRoute.DynamicLighting)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Warning, false, "Dynamic lighting is enabled- Route.LightDirection will be ignored");
                    break;
                }

                double theta = 60.0, phi = -26.565051177078;
                if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[0], out theta))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Theta is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }

                if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[1], out phi))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Phi is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }

                theta = theta.ToRadians();
                phi   = phi.ToRadians();
                double dx = Math.Cos(theta) * Math.Sin(phi);
                double dy = -Math.Sin(theta);
                double dz = Math.Cos(theta) * Math.Cos(phi);
                Plugin.CurrentRoute.Atmosphere.LightPosition = new Vector3((float)-dx, (float)-dy, (float)-dz);
            }
            break;

            case RouteCommand.DynamicLight:
                //Read the lighting XML file
                string path = Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), Arguments[0]);
                if (System.IO.File.Exists(path))
                {
                    if (DynamicLightParser.ReadLightingXML(path, out Plugin.CurrentRoute.LightDefinitions))
                    {
                        Plugin.CurrentRoute.DynamicLighting = true;
                        Data.Structure.LightDefinitions.Add(int.MaxValue, Plugin.CurrentRoute.LightDefinitions);
                    }
                    else
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "The file " + path + " is not a valid dynamic lighting XML file, at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                }
                else
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Dynamic lighting XML file not found at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                break;

            case RouteCommand.InitialViewPoint:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    int cv;
                    if (!NumberFormats.TryParseIntVb6(Arguments[0], out cv))
                    {
                        switch (Arguments[0].ToLowerInvariant())
                        {
                        case "cab":
                            cv = 0;
                            break;

                        case "exterior":
                            cv = 1;
                            break;

                        case "track":
                            cv = 2;
                            break;

                        case "flyby":
                            cv = 3;
                            break;

                        case "flybyzooming":
                            cv = 4;
                            break;

                        default:
                            cv = 0;
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is invalid at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                            break;
                        }
                    }

                    if (cv >= 0 && cv <= 4)
                    {
                        Plugin.CurrentOptions.InitialViewpoint = cv;
                    }
                    else
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is invalid at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                }
                break;

            case RouteCommand.TfoXML:
                if (!PreviewOnly)
                {
                    string tfoFile = Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), Arguments[0]);
                    if (!System.IO.File.Exists(tfoFile))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, true, "TrackFollowingObject XML file " + tfoFile + " not found in Track.TfoXML at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                        break;
                    }

                    if (Plugin.TrainManager.TFOs == null)
                    {
                        Plugin.TrainManager.TFOs = new AbstractTrain[] { };
                    }
                    int n = Plugin.TrainManager.TFOs.Length;
                    Array.Resize(ref Plugin.TrainManager.TFOs, n + 1);
                    Plugin.TrainManager.TFOs[n] = Plugin.CurrentHost.ParseTrackFollowingObject(ObjectPath, tfoFile);
                }
                break;
            }
        }
        /// <summary>Preprocesses the options contained within a route file</summary>
        /// <param name="IsRW">Whether the current route file is in RW format</param>
        /// <param name="Expressions">The initial list of expressions</param>
        /// <param name="Data">The finalized route data</param>
        /// <param name="UnitOfLength">The units of length conversion factor to be applied</param>
        /// <param name="PreviewOnly">Whether this is a preview only</param>
        private static void PreprocessOptions(bool IsRW, Expression[] Expressions, ref RouteData Data, ref double[] UnitOfLength, bool PreviewOnly)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            string Section             = "";
            bool   SectionAlwaysPrefix = false;

            // process expressions
            for (int j = 0; j < Expressions.Length; j++)
            {
                if (IsRW && Expressions[j].Text.StartsWith("[") && Expressions[j].Text.EndsWith("]"))
                {
                    Section = Expressions[j].Text.Substring(1, Expressions[j].Text.Length - 2).Trim(new char[] { });
                    if (string.Compare(Section, "object", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        Section = "Structure";
                    }
                    else if (string.Compare(Section, "railway", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        Section = "Track";
                    }
                    SectionAlwaysPrefix = true;
                }
                else
                {
                    Expressions[j].ConvertRwToCsv(Section, SectionAlwaysPrefix);
                    // separate command and arguments
                    string Command, ArgumentSequence;
                    Expressions[j].SeparateCommandsAndArguments(out Command, out ArgumentSequence, Culture, true, IsRW, Section);
                    // process command
                    double Number;
                    bool   NumberCheck = !IsRW || string.Compare(Section, "track", StringComparison.OrdinalIgnoreCase) == 0;
                    if (!NumberCheck || !NumberFormats.TryParseDoubleVb6(Command, UnitOfLength, out Number))
                    {
                        // 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(new char[] { });
                                    a            = k + 1; h++;
                                }
                                else if (ArgumentSequence[k] == ';')
                                {
                                    Arguments[h] = ArgumentSequence.Substring(a, k - a).Trim(new char[] { });
                                    a            = k + 1; h++;
                                }
                            }
                            if (ArgumentSequence.Length - a > 0)
                            {
                                Arguments[h] = ArgumentSequence.Substring(a).Trim(new char[] { });
                                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", "");
                        }
                        // handle indices
                        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(new char[] { });
                                    Command = Command.Substring(0, k).TrimEnd(new char[] { });
                                    int h = Indices.IndexOf(";", StringComparison.Ordinal);
                                    int CommandIndex1;
                                    if (h >= 0)
                                    {
                                        string a = Indices.Substring(0, h).TrimEnd(new char[] { });
                                        string b = Indices.Substring(h + 1).TrimStart(new char[] { });
                                        if (a.Length > 0 && !NumberFormats.TryParseIntVb6(a, out CommandIndex1))
                                        {
                                            Command = null; break;
                                        }
                                        int CommandIndex2;
                                        if (b.Length > 0 && !NumberFormats.TryParseIntVb6(b, out CommandIndex2))
                                        {
                                            Command = null;
                                        }
                                    }
                                    else
                                    {
                                        if (Indices.Length > 0 && !NumberFormats.TryParseIntVb6(Indices, out CommandIndex1))
                                        {
                                            Command = null;
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                        // process command
                        if (Command != null)
                        {
                            switch (Command.ToLowerInvariant())
                            {
                            // options
                            case "options.unitoflength":
                            {
                                if (Arguments.Length == 0)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "At least 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                }
                                else
                                {
                                    UnitOfLength = new double[Arguments.Length];
                                    for (int i = 0; i < Arguments.Length; i++)
                                    {
                                        UnitOfLength[i] = i == Arguments.Length - 1 ? 1.0 : 0.0;
                                        if (Arguments[i].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[i], out UnitOfLength[i]))
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "FactorInMeters" + 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);
                                            UnitOfLength[i] = i == 0 ? 1.0 : 0.0;
                                        }
                                        else if (UnitOfLength[i] <= 0.0)
                                        {
                                            Interface.AddMessage(MessageType.Error, false, "FactorInMeters" + i.ToString(Culture) + " 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);
                                            UnitOfLength[i] = i == Arguments.Length - 1 ? 1.0 : 0.0;
                                        }
                                    }
                                }
                            }
                            break;

                            case "options.unitofspeed":
                            {
                                if (Arguments.Length < 1)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Exactly 1 argument is expected 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(MessageType.Warning, false, "Exactly 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                    }
                                    if (Arguments[0].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[0], out Data.UnitOfSpeed))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "FactorInKmph is invalid in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                        Data.UnitOfSpeed = 0.277777777777778;
                                    }
                                    else if (Data.UnitOfSpeed <= 0.0)
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "FactorInKmph 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);
                                        Data.UnitOfSpeed = 0.277777777777778;
                                    }
                                    else
                                    {
                                        Data.UnitOfSpeed *= 0.277777777777778;
                                    }
                                }
                            }
                            break;

                            case "options.objectvisibility":
                            {
                                if (Arguments.Length == 0)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Exactly 1 argument is expected 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(MessageType.Warning, false, "Exactly 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                    }
                                    int mode = 0;
                                    if (Arguments.Length >= 1 && Arguments[0].Length != 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out mode))
                                    {
                                        Interface.AddMessage(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);
                                        mode = 0;
                                    }
                                    else if (mode != 0 & mode != 1)
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The specified Mode is not supported in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                        mode = 0;
                                    }
                                    Data.AccurateObjectDisposal = mode == 1;
                                }
                            }
                            break;

                            case "options.compatibletransparencymode":
                            {
                                //Whether to use fuzzy matching for BVE2 / BVE4 transparencies
                                //Should be DISABLED on openBVE content
                                if (PreviewOnly)
                                {
                                    continue;
                                }
                                if (Arguments.Length == 0)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Exactly 1 argument is expected 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(MessageType.Warning, false, "Exactly 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                    }
                                    int mode = 0;
                                    if (Arguments.Length >= 1 && Arguments[0].Length != 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out mode))
                                    {
                                        Interface.AddMessage(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);
                                        mode = 0;
                                    }
                                    else if (mode != 0 & mode != 1)
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The specified Mode is not supported in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                        mode = 0;
                                    }
                                    Interface.CurrentOptions.OldTransparencyMode = mode == 1;
                                }
                            }
                            break;

                            case "options.enablehacks":
                            {
                                //Whether to apply various hacks to fix BVE2 / BVE4 routes
                                //Whilst this is harmless, it should be DISABLED on openBVE content
                                //in order to ensure that all errors are correctly fixed by the developer
                                if (PreviewOnly)
                                {
                                    continue;
                                }
                                if (Arguments.Length == 0)
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Exactly 1 argument is expected 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(MessageType.Warning, false, "Exactly 1 argument is expected in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                    }
                                    int mode = 0;
                                    if (Arguments.Length >= 1 && Arguments[0].Length != 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out mode))
                                    {
                                        Interface.AddMessage(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);
                                        mode = 0;
                                    }
                                    else if (mode != 0 & mode != 1)
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "The specified Mode is not supported in " + Command + " at line " + Expressions[j].Line.ToString(Culture) + ", column " + Expressions[j].Column.ToString(Culture) + " in file " + Expressions[j].File);
                                        mode = 0;
                                    }
                                    Interface.CurrentOptions.EnableBveTsHacks = mode == 1;
                                }
                            }
                            break;
                            }
                        }
                    }
                }
            }
        }
Exemple #10
0
        private void ParseBrakeNode(XmlNode Node, string fileName, int Car, ref TrainBase Train)
        {
            double compressorRate = 5000.0, compressorMinimumPressure = 690000.0, compressorMaximumPressure = 780000.0;
            double auxiliaryReservoirChargeRate = 200000.0;
            double equalizingReservoirChargeRate = 200000.0, equalizingReservoirServiceRate = 50000.0, equalizingReservoirEmergencyRate = 250000.0;
            double brakePipeNormalPressure = 0.0, brakePipeChargeRate = 10000000.0, brakePipeServiceRate = 1500000.0, brakePipeEmergencyRate = 5000000.0;
            double straightAirPipeServiceRate = 300000.0, straightAirPipeEmergencyRate = 400000.0, straightAirPipeReleaseRate = 200000.0;
            double brakeCylinderServiceMaximumPressure = 440000.0, brakeCylinderEmergencyMaximumPressure = 440000.0, brakeCylinderEmergencyRate = 300000.0, brakeCylinderReleaseRate = 200000.0;

            foreach (XmlNode c in Node.ChildNodes)
            {
                //Note: Don't use the short-circuiting operator, as otherwise we need another if
                switch (c.Name.ToLowerInvariant())
                {
                case "compressor":
                    Train.Cars[Car].CarBrake.brakeType = BrakeType.Main;                             //We have a compressor so must be a main brake type
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "rate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out compressorRate) | compressorRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid compression rate defined for Car " + Car + " in XML file " + fileName);
                                    compressorRate = 5000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "mainreservoir":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "minimumpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out compressorMinimumPressure) | compressorMinimumPressure <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid main reservoir minumum pressure defined for Car " + Car + " in XML file " + fileName);
                                    compressorMinimumPressure = 690000.0;
                                }
                                break;

                            case "maximumpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out compressorMaximumPressure) | compressorMaximumPressure <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid main reservoir maximum pressure defined for Car " + Car + " in XML file " + fileName);
                                    compressorMaximumPressure = 780000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "auxiliaryreservoir":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "chargerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out auxiliaryReservoirChargeRate) | auxiliaryReservoirChargeRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid auxiliary reservoir charge rate defined for Car " + Car + " in XML file " + fileName);
                                    auxiliaryReservoirChargeRate = 200000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "equalizingreservoir":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "chargerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out equalizingReservoirChargeRate) | equalizingReservoirChargeRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid equalizing reservoir charge rate defined for Car " + Car + " in XML file " + fileName);
                                    equalizingReservoirChargeRate = 50000.0;
                                }
                                break;

                            case "servicerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out equalizingReservoirServiceRate) | equalizingReservoirServiceRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid equalizing reservoir service rate defined for Car " + Car + " in XML file " + fileName);
                                    equalizingReservoirServiceRate = 50000.0;
                                }
                                break;

                            case "emergencyrate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out equalizingReservoirEmergencyRate) | equalizingReservoirEmergencyRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid equalizing reservoir emergency rate defined for Car " + Car + " in XML file " + fileName);
                                    equalizingReservoirEmergencyRate = 50000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "brakepipe":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "normalpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakePipeNormalPressure) | brakePipeNormalPressure <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid brake pipe normal pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakePipeNormalPressure = 0.0;
                                }
                                break;

                            case "chargerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakePipeChargeRate) | brakePipeChargeRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid brake pipe charge rate defined for Car " + Car + " in XML file " + fileName);
                                    brakePipeChargeRate = 10000000.0;
                                }
                                break;

                            case "servicerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakePipeServiceRate) | brakePipeServiceRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid brake pipe service rate defined for Car " + Car + " in XML file " + fileName);
                                    brakePipeServiceRate = 1500000.0;
                                }
                                break;

                            case "emergencyrate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakePipeEmergencyRate) | brakePipeEmergencyRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid brake pipe emergency rate defined for Car " + Car + " in XML file " + fileName);
                                    brakePipeEmergencyRate = 400000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "straightairpipe":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "servicerate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out straightAirPipeServiceRate) | straightAirPipeServiceRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid straight air pipe service rate defined for Car " + Car + " in XML file " + fileName);
                                    straightAirPipeServiceRate = 300000.0;
                                }
                                break;

                            case "emergencyrate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out straightAirPipeEmergencyRate) | straightAirPipeEmergencyRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid straight air pipe emergency rate defined for Car " + Car + " in XML file " + fileName);
                                    straightAirPipeEmergencyRate = 400000.0;
                                }
                                break;

                            case "releaserate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out straightAirPipeReleaseRate) | straightAirPipeReleaseRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid straight air pipe emergency rate defined for Car " + Car + " in XML file " + fileName);
                                    straightAirPipeReleaseRate = 200000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;

                case "brakecylinder":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "servicemaximumpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakeCylinderServiceMaximumPressure) | brakeCylinderServiceMaximumPressure <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid brake cylinder service pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakeCylinderServiceMaximumPressure = 440000.0;
                                }
                                break;

                            case "emergencymaximumpressure":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakeCylinderEmergencyMaximumPressure) | brakeCylinderEmergencyMaximumPressure <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid brake cylinder emergency pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakeCylinderEmergencyMaximumPressure = 440000.0;
                                }
                                break;

                            case "emergencyrate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakeCylinderEmergencyRate) | brakeCylinderEmergencyRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid brake cylinder emergency pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakeCylinderEmergencyRate = 300000.0;
                                }
                                break;

                            case "releaserate":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out brakeCylinderReleaseRate) | brakeCylinderReleaseRate <= 0.0)
                                {
                                    Plugin.currentHost.AddMessage(MessageType.Warning, false, "Invalid brake cylinder emergency pressure defined for Car " + Car + " in XML file " + fileName);
                                    brakeCylinderReleaseRate = 200000.0;
                                }
                                break;
                            }
                        }
                    }
                    break;
                }
            }
            Train.Cars[Car].CarBrake.mainReservoir       = new MainReservoir(compressorMinimumPressure, compressorMaximumPressure, 0.01, (Train.Handles.Brake is AirBrakeHandle ? 0.25 : 0.075) / Train.Cars.Length);
            Train.Cars[Car].CarBrake.airCompressor       = new Compressor(compressorRate, Train.Cars[Car].CarBrake.mainReservoir, Train.Cars[Car]);
            Train.Cars[Car].CarBrake.equalizingReservoir = new EqualizingReservoir(equalizingReservoirServiceRate, equalizingReservoirEmergencyRate, equalizingReservoirChargeRate);
            Train.Cars[Car].CarBrake.equalizingReservoir.NormalPressure = 1.005 * brakePipeNormalPressure;

            Train.Cars[Car].CarBrake.brakePipe = new BrakePipe(brakePipeNormalPressure, brakePipeChargeRate, brakePipeServiceRate, brakePipeEmergencyRate, Train.Cars[0].CarBrake is ElectricCommandBrake);
            {
                double r = 200000.0 / brakeCylinderEmergencyMaximumPressure - 1.0;
                if (r < 0.1)
                {
                    r = 0.1;
                }
                if (r > 1.0)
                {
                    r = 1.0;
                }
                Train.Cars[Car].CarBrake.auxiliaryReservoir = new AuxiliaryReservoir(0.975 * brakePipeNormalPressure, auxiliaryReservoirChargeRate, 0.5, r);
            }
            Train.Cars[Car].CarBrake.brakeCylinder   = new BrakeCylinder(brakeCylinderServiceMaximumPressure, brakeCylinderEmergencyMaximumPressure, Train.Handles.Brake is AirBrakeHandle ? brakeCylinderEmergencyRate : 0.3 * brakeCylinderEmergencyRate, brakeCylinderEmergencyRate, brakeCylinderReleaseRate);
            Train.Cars[Car].CarBrake.straightAirPipe = new StraightAirPipe(straightAirPipeServiceRate, straightAirPipeEmergencyRate, straightAirPipeReleaseRate);
        }
Exemple #11
0
        private void ParseOptionCommand(OptionsCommand Command, string[] Arguments, double[] UnitOfLength, Expression Expression, ref RouteData Data, bool PreviewOnly)
        {
            switch (Command)
            {
            case OptionsCommand.BlockLength:
            {
                double length = 25.0;
                if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[0], UnitOfLength, out length))
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Length is invalid in Options.BlockLength at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    length = 25.0;
                }

                Data.BlockInterval = length;
            }
            break;

            case OptionsCommand.XParser:
                if (!PreviewOnly)
                {
                    int parser = 0;
                    if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out parser) | parser < 0 | parser > 3)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "XParser is invalid in Options.XParser at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        for (int i = 0; i < Plugin.CurrentHost.Plugins.Length; i++)
                        {
                            if (Plugin.CurrentHost.Plugins[i].Object != null)
                            {
                                Plugin.CurrentHost.Plugins[i].Object.SetObjectParser((XParsers)parser);                                          //Remember that this will be ignored if not the X plugin!
                            }
                        }
                    }
                }

                break;

            case OptionsCommand.ObjParser:
                if (!PreviewOnly)
                {
                    int parser = 0;
                    if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseIntVb6(Arguments[0], out parser) | parser < 0 | parser > 2)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "ObjParser is invalid in Options.ObjParser at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        for (int i = 0; i < Plugin.CurrentHost.Plugins.Length; i++)
                        {
                            if (Plugin.CurrentHost.Plugins[i].Object != null)
                            {
                                Plugin.CurrentHost.Plugins[i].Object.SetObjectParser((ObjParsers)parser);                                          //Remember that this will be ignored if not the Obj plugin!
                            }
                        }
                    }
                }

                break;

            case OptionsCommand.UnitOfLength:
            case OptionsCommand.UnitOfSpeed:
            case OptionsCommand.ObjectVisibility:
                break;

            case OptionsCommand.SectionBehavior:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    int a;
                    if (!NumberFormats.TryParseIntVb6(Arguments[0], out a))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a != 0 & a != 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        Data.ValueBasedSections = a == 1;
                    }
                }

                break;

            case OptionsCommand.CantBehavior:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    int a;
                    if (!NumberFormats.TryParseIntVb6(Arguments[0], out a))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a != 0 & a != 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        Data.SignedCant = a == 1;
                    }
                }

                break;

            case OptionsCommand.FogBehavior:
                if (Arguments.Length < 1)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, Command + " is expected to have one argument at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                }
                else
                {
                    int a;
                    if (!NumberFormats.TryParseIntVb6(Arguments[0], out a))
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Mode is invalid in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else if (a != 0 & a != 1)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Mode is expected to be either 0 or 1 in " + Command + " at line " + Expression.Line.ToString(Culture) + ", column " + Expression.Column.ToString(Culture) + " in file " + Expression.File);
                    }
                    else
                    {
                        Data.FogTransitionMode = a == 1;
                    }
                }
                break;
            }
        }
Exemple #12
0
        /// <summary>Parses a single XML node into a car sound</summary>
        /// <param name="node">The node to parse</param>
        /// <param name="Sound">The car sound</param>
        /// <param name="Position">The default position of this sound (May be overriden by the node)</param>
        /// <param name="Radius">The default radius of this sound (May be overriden by the node)</param>
        private static void ParseNode(XmlNode node, out CarSound Sound, Vector3 Position, double Radius)
        {
            string fileName = null;

            foreach (XmlNode c in node.ChildNodes)
            {
                switch (c.Name.ToLowerInvariant())
                {
                case "filename":
                    try
                    {
                        fileName = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);

                        if (!File.Exists(fileName))
                        {
                            //Valid path, but the file does not exist
                            Sound = new CarSound();
                            return;
                        }
                    }
                    catch
                    {
                        //Probably invalid filename characters
                        Sound = new CarSound();
                        return;
                    }
                    break;

                case "position":
                    string[] Arguments = c.InnerText.Split(',');
                    double   x = 0.0, y = 0.0, z = 0.0;

                    if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[0], out x))
                    {
                        x = 0.0;
                    }

                    if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[1], out y))
                    {
                        y = 0.0;
                    }

                    if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[2], out z))
                    {
                        z = 0.0;
                    }

                    Position = new Vector3(x, y, z);
                    break;

                case "radius":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Radius))
                    {
                    }
                    break;
                }
            }

            if (fileName == null)
            {
                //No valid filename node specified
                Sound = new CarSound();
                return;
            }

            Sound = new CarSound(Program.Sounds.RegisterBuffer(fileName, Radius), Position);
        }
Exemple #13
0
        private static void ParseCarNode(XmlNode Node, string fileName, int Car, ref TrainManager.Train Train, ref ObjectManager.UnifiedObject[] CarObjects, ref ObjectManager.UnifiedObject[] BogieObjects)
        {
            double driverZ      = 0.0;
            string interiorFile = string.Empty;

            foreach (XmlNode c in Node.ChildNodes)
            {
                //Note: Don't use the short-circuiting operator, as otherwise we need another if
                switch (c.Name.ToLowerInvariant())
                {
                case "length":
                    double l;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out l) | l <= 0.0)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid length defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Length = l;
                    break;

                case "width":
                    double w;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out w) | w <= 0.0)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid width defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Width = w;
                    break;

                case "height":
                    double h;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out h) | h <= 0.0)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid height defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Height = h;
                    break;

                case "motorcar":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        Train.Cars[Car].Specs.IsMotorCar = true;
                    }
                    else
                    {
                        Train.Cars[Car].Specs.IsMotorCar = false;
                    }
                    break;

                case "mass":
                    double m;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out m) | m <= 0.0)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid mass defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Specs.MassEmpty   = m;
                    Train.Cars[Car].Specs.MassCurrent = m;
                    break;

                case "frontaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].FrontAxle.Position))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid front axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "rearaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].RearAxle.Position))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid rear axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "object":
                    string f = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (System.IO.File.Exists(f))
                    {
                        CarObjects[Car] = ObjectManager.LoadObject(f, System.Text.Encoding.Default, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                    }
                    break;

                case "reversed":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        CarObjectsReversed[Car] = true;
                    }
                    break;

                case "frontbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid front bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid front bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    BogieObjects[Car * 2] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                }
                                break;

                            case "reversed":
                                BogieObjectsReversed[Car * 2] = true;
                                break;
                            }
                        }
                    }
                    break;

                case "rearbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid rear bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(Interface.MessageType.Warning, false, "Invalid rear bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    BogieObjects[Car * 2 + 1] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, ObjectManager.ObjectLoadMode.Normal, false, false, false);
                                }
                                break;

                            case "reversed":
                                BogieObjectsReversed[Car * 2 + 1] = true;
                                break;
                            }
                        }
                    }
                    break;

                case "driverposition":
                    string[] splitText = c.InnerText.Split(',');
                    if (splitText.Length != 3)
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Driver position must have three arguments for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Driver = new Vector3();
                    if (!NumberFormats.TryParseDoubleVb6(splitText[0], out Train.Cars[Car].Driver.X))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[1], out Train.Cars[Car].Driver.Y))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Driver position Y was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[2], out driverZ))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    Train.Cars[Car].Driver.Z = 0.5 * Train.Cars[Car].Length + driverZ;
                    break;

                case "interiorview":
                    if (Train != TrainManager.PlayerTrain)
                    {
                        break;
                    }
                    Train.Cars[Car].HasInteriorView = true;
                    if (Car != Train.DriverCar)
                    {
                        Train.Cars[Car].CarSections             = new TrainManager.CarSection[1];
                        Train.Cars[Car].CarSections[0]          = new TrainManager.CarSection();
                        Train.Cars[Car].CarSections[0].Elements = new ObjectManager.AnimatedObject[] { };
                        Train.Cars[Car].CarSections[0].Overlay  = true;
                    }
                    string cv = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (!System.IO.File.Exists(cv))
                    {
                        Interface.AddMessage(Interface.MessageType.Warning, false, "Interior view file was invalid for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    interiorFile = cv;
                    break;
                }
            }
            //Driver position is measured from the front of the car
            //As there is no set order, this needs to be done after the loop
            if (interiorFile != String.Empty)
            {
                if (interiorFile.ToLowerInvariant().EndsWith(".cfg"))
                {
                    //Only supports panel2.cfg format
                    Panel2CfgParser.ParsePanel2Config(System.IO.Path.GetFileName(interiorFile), System.IO.Path.GetDirectoryName(interiorFile), Encoding.UTF8, Train, Car);
                    Train.Cars[Car].CameraRestrictionMode = World.CameraRestrictionMode.On;
                }
                else if (interiorFile.ToLowerInvariant().EndsWith(".animated"))
                {
                    ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(interiorFile, Encoding.UTF8, ObjectManager.ObjectLoadMode.DontAllowUnloadOfTextures);
                    try
                    {
                        for (int i = 0; i < a.Objects.Length; i++)
                        {
                            a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                        }
                        Train.Cars[Car].CarSections[0].Elements = a.Objects;
                        Train.Cars[Car].CameraRestrictionMode   = World.CameraRestrictionMode.NotAvailable;
                    }
                    catch
                    {
                        Program.RestartArguments = " ";
                        Loading.Cancel           = true;
                    }
                }
                else
                {
                    Interface.AddMessage(Interface.MessageType.Warning, false, "Interior view file is not supported for Car " + Car + " in XML file " + fileName);
                }
            }
        }
Exemple #14
0
        /// <summary>
        /// Function to parse the contents of TravelData class
        /// </summary>
        /// <param name="FileName">The filename of the containing XML file</param>
        /// <param name="SectionElement">The XElement to parse</param>
        /// <param name="Data">Travel data to which the parse results apply</param>
        private static void ParseTravelDataNode(string FileName, XElement SectionElement, TravelData Data)
        {
            string Section = SectionElement.Name.LocalName;

            double Decelerate     = 0.0;
            double Accelerate     = 0.0;
            double TargetSpeed    = 0.0;
            bool   targetSpeedSet = false;

            foreach (XElement KeyNode in SectionElement.Elements())
            {
                string Key        = KeyNode.Name.LocalName;
                string Value      = KeyNode.Value;
                int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                switch (Key.ToLowerInvariant())
                {
                case "decelerate":
                    if (Value.Any() && !NumberFormats.TryParseDoubleVb6(Value, out Decelerate) || Decelerate < 0.0)
                    {
                        Interface.AddMessage(MessageType.Error, false, $"Value is expected to be a non-negative floating-point number in {Key} in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                    }
                    break;

                case "position":
                case "stopposition":
                    if (Value.Any() && !NumberFormats.TryParseDoubleVb6(Value, out Data.Position))
                    {
                        Interface.AddMessage(MessageType.Error, false, $"Value is invalid in {Key} in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                    }
                    break;

                case "accelerate":
                    if (Value.Any() && !NumberFormats.TryParseDoubleVb6(Value, out Accelerate) || Accelerate < 0.0)
                    {
                        Interface.AddMessage(MessageType.Error, false, $"Value is expected to be a non-negative floating-point number in {Key} in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                    }
                    break;

                case "targetspeed":
                    if (Value.Any() && !NumberFormats.TryParseDoubleVb6(Value, out TargetSpeed) || TargetSpeed < 0.0)
                    {
                        Interface.AddMessage(MessageType.Error, false, $"Value is expected to be a non-negative floating-point number in {Key} in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                    }
                    targetSpeedSet = true;
                    break;

                case "rail":
                    if (Value.Any() && !NumberFormats.TryParseIntVb6(Value, out Data.RailIndex) || Data.RailIndex < 0)
                    {
                        Interface.AddMessage(MessageType.Error, false, $"Value is expected to be a non-negative integer number in {Key} in {Section} at line {LineNumber.ToString(culture)} in {FileName}");
                        Data.RailIndex = 0;
                    }
                    break;
                }
            }

            if (!targetSpeedSet)
            {
                Interface.AddMessage(MessageType.Warning, false, $"A TargetSpeed was not set in {Section}. This may cause unexpected results.");
            }
            Data.Decelerate  = -Decelerate / 3.6;
            Data.Accelerate  = Accelerate / 3.6;
            Data.TargetSpeed = TargetSpeed / 3.6;
        }
Exemple #15
0
        /// <summary>Parses a train travel stop node</summary>
        /// <param name="Element">The XElement to parse</param>
        /// <param name="FileName">The filename of the containing XML file</param>
        /// <param name="Data">The list of travel data to add this to</param>
        private static void ParseStopNode(XElement Element, string FileName, List <Game.TravelData> Data)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;

            foreach (XElement SectionElement in Element.Elements())
            {
                string Section = SectionElement.Name.LocalName;

                switch (SectionElement.Name.LocalName.ToLowerInvariant())
                {
                case "stop":
                {
                    Game.TravelData NewData     = new Game.TravelData();
                    double          Decelerate  = 0.0;
                    double          Accelerate  = 0.0;
                    double          TargetSpeed = 0.0;

                    foreach (XElement KeyNode in SectionElement.Elements())
                    {
                        string Key        = KeyNode.Name.LocalName;
                        string Value      = KeyNode.Value;
                        int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                        switch (Key.ToLowerInvariant())
                        {
                        case "decelerate":
                            if (Value.Length != 0 && !NumberFormats.TryParseDoubleVb6(Value, out Decelerate))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;

                        case "stopposition":
                            if (Value.Length != 0 && !NumberFormats.TryParseDoubleVb6(Value, out NewData.StopPosition))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;

                        case "stoptime":
                            if (Value.Length != 0 && !Interface.TryParseTime(Value, out NewData.StopTime))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;

                        case "doors":
                        {
                            int  door     = 0;
                            bool doorboth = false;

                            switch (Value.ToLowerInvariant())
                            {
                            case "l":
                            case "left":
                                door = -1;
                                break;

                            case "r":
                            case "right":
                                door = 1;
                                break;

                            case "n":
                            case "none":
                            case "neither":
                                door = 0;
                                break;

                            case "b":
                            case "both":
                                doorboth = true;
                                break;

                            default:
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out door))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                    door = 0;
                                }
                                break;
                            }

                            NewData.OpenLeftDoors  = door < 0.0 | doorboth;
                            NewData.OpenRightDoors = door > 0.0 | doorboth;
                        }
                        break;

                        case "accelerate":
                            if (Value.Length != 0 && !NumberFormats.TryParseDoubleVb6(Value, out Accelerate))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;

                        case "targetspeed":
                            if (Value.Length != 0 && !NumberFormats.TryParseDoubleVb6(Value, out TargetSpeed))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;

                        case "direction":
                        {
                            int d = 0;
                            switch (Value.ToLowerInvariant())
                            {
                            case "f":
                                d = 1;
                                break;

                            case "r":
                                d = -1;
                                break;

                            default:
                                if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out d))
                                {
                                    Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                                }
                                break;
                            }
                            if (d == 1 || d == -1)
                            {
                                NewData.Direction = (Game.TravelDirection)d;
                            }
                        }
                        break;

                        case "rail":
                            if (Value.Length != 0 && !NumberFormats.TryParseIntVb6(Value, out NewData.RailIndex))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;
                        }
                    }

                    NewData.Decelerate  = Decelerate / 3.6;
                    NewData.Accelerate  = Accelerate / 3.6;
                    NewData.TargetSpeed = TargetSpeed / 3.6;
                    Data.Add(NewData);
                }
                break;
                }
            }
        }
Exemple #16
0
        /// <summary>Separates an expression into it's consituent command and arguments</summary>
        /// <param name="Command">The command</param>
        /// <param name="ArgumentSequence">The sequence of arguments contained within the expression</param>
        /// <param name="Culture">The current culture</param>
        /// <param name="RaiseErrors">Whether errors should be raised at this point</param>
        /// <param name="IsRw">Whether this is a RW format file</param>
        /// <param name="CurrentSection">The current section being processed</param>
        internal void SeparateCommandsAndArguments(out string Command, out string ArgumentSequence, System.Globalization.CultureInfo Culture, bool RaiseErrors, bool IsRw, string CurrentSection)
        {
            bool openingerror = false, closingerror = false;
            int  i, firstClosingBracket = 0;

            if (Plugin.CurrentOptions.EnableBveTsHacks)
            {
                if (Text.StartsWith("Train. ", StringComparison.InvariantCultureIgnoreCase))
                {
                    //HACK: Some Chinese routes seem to have used a space between Train. and the rest of the command
                    //e.g. Taipei Metro. BVE4/ 2 accept this......
                    Text = "Train." + Text.Substring(7, Text.Length - 7);
                }
                else if (Text.StartsWith("Texture. Background", StringComparison.InvariantCultureIgnoreCase))
                {
                    //Same hack as above, found in Minobu route for BVE2
                    Text = "Texture.Background" + Text.Substring(19, Text.Length - 19);
                }
                else if (Text.EndsWith(")height(0)", StringComparison.InvariantCultureIgnoreCase))
                {
                    //Heavy Coal original RW- Fix starting station
                    Text = Text.Substring(0, Text.Length - 9);
                }

                if (IsRw && CurrentSection.ToLowerInvariant() == "track")
                {
                    //Removes misplaced track position indicies from the end of a command in the Track section
                    int idx = Text.LastIndexOf(')');
                    if (idx != -1 && idx != Text.Length)
                    {
                        // ReSharper disable once NotAccessedVariable
                        double d;
                        string s = this.Text.Substring(idx + 1, this.Text.Length - idx - 1).Trim(new char[] { });
                        if (NumberFormats.TryParseDoubleVb6(s, out d))
                        {
                            this.Text = this.Text.Substring(0, idx).Trim(new char[] { });
                        }
                    }
                }

                if (IsRw && this.Text.EndsWith("))"))
                {
                    int openingBrackets = Text.Count(x => x == '(');
                    int closingBrackets = Text.Count(x => x == ')');
                    //Remove obviously wrong double-ending brackets
                    if (closingBrackets == openingBrackets + 1 && this.Text.EndsWith("))"))
                    {
                        this.Text = this.Text.Substring(0, this.Text.Length - 1);
                    }
                }

                if (Text.StartsWith("route.comment", StringComparison.InvariantCultureIgnoreCase) && Text.IndexOf("(C)", StringComparison.InvariantCultureIgnoreCase) != -1)
                {
                    //Some BVE4 routes use this instead of the copyright symbol
                    Text = Text.Replace("(C)", "©");
                    Text = Text.Replace("(c)", "©");
                }
            }

            for (i = 0; i < Text.Length; i++)
            {
                if (Text[i] == '(')
                {
                    bool found       = false;
                    bool stationName = false;
                    bool replaced    = false;
                    i++;
                    while (i < Text.Length)
                    {
                        if (Text[i] == ',' || Text[i] == ';')
                        {
                            //Only check parenthesis in the station name field- The comma and semi-colon are the argument separators
                            stationName = true;
                        }

                        if (Text[i] == '(')
                        {
                            if (RaiseErrors & !openingerror)
                            {
                                if (stationName)
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Invalid opening parenthesis encountered at line " + Line.ToString(Culture) + ", column " +
                                                                  Column.ToString(Culture) + " in file " + File);
                                    openingerror = true;
                                }
                                else
                                {
                                    Text     = Text.Remove(i, 1).Insert(i, "[");
                                    replaced = true;
                                }
                            }
                        }
                        else if (Text[i] == ')')
                        {
                            if (stationName == false && i != Text.Length && replaced)
                            {
                                Text = Text.Remove(i, 1).Insert(i, "]");
                                continue;
                            }

                            found = true;
                            firstClosingBracket = i;
                            break;
                        }

                        i++;
                    }

                    if (!found)
                    {
                        if (RaiseErrors & !closingerror)
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Missing closing parenthesis encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                            closingerror = true;
                        }

                        Text += ")";
                    }
                }
                else if (Text[i] == ')')
                {
                    if (RaiseErrors & !closingerror)
                    {
                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Invalid closing parenthesis encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                        closingerror = true;
                    }
                }
                else if (char.IsWhiteSpace(Text[i]))
                {
                    if (i >= Text.Length - 1 || !char.IsWhiteSpace(Text[i + 1]))
                    {
                        break;
                    }
                }
            }

            if (firstClosingBracket != 0 && firstClosingBracket < Text.Length - 1)
            {
                if (!Char.IsWhiteSpace(Text[firstClosingBracket + 1]) && Text[firstClosingBracket + 1] != '.' && Text[firstClosingBracket + 1] != ';')
                {
                    Text = Text.Insert(firstClosingBracket + 1, " ");
                    i    = firstClosingBracket;
                }
            }

            if (i < Text.Length)
            {
                // white space was found outside of parentheses
                string a = Text.Substring(0, i);
                if (a.IndexOf('(') >= 0 & a.IndexOf(')') >= 0)
                {
                    // indices found not separated from the command by spaces
                    Command          = Text.Substring(0, i).TrimEnd(new char[] { });
                    ArgumentSequence = Text.Substring(i + 1).TrimStart(new char[] { });
                    if (ArgumentSequence.StartsWith("(") & ArgumentSequence.EndsWith(")"))
                    {
                        // arguments are enclosed by parentheses
                        ArgumentSequence = ArgumentSequence.Substring(1, ArgumentSequence.Length - 2).Trim(new char[] { });
                    }
                    else if (ArgumentSequence.StartsWith("("))
                    {
                        // only opening parenthesis found
                        if (RaiseErrors & !closingerror)
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Missing closing parenthesis encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                        }

                        ArgumentSequence = ArgumentSequence.Substring(1).TrimStart(new char[] { });
                    }
                }
                else
                {
                    // no indices found before the space
                    if (i < Text.Length - 1 && Text[i + 1] == '(')
                    {
                        // opening parenthesis follows the space
                        int j = Text.IndexOf(')', i + 1);
                        if (j > i + 1)
                        {
                            // closing parenthesis found
                            if (j == Text.Length - 1)
                            {
                                // only closing parenthesis found at the end of the expression
                                Command          = Text.Substring(0, i).TrimEnd(new char[] { });
                                ArgumentSequence = Text.Substring(i + 2, j - i - 2).Trim(new char[] { });
                            }
                            else
                            {
                                // detect border between indices and arguments
                                bool found = false;
                                Command          = null;
                                ArgumentSequence = null;
                                for (int k = j + 1; k < Text.Length; k++)
                                {
                                    if (char.IsWhiteSpace(Text[k]))
                                    {
                                        Command          = Text.Substring(0, k).TrimEnd(new char[] { });
                                        ArgumentSequence = Text.Substring(k + 1).TrimStart(new char[] { });
                                        found            = true;
                                        break;
                                    }

                                    if (Text[k] == '(')
                                    {
                                        Command          = Text.Substring(0, k).TrimEnd(new char[] { });
                                        ArgumentSequence = Text.Substring(k).TrimStart(new char[] { });
                                        found            = true;
                                        break;
                                    }
                                }

                                if (!found)
                                {
                                    if (RaiseErrors & !openingerror & !closingerror)
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Invalid syntax encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                                        closingerror = true;
                                    }

                                    Command          = Text;
                                    ArgumentSequence = "";
                                }

                                if (ArgumentSequence.StartsWith("(") & ArgumentSequence.EndsWith(")"))
                                {
                                    // arguments are enclosed by parentheses
                                    ArgumentSequence = ArgumentSequence.Substring(1, ArgumentSequence.Length - 2).Trim(new char[] { });
                                }
                                else if (ArgumentSequence.StartsWith("("))
                                {
                                    // only opening parenthesis found
                                    if (RaiseErrors & !closingerror)
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Missing closing parenthesis encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                                    }

                                    ArgumentSequence = ArgumentSequence.Substring(1).TrimStart(new char[] { });
                                }
                            }
                        }
                        else
                        {
                            // no closing parenthesis found
                            if (RaiseErrors & !closingerror)
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Missing closing parenthesis encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                            }

                            Command          = Text.Substring(0, i).TrimEnd(new char[] { });
                            ArgumentSequence = Text.Substring(i + 2).TrimStart(new char[] { });
                        }
                    }
                    else
                    {
                        // no index possible
                        Command          = Text.Substring(0, i).TrimEnd(new char[] { });
                        ArgumentSequence = Text.Substring(i + 1).TrimStart(new char[] { });
                        if (ArgumentSequence.StartsWith("(") & ArgumentSequence.EndsWith(")"))
                        {
                            // arguments are enclosed by parentheses
                            ArgumentSequence = ArgumentSequence.Substring(1, ArgumentSequence.Length - 2).Trim(new char[] { });
                        }
                        else if (ArgumentSequence.StartsWith("("))
                        {
                            // only opening parenthesis found
                            if (RaiseErrors & !closingerror)
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Missing closing parenthesis encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                            }

                            ArgumentSequence = ArgumentSequence.Substring(1).TrimStart(new char[] { });
                        }
                    }
                }
            }
            else
            {
                // no single space found
                if (Text.EndsWith(")"))
                {
                    i = Text.LastIndexOf('(');
                    if (i >= 0)
                    {
                        Command          = Text.Substring(0, i).TrimEnd(new char[] { });
                        ArgumentSequence = Text.Substring(i + 1, Text.Length - i - 2).Trim(new char[] { });
                    }
                    else
                    {
                        Command          = Text;
                        ArgumentSequence = "";
                    }
                }
                else
                {
                    i = Text.IndexOf('(');
                    if (i >= 0)
                    {
                        if (RaiseErrors & !closingerror)
                        {
                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Missing closing parenthesis encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                        }

                        Command          = Text.Substring(0, i).TrimEnd(new char[] { });
                        ArgumentSequence = Text.Substring(i + 1).TrimStart(new char[] { });
                    }
                    else
                    {
                        if (RaiseErrors)
                        {
                            i = Text.IndexOf(')');
                            if (i >= 0 & !closingerror)
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Invalid closing parenthesis encountered at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                            }
                        }

                        Command          = Text;
                        ArgumentSequence = "";
                    }
                }
            }

            // invalid trailing characters
            if (Command.EndsWith(";"))
            {
                if (RaiseErrors)
                {
                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Invalid trailing semicolon encountered in " + Command + " at line " + Line.ToString(Culture) + ", column " + Column.ToString(Culture) + " in file " + File);
                }

                while (Command.EndsWith(";"))
                {
                    Command = Command.Substring(0, Command.Length - 1);
                }
            }
        }
Exemple #17
0
        /// <summary>Parses a base track following object node</summary>
        /// <param name="Element">The XElement to parse</param>
        /// <param name="FileName">The filename of the containing XML file</param>
        /// <param name="Path">The path of the containing XML file</param>
        /// <param name="Train">The track following object to parse this node into</param>
        private static void ParseTrackFollowingObjectNode(XElement Element, string FileName, string Path, string ObjectPath, TrainManager.TrackFollowingObject Train)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            string TrainDirectory       = string.Empty;
            bool   consistReversed      = false;
            List <Game.TravelData> Data = new List <Game.TravelData>();

            foreach (XElement SectionElement in Element.Elements())
            {
                string Section = SectionElement.Name.LocalName;

                switch (SectionElement.Name.LocalName.ToLowerInvariant())
                {
                case "stops":
                    ParseStopNode(SectionElement, FileName, Data);
                    break;

                case "train":
                    foreach (XElement KeyNode in SectionElement.Elements())
                    {
                        string Key        = KeyNode.Name.LocalName;
                        string Value      = KeyNode.Value;
                        int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                        switch (Key.ToLowerInvariant())
                        {
                        case "directory":
                        {
                            string trainDirectory = OpenBveApi.Path.CombineDirectory(Path, Value);
                            if (!System.IO.Directory.Exists(trainDirectory))
                            {
                                trainDirectory = OpenBveApi.Path.CombineFile(Program.FileSystem.InitialTrainFolder, Value);
                            }
                            if (!System.IO.Directory.Exists(trainDirectory))
                            {
                                trainDirectory = OpenBveApi.Path.CombineFile(Program.FileSystem.TrainInstallationDirectory, Value);
                            }
                            if (!System.IO.Directory.Exists(trainDirectory))
                            {
                                trainDirectory = OpenBveApi.Path.CombineFile(ObjectPath, Value);
                            }

                            if (!System.IO.Directory.Exists(trainDirectory))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Directory was not found in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            else
                            {
                                TrainDirectory = trainDirectory;
                            }
                        }
                        break;

                        case "reversed":
                            int n;
                            NumberFormats.TryParseIntVb6(Value, out n);
                            if (n == 1 || Value.ToLowerInvariant() == "true")
                            {
                                consistReversed = true;
                            }
                            break;
                        }
                    }
                    break;

                case "definition":
                    foreach (XElement KeyNode in SectionElement.Elements())
                    {
                        string Key        = KeyNode.Name.LocalName;
                        string Value      = KeyNode.Value;
                        int    LineNumber = ((IXmlLineInfo)KeyNode).LineNumber;

                        switch (Key.ToLowerInvariant())
                        {
                        case "appearancetime":
                            if (Value.Length != 0 && !Interface.TryParseTime(Value, out Train.AppearanceTime))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;

                        case "appearancestartposition":
                            if (Value.Length != 0 && !NumberFormats.TryParseDoubleVb6(Value, out Train.AppearanceStartPosition))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;

                        case "appearanceendposition":
                            if (Value.Length != 0 && !NumberFormats.TryParseDoubleVb6(Value, out Train.AppearanceEndPosition))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;

                        case "leavetime":
                            if (Value.Length != 0 && !Interface.TryParseTime(Value, out Train.LeaveTime))
                            {
                                Interface.AddMessage(MessageType.Error, false, "Value is invalid in " + Key + " in " + Section + " at line " + LineNumber.ToString(Culture) + " in " + FileName);
                            }
                            break;
                        }
                    }
                    break;
                }
            }

            if (!Data.Any() || string.IsNullOrEmpty(TrainDirectory))
            {
                return;
            }

            /*
             * First check for a train.ai file- Functionally identical, but allows for differently configured AI
             * trains not to show up as driveable
             */
            string TrainData = OpenBveApi.Path.CombineFile(TrainDirectory, "train.ai");

            if (!System.IO.File.Exists(TrainData))
            {
                // Check for the standard driveable train.dat
                TrainData = OpenBveApi.Path.CombineFile(TrainDirectory, "train.dat");
            }
            string ExteriorFile = OpenBveApi.Path.CombineFile(TrainDirectory, "extensions.cfg");

            if (!System.IO.File.Exists(TrainData) || !System.IO.File.Exists(ExteriorFile))
            {
                Interface.AddMessage(MessageType.Error, true, "The supplied train folder in TrackFollowingObject " + FileName + " did not contain a complete set of data.");
                return;
            }
            TrainDatParser.ParseTrainData(TrainData, TextEncoding.GetSystemEncodingFromFile(TrainData), Train);
            SoundCfgParser.ParseSoundConfig(TrainDirectory, Train);
            Train.AI = new Game.TrackFollowingObjectAI(Train, Data);

            UnifiedObject[] CarObjects     = new UnifiedObject[Train.Cars.Length];
            UnifiedObject[] BogieObjects   = new UnifiedObject[Train.Cars.Length * 2];
            UnifiedObject[] CouplerObjects = new UnifiedObject[Train.Cars.Length - 1];
            ExtensionsCfgParser.ParseExtensionsConfig(System.IO.Path.GetDirectoryName(ExteriorFile), TextEncoding.GetSystemEncodingFromFile(ExteriorFile), ref CarObjects, ref BogieObjects, ref CouplerObjects, Train, true);

            int currentBogieObject = 0;

            for (int i = 0; i < Train.Cars.Length; i++)
            {
                if (CarObjects[i] == null)
                {
                    // load default exterior object
                    string       file = OpenBveApi.Path.CombineFile(Program.FileSystem.GetDataFolder("Compatibility"), "exterior.csv");
                    StaticObject so   = ObjectManager.LoadStaticObject(file, System.Text.Encoding.UTF8, false);
                    if (so == null)
                    {
                        CarObjects[i] = null;
                    }
                    else
                    {
                        double sx = Train.Cars[i].Width;
                        double sy = Train.Cars[i].Height;
                        double sz = Train.Cars[i].Length;
                        so.ApplyScale(sx, sy, sz);
                        CarObjects[i] = so;
                    }
                }
                if (CarObjects[i] != null)
                {
                    // add object
                    Train.Cars[i].LoadCarSections(CarObjects[i]);
                }

                //Load bogie objects
                if (BogieObjects[currentBogieObject] != null)
                {
                    Train.Cars[i].FrontBogie.LoadCarSections(BogieObjects[currentBogieObject]);
                }
                currentBogieObject++;
                if (BogieObjects[currentBogieObject] != null)
                {
                    Train.Cars[i].RearBogie.LoadCarSections(BogieObjects[currentBogieObject]);
                }
                currentBogieObject++;
            }

            // door open/close speed
            foreach (var Car in Train.Cars)
            {
                if (Car.Specs.DoorOpenFrequency <= 0.0)
                {
                    if (Car.Doors[0].OpenSound.Buffer != null & Car.Doors[1].OpenSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        Program.Sounds.LoadBuffer(Car.Doors[1].OpenSound.Buffer);
                        double a = Car.Doors[0].OpenSound.Buffer.Duration;
                        double b = Car.Doors[1].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                    }
                    else if (Car.Doors[0].OpenSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        double a = Car.Doors[0].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = a > 0.0 ? 1.0 / a : 0.8;
                    }
                    else if (Car.Doors[1].OpenSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].OpenSound.Buffer);
                        double b = Car.Doors[1].OpenSound.Buffer.Duration;
                        Car.Specs.DoorOpenFrequency = b > 0.0 ? 1.0 / b : 0.8;
                    }
                    else
                    {
                        Car.Specs.DoorOpenFrequency = 0.8;
                    }
                }
                if (Car.Specs.DoorCloseFrequency <= 0.0)
                {
                    if (Car.Doors[0].CloseSound.Buffer != null & Car.Doors[1].CloseSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        Program.Sounds.LoadBuffer(Car.Doors[1].CloseSound.Buffer);
                        double a = Car.Doors[0].CloseSound.Buffer.Duration;
                        double b = Car.Doors[1].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = a + b > 0.0 ? 2.0 / (a + b) : 0.8;
                    }
                    else if (Car.Doors[0].CloseSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        double a = Car.Doors[0].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = a > 0.0 ? 1.0 / a : 0.8;
                    }
                    else if (Car.Doors[1].CloseSound.Buffer != null)
                    {
                        Program.Sounds.LoadBuffer(Car.Doors[0].CloseSound.Buffer);
                        double b = Car.Doors[1].CloseSound.Buffer.Duration;
                        Car.Specs.DoorCloseFrequency = b > 0.0 ? 1.0 / b : 0.8;
                    }
                    else
                    {
                        Car.Specs.DoorCloseFrequency = 0.8;
                    }
                }
                const double f = 0.015;
                const double g = 2.75;
                Car.Specs.DoorOpenPitch       = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                Car.Specs.DoorClosePitch      = Math.Exp(f * Math.Tan(g * (Program.RandomNumberGenerator.NextDouble() - 0.5)));
                Car.Specs.DoorOpenFrequency  /= Car.Specs.DoorOpenPitch;
                Car.Specs.DoorCloseFrequency /= Car.Specs.DoorClosePitch;

                /*
                 * Remove the following two lines, then the pitch at which doors play
                 * takes their randomized opening and closing times into account.
                 * */
                Car.Specs.DoorOpenPitch  = 1.0;
                Car.Specs.DoorClosePitch = 1.0;
            }

            foreach (var Car in Train.Cars)
            {
                Car.FrontAxle.Follower.TrackIndex            = Data[0].RailIndex;
                Car.RearAxle.Follower.TrackIndex             = Data[0].RailIndex;
                Car.FrontBogie.FrontAxle.Follower.TrackIndex = Data[0].RailIndex;
                Car.FrontBogie.RearAxle.Follower.TrackIndex  = Data[0].RailIndex;
                Car.RearBogie.FrontAxle.Follower.TrackIndex  = Data[0].RailIndex;
                Car.RearBogie.RearAxle.Follower.TrackIndex   = Data[0].RailIndex;
            }

            if (consistReversed)
            {
                Train.Reverse();
            }
            Train.PlaceCars(Data[0].StopPosition);
        }
Exemple #18
0
        internal static void Parse(string fileName, TrainManager.Train Train, ref UnifiedObject[] CarObjects, ref UnifiedObject[] BogieObjects)
        {
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

            //Load the marker's XML file
            currentXML.Load(fileName);
            currentPath = System.IO.Path.GetDirectoryName(fileName);
            if (System.IO.File.Exists(OpenBveApi.Path.CombineFile(currentPath, "train.dat")))
            {
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    if (Train.Cars[i].Specs.IsMotorCar)
                    {
                        AccelerationCurves = new TrainManager.BveAccelerationCurve[Train.Cars[i].Specs.AccelerationCurves.Length];
                        for (int j = 0; j < Train.Cars[i].Specs.AccelerationCurves.Length; j++)
                        {
                            TrainManager.BveAccelerationCurve c = (TrainManager.BveAccelerationCurve)Train.Cars[i].Specs.AccelerationCurves[j];
                            AccelerationCurves[j] = c.Clone(c.Multiplier);
                        }
                    }
                }
            }
            CarObjectsReversed   = new bool[Train.Cars.Length];
            BogieObjectsReversed = new bool[Train.Cars.Length * 2];
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Train/*[self::Car or self::Coupler]");
                if (DocumentNodes == null || DocumentNodes.Count == 0)
                {
                    Interface.AddMessage(MessageType.Error, false, "No car nodes defined in XML file " + fileName);
                    //If we have no appropriate nodes specified, return false and fallback to loading the legacy Sound.cfg file
                    throw new Exception("Empty train.xml file");
                }

                int carIndex = 0;
                //Use the index here for easy access to the car count
                for (int i = 0; i < DocumentNodes.Count; i++)
                {
                    if (carIndex > Train.Cars.Length)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "WARNING: A total of " + DocumentNodes.Count + " cars were specified in XML file " + fileName + " whilst only " + Train.Cars.Length + " were specified in the train.dat file.");
                        break;
                    }
                    if (DocumentNodes[i].ChildNodes.OfType <XmlElement>().Any())
                    {
                        if (DocumentNodes[i].Name == "Car")
                        {
                            ParseCarNode(DocumentNodes[i], fileName, carIndex, ref Train, ref CarObjects, ref BogieObjects);
                        }
                        else
                        {
                            if (carIndex - 1 > Train.Couplers.Length - 1)
                            {
                                Interface.AddMessage(MessageType.Error, false, "Unexpected extra coupler encountered in XML file " + fileName);
                                continue;
                            }
                            foreach (XmlNode c in DocumentNodes[i].ChildNodes)
                            {
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "minimum":
                                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Couplers[carIndex - 1].MinimumDistanceBetweenCars))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "MinimumDistanceBetweenCars is invalid for coupler " + carIndex + "in XML file " + fileName);
                                    }
                                    break;

                                case "maximum":
                                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Couplers[carIndex - 1].MaximumDistanceBetweenCars))
                                    {
                                        Interface.AddMessage(MessageType.Error, false, "MaximumDistanceBetweenCars is invalid for coupler " + carIndex + "in XML file " + fileName);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    else if (!String.IsNullOrEmpty(DocumentNodes[i].InnerText))
                    {
                        try
                        {
                            string      childFile = OpenBveApi.Path.CombineFile(currentPath, DocumentNodes[i].InnerText);
                            XmlDocument childXML  = new XmlDocument();
                            childXML.Load(childFile);
                            XmlNodeList childNodes = childXML.DocumentElement.SelectNodes("/openBVE/Car");
                            //We need to save and restore the current path to make relative paths within the child file work correctly
                            string savedPath = currentPath;
                            currentPath = System.IO.Path.GetDirectoryName(childFile);
                            ParseCarNode(childNodes[0], fileName, i, ref Train, ref CarObjects, ref BogieObjects);
                            currentPath = savedPath;
                        }
                        catch
                        {
                            Interface.AddMessage(MessageType.Error, false, "Failed to load the child Car XML file specified in " + DocumentNodes[i].InnerText);
                        }
                    }
                    if (i == DocumentNodes.Count && carIndex < Train.Cars.Length)
                    {
                        //If this is the case, the number of motor cars is the primary thing which may get confused....
                        //Not a lot to be done about this until a full replacement is built for the train.dat file & we can dump it entirely
                        Interface.AddMessage(MessageType.Warning, false, "WARNING: The number of cars specified in the train.xml file does not match that in the train.dat- Some properties may be invalid.");
                    }
                    if (DocumentNodes[i].Name == "Car")
                    {
                        carIndex++;
                    }
                }
                if (Train.Cars[Train.DriverCar].CameraRestrictionMode != Camera.RestrictionMode.NotSpecified)
                {
                    World.CameraRestriction = Train.Cars[Train.DriverCar].CameraRestrictionMode;
                    World.UpdateViewingDistances();
                }
                DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Train/NotchDescriptions");
                if (DocumentNodes != null && DocumentNodes.Count > 0)
                {
                    //Optional section
                    for (int i = 0; i < DocumentNodes.Count; i++)
                    {
                        if (DocumentNodes[i].ChildNodes.OfType <XmlElement>().Any())
                        {
                            foreach (XmlNode c in DocumentNodes[i].ChildNodes)
                            {
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "power":
                                    Train.PowerNotchDescriptions = c.InnerText.Split(';');
                                    for (int j = 0; j < Train.PowerNotchDescriptions.Length; j++)
                                    {
                                        Size s = Renderer.MeasureString(Fonts.NormalFont, Train.PowerNotchDescriptions[j]);
                                        if (s.Width > Train.MaxPowerNotchWidth)
                                        {
                                            Train.MaxPowerNotchWidth = s.Width;
                                        }
                                    }
                                    break;

                                case "brake":
                                    Train.BrakeNotchDescriptions = c.InnerText.Split(';');
                                    for (int j = 0; j < Train.BrakeNotchDescriptions.Length; j++)
                                    {
                                        Size s = Renderer.MeasureString(Fonts.NormalFont, Train.BrakeNotchDescriptions[j]);
                                        if (s.Width > Train.MaxBrakeNotchWidth)
                                        {
                                            Train.MaxBrakeNotchWidth = s.Width;
                                        }
                                    }
                                    break;

                                case "reverser":
                                    Train.ReverserDescriptions = c.InnerText.Split(';');
                                    for (int j = 0; j < Train.ReverserDescriptions.Length; j++)
                                    {
                                        Size s = Renderer.MeasureString(Fonts.NormalFont, Train.ReverserDescriptions[j]);
                                        if (s.Width > Train.MaxReverserWidth)
                                        {
                                            Train.MaxReverserWidth = s.Width;
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    if (CarObjects[i] != null)
                    {
                        if (CarObjectsReversed[i])
                        {
                            {
                                // reverse axle positions
                                double temp = Train.Cars[i].FrontAxle.Position;
                                Train.Cars[i].FrontAxle.Position = -Train.Cars[i].RearAxle.Position;
                                Train.Cars[i].RearAxle.Position  = -temp;
                            }
                            if (CarObjects[i] is ObjectManager.StaticObject)
                            {
                                ObjectManager.StaticObject obj = (ObjectManager.StaticObject)CarObjects[i];
                                obj.ApplyScale(-1.0, 1.0, -1.0);
                            }
                            else if (CarObjects[i] is ObjectManager.AnimatedObjectCollection)
                            {
                                ObjectManager.AnimatedObjectCollection obj = (ObjectManager.AnimatedObjectCollection)CarObjects[i];
                                for (int j = 0; j < obj.Objects.Length; j++)
                                {
                                    for (int h = 0; h < obj.Objects[j].States.Length; h++)
                                    {
                                        obj.Objects[j].States[h].Object.ApplyScale(-1.0, 1.0, -1.0);
                                        obj.Objects[j].States[h].Position.X *= -1.0;
                                        obj.Objects[j].States[h].Position.Z *= -1.0;
                                    }
                                    obj.Objects[j].TranslateXDirection.X *= -1.0;
                                    obj.Objects[j].TranslateXDirection.Z *= -1.0;
                                    obj.Objects[j].TranslateYDirection.X *= -1.0;
                                    obj.Objects[j].TranslateYDirection.Z *= -1.0;
                                    obj.Objects[j].TranslateZDirection.X *= -1.0;
                                    obj.Objects[j].TranslateZDirection.Z *= -1.0;
                                }
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }
                        }
                    }
                }

                //Check for bogie objects and reverse if necessary.....
                int bogieObjects = 0;
                for (int i = 0; i < Train.Cars.Length * 2; i++)
                {
                    bool IsOdd    = (i % 2 != 0);
                    int  CarIndex = i / 2;
                    if (BogieObjects[i] != null)
                    {
                        bogieObjects++;
                        if (BogieObjectsReversed[i])
                        {
                            {
                                // reverse axle positions
                                if (IsOdd)
                                {
                                    double temp = Train.Cars[CarIndex].FrontBogie.FrontAxle.Position;
                                    Train.Cars[CarIndex].FrontBogie.FrontAxle.Position = -Train.Cars[CarIndex].FrontBogie.RearAxle.Position;
                                    Train.Cars[CarIndex].FrontBogie.RearAxle.Position  = -temp;
                                }
                                else
                                {
                                    double temp = Train.Cars[CarIndex].RearBogie.FrontAxle.Position;
                                    Train.Cars[CarIndex].RearBogie.FrontAxle.Position = -Train.Cars[CarIndex].RearBogie.RearAxle.Position;
                                    Train.Cars[CarIndex].RearBogie.RearAxle.Position  = -temp;
                                }
                            }
                            if (BogieObjects[i] is ObjectManager.StaticObject)
                            {
                                ObjectManager.StaticObject obj = (ObjectManager.StaticObject)BogieObjects[i];
                                obj.ApplyScale(-1.0, 1.0, -1.0);
                            }
                            else if (BogieObjects[i] is ObjectManager.AnimatedObjectCollection)
                            {
                                ObjectManager.AnimatedObjectCollection obj = (ObjectManager.AnimatedObjectCollection)BogieObjects[i];
                                for (int j = 0; j < obj.Objects.Length; j++)
                                {
                                    for (int h = 0; h < obj.Objects[j].States.Length; h++)
                                    {
                                        obj.Objects[j].States[h].Object.ApplyScale(-1.0, 1.0, -1.0);
                                        obj.Objects[j].States[h].Position.X *= -1.0;
                                        obj.Objects[j].States[h].Position.Z *= -1.0;
                                    }
                                    obj.Objects[j].TranslateXDirection.X *= -1.0;
                                    obj.Objects[j].TranslateXDirection.Z *= -1.0;
                                    obj.Objects[j].TranslateYDirection.X *= -1.0;
                                    obj.Objects[j].TranslateYDirection.Z *= -1.0;
                                    obj.Objects[j].TranslateZDirection.X *= -1.0;
                                    obj.Objects[j].TranslateZDirection.Z *= -1.0;
                                }
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }
                        }
                    }
                }
            }
        }
Exemple #19
0
        /// <summary>This function processes the list of expressions for $Char, $Rnd, $If and $Sub directives, and evaluates them into the final expressions dataset</summary>
        private void PreprocessChrRndSub(string FileName, System.Text.Encoding Encoding, ref Expression[] Expressions)
        {
            string[] Subs    = new string[16];
            int      openIfs = 0;

            for (int i = 0; i < Expressions.Length; i++)
            {
                string Epilog = " at line " + Expressions[i].Line.ToString(Culture) + ", column " + Expressions[i].Column.ToString(Culture) + " in file " + Expressions[i].File;
                bool   continueWithNextExpression = false;
                for (int j = Expressions[i].Text.Length - 1; j >= 0; j--)
                {
                    if (Expressions[i].Text[j] == '$')
                    {
                        int k;
                        for (k = j + 1; k < Expressions[i].Text.Length; k++)
                        {
                            if (Expressions[i].Text[k] == '(')
                            {
                                break;
                            }
                            else if (Expressions[i].Text[k] == '/' | Expressions[i].Text[k] == '\\')
                            {
                                k = Expressions[i].Text.Length + 1;
                                break;
                            }
                        }
                        if (k <= Expressions[i].Text.Length)
                        {
                            string t = Expressions[i].Text.Substring(j, k - j).TrimEnd(new char[] { });
                            int    l = 1, h;
                            for (h = k + 1; h < Expressions[i].Text.Length; h++)
                            {
                                switch (Expressions[i].Text[h])
                                {
                                case '(':
                                    l++;
                                    break;

                                case ')':
                                    l--;
                                    if (l < 0)
                                    {
                                        continueWithNextExpression = true;
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Invalid parenthesis structure in " + t + Epilog);
                                    }
                                    break;
                                }
                                if (l <= 0)
                                {
                                    break;
                                }
                            }
                            if (continueWithNextExpression)
                            {
                                break;
                            }
                            if (l != 0)
                            {
                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Invalid parenthesis structure in " + t + Epilog);
                                break;
                            }
                            string s = Expressions[i].Text.Substring(k + 1, h - k - 1).Trim(new char[] { });
                            switch (t.ToLowerInvariant())
                            {
                            case "$if":
                                if (j != 0)
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "The $If directive must not appear within another statement" + Epilog);
                                }
                                else
                                {
                                    double num;
                                    if (double.TryParse(s, NumberStyles.Float, Culture, out num))
                                    {
                                        openIfs++;
                                        Expressions[i].Text = string.Empty;
                                        if (num == 0.0)
                                        {
                                            /*
                                             * Blank every expression until the matching $Else or $EndIf
                                             * */
                                            i++;
                                            int level = 1;
                                            while (i < Expressions.Length)
                                            {
                                                if (Expressions[i].Text.StartsWith("$if", StringComparison.OrdinalIgnoreCase))
                                                {
                                                    Expressions[i].Text = string.Empty;
                                                    level++;
                                                }
                                                else if (Expressions[i].Text.StartsWith("$else", StringComparison.OrdinalIgnoreCase))
                                                {
                                                    Expressions[i].Text = string.Empty;
                                                    if (level == 1)
                                                    {
                                                        level--;
                                                        break;
                                                    }
                                                }
                                                else if (Expressions[i].Text.StartsWith("$endif", StringComparison.OrdinalIgnoreCase))
                                                {
                                                    Expressions[i].Text = string.Empty;
                                                    level--;
                                                    if (level == 0)
                                                    {
                                                        openIfs--;
                                                        break;
                                                    }
                                                }
                                                else
                                                {
                                                    Expressions[i].Text = string.Empty;
                                                }
                                                i++;
                                            }
                                            if (level != 0)
                                            {
                                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "$EndIf missing at the end of the file" + Epilog);
                                            }
                                        }
                                        continueWithNextExpression = true;
                                        break;
                                    }
                                    else
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "The $If condition does not evaluate to a number" + Epilog);
                                    }
                                }
                                continueWithNextExpression = true;
                                break;

                            case "$else":
                                /*
                                 * Blank every expression until the matching $EndIf
                                 * */
                                Expressions[i].Text = string.Empty;
                                if (openIfs != 0)
                                {
                                    i++;
                                    int level = 1;
                                    while (i < Expressions.Length)
                                    {
                                        if (Expressions[i].Text.StartsWith("$if", StringComparison.OrdinalIgnoreCase))
                                        {
                                            Expressions[i].Text = string.Empty;
                                            level++;
                                        }
                                        else if (Expressions[i].Text.StartsWith("$else", StringComparison.OrdinalIgnoreCase))
                                        {
                                            Expressions[i].Text = string.Empty;
                                            if (level == 1)
                                            {
                                                Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Duplicate $Else encountered" + Epilog);
                                            }
                                        }
                                        else if (Expressions[i].Text.StartsWith("$endif", StringComparison.OrdinalIgnoreCase))
                                        {
                                            Expressions[i].Text = string.Empty;
                                            level--;
                                            if (level == 0)
                                            {
                                                openIfs--;
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            Expressions[i].Text = string.Empty;
                                        }
                                        i++;
                                    }
                                    if (level != 0)
                                    {
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "$EndIf missing at the end of the file" + Epilog);
                                    }
                                }
                                else
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "$Else without matching $If encountered" + Epilog);
                                }
                                continueWithNextExpression = true;
                                break;

                            case "$endif":
                                Expressions[i].Text = string.Empty;
                                if (openIfs != 0)
                                {
                                    openIfs--;
                                }
                                else
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "$EndIf without matching $If encountered" + Epilog);
                                }
                                continueWithNextExpression = true;
                                break;

                            case "$include":
                                if (j != 0)
                                {
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "The $Include directive must not appear within another statement" + Epilog);
                                    continueWithNextExpression = true;
                                    break;
                                }
                                string[] args = s.Split(new char[] { ';' });
                                for (int ia = 0; ia < args.Length; ia++)
                                {
                                    args[ia] = args[ia].Trim(new char[] { });
                                }
                                int      count        = (args.Length + 1) / 2;
                                string[] files        = new string[count];
                                double[] weights      = new double[count];
                                double[] offsets      = new double[count];
                                double   weightsTotal = 0.0;
                                for (int ia = 0; ia < count; ia++)
                                {
                                    string file;
                                    double offset;
                                    int    colon = args[2 * ia].IndexOf(':');
                                    if (colon >= 0)
                                    {
                                        file = args[2 * ia].Substring(0, colon).TrimEnd(new char[] { });
                                        string value = args[2 * ia].Substring(colon + 1).TrimStart(new char[] { });
                                        if (!double.TryParse(value, NumberStyles.Float, Culture, out offset))
                                        {
                                            continueWithNextExpression = true;
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "The track position offset " + value + " is invalid in " + t + Epilog);
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        file   = args[2 * ia];
                                        offset = 0.0;
                                    }
                                    files[ia]   = Path.CombineFile(System.IO.Path.GetDirectoryName(FileName), file);
                                    offsets[ia] = offset;
                                    if (!System.IO.File.Exists(files[ia]))
                                    {
                                        continueWithNextExpression = true;
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "The file " + file + " could not be found in " + t + Epilog);
                                        for (int ta = i; ta < Expressions.Length - 1; ta++)
                                        {
                                            Expressions[ta] = Expressions[ta + 1];
                                        }
                                        Array.Resize(ref Expressions, Expressions.Length - 1);
                                        i--;
                                        break;
                                    }
                                    if (2 * ia + 1 < args.Length)
                                    {
                                        if (!NumberFormats.TryParseDoubleVb6(args[2 * ia + 1], out weights[ia]))
                                        {
                                            continueWithNextExpression = true;
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "A weight is invalid in " + t + Epilog);
                                            break;
                                        }
                                        if (weights[ia] <= 0.0)
                                        {
                                            continueWithNextExpression = true;
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "A weight is not positive in " + t + Epilog);
                                            break;
                                        }
                                        weightsTotal += weights[ia];
                                    }
                                    else
                                    {
                                        weights[ia]   = 1.0;
                                        weightsTotal += 1.0;
                                    }
                                }
                                if (count == 0)
                                {
                                    continueWithNextExpression = true;
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "No file was specified in " + t + Epilog);
                                    break;
                                }
                                if (!continueWithNextExpression)
                                {
                                    double number      = Plugin.RandomNumberGenerator.NextDouble() * weightsTotal;
                                    double value       = 0.0;
                                    int    chosenIndex = 0;
                                    for (int ia = 0; ia < count; ia++)
                                    {
                                        value += weights[ia];
                                        if (value > number)
                                        {
                                            chosenIndex = ia;
                                            break;
                                        }
                                    }
                                    Expression[] expr;
                                    //Get the text encoding of our $Include file
                                    System.Text.Encoding includeEncoding = TextEncoding.GetSystemEncodingFromFile(files[chosenIndex]);
                                    if (!includeEncoding.Equals(Encoding) && includeEncoding.WindowsCodePage != Encoding.WindowsCodePage)
                                    {
                                        //If the encodings do not match, add a warning
                                        //This is not critical, but it's a bad idea to mix and match character encodings within a routefile, as the auto-detection may sometimes be wrong
                                        Plugin.CurrentHost.AddMessage(MessageType.Warning, false, "The text encoding of the $Include file " + files[chosenIndex] + " does not match that of the base routefile.");
                                    }
                                    string[] lines = System.IO.File.ReadAllLines(files[chosenIndex], includeEncoding);
                                    PreprocessSplitIntoExpressions(files[chosenIndex], lines, out expr, false, offsets[chosenIndex] + Expressions[i].TrackPositionOffset);
                                    int length = Expressions.Length;
                                    if (expr.Length == 0)
                                    {
                                        for (int ia = i; ia < Expressions.Length - 1; ia++)
                                        {
                                            Expressions[ia] = Expressions[ia + 1];
                                        }
                                        Array.Resize(ref Expressions, length - 1);
                                    }
                                    else
                                    {
                                        Array.Resize(ref Expressions, length + expr.Length - 1);
                                        for (int ia = Expressions.Length - 1; ia >= i + expr.Length; ia--)
                                        {
                                            Expressions[ia] = Expressions[ia - expr.Length + 1];
                                        }
                                        for (int ia = 0; ia < expr.Length; ia++)
                                        {
                                            Expressions[i + ia] = expr[ia];
                                        }
                                    }
                                    i--;
                                    continueWithNextExpression = true;
                                }
                                break;

                            case "$chr":
                            case "$chruni":
                            {
                                int x;
                                if (NumberFormats.TryParseIntVb6(s, out x))
                                {
                                    if (x < 0)
                                    {
                                        //Must be non-negative
                                        continueWithNextExpression = true;
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index must be a non-negative character in " + t + Epilog);
                                    }
                                    else
                                    {
                                        Expressions[i].Text = Expressions[i].Text.Substring(0, j) + char.ConvertFromUtf32(x) + Expressions[i].Text.Substring(h + 1);
                                    }
                                }
                                else
                                {
                                    continueWithNextExpression = true;
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                }
                            } break;

                            case "$chrascii":
                            {
                                int x;
                                if (NumberFormats.TryParseIntVb6(s, out x))
                                {
                                    if (x < 0 || x > 127)
                                    {
                                        //Standard ASCII characters from 0-127
                                        continueWithNextExpression = true;
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index does not correspond to a valid ASCII character in " + t + Epilog);
                                    }
                                    else
                                    {
                                        Expressions[i].Text = Expressions[i].Text.Substring(0, j) + char.ConvertFromUtf32(x) + Expressions[i].Text.Substring(h + 1);
                                    }
                                }
                                else
                                {
                                    continueWithNextExpression = true;
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                }
                            }
                            break;

                            case "$rnd":
                            {
                                int m = s.IndexOf(";", StringComparison.Ordinal);
                                if (m >= 0)
                                {
                                    string s1 = s.Substring(0, m).TrimEnd(new char[] { });
                                    string s2 = s.Substring(m + 1).TrimStart(new char[] { });
                                    int    x; if (NumberFormats.TryParseIntVb6(s1, out x))
                                    {
                                        int y; if (NumberFormats.TryParseIntVb6(s2, out y))
                                        {
                                            int z = x + (int)Math.Floor(Plugin.RandomNumberGenerator.NextDouble() * (y - x + 1));
                                            Expressions[i].Text = Expressions[i].Text.Substring(0, j) + z.ToString(Culture) + Expressions[i].Text.Substring(h + 1);
                                        }
                                        else
                                        {
                                            continueWithNextExpression = true;
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index2 is invalid in " + t + Epilog);
                                        }
                                    }
                                    else
                                    {
                                        continueWithNextExpression = true;
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index1 is invalid in " + t + Epilog);
                                    }
                                }
                                else
                                {
                                    continueWithNextExpression = true;
                                    Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Two arguments are expected in " + t + Epilog);
                                }
                            } break;

                            case "$sub":
                            {
                                l = 0;
                                bool f = false;
                                int  m;
                                for (m = h + 1; m < Expressions[i].Text.Length; m++)
                                {
                                    switch (Expressions[i].Text[m])
                                    {
                                    case '(': l++; break;

                                    case ')': l--; break;

                                    case '=':
                                        if (l == 0)
                                        {
                                            f = true;
                                        }
                                        break;

                                    default:
                                        if (!char.IsWhiteSpace(Expressions[i].Text[m]))
                                        {
                                            l = -1;
                                        }
                                        break;
                                    }
                                    if (f | l < 0)
                                    {
                                        break;
                                    }
                                }
                                if (f)
                                {
                                    l = 0;
                                    int n;
                                    for (n = m + 1; n < Expressions[i].Text.Length; n++)
                                    {
                                        switch (Expressions[i].Text[n])
                                        {
                                        case '(': l++; break;

                                        case ')': l--; break;
                                        }
                                        if (l < 0)
                                        {
                                            break;
                                        }
                                    }
                                    int x;
                                    if (NumberFormats.TryParseIntVb6(s, out x))
                                    {
                                        if (x >= 0)
                                        {
                                            while (x >= Subs.Length)
                                            {
                                                Array.Resize(ref Subs, Subs.Length << 1);
                                            }
                                            Subs[x]             = Expressions[i].Text.Substring(m + 1, n - m - 1).Trim(new char[] { });
                                            Expressions[i].Text = Expressions[i].Text.Substring(0, j) + Expressions[i].Text.Substring(n);
                                        }
                                        else
                                        {
                                            continueWithNextExpression = true;
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index is expected to be non-negative in " + t + Epilog);
                                        }
                                    }
                                    else
                                    {
                                        continueWithNextExpression = true;
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                    }
                                }
                                else
                                {
                                    int x;
                                    if (NumberFormats.TryParseIntVb6(s, out x))
                                    {
                                        if (x >= 0 & x < Subs.Length && Subs[x] != null)
                                        {
                                            Expressions[i].Text = Expressions[i].Text.Substring(0, j) + Subs[x] + Expressions[i].Text.Substring(h + 1);
                                        }
                                        else
                                        {
                                            continueWithNextExpression = true;
                                            Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index is out of range in " + t + Epilog);
                                        }
                                    }
                                    else
                                    {
                                        continueWithNextExpression = true;
                                        Plugin.CurrentHost.AddMessage(MessageType.Error, false, "Index is invalid in " + t + Epilog);
                                    }
                                }
                            }
                            break;
                            }
                        }
                    }
                    if (continueWithNextExpression)
                    {
                        break;
                    }
                }
            }
            // handle comments introduced via chr, rnd, sub
            {
                int length = Expressions.Length;
                for (int i = 0; i < length; i++)
                {
                    Expressions[i].Text = Expressions[i].Text.Trim(new char[] { });
                    if (Expressions[i].Text.Length != 0)
                    {
                        if (Expressions[i].Text[0] == ';')
                        {
                            for (int j = i; j < length - 1; j++)
                            {
                                Expressions[j] = Expressions[j + 1];
                            }
                            length--;
                            i--;
                        }
                    }
                    else
                    {
                        for (int j = i; j < length - 1; j++)
                        {
                            Expressions[j] = Expressions[j + 1];
                        }
                        length--;
                        i--;
                    }
                }
                if (length != Expressions.Length)
                {
                    Array.Resize(ref Expressions, length);
                }
            }
        }
Exemple #20
0
        public static Game.Station ReadStationXML(string fileName, bool PreviewOnly, Textures.Texture[] daytimeTimetableTextures, Textures.Texture[] nighttimeTimetableTextures, int CurrentStation, ref bool passAlarm, ref CsvRwRouteParser.StopRequest stopRequest)
        {
            Game.Station station = new Game.Station
            {
                Stops = new Game.StationStop[] { }
            };
            stopRequest.Early              = new TrackManager.RequestStop();
            stopRequest.OnTime             = new TrackManager.RequestStop();
            stopRequest.Late               = new TrackManager.RequestStop();
            stopRequest.OnTime.Probability = 75;
            //The current XML file to load
            XmlDocument currentXML = new XmlDocument();

            //Load the object's XML file
            currentXML.Load(fileName);
            string Path = System.IO.Path.GetDirectoryName(fileName);

            //Check for null
            if (currentXML.DocumentElement != null)
            {
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/Station");
                //Check this file actually contains OpenBVE light definition nodes
                if (DocumentNodes != null)
                {
                    foreach (XmlNode n in DocumentNodes)
                    {
                        if (n.ChildNodes.OfType <XmlElement>().Any())
                        {
                            foreach (XmlNode c in n.ChildNodes)
                            {
                                //string[] Arguments = c.InnerText.Split(',');
                                switch (c.Name.ToLowerInvariant())
                                {
                                case "name":
                                    if (!string.IsNullOrEmpty(c.InnerText))
                                    {
                                        station.Name = c.InnerText;
                                    }
                                    else
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, "Station name was empty in XML file " + fileName);
                                    }
                                    break;

                                case "arrivaltime":
                                    if (!string.IsNullOrEmpty(c.InnerText))
                                    {
                                        if (!Interface.TryParseTime(c.InnerText, out station.ArrivalTime))
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Station arrival time was invalid in XML file " + fileName);
                                        }
                                    }
                                    break;

                                case "departuretime":
                                    if (!string.IsNullOrEmpty(c.InnerText))
                                    {
                                        if (!Interface.TryParseTime(c.InnerText, out station.DepartureTime))
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Station arrival time was invalid in XML file " + fileName);
                                        }
                                    }
                                    break;

                                case "type":
                                    switch (c.InnerText.ToLowerInvariant())
                                    {
                                    case "c":
                                    case "changeends":
                                        station.Type = StationType.ChangeEnds;
                                        break;

                                    case "t":
                                    case "terminal":
                                        station.Type = StationType.Terminal;
                                        break;

                                    default:
                                        station.Type = StationType.Normal;
                                        break;
                                    }
                                    break;

                                case "passalarm":
                                    if (!string.IsNullOrEmpty(c.InnerText))
                                    {
                                        if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                                        {
                                            passAlarm = true;
                                        }
                                        else
                                        {
                                            passAlarm = false;
                                        }
                                    }
                                    break;

                                case "doors":
                                    int  door     = 0;
                                    bool doorboth = false;
                                    if (!string.IsNullOrEmpty(c.InnerText))
                                    {
                                        switch (c.InnerText.ToLowerInvariant())
                                        {
                                        case "l":
                                        case "left":
                                            door = -1;
                                            break;

                                        case "r":
                                        case "right":
                                            door = 1;
                                            break;

                                        case "n":
                                        case "none":
                                        case "neither":
                                            door = 0;
                                            break;

                                        case "b":
                                        case "both":
                                            doorboth = true;
                                            break;

                                        default:
                                            if (!NumberFormats.TryParseIntVb6(c.InnerText, out door))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Door side was invalid in XML file " + fileName);
                                                door = 0;
                                            }
                                            break;
                                        }
                                    }
                                    station.OpenLeftDoors  = door < 0.0 | doorboth;
                                    station.OpenRightDoors = door > 0.0 | doorboth;
                                    break;

                                case "forcedredsignal":
                                    if (!string.IsNullOrEmpty(c.InnerText))
                                    {
                                        if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                                        {
                                            station.ForceStopSignal = true;
                                        }
                                        else
                                        {
                                            station.ForceStopSignal = false;
                                        }
                                    }
                                    break;

                                case "system":
                                    switch (c.InnerText.ToLowerInvariant())
                                    {
                                    case "0":
                                    case "ATS":
                                        station.SafetySystem = Game.SafetySystem.Ats;
                                        break;

                                    case "1":
                                    case "ATC":
                                        station.SafetySystem = Game.SafetySystem.Atc;
                                        break;

                                    default:
                                        Interface.AddMessage(Interface.MessageType.Error, false, "An invalid station safety system was specified in XML file " + fileName);
                                        station.SafetySystem = Game.SafetySystem.Ats;
                                        break;
                                    }
                                    break;

                                case "arrivalsound":
                                    string arrSound  = string.Empty;
                                    double arrRadius = 30.0;
                                    if (!c.ChildNodes.OfType <XmlElement>().Any())
                                    {
                                        foreach (XmlNode cc in c.ChildNodes)
                                        {
                                            switch (c.Name.ToLowerInvariant())
                                            {
                                            case "filename":
                                                try
                                                {
                                                    arrSound = OpenBveApi.Path.CombineFile(Path, cc.InnerText);
                                                }
                                                catch
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Arrival sound filename is invalid in XML file " + fileName);
                                                }
                                                break;

                                            case "radius":
                                                if (!double.TryParse(cc.InnerText, out arrRadius))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Arrival sound radius was invalid in XML file " + fileName);
                                                }
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        try
                                        {
                                            arrSound = OpenBveApi.Path.CombineFile(Path, c.InnerText);
                                        }
                                        catch
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Arrival sound filename is invalid in XML file " + fileName);
                                        }
                                    }
                                    if (File.Exists(arrSound))
                                    {
                                        station.ArrivalSoundBuffer = Sounds.RegisterBuffer(arrSound, arrRadius);
                                    }
                                    else
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, "Arrival sound file does not exist in XML file " + fileName);
                                    }
                                    break;

                                case "stopduration":
                                    double stopDuration;
                                    if (!double.TryParse(c.InnerText, out stopDuration))
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, "Stop duration is invalid in XML file " + fileName);
                                    }
                                    else
                                    {
                                        if (stopDuration < 5.0)
                                        {
                                            stopDuration = 5.0;
                                        }
                                        station.StopTime = stopDuration;
                                    }
                                    break;

                                case "passengerratio":
                                    double ratio;
                                    if (!double.TryParse(c.InnerText, out ratio))
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, "Passenger ratio is invalid in XML file " + fileName);
                                    }
                                    else
                                    {
                                        if (ratio < 0.0)
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Passenger ratio must be non-negative in XML file " + fileName);
                                            ratio = 100.0;
                                        }
                                        station.PassengerRatio = ratio * 0.01;
                                    }
                                    break;

                                case "departuresound":
                                    string depSound  = string.Empty;
                                    double depRadius = 30.0;
                                    if (!c.ChildNodes.OfType <XmlElement>().Any())
                                    {
                                        foreach (XmlNode cc in c.ChildNodes)
                                        {
                                            switch (c.Name.ToLowerInvariant())
                                            {
                                            case "filename":
                                                try
                                                {
                                                    depSound = OpenBveApi.Path.CombineFile(Path, cc.InnerText);
                                                }
                                                catch
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Departure sound filename is invalid in XML file " + fileName);
                                                }
                                                break;

                                            case "radius":
                                                if (!double.TryParse(cc.InnerText, out depRadius))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Departure sound radius was invalid in XML file " + fileName);
                                                }
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        try
                                        {
                                            depSound = OpenBveApi.Path.CombineFile(Path, c.InnerText);
                                        }
                                        catch
                                        {
                                            Interface.AddMessage(Interface.MessageType.Error, false, "Departure sound filename is invalid in XML file " + fileName);
                                        }
                                    }
                                    if (File.Exists(depSound))
                                    {
                                        station.DepartureSoundBuffer = Sounds.RegisterBuffer(depSound, depRadius);
                                    }
                                    else
                                    {
                                        Interface.AddMessage(Interface.MessageType.Error, false, "Departure sound file does not exist in XML file " + fileName);
                                    }
                                    break;

                                case "timetableindex":
                                    if (!PreviewOnly)
                                    {
                                        int ttidx = -1;
                                        if (!string.IsNullOrEmpty(c.InnerText))
                                        {
                                            if (NumberFormats.TryParseIntVb6(c.InnerText, out ttidx))
                                            {
                                                if (ttidx < 0)
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Timetable index must be non-negative in XML file " + fileName);
                                                    ttidx = -1;
                                                }
                                                else if (ttidx >= daytimeTimetableTextures.Length & ttidx >= nighttimeTimetableTextures.Length)
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Timetable index references a non-loaded texture in XML file " + fileName);
                                                    ttidx = -1;
                                                }
                                                station.TimetableDaytimeTexture   = ttidx >= 0 & ttidx < daytimeTimetableTextures.Length ? daytimeTimetableTextures[ttidx] : null;
                                                station.TimetableNighttimeTexture = ttidx >= 0 & ttidx < nighttimeTimetableTextures.Length ? nighttimeTimetableTextures[ttidx] : null;
                                                break;
                                            }
                                        }
                                        if (ttidx == -1)
                                        {
                                            if (CurrentStation > 0)
                                            {
                                                station.TimetableDaytimeTexture   = Game.Stations[CurrentStation - 1].TimetableDaytimeTexture;
                                                station.TimetableNighttimeTexture = Game.Stations[CurrentStation - 1].TimetableNighttimeTexture;
                                            }
                                            else if (daytimeTimetableTextures.Length > 0 & nighttimeTimetableTextures.Length > 0)
                                            {
                                                station.TimetableDaytimeTexture   = daytimeTimetableTextures[0];
                                                station.TimetableNighttimeTexture = nighttimeTimetableTextures[0];
                                            }
                                        }
                                    }
                                    break;

                                case "requeststop":
                                    station.Type     = StationType.RequestStop;
                                    station.StopMode = StationStopMode.AllRequestStop;
                                    foreach (XmlNode cc in c.ChildNodes)
                                    {
                                        switch (cc.Name.ToLowerInvariant())
                                        {
                                        case "aibehaviour":
                                            switch (cc.InnerText.ToLowerInvariant())
                                            {
                                            case "fullspeed":
                                            case "0":
                                                //With this set, the AI driver will not attempt to brake, but pass through at linespeed
                                                stopRequest.FullSpeed = true;
                                                break;

                                            case "normalbrake":
                                            case "1":
                                                //With this set, the AI driver breaks to a near stop whilst passing through the station
                                                stopRequest.FullSpeed = false;
                                                break;
                                            }
                                            break;

                                        case "playeronly":
                                            station.StopMode = StationStopMode.PlayerRequestStop;
                                            break;

                                        case "distance":
                                            if (!string.IsNullOrEmpty(cc.InnerText))
                                            {
                                                double d;
                                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out d))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Request stop distance is invalid in XML file " + fileName);
                                                    break;
                                                }
                                                stopRequest.TrackPosition -= Math.Abs(d);
                                            }
                                            break;

                                        case "earlytime":
                                            if (!string.IsNullOrEmpty(cc.InnerText))
                                            {
                                                if (!Interface.TryParseTime(cc.InnerText, out stopRequest.Early.Time))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Request stop early time was invalid in XML file " + fileName);
                                                }
                                            }
                                            break;

                                        case "latetime":
                                            if (!string.IsNullOrEmpty(cc.InnerText))
                                            {
                                                if (!Interface.TryParseTime(cc.InnerText, out stopRequest.Late.Time))
                                                {
                                                    Interface.AddMessage(Interface.MessageType.Error, false, "Request stop late time was invalid in XML file " + fileName);
                                                }
                                            }
                                            break;

                                        case "stopmessage":
                                            if (cc.ChildNodes.OfType <XmlElement>().Any())
                                            {
                                                foreach (XmlNode cd in cc.ChildNodes)
                                                {
                                                    switch (cd.Name.ToLowerInvariant())
                                                    {
                                                    case "early":
                                                        if (!string.IsNullOrEmpty(cd.InnerText))
                                                        {
                                                            stopRequest.Early.StopMessage = cd.InnerText;
                                                        }
                                                        break;

                                                    case "ontime":
                                                        if (!string.IsNullOrEmpty(cd.InnerText))
                                                        {
                                                            stopRequest.OnTime.StopMessage = cd.InnerText;
                                                        }
                                                        break;

                                                    case "late":
                                                        if (!string.IsNullOrEmpty(cd.InnerText))
                                                        {
                                                            stopRequest.Late.StopMessage = cd.InnerText;
                                                        }
                                                        break;

                                                    case "#text":
                                                        stopRequest.Early.StopMessage  = cc.InnerText;
                                                        stopRequest.OnTime.StopMessage = cc.InnerText;
                                                        stopRequest.Late.StopMessage   = cc.InnerText;
                                                        break;
                                                    }
                                                }
                                            }
                                            break;

                                        case "passmessage":
                                            if (cc.ChildNodes.OfType <XmlElement>().Any())
                                            {
                                                foreach (XmlNode cd in cc.ChildNodes)
                                                {
                                                    switch (cd.Name.ToLowerInvariant())
                                                    {
                                                    case "early":
                                                        if (!string.IsNullOrEmpty(cd.InnerText))
                                                        {
                                                            stopRequest.Early.PassMessage = cd.InnerText;
                                                        }
                                                        break;

                                                    case "ontime":
                                                        if (!string.IsNullOrEmpty(cd.InnerText))
                                                        {
                                                            stopRequest.OnTime.PassMessage = cd.InnerText;
                                                        }
                                                        break;

                                                    case "late":
                                                        if (!string.IsNullOrEmpty(cd.InnerText))
                                                        {
                                                            stopRequest.Late.PassMessage = cd.InnerText;
                                                        }
                                                        break;

                                                    case "#text":
                                                        stopRequest.Early.PassMessage  = cc.InnerText;
                                                        stopRequest.OnTime.PassMessage = cc.InnerText;
                                                        stopRequest.Late.PassMessage   = cc.InnerText;
                                                        break;
                                                    }
                                                }
                                            }
                                            break;

                                        case "probability":
                                            foreach (XmlNode cd in cc.ChildNodes)
                                            {
                                                switch (cd.Name.ToLowerInvariant())
                                                {
                                                case "early":
                                                    if (!string.IsNullOrEmpty(cd.InnerText))
                                                    {
                                                        if (!NumberFormats.TryParseIntVb6(cd.InnerText, out stopRequest.Early.Probability))
                                                        {
                                                            Interface.AddMessage(Interface.MessageType.Error, false, "Request stop early probability was invalid in XML file " + fileName);
                                                        }
                                                    }
                                                    break;

                                                case "ontime":
                                                    if (!string.IsNullOrEmpty(cd.InnerText))
                                                    {
                                                        if (!NumberFormats.TryParseIntVb6(cd.InnerText, out stopRequest.OnTime.Probability))
                                                        {
                                                            Interface.AddMessage(Interface.MessageType.Error, false, "Request stop ontime probability was invalid in XML file " + fileName);
                                                        }
                                                    }
                                                    break;

                                                case "late":
                                                    if (!string.IsNullOrEmpty(cd.InnerText))
                                                    {
                                                        if (!NumberFormats.TryParseIntVb6(cd.InnerText, out stopRequest.OnTime.Probability))
                                                        {
                                                            Interface.AddMessage(Interface.MessageType.Error, false, "Request stop late probability was invalid in XML file " + fileName);
                                                        }
                                                    }
                                                    break;

                                                case "#text":
                                                    if (!NumberFormats.TryParseIntVb6(cd.InnerText, out stopRequest.OnTime.Probability))
                                                    {
                                                        Interface.AddMessage(Interface.MessageType.Error, false, "Request stop probability was invalid in XML file " + fileName);
                                                    }
                                                    break;
                                                }
                                            }

                                            break;

                                        case "maxcars":
                                            if (!NumberFormats.TryParseIntVb6(cc.InnerText, out stopRequest.MaxNumberOfCars))
                                            {
                                                Interface.AddMessage(Interface.MessageType.Error, false, "Request stop maximum cars was invalid in XML file " + fileName);
                                            }
                                            break;
                                        }
                                    }

                                    break;
                                }
                            }
                        }
                    }
                    return(station);
                }
            }
            //We couldn't find any valid XML, so return false
            throw new InvalidDataException();
        }
        private static void ParseCarNode(XmlNode Node, string fileName, int Car, ref TrainManager.Train Train, ref UnifiedObject[] CarObjects, ref UnifiedObject[] BogieObjects)
        {
            string interiorFile = string.Empty;

            foreach (XmlNode c in Node.ChildNodes)
            {
                //Note: Don't use the short-circuiting operator, as otherwise we need another if
                switch (c.Name.ToLowerInvariant())
                {
                case "brake":
                    Train.Cars[Car].CarBrake.brakeType = BrakeType.Auxiliary;
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        ParseBrakeNode(c, fileName, Car, ref Train);
                    }
                    else if (!String.IsNullOrEmpty(c.InnerText))
                    {
                        try
                        {
                            string      childFile = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                            XmlDocument childXML  = new XmlDocument();
                            childXML.Load(childFile);
                            XmlNodeList childNodes = childXML.DocumentElement.SelectNodes("/openBVE/Brake");
                            //We need to save and restore the current path to make relative paths within the child file work correctly
                            string savedPath = currentPath;
                            currentPath = System.IO.Path.GetDirectoryName(childFile);
                            ParseBrakeNode(childNodes[0], fileName, Car, ref Train);
                            currentPath = savedPath;
                        }
                        catch
                        {
                            Interface.AddMessage(MessageType.Error, false, "Failed to load the child Brake XML file specified in " + c.InnerText);
                        }
                    }
                    break;

                case "length":
                    double l;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out l) | l <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid length defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Length = l;
                    break;

                case "width":
                    double w;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out w) | w <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid width defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Width = w;
                    break;

                case "height":
                    double h;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out h) | h <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid height defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Height = h;
                    break;

                case "motorcar":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        Train.Cars[Car].Specs.IsMotorCar         = true;
                        Train.Cars[Car].Specs.AccelerationCurves = new TrainManager.AccelerationCurve[AccelerationCurves.Length];
                        for (int i = 0; i < AccelerationCurves.Length; i++)
                        {
                            Train.Cars[Car].Specs.AccelerationCurves[i] = AccelerationCurves[i].Clone(AccelerationCurves[i].Multiplier);
                        }
                        switch (Train.Specs.ReadhesionDeviceType)
                        {
                        case TrainManager.ReadhesionDeviceType.TypeA:
                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 0.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 8.0;
                            break;

                        case TrainManager.ReadhesionDeviceType.TypeB:
                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 0.1;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 0.9935;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 4.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 1.125;
                            break;

                        case TrainManager.ReadhesionDeviceType.TypeC:

                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 0.1;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 0.965;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 2.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 1.5;
                            break;

                        case TrainManager.ReadhesionDeviceType.TypeD:
                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 0.05;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 0.935;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 0.3;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 2.0;
                            break;

                        default:                                         // no readhesion device
                            Train.Cars[Car].Specs.ReAdhesionDevice.UpdateInterval    = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ApplicationFactor = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseInterval   = 1.0;
                            Train.Cars[Car].Specs.ReAdhesionDevice.ReleaseFactor     = 99.0;
                            break;
                        }
                    }
                    else
                    {
                        Train.Cars[Car].Specs.AccelerationCurves = new TrainManager.AccelerationCurve[] { };
                        Train.Cars[Car].Specs.IsMotorCar         = false;
                        Train.Cars[Car].Specs.ReAdhesionDevice   = new TrainManager.CarReAdhesionDevice(Train.Cars[Car]);
                    }
                    break;

                case "mass":
                    double m;
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out m) | m <= 0.0)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid mass defined for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Specs.MassEmpty   = m;
                    Train.Cars[Car].Specs.MassCurrent = m;
                    break;

                case "frontaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].FrontAxle.Position))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid front axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "rearaxle":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Train.Cars[Car].RearAxle.Position))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Invalid rear axle position defined for Car " + Car + " in XML file " + fileName);
                    }
                    break;

                case "object":
                    string f = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (System.IO.File.Exists(f))
                    {
                        CarObjects[Car] = ObjectManager.LoadObject(f, System.Text.Encoding.Default, false, false, false);
                    }
                    break;

                case "reversed":
                    if (c.InnerText.ToLowerInvariant() == "1" || c.InnerText.ToLowerInvariant() == "true")
                    {
                        CarObjectsReversed[Car] = true;
                    }
                    break;

                case "frontbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid front bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].FrontBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid front bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    BogieObjects[Car * 2] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, false, false, false);
                                }
                                break;

                            case "reversed":
                                BogieObjectsReversed[Car * 2] = true;
                                break;
                            }
                        }
                    }
                    break;

                case "rearbogie":
                    if (c.ChildNodes.OfType <XmlElement>().Any())
                    {
                        foreach (XmlNode cc in c.ChildNodes)
                        {
                            switch (cc.Name.ToLowerInvariant())
                            {
                            case "frontaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.FrontAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid rear bogie, front axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "rearaxle":
                                if (!NumberFormats.TryParseDoubleVb6(cc.InnerText, out Train.Cars[Car].RearBogie.RearAxle.Position))
                                {
                                    Interface.AddMessage(MessageType.Warning, false, "Invalid rear bogie, rear axle position defined for Car " + Car + " in XML file " + fileName);
                                }
                                break;

                            case "object":
                                string fb = OpenBveApi.Path.CombineFile(currentPath, cc.InnerText);
                                if (System.IO.File.Exists(fb))
                                {
                                    BogieObjects[Car * 2 + 1] = ObjectManager.LoadObject(fb, System.Text.Encoding.Default, false, false, false);
                                }
                                break;

                            case "reversed":
                                BogieObjectsReversed[Car * 2 + 1] = true;
                                break;
                            }
                        }
                    }
                    break;

                case "driverposition":
                    string[] splitText = c.InnerText.Split(',');
                    if (splitText.Length != 3)
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position must have three arguments for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    Train.Cars[Car].Driver = new Vector3();
                    double driverZ;
                    if (!NumberFormats.TryParseDoubleVb6(splitText[0], out Train.Cars[Car].Driver.X))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[1], out Train.Cars[Car].Driver.Y))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position Y was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    if (!NumberFormats.TryParseDoubleVb6(splitText[2], out driverZ))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Driver position X was invalid for Car " + Car + " in XML file " + fileName);
                    }
                    Train.Cars[Car].Driver.Z = 0.5 * Train.Cars[Car].Length + driverZ;
                    break;

                case "interiorview":
                    if (Train != TrainManager.PlayerTrain)
                    {
                        break;
                    }
                    Train.Cars[Car].HasInteriorView = true;
                    if (Car != Train.DriverCar)
                    {
                        Train.Cars[Car].CarSections             = new TrainManager.CarSection[1];
                        Train.Cars[Car].CarSections[0]          = new TrainManager.CarSection();
                        Train.Cars[Car].CarSections[0].Elements = new ObjectManager.AnimatedObject[] { };
                        Train.Cars[Car].CarSections[0].Overlay  = true;
                    }
                    string cv = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                    if (!System.IO.File.Exists(cv))
                    {
                        Interface.AddMessage(MessageType.Warning, false, "Interior view file was invalid for Car " + Car + " in XML file " + fileName);
                        break;
                    }
                    interiorFile = cv;
                    break;
                }
            }
            //Driver position is measured from the front of the car
            //As there is no set order, this needs to be done after the loop
            if (interiorFile != String.Empty)
            {
                if (interiorFile.ToLowerInvariant().EndsWith(".cfg"))
                {
                    //Only supports panel2.cfg format
                    Panel2CfgParser.ParsePanel2Config(System.IO.Path.GetFileName(interiorFile), System.IO.Path.GetDirectoryName(interiorFile), Encoding.UTF8, Train, Car);
                    Train.Cars[Car].CameraRestrictionMode = Camera.RestrictionMode.On;
                }
                else if (interiorFile.ToLowerInvariant().EndsWith(".animated"))
                {
                    ObjectManager.AnimatedObjectCollection a = AnimatedObjectParser.ReadObject(interiorFile, Encoding.UTF8);
                    try
                    {
                        for (int i = 0; i < a.Objects.Length; i++)
                        {
                            a.Objects[i].ObjectIndex = ObjectManager.CreateDynamicObject();
                        }
                        Train.Cars[Car].CarSections[0].Elements = a.Objects;
                        Train.Cars[Car].CameraRestrictionMode   = Camera.RestrictionMode.NotAvailable;
                    }
                    catch
                    {
                        Program.RestartArguments = " ";
                        Loading.Cancel           = true;
                    }
                }
                else
                {
                    Interface.AddMessage(MessageType.Warning, false, "Interior view file is not supported for Car " + Car + " in XML file " + fileName);
                }
            }
        }
Exemple #22
0
        /// <summary>Loads a list of compatibility signal objects</summary>
        /// <param name="currentHost">The host application interface</param>
        /// <param name="fileName">The file name of the object list</param>
        /// <param name="objects">The returned array of speed limits</param>
        /// <param name="signalPost">Sets the default signal post</param>
        /// <param name="speedLimits">The array of signal speed limits</param>
        /// <returns>An array of compatability signal objects</returns>
        public static void ReadCompatibilitySignalXML(HostInterface currentHost, string fileName, out CompatibilitySignalObject[] objects, out UnifiedObject signalPost, out double[] speedLimits)
        {
            signalPost = new StaticObject(currentHost);
            objects    = new CompatibilitySignalObject[9];
            //Default Japanese speed limits converted to m/s
            speedLimits = new[] { 0.0, 6.94444444444444, 15.2777777777778, 20.8333333333333, double.PositiveInfinity, double.PositiveInfinity };
            XmlDocument currentXML = new XmlDocument();

            currentXML.Load(fileName);
            string currentPath = System.IO.Path.GetDirectoryName(fileName);

            if (currentXML.DocumentElement != null)
            {
                XmlNode node = currentXML.SelectSingleNode("/openBVE/CompatibilitySignals/SignalSetName");
                if (node != null)
                {
                    currentHost.AddMessage(MessageType.Information, false, "INFO: Using the " + node.InnerText + " compatibility signal set.");
                }
                XmlNodeList DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/CompatibilitySignals/Signal");
                if (DocumentNodes != null)
                {
                    int index = 0;
                    foreach (XmlNode nn in DocumentNodes)
                    {
                        List <StaticObject> objectList = new List <StaticObject>();
                        List <int>          aspectList = new List <int>();
                        try
                        {
                            if (nn.HasChildNodes)
                            {
                                foreach (XmlNode n in nn.ChildNodes)
                                {
                                    if (n.Name != "Aspect")
                                    {
                                        continue;
                                    }

                                    int aspect = 0;
                                    if (!NumberFormats.TryParseIntVb6(n.Attributes["Number"].Value, out aspect))
                                    {
                                        currentHost.AddMessage(MessageType.Error, true, "Invalid aspect number " + aspect + " in the signal object list in the compatability signal file " + fileName);
                                        continue;
                                    }

                                    aspectList.Add(aspect);

                                    StaticObject staticObject = new StaticObject(currentHost);
                                    if (n.InnerText.ToLowerInvariant() != "null")
                                    {
                                        string objectFile = Path.CombineFile(currentPath, n.InnerText);
                                        if (File.Exists(objectFile))
                                        {
                                            currentHost.LoadStaticObject(objectFile, Encoding.UTF8, false, out staticObject);
                                        }
                                        else
                                        {
                                            currentHost.AddMessage(MessageType.Error, true, "Compatibility signal file " + objectFile + " not found in " + fileName);
                                        }
                                    }
                                    objectList.Add(staticObject);
                                }
                            }
                        }
                        catch
                        {
                            currentHost.AddMessage(MessageType.Error, true, "An unexpected error was encountered whilst processing the compatability signal file " + fileName);
                        }
                        objects[index] = new CompatibilitySignalObject(aspectList.ToArray(), objectList.ToArray());
                        index++;
                    }
                }

                string signalPostFile = Path.CombineFile(currentPath, "Japanese\\signal_post.csv");                 //default plain post
                try
                {
                    node = currentXML.SelectSingleNode("/openBVE/CompatibilitySignals/SignalPost");
                    if (node != null)
                    {
                        string newFile = Path.CombineFile(currentPath, node.InnerText);
                        if (System.IO.File.Exists(newFile))
                        {
                            signalPostFile = newFile;
                        }
                    }
                    currentHost.LoadObject(signalPostFile, Encoding.UTF8, out signalPost);
                }
                catch
                {
                    currentHost.AddMessage(MessageType.Error, true, "An unexpected error was encountered whilst processing the compatability signal file " + fileName);
                }

                DocumentNodes = currentXML.DocumentElement.SelectNodes("/openBVE/CompatibilitySignals/SpeedLimits");
                if (DocumentNodes != null)
                {
                    foreach (XmlNode nn in DocumentNodes)
                    {
                        try
                        {
                            if (nn.HasChildNodes)
                            {
                                foreach (XmlNode n in nn.ChildNodes)
                                {
                                    if (n.Name != "Aspect")
                                    {
                                        continue;
                                    }

                                    int aspect = 0;
                                    if (n.Attributes != null)
                                    {
                                        if (!NumberFormats.TryParseIntVb6(n.Attributes["Number"].Value, out aspect))
                                        {
                                            currentHost.AddMessage(MessageType.Error, true, "Invalid aspect number " + aspect + " in the speed limit list in the compatability signal file " + fileName);
                                            continue;
                                        }
                                    }

                                    if (aspect <= speedLimits.Length)
                                    {
                                        int l = speedLimits.Length;
                                        Array.Resize(ref speedLimits, aspect + 1);
                                        for (int i = l; i < speedLimits.Length; i++)
                                        {
                                            speedLimits[i] = double.PositiveInfinity;
                                        }

                                        if (!NumberFormats.TryParseDoubleVb6(n.InnerText, out speedLimits[aspect]))
                                        {
                                            speedLimits[aspect] = double.MaxValue;
                                            if (n.InnerText.ToLowerInvariant() != "unlimited")
                                            {
                                                currentHost.AddMessage(MessageType.Error, true, "Invalid speed limit provided for aspect " + aspect + " in the compatability signal file " + fileName);
                                            }
                                        }
                                        else
                                        {
                                            //convert to m/s as that's what we use internally
                                            speedLimits[aspect] *= 0.277777777777778;
                                        }
                                    }
                                }
                            }
                        }
                        catch
                        {
                            currentHost.AddMessage(MessageType.Error, true, "An unexpected error was encountered whilst processing the compatability signal file " + fileName);
                        }
                    }
                }
            }
        }
Exemple #23
0
        /// <summary>Parses a single XML node into a sound buffer and position reference</summary>
        /// <param name="node">The node to parse</param>
        /// <param name="Sound">The car sound</param>
        /// <param name="Position">The default position of this sound (May be overriden by the node)</param>
        /// <param name="Radius">The default radius of this sound (May be overriden by the node)</param>
        private static void ParseNode(XmlNode node, out Sounds.SoundBuffer Sound, ref Vector3 Position, double Radius)
        {
            string fileName = null;

            foreach (XmlNode c in node.ChildNodes)
            {
                switch (c.Name.ToLowerInvariant())
                {
                case "filename":
                    try
                    {
                        fileName = OpenBveApi.Path.CombineFile(currentPath, c.InnerText);
                        if (!System.IO.File.Exists(fileName))
                        {
                            //Valid path, but the file does not exist
                            Interface.AddMessage(Interface.MessageType.Error, false, "The sound path " + c.InnerText + " in XML node " + node.Name + " does not exist.");
                            Sound = null;
                            return;
                        }
                    }
                    catch
                    {
                        //Probably invalid filename characters
                        Interface.AddMessage(Interface.MessageType.Error, false, "The sound path " + c.InnerText + " in XML node " + node.Name + " is invalid.");
                        Sound = null;
                        return;
                    }
                    break;

                case "position":
                    string[] Arguments = c.InnerText.Split(',');
                    double   x = 0.0, y = 0.0, z = 0.0;
                    if (Arguments.Length >= 1 && Arguments[0].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[0], out x))
                    {
                        Interface.AddMessage(Interface.MessageType.Error, false, "Sound radius X " + Arguments[0] + " in XML node " + node.Name + " is invalid.");
                        x = 0.0;
                    }
                    if (Arguments.Length >= 2 && Arguments[1].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[1], out y))
                    {
                        Interface.AddMessage(Interface.MessageType.Error, false, "Sound radius Y " + Arguments[1] + " in XML node " + node.Name + " is invalid.");
                        y = 0.0;
                    }
                    if (Arguments.Length >= 3 && Arguments[2].Length > 0 && !NumberFormats.TryParseDoubleVb6(Arguments[2], out z))
                    {
                        Interface.AddMessage(Interface.MessageType.Error, false, "Sound radius Z " + Arguments[2] + " in XML node " + node.Name + " is invalid.");
                        z = 0.0;
                    }
                    Position = new Vector3(x, y, z);
                    break;

                case "radius":
                    if (!NumberFormats.TryParseDoubleVb6(c.InnerText, out Radius))
                    {
                        Interface.AddMessage(Interface.MessageType.Error, false, "The sound radius " + c.InnerText + " in XML node " + node.Name + " is invalid.");
                    }
                    break;
                }
            }
            if (fileName == null)
            {
                //No valid filename node specified
                Interface.AddMessage(Interface.MessageType.Error, false, "XML node " + node.Name + " does not point to a valid sound file.");
                Sound = null;
                return;
            }
            Sound = Sounds.SoundBuffer.TryToLoad(fileName, Radius);
        }
Exemple #24
0
        internal static void Process()
        {
            if (!System.IO.File.Exists(FileName))
            {
                MessageBox.Show("The selected folder does not contain a valid train.dat \r\n Please retry.", "CarXML Convertor", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            string[] Lines = System.IO.File.ReadAllLines(FileName);
            for (int i = 0; i < Lines.Length; i++)
            {
                int n = 0;
                switch (Lines[i].ToLowerInvariant())
                {
                case "#cockpit":
                case "#cab":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 0: ConvertSoundCfg.DriverPosition.X = 0.001 * a; break;

                            case 1: ConvertSoundCfg.DriverPosition.Y = 0.001 * a; break;

                            case 2: ConvertSoundCfg.DriverPosition.Z = 0.001 * a; break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                case "#car":
                    i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        double a; if (NumberFormats.TryParseDoubleVb6(Lines[i], out a))
                        {
                            switch (n)
                            {
                            case 4:
                                if (a <= 0.0)
                                {
                                    break;
                                }
                                else
                                {
                                    ConvertSoundCfg.length = a;
                                }
                                break;
                            }
                        }
                        i++; n++;
                    }
                    i--; break;

                default:
                {
                    i++;
                    while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal))
                    {
                        i++; n++;
                    }
                    i--;
                }
                break;
                }
            }
        }