OpenTTD Source  20241108-master-g80f628063a
order_backup.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "command_func.h"
12 #include "core/pool_func.hpp"
13 #include "network/network.h"
14 #include "network/network_func.h"
15 #include "order_backup.h"
16 #include "vehicle_base.h"
17 #include "window_func.h"
18 #include "station_map.h"
19 #include "order_cmd.h"
20 #include "group_cmd.h"
21 #include "vehicle_func.h"
22 
23 #include "safeguards.h"
24 
25 OrderBackupPool _order_backup_pool("BackupOrder");
27 
28 
30 {
31  if (CleaningPool()) return;
32 
33  Order *o = this->orders;
34  while (o != nullptr) {
35  Order *next = o->next;
36  delete o;
37  o = next;
38  }
39 }
40 
46 OrderBackup::OrderBackup(const Vehicle *v, uint32_t user)
47 {
48  this->user = user;
49  this->tile = v->tile;
50  this->group = v->group_id;
51 
53 
54  /* If we have shared orders, store the vehicle we share the order with. */
55  if (v->IsOrderListShared()) {
56  this->clone = (v->FirstShared() == v) ? v->NextShared() : v->FirstShared();
57  } else {
58  /* Else copy the orders */
59  Order **tail = &this->orders;
60 
61  /* Count the number of orders */
62  for (const Order *order : v->Orders()) {
63  Order *copy = new Order();
64  copy->AssignOrder(*order);
65  *tail = copy;
66  tail = &copy->next;
67  }
68  }
69 }
70 
76 {
77  /* If we had shared orders, recover that */
78  if (this->clone != nullptr) {
79  Command<CMD_CLONE_ORDER>::Do(DC_EXEC, CO_SHARE, v->index, this->clone->index);
80  } else if (this->orders != nullptr && OrderList::CanAllocateItem()) {
81  v->orders = new OrderList(this->orders, v);
82  this->orders = nullptr;
83  /* Make sure buoys/oil rigs are updated in the station list. */
85  }
86 
87  /* Remove backed up name if it's no longer unique. */
88  if (!IsUniqueVehicleName(this->name)) this->name.clear();
89 
91 
92  /* Make sure orders are in range */
95 
96  /* Restore vehicle group */
98 }
99 
106 /* static */ void OrderBackup::Backup(const Vehicle *v, uint32_t user)
107 {
108  /* Don't use reset as that broadcasts over the network to reset the variable,
109  * which is what we are doing at the moment. */
110  for (OrderBackup *ob : OrderBackup::Iterate()) {
111  if (ob->user == user) delete ob;
112  }
114  new OrderBackup(v, user);
115  }
116 }
117 
124 /* static */ void OrderBackup::Restore(Vehicle *v, uint32_t user)
125 {
126  for (OrderBackup *ob : OrderBackup::Iterate()) {
127  if (v->tile != ob->tile || ob->user != user) continue;
128 
129  ob->DoRestore(v);
130  delete ob;
131  }
132 }
133 
140 /* static */ void OrderBackup::ResetOfUser(TileIndex tile, uint32_t user)
141 {
142  for (OrderBackup *ob : OrderBackup::Iterate()) {
143  if (ob->user == user && (ob->tile == tile || tile == INVALID_TILE)) delete ob;
144  }
145 }
146 
155 {
156  /* No need to check anything. If the tile or user don't exist we just ignore it. */
157  if (flags & DC_EXEC) OrderBackup::ResetOfUser(tile == 0 ? INVALID_TILE : tile, user_id);
158 
159  return CommandCost();
160 }
161 
168 /* static */ void OrderBackup::ResetUser(uint32_t user)
169 {
170  assert(_network_server);
171 
172  for (OrderBackup *ob : OrderBackup::Iterate()) {
173  /* If it's not a backup of us, ignore it. */
174  if (ob->user != user) continue;
175 
177  return;
178  }
179 }
180 
187 /* static */ void OrderBackup::Reset(TileIndex t, bool from_gui)
188 {
189  /* The user has CLIENT_ID_SERVER as default when network play is not active,
190  * but compiled it. A network client has its own variable for the unique
191  * client/user identifier. Finally if networking isn't compiled in the
192  * default is just plain and simple: 0. */
194 
195  for (OrderBackup *ob : OrderBackup::Iterate()) {
196  /* If this is a GUI action, and it's not a backup of us, ignore it. */
197  if (from_gui && ob->user != user) continue;
198  /* If it's not for our chosen tile either, ignore it. */
199  if (t != INVALID_TILE && t != ob->tile) continue;
200 
201  if (from_gui) {
202  /* We need to circumvent the "prevention" from this command being executed
203  * while the game is paused, so use the internal method. Nor do we want
204  * this command to get its cost estimated when shift is pressed. */
205  Command<CMD_CLEAR_ORDER_BACKUP>::Unsafe<CommandCallback>(STR_NULL, nullptr, true, false, ob->tile, CommandTraits<CMD_CLEAR_ORDER_BACKUP>::Args{ ob->tile, static_cast<ClientID>(user) });
206  } else {
207  /* The command came from the game logic, i.e. the clearing of a tile.
208  * In that case we have no need to actually sync this, just do it. */
209  delete ob;
210  }
211  }
212 }
213 
218 /* static */ void OrderBackup::ClearGroup(GroupID group)
219 {
220  for (OrderBackup *ob : OrderBackup::Iterate()) {
221  if (ob->group == group) ob->group = DEFAULT_GROUP;
222  }
223 }
224 
232 /* static */ void OrderBackup::ClearVehicle(const Vehicle *v)
233 {
234  assert(v != nullptr);
235  for (OrderBackup *ob : OrderBackup::Iterate()) {
236  if (ob->clone == v) {
237  /* Get another item in the shared list. */
238  ob->clone = (v->FirstShared() == v) ? v->NextShared() : v->FirstShared();
239  /* But if that isn't there, remove it. */
240  if (ob->clone == nullptr) delete ob;
241  }
242  }
243 }
244 
253 /* static */ void OrderBackup::RemoveOrder(OrderType type, DestinationID destination, bool hangar)
254 {
255  for (OrderBackup *ob : OrderBackup::Iterate()) {
256  for (Order *order = ob->orders; order != nullptr; order = order->next) {
257  OrderType ot = order->GetType();
258  if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
259  if (ot == OT_GOTO_DEPOT && hangar && !IsHangarTile(ob->tile)) continue; // Not an aircraft? Can't have a hangar order.
260  if (ot == OT_IMPLICIT || (IsHangarTile(ob->tile) && ot == OT_GOTO_DEPOT && !hangar)) ot = OT_GOTO_STATION;
261  if (ot == type && order->GetDestination() == destination) {
262  /* Remove the order backup! If a station/depot gets removed, we can't/shouldn't restore those broken orders. */
263  delete ob;
264  break;
265  }
266  }
267  }
268 }
Common return value for all commands.
Definition: command_type.h:23
Functions related to commands.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_EXEC
execute the given command
Definition: command_type.h:376
Command definitions related to engine groups.
uint16_t GroupID
Type for all group identifiers.
Definition: group_type.h:13
static const GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition: group_type.h:17
bool _networking
are we in networking mode?
Definition: network.cpp:65
bool _network_server
network-server is active
Definition: network.cpp:66
ClientID _network_own_client_id
Our client identifier.
Definition: network.cpp:70
Basic functions/variables used all over the place.
Network functions used by other parts of OpenTTD.
ClientID
'Unique' identifier to be given to clients
Definition: network_type.h:49
@ CLIENT_ID_SERVER
Servers always have this ID.
Definition: network_type.h:51
CommandCost CmdClearOrderBackup(DoCommandFlag flags, TileIndex tile, ClientID user_id)
Clear an OrderBackup.
Functions related to order backups.
OrderBackupPool _order_backup_pool
The pool with order backups.
Command definitions related to orders.
@ ODATFB_NEAREST_DEPOT
Send the vehicle to the nearest depot.
Definition: order_type.h:105
OrderType
Order types.
Definition: order_type.h:35
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition: pool_func.hpp:237
A number of safeguards to prevent using unsafe methods.
Maps accessors for stations.
bool IsHangarTile(Tile t)
Is tile t an hangar tile?
Definition: station_map.h:420
Definition of base types and functions in a cross-platform compatible way.
std::string name
Name of vehicle.
Definition: base_consist.h:18
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:31
VehicleOrderID cur_implicit_order_index
The index to the current implicit order.
Definition: base_consist.h:32
void CopyConsistPropertiesFrom(const BaseConsist *src)
Copy properties of other BaseConsist.
Defines the traits of a command.
Definition: command_type.h:453
Data for backing up an order of a vehicle so it can be restored after a vehicle is rebuilt in the sam...
Definition: order_backup.h:33
static void Reset(TileIndex tile=INVALID_TILE, bool from_gui=true)
Reset the OrderBackups from GUI/game logic.
static void Restore(Vehicle *v, uint32_t user)
Restore the data of this order to the given vehicle.
void DoRestore(Vehicle *v)
Restore the data of this order to the given vehicle.
Order * orders
The actual orders if the vehicle was not a clone.
Definition: order_backup.h:42
static void Backup(const Vehicle *v, uint32_t user)
Create an order backup for the given vehicle.
static void ClearVehicle(const Vehicle *v)
Clear/update the (clone) vehicle from an order backup.
const Vehicle * clone
Vehicle this vehicle was a clone of.
Definition: order_backup.h:41
TileIndex tile
Tile of the depot where the order was changed.
Definition: order_backup.h:38
uint32_t user
The user that requested the backup.
Definition: order_backup.h:37
static void ClearGroup(GroupID group)
Clear the group of all backups having this group ID.
GroupID group
The group the vehicle was part of.
Definition: order_backup.h:39
OrderBackup()
Creation for savegame restoration.
Definition: order_backup.h:45
static void ResetOfUser(TileIndex tile, uint32_t user)
Reset an OrderBackup given a tile and user.
static void ResetUser(uint32_t user)
Reset an user's OrderBackup if needed.
static void RemoveOrder(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition: order_base.h:259
Order * next
Pointer to next order. If nullptr, end of list.
Definition: order_base.h:59
void AssignOrder(const Order &other)
Assign data to an order (from another order) This function makes sure that the index is maintained co...
Definition: order_cmd.cpp:257
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Base class for all pools.
Definition: pool_type.hpp:80
The information about a vehicle list.
Definition: vehiclelist.h:28
Vehicle data structure.
Definition: vehicle_base.h:244
bool IsOrderListShared() const
Check if we share our orders with another vehicle.
Definition: vehicle_base.h:732
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
Definition: vehicle_base.h:738
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:366
OrderList * orders
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:359
IterateWrapper Orders() const
Returns an iterable ensemble of orders of a vehicle.
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:726
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Definition: vehicle_base.h:714
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
void UpdateRealOrderIndex()
Skip implicit orders until cur_real_order_index is a non-implicit order.
Definition: vehicle_base.h:901
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:95
Base class for all vehicles.
bool IsUniqueVehicleName(const std::string &name)
Test if a name is unique among vehicle names.
Functions related to vehicles.
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3228
Window functions not directly related to making/drawing windows.
@ WC_STATION_LIST
Station list; Window numbers:
Definition: window_type.h:302