# HG changeset patch # User bjarni # Date 1130763587 0 # Node ID 70a4e3cb85bf601374941935b1c43fb301a4e68b # Parent 7a1e7290516170f04ab78e90ce9966915d7bcc81 (svn r3111) -Fix: [autoreplace] [ 1341783 ] Assertion failure in vehicle.c line 378 running MaybeReplaceVehicle() is now delayed until after the loop in CallVehicleTicks() This avoids selling the vehicle the loop currently works with (and continues to work with afterwards) diff -r 7a1e72905161 -r 70a4e3cb85bf aircraft_cmd.c --- a/aircraft_cmd.c Mon Oct 31 12:01:41 2005 +0000 +++ b/aircraft_cmd.c Mon Oct 31 12:59:47 2005 +0000 @@ -1302,8 +1302,6 @@ ServiceAircraft(v); InvalidateWindowClasses(WC_AIRCRAFT_LIST); - v = MaybeReplaceVehicle(v); - TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); if (v->current_order.type == OT_GOTO_DEPOT) { diff -r 7a1e72905161 -r 70a4e3cb85bf engine.c --- a/engine.c Mon Oct 31 12:01:41 2005 +0000 +++ b/engine.c Mon Oct 31 12:59:47 2005 +0000 @@ -718,6 +718,12 @@ (resolve_callback) TriggerVehicleSpriteGroup); } + if (trigger == VEHICLE_TRIGGER_DEPOT) { + // store that the vehicle entered a depot this tick + // it needs to be before all possible return statements; + VehicleEnteredDepotThisTick(veh); + } + if (group == NULL) return; diff -r 7a1e72905161 -r 70a4e3cb85bf roadveh_cmd.c --- a/roadveh_cmd.c Mon Oct 31 12:01:41 2005 +0000 +++ b/roadveh_cmd.c Mon Oct 31 12:59:47 2005 +0000 @@ -1522,8 +1522,6 @@ InvalidateWindow(WC_VEHICLE_DETAILS, v->index); - v = MaybeReplaceVehicle(v); - VehicleServiceInDepot(v); TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); diff -r 7a1e72905161 -r 70a4e3cb85bf ship_cmd.c --- a/ship_cmd.c Mon Oct 31 12:01:41 2005 +0000 +++ b/ship_cmd.c Mon Oct 31 12:59:47 2005 +0000 @@ -414,8 +414,6 @@ InvalidateWindow(WC_VEHICLE_DETAILS, v->index); - v = MaybeReplaceVehicle(v); - TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); if (v->current_order.type == OT_GOTO_DEPOT) { diff -r 7a1e72905161 -r 70a4e3cb85bf train_cmd.c --- a/train_cmd.c Mon Oct 31 12:01:41 2005 +0000 +++ b/train_cmd.c Mon Oct 31 12:59:47 2005 +0000 @@ -3328,8 +3328,6 @@ v->load_unload_time_rem = 0; v->cur_speed = 0; - v = MaybeReplaceVehicle(v); - TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT); if (v->current_order.type == OT_GOTO_DEPOT) { diff -r 7a1e72905161 -r 70a4e3cb85bf vehicle.c --- a/vehicle.c Mon Oct 31 12:01:41 2005 +0000 +++ b/vehicle.c Mon Oct 31 12:59:47 2005 +0000 @@ -264,6 +264,7 @@ v->string_id = 0; v->next_shared = NULL; v->prev_shared = NULL; + v->depot_list = NULL; /* random_bits is used to pick out a random sprite for vehicles which are technical the same (newgrf stuff). Because RandomRange() results in desyncs, and because it does @@ -515,6 +516,24 @@ void Train_Tick(Vehicle *v); static void EffectVehicle_Tick(Vehicle *v); void DisasterVehicle_Tick(Vehicle *v); +static void MaybeReplaceVehicle(Vehicle *v); + +// head of the linked list to tell what vehicles that visited a depot in a tick +Vehicle *_first_veh_in_depot_list; + +/** Adds a vehicle to the list of vehicles, that visited a depot this tick +* @param *v vehicle to add +*/ +void VehicleEnteredDepotThisTick(Vehicle *v) +{ + if (_first_veh_in_depot_list == NULL) { + _first_veh_in_depot_list = v; + } else { + Vehicle *w = _first_veh_in_depot_list; + while (w->depot_list != NULL) w = w->depot_list; + w->depot_list = v; + } +} VehicleTickProc *_vehicle_tick_procs[] = { Train_Tick, @@ -529,9 +548,21 @@ { Vehicle *v; + _first_veh_in_depot_list = NULL; // now we are sure it's initialized at the start of each tick + FOR_ALL_VEHICLES(v) { - if (v->type != 0) + if (v->type != 0) { _vehicle_tick_procs[v->type - 0x10](v); + } + } + + // now we handle all the vehicles that entered a depot this tick + v = _first_veh_in_depot_list; + while (v != NULL) { + Vehicle *w = v->depot_list; + v->depot_list = NULL; // it should always be NULL at the end of each tick + MaybeReplaceVehicle(v); + v = w; } } @@ -1566,18 +1597,21 @@ * if the vehicle is a train, v needs to be the front engine * return value is a pointer to the new vehicle, which is the same as the argument if nothing happened */ -Vehicle * MaybeReplaceVehicle(Vehicle *v) +static void MaybeReplaceVehicle(Vehicle *v) { Vehicle *w; const Player *p = GetPlayer(v->owner); byte flags = 0; int32 cost = 0, temp_cost = 0; + bool stopped = false; _current_player = v->owner; assert(v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship || v->type == VEH_Aircraft); - - DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); + if (!(v->vehstatus&VS_STOPPED)) { + stopped = true; // we stop the vehicle to do this, so we have to remember to start it again when we are done + DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); + } while (true) { w = v; @@ -1626,8 +1660,9 @@ AddNewsItem(message, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0); } - DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); //we start the vehicle again - return v; + if (stopped) + DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); //we start the vehicle again + return; } if (flags & DC_EXEC) { @@ -1641,9 +1676,9 @@ SubtractMoneyFromPlayer(cost); if (IsLocalPlayer()) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost); - DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); //we start the vehicle again + if (stopped) + DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); //we start the vehicle again _current_player = OWNER_NONE; - return v; } diff -r 7a1e72905161 -r 70a4e3cb85bf vehicle.h --- a/vehicle.h Mon Oct 31 12:01:41 2005 +0000 +++ b/vehicle.h Mon Oct 31 12:59:47 2005 +0000 @@ -153,6 +153,7 @@ Vehicle *next; // next Vehicle *first; // NOSAVE: pointer to the first vehicle in the chain + Vehicle *depot_list; //NOSAVE: linked list to tell what vehicles entered a depot during the last tick. Used by autoreplace StringID string_id; // Displayed string @@ -164,6 +165,7 @@ int32 x_pos; // coordinates int32 y_pos; + byte z_pos; byte direction; // facing @@ -240,6 +242,8 @@ int32 profit_last_year; uint32 value; + + union { VehicleRail rail; VehicleAir air; @@ -309,7 +313,7 @@ void DecreaseVehicleValue(Vehicle *v); void CheckVehicleBreakdown(Vehicle *v); void AgeVehicle(Vehicle *v); -Vehicle * MaybeReplaceVehicle(Vehicle *v); +void VehicleEnteredDepotThisTick(Vehicle *v); void BeginVehicleMove(Vehicle *v); void EndVehicleMove(Vehicle *v);