Changeset - r5708:7ae0ffd22f15
[Not reviewed]
master
0 4 0
celestar - 18 years ago 2007-01-17 11:15:51
celestar@openttd.org
(svn r8185) -Codechange: Equipped Roadstops with new/delete operators and gave them proper constructors/destructors (Thanks to KUDr for a nice interactive C++ lesson)
4 files changed with 122 insertions and 94 deletions:
0 comments (0 inline, 0 general)
src/oldloader.cpp
Show inline comments
 
@@ -305,45 +305,28 @@ static void FixOldTowns(void)
 

	
 
static void FixOldStations(void)
 
{
 
	Station *st;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		/* Check if we need to swap width and height for the station */
 
		if (st->train_tile != 0 && GetRailStationAxis(st->train_tile) != AXIS_X) {
 
			SwapT(&st->trainst_w, &st->trainst_h);
 
		}
 

	
 
		/* Check if there is a bus or truck station, and convert to new format */
 
		if (st->bus_tile_obsolete != 0) {
 
			st->bus_stops = AllocateRoadStop();
 
			st->bus_stops->xy = st->bus_tile_obsolete;
 
			st->bus_stops->used = true;
 
			st->bus_stops->status = 3;
 
			st->bus_stops->station = st->index;
 
			st->bus_stops->next = NULL;
 
			st->bus_stops->prev = NULL;
 
			st->bus_stops->num_vehicles = 0;
 
		}
 
		if (st->bus_tile_obsolete != 0) st->bus_stops = new RoadStop(st->bus_tile_obsolete, st->index);
 

	
 
		if (st->lorry_tile_obsolete != 0) {
 
			st->truck_stops = AllocateRoadStop();
 
			st->truck_stops->xy = st->lorry_tile_obsolete;
 
			st->truck_stops->used = true;
 
			st->truck_stops->status = 3;
 
			st->truck_stops->station = st->index;
 
			st->truck_stops->next = NULL;
 
			st->truck_stops->prev = NULL;
 
			st->truck_stops->num_vehicles = 0;
 
		}
 
		if (st->lorry_tile_obsolete != 0) st->truck_stops = new RoadStop(st->lorry_tile_obsolete, st->index);
 

	
 
	}
 
}
 

	
 
static void FixOldVehicles(void)
 
