changeset 8300:ae1baac75172 draft

(svn r11864) -Codechange: pass owner whose signals we will update instead of complex detection later
author smatz <smatz@openttd.org>
date Tue, 15 Jan 2008 15:00:01 +0000
parents 8879221d0548
children c1ae8f75ad7f
files src/economy.cpp src/rail_cmd.cpp src/signal.cpp src/signal_func.h src/station_cmd.cpp src/train_cmd.cpp src/tunnelbridge_cmd.cpp src/vehicle.cpp src/waypoint.cpp
diffstat 9 files changed, 72 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/src/economy.cpp
+++ b/src/economy.cpp
@@ -440,7 +440,7 @@
 					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);
+						if (HasSignalOnTrack(tile, track)) SetSignalsOnBothDir(tile, track, new_player);
 					} while (tracks != TRACK_BIT_NONE);
 				}
 			} while (++tile != MapSize());
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -418,7 +418,7 @@
 
 	if (flags & DC_EXEC) {
 		MarkTileDirtyByTile(tile);
-		SetSignalsOnBothDir(tile, track);
+		SetSignalsOnBothDir(tile, track, _current_player);
 		YapfNotifyTrackLayoutChange(tile, track);
 	}
 
@@ -441,6 +441,10 @@
 	if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR;
 	trackbit = TrackToTrackBits(track);
 
+	/* Need to read tile owner now because it may change when the rail is removed.
+	 * Also, in case of floods, _current_player != owner */
+	Owner owner = GetTileOwner(tile);
+
 	switch (GetTileType(tile)) {
 		case MP_ROAD: {
 			if (!IsLevelCrossing(tile) ||
@@ -498,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);
-			SetSignalsOnBothDir(tile, TRACK_Y);
+			SetSignalsOnBothDir(tile, TRACK_X, owner);
+			SetSignalsOnBothDir(tile, TRACK_Y, owner);
 			YapfNotifyTrackLayoutChange(tile, TRACK_X);
 			YapfNotifyTrackLayoutChange(tile, TRACK_Y);
 		} else {
-			SetSignalsOnBothDir(tile, track);
+			SetSignalsOnBothDir(tile, track, owner);
 			YapfNotifyTrackLayoutChange(tile, track);
 		}
 	}
@@ -741,7 +745,7 @@
 
 		d->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
 
-		UpdateSignalsOnSegment(tile, INVALID_DIAGDIR);
+		UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, _current_player);
 		YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir)));
 		d_auto_delete.Detach();
 	}
@@ -867,7 +871,7 @@
 		}
 
 		MarkTileDirtyByTile(tile);
-		SetSignalsOnBothDir(tile, track);
+		SetSignalsOnBothDir(tile, track, _current_player);
 		YapfNotifyTrackLayoutChange(tile, track);
 	}
 
@@ -1098,7 +1102,7 @@
 			SetSignalVariant(tile, INVALID_TRACK, SIG_ELECTRIC); // remove any possible semaphores
 		}
 
-		SetSignalsOnBothDir(tile, track);
+		SetSignalsOnBothDir(tile, track, GetTileOwner(tile));
 		YapfNotifyTrackLayoutChange(tile, track);
 
 		MarkTileDirtyByTile(tile);
@@ -1304,11 +1308,13 @@
 		return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
+		/* read variables before the depot is removed */
 		DiagDirection dir = GetRailDepotDirection(tile);
+		Owner owner = GetTileOwner(tile);
 
 		DoClearSquare(tile);
 		delete GetDepotByTile(tile);
-		UpdateSignalsOnSegment(tile, dir);
+		UpdateSignalsOnSegment(tile, dir, owner);
 		YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir)));
 	}
 
