Changeset - r15853:61b6cb670877
[Not reviewed]
master
0 6 0
rubidium - 14 years ago 2010-08-18 18:52:16
rubidium@openttd.org
(svn r20545) -Codechange: make sure an OrderBackup gets cleared when the depot it belongs to gets removed, the depot window gets closed or when another vehicle gets sold in a depot
6 files changed with 42 insertions and 25 deletions:
0 comments (0 inline, 0 general)
src/depot.cpp
Show inline comments
 
@@ -2,44 +2,46 @@
 

	
 
/*
 
 * 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 depot.cpp Handling of depots. */
 

	
 
#include "stdafx.h"
 
#include "depot_base.h"
 
#include "order_backup.h"
 
#include "order_func.h"
 
#include "window_func.h"
 
#include "core/pool_func.hpp"
 
#include "vehicle_gui.h"
 

	
 
DepotPool _depot_pool("Depot");
 
INSTANTIATE_POOL_METHODS(Depot)
 

	
 
/**
 
 * Clean up a depot
 
 */
 
Depot::~Depot()
 
{
 
	if (CleaningPool()) return;
 

	
 
	/* Clear the depot from all order-lists */
 
	RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, this->index);
 

	
 
	/* Delete the depot-window */
 
	DeleteWindowById(WC_VEHICLE_DEPOT, this->xy);
 
	OrderBackup::Reset(this->xy);
 

	
 
	/* Delete the depot list */
 
	WindowNumber wno = (this->index << 16) | VLW_DEPOT_LIST | GetTileOwner(this->xy);
 
	switch (GetTileType(this->xy)) {
 
		default: break; // It can happen there is no depot here anymore (TTO/TTD savegames)
 
		case MP_RAILWAY: DeleteWindowById(WC_TRAINS_LIST,  wno | (VEH_TRAIN << 11)); break;
 
		case MP_ROAD:    DeleteWindowById(WC_ROADVEH_LIST, wno | (VEH_ROAD  << 11)); break;
 
		case MP_WATER:   DeleteWindowById(WC_SHIPS_LIST,   wno | (VEH_SHIP  << 11)); break;
 
	}
 
}
 

	
 
void InitializeDepots()
src/depot_gui.cpp
Show inline comments
 