{
 
	/* Check for shared orders, and link them correctly */
 
	Vehicle* v;
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		Vehicle *u;
 

	
 
		FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
src/station.cpp
Show inline comments
 
@@ -303,12 +303,109 @@ bool StationRect::AfterRemoveRect(Statio
 
	return empty;
 
}
 

	
 
StationRect& StationRect::operator = (Rect src)
 
{
 
	left = src.left;
 
	top = src.top;
 
	right = src.right;
 
	bottom = src.bottom;
 
	return *this;
 
}
 

	
 

	
 
/************************************************************************/
 
/*                     RoadStop implementation                          */
 
/************************************************************************/
 

	
 
/** Allocates a new RoadStop onto the pool, or recycles an unsed one
 
 *  @return a pointer to the new roadstop
 
 */
 
void *RoadStop::operator new(size_t size)
 
{
 
	RoadStop *rs = AllocateRaw();
 
	return rs;
 
}
 

	
 
/** Gets a RoadStop with a given index and allocates it when needed
 
  * @return a pointer to the roadstop
 
  */
 
void *RoadStop::operator new(size_t size, int index)
 
{
 
	if (!AddBlockIfNeeded(&_RoadStop_pool, index)) {
 
		error("RoadStops: failed loading savegame: too many RoadStops");
 
	}
 

	
 
	RoadStop *rs = GetRoadStop(index);
 
	return rs;
 
}
 

	
 
void RoadStop::operator delete(void *p)
 
{
 
}
 

	
 
void RoadStop::operator delete(void *p, int index)
 
{
 
}
 

	
 
/** Initializes a RoadStop */
 
RoadStop::RoadStop(TileIndex tile, StationID index)
 
{
 
	DEBUG(ms, cDebugCtorLevel,  "I+%3d at %d[0x%x]", index, tile, tile);
 
	xy = tile;
 
	used = true;
 
	status = 3; //stop is free
 
	next = NULL;
 
	prev = NULL;
 
	station = index;
 
	num_vehicles = 0;
 
}
 

	
 
/** De-Initializes a RoadStops. This includes clearing all slots that vehicles might
 
  * have and unlinks it from the linked list of road stops at the given station
 
  */
 
RoadStop::~RoadStop()
 
{
 
	Vehicle *v;
 

	
 
	/* Clear the slot assignment of all vehicles heading for this road stop */
 
	if (num_vehicles != 0) {
 
		FOR_ALL_VEHICLES(v) {
 
			if (v->type == VEH_Road && v->u.road.slot == this) ClearSlot(v);
 
		}
 
	}
 
	assert(num_vehicles == 0);
 

	
 
	if (prev != NULL) prev->next = next;
 
	if (next != NULL) next->prev = prev;
 

	
 
	used = false;
 
	DEBUG(ms, cDebugCtorLevel , "I- at %3d%d[0x%x]", station, xy, xy);
 

	
 
	xy = INVALID_TILE;
 
	station = INVALID_STATION;
 
}
 

	
 

	
 
/** Low-level function for allocating a RoadStop on the pool */
 
RoadStop *RoadStop::AllocateRaw( void )
 
{
 
	RoadStop *rs;
 

	
 
	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
 
	 * TODO - This is just a temporary stage, this will be removed. */
 
	for (rs = GetRoadStop(0); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) {
 
		if (!IsValidRoadStop(rs)) {
 
			RoadStopID index = rs->index;
 

	
 
			memset(rs, 0, sizeof(*rs));
 
			rs->index = index;
 

	
 
			return rs;
 
		}
 
	}
 

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

	
 
	return NULL;
 
}
src/station.h
Show inline comments
 
@@ -44,24 +44,38 @@ enum {
 
	ROAD_STOP_LIMIT = 16,
 
};
 

	
 
typedef struct RoadStop {
 
	TileIndex xy;
 
	bool used;
 
	byte status;
 
	RoadStopID index;
 
	byte num_vehicles;
 
	StationID station;
 
	struct RoadStop *next;
 
	struct RoadStop *prev;
 

	
 
	static const int cDebugCtorLevel = 3;
 

	
 
	RoadStop(TileIndex tile, StationID index);
 
	~RoadStop();
 

	
 
	void *operator new (size_t size);
 
	void operator delete(void *rs);
 

	
 
	/* For loading games */
 
	void *operator new (size_t size, int index);
 
	void operator delete(void *rs, int index);
 

	
 
	static RoadStop *AllocateRaw( void );
 
} RoadStop;
 

	
 
typedef struct StationSpecList {
 
	const StationSpec *spec;
 
	uint32 grfid;      /// GRF ID of this custom station
 
	uint8  localidx;   /// Station ID within GRF of station
 
} StationSpecList;
 

	
 
/** StationRect - used to track station spread out rectangle - cheaper than scanning whole map */
 
struct StationRect : public Rect {
 
	enum StationRectMode
 
	{
 
@@ -239,32 +253,24 @@ static inline bool IsValidStationID(Stat
 
/* Stuff for ROADSTOPS */
 

	
 
DECLARE_OLD_POOL(RoadStop, RoadStop, 5, 2000)
 

	
 
/**
 
 * Check if a RaodStop really exists.
 
 */
 
static inline bool IsValidRoadStop(const RoadStop *rs)
 
{
 
	return rs->used;
 
}
 

	
 
void DestroyRoadStop(RoadStop* rs);
 

	
 
static inline void DeleteRoadStop(RoadStop *rs)
 
{
 
	DestroyRoadStop(rs);
 
	rs->used = false;
 
}
 

	
 
#define FOR_ALL_ROADSTOPS_FROM(rs, start) for (rs = GetRoadStop(start); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) if (IsValidRoadStop(rs))
 
#define FOR_ALL_ROADSTOPS(rs) FOR_ALL_ROADSTOPS_FROM(rs, 0)
 

	
 
/* End of stuff for ROADSTOPS */
 

	
 

	
 
void AfterLoadStations(void);
 
void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile, int w, int h, int rad);
 
void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile, int w, int h, int rad);
 
uint GetStationPlatforms(const Station *st, TileIndex tile);
 
uint GetPlatformLength(TileIndex tile, DiagDirection dir);
 

	
src/station_cmd.cpp
Show inline comments
 
@@ -68,34 +68,24 @@ static void RoadStopPoolNewBlock(uint st
 

	
 
	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
 
	 * TODO - This is just a temporary stage, this will be removed. */
 
	for (rs = GetRoadStop(start_item); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) rs->index = start_item++;
 
}
 

	
 
DEFINE_OLD_POOL(Station, Station, StationPoolNewBlock, StationPoolCleanBlock)
 
DEFINE_OLD_POOL(RoadStop, RoadStop, RoadStopPoolNewBlock, NULL)
 

	
 

	
 
extern void UpdateAirplanesOnNewStation(Station *st);
 

	
 
static void InitializeRoadStop(RoadStop *road_stop, RoadStop *previous, TileIndex tile, StationID index)
 
{
 
	road_stop->xy = tile;
 
	road_stop->used = true;
 
	road_stop->status = 3; //stop is free
 
	road_stop->next = NULL;
 
	road_stop->prev = previous;
 
	road_stop->station = index;
 
	road_stop->num_vehicles = 0;
 
}
 

	
 
RoadStop* GetPrimaryRoadStop(const Station* st, RoadStopType type)
 
{
 
	switch (type) {
 
		case RS_BUS:   return st->bus_stops;
 
		case RS_TRUCK: return st->truck_stops;
 
		default: NOT_REACHED();
 
	}
 

	
 
	return NULL;
 
}
 

	
 
@@ -113,46 +103,24 @@ RoadStop* GetRoadStopByTile(TileIndex ti
 

	
 
uint GetNumRoadStopsInStation(const Station* st, RoadStopType type)
 
{
 
	uint num = 0;
 
	const RoadStop *rs;
 

	
 
	assert(st != NULL);
 
	for (rs = GetPrimaryRoadStop(st, type); rs != NULL; rs = rs->next) num++;
 

	
 
	return num;
 
}
 

	
 
RoadStop *AllocateRoadStop(void)
 
{
 
	RoadStop *rs;
 

	
 
	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
 
	 * TODO - This is just a temporary stage, this will be removed. */
 
	for (rs = GetRoadStop(0); rs != NULL; rs = (rs->index + 1U < GetRoadStopPoolSize()) ? GetRoadStop(rs->index + 1U) : NULL) {
 
		if (!IsValidRoadStop(rs)) {
 
			RoadStopID index = rs->index;
 

	
 
			memset(rs, 0, sizeof(*rs));
 
			rs->index = index;
 

	
 
			return rs;
 
		}
 
	}
 

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

	
 
	return NULL;
 
}
 

	
 
/* Calculate the radius of the station. Basicly it is the biggest
 
 *  radius that is available within the station */
 
static uint FindCatchmentRadius(const Station* st)
 
{
 
	CatchmentAera ret = CA_NONE;
 

	
 
	if (st->bus_stops != NULL)   ret = max(ret, CA_BUS);
 
	if (st->truck_stops != NULL) ret = max(ret, CA_TRUCK);
 
	if (st->train_tile) ret = max(ret, CA_TRAIN);
 
	if (st->dock_tile)  ret = max(ret, CA_DOCK);
 

	
 
@@ -1384,25 +1352,25 @@ int32 CmdBuildRoadStop(TileIndex tile, u
 
	cost = ret;
 

	
 
	st = GetStationAround(tile, 1, 1, INVALID_STATION);
 
	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 

	
 
	/* Find a station close to us */
 
	if (st == NULL) {
 
		st = GetClosestStationFromTile(tile, 8, _current_player);
 
		if (st != NULL && st->facilities != 0) st = NULL;
 
	}
 

	
 
	//give us a road stop in the list, and check if something went wrong
 
	road_stop = AllocateRoadStop();
 
	road_stop = new RoadStop(tile, INVALID_STATION);
 
	if (road_stop == NULL) {
 
		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
 
	}
 

	
 
	if (st != NULL &&
 
			GetNumRoadStopsInStation(st, RS_BUS) + GetNumRoadStopsInStation(st, RS_TRUCK) >= ROAD_STOP_LIMIT) {
 
		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
 
	}
 

	
 
	/* In case of new station if DC_EXEC is NOT set we still need to create the station
 
	* to test if everything is OK. In this case we need to delete it before return. */
 
	std::auto_ptr<Station> st_auto_delete;
 
@@ -1434,25 +1402,26 @@ int32 CmdBuildRoadStop(TileIndex tile, u
 
		}
 

	
 
		st->sign.width_1 = 0;
 
	}
 

	
 
	cost += (type) ? _price.build_truck_station : _price.build_bus_station;
 

	
 
	if (flags & DC_EXEC) {
 
		//point to the correct item in the _busstops or _truckstops array
 
		*currstop = road_stop;
 

	
 
		//initialize an empty station
 
		InitializeRoadStop(road_stop, prev, tile, st->index);
 
		road_stop->prev = prev;
 
		road_stop->station = st->index;
 
		if (!st->facilities) st->xy = tile;
 
		st->facilities |= (type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP;
 
		st->owner = _current_player;
 

	
 
		st->build_date = _date;
 

	
 
		st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
 

	
 
		MakeRoadStop(tile, st->owner, st->index, type ? RS_TRUCK : RS_BUS, (DiagDirection)p1);
 

	
 
		UpdateStationVirtCoordDirty(st);
 
		UpdateStationAcceptance(st, false);
 
@@ -1490,25 +1459,25 @@ static int32 RemoveRoadStop(Station *st,
 
	if (flags & DC_EXEC) {
 
		//we only had one stop left
 
		if (cur_stop->next == NULL && cur_stop->prev == NULL) {
 
			//so we remove ALL stops
 
			*primary_stop = NULL;
 
			st->facilities &= (is_truck) ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP;
 
		} else if (cur_stop == *primary_stop) {
 
			//removed the first stop in the list
 
			//need to set the primary element to the next stop
 
			*primary_stop = (*primary_stop)->next;
 
		}
 

	
 
		DeleteRoadStop(cur_stop);
 
		delete cur_stop;
 
		DoClearSquare(tile);
 
		st->rect.AfterRemoveTile(st, tile);
 

	
 
		UpdateStationVirtCoordDirty(st);
 
		DeleteStationIfEmpty(st);
 
	}
 

	
 
	return (is_truck) ? _price.remove_truck_station : _price.remove_bus_station;
 
}
 

	
 

	
 

	
 
@@ -2347,45 +2316,24 @@ static uint32 VehicleEnter_Station(Vehic
 
					v->u.road.state += 2;
 
				}
 

	
 
				// mark the station as busy
 
				SETBIT(rs->status, 7);
 
			}
 
		}
 
	}
 

	
 
	return 0;
 
}
 

	
 
/**
 
 * Cleanup a RoadStop. Make sure no vehicles try to go to this roadstop.
 
 */
 
void DestroyRoadStop(RoadStop* rs)
 
{
 
	Vehicle *v;
 

	
 
	/* Clear the slot assignment of all vehicles heading for this road stop */
 
	if (rs->num_vehicles != 0) {
 
		FOR_ALL_VEHICLES(v) {
 
			if (v->type == VEH_Road && v->u.road.slot == rs) {
 
				ClearSlot(v);
 
			}
 
		}
 
	}
 
	assert(rs->num_vehicles == 0);
 

	
 
	if (rs->prev != NULL) rs->prev->next = rs->next;
 
	if (rs->next != NULL) rs->next->prev = rs->prev;
 
}
 

	
 

	
 
void DeleteAllPlayerStations(void)
 
{
 
	Station *st;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (IsValidPlayer(st->owner)) delete st;
 
	}
 
}
 

	
 
/* this function is called for one station each tick */
 
static void StationHandleBigTick(Station *st)
 
@@ -3050,63 +2998,57 @@ static void Load_STNS(void)
 
			uint w = GB(st->trainst_w, 4, 4);
 
			uint h = GB(st->trainst_w, 0, 4);
 

	
 
			if (GetRailStationAxis(st->train_tile) == AXIS_Y) uintswap(w, h);
 
			st->trainst_w = w;
 
			st->trainst_h = h;
 
		}
 

	
 
		/* In older versions, we had just 1 tile for a bus/lorry, now we have more..
 
		 *  convert, if needed */
 
		if (CheckSavegameVersion(6)) {
 
			if (st->bus_tile_obsolete != 0) {
 
				st->bus_stops = AllocateRoadStop();
 
				st->bus_stops = new RoadStop(st->bus_tile_obsolete, st->index);
 
				if (st->bus_stops == NULL)
 
					error("Station: too many busstations in savegame");
 

	
 
				InitializeRoadStop(st->bus_stops, NULL, st->bus_tile_obsolete, st->index);
 
			}
 
			if (st->lorry_tile_obsolete != 0) {
 
				st->truck_stops = AllocateRoadStop();
 
				st->truck_stops = new RoadStop(st->lorry_tile_obsolete, st->index);
 
				if (st->truck_stops == NULL)
 
					error("Station: too many truckstations in savegame");
 

	
 
				InitializeRoadStop(st->truck_stops, NULL, st->lorry_tile_obsolete, st->index);
 
			}
 
		}
 
	}
 

	
 
	/* This is to ensure all pointers are within the limits of _stations_size */
 
	if (_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
 
}
 

	
 
static void Save_ROADSTOP(void)
 
{
 
	RoadStop *rs;
 

	
 
	FOR_ALL_ROADSTOPS(rs) {
 
		SlSetArrayIndex(rs->index);
 
		SlObject(rs, _roadstop_desc);
 
	}
 
}
 

	
 
static void Load_ROADSTOP(void)
 
{
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		RoadStop *rs;
 

	
 
		if (!AddBlockIfNeeded(&_RoadStop_pool, index))
 
			error("RoadStops: failed loading savegame: too many RoadStops");
 

	
 
		rs = GetRoadStop(index);
 
		RoadStop *rs = new (index) RoadStop(INVALID_TILE, INVALID_STATION);
 

	
 
		SlObject(rs, _roadstop_desc);
 
	}
 
}
 

	
 
extern const ChunkHandler _station_chunk_handlers[] = {
 
	{ 'STNS', Save_STNS,      Load_STNS,      CH_ARRAY },
 
	{ 'ROAD', Save_ROADSTOP,  Load_ROADSTOP,  CH_ARRAY | CH_LAST},
 
};
 

	
 

	
0 comments (0 inline, 0 general)