import com.nolimitscoaster.*;
public class SwitchScript extends Script implements BlockSystemController {
private static final String _script = "SwitchScript";
private static final int STATE_BLOCK_FREE = 0;
private static final int STATE_BLOCK_APPROACHING = 1;
private static final int STATE_BLOCK_LEAVING = 2;
private static final int STATE_BLOCK_BEFORE_TRIGGER = 3;
private static final int STATE_BLOCK_BEHIND_TRIGGER = 4;
private static final int STATE_BLOCK_WAITING = 5;
private static final int STATE_BLOCK_WAIT_FOR_CLEAR = 6;
private static final int STATE_BLOCK_WAIT_FOR_ADVANCE = 7;
private static final int STATE_BLOCK_IN_STATION = 8;
private static final int AUTO_MODE = 0;
private static final int MANUAL_BLOCK_MODE = 1;
private static final int FULL_MANUAL_MODE = 2;
private Coaster _coaster;
private Block _station;
private SpecialTrack _switch;
private Block _preLaunch;
private float _preLaunchTime;
private Block _trimBrakes;
private float _trimBrakesTime;
private Block _stock;
private float _stockTime;
private Block _tableStock;
private float _tableStockTime;
private int _mode;
//<editor-fold desc="Initiation">
public bool onInit() {
System.out.println(_script + " started !");
String blockName;
_coaster = sim.getCoasterForEntityId(getParentEntityId());
if (_coaster == null) {
System.err.println(_script + " : Error loading Coaster.");
return false;
}
_coaster.setBlockSystemController(this);
blockName = "Station";
_station = _coaster.getBlock(blockName);
if (!checkAndSetInitialBlockState(_station, blockName)) {
return false;
}
_station.setAdvanceFwdVisible(true);
blockName = "Switch";
_switch = _coaster.getSpecialTrack(blockName);
if (_switch == null) {
System.err.println(_script + ": SpecialTrack '" + blockName + "' not found.");
return false;
}
blockName = "PreLaunch";
_preLaunch = _coaster.getBlock(blockName);
if (!checkAndSetInitialBlockState(_preLaunch, blockName)) {
return false;
}
_preLaunch.setAdvanceFwdVisible(true);
blockName = "TrimBrakes";
_trimBrakes = _coaster.getBlock(blockName);
if (!checkAndSetInitialBlockState(_trimBrakes, blockName)) {
return false;
}
_trimBrakes.setAdvanceFwdVisible(true);
blockName = "Stock";
_stock = _coaster.getBlock(blockName);
if (!checkAndSetInitialBlockState(_stock, blockName)) {
return false;
}
_stock.setAdvanceFwdVisible(true);
blockName = "TableBlock";
_tableStock = _coaster.getBlock(blockName);
if (!checkAndSetInitialBlockState(_tableStock, blockName)) {
return false;
}
_tableStock.setAdvanceFwdVisible(true);
_mode = AUTO_MODE;
return true;
}
//</editor-fold>
//<editor-fold desc="Trains Stages">
public void onNextFrame(float tick) {
if (_mode != FULL_MANUAL_MODE) {
processStation();
processPreLaunch();
processTrimBrakes();
processStock();
processTableStock();
if (_mode == MANUAL_BLOCK_MODE) {
updateControlPanel();
}
}
}
public void onAutoMode(Coaster c) {
if (_mode == FULL_MANUAL_MODE) {
setInitialBlockState(_station);
setInitialBlockState(_preLaunch);
setInitialBlockState(_trimBrakes);
setInitialBlockState(_stock);
setInitialBlockState(_tableStock);
}
_mode = AUTO_MODE;
updateControlPanel();
}
public void onManualBlockMode(Coaster c) {
if (_mode == FULL_MANUAL_MODE) {
setInitialBlockState(_station);
setInitialBlockState(_preLaunch);
setInitialBlockState(_trimBrakes);
setInitialBlockState(_stock);
setInitialBlockState(_tableStock);
}
_mode = MANUAL_BLOCK_MODE;
updateControlPanel();
}
public void onFullManualMode(Coaster c) {
_mode = FULL_MANUAL_MODE;
updateControlPanel();
}
public void onAdvanceFWDButton(Block block) {
if (block == _station) {
_preLaunch.setState(STATE_BLOCK_APPROACHING);
_station.setState(STATE_BLOCK_LEAVING);
_station.getSection().setStationLeaving();
}
if (block == _preLaunch) {
_trimBrakes.setState(STATE_BLOCK_APPROACHING);
_preLaunch.setState(STATE_BLOCK_LEAVING);
}
if (block == _trimBrakes) {
_stock.setState(STATE_BLOCK_APPROACHING);
_trimBrakes.setState(STATE_BLOCK_LEAVING);
}
if (block == _stock) {
_tableStock.setState(STATE_BLOCK_APPROACHING);
_stock.setState(STATE_BLOCK_LEAVING);
}
if (block == _tableStock) {
_station.setState(STATE_BLOCK_APPROACHING);
_tableStock.setState(STATE_BLOCK_LEAVING);
}
}
public void onAdvanceBWDButton(Block block) {
}
private void updateControlPanel() {
_station.setAdvanceFwdEnabled(_station.getState() == STATE_BLOCK_WAIT_FOR_ADVANCE && preparePreLaunchEntering());
_switch.setCanManualSwitchDirection((_preLaunch.getState() == STATE_BLOCK_FREE) || (_preLaunch.getState() == STATE_BLOCK_WAIT_FOR_ADVANCE) || (_preLaunch.getState() == STATE_BLOCK_WAIT_FOR_CLEAR));
_preLaunch.setAdvanceFwdEnabled(_preLaunch.getState() == STATE_BLOCK_WAIT_FOR_ADVANCE && prepareTrimBrakesEntering());
_trimBrakes.setAdvanceFwdEnabled(_trimBrakes.getState() == STATE_BLOCK_WAIT_FOR_ADVANCE && prepareStockEntering());
_stock.setAdvanceFwdEnabled(_stock.getState() == STATE_BLOCK_WAIT_FOR_ADVANCE && prepareTableStockEntering());
_tableStock.setAdvanceFwdEnabled(_tableStock.getState() == STATE_BLOCK_WAIT_FOR_ADVANCE && prepareStationEntering());
}
//</editor-fold>
//<editor-fold desc="Blocks Entering Preparation">
private bool preparePreLaunchEntering() {
if (_preLaunch.getState() == STATE_BLOCK_FREE && _trimBrakes.getState() != STATE_BLOCK_APPROACHING) {
if (_switch.getVisibleSwitchState() == 1) {
return true;
} else {
if (_mode == AUTO_MODE) {
_switch.setSwitchDirection(1);
}
}
}
return false;
}
private bool prepareTrimBrakesEntering() {
if (_trimBrakes.getState() == STATE_BLOCK_FREE) {
return true;
}
return false;
}
private bool prepareStockEntering() {
if (_stock.getState() == STATE_BLOCK_FREE) {
return true;
}
return false;
}
private bool prepareTableStockEntering() {
if (_tableStock.getState() == STATE_BLOCK_FREE) {
return true;
}
return false;
}
private bool prepareStationEntering() {
if (_station.getState() == STATE_BLOCK_FREE) {
return true;
}
return false;
}
//</editor-fold>
//<editor-fold desc="Blocks Processing">
private void processStation() {
Block stationBlock = _station;
Block nextBlock = _preLaunch;
switch (stationBlock.getState()) {
case STATE_BLOCK_IN_STATION:
if (stationBlock.getSection().isStationWaitingForClearBlock()) {
if (nextBlock.getState() == STATE_BLOCK_FREE) {
stationBlock.getSection().setStationNextBlockClear();
}
} else if (stationBlock.getSection().isStationWaitingForAdvance()) {
if (_mode == MANUAL_BLOCK_MODE) {
if (nextBlock.getState() == STATE_BLOCK_FREE) {
stationBlock.setState(STATE_BLOCK_WAIT_FOR_ADVANCE);
} else {
stationBlock.getSection().setStationNextBlockOccupied();
}
} else {
if (nextBlock.getState() == STATE_BLOCK_FREE) {
if (preparePreLaunchEntering()) {
nextBlock.setState(STATE_BLOCK_APPROACHING);
stationBlock.setState(STATE_BLOCK_LEAVING);
stationBlock.getSection().setStationLeaving();
}
} else {
stationBlock.getSection().setStationNextBlockOccupied();
}
}
}
break;
case STATE_BLOCK_WAIT_FOR_ADVANCE:
if ((_mode != MANUAL_BLOCK_MODE) || !stationBlock.getSection().isStationWaitingForAdvance() || (nextBlock.getState() != STATE_BLOCK_FREE)) {
stationBlock.setState(STATE_BLOCK_IN_STATION);
}
break;
case STATE_BLOCK_LEAVING:
if (stationBlock.getNumberOfTrainsOnBlock() != 0) {
stationBlock.getSection().setBrakesOff();
stationBlock.getSection().setTransportsStandardFwdOn();
stationBlock.getSection().setTransportsLaunchFwdOn();
} else {
stationBlock.setState(STATE_BLOCK_FREE);
}
break;
case STATE_BLOCK_FREE:
stationBlock.getSection().setTransportsOff();
stationBlock.getSection().setBrakesOn();
break;
case STATE_BLOCK_APPROACHING:
if (stationBlock.getSection().isTrainOnSection()) {
stationBlock.getSection().setStationEntering();
stationBlock.setState(STATE_BLOCK_IN_STATION);
} else {
stationBlock.getSection().setBrakesOff();
stationBlock.getSection().setTransportsOff();
}
break;
}
}
private void processPreLaunch() {
switch (_preLaunch.getState()) {
case STATE_BLOCK_APPROACHING:
_preLaunch.getSection().setBrakesOff();
_preLaunch.getSection().setTransportsOff();
if (_preLaunch.getSection().isTrainOnSection()) {
_preLaunch.setState(STATE_BLOCK_BEFORE_TRIGGER);
}
break;
case STATE_BLOCK_BEFORE_TRIGGER:
_preLaunch.getSection().setBrakesTrim();
_preLaunch.getSection().setTransportsStandardBwdDependingOnBrake();
if (!_preLaunch.getSection().isTrainBehindBrakeTrigger()) {
_preLaunch.setState(STATE_BLOCK_BEHIND_TRIGGER);
}
break;
case STATE_BLOCK_BEHIND_TRIGGER:
_preLaunch.getSection().setBrakesOn();
_preLaunch.getSection().setTransportsOff();
{
Train train = _preLaunch.getSection().getTrainOnSection();
if (train.getSpeed() == 0) {
_preLaunchTime = 0;
_preLaunch.setState(STATE_BLOCK_WAITING);
}
}
break;
case STATE_BLOCK_WAITING:
_preLaunch.getSection().setBrakesOn();
_preLaunch.getSection().setTransportsOff();
_preLaunchTime += sim.getCurSimulationTickSec();
preparePreLaunchLeaving();
if (_preLaunchTime >= _preLaunch.getSection().getBrakeWaitTime()) {
_preLaunch.setState(STATE_BLOCK_WAIT_FOR_CLEAR);
}
break;
case STATE_BLOCK_WAIT_FOR_CLEAR:
_preLaunch.getSection().setBrakesOn();
_preLaunch.getSection().setTransportsOff();
if (preparePreLaunchLeaving()) {
if (_mode == MANUAL_BLOCK_MODE) {
_preLaunch.setState(STATE_BLOCK_WAIT_FOR_ADVANCE);
} else {
if (prepareTrimBrakesEntering()) {
_trimBrakes.setState(STATE_BLOCK_APPROACHING);
_preLaunch.setState(STATE_BLOCK_LEAVING);
}
}
}
break;
case STATE_BLOCK_WAIT_FOR_ADVANCE:
_preLaunch.getSection().setBrakesOn();
_preLaunch.getSection().setTransportsOff();
if (!preparePreLaunchLeaving()) {
_preLaunch.setState(STATE_BLOCK_WAIT_FOR_CLEAR);
}
break;
case STATE_BLOCK_LEAVING:
if (_preLaunch.getSection().isTrainOnSection()) {
_preLaunch.getSection().setBrakesOff();
_preLaunch.getSection().setTransportsStandardFwdOn();
_preLaunch.getSection().setTransportsLaunchFwdOn();
} else {
_preLaunch.getSection().setBrakesOn();
_preLaunch.getSection().setTransportsOff();
}
if (_preLaunch.getNumberOfTrainsOnBlock() == 0) {
_preLaunch.setState(STATE_BLOCK_FREE);
}
break;
case STATE_BLOCK_FREE:
_preLaunch.getSection().setBrakesOn();
_preLaunch.getSection().setTransportsOff();
break;
}
}
private void processTrimBrakes() {
switch (_trimBrakes.getState()) {
case STATE_BLOCK_FREE:
_trimBrakes.getSection().setTransportsOff();
_trimBrakes.getSection().setBrakesOn();
break;
case STATE_BLOCK_APPROACHING:
if (_trimBrakes.getSection().isTrainOnSection()) {
_trimBrakes.setState(STATE_BLOCK_BEFORE_TRIGGER);
} else {
if (prepareStockEntering()) {
_trimBrakes.getSection().setBrakesOff();
} else {
_trimBrakes.getSection().setBrakesOn();
}
_trimBrakes.getSection().setTransportsOff();
}
break;
case STATE_BLOCK_BEFORE_TRIGGER:
prepareStockEntering();
_trimBrakes.getSection().setBrakesTrim();
_trimBrakes.getSection().setTransportsStandardFwdDependingOnBrake();
if (_trimBrakes.getSection().isTrainBehindBrakeTrigger()) {
_trimBrakes.setState(STATE_BLOCK_BEHIND_TRIGGER);
_trimBrakesTime = 0;
}
break;
case STATE_BLOCK_BEHIND_TRIGGER:
if (_mode == MANUAL_BLOCK_MODE) {
if (prepareStockEntering()) {
_trimBrakes.setState(STATE_BLOCK_WAIT_FOR_ADVANCE);
} else {
_trimBrakes.getSection().setTransportsOff();
_trimBrakes.getSection().setBrakesOn();
}
} else {
if (prepareStockEntering() && (_mode == AUTO_MODE) && (!_trimBrakes.getSection().isBrakeCompleteStop() || _trimBrakesTime > _trimBrakes.getSection().getBrakeWaitTime())) {
_stock.setState(STATE_BLOCK_APPROACHING);
_trimBrakes.setState(STATE_BLOCK_LEAVING);
} else {
if (_trimBrakes.getSection().getTrainOnSection().getSpeed() == 0)
_trimBrakesTime += sim.getCurSimulationTickSec();
_trimBrakes.getSection().setTransportsOff();
_trimBrakes.getSection().setBrakesOn();
}
}
break;
case STATE_BLOCK_WAIT_FOR_ADVANCE:
if (_mode == AUTO_MODE) {
_trimBrakes.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
if (!prepareStockEntering()) {
_trimBrakes.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
_trimBrakes.getSection().setTransportsOff();
_trimBrakes.getSection().setBrakesOn();
}
}
break;
case STATE_BLOCK_LEAVING:
_trimBrakes.getSection().setBrakesOff();
_trimBrakes.getSection().setTransportsStandardFwdOn();
_trimBrakes.getSection().setTransportsLaunchFwdOn();
preparePreLaunchEntering();
if (_trimBrakes.getNumberOfTrainsOnBlock() == 0) {
_trimBrakes.setState(STATE_BLOCK_FREE);
}
break;
case STATE_BLOCK_WAIT_FOR_CLEAR:
if (_trimBrakes.getSection().isTrainBehindBrakeTrigger()) {
_trimBrakes.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
_trimBrakes.setState(STATE_BLOCK_BEFORE_TRIGGER);
}
break;
}
}
private void processStock() {
switch (_stock.getState()) {
case STATE_BLOCK_FREE:
_stock.getSection().setTransportsOff();
_stock.getSection().setBrakesOn();
break;
case STATE_BLOCK_APPROACHING:
if (_stock.getSection().isTrainOnSection()) {
_stock.setState(STATE_BLOCK_BEFORE_TRIGGER);
} else {
if (prepareTableStockEntering()) {
_stock.getSection().setBrakesOff();
} else {
_stock.getSection().setBrakesOn();
}
_stock.getSection().setTransportsOff();
}
break;
case STATE_BLOCK_BEFORE_TRIGGER:
prepareTableStockEntering();
_stock.getSection().setBrakesTrim();
_stock.getSection().setTransportsStandardFwdDependingOnBrake();
if (_stock.getSection().isTrainBehindBrakeTrigger()) {
_stock.setState(STATE_BLOCK_BEHIND_TRIGGER);
_stockTime = 0;
}
break;
case STATE_BLOCK_BEHIND_TRIGGER:
if (_mode == MANUAL_BLOCK_MODE) {
if (prepareTableStockEntering()) {
_stock.setState(STATE_BLOCK_WAIT_FOR_ADVANCE);
} else {
_stock.getSection().setTransportsOff();
_stock.getSection().setBrakesOn();
}
} else {
if (prepareTableStockEntering() && (_mode == AUTO_MODE) && (!_stock.getSection().isBrakeCompleteStop() || _stockTime > _stock.getSection().getBrakeWaitTime())) {
_tableStock.setState(STATE_BLOCK_APPROACHING);
_stock.setState(STATE_BLOCK_LEAVING);
} else {
if (_stock.getSection().getTrainOnSection().getSpeed() == 0)
_stockTime += sim.getCurSimulationTickSec();
_stock.getSection().setTransportsOff();
_stock.getSection().setBrakesOn();
}
}
break;
case STATE_BLOCK_WAIT_FOR_ADVANCE:
if (_mode == AUTO_MODE) {
_stock.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
if (!prepareTableStockEntering()) {
_stock.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
_stock.getSection().setTransportsOff();
_stock.getSection().setBrakesOn();
}
}
break;
case STATE_BLOCK_LEAVING:
_stock.getSection().setBrakesOff();
_stock.getSection().setTransportsStandardFwdOn();
_stock.getSection().setTransportsLaunchFwdOn();
if (_stock.getNumberOfTrainsOnBlock() == 0) {
_stock.setState(STATE_BLOCK_FREE);
}
break;
case STATE_BLOCK_WAIT_FOR_CLEAR:
if (_stock.getSection().isTrainBehindBrakeTrigger()) {
_stock.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
_stock.setState(STATE_BLOCK_BEFORE_TRIGGER);
}
break;
}
}
private void processTableStock() {
switch (_tableStock.getState()) {
case STATE_BLOCK_FREE:
_tableStock.getSection().setTransportsOff();
_tableStock.getSection().setBrakesOn();
break;
case STATE_BLOCK_APPROACHING:
if (_tableStock.getSection().isTrainOnSection()) {
_tableStock.setState(STATE_BLOCK_BEFORE_TRIGGER);
} else {
if (prepareStationEntering()) {
_tableStock.getSection().setBrakesOff();
} else {
_tableStock.getSection().setBrakesOn();
}
_tableStock.getSection().setTransportsOff();
}
break;
case STATE_BLOCK_BEFORE_TRIGGER:
prepareStationEntering();
_tableStock.getSection().setBrakesTrim();
_tableStock.getSection().setTransportsStandardFwdDependingOnBrake();
if (_tableStock.getSection().isTrainBehindBrakeTrigger()) {
_tableStock.setState(STATE_BLOCK_BEHIND_TRIGGER);
_tableStockTime = 0;
}
break;
case STATE_BLOCK_BEHIND_TRIGGER:
if (_mode == MANUAL_BLOCK_MODE) {
if (prepareStationEntering()) {
_tableStock.setState(STATE_BLOCK_WAIT_FOR_ADVANCE);
} else {
_tableStock.getSection().setTransportsOff();
_tableStock.getSection().setBrakesOn();
}
} else {
if (prepareStationEntering() && (_mode == AUTO_MODE) && (!_tableStock.getSection().isBrakeCompleteStop() || _tableStockTime > _tableStock.getSection().getBrakeWaitTime())) {
_station.setState(STATE_BLOCK_APPROACHING);
_tableStock.setState(STATE_BLOCK_LEAVING);
} else {
if (_tableStock.getSection().getTrainOnSection().getSpeed() == 0)
_tableStockTime += sim.getCurSimulationTickSec();
_tableStock.getSection().setTransportsOff();
_tableStock.getSection().setBrakesOn();
}
}
break;
case STATE_BLOCK_WAIT_FOR_ADVANCE:
if (_mode == AUTO_MODE) {
_tableStock.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
if (!prepareStationEntering()) {
_tableStock.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
_tableStock.getSection().setTransportsOff();
_tableStock.getSection().setBrakesOn();
}
}
break;
case STATE_BLOCK_LEAVING:
_tableStock.getSection().setBrakesOff();
_tableStock.getSection().setTransportsStandardFwdOn();
_tableStock.getSection().setTransportsLaunchFwdOn();
if (_tableStock.getNumberOfTrainsOnBlock() == 0) {
_tableStock.setState(STATE_BLOCK_FREE);
}
break;
case STATE_BLOCK_WAIT_FOR_CLEAR:
if (_tableStock.getSection().isTrainBehindBrakeTrigger()) {
_tableStock.setState(STATE_BLOCK_BEHIND_TRIGGER);
} else {
_tableStock.setState(STATE_BLOCK_BEFORE_TRIGGER);
}
break;
}
}
//</editor-fold>
//<editor-fold desc="Blocks Leaving Preparation">
private bool preparePreLaunchLeaving() {
if (_switch.getVisibleSwitchState() == 0) {
return true;
} else {
if (_mode == AUTO_MODE) {
_switch.setSwitchDirection(0);
}
}
return false;
}
//</editor-fold>
//<editor-fold desc="Blocks States Management">
private static bool checkAndSetInitialBlockState(Block block, String name) {
if (block == null) {
System.err.println(_script + ": '" + name + "' not found.");
return false;
}
registerBlockStates(block);
setInitialBlockState(block);
return true;
}
private static void registerBlockStates(Block block) {
block.registerState(STATE_BLOCK_FREE, "Free", Block.LAMP_OFF);
block.registerState(STATE_BLOCK_APPROACHING, "Approaching", Block.LAMP_FLASHING);
block.registerState(STATE_BLOCK_LEAVING, "Leaving", Block.LAMP_ON);
block.registerState(STATE_BLOCK_BEFORE_TRIGGER, "Before Trigger", Block.LAMP_ON);
block.registerState(STATE_BLOCK_BEHIND_TRIGGER, "Behind Trigger", Block.LAMP_ON);
block.registerState(STATE_BLOCK_WAITING, "Waiting", Block.LAMP_ON);
block.registerState(STATE_BLOCK_WAIT_FOR_CLEAR, "Waiting for Clear Block", Block.LAMP_ON);
block.registerState(STATE_BLOCK_WAIT_FOR_ADVANCE, "Waiting for Advance", Block.LAMP_ON);
block.registerState(STATE_BLOCK_IN_STATION, "In Station", Block.LAMP_ON);
}
private static void setInitialBlockState(Block block) {
if (block.getNumberOfTrainsOnBlock() > 0) {
if (block.getSection().iStation()) {
block.setState(STATE_BLOCK_IN_STATION);
} else {
block.setState(STATE_BLOCK_WAIT_FOR_CLEAR);
}
} else {
block.setState(STATE_BLOCK_FREE);
}
}
//</editor-fold>
}