(svn r23005) -Fix (r23004): Of course there's still the 16-sprite version for shore...
[openttd/fttd.git] / src / order_backup.cpp
blobb2e7b068c59155c525593be3c0fd70653a65c8f0
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file order_backup.cpp Handling of order backups. */
12 #include "stdafx.h"
13 #include "command_func.h"
14 #include "core/pool_func.hpp"
15 #include "network/network.h"
16 #include "network/network_func.h"
17 #include "order_backup.h"
18 #include "vehicle_base.h"
20 OrderBackupPool _order_backup_pool("BackupOrder");
21 INSTANTIATE_POOL_METHODS(OrderBackup)
23 /** Free everything that is allocated. */
24 OrderBackup::~OrderBackup()
26 free(this->name);
28 if (CleaningPool()) return;
30 Order *o = this->orders;
31 while (o != NULL) {
32 Order *next = o->next;
33 delete o;
34 o = next;
38 /**
39 * Create an order backup for the given vehicle.
40 * @param v The vehicle to make a backup of.
41 * @param user The user that is requesting the backup.
43 OrderBackup::OrderBackup(const Vehicle *v, uint32 user)
45 this->user = user;
46 this->tile = v->tile;
47 this->orderindex = v->cur_implicit_order_index;
48 this->group = v->group_id;
49 this->service_interval = v->service_interval;
51 if (v->name != NULL) this->name = strdup(v->name);
53 /* If we have shared orders, store the vehicle we share the order with. */
54 if (v->IsOrderListShared()) {
55 this->clone = (v->FirstShared() == v) ? v->NextShared() : v->FirstShared();
56 } else {
57 /* Else copy the orders */
58 Order **tail = &this->orders;
60 /* Count the number of orders */
61 const Order *order;
62 FOR_VEHICLE_ORDERS(v, order) {
63 Order *copy = new Order();
64 copy->AssignOrder(*order);
65 *tail = copy;
66 tail = &copy->next;
71 /**
72 * Restore the data of this order to the given vehicle.
73 * @param v The vehicle to restore to.
75 void OrderBackup::DoRestore(Vehicle *v)
77 /* If we have a custom name, process that */
78 v->name = this->name;
79 this->name = NULL;
81 /* If we had shared orders, recover that */
82 if (this->clone != NULL) {
83 DoCommand(0, v->index | CO_SHARE << 30, this->clone->index, DC_EXEC, CMD_CLONE_ORDER);
84 } else if (this->orders != NULL && OrderList::CanAllocateItem()) {
85 v->orders.list = new OrderList(this->orders, v);
86 this->orders = NULL;
89 uint num_orders = v->GetNumOrders();
90 if (num_orders != 0) {
91 v->cur_real_order_index = v->cur_implicit_order_index = this->orderindex % num_orders;
92 v->UpdateRealOrderIndex();
94 v->service_interval = this->service_interval;
96 /* Restore vehicle group */
97 DoCommand(0, this->group, v->index, DC_EXEC, CMD_ADD_VEHICLE_GROUP);
101 * Create an order backup for the given vehicle.
102 * @param v The vehicle to make a backup of.
103 * @param user The user that is requesting the backup.
104 * @note Will automatically remove any previous backups of this user.
106 /* static */ void OrderBackup::Backup(const Vehicle *v, uint32 user)
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 OrderBackup *ob;
111 FOR_ALL_ORDER_BACKUPS(ob) {
112 if (ob->user == user) delete ob;
114 if (OrderBackup::CanAllocateItem()) {
115 new OrderBackup(v, user);
120 * Restore the data of this order to the given vehicle.
121 * @param v The vehicle to restore to.
122 * @param user The user that built the vehicle, thus wants to restore.
123 * @note After restoration the backup will automatically be removed.
125 /* static */ void OrderBackup::Restore(Vehicle *v, uint32 user)
127 OrderBackup *ob;
128 FOR_ALL_ORDER_BACKUPS(ob) {
129 if (v->tile != ob->tile || ob->user != user) continue;
131 ob->DoRestore(v);
132 delete ob;
137 * Reset an OrderBackup given a tile and user.
138 * @param tile The tile associated with the OrderBackup.
139 * @param user The user associated with the OrderBackup.
140 * @note Must not be used from the GUI!
142 /* static */ void OrderBackup::ResetOfUser(TileIndex tile, uint32 user)
144 OrderBackup *ob;
145 FOR_ALL_ORDER_BACKUPS(ob) {
146 if (ob->user == user && (ob->tile == tile || tile == INVALID_TILE)) delete ob;
151 * Clear an OrderBackup
152 * @param tile Tile related to the to-be-cleared OrderBackup.
153 * @param flags For command.
154 * @param p1 Unused.
155 * @param p2 User that had the OrderBackup.
156 * @param text Unused.
157 * @return The cost of this operation or an error.
159 CommandCost CmdClearOrderBackup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
161 /* No need to check anything. If the tile or user don't exist we just ignore it. */
162 if (flags & DC_EXEC) OrderBackup::ResetOfUser(tile == 0 ? INVALID_TILE : tile, p2);
164 return CommandCost();
168 * Reset an user's OrderBackup if needed.
169 * @param user The user associated with the OrderBackup.
170 * @pre _network_server.
171 * @note Must not be used from a command.
173 /* static */ void OrderBackup::ResetUser(uint32 user)
175 assert(_network_server);
177 OrderBackup *ob;
178 FOR_ALL_ORDER_BACKUPS(ob) {
179 /* If it's not an backup of us, so ignore it. */
180 if (ob->user != user) continue;
182 DoCommandP(0, 0, user, CMD_CLEAR_ORDER_BACKUP);
183 return;
188 * Reset the OrderBackups from GUI/game logic.
189 * @param t The tile of the order backup.
190 * @param from_gui Whether the call came from the GUI, i.e. whether
191 * it must be synced over the network.
193 /* static */ void OrderBackup::Reset(TileIndex t, bool from_gui)
195 /* The user has CLIENT_ID_SERVER as default when network play is not active,
196 * but compiled it. A network client has its own variable for the unique
197 * client/user identifier. Finally if networking isn't compiled in the
198 * default is just plain and simple: 0. */
199 #ifdef ENABLE_NETWORK
200 uint32 user = _networking && !_network_server ? _network_own_client_id : CLIENT_ID_SERVER;
201 #else
202 uint32 user = 0;
203 #endif
205 OrderBackup *ob;
206 FOR_ALL_ORDER_BACKUPS(ob) {
207 /* If it's not an backup of us, so ignore it. */
208 if (ob->user != user) continue;
209 /* If it's not for our chosen tile either, ignore it. */
210 if (t != INVALID_TILE && t != ob->tile) continue;
212 if (from_gui) {
213 /* We need to circumvent the "prevention" from this command being executed
214 * while the game is paused, so use the internal method. Nor do we want
215 * this command to get its cost estimated when shift is pressed. */
216 DoCommandPInternal(ob->tile, 0, user, CMD_CLEAR_ORDER_BACKUP, NULL, NULL, true, false);
217 } else {
218 /* The command came from the game logic, i.e. the clearing of a tile.
219 * In that case we have no need to actually sync this, just do it. */
220 delete ob;
226 * Clear the group of all backups having this group ID.
227 * @param group The group to clear.
229 /* static */ void OrderBackup::ClearGroup(GroupID group)
231 OrderBackup *ob;
232 FOR_ALL_ORDER_BACKUPS(ob) {
233 if (ob->group == group) ob->group = DEFAULT_GROUP;
238 * Clear/update the (clone) vehicle from an order backup.
239 * @param v The vehicle to clear.
240 * @pre v != NULL
241 * @note If it is not possible to set another vehicle as clone
242 * "example", then this backed up order will be removed.
244 /* static */ void OrderBackup::ClearVehicle(const Vehicle *v)
246 assert(v != NULL);
247 OrderBackup *ob;
248 FOR_ALL_ORDER_BACKUPS(ob) {
249 if (ob->clone == v) {
250 /* Get another item in the shared list. */
251 ob->clone = (v->FirstShared() == v) ? v->NextShared() : v->FirstShared();
252 /* But if that isn't there, remove it. */
253 if (ob->clone == NULL) delete ob;