Skip to content

Commit e1e89a3

Browse files
committed
Fix: Crash in plugin updates caused by a station with no stops
1 parent eb8348a commit e1e89a3

File tree

4 files changed

+264
-229
lines changed

4 files changed

+264
-229
lines changed

source/OpenBVE/OldCode/PluginManager.cs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ internal abstract class Plugin {
6161
internal abstract void EndJump();
6262
/// <summary>Called every frame to update the plugin.</summary>
6363
internal void UpdatePlugin() {
64+
if (Train.Cars == null || Train.Cars.Length == 0)
65+
{
66+
return;
67+
}
6468
/*
6569
* Prepare the vehicle state.
6670
* */
@@ -75,6 +79,11 @@ internal void UpdatePlugin() {
7579
currentRouteStations = new List<Station>();
7680
foreach (Game.Station selectedStation in Game.Stations)
7781
{
82+
double stopPosition = -1;
83+
if (selectedStation.Stops.Length != 0)
84+
{
85+
stopPosition = selectedStation.Stops[Game.GetStopIndex(Train.Station, Train.Cars.Length)].TrackPosition;
86+
}
7887
Station i = new Station
7988
{
8089
Name = selectedStation.Name,
@@ -85,7 +94,7 @@ internal void UpdatePlugin() {
8594
OpenRightDoors = selectedStation.OpenRightDoors,
8695
ForceStopSignal = selectedStation.ForceStopSignal,
8796
DefaultTrackPosition = selectedStation.DefaultTrackPosition,
88-
StopPosition = selectedStation.Stops[Game.GetStopIndex(Train.Station, Train.Cars.Length)].TrackPosition
97+
StopPosition = stopPosition
8998
};
9099
currentRouteStations.Add(i);
91100
}
@@ -104,17 +113,28 @@ internal void UpdatePlugin() {
104113
* */
105114
double bestLocation = double.MaxValue;
106115
double bestSpeed = 0.0;
107-
for (int i = 0; i < TrainManager.Trains.Length; i++) {
108-
if (TrainManager.Trains[i] != this.Train & TrainManager.Trains[i].State == TrainManager.TrainState.Available) {
109-
int c = TrainManager.Trains[i].Cars.Length - 1;
110-
double z = TrainManager.Trains[i].Cars[c].RearAxle.Follower.TrackPosition - TrainManager.Trains[i].Cars[c].RearAxle.Position - 0.5 * TrainManager.Trains[i].Cars[c].Length;
111-
if (z >= location & z < bestLocation) {
112-
bestLocation = z;
113-
bestSpeed = TrainManager.Trains[i].Specs.CurrentAverageSpeed;
116+
PrecedingVehicleState precedingVehicle;
117+
try
118+
{
119+
for (int i = 0; i < TrainManager.Trains.Length; i++)
120+
{
121+
if (TrainManager.Trains[i] != this.Train & TrainManager.Trains[i].State == TrainManager.TrainState.Available & Train.Cars.Length > 0)
122+
{
123+
int c = TrainManager.Trains[i].Cars.Length - 1;
124+
double z = TrainManager.Trains[i].Cars[c].RearAxle.Follower.TrackPosition - TrainManager.Trains[i].Cars[c].RearAxle.Position - 0.5 * TrainManager.Trains[i].Cars[c].Length;
125+
if (z >= location & z < bestLocation)
126+
{
127+
bestLocation = z;
128+
bestSpeed = TrainManager.Trains[i].Specs.CurrentAverageSpeed;
129+
}
114130
}
115131
}
132+
precedingVehicle = bestLocation != double.MaxValue ? new PrecedingVehicleState(bestLocation, bestLocation - location, new Speed(bestSpeed)) : null;
133+
}
134+
catch
135+
{
136+
precedingVehicle = null;
116137
}
117-
var precedingVehicle = bestLocation != double.MaxValue ? new PrecedingVehicleState(bestLocation, bestLocation - location, new Speed(bestSpeed)) : null;
118138
/*
119139
* Get the driver handles.
120140
* */

source/OpenBVE/OldCode/TrainManager.cs

Lines changed: 4 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -322,128 +322,7 @@ internal enum StopSkipMode
322322
Linespeed = 2
323323
}
324324

325-
/// <summary>The root class for a train within the simulation</summary>
326-
public class Train
327-
{
328-
/// <summary>The plugin used by this train.</summary>
329-
internal PluginManager.Plugin Plugin;
330-
internal int TrainIndex;
331-
internal TrainState State;
332-
internal Car[] Cars;
333-
internal Coupler[] Couplers;
334-
internal int DriverCar;
335-
internal TrainSpecs Specs;
336-
internal TrainPassengers Passengers;
337-
internal int LastStation;
338-
internal int Station;
339-
internal bool StationFrontCar;
340-
internal bool StationRearCar;
341-
internal TrainStopState StationState;
342-
internal double StationArrivalTime;
343-
internal double StationDepartureTime;
344-
internal bool StationDepartureSoundPlayed;
345-
internal bool StationAdjust;
346-
internal double StationDistanceToStopPoint;
347-
internal double[] RouteLimits;
348-
internal double CurrentRouteLimit;
349-
internal double CurrentSectionLimit;
350-
internal int CurrentSectionIndex;
351-
internal double TimetableDelta;
352-
internal Game.GeneralAI AI;
353-
internal double InternalTimerTimeElapsed;
354-
internal bool Derailed;
355-
internal StopSkipMode NextStopSkipped = StopSkipMode.None;
356-
357-
/// <summary>Call this method to derail a car</summary>
358-
/// <param name="CarIndex">The car index to derail</param>
359-
/// <param name="ElapsedTime">The elapsed time for this frame (Used for logging)</param>
360-
internal void Derail(int CarIndex, double ElapsedTime)
361-
{
362-
this.Cars[CarIndex].Derailed = true;
363-
this.Derailed = true;
364-
if (Program.GenerateDebugLogging)
365-
{
366-
Program.AppendToLogFile("Train " + TrainIndex + ", Car " + CarIndex + " derailed. Current simulation time: " + Game.SecondsSinceMidnight + " Current frame time: " + ElapsedTime);
367-
}
368-
}
369-
370-
/// <summary>Call this method to topple a car</summary>
371-
/// <param name="CarIndex">The car index to derail</param>
372-
/// <param name="ElapsedTime">The elapsed time for this frame (Used for logging)</param>
373-
internal void Topple(int CarIndex, double ElapsedTime)
374-
{
375-
this.Cars[CarIndex].Topples = true;
376-
if (Program.GenerateDebugLogging)
377-
{
378-
Program.AppendToLogFile("Train " + TrainIndex + ", Car " + CarIndex + " toppled. Current simulation time: " + Game.SecondsSinceMidnight + " Current frame time: " + ElapsedTime);
379-
}
380-
}
381-
382-
/// <summary>Initializes a train with the default (empty) set of car sounds</summary>
383-
internal void InitializeCarSounds()
384-
{
385-
// initialize
386-
for (int i = 0; i < Cars.Length; i++)
387-
{
388-
Cars[i].Sounds.Run = new TrainManager.CarSound[] { };
389-
Cars[i].Sounds.Flange = new TrainManager.CarSound[] { };
390-
Cars[i].Sounds.Adjust = TrainManager.CarSound.Empty;
391-
Cars[i].Sounds.Air = TrainManager.CarSound.Empty;
392-
Cars[i].Sounds.AirHigh = TrainManager.CarSound.Empty;
393-
Cars[i].Sounds.AirZero = TrainManager.CarSound.Empty;
394-
Cars[i].Sounds.Brake = TrainManager.CarSound.Empty;
395-
Cars[i].Sounds.BrakeHandleApply = TrainManager.CarSound.Empty;
396-
Cars[i].Sounds.BrakeHandleMin = TrainManager.CarSound.Empty;
397-
Cars[i].Sounds.BrakeHandleMax = TrainManager.CarSound.Empty;
398-
Cars[i].Sounds.BrakeHandleRelease = TrainManager.CarSound.Empty;
399-
Cars[i].Sounds.BreakerResume = TrainManager.CarSound.Empty;
400-
Cars[i].Sounds.BreakerResumeOrInterrupt = TrainManager.CarSound.Empty;
401-
Cars[i].Sounds.CpEnd = TrainManager.CarSound.Empty;
402-
Cars[i].Sounds.CpLoop = TrainManager.CarSound.Empty;
403-
Cars[i].Sounds.CpStart = TrainManager.CarSound.Empty;
404-
Cars[i].Sounds.DoorCloseL = TrainManager.CarSound.Empty;
405-
Cars[i].Sounds.DoorCloseR = TrainManager.CarSound.Empty;
406-
Cars[i].Sounds.DoorOpenL = TrainManager.CarSound.Empty;
407-
Cars[i].Sounds.DoorOpenR = TrainManager.CarSound.Empty;
408-
Cars[i].Sounds.EmrBrake = TrainManager.CarSound.Empty;
409-
Cars[i].Sounds.Flange = new TrainManager.CarSound[] { };
410-
Cars[i].Sounds.FlangeVolume = new double[] { };
411-
Cars[i].Sounds.Halt = TrainManager.CarSound.Empty;
412-
Cars[i].Sounds.Horns = new TrainManager.Horn[]
413-
{
414-
new TrainManager.Horn(),
415-
new TrainManager.Horn(),
416-
new TrainManager.Horn()
417-
};
418-
Cars[i].Sounds.RequestStop = new CarSound[]
419-
{
420-
//Stop
421-
CarSound.Empty,
422-
//Pass
423-
CarSound.Empty,
424-
//Ignored
425-
CarSound.Empty
426-
};
427-
Cars[i].Sounds.Loop = TrainManager.CarSound.Empty;
428-
Cars[i].Sounds.MasterControllerUp = TrainManager.CarSound.Empty;
429-
Cars[i].Sounds.MasterControllerDown = TrainManager.CarSound.Empty;
430-
Cars[i].Sounds.MasterControllerMin = TrainManager.CarSound.Empty;
431-
Cars[i].Sounds.MasterControllerMax = TrainManager.CarSound.Empty;
432-
Cars[i].Sounds.PilotLampOn = TrainManager.CarSound.Empty;
433-
Cars[i].Sounds.PilotLampOff = TrainManager.CarSound.Empty;
434-
Cars[i].Sounds.PointFrontAxle = new TrainManager.CarSound[] { };
435-
Cars[i].Sounds.PointRearAxle = new TrainManager.CarSound[] { };
436-
Cars[i].Sounds.ReverserOn = TrainManager.CarSound.Empty;
437-
Cars[i].Sounds.ReverserOff = TrainManager.CarSound.Empty;
438-
Cars[i].Sounds.Rub = TrainManager.CarSound.Empty;
439-
Cars[i].Sounds.Run = new TrainManager.CarSound[] { };
440-
Cars[i].Sounds.RunVolume = new double[] { };
441-
Cars[i].Sounds.SpringL = TrainManager.CarSound.Empty;
442-
Cars[i].Sounds.SpringR = TrainManager.CarSound.Empty;
443-
Cars[i].Sounds.Plugin = new TrainManager.CarSound[] { };
444-
}
445-
}
446-
}
325+
447326

448327
// trains
449328
/// <summary>The list of trains available in the simulation.</summary>
@@ -697,7 +576,7 @@ internal static void InitializeTrain(Train Train)
697576
InitializeCar(Train, i);
698577
}
699578
UpdateAtmosphericConstants(Train);
700-
UpdateTrain(Train, 0.0);
579+
Train.Update(0.0);
701580
}
702581

703582
// initialize car
@@ -836,109 +715,14 @@ private static void UpdateTrainObjects(Train Train, int CarIndex, double TimeEla
836715

837716

838717
// update train
839-
internal static void UpdateTrain(Train Train, double TimeElapsed)
840-
{
841-
if (Train.State == TrainState.Pending)
842-
{
843-
// pending train
844-
bool forceIntroduction = Train == PlayerTrain && !Game.MinimalisticSimulation;
845-
double time = 0.0;
846-
if (!forceIntroduction)
847-
{
848-
for (int i = 0; i < Game.Stations.Length; i++)
849-
{
850-
if (Game.Stations[i].StopMode == Game.StationStopMode.AllStop | Game.Stations[i].StopMode == Game.StationStopMode.PlayerPass)
851-
{
852-
if (Game.Stations[i].ArrivalTime >= 0.0)
853-
{
854-
time = Game.Stations[i].ArrivalTime;
855-
}
856-
else if (Game.Stations[i].DepartureTime >= 0.0)
857-
{
858-
time = Game.Stations[i].DepartureTime - Game.Stations[i].StopTime;
859-
}
860-
break;
861-
}
862-
}
863-
time -= Train.TimetableDelta;
864-
}
865-
if (Game.SecondsSinceMidnight >= time | forceIntroduction)
866-
{
867-
bool introduce = true;
868-
if (!forceIntroduction)
869-
{
870-
if (Train.CurrentSectionIndex >= 0)
871-
{
872-
if (!Game.Sections[Train.CurrentSectionIndex].IsFree())
873-
{
874-
introduce = false;
875-
}
876-
}
877-
}
878-
if (introduce)
879-
{
880-
// train is introduced
881-
Train.State = TrainState.Available;
882-
for (int j = 0; j < Train.Cars.Length; j++)
883-
{
884-
if (Train.Cars[j].CarSections.Length != 0)
885-
{
886-
Train.Cars[j].ChangeCarSection(j <= Train.DriverCar | Train != PlayerTrain ? 0 : -1);
887-
}
888-
Train.Cars[j].FrontBogie.ChangeSection(Train != PlayerTrain ? 0 : -1);
889-
Train.Cars[j].RearBogie.ChangeSection(Train != PlayerTrain ? 0 : -1);
890-
if (Train.Cars[j].Specs.IsMotorCar)
891-
{
892-
if (Train.Cars[j].Sounds.Loop.Buffer != null)
893-
{
894-
OpenBveApi.Math.Vector3 pos = Train.Cars[j].Sounds.Loop.Position;
895-
Train.Cars[j].Sounds.Loop.Source = Sounds.PlaySound(Train.Cars[j].Sounds.Loop.Buffer, 1.0, 1.0, pos, Train, j, true);
896-
}
897-
}
898-
}
899-
}
900-
}
901-
}
902-
else if (Train.State == TrainState.Available)
903-
{
904-
// available train
905-
UpdateTrainPhysicsAndControls(Train, TimeElapsed);
906-
if (Interface.CurrentOptions.GameMode == Interface.GameMode.Arcade)
907-
{
908-
if (Train.Specs.CurrentAverageSpeed > Train.CurrentRouteLimit)
909-
{
910-
Game.AddMessage(Interface.GetInterfaceString("message_route_overspeed"), MessageManager.MessageDependency.RouteLimit, Interface.GameMode.Arcade, MessageColor.Orange, double.PositiveInfinity, null);
911-
}
912-
if (Train.CurrentSectionLimit == 0.0)
913-
{
914-
Game.AddMessage(Interface.GetInterfaceString("message_signal_stop"), MessageManager.MessageDependency.SectionLimit, Interface.GameMode.Normal, MessageColor.Red, double.PositiveInfinity, null);
915-
}
916-
else if (Train.Specs.CurrentAverageSpeed > Train.CurrentSectionLimit)
917-
{
918-
Game.AddMessage(Interface.GetInterfaceString("message_signal_overspeed"), MessageManager.MessageDependency.SectionLimit, Interface.GameMode.Normal, MessageColor.Orange, double.PositiveInfinity, null);
919-
}
920-
}
921-
if (Train.AI != null)
922-
{
923-
Train.AI.Trigger(Train, TimeElapsed);
924-
}
925-
}
926-
else if (Train.State == TrainState.Bogus)
927-
{
928-
// bogus train
929-
if (Train.AI != null)
930-
{
931-
Train.AI.Trigger(Train, TimeElapsed);
932-
}
933-
}
934-
}
718+
935719

936720
/// <summary>This method should be called once a frame to update the position, speed and state of all trains within the simulation</summary>
937721
/// <param name="TimeElapsed">The time elapsed since the last call to this function</param>
938722
internal static void UpdateTrains(double TimeElapsed)
939723
{
940724
for (int i = 0; i < Trains.Length; i++) {
941-
UpdateTrain(Trains[i], TimeElapsed);
725+
Trains[i].Update(TimeElapsed);
942726
}
943727
// detect collision
944728
if (!Game.MinimalisticSimulation & Interface.CurrentOptions.Collisions)

source/OpenBVE/OpenBve.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
<Compile Include="Simulation\TrainManager\Station.cs" />
176176
<Compile Include="Simulation\TrainManager\Train\Horn.cs" />
177177
<Compile Include="Simulation\TrainManager\Train\Reverser.cs" />
178+
<Compile Include="Simulation\TrainManager\Train\Train.cs" />
178179
<Compile Include="Simulation\World\BackgroundManager.cs" />
179180
<Compile Include="Simulation\World\Transformations.cs" />
180181
<Compile Include="System\Functions\CrashHandler.cs" />

0 commit comments

Comments
 (0)