Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // LOCOMOTIVE SCRIPT EXTENDER LIBRARY
- // Version: 0.0.7, date: 24.07.2011
- // Author: agentmike, e-mail: agentmike@rambler.ru
- // For license information see config.txt file.
- //
- // LSE is extensible framework for creating prototypically working locomotives.
- // LSE.Init is standalone part of LSE providing support of unified initialization
- // system for locomotives with custom scripts.
- include "train.gs"
- // +
- // Initialization messages (all major strings are prefixed with 'Lse.Init.'):
- //
- // # | source | destination | major | minor |
- //
- // 1 train Broadcast TrainPhysics state
- // 2 vehicle Broadcast PreState preState time
- // 3 vehicle Broadcast SetRunlevel runlevel
- // 4 vehicle Broadcast RunlevelChanged runlevel
- // 5 vehicle Broadcast Runlevel runlevel
- // 6 vehicle Broadcast RunlevelChange runlevel proc
- //
- // Note:
- // Every message is broadcasted from concrete vehicle. This is because
- // they could be used by other systems to monitor init/run activities.
- // I. e. Lse.Pneumatics rely on this messages to set initial pressures in
- // reservoirs and starting brake systems simulation.
- // If message is a directive command, only vehicle referenced as message
- // source will respond to it. Such messages should be sent using
- // Router.PostMessage by InitV or other custom initialization controller.
- //
- // Description:
- // 1. This message is directive command that has to be sent by an
- // InitV/other init controller to properly handle the Train.EnablePhysics
- // call and state.
- // Message must be broadcasted with concrete train as source.
- // 2. This is optional message to handle preinitialization
- // state of a vehicle. It allows to init state of vehicle with
- // consideration of how it was used (or not used) before the initialization
- // process. PreState has 4 defined values: Cold, Warm, Hot, HotRunning and
- // number representing how long in minutes vehicle was in that state.
- // Supporting of this feature is optional; default value is 'Warm 1140',
- // meaning last crew left it in loco yard one day ago. Unsupported levels
- // should be handled by falling to the closest preferring lower (i.e. Cold
- // instead of Hot if Warm if not supported).
- // Message must be broadcasted with concrete vehicle as source.
- // 3. This message used to control current runlevel of a vehicle.
- // Message must be broadcasted with concrete vehicle as source.
- // 4. This message is used to notify world about finished runlevel transition.
- // Not sent for Halt runlevel.
- // Message is broadcasted by LseInit instance.
- // 5. This message is used to notify world current runlevel.
- // Not sent for Halt runlevel.
- // Message is broadcasted by LseInit instance in regular intervals
- // (currently every minute).
- // 6. This message is used to notify world about beginning runlevel transition.
- // Message is broadcasted by LseInit instance.
- //
- // Message parameters:
- // train: Train object containing some vehicle
- // vehicle: Vehicle object we want to monitor/init
- // Any: means src/dst is not relevant
- // Broadcast: means message is sent to every object in the world
- // state: Enabled or Disabled
- // preState: Cold or Warm or Hot or HotRunning
- // time: integer value, minutes since vehicle was left in this preState
- // runlevel: Halt or Wait or User or Auto
- // proc: Init or Term
- //
- class LseInit
- {
- Vehicle _vehicle;
- final Vehicle _getVehicle() { return _vehicle; }
- define public int RunlevelHalt = 0;
- define public int RunlevelWait = 1;
- define public int RunlevelAuto = 2;
- define public int RunlevelUser = 3;
- int _runlevel = RunlevelHalt;
- int _runlevelTo = RunlevelHalt;
- int _runlevelNext = RunlevelHalt;
- bool _runlevelChange = false;
- bool _runlevelWaitThread = false;
- bool _trainPhysicsState = true;
- final public bool GetPhysicsState() { return _trainPhysicsState; }
- define public int PreStateCold = 0; // После ТР/КР
- define public int PreStateWarm = 1; // После отстоя в депо
- define public int PreStateHot = 2; // После смены бригад
- define public int PreStateHotRunning = 3; // После смены бригад, локомотив запущен
- define public int PreStateIdleForHour = 60;
- define public int PreStateIdleForDay = 24 * PreStateIdleForHour;
- define public int PreStateIdleForMonth = 30 * PreStateIdleForDay;
- int _preState = PreStateWarm;
- int _preStateIdleMinutes = PreStateIdleForDay;
- final public int GetPreState() { return _preState; }
- final public int GetPreStateIdleMinutes() { return _preStateIdleMinutes; }
- final public int GetPreStateTime(int months, int days, int hours, int minutes)
- {
- return minutes
- + hours * PreStateIdleForHour
- + days * PreStateIdleForDay
- + months * PreStateIdleForMonth;
- }
- // Call this to change loco runlevel
- final void RcSet(int runlevel)
- {
- if ( RunlevelHalt == runlevel
- or RunlevelWait == runlevel
- or RunlevelUser == runlevel
- or RunlevelAuto == runlevel)
- {
- if (_trainPhysicsState or runlevel == RunlevelHalt)
- {
- _runlevelTo = runlevel;
- }
- }
- }
- // Call this to terminate script in case of fatal error (i.e. derailment)
- final public void RcHalt()
- {
- RcSet(RunlevelHalt);
- }
- void RcUserInit(); // Override this methods with your custom loco logic
- void RcUserTerm(); // Call RcFin() when initiation/termination is complete.
- void RcAutoInit(); // CALL inherited() AT THE FIRST LINE OF YOUR CODE!!!
- void RcAutoTerm(); //
- void RcWaitInit(); //
- void RcWaitTerm(); //
- final thread void _rcInvoke(int rl, bool status)
- {
- _runlevelChange = true;
- switch (rl)
- {
- case RunlevelWait:
- if (status)
- RcWaitInit();
- else
- RcWaitTerm();
- break;
- case RunlevelUser:
- if (status)
- RcUserInit();
- else
- RcUserTerm();
- break;
- case RunlevelAuto:
- if (status)
- RcAutoInit();
- else
- RcAutoTerm();
- break;
- case RunlevelHalt:
- default:
- break;
- }
- switch (_runlevelNext)
- {
- case RunlevelWait:
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChanged", "Wait", 0.0);
- break;
- case RunlevelUser:
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChanged", "User", 0.0);
- break;
- case RunlevelAuto:
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChanged", "Auto", 0.0);
- break;
- case RunlevelHalt:
- default:
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChanged", "Halt", 0.0);
- break;
- }
- _runlevel = _runlevelNext;
- _runlevelChange = false;
- }
- final void _rcDispatch()
- {
- if (_runlevelChange)
- return;
- switch (_runlevel)
- {
- case RunlevelWait:
- switch (_runlevelTo)
- {
- case RunlevelHalt:
- _runlevelNext = RunlevelHalt;
- _rcInvoke(RunlevelWait, false);
- break;
- case RunlevelUser:
- _runlevelNext = RunlevelUser;
- _rcInvoke(RunlevelUser, true);
- break;
- case RunlevelAuto:
- _runlevelNext = RunlevelAuto;
- _rcInvoke(RunlevelAuto, true);
- break;
- case RunlevelWait:
- default:
- break;
- }
- break;
- case RunlevelUser:
- switch (_runlevelTo)
- {
- case RunlevelHalt:
- case RunlevelWait:
- case RunlevelAuto:
- _runlevelNext = RunlevelWait;
- _rcInvoke(RunlevelUser, false);
- break;
- case RunlevelUser:
- default:
- break;
- }
- break;
- case RunlevelAuto:
- switch (_runlevelTo)
- {
- case RunlevelHalt:
- case RunlevelWait:
- case RunlevelUser:
- _runlevelNext = RunlevelWait;
- _rcInvoke(RunlevelAuto, false);
- break;
- case RunlevelAuto:
- default:
- break;
- }
- break;
- case RunlevelHalt:
- default:
- switch (_runlevelTo)
- {
- case RunlevelWait:
- case RunlevelUser:
- case RunlevelAuto:
- _runlevelNext = RunlevelWait;
- _rcInvoke(RunlevelWait, true);
- break;
- case RunlevelHalt:
- default:
- break;
- }
- break;
- }
- }
- final thread void _initWait()
- {
- float sleepTime = 1.0;
- float runlevelMessageTime = 60.0;
- float runlevelMessageTimeLeft = 0.0;
- while (_runlevelWaitThread)
- {
- if (!_trainPhysicsState)
- RcSet(RunlevelWait);
- if (_runlevel != _runlevelTo)
- _rcDispatch();
- if (_runlevelChange)
- runlevelMessageTimeLeft = 0.0;
- else
- {
- if (runlevelMessageTimeLeft <= 0.0)
- {
- switch (_runlevel)
- {
- case RunlevelWait: _getVehicle().PostMessage(null, "Lse.Init.Runlevel", "Wait", 0.0); break;
- case RunlevelAuto: _getVehicle().PostMessage(null, "Lse.Init.Runlevel", "Auto", 0.0); break;
- case RunlevelUser: _getVehicle().PostMessage(null, "Lse.Init.Runlevel", "User", 0.0); break;
- case RunlevelHalt: break;
- default: break;
- }
- runlevelMessageTimeLeft = runlevelMessageTime;
- }
- else
- runlevelMessageTimeLeft = runlevelMessageTimeLeft - sleepTime;
- }
- _getVehicle().Sleep(sleepTime);
- }
- }
- void RcUserInit()
- {
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChange", "User Init", 0.0);
- }
- void RcUserTerm()
- {
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChange", "User Term", 0.0);
- }
- void RcAutoInit()
- {
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChange", "Auto Init", 0.0);
- }
- void RcAutoTerm()
- {
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChange", "Auto Term", 0.0);
- }
- void RcWaitInit()
- {
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChange", "Wait Init", 0.0);
- if (!_runlevelWaitThread)
- {
- _runlevelWaitThread = true;
- _initWait();
- }
- _getVehicle().Sleep(0.1);
- }
- void RcWaitTerm()
- {
- _getVehicle().PostMessage(null, "Lse.Init.RunlevelChange", "Wait Term", 0.0);
- _runlevelWaitThread = false;
- _getVehicle().Sleep(1.0);
- }
- final void _onLseTrainPhysics(Message msg)
- {
- Train msgTrain = cast<Train> msg.src;
- if (msgTrain and msgTrain == _getVehicle().GetMyTrain())
- {
- string stateStr = Str.CloneString(msg.minor);
- Str.ToLower(stateStr);
- if (stateStr == "disabled" or stateStr == "false" or stateStr == "0")
- _trainPhysicsState = false;
- else
- _trainPhysicsState = true;
- }
- }
- final void _onLsePreState(Message msg)
- {
- if (msg.src != me)
- return;
- string[] msgParams = Str.Tokens(msg.minor, "");
- if (msgParams.size() != 2)
- return;
- string preState = msgParams[0];
- Str.ToLower(preState);
- string preStateIdleTime = msgParams[1];
- if (preState == "cold")
- _preState = PreStateCold;
- else if (preState == "warm")
- _preState = PreStateWarm;
- else if (preState == "hot")
- _preState = PreStateHot;
- else if (preState == "hotrunning")
- _preState = PreStateHotRunning;
- int preStateIdleTimeInt = Str.ToInt(preStateIdleTime);
- if (preStateIdleTimeInt > 0)
- _preStateIdleMinutes = preStateIdleTimeInt;
- }
- final void _onLseSetRunlevel(Message msg)
- {
- if (msg.src != me)
- return;
- string runlevel = Str.CloneString(msg.minor);
- Str.ToLower(runlevel);
- if (runlevel == "halt")
- RcSet(RunlevelHalt);
- else if (runlevel == "wait")
- RcSet(RunlevelWait);
- else if (runlevel == "user")
- RcSet(RunlevelUser);
- else if (runlevel == "auto")
- RcSet(RunlevelAuto);
- }
- public void LseInit()
- {
- _vehicle = cast<Vehicle> (object) me;
- if (_vehicle == null)
- Interface.Exception("LseInit should be inherited by Vehicle or descendants! (line 430)");
- _getVehicle().AddHandler(_getVehicle(), "Lse.Init.TrainPhysics", "", "_onLseTrainPhysics");
- _getVehicle().AddHandler(_getVehicle(), "Lse.Init.PreState", "", "_onLsePreState" );
- _getVehicle().AddHandler(_getVehicle(), "Lse.Init.SetRunlevel", "", "_onLseSetRunlevel" );
- // _getVehicle().AddHandler(_getVehicle(), "Lse.Init.TrainPhysics.Direct", "", "_onLseTrainPhysics");
- // _getVehicle().AddHandler(_getVehicle(), "Lse.Init.PreState.Direct", "", "_onLsePreState" );
- // _getVehicle().AddHandler(_getVehicle(), "Lse.Init.SetRunlevel.Direct", "", "_onLseSetRunlevel" );
- RcSet(RunlevelWait);
- _rcDispatch();
- }
- };
- // Dummy class for script and class tags in config.txt
- class LseInitLibrary isclass Library
- {
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement