Changeset - r27976:645fcc9c218c
[Not reviewed]
master
0 8 0
Peter Nelson - 8 months ago 2023-09-30 11:30:25
peter1138@openttd.org
Change: Store station blocked/wires/pylons flags in map. (#11337)

This stores three flags in unused map bits, and avoids having to look up
station graphics and custom station specs to determine blocked/wires/pylons
status.

This potentially affects rail pathfinding performance.

Savegame version is not bumped, as the flags can just be updated every
time.
8 files changed with 124 insertions and 51 deletions:
0 comments (0 inline, 0 general)
docs/landscape.html
Show inline comments
 
@@ -986,14 +986,17 @@
 
          </tr>
 
         </table>
 
        </td>
 
       </tr>
 
      </table>
 
     </li>
 
     <li>m6 bit 7: rail station / waypoint may have catenary pylons</li>
 
     <li>m6 bit 6: rail station / waypoint may have catenary wires</li>
 
     <li>m6 bits 5..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy, waypoint)</li>
 
     <li>m6 bit 2: pbs reservation state for railway stations/waypoints</li>
 
     <li>m6 bit 0: rail station / waypoint is blocked</li>
 

	
 
     <li>m7 bits 4..0: <a href="#OwnershipInfo">owner</a> of road (road stops)</li>
 
     <li>m7: animation frame (railway stations/waypoints, airports)</li>
 
     <li>m8 bits 11..6: <a href="#TramType">Tramtype</a></li>
 
     <li>m8 bits 5..0: <a href="#TrackType">track type</a> for railway stations/waypoints</li>
 
     <li>m8 bits 5..0: custom road stop id; 0 means standard graphics</li>
docs/landscape_grid.html
Show inline comments
 
@@ -185,13 +185,13 @@ the array so you can quickly see what is
 
      <td class="caption">rail station</td>
 
      <td class="bits" rowspan=7><span class="free">O</span><span class="used" title="Water class">XX</span> <span class="used" title="Owner">XXXXX</span></td>
 
      <td class="bits" rowspan=7><span class="pool" title="Station index on pool">XXXX XXXX XXXX XXXX</span></td>
 
      <td class="bits" rowspan=2><span class="used" title="Random bits">XXXX</span> <span class="free">OOOO</span></td>
 
      <td class="bits" rowspan=2><span class="used" title="Custom station specifications ID">XXXX XXXX</span></td>
 
      <td class="bits"><span class="used" title="Graphics index">XXXX XXXX</span></td>
 
      <td class="bits" rowspan=2><span class="free">OO</span><span class="used" title="Station type">XXX</span> <span class="used" title="Reserved track">X</span><span class="free">OO</span></td>
 
      <td class="bits" rowspan=2><span class="used" title="May have pylons">X</span><span class="used" title="May have wires">X</span><span class="used" title="Station type">XXX</span> <span class="used" title="Reserved track">X</span><span class="free">O</span><span class="used" title="Tile is blocked">X</span></td>
 
      <td class="bits" rowspan=2><span class="used" title="Animation frame">XXXX XXXX</span></td>
 
      <td class="bits" rowspan=2><span class="free">OOOO OOOO OO</span><span class="used" title="Railway type">XX XXXX</span></td>
 
    </tr>
 
    <tr>
 
      <td class="caption">rail waypoint</td>
 
      <td class="bits"><span class="usable" title="Graphics index">OOOO OOO</span><span class="used" title="Graphics index">X</span></td>
src/newgrf_station.cpp
Show inline comments
 
@@ -837,52 +837,12 @@ const StationSpec *GetStationSpec(TileIn
 

	
 
	const BaseStation *st = BaseStation::GetByTile(t);
 
	uint specindex = GetCustomStationSpecIndex(t);
 
	return specindex < st->speclist.size() ? st->speclist[specindex].spec : nullptr;
 
}
 

	
 

	
 
/**
 
 * Check whether a rail station tile is NOT traversable.
 
 * @param tile %Tile to test.
 
 * @return Station tile is blocked.
 
 * @note This could be cached (during build) in the map array to save on all the dereferencing.
 
 */
 