--- a/src/signal.cpp
+++ b/src/signal.cpp
@@ -257,12 +257,10 @@
 {
 	SigFlags flags = SF_NONE;
 
-	while (!_tbdset.IsEmpty()) {
-		TileIndex tile;
-		DiagDirection enterdir;
+	TileIndex tile;
+	DiagDirection enterdir;
 
-		_tbdset.Get(&tile, &enterdir);
-
+	while (_tbdset.Get(&tile, &enterdir)) {
 		TileIndex oldtile = tile; // tile we are leaving
 		DiagDirection exitdir = enterdir == INVALID_DIAGDIR ? INVALID_DIAGDIR : ReverseDiagDir(enterdir); // expected new exit direction (for straight line)
 
@@ -396,11 +394,10 @@
  */
 static void UpdateSignalsAroundSegment(SigFlags flags)
 {
-	while (!_tbuset.IsEmpty()) {
-		TileIndex tile;
-		Trackdir trackdir;
-		_tbuset.Get(&tile, &trackdir);
+	TileIndex tile;
+	Trackdir trackdir;
 
+	while (_tbuset.Get(&tile, &trackdir)) {
 		assert(HasSignalOnTrackdir(tile, trackdir));
 
 		SignalType sig = GetSignalType(tile, TrackdirToTrack(trackdir));
@@ -453,15 +450,17 @@
 /**
  * Updates blocks in _globset buffer
  *
+ * @param owner player whose signals we are updating
  * @return false iff presignal entry would be green (needed for trains leaving depot)
+ * @pre IsValidPlayer(owner)
  */
-static bool UpdateSignalsInBuffer()
+static bool UpdateSignalsInBuffer(Owner owner)
 {
+	assert(IsValidPlayer(owner));
+
 	bool first = true;  // first block?
 	bool state = false; // value to return
 
-	Owner owner = OWNER_NONE; // owner whose signals we are updating
-
 	TileIndex tile;
 	DiagDirection dir;
 
@@ -479,7 +478,6 @@
 				/* 'optimization assert' - do not try to update signals when it is not needed */
 				assert(GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL);
 				assert(dir == INVALID_DIAGDIR || dir == ReverseDiagDir(GetTunnelBridgeDirection(tile)));
-				if (first) owner = GetTileOwner(tile);
 				_tbdset.Add(tile, INVALID_DIAGDIR);  // we can safely start from wormhole centre
 				_tbdset.Add(GetOtherTunnelBridgeEnd(tile), INVALID_DIAGDIR);
 				break;
@@ -488,7 +486,6 @@
 				if (IsRailDepot(tile)) {
 					/* 'optimization assert' do not try to update signals in other cases */
 					assert(dir == INVALID_DIAGDIR || dir == GetRailDepotDirection(tile));
-					if (first) owner = GetTileOwner(tile);
 					_tbdset.Add(tile, INVALID_DIAGDIR); // start from depot inside
 					break;
 				}
@@ -497,7 +494,6 @@
 			case MP_ROAD:
 				if ((TrackBits)(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _enterdir_to_trackbits[dir]) != TRACK_BIT_NONE) {
  					/* only add to set when there is some 'interesting' track */
-					if (first) owner = GetTileOwner(tile);
 					_tbdset.Add(tile, dir);
 					_tbdset.Add(tile + TileOffsByDiagDir(dir), ReverseDiagDir(dir));
 					break;
@@ -508,7 +504,6 @@
 				tile = tile + TileOffsByDiagDir(dir);
 				dir = ReverseDiagDir(dir);
 				if ((TrackBits)(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _enterdir_to_trackbits[dir]) != TRACK_BIT_NONE) {
-					if (first) owner = GetTileOwner(tile);
 					_tbdset.Add(tile, dir);
 					break;
 				}
@@ -516,7 +511,6 @@
 				continue; // continue the while() loop
 		}
 
-		assert(IsValidPlayer(owner));
 		assert(!_tbdset.Overflowed()); // it really shouldn't overflow by these one or two items
 		assert(!_tbdset.IsEmpty()); // it wouldn't hurt anyone, but shouldn't happen too
 
@@ -547,14 +541,15 @@
  * @see UpdateSignalsInBuffer()
  * @param tile tile where we start
  * @param side side of tile
+ * @param owner owner whose signals we will update
  * @return false iff train can leave depot
  */
-bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection side)
+bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner)
 {
 	assert(_globset.IsEmpty());
 	_globset.Add(tile, side);
 
-	return UpdateSignalsInBuffer();
+	return UpdateSignalsInBuffer(owner);
 }
 
 
@@ -565,8 +560,9 @@
  * @see UpdateSignalsInBuffer()
  * @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 SetSignalsOnBothDir(TileIndex tile, Track track)
+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
@@ -579,5 +575,5 @@
 
 	_globset.Add(tile, _search_dir_1[track]);
 	_globset.Add(tile, _search_dir_2[track]);
-	UpdateSignalsInBuffer();
+	UpdateSignalsInBuffer(owner);
 }
--- a/src/signal_func.h
+++ b/src/signal_func.h
@@ -9,6 +9,7 @@
 #include "tile_type.h"
 #include "direction_type.h"
 #include "track_type.h"
+#include "player_type.h"
 
 /**
  * Maps a trackdir to the bit that stores its status in the map arrays, in the
@@ -40,7 +41,7 @@
 	return _signal_on_track[track];
 }
 
-bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection side);
-void SetSignalsOnBothDir(TileIndex tile, Track track);
+bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner);
+void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner);
 
 #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);
+			SetSignalsOnBothDir(tile_org, track, _current_player);
 			YapfNotifyTrackLayoutChange(tile_org, track);
 			tile_org += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
 		} while (--numtracks);
@@ -1202,11 +1202,14 @@
 		quantity++;
 
 		if (flags & DC_EXEC) {
+			/* read variables before the station tile is removed */
 			uint specindex = GetCustomStationSpecIndex(tile2);
 			Track track = GetRailStationTrack(tile2);
+			Owner owner = GetTileOwner(tile2);
+
 			DoClearSquare(tile2);
 			st->rect.AfterRemoveTile(st, tile2);
-			SetSignalsOnBothDir(tile2, track);
+			SetSignalsOnBothDir(tile2, track, owner);
 			YapfNotifyTrackLayoutChange(tile2, track);
 
 			DeallocateSpecFromStation(st, specindex);
@@ -1257,15 +1260,17 @@
 	do {
 		int w_bak = w;
 		do {
-			// for nonuniform stations, only remove tiles that are actually train station tiles
+			/* for nonuniform stations, only remove tiles that are actually train station tiles */
 			if (st->TileBelongsToRailStation(tile)) {
 				if (!EnsureNoVehicleOnGround(tile))
 					return CMD_ERROR;
 				cost.AddCost(_price.remove_rail_station);
 				if (flags & DC_EXEC) {
+					/* read variables before the station tile is removed */
 					Track track = GetRailStationTrack(tile);
+					Owner owner = GetTileOwner(tile); // _current_player can be OWNER_WATER
 					DoClearSquare(tile);
-					SetSignalsOnBothDir(tile, track);
+					SetSignalsOnBothDir(tile, track, owner);
 					YapfNotifyTrackLayoutChange(tile, track);
 				}
 			}
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -2168,7 +2168,7 @@
 
 		v->load_unload_time_rem = 0;
 
-		if (UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR)) {
+		if (UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner)) {
 			InvalidateWindowClasses(WC_TRAINS_LIST);
 			return true;
 		}
@@ -2187,7 +2187,7 @@
 	v->UpdateDeltaXY(v->direction);
 	v->cur_image = v->GetImage(v->direction);
 	VehiclePositionChanged(v);
-	UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR);
+	UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner);
 	UpdateTrainAcceleration(v);
 	InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
@@ -2768,7 +2768,7 @@
 	if (IsTileType(tile, MP_RAILWAY) &&
 			GetRailTileType(tile) == RAIL_TILE_SIGNALS) {
 		uint i = FindFirstBit2x64(GetTrackBits(tile) * 0x101 & _reachable_tracks[dir]);
-		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
+		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i], GetTileOwner(tile));
 	}
 }
 
