summaryrefslogtreecommitdiff
path: root/src/order_backup.cpp
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2010-08-18 15:15:59 +0000
committerrubidium <rubidium@openttd.org>2010-08-18 15:15:59 +0000
commit38ca44594fa71eda7c53e5c2e320020fb5cba6c8 (patch)
treebeceaa73d44f4f10f657aac9a1a09c16f0cf5bea /src/order_backup.cpp
parenta65345d7edd92bcb86befa568d676470b276d164 (diff)
downloadopenttd-38ca44594fa71eda7c53e5c2e320020fb5cba6c8.tar.xz
(svn r20539) -Codechange: make order backups more self-contained.
Diffstat (limited to 'src/order_backup.cpp')
-rw-r--r--src/order_backup.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/order_backup.cpp b/src/order_backup.cpp
new file mode 100644
index 000000000..3a462e3ce
--- /dev/null
+++ b/src/order_backup.cpp
@@ -0,0 +1,146 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * 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.
+ * 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.
+ * 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/>.
+ */
+
+/** @file order_backup.cpp Handling of order backups. */
+
+#include "stdafx.h"
+#include "command_func.h"
+#include "core/pool_func.hpp"
+#include "order_backup.h"
+#include "order_base.h"
+#include "vehicle_base.h"
+#include "settings_type.h"
+
+OrderBackupPool _order_backup_pool("BackupOrder");
+INSTANTIATE_POOL_METHODS(OrderBackup)
+
+OrderBackup::~OrderBackup()
+{
+ free(this->name);
+ free(this->orders);
+}
+
+OrderBackup::OrderBackup(const Vehicle *v)
+{
+ this->tile = v->tile;
+ this->orderindex = v->cur_order_index;
+ this->group = v->group_id;
+ this->service_interval = v->service_interval;
+
+ if (v->name != NULL) this->name = strdup(v->name);
+
+ /* If we have shared orders, store the vehicle we share the order with. */
+ if (v->IsOrderListShared()) {
+ const Vehicle *u = (v->FirstShared() == v) ? v->NextShared() : v->FirstShared();
+
+ this->clone = u->index;
+ } else {
+ /* Else copy the orders */
+
+ /* We do not have shared orders */
+ this->clone = INVALID_VEHICLE;
+
+ /* Count the number of orders */
+ uint cnt = 0;
+ const Order *order;
+ FOR_VEHICLE_ORDERS(v, order) cnt++;
+
+ /* Allocate memory for the orders plus an end-of-orders marker */
+ this->orders = MallocT<Order>(cnt + 1);
+
+ Order *dest = this->orders;
+
+ /* Copy the orders */
+ FOR_VEHICLE_ORDERS(v, order) {
+ memcpy(dest, order, sizeof(Order));
+ dest++;
+ }
+ /* End the list with an empty order */
+ dest->Free();
+ }
+}
+
+void OrderBackup::RestoreTo(const Vehicle *v)
+{
+ /* If we have a custom name, process that */
+ if (this->name != NULL) DoCommandP(0, v->index, 0, CMD_RENAME_VEHICLE, NULL, this->name);
+
+ /* If we had shared orders, recover that */
+ if (this->clone != INVALID_VEHICLE) {
+ DoCommandP(0, v->index | (this->clone << 16), CO_SHARE, CMD_CLONE_ORDER);
+ } else {
+
+ /* CMD_NO_TEST_IF_IN_NETWORK is used here, because CMD_INSERT_ORDER checks if the
+ * order number is one more than the current amount of orders, and because
+ * in network the commands are queued before send, the second insert always
+ * fails in test mode. By bypassing the test-mode, that no longer is a problem. */
+ for (uint i = 0; !this->orders[i].IsType(OT_NOTHING); i++) {
+ Order o = this->orders[i];
+ /* Conditional orders need to have their destination to be valid on insertion. */
+ if (o.IsType(OT_CONDITIONAL)) o.SetConditionSkipToOrder(0);
+
+ if (!DoCommandP(0, v->index + (i << 16), o.Pack(),
+ CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) {
+ break;
+ }
+
+ /* Copy timetable if enabled */
+ if (_settings_game.order.timetabling && !DoCommandP(0, v->index | (i << 16) | (1 << 25),
+ o.wait_time << 16 | o.travel_time,
+ CMD_CHANGE_TIMETABLE | CMD_NO_TEST_IF_IN_NETWORK)) {
+ break;
+ }
+ }
+
+ /* Fix the conditional orders' destination. */
+ for (uint i = 0; !this->orders[i].IsType(OT_NOTHING); i++) {
+ if (!this->orders[i].IsType(OT_CONDITIONAL)) continue;
+
+ if (!DoCommandP(0, v->index + (i << 16), MOF_LOAD | (this->orders[i].GetConditionSkipToOrder() << 4),
+ CMD_MODIFY_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) {
+ break;
+ }
+ }
+ }
+
+ /* Restore vehicle order-index and service interval */
+ DoCommandP(0, v->index, this->orderindex | (this->service_interval << 16), CMD_RESTORE_ORDER_INDEX);
+
+ /* Restore vehicle group */
+ DoCommandP(0, this->group, v->index, CMD_ADD_VEHICLE_GROUP);
+
+ delete this;
+}
+
+/* static */ OrderBackup *OrderBackup::GetByTile(TileIndex t)
+{
+ OrderBackup *ob;
+ FOR_ALL_ORDER_BACKUPS(ob) {
+ if (ob->tile == t) return ob;
+ }
+ return NULL;
+}
+
+/* static */ void OrderBackup::Reset()
+{
+ _order_backup_pool.CleanPool();
+}
+
+/* static */ void OrderBackup::ClearGroup(GroupID group)
+{
+ OrderBackup *ob;
+ FOR_ALL_ORDER_BACKUPS(ob) {
+ if (ob->group == group) ob->group = DEFAULT_GROUP;
+ }
+}
+
+void InitializeOrderBackups()
+{
+ _order_backup_pool.CleanPool();
+}