C# Scripting: ScriptStub
Starting with 0.9.18 SPAD.neXt.Interfaces contains an abstract ScriptStub which can be used for easier implementation:
/// <summary>
/// A basic Script Stub for free use
/// </summary>
public abstract class ScriptStub : IScript, IScriptCreation
{
/// <summary>
/// String to prefix all datat with. Data will be available as LOCAL:[PREFIX]_[name]
/// </summary>
protected abstract string ScriptDataPrefix { get; }
protected abstract void InitializeScript();
protected abstract void DeinitializeScript();
/// <summary>
/// Interface to Application for this Script
/// </summary>
protected IApplication Application { get; private set; }
/// <summary>
/// Our logger for the script.
/// </summary>
protected ILogger ScriptLogger { get; private set; }
protected CancellationTokenSource CancelTokenSource { get; private set; } = new CancellationTokenSource();
protected CancellationToken CancelToken => CancelTokenSource.Token;
/// <summary>
/// The loaded SPAD.neXtprofile has changed
/// </summary>
protected EventHandler<IProfile, string> ProfileChanged;
/// <summary>
/// The active aircraft/vehicle has changed
/// </summary>
protected EventHandler<IAircraft, string> AircraftChanged;
/// <summary>
/// A flight has been started
/// </summary>
protected EventHandler<ISimulationInterface, IAircraft> FlightStarted;
/// <summary>
/// The flight ended
/// </summary>
protected EventHandler<ISimulationInterface, SimulationGamestate> FlightEnded;
/// <summary>
/// The Simulation gamestate has changed (NewState,OldState)
/// </summary>
protected EventHandler<ISimulationInterface,SimulationGamestate, SimulationGamestate> GameStateChanged;
private Dictionary<string, IDataDefinition> scriptDataValues = new Dictionary<string, IDataDefinition>(StringComparer.InvariantCultureIgnoreCase);
public void Initialize(IApplication app)
{
Application = app;
ScriptLogger = app.GetLogger("Script." + ScriptDataPrefix);
scriptDataValues = new Dictionary<string, IDataDefinition>(StringComparer.InvariantCultureIgnoreCase);
ScriptLogger.Debug("Initialize");
Application.RegisterSimulationConnected(simulationConnected);
Application.ActiveProfileChanged += (s, e) => ProfileChanged?.Invoke(Application.ActiveProfile, e.PropertyName);
Application.AircraftChanged += (s, e) => AircraftChanged?.Invoke(Application.CurrentAircraft, e.PropertyName);
SafeCall(() => InitializeScript());
}
private void simulationConnected(SimulationConfiguration sender, IValueProvider e)
{
if (sender != null && sender.SimulationInterface is ISimulationInterface simulationInterface)
{
simulationInterface.SimulationGamestateChanged -= SimulationInterface_SimulationGamestateChanged;
simulationInterface.SimulationGamestateChanged += SimulationInterface_SimulationGamestateChanged;
}
}
private void SimulationInterface_SimulationGamestateChanged(ISimulationInterface sender, SimulationGamestate newState, SimulationGamestate oldState)
{
SafeCall(() =>
{
if (newState != oldState)
{
if (newState == SimulationGamestate.Flying)
{
FlightStarted?.Invoke(sender, Application.CurrentAircraft);
}
else
{
FlightEnded?.Invoke(sender, newState);
}
}
GameStateChanged?.Invoke(sender, oldState, newState);
});
}
public void Deinitialize()
{
ScriptLogger.Debug("Deinitialize");
CancelTokenSource.Cancel();
SafeCall(() => DeinitializeScript());
scriptDataValues?.Clear();
scriptDataValues = null;
}
protected IDataDefinition GetOrCreateScriptDataValue(string name)
{
if (name.Contains(":"))
{
throw new InvalidCastException("Symbol ':' is not allowed in datanames");
}
var realName = "LOCAL:" + ScriptDataPrefix + "_" + name;
if (scriptDataValues.TryGetValue(name, out var data))
return data;
data = EventSystem.GetDataDefinition(realName);
scriptDataValues[name] = data;
return data;
}
protected T GetScriptDataValue<T>(string name, T defaultValue = default)
{
var data = GetOrCreateScriptDataValue(name);
return data.GetValueAs<T>(defaultValue);
}
protected void SetScriptDataValue(string name, object value)
{
var data = GetOrCreateScriptDataValue(name);
if (data != null) { data.SetRawValue(value); }
}
private void SafeCall(Action _call)
{
try
{
_call();
}
catch (Exception ex)
{
ScriptLogger.Error(ex.ToString());
}
}
}
Last updated