Change: Store station blocked/wires/pylons flags in map.

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.

(cherry picked from commit cb658e6cc6e1c114c1eaafaaa5b14849f04ca083)
This commit is contained in:
Peter Nelson
2023-09-25 20:22:36 +01:00
committed by Jonathan G Rennison
parent e162e7a331
commit b2a1ec96f1
8 changed files with 124 additions and 51 deletions

View File

@@ -1050,8 +1050,11 @@
</tr> </tr>
</table> </table>
</li> </li>
<li>m6 bit 7: rail station / waypoint may have catenary pylons</li>
<li>m6 bits <span style="color: blue">6</span>..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy, waypoint, <span style="color: blue">road waypoint</span>)</li> <li>m6 bits <span style="color: blue">6</span>..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy, waypoint, <span style="color: blue">road waypoint</span>)</li>
<li>m6 bit 2: pbs reservation state for railway stations/waypoints</li> <li>m6 bit 2: pbs reservation state for railway stations/waypoints</li>
<li>m6 bit <span style="color: blue">1</span>: rail station / waypoint may have catenary wires</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 bits 4..0: <a href="#OwnershipInfo">owner</a> of road (road stops)</li>
<li>m7: animation frame (railway stations/waypoints, airports)</li> <li>m7: animation frame (railway stations/waypoints, airports)</li>

View File

@@ -194,7 +194,7 @@ the array so you can quickly see what is used and what is not.
<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="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" 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"><span class="used" title="Graphics index">XXXX XXXX</span></td>
<td class="bits" rowspan=2><span class="free">O<span class="patch" title="Station type (extra bit)">P</span></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="patch" title="Station type (extra bit)">P</span><span class="used" title="Station type">XXX</span> <span class="used" title="Reserved track">X</span><span class="patch" title="May have wires (moved from bit 6)">P</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="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> <td class="bits" rowspan=2><span class="free">OOOO OOOO OO</span><span class="used" title="Railway type">XX XXXX</span></td>
</tr> </tr>

View File

@@ -872,46 +872,6 @@ const StationSpec *GetStationSpec(TileIndex t)
return specindex < st->speclist.size() ? st->speclist[specindex].spec : nullptr; 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. */ /** Wrapper for animation control, see GetStationCallback. */
uint16 GetAnimStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int extra_data) uint16 GetAnimStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int extra_data)
{ {

View File

@@ -49,6 +49,7 @@
#include "../subsidy_base.h" #include "../subsidy_base.h"
#include "../subsidy_func.h" #include "../subsidy_func.h"
#include "../newgrf.h" #include "../newgrf.h"
#include "../newgrf_station.h"
#include "../engine_func.h" #include "../engine_func.h"
#include "../rail_gui.h" #include "../rail_gui.h"
#include "../road_gui.h" #include "../road_gui.h"
@@ -3337,6 +3338,26 @@ bool AfterLoadGame()
_settings_game.script.settings_profile = IsInsideMM(_old_diff_level, SP_BEGIN, SP_END) ? _old_diff_level : (uint)SP_MEDIUM; _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 (TileIndex t = 0; t < map_size; t++) {
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)) { if (IsSavegameVersionBefore(SLV_182)) {
/* Aircraft acceleration variable was bonkers */ /* Aircraft acceleration variable was bonkers */
for (Aircraft *v : Aircraft::Iterate()) { for (Aircraft *v : Aircraft::Iterate()) {

View File

@@ -1641,7 +1641,18 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
SetStationTileRandomBits(tile, GB(Random(), 0, 4)); SetStationTileRandomBits(tile, GB(Random(), 0, 4));
SetAnimationFrame(tile, 0); 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++; c->infrastructure.station++;
if (statspec != nullptr) { if (statspec != nullptr) {

View File

@@ -42,12 +42,6 @@ void RemoveDockingTile(TileIndex t);
void ClearDockingTilesCheckingNeighbours(TileIndex tile); void ClearDockingTilesCheckingNeighbours(TileIndex tile);
bool IsValidDockingDirectionForDock(TileIndex t, DiagDirection d); bool IsValidDockingDirectionForDock(TileIndex t, DiagDirection d);
/* Check if a rail station tile is traversable. */
bool IsStationTileBlocked(TileIndex tile);
bool CanStationTileHavePylons(TileIndex tile);
bool CanStationTileHaveWires(TileIndex tile);
void UpdateAirportsNoise(); void UpdateAirportsNoise();
bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset); bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset);

View File

@@ -438,6 +438,78 @@ static inline bool IsHangarTile(TileIndex t)
return IsTileType(t, MP_STATION) && IsHangar(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(TileIndex t)
{
assert(HasStationRail(t));
return HasBit(_me[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(TileIndex t, bool b)
{
assert(HasStationRail(t));
SB(_me[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(TileIndex t)
{
assert(HasStationRail(t));
return HasBit(_me[t].m6, 1);
}
/**
* 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(TileIndex t, bool b)
{
assert(HasStationRail(t));
SB(_me[t].m6, 1, 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(TileIndex t)
{
assert(HasStationRail(t));
return HasBit(_me[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(TileIndex t, bool b)
{
assert(HasStationRail(t));
SB(_me[t].m6, 7, 1, b ? 1 : 0);
}
/** /**
* Get the rail direction of a rail station. * Get the rail direction of a rail station.
* @param t Tile to query * @param t Tile to query
@@ -488,10 +560,10 @@ static inline TrackBits GetRailStationTrackBits(TileIndex t)
static inline bool IsCompatibleTrainStationTile(TileIndex test_tile, TileIndex station_tile) static inline bool IsCompatibleTrainStationTile(TileIndex test_tile, TileIndex station_tile)
{ {
dbg_assert_tile(IsRailStationTile(station_tile), station_tile); dbg_assert_tile(IsRailStationTile(station_tile), 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) && GetRailStationAxis(test_tile) == GetRailStationAxis(station_tile) &&
GetStationIndex(test_tile) == GetStationIndex(station_tile) && GetStationIndex(test_tile) == GetStationIndex(station_tile);
!IsStationTileBlocked(test_tile);
} }
/** /**

View File

@@ -317,6 +317,18 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
MakeRailWaypoint(tile, wp->owner, wp->index, axis, layout_ptr[i], GetRailType(tile)); MakeRailWaypoint(tile, wp->owner, wp->index, axis, layout_ptr[i], GetRailType(tile));
if (old_specindex != map_spec_index) DeallocateSpecFromStation(wp, old_specindex); if (old_specindex != map_spec_index) DeallocateSpecFromStation(wp, old_specindex);
SetCustomStationSpecIndex(tile, map_spec_index); 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); SetRailStationReservation(tile, reserved);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);