Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions source/Plugins/Formats.OpenBve/Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,148 @@ public virtual bool GetNextRawValue(out string s)
return false;
}

/// <summary>Gets the next double from the block</summary>
public virtual bool GetNextDouble(T2 key, NumberRange range, out double d)
{
d = -1;
if (rawValues.Count > 0)
{
KeyValuePair<int, string> value = rawValues.Dequeue();
if(NumberFormats.TryParseDoubleVb6(value.Value, out double newValue))
{
switch (range)
{
case NumberRange.Any:
d = newValue;
return true;
case NumberRange.Positive:
if (newValue > 0)
{
d = newValue;
return true;
}
currentHost.AddMessage(MessageType.Warning, false, "Value " + newValue + " is not a positive double in Key " + key + " in Section " + Key + " at line " + value.Key);
return false;
case NumberRange.NonNegative:
if (newValue >= 0)
{
d = newValue;
return true;
}
currentHost.AddMessage(MessageType.Warning, false, "Value " + newValue + " is not a non-negative double in Key " + key + " in Section " + Key + " at line " + value.Key);
return false;
case NumberRange.NonZero:
if (newValue != 0)
{
d = newValue;
return true;
}
currentHost.AddMessage(MessageType.Warning, false, "Value " + newValue + " is not a non-zero double in Key " + key + " in Section " + Key + " at line " + value.Key);
return false;
}
}

currentHost.AddMessage("Value is invalid in " + key + " in " + Key + " at line " + value.Key + " in file " + FileName);
}
return false;
}

public virtual bool GetNextInt(T2 key, NumberRange range, out int d)
{
d = -1;
if (rawValues.Count > 0)
{
KeyValuePair<int, string> value = rawValues.Dequeue();
if (NumberFormats.TryParseIntVb6(value.Value, out int newValue))
{
switch (range)
{
case NumberRange.Any:
d = newValue;
return true;
case NumberRange.Positive:
if (newValue > 0)
{
d = newValue;
return true;
}
currentHost.AddMessage(MessageType.Warning, false, "Value " + newValue + " is not a positive double in Key " + key + " in Section " + Key + " at line " + value.Key);
return false;
case NumberRange.NonNegative:
if (newValue >= 0)
{
d = newValue;
return true;
}
currentHost.AddMessage(MessageType.Warning, false, "Value " + newValue + " is not a non-negative double in Key " + key + " in Section " + Key + " at line " + value.Key);
return false;
case NumberRange.NonZero:
if (newValue != 0)
{
d = newValue;
return true;
}
currentHost.AddMessage(MessageType.Warning, false, "Value " + newValue + " is not a non-zero double in Key " + key + " in Section " + Key + " at line " + value.Key);
return false;
}
}

currentHost.AddMessage("Value is invalid in " + key + " in " + Key + " at line " + value.Key + " in file " + FileName);
}
return false;
}

public virtual bool GetNextBool(T2 key, out bool b)
{
if (rawValues.Count > 0)
{
KeyValuePair<int, string> value = rawValues.Dequeue();
int i = int.Parse(value.Value);
b = i == 1;
return true;
}

b = false;
return false;
}

public virtual bool GetNextDoubleArray(char separator, out double[] array)
{
if (rawValues.Count > 0)
{
string s = rawValues.Dequeue().Value;
string[] splitString = s.Split(separator);
array = new double[splitString.Length];
for (int i = 0; i < array.Length; i++)
{
if (!NumberFormats.TryParseDoubleVb6(splitString[i], out array[i]))
{
Array.Resize(ref array, i);
break;
}
}

return true;
}

array = Array.Empty<double>();
return false;
}

public virtual bool GetNextEnumValue<T3>(T2 key, out T3 enumValue) where T3 : struct, Enum
{
if (rawValues.Count > 0)
{
string s = rawValues.Dequeue().Value;
if (Enum.TryParse(s, out enumValue) && Enum.IsDefined(typeof(T3), enumValue))
{
return true;
}
}
enumValue = default(T3);
return false;
}

