mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-10-31 15:20:10 +00:00
Change ship path cache to be optional and use a ring buffer
This commit is contained in:
parent
2ae4e5bdc1
commit
92e632454e
@ -38,9 +38,6 @@ static const int YAPF_TILE_CORNER_LENGTH = 71;
|
||||
*/
|
||||
static const int YAPF_INFINITE_PENALTY = 1000 * YAPF_TILE_LENGTH;
|
||||
|
||||
/** Maximum length of ship path cache */
|
||||
static const int YAPF_SHIP_PATH_CACHE_LENGTH = 32;
|
||||
|
||||
/** Distance from destination road stops to not cache any further */
|
||||
static const int YAPF_ROADVEH_PATH_CACHE_DESTINATION_LIMIT = 8;
|
||||
|
||||
|
@ -173,7 +173,7 @@ public:
|
||||
uint steps = 0;
|
||||
for (Node *n = pNode; n->m_parent != nullptr; n = n->m_parent) steps++;
|
||||
uint skip = 0;
|
||||
if (path_found) skip = YAPF_SHIP_PATH_CACHE_LENGTH / 2;
|
||||
if (path_found) skip = SHIP_PATH_CACHE_LENGTH / 2;
|
||||
|
||||
/* walk through the path back to the origin */
|
||||
Node *pPrevNode = nullptr;
|
||||
@ -181,7 +181,7 @@ public:
|
||||
steps--;
|
||||
/* Skip tiles at end of path near destination. */
|
||||
if (skip > 0) skip--;
|
||||
if (skip == 0 && steps > 0 && steps < YAPF_SHIP_PATH_CACHE_LENGTH) {
|
||||
if (skip == 0 && steps > 0 && steps < SHIP_PATH_CACHE_LENGTH) {
|
||||
path_cache.push_front(pNode->GetTrackdir());
|
||||
}
|
||||
pPrevNode = pNode;
|
||||
|
@ -293,7 +293,7 @@ public:
|
||||
inline static const SaveLoad description[] = {
|
||||
SLEG_STRUCT("common", SlVehicleCommon),
|
||||
SLE_VAR(Ship, state, SLE_UINT8),
|
||||
SLE_CONDDEQUE(Ship, path, SLE_UINT8, SLV_SHIP_PATH_CACHE, SL_MAX_VERSION),
|
||||
SLEG_CONDVECTOR("path", _path_td, SLE_UINT8, SLV_SHIP_PATH_CACHE, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Ship, rotation, SLE_UINT8, SLV_SHIP_ROTATION, SL_MAX_VERSION),
|
||||
};
|
||||
inline const static SaveLoadCompatTable compat_description = _vehicle_ship_sl_compat;
|
||||
@ -308,6 +308,16 @@ public:
|
||||
{
|
||||
if (v->type != VEH_SHIP) return;
|
||||
SlObject(v, this->GetLoadDescription());
|
||||
|
||||
if (!_path_td.empty() && _path_td.size() <= SHIP_PATH_CACHE_LENGTH) {
|
||||
Ship *s = Ship::From(v);
|
||||
s->cached_path.reset(new ShipPathCache());
|
||||
s->cached_path->count = _path_td.size();
|
||||
for (size_t i = 0; i < _path_td.size(); i++) {
|
||||
s->cached_path->td[i] = _path_td[i];
|
||||
}
|
||||
}
|
||||
_path_td.clear();
|
||||
}
|
||||
|
||||
void FixPointers(Vehicle *v) const override
|
||||
|
@ -1709,7 +1709,7 @@ static void MaxVehiclesChanged(int32 new_value)
|
||||
static void InvalidateShipPathCache(int32 new_value)
|
||||
{
|
||||
for (Ship *s : Ship::Iterate()) {
|
||||
s->path.clear();
|
||||
s->cached_path.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
53
src/ship.h
53
src/ship.h
@ -10,7 +10,7 @@
|
||||
#ifndef SHIP_H
|
||||
#define SHIP_H
|
||||
|
||||
#include <deque>
|
||||
#include <array>
|
||||
|
||||
#include "vehicle_base.h"
|
||||
#include "water_map.h"
|
||||
@ -20,14 +20,55 @@ extern const DiagDirection _ship_search_directions[TRACK_END][DIAGDIR_END];
|
||||
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
|
||||
WaterClass GetEffectiveWaterClass(TileIndex tile);
|
||||
|
||||
typedef std::deque<Trackdir> ShipPathCache;
|
||||
/** Maximum segments of ship path cache */
|
||||
static const uint8 SHIP_PATH_CACHE_LENGTH = 32;
|
||||
static const uint8 SHIP_PATH_CACHE_MASK = (SHIP_PATH_CACHE_LENGTH - 1);
|
||||
static_assert((SHIP_PATH_CACHE_LENGTH & SHIP_PATH_CACHE_MASK) == 0, ""); // Must be a power of 2
|
||||
|
||||
struct ShipPathCache {
|
||||
std::array<Trackdir, SHIP_PATH_CACHE_LENGTH> td;
|
||||
uint8 start = 0;
|
||||
uint8 count = 0;
|
||||
|
||||
inline bool empty() const { return this->count == 0; }
|
||||
inline uint8 size() const { return this->count; }
|
||||
inline bool full() const { return this->count >= SHIP_PATH_CACHE_LENGTH; }
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
this->start = 0;
|
||||
this->count = 0;
|
||||
}
|
||||
|
||||
inline Trackdir front() const { return this->td[this->start]; }
|
||||
inline Trackdir back() const { return this->td[(this->start + this->count - 1) & SHIP_PATH_CACHE_MASK]; }
|
||||
|
||||
/* push an item to the front of the ring, if the ring is already full, the back item is overwritten */
|
||||
inline void push_front(Trackdir td)
|
||||
{
|
||||
this->start = (this->start - 1) & SHIP_PATH_CACHE_MASK;
|
||||
if (!this->full()) this->count++;
|
||||
this->td[this->start] = td;
|
||||
}
|
||||
|
||||
inline void pop_front()
|
||||
{
|
||||
this->start = (this->start + 1) & SHIP_PATH_CACHE_MASK;
|
||||
this->count--;
|
||||
}
|
||||
|
||||
inline void pop_back()
|
||||
{
|
||||
this->count--;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* All ships have this type.
|
||||
*/
|
||||
struct Ship FINAL : public SpecializedVehicle<Ship, VEH_SHIP> {
|
||||
TrackBits state; ///< The "track" the ship is following.
|
||||
ShipPathCache path; ///< Cached path.
|
||||
std::unique_ptr<ShipPathCache> cached_path; ///< Cached path.
|
||||
Direction rotation; ///< Visible direction.
|
||||
int16 rotation_x_pos; ///< NOSAVE: X Position before rotation.
|
||||
int16 rotation_y_pos; ///< NOSAVE: Y Position before rotation.
|
||||
@ -61,6 +102,12 @@ struct Ship FINAL : public SpecializedVehicle<Ship, VEH_SHIP> {
|
||||
ClosestDepot FindClosestDepot() override;
|
||||
void UpdateCache();
|
||||
void SetDestTile(TileIndex tile) override;
|
||||
|
||||
inline ShipPathCache &GetOrCreatePathCache()
|
||||
{
|
||||
if (!this->cached_path) this->cached_path.reset(new ShipPathCache());
|
||||
return *this->cached_path;
|
||||
}
|
||||
};
|
||||
|
||||
bool IsShipDestinationTile(TileIndex tile, StationID station);
|
||||
|
@ -567,22 +567,22 @@ static Track ChooseShipTrack(Ship *v, TileIndex tile, DiagDirection enterdir, Tr
|
||||
path_found = false;
|
||||
} else {
|
||||
/* Attempt to follow cached path. */
|
||||
if (!v->path.empty()) {
|
||||
track = TrackdirToTrack(v->path.front());
|
||||
if (v->cached_path != nullptr && !v->cached_path->empty()) {
|
||||
track = TrackdirToTrack(v->cached_path->front());
|
||||
|
||||
if (HasBit(tracks, track)) {
|
||||
v->path.pop_front();
|
||||
v->cached_path->pop_front();
|
||||
/* HandlePathfindResult() is not called here because this is not a new pathfinder result. */
|
||||
return track;
|
||||
}
|
||||
|
||||
/* Cached path is invalid so continue with pathfinder. */
|
||||
v->path.clear();
|
||||
v->cached_path->clear();
|
||||
}
|
||||
|
||||
switch (_settings_game.pf.pathfinder_for_ships) {
|
||||
case VPF_NPF: track = NPFShipChooseTrack(v, path_found); break;
|
||||
case VPF_YAPF: track = YapfShipChooseTrack(v, tile, enterdir, tracks, path_found, v->path); break;
|
||||
case VPF_YAPF: track = YapfShipChooseTrack(v, tile, enterdir, tracks, path_found, v->GetOrCreatePathCache()); break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
@ -882,7 +882,7 @@ static void ReverseShipIntoTrackdir(Ship *v, Trackdir trackdir)
|
||||
v->rotation_x_pos = v->x_pos;
|
||||
v->rotation_y_pos = v->y_pos;
|
||||
UpdateShipSpeed(v, 0);
|
||||
v->path.clear();
|
||||
if (v->cached_path != nullptr) v->cached_path->clear();
|
||||
|
||||
v->UpdatePosition();
|
||||
v->UpdateViewport(true, true);
|
||||
@ -896,7 +896,7 @@ static void ReverseShip(Ship *v)
|
||||
v->rotation_x_pos = v->x_pos;
|
||||
v->rotation_y_pos = v->y_pos;
|
||||
UpdateShipSpeed(v, 0);
|
||||
v->path.clear();
|
||||
if (v->cached_path != nullptr) v->cached_path->clear();
|
||||
|
||||
v->UpdatePosition();
|
||||
v->UpdateViewport(true, true);
|
||||
@ -1081,7 +1081,7 @@ static void ShipController(Ship *v)
|
||||
|
||||
/* Ship is back on the bridge head, we need to consume its path
|
||||
* cache entry here as we didn't have to choose a ship track. */
|
||||
if (!v->path.empty()) v->path.pop_front();
|
||||
if (v->cached_path != nullptr && !v->cached_path->empty()) v->cached_path->pop_front();
|
||||
}
|
||||
|
||||
/* update image of ship, as well as delta XY */
|
||||
@ -1107,7 +1107,7 @@ bool Ship::Tick()
|
||||
void Ship::SetDestTile(TileIndex tile)
|
||||
{
|
||||
if (tile == this->dest_tile) return;
|
||||
this->path.clear();
|
||||
if (this->cached_path != nullptr) this->cached_path->clear();
|
||||
this->dest_tile = tile;
|
||||
}
|
||||
|
||||
|
@ -877,7 +877,7 @@ SaveLoadTable GetVehicleDescription(VehicleType vt)
|
||||
SLE_WRITEBYTE(Vehicle, type),
|
||||
SLE_VEH_INCLUDE(),
|
||||
SLE_VAR(Ship, state, SLE_UINT8),
|
||||
SLE_CONDDEQUE(Ship, path, SLE_UINT8, SLV_SHIP_PATH_CACHE, SL_MAX_VERSION),
|
||||
SLEG_CONDVARVEC(_path_td, SLE_UINT8, SLV_SHIP_PATH_CACHE, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Ship, rotation, SLE_UINT8, SLV_SHIP_ROTATION, SL_MAX_VERSION),
|
||||
SLE_CONDVAR_X(Ship, lost_count, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SHIP_LOST_COUNTER)),
|
||||
SLE_CONDVAR_X(Ship, critical_breakdown_count, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_IMPROVED_BREAKDOWNS, 8)),
|
||||
@ -1043,6 +1043,17 @@ static void Save_VEHS()
|
||||
}
|
||||
_path_layout_ctr = rv->cached_path->layout_ctr;
|
||||
}
|
||||
} else if (v->type == VEH_SHIP) {
|
||||
_path_td.clear();
|
||||
|
||||
Ship *s = Ship::From(v);
|
||||
if (s->cached_path != nullptr && !s->cached_path->empty()) {
|
||||
uint idx = s->cached_path->start;
|
||||
for (uint i = 0; i < s->cached_path->size(); i++) {
|
||||
_path_td.push_back(s->cached_path->td[idx]);
|
||||
idx = (idx + 1) & SHIP_PATH_CACHE_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
SlSetArrayIndex(v->index);
|
||||
SlObjectSaveFiltered(v, GetVehicleDescriptionFiltered(v->type));
|
||||
@ -1123,6 +1134,13 @@ void Load_VEHS()
|
||||
rv->cached_path->tile[i] = _path_tile[i];
|
||||
}
|
||||
rv->cached_path->layout_ctr = _path_layout_ctr;
|
||||
} else if (vtype == VEH_SHIP && !_path_td.empty() && _path_td.size() <= SHIP_PATH_CACHE_LENGTH) {
|
||||
Ship *s = Ship::From(v);
|
||||
s->cached_path.reset(new ShipPathCache());
|
||||
s->cached_path->count = _path_td.size();
|
||||
for (size_t i = 0; i < _path_td.size(); i++) {
|
||||
s->cached_path->td[i] = _path_td[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user