depot.c
author Darkvater
Sun, 29 Jan 2006 19:50:01 +0000
changeset 2919 3e42ca528f01
parent 2186 db48cf29b983
child 3047 2880aef0ee9d
permissions -rw-r--r--
(svn r3475) - Fix: you couldn't remove an item from a list-type of config ingame from the configuration file. Whatever you did, upon restart of OpenTTD those items were still there. To fix this we initialize the first item to NULL in SaveList as it is rebuilt anyways fully.
/* $Id$ */

#include "stdafx.h"
#include "openttd.h"
#include "depot.h"
#include "functions.h"
#include "tile.h"
#include "map.h"
#include "table/strings.h"
#include "saveload.h"
#include "order.h"

enum {
	/* Max depots: 64000 (8 * 8000) */
	DEPOT_POOL_BLOCK_SIZE_BITS = 3,       /* In bits, so (1 << 3) == 8 */
	DEPOT_POOL_MAX_BLOCKS      = 8000,
};

/**
 * Called if a new block is added to the depot-pool
 */
static void DepotPoolNewBlock(uint start_item)
{
	Depot *depot;

	FOR_ALL_DEPOTS_FROM(depot, start_item)
		depot->index = start_item++;
}

/* Initialize the town-pool */
MemoryPool _depot_pool = { "Depots", DEPOT_POOL_MAX_BLOCKS, DEPOT_POOL_BLOCK_SIZE_BITS, sizeof(Depot), &DepotPoolNewBlock, 0, 0, NULL };


/**
 * Gets a depot from a tile
 *
 * @return Returns the depot if the tile had a depot, else it returns NULL
 */
Depot *GetDepotByTile(TileIndex tile)
{
	Depot *depot;

	FOR_ALL_DEPOTS(depot) {
		if (depot->xy == tile)
			return depot;
	}

	return NULL;
}

/**
 * Allocate a new depot
 */
Depot *AllocateDepot(void)
{
	Depot *depot;

	FOR_ALL_DEPOTS(depot) {
		if (!IsValidDepot(depot)) {
			uint index = depot->index;

			memset(depot, 0, sizeof(Depot));
			depot->index = index;

			return depot;
		}
	}

	/* Check if we can add a block to the pool */
	if (AddBlockToPool(&_depot_pool))
		return AllocateDepot();

	return NULL;
}

/**
 * Delete a depot
 */
void DoDeleteDepot(TileIndex tile)
{
	Order order;
	Depot *depot;

	/* Get the depot */
	depot = GetDepotByTile(tile);

	/* Clear the tile */
	DoClearSquare(tile);

	/* Clear the depot */
	depot->xy = 0;

	/* Clear the depot from all order-lists */
	order.type    = OT_GOTO_DEPOT;
	order.station = depot->index;
	DeleteDestinationFromVehicleOrder(order);

	/* Delete the depot-window */
	DeleteWindowById(WC_VEHICLE_DEPOT, tile);
}

void InitializeDepot(void)
{
	CleanPool(&_depot_pool);
	AddBlockToPool(&_depot_pool);
}


static const SaveLoad _depot_desc[] = {
	SLE_CONDVAR(Depot, xy,			SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
	SLE_CONDVAR(Depot, xy,			SLE_UINT32, 6, 255),
	SLE_VAR(Depot,town_index,		SLE_UINT16),
	SLE_END()
};

static void Save_DEPT(void)
{
	Depot *depot;

	FOR_ALL_DEPOTS(depot) {
		if (IsValidDepot(depot)) {
			SlSetArrayIndex(depot->index);
			SlObject(depot, _depot_desc);
		}
	}
}

static void Load_DEPT(void)
{
	int index;

	while ((index = SlIterateArray()) != -1) {
		Depot *depot;

		if (!AddBlockIfNeeded(&_depot_pool, index))
			error("Depots: failed loading savegame: too many depots");

		depot = GetDepot(index);
		SlObject(depot, _depot_desc);
	}
}

const ChunkHandler _depot_chunk_handlers[] = {
	{ 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY | CH_LAST},
};