bool IsStationTileBlocked(TileIndex tile)
 
{
 
	const StationSpec *statspec = GetStationSpec(tile);
 

	
 
	return statspec != nullptr && HasBit(statspec->blocked, GetStationGfx(tile));
 
}
 

	
 
/**
 
 * Check if a rail station tile shall have pylons when electrified.
 
 * @param tile %Tile to test.
 
 * @return Tile shall have pylons.
 
 * @note This could be cached (during build) in the map array to save on all the dereferencing.
 
 */
 
bool CanStationTileHavePylons(TileIndex tile)
 
{
 
	const StationSpec *statspec = GetStationSpec(tile);
 
	uint gfx = GetStationGfx(tile);
 
	/* Default stations do not draw pylons under roofs (gfx >= 4) */
 
	return statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4;
 
}
 

	
 
/**
 
 * Check if a rail station tile shall have wires when electrified.
 
 * @param tile %Tile to test.
 
 * @return Tile shall have wires.
 
 * @note This could be cached (during build) in the map array to save on all the dereferencing.
 
 */
 
bool CanStationTileHaveWires(TileIndex tile)
 
{
 
	const StationSpec *statspec = GetStationSpec(tile);
 
	return statspec == nullptr || !HasBit(statspec->wires, GetStationGfx(tile));
 
}
 

	
 
/** Wrapper for animation control, see GetStationCallback. */
 
uint16_t GetAnimStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int)
 
{
 
	return GetStationCallback(callback, param1, param2, statspec, st, tile);
 
}
 

	
src/saveload/afterload.cpp
Show inline comments
 
@@ -44,12 +44,13 @@
 
#include "../town.h"
 
#include "../economy_base.h"
 
#include "../animated_tile_func.h"
 
#include "../subsidy_base.h"
 
#include "../subsidy_func.h"
 
#include "../newgrf.h"
 
#include "../newgrf_station.h"
 
#include "../engine_func.h"
 
#include "../rail_gui.h"
 
#include "../core/backup_type.hpp"
 
#include "../smallmap_gui.h"
 
#include "../news_func.h"
 
#include "../order_backup.h"
 
