mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r14753) -Fix (r1): after buying a company, one could have more vehicles with the same UnitID
This commit is contained in:
parent
b8d82cc28c
commit
53679122af
|
@ -363,25 +363,12 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int num_train = 0;
|
FreeUnitIDGenerator unitidgen[] = {
|
||||||
int num_road = 0;
|
FreeUnitIDGenerator(VEH_TRAIN, new_owner), FreeUnitIDGenerator(VEH_ROAD, new_owner),
|
||||||
int num_ship = 0;
|
FreeUnitIDGenerator(VEH_SHIP, new_owner), FreeUnitIDGenerator(VEH_AIRCRAFT, new_owner)
|
||||||
int num_aircraft = 0;
|
};
|
||||||
|
|
||||||
Vehicle *v;
|
Vehicle *v;
|
||||||
|
|
||||||
/* Determine Ids for the new vehicles */
|
|
||||||
FOR_ALL_VEHICLES(v) {
|
|
||||||
if (v->owner == new_owner) {
|
|
||||||
switch (v->type) {
|
|
||||||
case VEH_TRAIN: if (IsFrontEngine(v)) num_train++; break;
|
|
||||||
case VEH_ROAD: if (IsRoadVehFront(v)) num_road++; break;
|
|
||||||
case VEH_SHIP: num_ship++; break;
|
|
||||||
case VEH_AIRCRAFT: if (IsNormalAircraft(v)) num_aircraft++; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FOR_ALL_VEHICLES(v) {
|
FOR_ALL_VEHICLES(v) {
|
||||||
if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
|
if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
|
||||||
if (new_owner == INVALID_OWNER) {
|
if (new_owner == INVALID_OWNER) {
|
||||||
|
@ -391,13 +378,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
|
||||||
v->colormap = PAL_NONE;
|
v->colormap = PAL_NONE;
|
||||||
v->group_id = DEFAULT_GROUP;
|
v->group_id = DEFAULT_GROUP;
|
||||||
if (IsEngineCountable(v)) GetCompany(new_owner)->num_engines[v->engine_type]++;
|
if (IsEngineCountable(v)) GetCompany(new_owner)->num_engines[v->engine_type]++;
|
||||||
switch (v->type) {
|
if (v->IsPrimaryVehicle()) v->unitnumber = unitidgen[v->type].NextID();
|
||||||
case VEH_TRAIN: if (IsFrontEngine(v)) v->unitnumber = ++num_train; break;
|
|
||||||
case VEH_ROAD: if (IsRoadVehFront(v)) v->unitnumber = ++num_road; break;
|
|
||||||
case VEH_SHIP: v->unitnumber = ++num_ship; break;
|
|
||||||
case VEH_AIRCRAFT: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break;
|
|
||||||
default: NOT_REACHED();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "core/alloc_func.hpp"
|
#include "core/alloc_func.hpp"
|
||||||
#include "core/smallmap_type.hpp"
|
#include "core/smallmap_type.hpp"
|
||||||
#include "vehiclelist.h"
|
#include "vehiclelist.h"
|
||||||
|
#include "core/mem_func.hpp"
|
||||||
#include "depot_func.h"
|
#include "depot_func.h"
|
||||||
|
|
||||||
#include "table/sprites.h"
|
#include "table/sprites.h"
|
||||||
|
@ -1867,51 +1868,47 @@ VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y
|
||||||
return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
|
return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnitID GetFreeUnitNumber(VehicleType type)
|
FreeUnitIDGenerator::FreeUnitIDGenerator(VehicleType type, CompanyID owner) : cache(NULL), maxid(0), curid(0)
|
||||||
{
|
{
|
||||||
UnitID max = 0;
|
/* Find maximum */
|
||||||
const Vehicle *u;
|
const Vehicle *v;
|
||||||
static bool *cache = NULL;
|
FOR_ALL_VEHICLES(v) {
|
||||||
static UnitID gmax = 0;
|
if (v->type == type && v->owner == owner) {
|
||||||
|
this->maxid = max<UnitID>(this->maxid, v->unitnumber);
|
||||||
switch (type) {
|
}
|
||||||
case VEH_TRAIN: max = _settings_game.vehicle.max_trains; break;
|
|
||||||
case VEH_ROAD: max = _settings_game.vehicle.max_roadveh; break;
|
|
||||||
case VEH_SHIP: max = _settings_game.vehicle.max_ships; break;
|
|
||||||
case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break;
|
|
||||||
default: NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max == 0) {
|
if (this->maxid == 0) return;
|
||||||
/* we can't build any of this kind of vehicle, so we just return 1 instead of looking for a free number
|
|
||||||
* a max of 0 will cause the following code to write to a NULL pointer
|
|
||||||
* We know that 1 is bigger than the max allowed vehicle number, so it's the same as returning something, that is too big
|
|
||||||
*/
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max > gmax) {
|
this->maxid++; // so there is space for last item (with v->unitnumber == maxid)
|
||||||
gmax = max;
|
this->maxid++; // this one will always be free (well, it will fail when there are 65535 units, so this overflows)
|
||||||
free(cache);
|
|
||||||
cache = MallocT<bool>(max + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the cache */
|
this->cache = MallocT<bool>(this->maxid);
|
||||||
memset(cache, 0, (max + 1) * sizeof(*cache));
|
|
||||||
|
MemSetT(this->cache, 0, this->maxid);
|
||||||
|
|
||||||
/* Fill the cache */
|
/* Fill the cache */
|
||||||
FOR_ALL_VEHICLES(u) {
|
FOR_ALL_VEHICLES(v) {
|
||||||
if (u->type == type && u->owner == _current_company && u->unitnumber != 0 && u->unitnumber <= max)
|
if (v->type == type && v->owner == owner) {
|
||||||
cache[u->unitnumber] = true;
|
this->cache[v->unitnumber] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the first unused unit number */
|
UnitID FreeUnitIDGenerator::NextID()
|
||||||
UnitID unit = 1;
|
{
|
||||||
for (; unit <= max; unit++) {
|
if (this->maxid <= this->curid) return ++this->curid;
|
||||||
if (!cache[unit]) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return unit;
|
while (this->cache[++this->curid]) { } // it will stop, we reserved more space than needed
|
||||||
|
|
||||||
|
return this->curid;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitID GetFreeUnitNumber(VehicleType type)
|
||||||
|
{
|
||||||
|
FreeUnitIDGenerator gen(type, _current_company);
|
||||||
|
|
||||||
|
return gen.NextID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -647,6 +647,28 @@ static inline bool IsValidVehicleID(uint index)
|
||||||
return index < GetVehiclePoolSize() && GetVehicle(index)->IsValid();
|
return index < GetVehiclePoolSize() && GetVehicle(index)->IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Generates sequence of free UnitID numbers */
|
||||||
|
struct FreeUnitIDGenerator {
|
||||||
|
bool *cache; ///< array of occupied unit id numbers
|
||||||
|
UnitID maxid; ///< maximum ID at the moment of constructor call
|
||||||
|
UnitID curid; ///< last ID returned ; 0 if none
|
||||||
|
|
||||||
|
/** Initializes the structure. Vehicle unit numbers are supposed not to change after
|
||||||
|
* struct initialization, except after each call to this->NextID() the returned value
|
||||||
|
* is assigned to a vehicle.
|
||||||
|
* @param type type of vehicle
|
||||||
|
* @param owner owner of vehicles
|
||||||
|
*/
|
||||||
|
FreeUnitIDGenerator(VehicleType type, CompanyID owner);
|
||||||
|
|
||||||
|
/** Returns next free UnitID. Supposes the last returned value was assigned to a vehicle. */
|
||||||
|
UnitID NextID();
|
||||||
|
|
||||||
|
/** Releases allocated memory */
|
||||||
|
~FreeUnitIDGenerator() { free(this->cache); }
|
||||||
|
};
|
||||||
|
|
||||||
/* Returns order 'index' of a vehicle or NULL when it doesn't exists */
|
/* Returns order 'index' of a vehicle or NULL when it doesn't exists */
|
||||||
static inline Order *GetVehicleOrder(const Vehicle *v, int index)
|
static inline Order *GetVehicleOrder(const Vehicle *v, int index)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue