From 61e40b1aa5f1b7137d0fc56d42c8221d9146e40a Mon Sep 17 00:00:00 2001 From: smatz Date: Wed, 16 Jan 2008 01:18:15 +0000 Subject: [PATCH] (svn r11871) -Fix [FS#1074]: do not update signals after each tile when building/removing a large block of track/signals/station --- src/ai/ai.cpp | 4 ++ src/command.cpp | 4 ++ src/economy.cpp | 5 +- src/rail_cmd.cpp | 16 +++---- src/signal.cpp | 100 ++++++++++++++++++++++++++++++++++----- src/signal_func.h | 3 ++ src/station_cmd.cpp | 6 +-- src/tunnelbridge_cmd.cpp | 12 ++--- src/water_cmd.cpp | 3 ++ src/waypoint.cpp | 2 +- 10 files changed, 124 insertions(+), 31 deletions(-) diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp index c6158b0c46..4849cf2735 100644 --- a/src/ai/ai.cpp +++ b/src/ai/ai.cpp @@ -10,6 +10,7 @@ #include "../player_base.h" #include "ai.h" #include "default/default.h" +#include "../signal_func.h" AIStruct _ai; AIPlayer _ai_player[MAX_PLAYERS]; @@ -159,6 +160,9 @@ static void AI_RunTick(PlayerID player) AiDoGameLoop(p); _is_old_ai_player = false; } + + /* AI could change some track, so update signals */ + UpdateSignalsInBuffer(); } diff --git a/src/command.cpp b/src/command.cpp index cf25d13bf0..40b3ff9b8f 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -20,6 +20,7 @@ #include "debug.h" #include "player_func.h" #include "player_base.h" +#include "signal_func.h" #include "table/strings.h" @@ -642,6 +643,9 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, SubtractMoneyFromPlayer(res2); + /* update signals if needed */ + UpdateSignalsInBuffer(); + if (IsLocalPlayer() && _game_mode != GM_EDITOR) { if (res2.GetCost() != 0 && tile != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2.GetCost()); if (_additional_cash_required != 0) { diff --git a/src/economy.cpp b/src/economy.cpp index d9f51bb821..9377a7a804 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -440,10 +440,13 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player) TrackBits tracks = GetTrackBits(tile); do { // there may be two tracks with signals for TRACK_BIT_HORZ and TRACK_BIT_VERT Track track = RemoveFirstTrack(&tracks); - if (HasSignalOnTrack(tile, track)) SetSignalsOnBothDir(tile, track, new_player); + if (HasSignalOnTrack(tile, track)) AddTrackToSignalBuffer(tile, track, new_player); } while (tracks != TRACK_BIT_NONE); } } while (++tile != MapSize()); + + /* update signals in buffer */ + UpdateSignalsInBuffer(); } } diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 2142cec25a..c404d15d53 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -418,7 +418,7 @@ CommandCost CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p if (flags & DC_EXEC) { MarkTileDirtyByTile(tile); - SetSignalsOnBothDir(tile, track, _current_player); + AddTrackToSignalBuffer(tile, track, _current_player); YapfNotifyTrackLayoutChange(tile, track); } @@ -502,12 +502,12 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 * are removing one of these pieces, we'll need to update signals for * both directions explicitly, as after the track is removed it won't * 'connect' with the other piece. */ - SetSignalsOnBothDir(tile, TRACK_X, owner); - SetSignalsOnBothDir(tile, TRACK_Y, owner); + AddTrackToSignalBuffer(tile, TRACK_X, owner); + AddTrackToSignalBuffer(tile, TRACK_Y, owner); YapfNotifyTrackLayoutChange(tile, TRACK_X); YapfNotifyTrackLayoutChange(tile, TRACK_Y); } else { - SetSignalsOnBothDir(tile, track, owner); + AddTrackToSignalBuffer(tile, track, owner); YapfNotifyTrackLayoutChange(tile, track); } } @@ -745,7 +745,7 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p d->town_index = ClosestTownFromTile(tile, (uint)-1)->index; - UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, _current_player); + AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_player); YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); d_auto_delete.Detach(); } @@ -871,7 +871,7 @@ CommandCost CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 } MarkTileDirtyByTile(tile); - SetSignalsOnBothDir(tile, track, _current_player); + AddTrackToSignalBuffer(tile, track, _current_player); YapfNotifyTrackLayoutChange(tile, track); } @@ -1102,7 +1102,7 @@ CommandCost CmdRemoveSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint3 SetSignalVariant(tile, INVALID_TRACK, SIG_ELECTRIC); // remove any possible semaphores } - SetSignalsOnBothDir(tile, track, GetTileOwner(tile)); + AddTrackToSignalBuffer(tile, track, GetTileOwner(tile)); YapfNotifyTrackLayoutChange(tile, track); MarkTileDirtyByTile(tile); @@ -1314,7 +1314,7 @@ static CommandCost RemoveTrainDepot(TileIndex tile, uint32 flags) DoClearSquare(tile); delete GetDepotByTile(tile); - UpdateSignalsOnSegment(tile, dir, owner); + AddSideToSignalBuffer(tile, dir, owner); YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); } diff --git a/src/signal.cpp b/src/signal.cpp index fa9b6c796f..6c529125b8 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -22,11 +22,14 @@ /** these are the maximums used for updating signal blocks */ enum { - SIG_TBU_SIZE = 64, ///< number of signals entering to block - SIG_TBD_SIZE = 256, ///< number of intersections - open nodes in current block - SIG_GLOB_SIZE = 64, ///< number of open blocks (block can be opened more times until detected) + SIG_TBU_SIZE = 64, ///< number of signals entering to block + SIG_TBD_SIZE = 256, ///< number of intersections - open nodes in current block + SIG_GLOB_SIZE = 128, ///< number of open blocks (block can be opened more times until detected) + SIG_GLOB_UPDATE = 64, ///< how many items need to be in _globset to force update }; +assert_compile(SIG_GLOB_UPDATE <= SIG_GLOB_SIZE); + /** incidating trackbits with given enterdir */ static const TrackBitsByte _enterdir_to_trackbits[DIAGDIR_END] = { {TRACK_BIT_3WAY_NE}, @@ -99,6 +102,16 @@ public: return this->n == lengthof(data); } + /** + * Reads the number of items + * @return current number of items + */ + uint Items() + { + return this->n; + } + + /** * Tries to remove first instance of given tile and dir * @param tile tile @@ -534,6 +547,77 @@ static bool UpdateSignalsInBuffer(Owner owner) } +static Owner _last_owner = INVALID_OWNER; ///< last owner whose track was put into _globset + + +/** + * Update signals in buffer + * Called from 'outside' + */ +void UpdateSignalsInBuffer() +{ + if (!_globset.IsEmpty()) { + UpdateSignalsInBuffer(_last_owner); + _last_owner = INVALID_OWNER; // invalidate + } +} + + +/** + * Add track to signal update buffer + * + * @param tile tile where we start + * @param track track at which ends we will update signals + * @param owner owner whose signals we will update + */ +void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner) +{ + static const DiagDirection _search_dir_1[] = { + DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE + }; + static const DiagDirection _search_dir_2[] = { + DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE + }; + + /* do not allow signal updates for two players in one run */ + assert(_globset.IsEmpty() || owner == _last_owner); + + _last_owner = owner; + + _globset.Add(tile, _search_dir_1[track]); + _globset.Add(tile, _search_dir_2[track]); + + if (_globset.Items() >= SIG_GLOB_UPDATE) { + /* too many items, force update */ + UpdateSignalsInBuffer(_last_owner); + _last_owner = INVALID_OWNER; + } +} + + +/** + * Add side of tile to signal update buffer + * + * @param tile tile where we start + * @param side side of tile + * @param owner owner whose signals we will update + */ +void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner) +{ + /* do not allow signal updates for two players in one run */ + assert(_globset.IsEmpty() || owner == _last_owner); + + _last_owner = owner; + + _globset.Add(tile, side); + + if (_globset.Items() >= SIG_GLOB_UPDATE) { + /* too many items, force update */ + UpdateSignalsInBuffer(_last_owner); + _last_owner = INVALID_OWNER; + } +} + /** * Update signals, starting at one side of a tile * Will check tile next to this at opposite side too @@ -564,16 +648,8 @@ bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner) */ void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner) { - static const DiagDirection _search_dir_1[] = { - DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE - }; - static const DiagDirection _search_dir_2[] = { - DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE - }; - assert(_globset.IsEmpty()); - _globset.Add(tile, _search_dir_1[track]); - _globset.Add(tile, _search_dir_2[track]); + AddTrackToSignalBuffer(tile, track, owner); UpdateSignalsInBuffer(owner); } diff --git a/src/signal_func.h b/src/signal_func.h index a1a37f3fea..a5479a3e0c 100644 --- a/src/signal_func.h +++ b/src/signal_func.h @@ -43,5 +43,8 @@ static inline byte SignalOnTrack(Track track) bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner); void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner); +void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner); +void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner); +void UpdateSignalsInBuffer(); #endif /* SIGNAL_FUNC_H */ diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 83b07ca62b..38a0681c68 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1073,7 +1073,7 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, tile += tile_delta; } while (--w); - SetSignalsOnBothDir(tile_org, track, _current_player); + AddTrackToSignalBuffer(tile_org, track, _current_player); YapfNotifyTrackLayoutChange(tile_org, track); tile_org += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta } while (--numtracks); @@ -1209,7 +1209,7 @@ CommandCost CmdRemoveFromRailroadStation(TileIndex tile, uint32 flags, uint32 p1 DoClearSquare(tile2); st->rect.AfterRemoveTile(st, tile2); - SetSignalsOnBothDir(tile2, track, owner); + AddTrackToSignalBuffer(tile2, track, owner); YapfNotifyTrackLayoutChange(tile2, track); DeallocateSpecFromStation(st, specindex); @@ -1270,7 +1270,7 @@ static CommandCost RemoveRailroadStation(Station *st, TileIndex tile, uint32 fla Track track = GetRailStationTrack(tile); Owner owner = GetTileOwner(tile); // _current_player can be OWNER_WATER DoClearSquare(tile); - SetSignalsOnBothDir(tile, track, owner); + AddTrackToSignalBuffer(tile, track, owner); YapfNotifyTrackLayoutChange(tile, track); } } diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index e991bfc427..fe06955e51 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -419,7 +419,7 @@ not_valid_below:; if (flags & DC_EXEC && railtype != INVALID_RAILTYPE) { Track track = AxisToTrack(direction); - UpdateSignalsOnSegment(tile_start, INVALID_DIAGDIR, _current_player); + AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, _current_player); YapfNotifyTrackLayoutChange(tile_start, track); } @@ -549,7 +549,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 if (GB(p1, 9, 1) == TRANSPORT_RAIL) { MakeRailTunnel(start_tile, _current_player, direction, (RailType)GB(p1, 0, 4)); MakeRailTunnel(end_tile, _current_player, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4)); - UpdateSignalsOnSegment(start_tile, INVALID_DIAGDIR, _current_player); + AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_player); YapfNotifyTrackLayoutChange(start_tile, AxisToTrack(DiagDirToAxis(direction))); } else { MakeRoadTunnel(start_tile, _current_player, direction, (RoadTypes)GB(p1, 0, 3)); @@ -612,8 +612,8 @@ static CommandCost DoClearTunnel(TileIndex tile, uint32 flags) DoClearSquare(endtile); /* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */ - UpdateSignalsOnSegment(tile, ReverseDiagDir(dir), owner); - UpdateSignalsOnSegment(endtile, dir, owner); + AddSideToSignalBuffer(tile, ReverseDiagDir(dir), owner); + AddSideToSignalBuffer(endtile, dir, owner); Track track = AxisToTrack(DiagDirToAxis(dir)); YapfNotifyTrackLayoutChange(tile, track); @@ -674,8 +674,8 @@ static CommandCost DoClearBridge(TileIndex tile, uint32 flags) if (rail) { /* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */ - UpdateSignalsOnSegment(tile, ReverseDiagDir(direction), owner); - UpdateSignalsOnSegment(endtile, direction, owner); + AddSideToSignalBuffer(tile, ReverseDiagDir(direction), owner); + AddSideToSignalBuffer(endtile, direction, owner); Track track = AxisToTrack(DiagDirToAxis(direction)); YapfNotifyTrackLayoutChange(tile, track); diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index b9f2f348a4..db9fbf8395 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -648,6 +648,9 @@ static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs) MarkTileDirtyIfCanal(target + TileOffsByDir(dir)); } } + + /* update signals if needed */ + UpdateSignalsInBuffer(); } } diff --git a/src/waypoint.cpp b/src/waypoint.cpp index 1af10cb07d..04b7de41cd 100644 --- a/src/waypoint.cpp +++ b/src/waypoint.cpp @@ -297,7 +297,7 @@ CommandCost RemoveTrainWaypoint(TileIndex tile, uint32 flags, bool justremove) MarkTileDirtyByTile(tile); } else { DoClearSquare(tile); - SetSignalsOnBothDir(tile, track, owner); + AddTrackToSignalBuffer(tile, track, owner); } YapfNotifyTrackLayoutChange(tile, track); }