diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 38b88b85d1..084ca8c838 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -790,6 +790,8 @@ CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id) assert(free_wagon || v->IsStoppedInDepot()); + if (IsExtendedDepotTile(v->tile)) UpdateExtendedDepotReservation(v, false); + /* We have to construct the new vehicle chain to test whether it is valid. * Vehicle construction needs random bits, so we have to save the random seeds * to prevent desyncs and to replay newgrf callbacks during DC_EXEC */ @@ -813,6 +815,8 @@ CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id) assert(ret.GetCost() == cost.GetCost()); } + if (IsExtendedDepotTile(v->tile)) UpdateExtendedDepotReservation(v, true); + /* Restart the vehicle */ if (!was_stopped) cost.AddCost(DoCmdStartStopVehicle(v, false)); diff --git a/src/depot.cpp b/src/depot.cpp index 3a900988eb..01b8d4e3b3 100644 --- a/src/depot.cpp +++ b/src/depot.cpp @@ -245,3 +245,35 @@ void Depot::RescanDepotTiles() InvalidateWindowData(WC_BUILD_VEHICLE, this->index, 0, true); } } + +/** + * Fix tile reservations and vehicle on extended depots. + * @param v Vehicle to be checked. + * @param reserve Whether to reserve or free the position v is occupying. + */ +void UpdateExtendedDepotReservation(Vehicle *v, bool reserve) +{ + assert(v != nullptr); + assert(IsExtendedDepotTile(v->tile)); + DepotReservation res_type = DEPOT_RESERVATION_EMPTY; + + res_type = (v->vehstatus & VS_STOPPED) ? + DEPOT_RESERVATION_FULL_STOPPED_VEH : DEPOT_RESERVATION_IN_USE; + + switch (v->type) { + case VEH_ROAD: + break; + + case VEH_SHIP: + SetDepotReservation(v->tile, res_type); + break; + + case VEH_TRAIN: + break; + + case VEH_AIRCRAFT: + break; + + default: NOT_REACHED(); + } +} diff --git a/src/depot_map.h b/src/depot_map.h index 18d172fbeb..da3e1804c9 100644 --- a/src/depot_map.h +++ b/src/depot_map.h @@ -175,4 +175,6 @@ static inline void SetDepotReservation(Tile t, DepotReservation reservation, boo SB(t.m4(), 6, 2, reservation); } +void UpdateExtendedDepotReservation(Vehicle *v, bool state); + #endif /* DEPOT_MAP_H */ diff --git a/src/ship.h b/src/ship.h index 927dc171ef..42d9392e88 100644 --- a/src/ship.h +++ b/src/ship.h @@ -31,7 +31,7 @@ struct Ship final : public SpecializedVehicle { /** We don't want GCC to zero our struct! It already is zeroed and has an index! */ Ship() : SpecializedVehicleBase() {} /** We want to 'destruct' the right class. */ - virtual ~Ship() { this->PreDestructor(); } + virtual ~Ship(); void MarkDirty() override; void UpdateDeltaXY() override; diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index cb7db048a9..0f06765b4b 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -303,6 +303,15 @@ Trackdir Ship::GetVehicleTrackdir() const return TrackDirectionToTrackdir(FindFirstTrack(this->state), this->direction); } +Ship::~Ship() +{ + if (CleaningPool()) return; + + if (this->IsInDepot()) SetDepotReservation(this->tile, DEPOT_RESERVATION_EMPTY); + + this->PreDestructor(); +} + void Ship::MarkDirty() { this->colourmap = PAL_NONE; @@ -385,6 +394,7 @@ void HandleShipEnterDepot(Ship *v) assert(IsShipDepotTile(v->tile)); if (IsExtendedDepot(v->tile)) { + SetDepotReservation(v->tile, DEPOT_RESERVATION_IN_USE); v->state |= TRACK_BIT_DEPOT; v->cur_speed = 0; v->UpdateCache(); @@ -416,7 +426,9 @@ static bool CheckShipLeaveDepot(Ship *v) /* Don't leave depot if no destination set */ if (v->dest_tile == 0) return true; - if (!IsExtendedDepot(v->tile)) { + if (IsExtendedDepot(v->tile)) { + SetDepotReservation(v->tile, DEPOT_RESERVATION_EMPTY); + } else { /* Don't leave depot if another vehicle is already entering/leaving */ /* This helps avoid CPU load if many ships are set to start at the same time */ if (HasVehicleOnPos(v->tile, nullptr, &EnsureNoMovingShipProc)) return true; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index f38c5650d7..a787f89b25 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1198,7 +1198,11 @@ void CallVehicleTicks() /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick() * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that * they are already leaving the depot again before being replaced. */ - if (it.second) v->vehstatus &= ~VS_STOPPED; + if (it.second) { + v->vehstatus &= ~VS_STOPPED; + } else if (IsExtendedDepotTile(v->tile)){ + UpdateExtendedDepotReservation(v, true); + } /* Store the position of the effect as the vehicle pointer will become invalid later */ int x = v->x_pos;