diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 0d6fc4d143..f6158ba6b2 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -268,7 +268,7 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoff * @param[out] ret the vehicle that has been built. * @return the cost of this operation or an error. */ -CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret) +CommandCost CmdBuildAircraft(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret) { const AircraftVehicleInfo *avi = &e->u.air; const Station *st = Station::GetByTile(tile); @@ -279,7 +279,7 @@ CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine * /* Make sure all aircraft end up in the first tile of the hangar. */ tile = st->airport.GetHangarTile(st->airport.GetHangarNum(tile)); - if (flags & DC_EXEC) { + if (flags.Test(DoCommandFlag::Execute)) { Aircraft *v = new Aircraft(); // aircraft Aircraft *u = new Aircraft(); // shadow *ret = v; @@ -1287,7 +1287,7 @@ void HandleMissingAircraftOrders(Aircraft *v) const Station *st = GetTargetAirportIfValid(v); if (st == nullptr) { Backup cur_company(_current_company, v->owner); - CommandCost ret = Command::Do(DC_EXEC, v->index, DepotCommandFlag{}, {}); + CommandCost ret = Command::Do(DoCommandFlag::Execute, v->index, DepotCommandFlag{}, {}); cur_company.Restore(); if (ret.Failed()) CrashAirplane(v); @@ -1653,7 +1653,7 @@ static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass /* Send the helicopter to a hangar if needed for replacement */ if (v->NeedsAutomaticServicing()) { Backup cur_company(_current_company, v->owner); - Command::Do(DC_EXEC, v->index, DepotCommandFlags{DepotCommandFlag::Service, DepotCommandFlag::LocateHangar}, {}); + Command::Do(DoCommandFlag::Execute, v->index, DepotCommandFlags{DepotCommandFlag::Service, DepotCommandFlag::LocateHangar}, {}); cur_company.Restore(); } } @@ -1704,7 +1704,7 @@ static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *) /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */ if (v->NeedsAutomaticServicing()) { Backup cur_company(_current_company, v->owner); - Command::Do(DC_EXEC, v->index, DepotCommandFlag::Service, {}); + Command::Do(DoCommandFlag::Execute, v->index, DepotCommandFlag::Service, {}); cur_company.Restore(); } } diff --git a/src/aircraft_cmd.h b/src/aircraft_cmd.h index df58739a54..7f8c372cff 100644 --- a/src/aircraft_cmd.h +++ b/src/aircraft_cmd.h @@ -14,6 +14,6 @@ #include "engine_type.h" #include "vehicle_type.h" -CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **v); +CommandCost CmdBuildAircraft(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **v); #endif /* AIRCRAFT_CMD_H */ diff --git a/src/autoreplace.cpp b/src/autoreplace.cpp index 2161db9b5b..48c6a575fa 100644 --- a/src/autoreplace.cpp +++ b/src/autoreplace.cpp @@ -94,12 +94,12 @@ EngineID EngineReplacement(EngineRenewList erl, EngineID engine, GroupID group, * @param flags The calling command flags. * @return 0 on success, CMD_ERROR on failure. */ -CommandCost AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, GroupID group, bool replace_when_old, DoCommandFlag flags) +CommandCost AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, GroupID group, bool replace_when_old, DoCommandFlags flags) { /* Check if the old vehicle is already in the list */ EngineRenew *er = GetEngineReplacement(*erl, old_engine, group); if (er != nullptr) { - if (flags & DC_EXEC) { + if (flags.Test(DoCommandFlag::Execute)) { er->to = new_engine; er->replace_when_old = replace_when_old; } @@ -108,7 +108,7 @@ CommandCost AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, Engi if (!EngineRenew::CanAllocateItem()) return CMD_ERROR; - if (flags & DC_EXEC) { + if (flags.Test(DoCommandFlag::Execute)) { er = new EngineRenew(old_engine, new_engine); er->group_id = group; er->replace_when_old = replace_when_old; @@ -129,14 +129,14 @@ CommandCost AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, Engi * @param flags The calling command flags. * @return 0 on success, CMD_ERROR on failure. */ -CommandCost RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, GroupID group, DoCommandFlag flags) +CommandCost RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, GroupID group, DoCommandFlags flags) { EngineRenew *er = (EngineRenew *)(*erl); EngineRenew *prev = nullptr; while (er != nullptr) { if (er->from == engine && er->group_id == group) { - if (flags & DC_EXEC) { + if (flags.Test(DoCommandFlag::Execute)) { if (prev == nullptr) { // First element /* The second becomes the new first element */ *erl = (EngineRenewList)er->next; diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 3e79621ee9..132ff9a826 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -318,7 +318,7 @@ static CommandCost GetNewEngineType(const Vehicle *v, const Company *c, bool alw * @param flags The calling command flags. * @return cost or error */ -static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehicle, bool part_of_chain, DoCommandFlag flags) +static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehicle, bool part_of_chain, DoCommandFlags flags) { *new_vehicle = nullptr; @@ -332,7 +332,7 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic /* Does it need to be refitted */ CargoType refit_cargo = GetNewCargoTypeForReplace(old_veh, e, part_of_chain); if (!IsValidCargoType(refit_cargo)) { - if (!IsLocalCompany() || (flags & DC_EXEC) == 0) return CommandCost(); + if (!IsLocalCompany() || !flags.Test(DoCommandFlag::Execute)) return CommandCost(); VehicleID old_veh_id = (old_veh->type == VEH_TRAIN) ? Train::From(old_veh)->First()->index : old_veh->index; SetDParam(0, old_veh_id); @@ -354,7 +354,7 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic /* Build the new vehicle */ VehicleID new_veh_id; - std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) = Command::Do(DC_EXEC | DC_AUTOREPLACE, old_veh->tile, e, true, INVALID_CARGO, INVALID_CLIENT_ID); + std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) = Command::Do({DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, old_veh->tile, e, true, INVALID_CARGO, INVALID_CLIENT_ID); if (cost.Failed()) return cost; Vehicle *new_veh = Vehicle::Get(new_veh_id); @@ -364,13 +364,13 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic if (refit_cargo != CARGO_NO_REFIT) { uint8_t subtype = GetBestFittingSubType(old_veh, new_veh, refit_cargo); - cost.AddCost(std::get<0>(Command::Do(DC_EXEC, new_veh->index, refit_cargo, subtype, false, false, 0))); + cost.AddCost(std::get<0>(Command::Do(DoCommandFlag::Execute, new_veh->index, refit_cargo, subtype, false, false, 0))); assert(cost.Succeeded()); // This should be ensured by GetNewCargoTypeForReplace() } /* Try to reverse the vehicle, but do not care if it fails as the new type might not be reversible */ if (new_veh->type == VEH_TRAIN && HasBit(Train::From(old_veh)->flags, VRF_REVERSE_DIRECTION)) { - Command::Do(DC_EXEC, new_veh->index, true); + Command::Do(DoCommandFlag::Execute, new_veh->index, true); } return cost; @@ -384,7 +384,7 @@ static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehic */ static inline CommandCost DoCmdStartStopVehicle(const Vehicle *v, bool evaluate_callback) { - return Command::Do(DC_EXEC | DC_AUTOREPLACE, v->index, evaluate_callback); + return Command::Do({DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, v->index, evaluate_callback); } /** @@ -395,9 +395,9 @@ static inline CommandCost DoCmdStartStopVehicle(const Vehicle *v, bool evaluate_ * @param whole_chain move all vehicles following 'v' (true), or only 'v' (false) * @return success or error */ -static inline CommandCost CmdMoveVehicle(const Vehicle *v, const Vehicle *after, DoCommandFlag flags, bool whole_chain) +static inline CommandCost CmdMoveVehicle(const Vehicle *v, const Vehicle *after, DoCommandFlags flags, bool whole_chain) { - return Command::Do(flags | DC_NO_CARGO_CAP_CHECK, v->index, after != nullptr ? after->index : INVALID_VEHICLE, whole_chain); + return Command::Do(flags.Set(DoCommandFlag::NoCargoCapacityCheck), v->index, after != nullptr ? after->index : INVALID_VEHICLE, whole_chain); } /** @@ -406,15 +406,15 @@ static inline CommandCost CmdMoveVehicle(const Vehicle *v, const Vehicle *after, * @param new_head The new head of the completely replaced vehicle chain * @param flags the command flags to use */ -static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, DoCommandFlag flags) +static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, DoCommandFlags flags) { CommandCost cost = CommandCost(); /* Share orders */ - if (cost.Succeeded() && old_head != new_head) cost.AddCost(Command::Do(DC_EXEC, CO_SHARE, new_head->index, old_head->index)); + if (cost.Succeeded() && old_head != new_head) cost.AddCost(Command::Do(DoCommandFlag::Execute, CO_SHARE, new_head->index, old_head->index)); /* Copy group membership */ - if (cost.Succeeded() && old_head != new_head) cost.AddCost(std::get<0>(Command::Do(DC_EXEC, old_head->group_id, new_head->index, false, VehicleListIdentifier{}))); + if (cost.Succeeded() && old_head != new_head) cost.AddCost(std::get<0>(Command::Do(DoCommandFlag::Execute, old_head->group_id, new_head->index, false, VehicleListIdentifier{}))); /* Perform start/stop check whether the new vehicle suits newgrf restrictions etc. */ if (cost.Succeeded()) { @@ -427,7 +427,7 @@ static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, } /* Last do those things which do never fail (resp. we do not care about), but which are not undo-able */ - if (cost.Succeeded() && old_head != new_head && (flags & DC_EXEC) != 0) { + if (cost.Succeeded() && old_head != new_head && flags.Test(DoCommandFlag::Execute)) { /* Copy other things which cannot be copied by a command and which shall not stay resetted from the build vehicle command */ new_head->CopyVehicleConfigAndStatistics(old_head); GroupStatistics::AddProfitLastYear(new_head); @@ -448,7 +448,7 @@ static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, * @param nothing_to_do is set to 'false' when something was done (only valid when not failed) * @return cost or error */ -static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, bool *nothing_to_do) +static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlags flags, bool *nothing_to_do) { Train *old_v = Train::From(*single_unit); assert(!old_v->IsArticulatedPart() && !old_v->IsRearDualheaded()); @@ -463,9 +463,9 @@ static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, b if (cost.Succeeded() && new_v != nullptr) { *nothing_to_do = false; - if ((flags & DC_EXEC) != 0) { + if (flags.Test(DoCommandFlag::Execute)) { /* Move the new vehicle behind the old */ - CmdMoveVehicle(new_v, old_v, DC_EXEC, false); + CmdMoveVehicle(new_v, old_v, DoCommandFlag::Execute, false); /* Take over cargo * Note: We do only transfer cargo from the old to the new vehicle. @@ -483,9 +483,9 @@ static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlag flags, b /* Sell the old vehicle */ cost.AddCost(Command::Do(flags, old_v->index, false, false, INVALID_CLIENT_ID)); - /* If we are not in DC_EXEC undo everything */ - if ((flags & DC_EXEC) == 0) { - Command::Do(DC_EXEC, new_v->index, false, false, INVALID_CLIENT_ID); + /* If we are not in DoCommandFlag::Execute undo everything */ + if (!flags.Test(DoCommandFlag::Execute)) { + Command::Do(DoCommandFlag::Execute, new_v->index, false, false, INVALID_CLIENT_ID); } } @@ -515,7 +515,7 @@ struct ReplaceChainItem { * @param nothing_to_do is set to 'false' when something was done (only valid when not failed) * @return cost or error */ -static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon_removal, bool *nothing_to_do) +static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlags flags, bool wagon_removal, bool *nothing_to_do) { Vehicle *old_head = *chain; assert(old_head->IsPrimaryVehicle()); @@ -546,7 +546,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon if (cost.Succeeded()) { /* Separate the head, so we can start constructing the new chain */ Train *second = Train::From(old_head)->GetNextUnit(); - if (second != nullptr) cost.AddCost(CmdMoveVehicle(second, nullptr, DC_EXEC | DC_AUTOREPLACE, true)); + if (second != nullptr) cost.AddCost(CmdMoveVehicle(second, nullptr, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, true)); assert(Train::From(new_head)->GetNextUnit() == nullptr); @@ -562,14 +562,14 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon if (RailVehInfo(append->engine_type)->railveh_type == RAILVEH_WAGON) continue; if (it->new_veh != nullptr) { - /* Move the old engine to a separate row with DC_AUTOREPLACE. Else + /* Move the old engine to a separate row with DoCommandFlag::AutoReplace. Else * moving the wagon in front may fail later due to unitnumber limit. - * (We have to attach wagons without DC_AUTOREPLACE.) */ - CmdMoveVehicle(it->old_veh, nullptr, DC_EXEC | DC_AUTOREPLACE, false); + * (We have to attach wagons without DoCommandFlag::AutoReplace.) */ + CmdMoveVehicle(it->old_veh, nullptr, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, false); } if (last_engine == nullptr) last_engine = append; - cost.AddCost(CmdMoveVehicle(append, new_head, DC_EXEC, false)); + cost.AddCost(CmdMoveVehicle(append, new_head, DoCommandFlag::Execute, false)); if (cost.Failed()) break; } if (last_engine == nullptr) last_engine = new_head; @@ -588,13 +588,13 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon if (RailVehInfo(append->engine_type)->railveh_type == RAILVEH_WAGON) { /* Insert wagon after 'last_engine' */ - CommandCost res = CmdMoveVehicle(append, last_engine, DC_EXEC, false); + CommandCost res = CmdMoveVehicle(append, last_engine, DoCommandFlag::Execute, false); /* When we allow removal of wagons, either the move failing due * to the train becoming too long, or the train becoming longer * would move the vehicle to the empty vehicle chain. */ if (wagon_removal && (res.Failed() ? res.GetErrorMessage() == STR_ERROR_TRAIN_TOO_LONG : Train::From(new_head)->gcache.cached_total_length > old_total_length)) { - CmdMoveVehicle(append, nullptr, DC_EXEC | DC_AUTOREPLACE, false); + CmdMoveVehicle(append, nullptr, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, false); break; } @@ -619,7 +619,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon assert(RailVehInfo(wagon->engine_type)->railveh_type == RAILVEH_WAGON); /* Sell wagon */ - [[maybe_unused]] CommandCost ret = Command::Do(DC_EXEC, wagon->index, false, false, INVALID_CLIENT_ID); + [[maybe_unused]] CommandCost ret = Command::Do(DoCommandFlag::Execute, wagon->index, false, false, INVALID_CLIENT_ID); assert(ret.Succeeded()); it->new_veh = nullptr; @@ -634,7 +634,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon if (cost.Succeeded()) { /* Success ! */ - if ((flags & DC_EXEC) != 0 && new_head != old_head) { + if (flags.Test(DoCommandFlag::Execute) && new_head != old_head) { *chain = new_head; AI::NewEvent(old_head->owner, new ScriptEventVehicleAutoReplaced(old_head->index, new_head->index)); } @@ -646,43 +646,43 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon * Note: We cannot test 'new_vehs[i] != nullptr' as wagon removal might cause to remove both */ if (w->First() == new_head) continue; - if ((flags & DC_EXEC) != 0) TransferCargo(w, new_head, true); + if (flags.Test(DoCommandFlag::Execute)) TransferCargo(w, new_head, true); /* Sell the vehicle. - * Note: This might temporarily construct new trains, so use DC_AUTOREPLACE to prevent + * Note: This might temporarily construct new trains, so use DoCommandFlag::AutoReplace to prevent * it from failing due to engine limits. */ - cost.AddCost(Command::Do(flags | DC_AUTOREPLACE, w->index, false, false, INVALID_CLIENT_ID)); - if ((flags & DC_EXEC) != 0) { + cost.AddCost(Command::Do(DoCommandFlags{flags}.Set(DoCommandFlag::AutoReplace), w->index, false, false, INVALID_CLIENT_ID)); + if (flags.Test(DoCommandFlag::Execute)) { it->old_veh = nullptr; if (it == std::begin(replacements)) old_head = nullptr; } } - if ((flags & DC_EXEC) != 0) CheckCargoCapacity(new_head); + if (flags.Test(DoCommandFlag::Execute)) CheckCargoCapacity(new_head); } - /* If we are not in DC_EXEC undo everything, i.e. rearrange old vehicles. + /* If we are not in DoCommandFlag::Execute undo everything, i.e. rearrange old vehicles. * We do this from back to front, so that the head of the temporary vehicle chain does not change all the time. * Note: The vehicle attach callback is disabled here :) */ - if ((flags & DC_EXEC) == 0) { + if (!flags.Test(DoCommandFlag::Execute)) { /* Separate the head, so we can reattach the old vehicles */ Train *second = Train::From(old_head)->GetNextUnit(); - if (second != nullptr) CmdMoveVehicle(second, nullptr, DC_EXEC | DC_AUTOREPLACE, true); + if (second != nullptr) CmdMoveVehicle(second, nullptr, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, true); assert(Train::From(old_head)->GetNextUnit() == nullptr); for (auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) { - [[maybe_unused]] CommandCost ret = CmdMoveVehicle(it->old_veh, old_head, DC_EXEC | DC_AUTOREPLACE, false); + [[maybe_unused]] CommandCost ret = CmdMoveVehicle(it->old_veh, old_head, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace}, false); assert(ret.Succeeded()); } } } /* Finally undo buying of new vehicles */ - if ((flags & DC_EXEC) == 0) { + if (!flags.Test(DoCommandFlag::Execute)) { for (auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) { if (it->new_veh != nullptr) { - Command::Do(DC_EXEC, it->new_veh->index, false, false, INVALID_CLIENT_ID); + Command::Do(DoCommandFlag::Execute, it->new_veh->index, false, false, INVALID_CLIENT_ID); it->new_veh = nullptr; } } @@ -701,7 +701,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon if (cost.Succeeded()) { /* The new vehicle is constructed, now take over cargo */ - if ((flags & DC_EXEC) != 0) { + if (flags.Test(DoCommandFlag::Execute)) { TransferCargo(old_head, new_head, true); *chain = new_head; @@ -712,9 +712,9 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon cost.AddCost(Command::Do(flags, old_head->index, false, false, INVALID_CLIENT_ID)); } - /* If we are not in DC_EXEC undo everything */ - if ((flags & DC_EXEC) == 0) { - Command::Do(DC_EXEC, new_head->index, false, false, INVALID_CLIENT_ID); + /* If we are not in DoCommandFlag::Execute undo everything */ + if (!flags.Test(DoCommandFlag::Execute)) { + Command::Do(DoCommandFlag::Execute, new_head->index, false, false, INVALID_CLIENT_ID); } } } @@ -729,7 +729,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon * @param veh_id Index of vehicle * @return the cost of this operation or an error */ -CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id) +CommandCost CmdAutoreplaceVehicle(DoCommandFlags flags, VehicleID veh_id) { Vehicle *v = Vehicle::GetIfValid(veh_id); if (v == nullptr) return CMD_ERROR; @@ -781,17 +781,17 @@ CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id) /* 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 */ + * to prevent desyncs and to replay newgrf callbacks during DoCommandFlag::Execute */ SavedRandomSeeds saved_seeds; SaveRandomSeeds(&saved_seeds); if (free_wagon) { - cost.AddCost(ReplaceFreeUnit(&v, flags & ~DC_EXEC, ¬hing_to_do)); + cost.AddCost(ReplaceFreeUnit(&v, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), ¬hing_to_do)); } else { - cost.AddCost(ReplaceChain(&v, flags & ~DC_EXEC, wagon_removal, ¬hing_to_do)); + cost.AddCost(ReplaceChain(&v, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), wagon_removal, ¬hing_to_do)); } RestoreRandomSeeds(saved_seeds); - if (cost.Succeeded() && (flags & DC_EXEC) != 0) { + if (cost.Succeeded() && flags.Test(DoCommandFlag::Execute)) { if (free_wagon) { ret = ReplaceFreeUnit(&v, flags, ¬hing_to_do); } else { @@ -817,7 +817,7 @@ CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id) * @param when_old replace when engine gets old? * @return the cost of this operation or an error */ -CommandCost CmdSetAutoReplace(DoCommandFlag flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old) +CommandCost CmdSetAutoReplace(DoCommandFlags flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old) { Company *c = Company::GetIfValid(_current_company); if (c == nullptr) return CMD_ERROR; @@ -837,14 +837,14 @@ CommandCost CmdSetAutoReplace(DoCommandFlag flags, GroupID id_g, EngineID old_en cost = RemoveEngineReplacementForCompany(c, old_engine_type, id_g, flags); } - if (flags & DC_EXEC) { + if (flags.Test(DoCommandFlag::Execute)) { GroupStatistics::UpdateAutoreplace(_current_company); if (IsLocalCompany()) SetWindowDirty(WC_REPLACE_VEHICLE, Engine::Get(old_engine_type)->type); const VehicleType vt = Engine::Get(old_engine_type)->type; SetWindowDirty(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).ToWindowNumber()); } - if ((flags & DC_EXEC) && IsLocalCompany()) InvalidateAutoreplaceWindow(old_engine_type, id_g); + if (flags.Test(DoCommandFlag::Execute) && IsLocalCompany()) InvalidateAutoreplaceWindow(old_engine_type, id_g); return cost; } diff --git a/src/autoreplace_cmd.h b/src/autoreplace_cmd.h index c42e740c93..71450a95eb 100644 --- a/src/autoreplace_cmd.h +++ b/src/autoreplace_cmd.h @@ -15,8 +15,8 @@ #include "engine_type.h" #include "group_type.h" -CommandCost CmdAutoreplaceVehicle(DoCommandFlag flags, VehicleID veh_id); -CommandCost CmdSetAutoReplace(DoCommandFlag flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old); +CommandCost CmdAutoreplaceVehicle(DoCommandFlags flags, VehicleID veh_id); +CommandCost CmdSetAutoReplace(DoCommandFlags flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old); DEF_CMD_TRAIT(CMD_AUTOREPLACE_VEHICLE, CmdAutoreplaceVehicle, 0, CMDT_VEHICLE_MANAGEMENT) DEF_CMD_TRAIT(CMD_SET_AUTOREPLACE, CmdSetAutoReplace, 0, CMDT_VEHICLE_MANAGEMENT) diff --git a/src/autoreplace_func.h b/src/autoreplace_func.h index 0943985e7d..574761fc32 100644 --- a/src/autoreplace_func.h +++ b/src/autoreplace_func.h @@ -15,8 +15,8 @@ void RemoveAllEngineReplacement(EngineRenewList *erl); EngineID EngineReplacement(EngineRenewList erl, EngineID engine, GroupID group, bool *replace_when_old = nullptr); -CommandCost AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, GroupID group, bool replace_when_old, DoCommandFlag flags); -CommandCost RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, GroupID group, DoCommandFlag flags); +CommandCost AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, EngineID new_engine, GroupID group, bool replace_when_old, DoCommandFlags flags); +CommandCost RemoveEngineReplacement(EngineRenewList *erl, EngineID engine, GroupID group, DoCommandFlags flags); /** * Remove all engine replacement settings for the given company. @@ -77,7 +77,7 @@ inline bool EngineHasReplacementWhenOldForCompany(const Company *c, EngineID eng * @param flags The calling command flags. * @return 0 on success, CMD_ERROR on failure. */ -inline CommandCost AddEngineReplacementForCompany(Company *c, EngineID old_engine, EngineID new_engine, GroupID group, bool replace_when_old, DoCommandFlag flags) +inline CommandCost AddEngineReplacementForCompany(Company *c, EngineID old_engine, EngineID new_engine, GroupID group, bool replace_when_old, DoCommandFlags flags) { return AddEngineReplacement(&c->engine_renew_list, old_engine, new_engine, group, replace_when_old, flags); } @@ -90,7 +90,7 @@ inline CommandCost AddEngineReplacementForCompany(Company *c, EngineID old_engin * @param flags The calling command flags. * @return 0 on success, CMD_ERROR on failure. */ -inline CommandCost RemoveEngineReplacementForCompany(Company *c, EngineID engine, GroupID group, DoCommandFlag flags) +inline CommandCost RemoveEngineReplacementForCompany(Company *c, EngineID engine, GroupID group, DoCommandFlags flags) { return RemoveEngineReplacement(&c->engine_renew_list, engine, group, flags); } diff --git a/src/bridge.h b/src/bridge.h index 0fa4822336..0b23b24ea4 100644 --- a/src/bridge.h +++ b/src/bridge.h @@ -72,7 +72,7 @@ inline const BridgeSpec *GetBridgeSpec(BridgeType i) void DrawBridgeMiddle(const TileInfo *ti); -CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags = DC_NONE); +CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlags flags = {}); int CalcBridgeLenCostFactor(int x); void ResetBridges(); diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 5551dfd86d..1a2d115a18 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -377,7 +377,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo /* only query bridge building possibility once, result is the same for all bridges! * returns CMD_ERROR on failure, and price on success */ StringID errmsg = INVALID_STRING_ID; - CommandCost ret = Command::Do(CommandFlagsToDCFlags(GetCommandFlags()) | DC_QUERY_COST, end, start, transport_type, 0, road_rail_type); + CommandCost ret = Command::Do(CommandFlagsToDCFlags(GetCommandFlags()) | DoCommandFlag::QueryCost, end, start, transport_type, 0, road_rail_type); GUIBridgeList bl; if (ret.Failed()) { @@ -422,7 +422,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo item.index = brd_type; item.spec = GetBridgeSpec(brd_type); /* Add to terraforming & bulldozing costs the cost of the - * bridge itself (not computed with DC_QUERY_COST) */ + * bridge itself (not computed with DoCommandFlag::QueryCost) */ item.cost = ret.GetCost() + (((int64_t)tot_bridgedata_len * _price[PR_BUILD_BRIDGE] * item.spec->price) >> 8) + infra_cost; any_available = true; } diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 8411a549e3..eda475e39f 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1322,7 +1322,7 @@ struct BuildVehicleWindow : Window { if (!this->listview_mode) { /* Query for cost and refitted capacity */ - auto [ret, veh_id, refit_capacity, refit_mail, cargo_capacities] = Command::Do(DC_QUERY_COST, TileIndex(this->window_number), this->sel_engine, true, cargo, INVALID_CLIENT_ID); + auto [ret, veh_id, refit_capacity, refit_mail, cargo_capacities] = Command::Do(DoCommandFlag::QueryCost, TileIndex(this->window_number), this->sel_engine, true, cargo, INVALID_CLIENT_ID); if (ret.Succeeded()) { this->te.cost = ret.GetCost() - e->GetCost(); this->te.capacity = refit_capacity; diff --git a/src/clear_cmd.cpp b/src/clear_cmd.cpp index be488f8a3e..d19b769230 100644 --- a/src/clear_cmd.cpp +++ b/src/clear_cmd.cpp @@ -23,7 +23,7 @@ #include "safeguards.h" -static CommandCost ClearTile_Clear(TileIndex tile, DoCommandFlag flags) +static CommandCost ClearTile_Clear(TileIndex tile, DoCommandFlags flags) { static const Price clear_price_table[] = { PR_CLEAR_GRASS, @@ -39,7 +39,7 @@ static CommandCost ClearTile_Clear(TileIndex tile, DoCommandFlag flags) price.AddCost(_price[clear_price_table[GetClearGround(tile)]]); } - if (flags & DC_EXEC) DoClearSquare(tile); + if (flags.Test(DoCommandFlag::Execute)) DoClearSquare(tile); return price; } @@ -352,7 +352,7 @@ static void ChangeTileOwner_Clear(TileIndex, Owner, Owner) return; } -static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlag flags, int, Slope) +static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlags flags, int, Slope) { return Command::Do(flags, tile); } diff --git a/src/command.cpp b/src/command.cpp index b5865ad4ae..a9ae18e0ea 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -179,17 +179,17 @@ void CommandHelperBase::InternalDoBefore(bool top_level, bool test) * @param top_level Top level of command execution, i.e. command from a command. * @param test Test run of command? */ -void CommandHelperBase::InternalDoAfter(CommandCost &res, DoCommandFlag flags, bool top_level, bool test) +void CommandHelperBase::InternalDoAfter(CommandCost &res, DoCommandFlags flags, bool top_level, bool test) { if (test) { SetTownRatingTestMode(false); - if (res.Succeeded() && top_level && !(flags & DC_QUERY_COST) && !(flags & DC_BANKRUPT)) { + if (res.Succeeded() && top_level && !flags.Test(DoCommandFlag::QueryCost) && !flags.Test(DoCommandFlag::Bankrupt)) { CheckCompanyHasMoney(res); // CheckCompanyHasMoney() modifies 'res' to an error if it fails. } } else { /* If top-level, subtract the money. */ - if (res.Succeeded() && top_level && !(flags & DC_BANKRUPT)) { + if (res.Succeeded() && top_level && !flags.Test(DoCommandFlag::Bankrupt)) { SubtractMoneyFromCompany(res); } } diff --git a/src/command_func.h b/src/command_func.h index 2879ecf520..1181459987 100644 --- a/src/command_func.h +++ b/src/command_func.h @@ -45,12 +45,12 @@ constexpr CommandFlags GetCommandFlags() * @param cmd_flags Flags from GetCommandFlags * @return flags for DoCommand */ -static constexpr inline DoCommandFlag CommandFlagsToDCFlags(CommandFlags cmd_flags) +static constexpr inline DoCommandFlags CommandFlagsToDCFlags(CommandFlags cmd_flags) { - DoCommandFlag flags = DC_NONE; - if (cmd_flags & CMD_NO_WATER) flags |= DC_NO_WATER; - if (cmd_flags & CMD_AUTO) flags |= DC_AUTO; - if (cmd_flags & CMD_ALL_TILES) flags |= DC_ALL_TILES; + DoCommandFlags flags = {}; + if (cmd_flags & CMD_NO_WATER) flags.Set(DoCommandFlag::NoWater); + if (cmd_flags & CMD_AUTO) flags.Set(DoCommandFlag::Auto); + if (cmd_flags & CMD_ALL_TILES) flags.Set(DoCommandFlag::AllTiles); return flags; } @@ -85,7 +85,7 @@ template struct CommandHelper; class CommandHelperBase { protected: static void InternalDoBefore(bool top_level, bool test); - static void InternalDoAfter(CommandCost &res, DoCommandFlag flags, bool top_level, bool test); + static void InternalDoAfter(CommandCost &res, DoCommandFlags flags, bool top_level, bool test); static std::tuple InternalPostBefore(Commands cmd, CommandFlags flags, TileIndex tile, StringID err_message, bool network_command); static void InternalPostResult(const CommandCost &res, TileIndex tile, bool estimate_only, bool only_sending, StringID err_message, bool my_cmd); static bool InternalExecutePrepTest(CommandFlags cmd_flags, TileIndex tile, Backup &cur_company); @@ -102,7 +102,7 @@ protected: * @tparam Targs The command parameter types. */ template -struct CommandHelper : protected CommandHelperBase { +struct CommandHelper : protected CommandHelperBase { private: /** Extract the \c CommandCost from a command proc result. */ static inline CommandCost &ExtractCommandCost(Tret &ret) @@ -136,23 +136,23 @@ public: * @see CommandProc * @return the cost */ - static Tret Do(DoCommandFlag flags, Targs... args) + static Tret Do(DoCommandFlags flags, Targs... args) { if constexpr (std::is_same_v>>) { /* Do not even think about executing out-of-bounds tile-commands. */ TileIndex tile = std::get<0>(std::make_tuple(args...)); - if (tile != 0 && (tile >= Map::Size() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return MakeResult(CMD_ERROR); + if (tile != 0 && (tile >= Map::Size() || (!IsValidTile(tile) && !flags.Test(DoCommandFlag::AllTiles)))) return MakeResult(CMD_ERROR); } RecursiveCommandCounter counter{}; /* Only execute the test call if it's toplevel, or we're not execing. */ - if (counter.IsTopLevel() || !(flags & DC_EXEC)) { + if (counter.IsTopLevel() || !flags.Test(DoCommandFlag::Execute)) { InternalDoBefore(counter.IsTopLevel(), true); - Tret res = CommandTraits::proc(flags & ~DC_EXEC, args...); + Tret res = CommandTraits::proc(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), args...); InternalDoAfter(ExtractCommandCost(res), flags, counter.IsTopLevel(), true); // Can modify res. - if (ExtractCommandCost(res).Failed() || !(flags & DC_EXEC)) return res; + if (ExtractCommandCost(res).Failed() || !flags.Test(DoCommandFlag::Execute)) return res; } /* Execute the command here. All cost-relevant functions set the expenses type @@ -369,7 +369,7 @@ protected: } /* Test the command. */ - DoCommandFlag flags = CommandFlagsToDCFlags(cmd_flags); + DoCommandFlags flags = CommandFlagsToDCFlags(cmd_flags); Tret res = std::apply(CommandTraits::proc, std::tuple_cat(std::make_tuple(flags), args)); auto [exit_test, desync_log, send_net] = InternalExecuteValidateTestAndPrepExec(ExtractCommandCost(res), cmd_flags, estimate_only, network_command, cur_company); @@ -395,7 +395,7 @@ protected: if (desync_log) LogCommandExecution(Tcmd, err_message, EndianBufferWriter::FromValue(args), false); /* Actually try and execute the command. */ - Tret res2 = std::apply(CommandTraits::proc, std::tuple_cat(std::make_tuple(flags | DC_EXEC), args)); + Tret res2 = std::apply(CommandTraits::proc, std::tuple_cat(std::make_tuple(flags | DoCommandFlag::Execute), args)); /* Convention: If the second result element is of type Money, * this is the additional cash required for the command. */ @@ -421,7 +421,7 @@ protected: * @tparam Targs The command parameter types. */ template -struct CommandHelper : CommandHelper +struct CommandHelper : CommandHelper { /* Do not allow Post without explicit location. */ static inline bool Post(StringID err_message, Targs... args) = delete; @@ -464,7 +464,7 @@ struct CommandHelper : CommandHel template static inline bool Post(StringID err_message, Tcallback *callback, TileIndex location, Targs... args) { - return CommandHelper::InternalPost(err_message, callback, true, false, location, std::forward_as_tuple(args...)); + return CommandHelper::InternalPost(err_message, callback, true, false, location, std::forward_as_tuple(args...)); } }; diff --git a/src/command_type.h b/src/command_type.h index 1fac124552..37a82b538f 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -371,22 +371,20 @@ enum Commands : uint8_t { * * This enums defines some flags which can be used for the commands. */ -enum DoCommandFlag : uint16_t { - DC_NONE = 0x000, ///< no flag is set - DC_EXEC = 0x001, ///< execute the given command - DC_AUTO = 0x002, ///< don't allow building on structures - DC_QUERY_COST = 0x004, ///< query cost only, don't build. - DC_NO_WATER = 0x008, ///< don't allow building on water - // 0x010 is unused - 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_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 +enum DoCommandFlag : uint8_t { + Execute, ///< execute the given command + Auto, ///< don't allow building on structures + QueryCost, ///< query cost only, don't build. + NoWater, ///< don't allow building on water + NoTestTownRating, ///< town rating does not disallow you from building + Bankrupt, ///< company bankrupts, skip money check, skip vehicle on tile check in some cases + AutoReplace, ///< autoreplace/autorenew is in progress, this shall disable vehicle limits when building, and ignore certain restrictions when undoing things (like vehicle attach callback) + NoCargoCapacityCheck, ///< 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 + AllTiles, ///< allow this command also on MP_VOID tiles + NoModifyTownRating, ///< do not change town rating + ForceClearTile, ///< do not only remove the object on the tile, but also clear any water left on it }; -DECLARE_ENUM_AS_BIT_SET(DoCommandFlag) +using DoCommandFlags = EnumBitSet; /** * Command flags for the command table _command_proc_table. @@ -397,10 +395,10 @@ enum CommandFlags : uint16_t { CMD_SERVER = 0x001, ///< the command can only be initiated by the server CMD_SPECTATOR = 0x002, ///< the command may be initiated by a spectator CMD_OFFLINE = 0x004, ///< the command cannot be executed in a multiplayer game; single-player only - CMD_AUTO = 0x008, ///< set the DC_AUTO flag on this command + CMD_AUTO = 0x008, ///< set the DoCommandFlag::Auto flag on this command CMD_ALL_TILES = 0x010, ///< allow this command also on MP_VOID tiles CMD_NO_TEST = 0x020, ///< the command's output may differ between test and execute due to town rating changes etc. - CMD_NO_WATER = 0x040, ///< set the DC_NO_WATER flag on this command + CMD_NO_WATER = 0x040, ///< set the DoCommandFlag::NoWater flag on this command CMD_CLIENT_ID = 0x080, ///< set p2 with the ClientID of the sending client. CMD_DEITY = 0x100, ///< the command may be executed by COMPANY_DEITY CMD_STR_CTRL = 0x200, ///< the command's string may contain control strings @@ -435,14 +433,14 @@ enum CommandPauseLevel : uint8_t { template struct CommandFunctionTraitHelper; template -struct CommandFunctionTraitHelper { +struct CommandFunctionTraitHelper { using Args = std::tuple...>; using RetTypes = void; using CbArgs = Args; using CbProcType = void(*)(Commands, const CommandCost &); }; template