@@ -3141,8 +3141,10 @@
 	/* 'v' shouldn't be accessed after it has been deleted */
 	TrackBits track = v->u.rail.track;
 	TileIndex tile = v->tile;
+	Owner owner = v->owner;
 
 	delete v;
+	v = NULL; // make sure nobody will won't try to read 'v' anymore
 
 	/* Check if the wagon was on a road/rail-crossing and disable it if no
 	 * others are on it */
@@ -3150,9 +3152,9 @@
 
 	/* Update signals */
 	if (IsTileType(tile, MP_TUNNELBRIDGE) || IsTileDepotType(tile, TRANSPORT_RAIL)) {
-		UpdateSignalsOnSegment(tile, INVALID_DIAGDIR);
+		UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, owner);
 	} else {
-		SetSignalsOnBothDir(tile, (Track)(FIND_FIRST_BIT(track)));
+		SetSignalsOnBothDir(tile, (Track)(FIND_FIRST_BIT(track)), owner);
 	}
 }
 
--- 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);
+		UpdateSignalsOnSegment(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);
+			UpdateSignalsOnSegment(start_tile, INVALID_DIAGDIR, _current_player);
 			YapfNotifyTrackLayoutChange(start_tile, AxisToTrack(DiagDirToAxis(direction)));
 		} else {
 			MakeRoadTunnel(start_tile, _current_player, direction,                 (RoadTypes)GB(p1, 0, 3));
@@ -603,21 +603,24 @@
 	}
 
 	if (flags & DC_EXEC) {
-		/* We first need to request the direction before calling DoClearSquare
-		 *  else the direction is always 0.. dah!! ;) */
-		DiagDirection dir = GetTunnelBridgeDirection(tile);
-		bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
+		if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
+			/* We first need to request values before calling DoClearSquare */
+			DiagDirection dir = GetTunnelBridgeDirection(tile);
+			Owner owner = GetTileOwner(tile);
 
-		DoClearSquare(tile);
-		DoClearSquare(endtile);
+			DoClearSquare(tile);
+			DoClearSquare(endtile);
 
-		if (rail) {
-			UpdateSignalsOnSegment(tile, ReverseDiagDir(dir));
-			UpdateSignalsOnSegment(endtile, dir);
+			/* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */
+			UpdateSignalsOnSegment(tile, ReverseDiagDir(dir), owner);
+			UpdateSignalsOnSegment(endtile, dir, owner);
 
 			Track track = AxisToTrack(DiagDirToAxis(dir));
 			YapfNotifyTrackLayoutChange(tile, track);
 			YapfNotifyTrackLayoutChange(endtile, track);
+		} else {
+			DoClearSquare(tile);
+			DoClearSquare(endtile);
 		}
 	}
 	return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_tunnel * (DistanceManhattan(tile, endtile) + 1));
