changeset 8306:ea2c123b3655 draft

(svn r11871) -Fix [FS#1074]: do not update signals after each tile when building/removing a large block of track/signals/station
author smatz <smatz@openttd.org>
date Wed, 16 Jan 2008 01:18:15 +0000
parents 1e1e16a1129c
children 820c6cc79cf4
files src/ai/ai.cpp src/command.cpp src/economy.cpp src/rail_cmd.cpp src/signal.cpp src/signal_func.h src/station_cmd.cpp src/tunnelbridge_cmd.cpp src/water_cmd.cpp src/waypoint.cpp
diffstat 10 files changed, 124 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- 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 @@
 		AiDoGameLoop(p);
 		_is_old_ai_player = false;
 	}
+
+	/* AI could change some track, so update signals */
+	UpdateSignalsInBuffer();
 }
 
 
--- 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 @@
 
 	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) {
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -440,10 +440,13 @@
 					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();
 		}
 	}
 
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -418,7 +418,7 @@
 
 	if (flags & DC_EXEC) {
 		MarkTileDirtyByTile(tile);
-		SetSignalsOnBothDir(tile, track, _current_player);
+		AddTrackToSignalBuffer(tile, track, _current_player);
 		YapfNotifyTrackLayoutChange(tile, track);
 	}
 
@@ -502,12 +502,12 @@
 			 * 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 @@
 
 		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 @@
 		}
 
 		MarkTileDirtyByTile(tile);
-		SetSignalsOnBothDir(tile, track, _current_player);
+		AddTrackToSignalBuffer(tile, track, _current_player);
 		YapfNotifyTrackLayoutChange(tile, track);
 	}
 
@@ -1102,7 +1102,7 @@
 			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 @@
 
 		DoClearSquare(tile);
 		delete GetDepotByTile(tile);
-		UpdateSignalsOnSegment(tile, dir, owner);
+		AddSideToSignalBuffer(tile, dir, owner);
 		YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir)));
 	}
 
--- 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},
@@ -100,6 +103,16 @@
 	}
 
 	/**
+	 * 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
 	 * @param dir and dir to remove
@@ -534,6 +547,77 @@
 }
 
 
+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 @@
  */
 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);
 }
--- a/src/signal_func.h
+++ b/src/signal_func.h
@@ -43,5 +43,8 @@
 
 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 */
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -1073,7 +1073,7 @@
 
 				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 @@
 
 			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 @@
 					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);
 				}
 			}
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -419,7 +419,7 @@
 
 	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 @@
 		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 @@
 			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 @@
 
 		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);
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -648,6 +648,9 @@
 				MarkTileDirtyIfCanal(target + TileOffsByDir(dir));
 			}
 		}
+
+		/* update signals if needed */
+		UpdateSignalsInBuffer();
 	}
 }
 
--- a/src/waypoint.cpp
+++ b/src/waypoint.cpp
@@ -297,7 +297,7 @@
 			MarkTileDirtyByTile(tile);
 		} else {
 			DoClearSquare(tile);
-			SetSignalsOnBothDir(tile, track, owner);
+			AddTrackToSignalBuffer(tile, track, owner);
 		}
 		YapfNotifyTrackLayoutChange(tile, track);
 	}