@@ -2853,12 +2854,32 @@ bool AfterLoadGame()
 
	if (IsSavegameVersionBefore(SLV_178)) {
 
		extern uint8_t _old_diff_level;
 
		/* Initialise script settings profile */
 
		_settings_game.script.settings_profile = IsInsideMM(_old_diff_level, SP_BEGIN, SP_END) ? _old_diff_level : (uint)SP_MEDIUM;
 
	}
 

	
 
	{
 
		/* Station blocked, wires and pylon flags need to be stored in the map. This is effectively cached data, so no
 
		 * version check is necessary. This is done here as the SLV_182 check below needs the blocked status. */
 
		for (auto t : Map::Iterate()) {
 
			if (HasStationTileRail(t)) {
 
				StationGfx gfx = GetStationGfx(t);
 
				const StationSpec *statspec = GetStationSpec(t);
 

	
 
				bool blocked = statspec != nullptr && HasBit(statspec->blocked, gfx);
 
				/* Default stations do not draw pylons under roofs (gfx >= 4) */
 
				bool pylons = statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4;
 
				bool wires = statspec == nullptr || !HasBit(statspec->wires, gfx);
 

	
 
				SetStationTileBlocked(t, blocked);
 
				SetStationTileHavePylons(t, pylons);
 
				SetStationTileHaveWires(t, wires);
 
			}
 
		}
 
	}
 

	
 
	if (IsSavegameVersionBefore(SLV_182)) {
 
		/* Aircraft acceleration variable was bonkers */
 
		for (Aircraft *v : Aircraft::Iterate()) {
 
			if (v->subtype <= AIR_AIRCRAFT) {
 
				const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
 
				v->acceleration = avi->acceleration;
src/station_cmd.cpp
Show inline comments
 
@@ -1463,13 +1463,24 @@ CommandCost CmdBuildRailStation(DoComman
 
				DeallocateSpecFromStation(st, old_specindex);
 

	
 
				SetCustomStationSpecIndex(tile, specindex);
 
				SetStationTileRandomBits(tile, GB(Random(), 0, 4));
 
				SetAnimationFrame(tile, 0);
 

	
 
				if (!IsStationTileBlocked(tile)) c->infrastructure.rail[rt]++;
 
				/* Should be the same as layout but axis component could be wrong... */
 
				StationGfx gfx = GetStationGfx(tile);
 
				bool blocked = statspec != nullptr && HasBit(statspec->blocked, gfx);
 
				/* Default stations do not draw pylons under roofs (gfx >= 4) */
 
				bool pylons = statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4;
 
				bool wires = statspec == nullptr || !HasBit(statspec->wires, gfx);
 

	
 
				SetStationTileBlocked(tile, blocked);
 
				SetStationTileHavePylons(tile, pylons);
 
				SetStationTileHaveWires(tile, wires);
 

	
 
				if (!blocked) c->infrastructure.rail[rt]++;
 
				c->infrastructure.station++;
 

	
 
				if (statspec != nullptr) {
 
					/* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
 
					uint32_t platinfo = GetPlatformInfo(AXIS_X, GetStationGfx(tile), plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
 

	
src/station_func.h
Show inline comments
 
@@ -40,18 +40,12 @@ bool HasStationInUse(StationID station, 
 

	
 
void DeleteOilRig(TileIndex t);
 
void UpdateStationDockingTiles(Station *st);
 
void RemoveDockingTile(TileIndex t);
 
void ClearDockingTilesCheckingNeighbours(TileIndex tile);
 

	
 
/* Check if a rail station tile is traversable. */
 
bool IsStationTileBlocked(TileIndex tile);
 

	
 
bool CanStationTileHavePylons(TileIndex tile);
 
bool CanStationTileHaveWires(TileIndex tile);
 

	
 
void UpdateAirportsNoise();
 

	
 
bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset);
 

	
 
void IncreaseStats(Station *st, const Vehicle *v, StationID next_station_id, uint32_t time);
 
void IncreaseStats(Station *st, CargoID cargo, StationID next_station_id, uint capacity, uint usage, uint32_t time, EdgeUpdateMode mode);
src/station_map.h
Show inline comments
 
@@ -327,12 +327,84 @@ static inline bool IsBuoyTile(Tile t)
 
static inline bool IsHangarTile(Tile t)
 
{
 
	return IsTileType(t, MP_STATION) && IsHangar(t);
 
}
 

	
 
/**
 
 * Is tile \a t a blocked tile?
 
 * @pre HasStationRail(t)
 
 * @param t Tile to check
 
 * @return \c true if the tile is blocked
 
 */
 
static inline bool IsStationTileBlocked(Tile t)
 
{
 
	assert(HasStationRail(t));
 
	return HasBit(t.m6(), 0);
 
}
 

	
 
/**
 
 * Set the blocked state of the rail station
 
 * @pre HasStationRail(t)
 
 * @param t the station tile
 
 * @param b the blocked state
 
 */
 
static inline void SetStationTileBlocked(Tile t, bool b)
 
{
 
	assert(HasStationRail(t));
 
	SB(t.m6(), 0, 1, b ? 1 : 0);
 
}
 

	
 
/**
 
 * Can tile \a t have catenary wires?
 
 * @pre HasStationRail(t)
 
 * @param t Tile to check
 
 * @return \c true if the tile can have catenary wires
 
 */
 
static inline bool CanStationTileHaveWires(Tile t)
 
{
 
	assert(HasStationRail(t));
 
	return HasBit(t.m6(), 6);
 
}
 

	
 
/**
 
 * Set the catenary wires state of the rail station
 
 * @pre HasStationRail(t)
 
 * @param t the station tile
 
 * @param b the catenary wires state
 
 */
 
static inline void SetStationTileHaveWires(Tile t, bool b)
 
{
 
	assert(HasStationRail(t));
 
	SB(t.m6(), 6, 1, b ? 1 : 0);
 
}
 

	
 
/**
 
 * Can tile \a t have catenary pylons?
 
 * @pre HasStationRail(t)
 
 * @param t Tile to check
 
 * @return \c true if the tile can have catenary pylons
 
 */
 
static inline bool CanStationTileHavePylons(Tile t)
 
{
 
	assert(HasStationRail(t));
 
	return HasBit(t.m6(), 7);
 
}
 

	
 
/**
 
 * Set the catenary pylon state of the rail station
 
 * @pre HasStationRail(t)
 
 * @param t the station tile
 
 * @param b the catenary pylons state
 
 */
 
static inline void SetStationTileHavePylons(Tile t, bool b)
 
{
 
	assert(HasStationRail(t));
 
	SB(t.m6(), 7, 1, b ? 1 : 0);
 
}
 

	
 
/**
 
 * Get the rail direction of a rail station.
 
 * @param t Tile to query
 
 * @pre HasStationRail(t)
 
 * @return The direction of the rails on tile \a t.
 
 */
 
static inline Axis GetRailStationAxis(Tile t)
 
@@ -376,16 +448,16 @@ static inline TrackBits GetRailStationTr
 
 * @pre IsRailStationTile(station_tile)
 
 * @return true if the two tiles are compatible
 
 */
 
static inline bool IsCompatibleTrainStationTile(Tile test_tile, Tile station_tile)
 
{
 
	assert(IsRailStationTile(station_tile));
 
	return IsRailStationTile(test_tile) && IsCompatibleRail(GetRailType(test_tile), GetRailType(station_tile)) &&
 
	return IsRailStationTile(test_tile) && !IsStationTileBlocked(test_tile) &&
 
			IsCompatibleRail(GetRailType(test_tile), GetRailType(station_tile)) &&
 
			GetRailStationAxis(test_tile) == GetRailStationAxis(station_tile) &&
 
			GetStationIndex(test_tile) == GetStationIndex(station_tile) &&
 
			!IsStationTileBlocked(test_tile);
 
			GetStationIndex(test_tile) == GetStationIndex(station_tile);
 
}
 

	
 
/**
 
 * Get the reservation state of the rail station
 
 * @pre HasStationRail(t)
 
 * @param t the station tile
src/waypoint_cmd.cpp
Show inline comments
 
@@ -274,12 +274,24 @@ CommandCost CmdBuildRailWaypoint(DoComma
 
			if (!HasStationTileRail(tile)) c->infrastructure.station++;
 
			bool reserved = IsTileType(tile, MP_RAILWAY) ?
 
					HasBit(GetRailReservationTrackBits(tile), AxisToTrack(axis)) :
 
					HasStationReservation(tile);
 
			MakeRailWaypoint(tile, wp->owner, wp->index, axis, layout_ptr[i], GetRailType(tile));
 
			SetCustomStationSpecIndex(tile, map_spec_index);
 

	
 
			/* Should be the same as layout but axis component could be wrong... */
 
			StationGfx gfx = GetStationGfx(tile);
 
			bool blocked = spec != nullptr && HasBit(spec->blocked, gfx);
 
			/* Default stations do not draw pylons under roofs (gfx >= 4) */
 
			bool pylons = spec != nullptr ? HasBit(spec->pylons, gfx) : gfx < 4;
 
			bool wires = spec == nullptr || !HasBit(spec->wires, gfx);
 

	
 
			SetStationTileBlocked(tile, blocked);
 
			SetStationTileHavePylons(tile, pylons);
 
			SetStationTileHaveWires(tile, wires);
 

	
 
			SetRailStationReservation(tile, reserved);
 
			MarkTileDirtyByTile(tile);
 

	
 
			DeallocateSpecFromStation(wp, old_specindex);
 
			YapfNotifyTrackLayoutChange(tile, AxisToTrack(axis));
 
		}
0 comments (0 inline, 0 general)