diff --git a/source/OpenBVE/System/Loading.cs b/source/OpenBVE/System/Loading.cs
index 67847a071d..8905d4c9c6 100644
--- a/source/OpenBVE/System/Loading.cs
+++ b/source/OpenBVE/System/Loading.cs
@@ -200,6 +200,27 @@ private static void LoadEverythingThreaded() {
Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableRoutePluginCount + " Route loading plugins available.");
Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableObjectPluginCount + " Object loading plugins available.");
Program.FileSystem.AppendToLogFile("INFO: " + Program.CurrentHost.AvailableRoutePluginCount + " Sound loading plugins available.");
+
+ // initialize trains
+ Program.TrainManager.Trains = new TrainBase[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length + 1 + (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0 ? 1 : 0)];
+ for (int k = 0; k < Program.TrainManager.Trains.Length; k++)
+ {
+ if (k == Program.TrainManager.Trains.Length - 1 & Program.CurrentRoute.BogusPreTrainInstructions.Length != 0) {
+ Program.TrainManager.Trains[k] = new TrainBase(TrainState.Bogus);
+ } else {
+ Program.TrainManager.Trains[k] = new TrainBase(TrainState.Pending);
+ }
+
+ }
+ TrainManager.PlayerTrain = Program.TrainManager.Trains[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length];
+
+ // load player train plugin
+ if (!TrainManager.PlayerTrain.LoadCustomPlugin(CurrentTrainFolder, CurrentTrainEncoding))
+ {
+ TrainManager.PlayerTrain.LoadDefaultPlugin(CurrentTrainFolder);
+ }
+
+ // load route
for (int i = 0; i < Program.CurrentHost.Plugins.Length; i++)
{
if (Program.CurrentHost.Plugins[i].Route != null && Program.CurrentHost.Plugins[i].Route.CanLoadRoute(CurrentRouteFile))
@@ -262,24 +283,8 @@ private static void LoadEverythingThreaded() {
Program.FileSystem.AppendToLogFile("The processed route file only contains a single station.");
}
Program.FileSystem.AppendToLogFile("Route file loaded successfully.");
- // initialize trains
- System.Threading.Thread.Sleep(1); if (Cancel) return;
- Program.TrainManager.Trains = new TrainBase[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length + 1 + (Program.CurrentRoute.BogusPreTrainInstructions.Length != 0 ? 1 : 0)];
- for (int k = 0; k < Program.TrainManager.Trains.Length; k++)
- {
- if (k == Program.TrainManager.Trains.Length - 1 & Program.CurrentRoute.BogusPreTrainInstructions.Length != 0)
- {
- Program.TrainManager.Trains[k] = new TrainBase(TrainState.Bogus);
- }
- else
- {
- Program.TrainManager.Trains[k] = new TrainBase(TrainState.Pending);
- }
-
- }
- TrainManager.PlayerTrain = Program.TrainManager.Trains[Program.CurrentRoute.PrecedingTrainTimeDeltas.Length];
-
+ System.Threading.Thread.Sleep(1); if (Cancel) return;
// load trains
for (int k = 0; k < Program.TrainManager.Trains.Length; k++) {
@@ -312,6 +317,7 @@ private static void LoadEverythingThreaded() {
train.Specs.DoorCloseMode = DoorMode.Manual;
}
}
+
// finished created objects
System.Threading.Thread.Sleep(1); if (Cancel) return;
Array.Resize(ref ObjectManager.AnimatedWorldObjects, ObjectManager.AnimatedWorldObjectsUsed);
@@ -319,19 +325,15 @@ private static void LoadEverythingThreaded() {
if (Program.CurrentRoute.Sections.Length > 0) {
Program.CurrentRoute.UpdateAllSections();
}
- // load plugin
-
+ // load other train plugin
CurrentTrain = 0;
for (int i = 0; i < Program.TrainManager.Trains.Length; i++) {
if ( Program.TrainManager.Trains[i].State != TrainState.Bogus) {
- if ( Program.TrainManager.Trains[i].IsPlayerTrain) {
- if (! Program.TrainManager.Trains[i].LoadCustomPlugin(Program.TrainManager.Trains[i].TrainFolder, CurrentTrainEncoding)) {
- Program.TrainManager.Trains[i].LoadDefaultPlugin(Program.TrainManager.Trains[i].TrainFolder);
- }
- } else {
+ if (!Program.TrainManager.Trains[i].IsPlayerTrain) {
Program.TrainManager.Trains[i].LoadDefaultPlugin( Program.TrainManager.Trains[i].TrainFolder);
}
+ Program.TrainManager.Trains[i].InitializePlugin();
for (int j = 0; j < InputDevicePlugin.AvailablePluginInfos.Count; j++) {
if (InputDevicePlugin.AvailablePluginInfos[j].Status == InputDevicePlugin.PluginInfo.PluginStatus.Enable && InputDevicePlugin.AvailablePlugins[j] is ITrainInputDevice)
{
diff --git a/source/OpenBveApi/System/Files.cs b/source/OpenBveApi/System/Files.cs
deleted file mode 100644
index 36bdaba349..0000000000
--- a/source/OpenBveApi/System/Files.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.IO;
-
-namespace OpenBveApi
-{
- /// Provides helper functions for working with specific file formats, which may not be uniquely identifiable
- public static class FileFormats
- {
- /// Whether the file is Nautilus
- public static bool IsNautilusFile(string path)
- {
- /*
- * Encryption used by certain Chinese items.
- * This is NOT supported or encouraged in any manner by the OpenBVE project,
- * and this detection is provided as a courtesy only.
- */
- try
- {
- using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
- {
- if (stream.Length < 32)
- {
- return false;
- }
- using (BinaryReader reader = new BinaryReader(stream))
- {
- byte[] readBytes = reader.ReadBytes(16);
- return (BitConverter.ToUInt32(readBytes, 0) == 0x554c544eu && BitConverter.ToUInt32(readBytes, 4) == 0x4d524453u
- && BitConverter.ToUInt32(readBytes, 8) == 0x14131211u && BitConverter.ToUInt32(readBytes, 12) == 0x00811919u);
- }
- }
- }
- catch
- {
- return false;
- }
-
- }
-
- }
-}
diff --git a/source/OpenBveApi/System/Interop.cs b/source/OpenBveApi/System/Interop.cs
index f78949a825..8bed5ca027 100644
--- a/source/OpenBveApi/System/Interop.cs
+++ b/source/OpenBveApi/System/Interop.cs
@@ -1,4 +1,4 @@
-using System.ServiceModel;
+using System.ServiceModel;
using OpenBveApi.Runtime;
namespace OpenBveApi.Interop
@@ -14,11 +14,16 @@ public interface IAtsPluginProxy
void SetPluginFile(string fileName, int SimulationProcessID);
/// Called to load and initialize the plugin.
+ /// Whether loading the plugin was successful.
+ [OperationContract]
+ bool Load();
+
+ /// Called to initialize the plugin.
/// The train specifications.
/// The initialization mode of the train.
- /// Whether loading the plugin was successful.
+ /// Whether initializing the plugin was successful.
[OperationContract]
- bool Load(VehicleSpecs specs, InitializationModes mode);
+ bool Initialize(VehicleSpecs specs, InitializationModes mode);
/// Called to unload the plugin
[OperationContract]
diff --git a/source/Plugins/Object.CsvB3d/Plugin.cs b/source/Plugins/Object.CsvB3d/Plugin.cs
index 8663a200a8..8aae24c0d8 100644
--- a/source/Plugins/Object.CsvB3d/Plugin.cs
+++ b/source/Plugins/Object.CsvB3d/Plugin.cs
@@ -1,4 +1,4 @@
-using OpenBveApi;
+using OpenBveApi;
using OpenBveApi.FileSystem;
using OpenBveApi.Hosts;
using OpenBveApi.Interface;
@@ -30,10 +30,6 @@ public override bool CanLoadObject(string path)
path = path.ToLowerInvariant();
if (path.EndsWith(".b3d") || path.EndsWith(".csv"))
{
- if (System.IO.File.Exists(path) && FileFormats.IsNautilusFile(path))
- {
- return false;
- }
return true;
}
diff --git a/source/Plugins/Texture.BmpGifJpegPngTiff/Plugin.cs b/source/Plugins/Texture.BmpGifJpegPngTiff/Plugin.cs
index 65e323a60a..8ef94d7000 100644
--- a/source/Plugins/Texture.BmpGifJpegPngTiff/Plugin.cs
+++ b/source/Plugins/Texture.BmpGifJpegPngTiff/Plugin.cs
@@ -78,10 +78,6 @@ public override bool QueryTextureDimensions(string path, out int width, out int
/// Whether the plugin can load the specified texture.
public override bool CanLoadTexture(string path) {
if (File.Exists(path)) {
- if (FileFormats.IsNautilusFile(path))
- {
- return false;
- }
using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) {
using (BinaryReader reader = new BinaryReader(stream)) {
if (stream.Length < 8)
diff --git a/source/Plugins/Win32PluginProxy/Win32PluginProxy.cs b/source/Plugins/Win32PluginProxy/Win32PluginProxy.cs
index a114226207..bcc4ebac81 100644
--- a/source/Plugins/Win32PluginProxy/Win32PluginProxy.cs
+++ b/source/Plugins/Win32PluginProxy/Win32PluginProxy.cs
@@ -1,4 +1,4 @@
-//Simplified BSD License (BSD-2-Clause)
+//Simplified BSD License (BSD-2-Clause)
//
//Copyright (c) 2020, Christopher Lees, The OpenBVE Project
//
@@ -75,7 +75,7 @@ public void SetPluginFile(string fileName, int simulationProcessID)
this.PluginFile = fileName;
}
- public bool Load(VehicleSpecs specs, InitializationModes mode)
+ public bool Load()
{
int result;
try
@@ -133,8 +133,20 @@ public bool Load(VehicleSpecs specs, InitializationModes mode)
return false;
}
- try
- {
+ Console.WriteLine(@"Plugin loaded successfully.");
+ if (PanelHandle.IsAllocated) {
+ PanelHandle.Free();
+ }
+ if (SoundHandle.IsAllocated) {
+ SoundHandle.Free();
+ }
+ PanelHandle = GCHandle.Alloc(Panel, GCHandleType.Pinned);
+ SoundHandle = GCHandle.Alloc(Sound, GCHandleType.Pinned);
+ return true;
+ }
+
+ public bool Initialize(VehicleSpecs specs, InitializationModes mode) {
+ try {
Win32VehicleSpec win32Spec;
win32Spec.BrakeNotches = specs.BrakeNotches;
win32Spec.PowerNotches = specs.PowerNotches;
@@ -142,33 +154,19 @@ public bool Load(VehicleSpecs specs, InitializationModes mode)
win32Spec.B67Notch = specs.B67Notch;
win32Spec.Cars = specs.Cars;
Win32SetVehicleSpec(ref win32Spec.BrakeNotches);
- }
- catch (Exception ex)
- {
+ } catch (Exception ex) {
Callback.ReportError("Error loading Win32 plugin: " + ex);
return false;
}
- try
- {
+ try {
Console.WriteLine(@"Initializing in mode: " + mode);
- Win32Initialize((int) mode);
- }
- catch (Exception ex)
- {
+ Win32Initialize((int)mode);
+ } catch (Exception ex) {
Callback.ReportError("Error loading Win32 plugin: " + ex);
return false;
}
- Console.WriteLine(@"Plugin loaded successfully.");
- if (PanelHandle.IsAllocated) {
- PanelHandle.Free();
- }
- if (SoundHandle.IsAllocated) {
- SoundHandle.Free();
- }
- PanelHandle = GCHandle.Alloc(Panel, GCHandleType.Pinned);
- SoundHandle = GCHandle.Alloc(Sound, GCHandleType.Pinned);
return true;
}
diff --git a/source/TrainManager/SafetySystems/Plugin/LegacyPlugin.cs b/source/TrainManager/SafetySystems/Plugin/LegacyPlugin.cs
index a5f71d9610..d2ab398bec 100644
--- a/source/TrainManager/SafetySystems/Plugin/LegacyPlugin.cs
+++ b/source/TrainManager/SafetySystems/Plugin/LegacyPlugin.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Threading;
@@ -163,7 +163,7 @@ internal Win32Plugin(string pluginFile, TrainBase train)
}
// --- functions ---
- public override bool Load(VehicleSpecs specs, InitializationModes mode)
+ public override bool Load()
{
int result;
bool retry = true;
@@ -235,8 +235,24 @@ public override bool Load(VehicleSpecs specs, InitializationModes mode)
return false;
}
- try
+ if (PanelHandle.IsAllocated)
{
+ PanelHandle.Free();
+ }
+
+ if (SoundHandle.IsAllocated)
+ {
+ SoundHandle.Free();
+ }
+
+ PanelHandle = GCHandle.Alloc(Panel, GCHandleType.Pinned);
+ SoundHandle = GCHandle.Alloc(Sound, GCHandleType.Pinned);
+ return true;
+ }
+
+ public override bool Initialize(VehicleSpecs specs, InitializationModes mode) {
+
+ try {
Win32VehicleSpec win32Spec;
win32Spec.BrakeNotches = specs.BrakeNotches;
win32Spec.PowerNotches = specs.PowerNotches;
@@ -244,19 +260,14 @@ public override bool Load(VehicleSpecs specs, InitializationModes mode)
win32Spec.B67Notch = specs.B67Notch;
win32Spec.Cars = specs.Cars;
Win32SetVehicleSpec(ref win32Spec.BrakeNotches);
- }
- catch (Exception ex)
- {
+ } catch (Exception ex) {
base.LastException = ex;
throw;
}
- try
- {
- Win32Initialize((int) mode);
- }
- catch (Exception ex)
- {
+ try {
+ Win32Initialize((int)mode);
+ } catch (Exception ex) {
base.LastException = ex;
throw;
}
@@ -264,18 +275,7 @@ public override bool Load(VehicleSpecs specs, InitializationModes mode)
UpdatePower();
UpdateBrake();
UpdateReverser();
- if (PanelHandle.IsAllocated)
- {
- PanelHandle.Free();
- }
- if (SoundHandle.IsAllocated)
- {
- SoundHandle.Free();
- }
-
- PanelHandle = GCHandle.Alloc(Panel, GCHandleType.Pinned);
- SoundHandle = GCHandle.Alloc(Sound, GCHandleType.Pinned);
return true;
}
diff --git a/source/TrainManager/SafetySystems/Plugin/NetPlugin.cs b/source/TrainManager/SafetySystems/Plugin/NetPlugin.cs
index 9772f2bda4..9806add88d 100644
--- a/source/TrainManager/SafetySystems/Plugin/NetPlugin.cs
+++ b/source/TrainManager/SafetySystems/Plugin/NetPlugin.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Threading;
using OpenBveApi;
using OpenBveApi.Colors;
@@ -80,7 +80,7 @@ internal NetPlugin(string pluginFile, string trainFolder, IRuntime api, TrainBas
}
// --- functions ---
- public override bool Load(VehicleSpecs specs, InitializationModes mode)
+ public override bool Load()
{
LoadProperties properties = new LoadProperties(this.PluginFolder, this.TrainFolder, this.PlaySound, this.PlaySound, this.AddInterfaceMessage, this.AddScore);
bool success;
@@ -107,20 +107,6 @@ public override bool Load(VehicleSpecs specs, InitializationModes mode)
if (success)
{
base.Panel = properties.Panel ?? new int[] { };
-#if !DEBUG
- try {
-#endif
- Api.SetVehicleSpecs(specs);
- Api.Initialize(mode);
-#if !DEBUG
- } catch (Exception ex) {
- base.LastException = ex;
- throw;
- }
-#endif
- UpdatePower();
- UpdateBrake();
- UpdateReverser();
return true;
}
@@ -133,6 +119,53 @@ public override bool Load(VehicleSpecs specs, InitializationModes mode)
return false;
}
+ public bool PreLoad() {
+ LoadProperties properties = new LoadProperties(this.PluginFolder, this.TrainFolder, this.PlaySound, this.PlaySound, this.AddInterfaceMessage, this.AddScore);
+ var preLoadMethod = Api.GetType().GetMethod("PreLoad");
+ if (preLoadMethod == null
+ || preLoadMethod.GetParameters().Length != 1
+ || preLoadMethod.GetParameters()[0].ParameterType != typeof(LoadProperties)
+ || preLoadMethod.ReturnType != typeof(bool)
+ ) return true;
+
+ bool success;
+ try {
+ success = (bool)preLoadMethod.Invoke(Api, new object[] { properties });
+ } catch (Exception ex) {
+ success = false;
+ properties.FailureReason = ex.Message;
+ }
+
+ if (success) {
+ return true;
+ }
+
+ if (properties.FailureReason != null) {
+ TrainManagerBase.currentHost.AddMessage(MessageType.Error, false, "The train plugin " + base.PluginTitle + " failed to preload for the following reason: " + properties.FailureReason);
+ return false;
+ }
+ TrainManagerBase.currentHost.AddMessage(MessageType.Error, false, "The train plugin " + base.PluginTitle + " failed to preload for an unspecified reason.");
+ return false;
+ }
+
+ public override bool Initialize(VehicleSpecs specs, InitializationModes mode) {
+#if !DEBUG
+ try {
+#endif
+ Api.SetVehicleSpecs(specs);
+ Api.Initialize(mode);
+#if !DEBUG
+ } catch (Exception ex) {
+ base.LastException = ex;
+ throw;
+ }
+#endif
+ UpdatePower();
+ UpdateBrake();
+ UpdateReverser();
+ return true;
+ }
+
public override void Unload()
{
#if !DEBUG
diff --git a/source/TrainManager/SafetySystems/Plugin/Plugin.Functions.cs b/source/TrainManager/SafetySystems/Plugin/Plugin.Functions.cs
index 7c06b9fccd..d9207c5291 100644
--- a/source/TrainManager/SafetySystems/Plugin/Plugin.Functions.cs
+++ b/source/TrainManager/SafetySystems/Plugin/Plugin.Functions.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Reflection;
using OpenBveApi.Hosts;
using OpenBveApi.Interface;
@@ -152,11 +152,6 @@ public bool LoadPlugin(string pluginFile, string trainFolder)
UnloadPlugin();
}
- /*
- * Prepare initialization data for the plugin.
- * */
-
- InitializationModes mode = (InitializationModes) TrainManagerBase.CurrentOptions.TrainStart;
/*
* Check if the plugin is a .NET plugin.
* */
@@ -218,15 +213,10 @@ public bool LoadPlugin(string pluginFile, string trainFolder)
IRuntime api = assembly.CreateInstance(type.FullName) as IRuntime;
Plugin = new NetPlugin(pluginFile, trainFolder, api, this);
- if (Plugin.Load(vehicleSpecs(), mode))
- {
- return true;
- }
- else
- {
- Plugin = null;
+ if (!(Plugin as NetPlugin).PreLoad()) {
return false;
}
+ return true;
}
}
@@ -254,23 +244,16 @@ public bool LoadPlugin(string pluginFile, string trainFolder)
if (TrainManagerBase.currentHost.Platform != HostPlatform.MicrosoftWindows | IntPtr.Size != 4)
{
- if (TrainManagerBase.currentHost.Platform == HostPlatform.MicrosoftWindows && IntPtr.Size != 4)
- {
+ if (TrainManagerBase.currentHost.Platform == HostPlatform.MicrosoftWindows && IntPtr.Size != 4) {
//We can't load the plugin directly on x64 Windows, so use the proxy interface
Plugin = new ProxyPlugin(pluginFile, this);
- if (Plugin.Load(vehicleSpecs(), mode))
- {
- return true;
- }
+ return true;
+ } else {
- Plugin = null;
- TrainManagerBase.currentHost.AddMessage(MessageType.Error, false, "The train plugin " + pluginTitle + " failed to load.");
+ //WINE doesn't seem to like the WCF proxy :(
+ TrainManagerBase.currentHost.AddMessage(MessageType.Warning, false, "The train plugin " + pluginTitle + " can only be used on Microsoft Windows or compatible.");
return false;
}
-
- //WINE doesn't seem to like the WCF proxy :(
- TrainManagerBase.currentHost.AddMessage(MessageType.Warning, false, "The train plugin " + pluginTitle + " can only be used on Microsoft Windows or compatible.");
- return false;
}
if (TrainManagerBase.currentHost.Platform == HostPlatform.MicrosoftWindows && !System.IO.File.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\AtsPluginProxy.dll"))
@@ -280,16 +263,8 @@ public bool LoadPlugin(string pluginFile, string trainFolder)
}
Plugin = new Win32Plugin(pluginFile, this);
- if (Plugin.Load(vehicleSpecs(), mode))
- {
- return true;
- }
- else
- {
- Plugin = null;
- TrainManagerBase.currentHost.AddMessage(MessageType.Error, false, "The train plugin " + pluginTitle + " does not export a train interface and therefore cannot be used with openBVE.");
- return false;
- }
+ return true;
+
}
/// Loads the default plugin for the specified train.
@@ -305,6 +280,26 @@ public void LoadDefaultPlugin(string trainFolder)
}
}
+ public bool InitializePlugin() {
+ if (!Plugin.Load()) {
+ Plugin = null;
+ TrainManagerBase.currentHost.AddMessage(MessageType.Error, false, "The train plugin " + Plugin.PluginTitle + " failed to load.");
+ return false;
+ }
+
+ /*
+ * Prepare initialization data for the plugin.
+ * */
+
+ InitializationModes mode = (InitializationModes)TrainManagerBase.CurrentOptions.TrainStart;
+
+ if (!Plugin.Initialize(vehicleSpecs(), mode)) {
+ return false;
+ }
+
+ return true;
+ }
+
/// Unloads the currently loaded plugin, if any.
public void UnloadPlugin()
{
diff --git a/source/TrainManager/SafetySystems/Plugin/Plugin.cs b/source/TrainManager/SafetySystems/Plugin/Plugin.cs
index f51470d744..b0d29330ff 100644
--- a/source/TrainManager/SafetySystems/Plugin/Plugin.cs
+++ b/source/TrainManager/SafetySystems/Plugin/Plugin.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using OpenBveApi.Interface;
using OpenBveApi.Runtime;
@@ -69,11 +69,15 @@ public abstract class Plugin
internal PluginAI AI;
// --- functions ---
- /// Called to load and initialize the plugin.
+ /// Called to load the plugin.
+ /// Whether loading the plugin was successful.
+ public abstract bool Load();
+
+ /// Called to initialize the plugin.
/// The train specifications.
/// The initialization mode of the train.
- /// Whether loading the plugin was successful.
- public abstract bool Load(VehicleSpecs specs, InitializationModes mode);
+ /// Whether initializing the plugin was successful.
+ public abstract bool Initialize(VehicleSpecs specs, InitializationModes mode);
/// Called to unload the plugin.
public abstract void Unload();
diff --git a/source/TrainManager/SafetySystems/Plugin/ProxyPlugin.cs b/source/TrainManager/SafetySystems/Plugin/ProxyPlugin.cs
index aba7e8faa9..12267c30d8 100644
--- a/source/TrainManager/SafetySystems/Plugin/ProxyPlugin.cs
+++ b/source/TrainManager/SafetySystems/Plugin/ProxyPlugin.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.ServiceModel;
@@ -76,15 +76,22 @@ internal ProxyPlugin(string pluginFile, TrainBase train)
[DllImport("User32.dll")]
public static extern Int32 SetForegroundWindow(int hWnd);
- public override bool Load(VehicleSpecs specs, InitializationModes mode)
+ public override bool Load()
{
if (externalCrashed)
{
//Most likely the plugin proxy app failed to launch or something
return false;
}
- if (pipeProxy.Load(specs, mode))
+ if (pipeProxy.Load())
{
+ return true;
+ }
+ return false;
+ }
+
+ public override bool Initialize(VehicleSpecs specs, InitializationModes mode) {
+ if (pipeProxy.Initialize(specs, mode)) {
UpdatePower();
UpdateBrake();
UpdateReverser();