diff --git a/train_cmd.c b/train_cmd.c index ba350753d5..cfde2d7ea2 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -93,6 +93,9 @@ void TrainConsistChanged(Vehicle* v) const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); uint16 veh_len; + // Update the v->first cache. This is faster than having to brute force it later. + if (u->first == NULL) u->first = v; + // update the 'first engine' u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine; diff --git a/vehicle.c b/vehicle.c index 5c8a275de3..7dd32be539 100644 --- a/vehicle.c +++ b/vehicle.c @@ -218,6 +218,11 @@ void AfterLoadVehicles(void) FOR_ALL_VEHICLES(v) { v->first = NULL; + if (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v))) + TrainConsistChanged(v); + } + + FOR_ALL_VEHICLES(v) { if (v->type != 0) { switch (v->type) { case VEH_Train: v->cur_image = GetTrainImage(v, v->direction); break; @@ -234,9 +239,6 @@ void AfterLoadVehicles(void) v->left_coord = INVALID_COORD; VehiclePositionChanged(v); - - if (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v))) - TrainConsistChanged(v); } } } @@ -1999,19 +2001,41 @@ uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y) UnitID GetFreeUnitNumber(byte type) { - UnitID unit_num = 0; - Vehicle *u; + UnitID unit, max; + const Vehicle *u; + static bool *cache = NULL; + static UnitID gmax = 0; -restart: - unit_num++; - FOR_ALL_VEHICLES(u) { - if (u->type == type && u->owner == _current_player && - unit_num == u->unitnumber) - goto restart; + switch (type) { + case VEH_Train: max = _patches.max_trains; break; + case VEH_Road: max = _patches.max_roadveh; break; + case VEH_Ship: max = _patches.max_ships; break; + case VEH_Aircraft: max = _patches.max_aircraft; break; + default: assert(0); } - return unit_num; -} + if (max > gmax) { + gmax = max; + free(cache); + cache = malloc((max + 1) * sizeof(*cache)); + } + + // Clear the cache + memset(cache, 0, (max + 1) * sizeof(*cache)); + + // Fill the cache + FOR_ALL_VEHICLES(u) { + if (u->type == type && u->owner == _current_player && u->unitnumber != 0 && u->unitnumber <= max) + cache[u->unitnumber] = true; + } + + // Find the first unused unit number + for (unit = 1; unit <= max; unit++) { + if (!cache[unit]) break; + } + + return unit; +} // Save and load of vehicles const SaveLoad _common_veh_desc[] = {