summaryrefslogtreecommitdiff
path: root/src/vehicle.cpp
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-01-03 13:52:06 +0000
committerrubidium <rubidium@openttd.org>2009-01-03 13:52:06 +0000
commit0d54db5f9fb3a3987f908645ca9693684f34674b (patch)
treed7251708eeba7b26d032505b22c0bb570da26501 /src/vehicle.cpp
parentfa2bf69a5384a8035a92a069f47f31a178bc3f3c (diff)
downloadopenttd-0d54db5f9fb3a3987f908645ca9693684f34674b.tar.xz
(svn r14803) -Codechange: move order list management into it's own class and remove the order count from the savegame as we can easily count that (PhilSophus)
Diffstat (limited to 'src/vehicle.cpp')
-rw-r--r--src/vehicle.cpp110
1 files changed, 63 insertions, 47 deletions
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index f267c635f..4f620e5f0 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -59,6 +59,8 @@
#include "table/sprites.h"
#include "table/strings.h"
+#include <map>
+
#define INVALID_COORD (0x7fffffff)
#define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
@@ -221,7 +223,7 @@ void VehiclePositionChanged(Vehicle *v)
}
/** Called after load to update coordinates */
-void AfterLoadVehicles(bool clear_te_id)
+void AfterLoadVehicles(bool part_of_load)
{
Vehicle *v;
@@ -232,7 +234,7 @@ void AfterLoadVehicles(bool clear_te_id)
v->UpdateDeltaXY(v->direction);
- if (clear_te_id) v->fill_percent_te_id = INVALID_TE_ID;
+ if (part_of_load) v->fill_percent_te_id = INVALID_TE_ID;
v->first = NULL;
if (v->type == VEH_TRAIN) v->u.rail.first_engine = INVALID_ENGINE;
if (v->type == VEH_ROAD) v->u.road.first_engine = INVALID_ENGINE;
@@ -240,19 +242,45 @@ void AfterLoadVehicles(bool clear_te_id)
v->cargo.InvalidateCache();
}
+ /* AfterLoadVehicles may also be called in case of NewGRF reload, in this
+ * case we may not convert orders again. */
+ if (part_of_load) {
+ /* Create shared vehicle chain for very old games (pre 5,2) and create
+ * OrderList from shared vehicle chains. For this to work correctly, the
+ * following conditions must be fulfilled:
+ * a) both next_shared and previous_shared are not set for pre 5,2 games
+ * b) both next_shared and previous_shared are set for later games
+ */
+ std::map<Order*, OrderList*> mapping;
+
+ FOR_ALL_VEHICLES(v) {
+ if (v->orders.old != NULL) {
+ if (CheckSavegameVersion(105)) { // Pre-105 didn't save an OrderList
+ if (mapping[v->orders.old] == NULL) {
+ /* This adds the whole shared vehicle chain for case b */
+ v->orders.list = mapping[v->orders.old] = new OrderList(v->orders.old, v);
+ } else {
+ v->orders.list = mapping[v->orders.old];
+ /* For old games (case a) we must create the shared vehicle chain */
+ if (CheckSavegameVersionOldStyle(5, 2)) {
+ v->AddToShared(v->orders.list->GetFirstSharedVehicle());
+ }
+ }
+ } else { // OrderList was saved as such, only recalculate not saved values
+ if (v->PreviousShared() == NULL) {
+ new (v->orders.list) OrderList(v->orders.list->GetFirstOrder(), v);
+ }
+ }
+ }
+ }
+ }
+
FOR_ALL_VEHICLES(v) {
/* Fill the first pointers */
if (v->Previous() == NULL) {
for (Vehicle *u = v; u != NULL; u = u->Next()) {
u->first = v;
}
-
- /* Shared orders are only valid for first vehicles in chains. */
- if (v->previous_shared == NULL) {
- for (Vehicle *u = v; u != NULL; u = u->NextShared()) {
- u->first_shared = v;
- }
- }
}
}
@@ -315,7 +343,6 @@ Vehicle::Vehicle()
this->group_id = DEFAULT_GROUP;
this->fill_percent_te_id = INVALID_TE_ID;
this->first = this;
- this->first_shared = this;
this->colormap = PAL_NONE;
}
@@ -2168,7 +2195,8 @@ static const SaveLoad _common_veh_desc[] = {
SLE_CONDVAR(Vehicle, running_ticks, SLE_UINT8, 88, SL_MAX_VERSION),
SLE_VAR(Vehicle, cur_order_index, SLE_UINT8),
- SLE_VAR(Vehicle, num_orders, SLE_UINT8),
+ /* num_orders is now part of OrderList and is not saved but counted */
+ SLE_CONDNULL(1, 0, 104),
/* This next line is for version 4 and prior compatibility.. it temporarily reads
type and flags (which were both 4 bits) into type. Later on this is
@@ -2189,7 +2217,8 @@ static const SaveLoad _common_veh_desc[] = {
SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, wait_time), SLE_UINT16, 67, SL_MAX_VERSION),
SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, travel_time), SLE_UINT16, 67, SL_MAX_VERSION),
- SLE_REF(Vehicle, orders, REF_ORDER),
+ SLE_CONDREF(Vehicle, orders, REF_ORDER, 0, 104),
+ SLE_CONDREF(Vehicle, orders, REF_ORDERLIST, 105, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
SLE_CONDVAR(Vehicle, age, SLE_INT32, 31, SL_MAX_VERSION),
@@ -2409,7 +2438,6 @@ void Load_VEHS()
_vehicles_to_autoreplace.Reset();
int index;
- Vehicle *v;
_cargo_count = 0;
@@ -2456,22 +2484,6 @@ void Load_VEHS()
/* Advanced vehicle lists got added */
if (CheckSavegameVersion(60)) v->group_id = DEFAULT_GROUP;
}
-
- /* Check for shared order-lists (we now use pointers for that) */
- if (CheckSavegameVersionOldStyle(5, 2)) {
- FOR_ALL_VEHICLES(v) {
- Vehicle *u;
-
- FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
- /* If a vehicle has the same orders, add the link to eachother
- * in both vehicles */
- if (v->orders == u->orders) {
- u->AddToShared(v);
- break;
- }
- }
- }
- }
}
extern const ChunkHandler _veh_chunk_handlers[] = {
@@ -2651,47 +2663,51 @@ void Vehicle::SetNext(Vehicle *next)
void Vehicle::AddToShared(Vehicle *shared_chain)
{
- assert(!this->IsOrderListShared());
+ assert(this->previous_shared == NULL && this->next_shared == NULL);
+
+ if (!shared_chain->orders.list) {
+ assert(shared_chain->previous_shared == NULL);
+ assert(shared_chain->next_shared == NULL);
+ this->orders.list = shared_chain->orders.list = new OrderList(NULL, shared_chain);
+ }
this->next_shared = shared_chain->next_shared;
this->previous_shared = shared_chain;
- this->first_shared = shared_chain->first_shared;
shared_chain->next_shared = this;
if (this->next_shared != NULL) this->next_shared->previous_shared = this;
+
+ shared_chain->orders.list->AddVehicle(this);
}
void Vehicle::RemoveFromShared()
{
- Vehicle *new_first;
+ /* Remember if we were first and the old window number before RemoveVehicle()
+ * as this changes first if needed. */
+ bool were_first = (this->FirstShared() == this);
+ uint32 old_window_number = (this->FirstShared()->index << 16) | (this->type << 11) | VLW_SHARED_ORDERS | this->owner;
- if (this->FirstShared() == this) {
- /* We are the first shared one, so update all the first pointers of our next shared ones. */
- new_first = this->NextShared();
- for (Vehicle *u = new_first; u != NULL; u = u->NextShared()) {
- u->first_shared = new_first;
- }
- } else {
+ this->orders.list->RemoveVehicle(this);
+
+ if (!were_first) {
/* We are not the first shared one, so only relink our previous one. */
- new_first = this->FirstShared();
this->previous_shared->next_shared = this->NextShared();
}
if (this->next_shared != NULL) this->next_shared->previous_shared = this->previous_shared;
- uint32 old_window_number = (this->FirstShared()->index << 16) | (this->type << 11) | VLW_SHARED_ORDERS | this->owner;
- if (new_first->NextShared() == NULL) {
+ if (this->orders.list->GetNumVehicles() == 1) {
/* When there is only one vehicle, remove the shared order list window. */
DeleteWindowById(GetWindowClassForVehicleType(this->type), old_window_number);
- InvalidateVehicleOrder(new_first, 0);
- } else if (this->FirstShared() == this) {
- /* If we were the first one, update to the new first one. */
- InvalidateWindowData(GetWindowClassForVehicleType(this->type), old_window_number, (new_first->index << 16) | (1 << 15));
+ InvalidateVehicleOrder(this->FirstShared(), 0);
+ } else if (were_first) {
+ /* If we were the first one, update to the new first one.
+ * Note: FirstShared() is already the new first */
+ InvalidateWindowData(GetWindowClassForVehicleType(this->type), old_window_number, (this->FirstShared()->index << 16) | (1 << 15));
}
- this->first_shared = this;
this->next_shared = NULL;
this->previous_shared = NULL;
}