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)
pull/603/head
Peter Nelson 8 months ago committed by Jonathan G Rennison
parent e162e7a331
commit b2a1ec96f1

@ -1050,8 +1050,11 @@
</tr>
</table>
</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 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: animation frame (railway stations/waypoints, airports)</li>

@ -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="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">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="free">OOOO OOOO OO</span><span class="used" title="Railway type">XX XXXX</span></td>
</tr>

@ -872,46 +872,6 @@ const StationSpec *GetStationSpec(TileIndex 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 GetAnimStationCallback(CallbackID callback, uint32 param1, uint32 param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, int extra_data)
{

@ -49,6 +49,7 @@
#include "../subsidy_base.h"
#include "../subsidy_func.h"
#include "../newgrf.h"
#include "../newgrf_station.h"
#include "../engine_func.h"
#include "../rail_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;
}
{
/* 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)) {
/* Aircraft acceleration variable was bonkers */
for (Aircraft *v : Aircraft::Iterate()) {

@ -1641,7 +1641,18 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
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) {

@ -42,12 +42,6 @@ void RemoveDockingTile(TileIndex t);
void ClearDockingTilesCheckingNeighbours(TileIndex tile);
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();
bool SplitGroundSpriteForOverlay(const TileInfo *ti, SpriteID *ground, RailTrackOffset *overlay_offset);

@ -438,6 +438,78 @@ static inline bool IsHangarTile(TileIndex 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.
* @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)
{
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) &&
GetStationIndex(test_tile) == GetStationIndex(station_tile) &&
!IsStationTileBlocked(test_tile);
GetStationIndex(test_tile) == GetStationIndex(station_tile);
}
/**

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

Loading…
Cancel
Save