summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/autoreplace_cmd.cpp31
-rw-r--r--src/command_type.h7
-rw-r--r--src/train_cmd.cpp5
-rw-r--r--src/vehicle_func.h2
4 files changed, 41 insertions, 4 deletions
diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp
index ea4124e1f..264354085 100644
--- a/src/autoreplace_cmd.cpp
+++ b/src/autoreplace_cmd.cpp
@@ -90,6 +90,33 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
}
/**
+ * Check the capacity of all vehicles in a chain and spread cargo if needed.
+ * @param v The vehicle to check.
+ */
+void CheckCargoCapacity(Vehicle *v)
+{
+ assert(v == NULL || v->First() == v);
+
+ for (Vehicle *src = v; src != NULL; src = src->Next()) {
+ /* Do we need to more cargo away? */
+ if (src->cargo.Count() <= src->cargo_cap) continue;
+
+ /* We need to move a particular amount. Try that on the other vehicles. */
+ uint to_spread = src->cargo.Count() - src->cargo_cap;
+ for (Vehicle *dest = v; dest != NULL && to_spread != 0; dest = dest->Next()) {
+ if (dest->cargo.Count() >= dest->cargo_cap || dest->cargo_type != src->cargo_type) continue;
+
+ uint amount = min(to_spread, dest->cargo_cap - dest->cargo.Count());
+ src->cargo.MoveTo(&dest->cargo, amount, VehicleCargoList::MTA_UNLOAD, NULL);
+ to_spread -= amount;
+ }
+
+ /* Any left-overs will be thrown away, but not their feeder share. */
+ src->cargo.Truncate(src->cargo_cap);
+ }
+}
+
+/**
* Transfer cargo from a single (articulated )old vehicle to the new vehicle chain
* @param old_veh Old vehicle that will be sold
* @param new_head Head of the completely constructed new vehicle chain
@@ -297,7 +324,7 @@ static inline CommandCost CmdStartStopVehicle(const Vehicle *v, bool evaluate_ca
*/
static inline CommandCost CmdMoveVehicle(const Vehicle *v, const Vehicle *after, DoCommandFlag flags, bool whole_chain)
{
- return DoCommand(0, v->index | (whole_chain ? 1 : 0) << 20, after != NULL ? after->index : INVALID_VEHICLE, flags, CMD_MOVE_RAIL_VEHICLE);
+ return DoCommand(0, v->index | (whole_chain ? 1 : 0) << 20, after != NULL ? after->index : INVALID_VEHICLE, flags | DC_NO_CARGO_CAP_CHECK, CMD_MOVE_RAIL_VEHICLE);
}
/**
@@ -551,6 +578,8 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
if (i == 0) old_head = NULL;
}
}
+
+ if ((flags & DC_EXEC) != 0) CheckCargoCapacity(new_head);
}
/* If we are not in DC_EXEC undo everything, i.e. rearrange old vehicles.
diff --git a/src/command_type.h b/src/command_type.h
index 152f66618..406f58364 100644
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -318,9 +318,10 @@ enum DoCommandFlag {
DC_NO_TEST_TOWN_RATING = 0x020, ///< town rating does not disallow you from building
DC_BANKRUPT = 0x040, ///< company bankrupts, skip money check, skip vehicle on tile check in some cases
DC_AUTOREPLACE = 0x080, ///< autoreplace/autorenew is in progress, this shall disable vehicle limits when building, and ignore certain restrictions when undoing things (like vehicle attach callback)
- DC_ALL_TILES = 0x100, ///< allow this command also on MP_VOID tiles
- DC_NO_MODIFY_TOWN_RATING = 0x200, ///< do not change town rating
- DC_FORCE_CLEAR_TILE = 0x400, ///< do not only remove the object on the tile, but also clear any water left on it
+ DC_NO_CARGO_CAP_CHECK = 0x100, ///< when autoreplace/autorenew is in progress, this shall prevent truncating the amount of cargo in the vehicle to prevent testing the command to remove cargo
+ DC_ALL_TILES = 0x200, ///< allow this command also on MP_VOID tiles
+ DC_NO_MODIFY_TOWN_RATING = 0x400, ///< do not change town rating
+ DC_FORCE_CLEAR_TILE = 0x800, ///< do not only remove the object on the tile, but also clear any water left on it
};
DECLARE_ENUM_AS_BIT_SET(DoCommandFlag)
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 5bdef09a7..c3eb8c1fa 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -1281,6 +1281,11 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
NormaliseTrainHead(src_head);
NormaliseTrainHead(dst_head);
+ if ((flags & DC_NO_CARGO_CAP_CHECK) == 0) {
+ CheckCargoCapacity(src_head);
+ CheckCargoCapacity(dst_head);
+ }
+
/* We are undoubtedly changing something in the depot and train list. */
InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile);
InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
diff --git a/src/vehicle_func.h b/src/vehicle_func.h
index a41f3c466..283d420a4 100644
--- a/src/vehicle_func.h
+++ b/src/vehicle_func.h
@@ -173,4 +173,6 @@ void ReleaseDisastersTargetingVehicle(VehicleID vehicle);
typedef SmallVector<VehicleID, 2> VehicleSet;
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles);
+void CheckCargoCapacity(Vehicle *v);
+
#endif /* VEHICLE_FUNC_H */