diff --git a/docs/landscape.html b/docs/landscape.html index 50e53a9f3a..86a6943fdd 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -1557,9 +1557,10 @@ If signal simulation entrance or exit: diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index 2db8e015fb..91a3a246f6 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -337,7 +337,7 @@ the array so you can quickly see what is used and what is not. XXXX XXXX OOOO OOOO XPPX XXXX - OPOO OOPP + PPOO OOPP XXXX XXXX diff --git a/src/pbs.cpp b/src/pbs.cpp index f1adaf0d9c..8e9edb8e55 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -125,7 +125,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations) case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && !GetTunnelBridgeReservationTrackBits(tile)) { SetTunnelBridgeReservation(tile, true); - if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_GREEN); + if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitSignalState(tile, SIGNAL_STATE_GREEN); MarkTileDirtyByTile(tile); return true; } @@ -181,7 +181,7 @@ void UnreserveRailTrack(TileIndex tile, Track t) case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) { SetTunnelBridgeReservation(tile, false); - if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_RED); + if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitSignalState(tile, SIGNAL_STATE_RED); MarkTileDirtyByTile(tile); } break; diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 4d97ee8ca9..bfc1f7c78e 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1022,7 +1022,7 @@ static void ClearBridgeTunnelSignalSimulation(TileIndex entrance, TileIndex exit static void SetupBridgeTunnelSignalSimulation(TileIndex entrance, TileIndex exit) { SetTunnelBridgeSignalSimulationEntrance(entrance); - SetTunnelBridgeSignalState(entrance, SIGNAL_STATE_GREEN); + SetTunnelBridgeEntranceSignalState(entrance, SIGNAL_STATE_GREEN); SetTunnelBridgeSignalSimulationExit(exit); } @@ -1144,8 +1144,8 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, SetTunnelBridgePBS(tile_exit, is_pbs); } } - if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile) && !HasTunnelBridgeReservation(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_RED); - if (IsTunnelBridgeSignalSimulationExit(tile_exit) && IsTunnelBridgePBS(tile_exit) && !HasTunnelBridgeReservation(tile_exit)) SetTunnelBridgeSignalState(tile_exit, SIGNAL_STATE_RED); + if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile) && !HasTunnelBridgeReservation(tile)) SetTunnelBridgeExitSignalState(tile, SIGNAL_STATE_RED); + if (IsTunnelBridgeSignalSimulationExit(tile_exit) && IsTunnelBridgePBS(tile_exit) && !HasTunnelBridgeReservation(tile_exit)) SetTunnelBridgeExitSignalState(tile_exit, SIGNAL_STATE_RED); MarkBridgeOrTunnelDirty(tile); AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile)); AddSideToSignalBuffer(tile_exit, INVALID_DIAGDIR, GetTileOwner(tile)); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 8080e9f27c..95fc762047 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2989,7 +2989,7 @@ bool AfterLoadGame() /* signalled tunnel entrance */ SignalState state = HasBit(_m[t].m5, 6) ? SIGNAL_STATE_RED : SIGNAL_STATE_GREEN; ClrBit(_m[t].m5, 6); - SetTunnelBridgeSignalState(t, state); + SetTunnelBridgeEntranceSignalState(t, state); } } } @@ -3005,6 +3005,14 @@ bool AfterLoadGame() } } } + if (SlXvIsFeaturePresent(XSLFI_SIG_TUNNEL_BRIDGE, 1, 5)) { + /* entrance and exit signal red/green states now have separate bits */ + for (TileIndex t = 0; t < map_size; t++) { + if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && IsTunnelBridgeSignalSimulationExit(t)) { + SetTunnelBridgeExitSignalState(t, HasBit(_me[t].m6, 0) ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED); + } + } + } /* Station acceptance is some kind of cache */ if (IsSavegameVersionBefore(127)) { diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 40779a3b3e..d42b7b8b21 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -45,8 +45,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 5, 5, "signal_tunnel_bridge", NULL, NULL, "XBSS" }, - { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker + { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 6, 6, "signal_tunnel_bridge", NULL, NULL, "XBSS" }, }; /** diff --git a/src/signal.cpp b/src/signal.cpp index 57eabb5a84..8237fa723c 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -455,10 +455,10 @@ static void UpdateSignalsAroundSegment(SigFlags flags) while (_tbuset.Get(&tile, &trackdir)) { if (IsTileType(tile, MP_TUNNELBRIDGE) && IsTunnelBridgeSignalSimulationExit(tile)) { if (IsTunnelBridgePBS(tile)) continue; - SignalState old_state = GetTunnelBridgeSignalState(tile); + SignalState old_state = GetTunnelBridgeExitSignalState(tile); SignalState new_state = (flags & SF_TRAIN) ? SIGNAL_STATE_RED : SIGNAL_STATE_GREEN; if (old_state != new_state) { - SetTunnelBridgeSignalState(tile, new_state); + SetTunnelBridgeExitSignalState(tile, new_state); MarkTileDirtyByTile(tile); } continue; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 5a6f169163..fbcdf65bb5 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1874,10 +1874,10 @@ void ReverseTrainDirection(Train *v) return; } - /* We are inside tunnel/bidge with signals, reversing will close the entrance. */ + /* We are inside tunnel/bridge with signals, reversing will close the entrance. */ if (IsTunnelBridgeWithSignalSimulation(v->tile)) { /* Flip signal on tunnel entrance tile red. */ - SetTunnelBridgeSignalState(v->tile, SIGNAL_STATE_RED); + SetTunnelBridgeEntranceSignalState(v->tile, SIGNAL_STATE_RED); MarkTileDirtyByTile(v->tile); /* Clear counters. */ v->wait_counter = 0; @@ -2266,11 +2266,11 @@ static void HandleLastTunnelBridgeSignals(TileIndex tile, TileIndex end, DiagDir SetAllBridgeEntranceSimulatedSignalsGreen(end); } - if (IsTunnelBridgeSignalSimulationEntrance(end) && GetTunnelBridgeSignalState(end) == SIGNAL_STATE_RED) { - SetTunnelBridgeSignalState(end, SIGNAL_STATE_GREEN); + if (IsTunnelBridgeSignalSimulationEntrance(end) && GetTunnelBridgeEntranceSignalState(end) == SIGNAL_STATE_RED) { + SetTunnelBridgeEntranceSignalState(end, SIGNAL_STATE_GREEN); MarkTileDirtyByTile(end); - } else if (IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeSignalState(tile) == SIGNAL_STATE_RED) { - SetTunnelBridgeSignalState(tile, SIGNAL_STATE_GREEN); + } else if (IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeEntranceSignalState(tile) == SIGNAL_STATE_RED) { + SetTunnelBridgeEntranceSignalState(tile, SIGNAL_STATE_GREEN); MarkTileDirtyByTile(tile); } } @@ -2279,7 +2279,7 @@ static void HandleLastTunnelBridgeSignals(TileIndex tile, TileIndex end, DiagDir static void UnreserveBridgeTunnelTile(TileIndex tile) { SetTunnelBridgeReservation(tile, false); - if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_RED); + if (IsTunnelBridgeSignalSimulationExit(tile) && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitSignalState(tile, SIGNAL_STATE_RED); } /** @@ -3269,7 +3269,7 @@ static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile) } bool ok = TryPathReserve(t); t->tile = veh_orig; - if (ok && IsTunnelBridgePBS(tile)) SetTunnelBridgeSignalState(tile, SIGNAL_STATE_GREEN); + if (ok && IsTunnelBridgePBS(tile)) SetTunnelBridgeExitSignalState(tile, SIGNAL_STATE_GREEN); return ok; } @@ -3317,8 +3317,8 @@ static void HandleSignalBehindTrain(Train *v, int signal_number) if(tile == v->tile) { /* Flip signal on ramp. */ - if (IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeSignalState(tile) == SIGNAL_STATE_RED) { - SetTunnelBridgeSignalState(tile, SIGNAL_STATE_GREEN); + if (IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeEntranceSignalState(tile) == SIGNAL_STATE_RED) { + SetTunnelBridgeEntranceSignalState(tile, SIGNAL_STATE_GREEN); MarkTileDirtyByTile(tile); } } else if (IsBridge(v->tile) && signal_number >= 0) { @@ -3515,7 +3515,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) if (IsTunnelBridgeWithSignalSimulation(gp.new_tile)) { /* If red signal stop. */ if (v->IsFrontEngine() && v->force_proceed == 0) { - if (IsTunnelBridgeSignalSimulationEntrance(gp.new_tile) && GetTunnelBridgeSignalState(gp.new_tile) == SIGNAL_STATE_RED) { + if (IsTunnelBridgeSignalSimulationEntrance(gp.new_tile) && GetTunnelBridgeEntranceSignalState(gp.new_tile) == SIGNAL_STATE_RED) { v->cur_speed = 0; v->vehstatus |= VS_TRAIN_SLOWING; return false; @@ -3525,7 +3525,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) goto invalid_rail; } /* Flip signal on tunnel entrance tile red. */ - SetTunnelBridgeSignalState(gp.new_tile, SIGNAL_STATE_RED); + SetTunnelBridgeEntranceSignalState(gp.new_tile, SIGNAL_STATE_RED); MarkTileDirtyByTile(gp.new_tile); } } @@ -3837,7 +3837,25 @@ static void DeleteLastWagon(Train *v) if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile); /* Update signals */ - if (IsTileType(tile, MP_TUNNELBRIDGE) || IsRailDepotTile(tile)) { + if (IsTileType(tile, MP_TUNNELBRIDGE)) { + UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, owner); + if (IsTunnelBridgeWithSignalSimulation(tile)) { + TileIndex end = GetOtherTunnelBridgeEnd(tile); + UpdateSignalsOnSegment(end, INVALID_DIAGDIR, owner); + bool is_entrance = IsTunnelBridgeSignalSimulationEntrance(tile); + TileIndex entrance = is_entrance ? tile : end; + if (TunnelBridgeIsFree(tile, end, nullptr).Succeeded()) { + if (IsBridge(entrance)) { + SetAllBridgeEntranceSimulatedSignalsGreen(entrance); + MarkBridgeDirty(entrance); + } + if (IsTunnelBridgeSignalSimulationEntrance(entrance) && GetTunnelBridgeEntranceSignalState(entrance) == SIGNAL_STATE_RED) { + SetTunnelBridgeEntranceSignalState(entrance, SIGNAL_STATE_GREEN); + MarkTileDirtyByTile(entrance); + } + } + } + } else if (IsRailDepotTile(tile)) { UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, owner); } else { SetSignalsOnBothDir(tile, track, owner); @@ -4078,7 +4096,7 @@ static bool TrainCheckIfLineEnds(Train *v, bool reverse) if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile); if (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && - IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeSignalState(tile) == SIGNAL_STATE_RED) { + IsTunnelBridgeSignalSimulationEntrance(tile) && GetTunnelBridgeEntranceSignalState(tile) == SIGNAL_STATE_RED) { return TrainApproachingLineEnd(v, true, reverse); } diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 83f82e29f5..ccb25a315f 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1183,13 +1183,14 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) SignalType type = SIGTYPE_NORMAL; - bool is_green = (GetTunnelBridgeSignalState(ti->tile) == SIGNAL_STATE_GREEN); - bool show_exit; + bool is_green, show_exit; if (IsTunnelBridgeSignalSimulationExit(ti->tile)) { + is_green = (GetTunnelBridgeExitSignalState(ti->tile) == SIGNAL_STATE_GREEN); show_exit = true; position ^= 1; if (IsTunnelBridgePBS(ti->tile)) type = SIGTYPE_PBS_ONEWAY; } else { + is_green = (GetTunnelBridgeEntranceSignalState(ti->tile) == SIGNAL_STATE_GREEN); show_exit = false; } @@ -1216,7 +1217,7 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) } /* Draws a signal on tunnel / bridge entrance tile. */ -static void DrawBrigeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_start_tile, uint z) +static void DrawBridgeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_start_tile, uint z) { uint bridge_signal_position = 0; diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h index 499aad99b7..f6a21e9992 100644 --- a/src/tunnelbridge_map.h +++ b/src/tunnelbridge_map.h @@ -199,29 +199,53 @@ static inline bool IsTunnelBridgeSignalSimulationExit(TileIndex t) } /** - * Get the signal state for a tunnel/bridge entrance or exit with signal simulation + * Get the signal state for a tunnel/bridge entrance with signal simulation * @param t the tunnel/bridge entrance or exit tile with signal simulation * @pre IsTunnelBridgeWithSignalSimulation(t) * @return signal state */ -static inline SignalState GetTunnelBridgeSignalState(TileIndex t) +static inline SignalState GetTunnelBridgeEntranceSignalState(TileIndex t) { - assert(IsTunnelBridgeWithSignalSimulation(t)); + assert(IsTunnelBridgeSignalSimulationEntrance(t)); return HasBit(_me[t].m6, 0) ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED; } +/** + * Get the signal state for a tunnel/bridge exit with signal simulation + * @param t the tunnel/bridge entrance or exit tile with signal simulation + * @pre IsTunnelBridgeWithSignalSimulation(t) + * @return signal state + */ +static inline SignalState GetTunnelBridgeExitSignalState(TileIndex t) +{ + assert(IsTunnelBridgeSignalSimulationExit(t)); + return HasBit(_me[t].m6, 7) ? SIGNAL_STATE_GREEN : SIGNAL_STATE_RED; +} + /** * Set the signal state for a tunnel/bridge entrance or exit with signal simulation * @param t the tunnel/bridge entrance or exit tile with signal simulation * @pre IsTunnelBridgeWithSignalSimulation(t) * @param state signal state */ -static inline void SetTunnelBridgeSignalState(TileIndex t, SignalState state) +static inline void SetTunnelBridgeEntranceSignalState(TileIndex t, SignalState state) { - assert(IsTunnelBridgeWithSignalSimulation(t)); + assert(IsTunnelBridgeSignalSimulationEntrance(t)); SB(_me[t].m6, 0, 1, (state == SIGNAL_STATE_GREEN) ? 1 : 0); } +/** + * Set the signal state for a tunnel/bridge entrance or exit with signal simulation + * @param t the tunnel/bridge entrance or exit tile with signal simulation + * @pre IsTunnelBridgeWithSignalSimulation(t) + * @param state signal state + */ +static inline void SetTunnelBridgeExitSignalState(TileIndex t, SignalState state) +{ + assert(IsTunnelBridgeSignalSimulationExit(t)); + SB(_me[t].m6, 7, 1, (state == SIGNAL_STATE_GREEN) ? 1 : 0); +} + static inline bool IsTunnelBridgeSemaphore(TileIndex t) { assert(IsTunnelBridgeWithSignalSimulation(t));