@@ -660,6 +663,7 @@
 	if (flags & DC_EXEC) {
 		/* read this value before actual removal of bridge */
 		bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
+		Owner owner = GetTileOwner(tile);
 
 		DoClearSquare(tile);
 		DoClearSquare(endtile);
@@ -669,8 +673,9 @@
 		}
 
 		if (rail) {
-			UpdateSignalsOnSegment(tile, ReverseDiagDir(direction));
-			UpdateSignalsOnSegment(endtile, direction);
+			/* cannot use INVALID_DIAGDIR for signal update because the bridge doesn't exist anymore */
+			UpdateSignalsOnSegment(tile, ReverseDiagDir(direction), owner);
+			UpdateSignalsOnSegment(endtile, direction, owner);
 
 			Track track = AxisToTrack(DiagDirToAxis(direction));
 			YapfNotifyTrackLayoutChange(tile, track);
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -2178,7 +2178,7 @@
 		case VEH_TRAIN:
 			InvalidateWindowClasses(WC_TRAINS_LIST);
 			if (!IsFrontEngine(v)) v = v->First();
-			UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR);
+			UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner);
 			v->load_unload_time_rem = 0;
 			break;
 
--- a/src/waypoint.cpp
+++ b/src/waypoint.cpp
@@ -286,6 +286,7 @@
 
 	if (flags & DC_EXEC) {
 		Track track = GetRailWaypointTrack(tile);
+		Owner owner = GetTileOwner(tile); // cannot use _current_player because of possible floods
 		wp = GetWaypointByTile(tile);
 
 		wp->deleted = 30; // let it live for this many days before we do the actual deletion.
@@ -296,7 +297,7 @@
 			MarkTileDirtyByTile(tile);
 		} else {
 			DoClearSquare(tile);
-			SetSignalsOnBothDir(tile, track);
+			SetSignalsOnBothDir(tile, track, owner);
 		}
 		YapfNotifyTrackLayoutChange(tile, track);
 	}