From 0d54db5f9fb3a3987f908645ca9693684f34674b Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 3 Jan 2009 13:52:06 +0000 Subject: (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) --- src/vehicle.cpp | 110 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 47 deletions(-) (limited to 'src/vehicle.cpp') 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 + #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 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; } -- cgit v1.2.3-54-g00ecf