@@ -252,24 +252,25 @@ struct DepotWindow : Window {
 
		this->GetWidget<NWidgetStacked>(DEPOT_WIDGET_SHOW_H_SCROLL)->SetDisplayedPlane(type == VEH_TRAIN ? 0 : SZSP_HORIZONTAL);
 
		this->GetWidget<NWidgetStacked>(DEPOT_WIDGET_SHOW_SELL_CHAIN)->SetDisplayedPlane(type == VEH_TRAIN ? 0 : SZSP_NONE);
 
		this->SetupWidgetData(type);
 
		this->FinishInitNested(desc, tile);
 

	
 
		this->owner = GetTileOwner(tile);
 
		OrderBackup::Reset();
 
	}
 

	
 
	~DepotWindow()
 
	{
 
		DeleteWindowById(WC_BUILD_VEHICLE, this->window_number);
 
		OrderBackup::Reset(this->window_number);
 
	}
 

	
 
	/**
 
	 * Draw a vehicle in the depot window in the box with the top left corner at x,y.
 
	 * @param v     Vehicle to draw.
 
	 * @param left  Left side of the box to draw in.
 
	 * @param right Right side of the box to draw in.
 
	 * @param y     Top of the box to draw in.
 
	 */
 
	void DrawVehicleInDepot(const Vehicle *v, int left, int right, int y) const
 
	{
 
		bool free_wagon = false;
 
@@ -969,30 +970,27 @@ struct DepotWindow : Window {
 
				if (this->sel == INVALID_VEHICLE) return;
 

	
 
				this->HandleButtonClick(widget);
 

	
 
				const Vehicle *v = Vehicle::Get(this->sel);
 
				this->sel = INVALID_VEHICLE;
 
				this->SetDirty();
 

	
 
				int sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0;
 

	
 
				bool is_engine = (v->type != VEH_TRAIN || Train::From(v)->IsFrontEngine());
 

	
 
				if (is_engine) {
 
					OrderBackup::Reset();
 
					new OrderBackup(v);
 
				}
 
				if (is_engine) OrderBackup::Backup(v);
 

	
 
				if (!DoCommandP(v->tile, v->index | sell_cmd << 16, 0, GetCmdSellVeh(v->type)) && is_engine) OrderBackup::Reset();
 
				if (!DoCommandP(v->tile, v->index | sell_cmd << 16, 0, GetCmdSellVeh(v->type)) && is_engine) OrderBackup::Reset(this->window_number);
 
				break;
 
			}
 

	
 
			default:
 
				this->sel = INVALID_VEHICLE;
 
				this->SetDirty();
 
		}
 
		_cursor.vehchain = false;
 
	}
 

	
 
	virtual void OnTimeout()
 
	{
src/order_backup.cpp
Show inline comments
 
@@ -52,25 +52,25 @@ OrderBackup::OrderBackup(const Vehicle *
 
		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)
 
void OrderBackup::DoRestore(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 != NULL) {
 
		DoCommandP(0, v->index | (this->clone->index << 16), CO_SHARE, CMD_CLONE_ORDER);
 
	} else if (this->orders != NULL) {
 

	
 
		/* 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
 
@@ -100,40 +100,49 @@ void OrderBackup::RestoreTo(const Vehicl
 
			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)
 
/* static */ void OrderBackup::Backup(const Vehicle *v)
 
{
 
	OrderBackup::Reset();
 
	new OrderBackup(v);
 
}
 

	
 
/* static */ void OrderBackup::Restore(const Vehicle *v)
 
{
 
	OrderBackup *ob;
 
	FOR_ALL_ORDER_BACKUPS(ob) {
 
		if (ob->tile == t) return ob;
 
		if (v->tile != ob->tile) continue;
 

	
 
		ob->DoRestore(v);
 
		delete ob;
 
	}
 
	return NULL;
 
}
 

	
 
/* static */ void OrderBackup::Reset()
 
/* static */ void OrderBackup::Reset(TileIndex t)
 
{
 
	_order_backup_pool.CleanPool();
 
	OrderBackup *ob;
 
	FOR_ALL_ORDER_BACKUPS(ob) {
 
		if (t == INVALID_TILE || t == ob->tile) delete ob;
 
	}
 
}
 

	
 
/* static */ void OrderBackup::ClearGroup(GroupID group)
 
{
 
	OrderBackup *ob;
 
	FOR_ALL_ORDER_BACKUPS(ob) {
 
		if (ob->group == group) ob->group = DEFAULT_GROUP;
 
	}
 
}
 

	
 
/* static */ void OrderBackup::ClearVehicle(const Vehicle *v)
 
{
src/order_backup.h
Show inline comments
 
@@ -34,52 +34,59 @@ extern OrderBackupPool _order_backup_poo
 
 */
 
struct OrderBackup : OrderBackupPool::PoolItem<&_order_backup_pool> {
 
private:
 
	TileIndex tile;            ///< Tile of the depot where the order was changed.
 
	GroupID group;             ///< The group the vehicle was part of.
 
	uint16 service_interval;   ///< The service interval of the vehicle.
 
	char *name;                ///< The custom name of the vehicle.
 

	
 
	const Vehicle *clone;      ///< Vehicle this vehicle was a clone of.
 
	VehicleOrderID orderindex; ///< The order-index the vehicle had.
 
	Order *orders;             ///< The actual orders if the vehicle was not a clone.
 

	
 
public:
 
	/**
 
	 * Create an order backup for the given vehicle.
 
	 * @param v The vehicle to make a backup of.
 
	 */
 
	OrderBackup(const Vehicle *v);
 

	
 
	/**
 
	 * Restore the data of this order to the given vehicle.
 
	 * @param v The vehicle to restore to.
 
	 */
 
	void DoRestore(const Vehicle *v);
 

	
 
public:
 
	/** Free everything that is allocated. */
 
	~OrderBackup();
 

	
 
	/**
 
	 * Create an order backup for the given vehicle.
 
	 * @param v The vehicle to make a backup of.
 
	 * @note Will automatically remove any previous backups of this user.
 
	 */
 
	static void Backup(const Vehicle *v);
 

	
 
	/**
 
	 * Restore the data of this order to the given vehicle.
 
	 * @param v The vehicle to restore to.
 
	 * @note After restoration the backup will automatically be removed.
 
	 */
 
	void RestoreTo(const Vehicle *v);
 

	
 
	/**
 
	 * Get the order backup associated with a given tile.
 
	 * @param t The tile to get the order backup for.
 
	 * @return The order backup, or NULL if it doesn't exist.
 
	 */
 
	static OrderBackup *GetByTile(TileIndex t);
 
	static void Restore(const Vehicle *v);
 

	
 
	/**
 
	 * Reset the OrderBackups.
 
	 * @param tile The tile of the order backup.
 
	 */
 
	static void Reset();
 
	static void Reset(TileIndex tile = INVALID_TILE);
 

	
 
	/**
 
	 * Clear the group of all backups having this group ID.
 
	 * @param group The group to clear.
 
	 */
 
	static void ClearGroup(GroupID group);
 

	
 
	/**
 
	 * Clear/update the (clone) vehicle from an order backup.
 
	 * @param v The vehicle to clear.
 
	 * @pre v != NULL
 
	 * @note If it is not possible to set another vehicle as clone
src/station_cmd.cpp
Show inline comments
 
@@ -40,24 +40,25 @@
 
#include "station_base.h"
 
#include "roadstop_base.h"
 
#include "newgrf_railtype.h"
 
#include "waypoint_base.h"
 
#include "waypoint_func.h"
 
#include "pbs.h"
 
#include "debug.h"
 
#include "core/random_func.hpp"
 
#include "company_base.h"
 
#include "newgrf.h"
 
#include "table/airporttile_ids.h"
 
#include "newgrf_airporttiles.h"
 
#include "order_backup.h"
 

	
 
#include "table/strings.h"
 

	
 
/**
 
 * Check whether the given tile is a hangar.
 
 * @param t the tile to of whether it is a hangar.
 
 * @pre IsTileType(t, MP_STATION)
 
 * @return true if and only if the tile is a hangar.
 
 */
 
bool IsHangar(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_STATION));
 
@@ -2278,24 +2279,25 @@ static CommandCost RemoveAirport(TileInd
 
		if (a->targetairport == st->index && a->state != FLYING) return CMD_ERROR;
 
	}
 

	
 
	TILE_AREA_LOOP(tile_cur, st->airport) {
 
		if (!st->TileBelongsToAirport(tile_cur)) continue;
 

	
 
		CommandCost ret = EnsureNoVehicleOnGround(tile_cur);
 
		if (ret.Failed()) return ret;
 

	
 
		cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
 

	
 
		if (flags & DC_EXEC) {
 
			if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur);
 
			DeleteAnimatedTile(tile_cur);
 
			DoClearSquare(tile_cur);
 
			DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur);
 
		}
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		const AirportSpec *as = st->airport.GetSpec();
 
		for (uint i = 0; i < st->airport.GetNumHangars(); ++i) {
 
			DeleteWindowById(
 
				WC_VEHICLE_DEPOT, st->airport.GetHangarTile(i)
 
			);
src/vehicle_gui.cpp
Show inline comments
 
@@ -2364,16 +2364,15 @@ void StopGlobalFollowVehicle(const Vehic
 
/**
 
 * This is the Callback method after the construction attempt of a primary vehicle
 
 * @param result indicates completion (or not) of the operation
 
 * @param tile unused
 
 * @param p1 unused
 
 * @param p2 unused
 
 */
 
void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
 
{
 
	if (result.Failed()) return;
 

	
 
	const Vehicle *v = Vehicle::Get(_new_vehicle_id);
 
	OrderBackup *ob = OrderBackup::GetByTile(v->tile);
 
	if (ob != NULL) ob->RestoreTo(v);
 
	OrderBackup::Restore(v);
 
	ShowVehicleViewWindow(v);
 
}
0 comments (0 inline, 0 general)