public void a( OWorld oworld, int i, int j, int k, OAxisAlignedBB oaxisalignedbb, ArrayList arraylist) { int l = oworld.c(i, j, k); int i1 = l & 3; float f = 0.0F; float f1 = 0.5F; float f2 = 0.5F; float f3 = 1.0F; if ((l & 4) != 0) { f = 0.5F; f1 = 1.0F; f2 = 0.0F; f3 = 0.5F; } this.a(0.0F, f, 0.0F, 1.0F, f1, 1.0F); super.a(oworld, i, j, k, oaxisalignedbb, arraylist); if (i1 == 0) { this.a(0.5F, f2, 0.0F, 1.0F, f3, 1.0F); super.a(oworld, i, j, k, oaxisalignedbb, arraylist); } else if (i1 == 1) { this.a(0.0F, f2, 0.0F, 0.5F, f3, 1.0F); super.a(oworld, i, j, k, oaxisalignedbb, arraylist); } else if (i1 == 2) { this.a(0.0F, f2, 0.5F, 1.0F, f3, 1.0F); super.a(oworld, i, j, k, oaxisalignedbb, arraylist); } else if (i1 == 3) { this.a(0.0F, f2, 0.0F, 1.0F, f3, 0.5F); super.a(oworld, i, j, k, oaxisalignedbb, arraylist); } this.a(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); }
@Override public void b(OWorld paramOWorld, int paramInt1, int paramInt2, int paramInt3) { super.b(paramOWorld, paramInt1, paramInt2, paramInt3); if (paramOWorld.z) return; paramOWorld.h(paramInt1, paramInt2 + 1, paramInt3, bi); paramOWorld.h(paramInt1, paramInt2 - 1, paramInt3, bi); g(paramOWorld, paramInt1, paramInt2, paramInt3); h(paramOWorld, paramInt1 - 1, paramInt2, paramInt3); h(paramOWorld, paramInt1 + 1, paramInt2, paramInt3); h(paramOWorld, paramInt1, paramInt2, paramInt3 - 1); h(paramOWorld, paramInt1, paramInt2, paramInt3 + 1); if (paramOWorld.d(paramInt1 - 1, paramInt2, paramInt3)) h(paramOWorld, paramInt1 - 1, paramInt2 + 1, paramInt3); else h(paramOWorld, paramInt1 - 1, paramInt2 - 1, paramInt3); if (paramOWorld.d(paramInt1 + 1, paramInt2, paramInt3)) h(paramOWorld, paramInt1 + 1, paramInt2 + 1, paramInt3); else h(paramOWorld, paramInt1 + 1, paramInt2 - 1, paramInt3); if (paramOWorld.d(paramInt1, paramInt2, paramInt3 - 1)) h(paramOWorld, paramInt1, paramInt2 + 1, paramInt3 - 1); else h(paramOWorld, paramInt1, paramInt2 - 1, paramInt3 - 1); if (paramOWorld.d(paramInt1, paramInt2, paramInt3 + 1)) h(paramOWorld, paramInt1, paramInt2 + 1, paramInt3 + 1); else h(paramOWorld, paramInt1, paramInt2 - 1, paramInt3 + 1); }
/** * Block in the route is going Inactive. Release the blocks that we have left. Check if current * block has been left (i.e. we have left our route) and stop the train in that case. */ protected void goingInactive(OBlock block) { if (_runMode != MODE_RUN) { return; } int idx = getIndexOfBlock(block, 0); // if idx >= 0, it is in this warrant if (log.isDebugEnabled()) { log.debug( _trainName + " Block \"" + block.getDisplayName() + "\" goingInactive. idx= " + idx + ", _idxCurrentOrder= " + _idxCurrentOrder + " - warrant= " + getDisplayName()); } if (idx < _idxCurrentOrder) { deallocateUpToBlock(idx); } else if (idx == _idxCurrentOrder) { // train is lost if (log.isDebugEnabled()) { log.debug( _trainName + " LOST TRAIN firePropertyChange(\"blockChange\", " + block.getDisplayName() + ", null) - warrant= " + getDisplayName()); } // firePropertyChange("blockChange", block, null); if (_engineer != null) { _engineer.setSpeed(SPEED_STOP); } // controlRunTrain(ABORT); } // now let the main loop stop our train if this means that the train is now entirely within the // last block. // Or let the train continue if an other train that was in its way has now moved. synchronized (this) { notify(); } }
/** * Deallocate all blocks up to and including idx, but only on these conditions in order to ensure * that only a consecutive list of blocks are allocated at any time: 1. Only if our train has left * not only this block, but also all previous blocks. 2. Only if the block shall not be re-used * ahead and all block up until the block are allocated. */ protected void deallocateUpToBlock(int idx) { for (int i = 0; i <= idx; i++) { OBlock block_i = getBlockOrderAt(i).getBlock(); if (block_i.isAllocatedTo(this)) { if ((block_i.getState() & OBlock.UNOCCUPIED) != OBlock.UNOCCUPIED) { // Do not deallocate further blocks, since this one is still allocated to us and not free. return; } boolean deAllocate = true; // look ahead to see if block_i is reused in the remaining part of the route. for (int j = _idxCurrentOrder; j < _orders.size(); j++) { OBlock block_j = getBlockOrderAt(j).getBlock(); if (!block_j.isAllocatedTo(this)) { // There is an unallocated block ahead before we have found block_i is re-used. So // deallocate block_i deAllocate = true; break; } if (block_i == block_j) { // clock_i is re-used, and we have no "holes" in the string of allocated blocks before // it. So do not deallocate. deAllocate = false; break; } } if (deAllocate) { block_i.deAllocate(this); } } } }
@Override public void b(OWorld paramOWorld, int paramInt1, int paramInt2, int paramInt3, int paramInt4) { if (paramOWorld.z) return; int i = paramOWorld.b(paramInt1, paramInt2, paramInt3); boolean bool = a(paramOWorld, paramInt1, paramInt2, paramInt3); if (!bool) { a_(paramOWorld, paramInt1, paramInt2, paramInt3, i); paramOWorld.e(paramInt1, paramInt2, paramInt3, 0); } else g(paramOWorld, paramInt1, paramInt2, paramInt3); super.b(paramOWorld, paramInt1, paramInt2, paramInt3, paramInt4); }
/** * Block in the route going active. Make sure to allocate the rest of the route, update our * present location and then tell the main loop to find a new throttle setting. */ protected void goingActive(OBlock block) { if (_runMode != MODE_RUN) { return; } int activeIdx = getIndexOfBlock(block, _idxCurrentOrder); if (log.isDebugEnabled()) { log.debug( _trainName + " **Block \"" + block.getDisplayName() + "\" goingActive. activeIdx= " + activeIdx + ", _idxCurrentOrder= " + _idxCurrentOrder + " - warrant= " + getDisplayName()); } if (activeIdx <= 0) { // The block going active is not part of our route ahead log.debug(_trainName + " Block going active is not part of this trains route forward"); } else if (activeIdx == _idxCurrentOrder) { // Unusual case of current block losing detection, then regaining it. i.e. dirty track, // derail etc. log.debug(_trainName + " Current block becoming active - ignored"); } else if (activeIdx == _idxCurrentOrder + 1) { // not necessary: It is done in the main loop in SCTrainRunner.run: // allocateBlocksAndSetTurnouts(_idxCurrentOrder+1); // update our present location _idxCurrentOrder++; // fire property change (entered new block) firePropertyChange( "blockChange", getBlockAt(_idxCurrentOrder - 1), getBlockAt(_idxCurrentOrder)); // now let the main loop adjust speed. synchronized (this) { notify(); } } else { log.debug(_trainName + " Rogue occupation of block."); // now let the main loop stop for a train that is coming in our immediate way. synchronized (this) { notify(); } } }
/** * This should not be necessary, but it turns out that if three or more trains are running on a * small layout, at some point in time a deadlock will occur where more trains want to run on the * same line in the same direction, but the train behind have allocated a block ahead of the front * train. The task of this function is therefore to deallocate any such block. */ protected void ensureRouteConsecutivity() { boolean deAllocateRestOfRoute = false; for (int i = _idxCurrentOrder + 1; i < _orders.size(); i++) { log.debug(_trainName + " ensureRouteConsecutivity for loop #" + i); BlockOrder bo = getBlockOrderAt(i); OBlock block = bo.getBlock(); if (!block.isAllocatedTo(this) || (block.getState() & OBlock.OCCUPIED) != 0) { deAllocateRestOfRoute = true; } if (deAllocateRestOfRoute) { if (block.isAllocatedTo(this)) { log.info( _trainName + " deallocating " + block.getDisplayName() + " due to risk of deadlock"); block.deAllocate(this); } } } }
/** * Do what the title says. But make sure not to set the turnouts if already done, since that would * just cause all signals to go to Stop aspects and thus cause a jerky train movement. */ protected void allocateBlocksAndSetTurnouts(int startIndex) { log.debug( _trainName + " allocateBlocksAndSetTurnouts startIndex=" + startIndex + " _orders.size()=" + _orders.size()); ensureRouteConsecutivity(); for (int i = startIndex; i < _orders.size(); i++) { log.debug(_trainName + " allocateBlocksAndSetTurnouts for loop #" + i); BlockOrder bo = getBlockOrderAt(i); OBlock block = bo.getBlock(); String pathAlreadySet = block.isPathSet(bo.getPathName()); if (pathAlreadySet == null) { String message = null; if ((block.getState() & OBlock.OCCUPIED) != 0) { log.info( _trainName + " block allocation failed " + block.getDisplayName() + " not allocated, but Occupied."); message = " block allocation failed "; } if (message == null) { message = block.allocate(this); if (message != null) { log.info(_trainName + " block allocation failed " + message); } } if (message == null) { message = bo.setPath(this); } if (message != null) { log.debug( _trainName + " path setting failed for " + this.getDisplayName() + " at block " + block.getDisplayName() + " " + message); if (_stoppingBlock != null) { _stoppingBlock.removePropertyChangeListener(this); } _stoppingBlock = block; _stoppingBlock.addPropertyChangeListener(this); // This allocation failed. Do not attempt to allocate the rest of the route.allocation // That would potentially lead to deadlock situations where two warrants are competing // and each getting every second block along the same route. return; } } else if (pathAlreadySet.equals(this.getDisplayName())) { log.debug( _trainName + " Path already set (and thereby block allocated) for " + bo.getPathName()); } else { log.info( _trainName + " Block allocation failed: Path already set (and thereby block allocated) for " + bo.getPathName()); return; } } }
@Override public void propertyChange(java.beans.PropertyChangeEvent e) { String property = e.getPropertyName(); if (property.equals("length")) { // a NamedBean added or deleted init(); fireTableDataChanged(); } else if (e.getSource() instanceof Warrant) { // a value changed. Find it, to avoid complete redraw Warrant bean = (Warrant) e.getSource(); for (int i = 0; i < _warList.size(); i++) { if (bean.equals(_warList.get(i))) { if (_warNX.contains(bean) && ((property.equals("runMode") && ((Integer) e.getNewValue()).intValue() == Warrant.MODE_NONE) || (property.equals("controlChange") && ((Integer) e.getNewValue()).intValue() == Warrant.ABORT))) { fireTableRowsDeleted(i, i); removeNXWarrant(bean); } else { fireTableRowsUpdated(i, i); } break; } } if (e.getPropertyName().equals("blockChange")) { OBlock oldBlock = (OBlock) e.getOldValue(); OBlock newBlock = (OBlock) e.getNewValue(); if (newBlock == null) { _frame.setStatusText( Bundle.getMessage( "ChangedRoute", bean.getDisplayName(), oldBlock.getDisplayName(), bean.getTrainName()), Color.red, true); } else { _frame.setStatusText( Bundle.getMessage( "TrackerBlockEnter", bean.getTrainName(), newBlock.getDisplayName()), myGreen, true); } } else if (e.getPropertyName().equals("blockRelease")) { OBlock block = (OBlock) e.getNewValue(); long et = (System.currentTimeMillis() - block._entryTime) / 1000; _frame.setStatusText( Bundle.getMessage( "TrackerBlockLeave", bean.getTrainName(), block.getDisplayName(), et / 60, et % 60), myGreen, true); } else if (e.getPropertyName().equals("SpeedRestriction")) { _frame.setStatusText( Bundle.getMessage( "speedChange", bean.getTrainName(), bean.getCurrentBlockOrder().getBlock().getDisplayName(), e.getNewValue()), myGold, true); } else if (e.getPropertyName().equals("SpeedChange")) { int row = getRow(bean); if (row >= 0) { fireTableRowsUpdated(row, row); // _frame.setStatusText(bean.getRunningMessage(), myGreen, true); } } else if (e.getPropertyName().equals("runMode")) { int oldMode = ((Integer) e.getOldValue()).intValue(); int newMode = ((Integer) e.getNewValue()).intValue(); if (oldMode == Warrant.MODE_NONE) { if (newMode != Warrant.MODE_NONE) { _frame.setStatusText( Bundle.getMessage( "warrantStart", bean.getTrainName(), bean.getDisplayName(), bean.getCurrentBlockOrder().getBlock().getDisplayName(), Bundle.getMessage(Warrant.MODES[newMode])), myGreen, true); } } else if (newMode == Warrant.MODE_NONE) { OBlock block = bean.getCurrentBlockOrder().getBlock(); int state = block.getState(); if ((state & OBlock.OCCUPIED) != 0 || (state & OBlock.DARK) != 0) { _frame.setStatusText( Bundle.getMessage( "warrantEnd", bean.getTrainName(), bean.getDisplayName(), block.getDisplayName()), myGreen, true); } else { _frame.setStatusText( Bundle.getMessage("warrantAbort", bean.getTrainName(), bean.getDisplayName()), myGreen, true); } } else { _frame.setStatusText( Bundle.getMessage( "modeChange", bean.getTrainName(), bean.getDisplayName(), Bundle.getMessage(Warrant.MODES[oldMode]), Bundle.getMessage(Warrant.MODES[newMode])), myGold, true); } } else if (e.getPropertyName().equals("controlChange")) { int runState = ((Integer) e.getOldValue()).intValue(); int newCntrl = ((Integer) e.getNewValue()).intValue(); String stateStr = null; if (runState < 0) { stateStr = Bundle.getMessage(Warrant.MODES[-runState]); } else { stateStr = Bundle.getMessage( Warrant.RUN_STATE[runState], bean.getCurrentBlockOrder().getBlock().getDisplayName()); } _frame.setStatusText( Bundle.getMessage( "controlChange", bean.getTrainName(), stateStr, Bundle.getMessage(Warrant.CNTRL_CMDS[newCntrl])), myGold, true); } else if (e.getPropertyName().equals("throttleFail")) { _frame.setStatusText( Bundle.getMessage("ThrottleFail", bean.getTrainName(), e.getNewValue()), Color.red, true); } } if (log.isDebugEnabled()) log.debug( "propertyChange of \"" + e.getPropertyName() + "\" for " + e.getSource().getClass().getName()); }