public virtual bool GetNextPath(string absolutePath, out string finalPath)
{
if (rawValues.Count > 0)
Expand Down
165 changes: 165 additions & 0 deletions source/Plugins/Formats.OpenBve/DAT/TrainDat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
using OpenBveApi.Hosts;
using OpenBveApi.Math;
using System;
using System.Collections.Generic;
using System.IO;
using OpenBveApi.Interface;

namespace Formats.OpenBve
{
/// <summary>Root block for a .CFG type file</summary>
public class TrainDatFile<T1, T2> : Block<T1, T2> where T1 : struct, Enum where T2 : struct, Enum
{
/// <summary>The format of the current file</summary>
public readonly TrainDatFormats Format;

public readonly int Version;
public TrainDatFile(string myFile, HostInterface currentHost) : base(-1, default, myFile, currentHost)
{
string[] lines = File.ReadAllLines(myFile);
List<string> blockLines = new List<string>();
bool addToBlock = false;
T1 previousSection = default(T1);
bool formatFound = false;
int startingLine = 0;
Version = 0;
for (int i = 0; i < lines.Length; i++)
{
int semiColon = lines[i].IndexOf(';');
if (semiColon != -1)
{
lines[i] = lines[i].Substring(0, semiColon);
}
lines[i] = lines[i].Trim();
if (lines[i].Length > 0 && !formatFound)
{
formatFound = true;
Format = ParseFormat(lines[i], out Version);
}

const int currentVersion = 18230;

switch (Format)
{
case TrainDatFormats.openBVE when Version == -1:
currentHost.AddMessage(MessageType.Error, false, "The train.dat version is invalid in " + FileName);
break;
case TrainDatFormats.openBVE:
{
if (Version > currentVersion)
{
currentHost.AddMessage(MessageType.Warning, false, "The train.dat " + FileName + " with version " + Version + " was created with a newer version of openBVE. Please check for an update.");
}
break;
}
case TrainDatFormats.Unsupported:
currentHost.AddMessage(MessageType.Error, false, "The train.dat format " + Version + " is not supported in " + FileName);
break;
case TrainDatFormats.UnknownBVE:
currentHost.AddMessage(MessageType.Error, false, "The train.dat appears to have been created by an unknown BVE version in " + FileName + " - Please report this.");
break;
case TrainDatFormats.MissingHeader:
currentHost.AddMessage(MessageType.Error, false, "The train.dat appears be missing the required header in " + FileName + " - Please report this.");
break;
}

if (lines[i].Length > 0 && lines[i][0] == '#')
{
if (!Enum.TryParse(lines[i].Substring(1), true, out T1 currentSection))
{
addToBlock = false;
}
else
{
addToBlock = true;
}

if (blockLines.Count > 0)
{
subBlocks.Add(new TrainDatSection<T1, T2>(blockLines, previousSection, startingLine + 1, myFile, currentHost));
blockLines.Clear();
}

startingLine = i;
previousSection = currentSection;
}
else
{
if (addToBlock && !string.IsNullOrEmpty(lines[i]))
{
blockLines.Add(lines[i]);
}
}
}

if (blockLines.Count > 0)
{
subBlocks.Add(new TrainDatSection<T1, T2>(blockLines, previousSection, startingLine, myFile, currentHost));
}
}



/// <summary>Parse the format of the specified train.dat</summary>
/// <param name="line">The version line of the train.dat</param>
/// <param name="version">The version of the specified OpenBVE train.dat</param>
public static TrainDatFormats ParseFormat(string line, out int version)
{
version = -1;
switch (line.ToLowerInvariant())
{
case "bve1200000":
return TrainDatFormats.BVE1200000;
case "bve1210000":
return TrainDatFormats.BVE1210000;
case "bve1220000":
return TrainDatFormats.BVE1220000;
case "bve2000000":
return TrainDatFormats.BVE2000000;
case "bve2060000":
return TrainDatFormats.BVE2060000;
case "openbve":
version = 0;
return TrainDatFormats.openBVE;
case "#acceleration":
case "#deceleration":
case "#delay":
case "#move":
case "#brake":
case "#pressure":
case "#handle":
case "#cab":
case "#car":
case "#device":
case "motor_p1":
case "motor_p2":
case "brake_p1":
case "brake_p2":
version = 0;
return TrainDatFormats.MissingHeader;
default:
if (line.ToLowerInvariant().StartsWith("openbve"))
{
string tt = line.Substring(7, line.Length - 7).Trim();
if (!NumberFormats.TryParseIntVb6(tt, out version))
{
version = -1;
}
return TrainDatFormats.openBVE;
}

return line.ToLowerInvariant().StartsWith("bve") ? TrainDatFormats.UnknownBVE : TrainDatFormats.Unsupported;
}
}
}
public class TrainDatSection<T1, T2> : Block<T1, T2> where T1 : struct, Enum where T2 : struct, Enum
{
public TrainDatSection(List<string> blockLines, T1 myKey, int startingLine, string myFile, HostInterface currentHost) : base(-1, myKey, myFile, currentHost)
{
for (int i = 0; i < blockLines.Count; i++)
{
rawValues.Enqueue(new KeyValuePair<int, string>(startingLine + i, blockLines[i]));
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// ReSharper disable InconsistentNaming
namespace Train.OpenBve
namespace Formats.OpenBve
{
/// <summary>The different train.dat format types</summary>
internal enum TrainDatFormats
public enum TrainDatFormats
{
/// <summary>The train.dat format string is unsupported</summary>
Unsupported = -1,
Expand Down
56 changes: 56 additions & 0 deletions source/Plugins/Formats.OpenBve/Enums/TrainDat/TrainDatKey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
namespace Formats.OpenBve
{
public enum TrainDatKey
{
BrakeDeceleration,
CoefficientOfStaticFriction,
CoefficientOfRollingResistance,
CoefficientOfAerodynamicDrag,
ElectricBrakeDelayUp,
ElectricBrakeDelayDown,
JerkPowerUp,
JerkPowerDown,
JerkBrakeUp,
JerkBrakeDown,
BrakeCylinderUp,
BrakeCylinderDown,
BrakeSystemType,
ElectropneumaticType,
BrakeControlSpeed,
LocoBrakeType,
BrakeCylinderServiceMaximumPressure,
BrakeCylinderEmergencyMaximumPressure,
MainReservoirMinimumPressure,
MainReservoirMaximumPressure,
BrakePipePressure,
HandleType,
NumberOfPowerNotches,
NumberOfBrakeNotches,
PowerReduceSteps,
EbHandleBehaviour,
LocoBrakeNotches,
DriverPowerNotches,
DriverBrakeNotches,
DriverX,
DriverY,
DriverZ,
MotorCarMass,
NumberOfMotorCars,
TrailerCarMass,
NumberOfTrailerCars,
CarLength,
FrontCarIsMotorCar,
LengthOfCar,
WidthOfCar,
HeightOfCar,
ExposedFrontalArea,
UnexposedFrontalArea,
DefaultSafetySystems,
ReAdhesionDeviceType,
PassAlarm,
DoorOpenMode,
DoorCloseMode,
DoorWidth,
DoorMaxTolerance,
}
}
Loading