diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -90,6 +90,33 @@ bool CheckAutoreplaceValidity(EngineID f } /** + * 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 CmdStartStopVe */ 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 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 --- 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 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1281,6 +1281,11 @@ CommandCost CmdMoveRailVehicle(TileIndex 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 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -173,4 +173,6 @@ void ReleaseDisastersTargetingVehicle(Ve typedef SmallVector VehicleSet; void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles); +void CheckCargoCapacity(Vehicle *v); + #endif /* VEHICLE_FUNC_H */