From 9f65c1b8f09b0fce75fc87b41eb565096f1c5adf Mon Sep 17 00:00:00 2001 From: rubidium Date: Thu, 24 Apr 2008 11:48:09 +0000 Subject: [PATCH] (svn r12864) [0.6] -Backport from trunk r12859, r12857, r12855, r12845, r12844: - Fix: Make the town rating tests use less memory and much quicker (r12859) - Fix: Usage of AutoPtr made (trying to) build stuff very expensive (r12857, r12855) - Fix: Use YAPF for fairly old savegames from before YAPF was introduced (r12845) - Fix: The industry tick trigger should only be triggered once every 256 ticks, not every tick... Also bail out of the triggers a little earlier if you know they are not going to happen anyway (r12844) --- projects/openttd_vs80.vcproj | 8 -- projects/openttd_vs90.vcproj | 8 -- source.list | 2 - src/engine.cpp | 9 +-- src/group_cmd.cpp | 11 +-- src/industry_cmd.cpp | 18 +++-- src/misc/autocopyptr.hpp | 85 -------------------- src/misc/autoptr.hpp | 106 ------------------------- src/newgrf_house.cpp | 2 + src/newgrf_industrytiles.cpp | 2 + src/newgrf_station.cpp | 2 +- src/oldpool.h | 22 ++++++ src/openttd.cpp | 4 +- src/rail_cmd.cpp | 8 +- src/road_cmd.cpp | 7 +- src/ship_cmd.cpp | 1 - src/signs.cpp | 7 +- src/station_cmd.cpp | 146 ++++++++++++----------------------- src/town_cmd.cpp | 33 ++++---- src/water_cmd.cpp | 7 +- src/waypoint.cpp | 56 +++++++------- 21 files changed, 146 insertions(+), 398 deletions(-) delete mode 100644 src/misc/autocopyptr.hpp delete mode 100644 src/misc/autoptr.hpp diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 5327d8e360..4d40e3f7ec 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -2075,14 +2075,6 @@ RelativePath=".\..\src\misc\array.hpp" > - - - - diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 3447d0f62f..2db8b459dc 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -2072,14 +2072,6 @@ RelativePath=".\..\src\misc\array.hpp" > - - - - diff --git a/source.list b/source.list index c209f3f028..952e8e3d35 100644 --- a/source.list +++ b/source.list @@ -439,8 +439,6 @@ water_map.h # Misc misc/array.hpp -misc/autocopyptr.hpp -misc/autoptr.hpp misc/binaryheap.hpp misc/blob.hpp misc/countedptr.hpp diff --git a/src/engine.cpp b/src/engine.cpp index 699486c1eb..d9c3c76857 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -16,7 +16,6 @@ #include "aircraft.h" #include "newgrf_cargo.h" #include "group.h" -#include "misc/autoptr.hpp" #include "strings_func.h" #include "gfx_func.h" #include "functions.h" @@ -516,19 +515,15 @@ CommandCost AddEngineReplacement(EngineRenewList *erl, EngineID old_engine, Engi return CommandCost(); } - er = new EngineRenew(old_engine, new_engine); - if (er == NULL) return CMD_ERROR; - AutoPtrT er_auto_delete = er; - + if (!EngineRenew::CanAllocateItem()) return CMD_ERROR; if (flags & DC_EXEC) { + er = new EngineRenew(old_engine, new_engine); er->group_id = group; /* Insert before the first element */ er->next = (EngineRenew *)(*erl); *erl = (EngineRenewList)er; - - er_auto_delete.Detach(); } return CommandCost(); diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 84aa0b39e2..be3348f0a0 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -12,7 +12,6 @@ #include "train.h" #include "aircraft.h" #include "vehicle_gui.h" -#include "misc/autoptr.hpp" #include "strings_func.h" #include "functions.h" #include "window_func.h" @@ -92,20 +91,14 @@ CommandCost CmdCreateGroup(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) VehicleType vt = (VehicleType)p1; if (!IsPlayerBuildableVehicleType(vt)) return CMD_ERROR; - AutoPtrT g_auto_delete; - - Group *g = new Group(_current_player); - if (g == NULL) return CMD_ERROR; - - g_auto_delete = g; + if (!Group::CanAllocateItem()) return CMD_ERROR; if (flags & DC_EXEC) { + Group *g = new Group(_current_player); g->replace_protection = false; g->vehicle_type = vt; InvalidateWindowData(GetWCForVT(vt), (vt << 11) | VLW_GROUP_LIST | _current_player); - - g_auto_delete.Detach(); } return CommandCost(); diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 7b8d840e9a..2a454bf1a1 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -25,7 +25,6 @@ #include "newgrf_industries.h" #include "newgrf_industrytiles.h" #include "newgrf_callbacks.h" -#include "misc/autoptr.hpp" #include "autoslope.h" #include "transparency.h" #include "water.h" @@ -1025,6 +1024,9 @@ static void ProduceIndustryGoods(Industry *i) if (cut) ChopLumberMillTrees(i); } + + TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK); + StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK); } } @@ -1046,8 +1048,6 @@ void OnTick_Industry() if (_game_mode == GM_EDITOR) return; FOR_ALL_INDUSTRIES(i) { - TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK); - StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK); ProduceIndustryGoods(i); } } @@ -1583,17 +1583,19 @@ static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL; if (!CheckSuitableIndustryPos(tile)) return NULL; - Industry *i = new Industry(tile); - if (i == NULL) return NULL; - AutoPtrT i_auto_delete = i; + if (!Industry::CanAllocateItem()) return NULL; if (flags & DC_EXEC) { + Industry *i = new Industry(tile); if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type); DoCreateNewIndustry(i, tile, type, it, itspec_index, t, OWNER_NONE); - i_auto_delete.Detach(); + + return i; } - return i; + /* We need to return a non-NULL pointer to tell we have created an industry. + * However, we haven't created a real one (no DC_EXEC), so return a fake one. */ + return GetIndustry(0); } /** Build/Fund an industry diff --git a/src/misc/autocopyptr.hpp b/src/misc/autocopyptr.hpp deleted file mode 100644 index 0c684aac26..0000000000 --- a/src/misc/autocopyptr.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* $Id$ */ - -/** @file autocopyptr.hpp */ - -#ifndef AUTOCOPYPTR_HPP -#define AUTOCOPYPTR_HPP - -#if 0 // reenable when needed -/** CAutoCopyPtrT - kind of CoW (Copy on Write) pointer. - * It is non-invasive smart pointer (reference counter is held outside - * of Tdata). - * When copied, its new copy shares the same underlaying structure Tdata. - * When dereferenced, its behaviour depends on 2 factors: - * - whether the data is shared (used by more than one pointer) - * - type of access (read/write) - * When shared pointer is dereferenced for write, new clone of Tdata - * is made first. - * Can't be used for polymorphic data types (interfaces). - */ -template -class CAutoCopyPtrT { -protected: - typedef Tdata_ Tdata; - - struct CItem { - int m_ref_cnt; ///< reference counter - Tdata m_data; ///< custom data itself - - FORCEINLINE CItem() : m_ref_cnt(1) {}; - FORCEINLINE CItem(const Tdata& data) : m_ref_cnt(1), m_data(data) {}; - FORCEINLINE CItem(const CItem& src) : m_ref_cnt(1), m_data(src.m_data) {}; - }; - - mutable CItem* m_pI; ///< points to the ref-counted data - -public: - FORCEINLINE CAutoCopyPtrT() : m_pI(NULL) {}; - FORCEINLINE CAutoCopyPtrT(const Tdata& data) : m_pI(new CItem(data)) {}; - FORCEINLINE CAutoCopyPtrT(const CAutoCopyPtrT& src) : m_pI(src.m_pI) {if (m_pI != NULL) m_pI->m_ref_cnt++;} - FORCEINLINE ~CAutoCopyPtrT() {if (m_pI == NULL || (--m_pI->m_ref_cnt) > 0) return; delete m_pI; m_pI = NULL;} - - /** data accessor (read only) */ - FORCEINLINE const Tdata& GetDataRO() const {if (m_pI == NULL) m_pI = new CItem(); return m_pI->m_data;} - /** data accessor (read / write) */ - FORCEINLINE Tdata& GetDataRW() {CloneIfShared(); if (m_pI == NULL) m_pI = new CItem(); return m_pI->m_data;} - - /** clone data if it is shared */ - FORCEINLINE void CloneIfShared() - { - if (m_pI != NULL && m_pI->m_ref_cnt > 1) { - // we share data item with somebody, clone it to become an exclusive owner - CItem* pNewI = new CItem(*m_pI); - m_pI->m_ref_cnt--; - m_pI = pNewI; - } - } - - /** assign pointer from the other one (maintaining ref counts) */ - FORCEINLINE void Assign(const CAutoCopyPtrT& src) - { - if (m_pI == src.m_pI) return; - if (m_pI != NULL && (--m_pI->m_ref_cnt) <= 0) delete m_pI; - m_pI = src.m_pI; - if (m_pI != NULL) m_pI->m_ref_cnt++; - } - - /** dereference operator (read only) */ - FORCEINLINE const Tdata* operator -> () const {return &GetDataRO();} - /** dereference operator (read / write) */ - FORCEINLINE Tdata* operator -> () {return &GetDataRW();} - - /** assignment operator */ - FORCEINLINE CAutoCopyPtrT& operator = (const CAutoCopyPtrT& src) {Assign(src); return *this;} - - /** forwarding 'lower then' operator to the underlaying items */ - FORCEINLINE bool operator < (const CAutoCopyPtrT& other) const - { - assert(m_pI != NULL); - assert(other.m_pI != NULL); - return (m_pI->m_data) < (other.m_pI->m_data); - } -}; - -#endif /* 0 */ -#endif /* AUTOCOPYPTR_HPP */ diff --git a/src/misc/autoptr.hpp b/src/misc/autoptr.hpp deleted file mode 100644 index 8b0d920f5a..0000000000 --- a/src/misc/autoptr.hpp +++ /dev/null @@ -1,106 +0,0 @@ -/* $Id$ */ - -/** @file autoptr.hpp */ - -#ifndef AUTOPTR_HPP -#define AUTOPTR_HPP - -/** AutoPtrT - kind of smart pointer that ensures the owned object gets - * deleted when its pointer goes out of scope. - * It is non-invasive smart pointer (no reference counter). - * When copied, the copy takes ownership of underlying object - * and original becomes NULL! - * Can be used also for polymorphic data types (interfaces). - */ -template -class AutoPtrT { -public: - typedef T obj_t; - -protected: - mutable T* m_p; ///< points to the data - -public: - FORCEINLINE AutoPtrT() - : m_p(NULL) - {}; - - FORCEINLINE AutoPtrT(const AutoPtrT& src) - : m_p(src.m_p) - { - if (m_p != NULL) src.m_p = NULL; - }; - - FORCEINLINE AutoPtrT(T *p) - : m_p(p) - {} - - FORCEINLINE ~AutoPtrT() - { - if (m_p != NULL) { - T *p = m_p; - m_p = NULL; - delete p; - } - } - - /** give-up ownership and NULLify the raw pointer */ - FORCEINLINE T* Detach() - { - T* p = m_p; - m_p = NULL; - return p; - } - - /** raw-pointer cast operator (read only) */ - FORCEINLINE operator const T* () const - { - return m_p; - } - - /** raw-pointer cast operator */ - FORCEINLINE operator T* () - { - return m_p; - } - - /** dereference operator (read only) */ - FORCEINLINE const T* operator -> () const - { - assert(m_p != NULL); - return m_p; - } - - /** dereference operator (read / write) */ - FORCEINLINE T* operator -> () - { - assert(m_p != NULL); - return m_p; - } - - /** assignment operator */ - FORCEINLINE AutoPtrT& operator = (const AutoPtrT& src) - { - /* Save original pointer and replace it with the given one to avoid recursive calls. */ - T* p = m_p; - m_p = src.m_p; - - if (m_p != NULL) src.m_p = NULL; - - if (p != NULL) { - /* Now we can safely delete the old one. */ - delete p; - } - return *this; - } - - /** forwarding 'lower than' operator to the underlaying items */ - FORCEINLINE bool operator < (const AutoPtrT& other) const - { - assert(m_p != NULL); - assert(other.m_p != NULL); - return (*m_p) < (*other.m_p); - } -}; - -#endif /* AUTOPTR_HPP */ diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp index 251207c195..1e6178650f 100644 --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -541,6 +541,8 @@ static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_rando HouseID hid = GetHouseType(tile); HouseSpec *hs = GetHouseSpecs(hid); + if (hs->spritegroup == NULL) return; + NewHouseResolver(&object, hid, tile, GetTownByTile(tile)); object.callback = CBID_RANDOM_TRIGGER; diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index 4b229f7e3b..9032b95634 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -403,6 +403,8 @@ static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, I IndustryGfx gfx = GetIndustryGfx(tile); const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); + if (itspec->grf_prop.spritegroup == NULL) return; + NewIndustryTileResolver(&object, gfx, tile, ind); object.callback = CBID_RANDOM_TRIGGER; diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index aefef9ed1e..f3e083d2ea 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -665,7 +665,7 @@ int AllocateSpecToStation(const StationSpec *statspec, Station *st, bool exec) { uint i; - if (statspec == NULL) return 0; + if (statspec == NULL || st == NULL) return 0; /* Check if this spec has already been allocated */ for (i = 1; i < st->num_specs && i < MAX_SPECLIST; i++) { diff --git a/src/oldpool.h b/src/oldpool.h index 1bcd41f8c7..e9ec3591a3 100644 --- a/src/oldpool.h +++ b/src/oldpool.h @@ -317,6 +317,28 @@ protected: { return Tpool->CleaningPool(); } + +public: + /** + * Check whether we can allocate an item in this pool. This to prevent the + * need to actually construct the object and then destructing it again, + * which could be *very* costly. + * @return true if and only if at least ONE item can be allocated. + */ + static inline bool CanAllocateItem() + { + uint last_minus_one = Tpool->GetSize() - 1; + + for (T *t = Tpool->Get(Tpool->first_free_index); t != NULL; t = (t->index < last_minus_one) ? Tpool->Get(t->index + 1U) : NULL) { + if (!t->IsValid()) return true; + Tpool->first_free_index = t->index; + } + + /* Check if we can add a block to the pool */ + if (Tpool->AddBlockToPool()) return CanAllocateItem(); + + return false; + } }; diff --git a/src/openttd.cpp b/src/openttd.cpp index d4dc25aaac..a27e7bc365 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -2402,13 +2402,13 @@ bool AfterLoadGame() } /* Convert old PF settings to new */ - if (_patches.yapf.rail_use_yapf) { + if (_patches.yapf.rail_use_yapf || CheckSavegameVersion(28)) { _patches.pathfinder_for_trains = VPF_YAPF; } else { _patches.pathfinder_for_trains = (_patches.new_pathfinding_all ? VPF_NPF : VPF_NTP); } - if (_patches.yapf.road_use_yapf) { + if (_patches.yapf.road_use_yapf || CheckSavegameVersion(28)) { _patches.pathfinder_for_roadvehs = VPF_YAPF; } else { _patches.pathfinder_for_roadvehs = (_patches.new_pathfinding_all ? VPF_NPF : VPF_OPF); diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 724a7213db..b979225ca1 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -30,7 +30,6 @@ #include "newgrf_callbacks.h" #include "newgrf_station.h" #include "train.h" -#include "misc/autoptr.hpp" #include "variables.h" #include "autoslope.h" #include "transparency.h" @@ -763,12 +762,10 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); - Depot *d = new Depot(tile); - - if (d == NULL) return CMD_ERROR; - AutoPtrT d_auto_delete = d; + if (!Depot::CanAllocateItem()) return CMD_ERROR; if (flags & DC_EXEC) { + Depot *d = new Depot(tile); MakeRailDepot(tile, _current_player, dir, (RailType)p1); MarkTileDirtyByTile(tile); @@ -776,7 +773,6 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_player); YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); - d_auto_delete.Detach(); } return cost.AddCost(_price.build_train_depot); diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 0f321dfb69..0f8f711019 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -22,7 +22,6 @@ #include "newgrf.h" #include "station_map.h" #include "tunnel_map.h" -#include "misc/autoptr.hpp" #include "variables.h" #include "autoslope.h" #include "transparency.h" @@ -805,16 +804,14 @@ CommandCost CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); - Depot *dep = new Depot(tile); - if (dep == NULL) return CMD_ERROR; - AutoPtrT d_auto_delete = dep; + if (!Depot::CanAllocateItem()) return CMD_ERROR; if (flags & DC_EXEC) { + Depot *dep = new Depot(tile); dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index; MakeRoadDepot(tile, _current_player, dir, rt); MarkTileDirtyByTile(tile); - d_auto_delete.Detach(); } return cost.AddCost(_price.build_road_depot); } diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index dea4d22962..ce83f898d5 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -27,7 +27,6 @@ #include "newgrf_text.h" #include "newgrf_sound.h" #include "spritecache.h" -#include "misc/autoptr.hpp" #include "strings_func.h" #include "functions.h" #include "window_func.h" diff --git a/src/signs.cpp b/src/signs.cpp index 7444bf0246..c753daf81c 100644 --- a/src/signs.cpp +++ b/src/signs.cpp @@ -10,7 +10,6 @@ #include "saveload.h" #include "command_func.h" #include "variables.h" -#include "misc/autoptr.hpp" #include "strings_func.h" #include "viewport_func.h" #include "zoom_func.h" @@ -97,12 +96,11 @@ static void MarkSignDirty(Sign *si) CommandCost CmdPlaceSign(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { /* Try to locate a new sign */ - Sign *si = new Sign(_current_player); - if (si == NULL) return_cmd_error(STR_2808_TOO_MANY_SIGNS); - AutoPtrT s_auto_delete = si; + if (!Sign::CanAllocateItem()) return_cmd_error(STR_2808_TOO_MANY_SIGNS); /* When we execute, really make the sign */ if (flags & DC_EXEC) { + Sign *si = new Sign(_current_player); int x = TileX(tile) * TILE_SIZE; int y = TileY(tile) * TILE_SIZE; @@ -115,7 +113,6 @@ CommandCost CmdPlaceSign(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) _sign_sort_dirty = true; _new_sign_id = si->index; _total_signs++; - s_auto_delete.Detach(); } return CommandCost(); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index c7c0ec5376..5603123913 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -27,7 +27,6 @@ #include "newgrf_callbacks.h" #include "newgrf_station.h" #include "yapf/yapf.h" -#include "misc/autoptr.hpp" #include "road_type.h" #include "road_internal.h" /* For drawing catenary/checking road removal */ #include "cargotype.h" @@ -239,7 +238,7 @@ enum StationNaming { STATIONNAMING_HELIPORT, }; -static bool GenerateStationName(Station *st, TileIndex tile, int flag) +static void GenerateStationName(Station *st, TileIndex tile, int flag) { static const uint32 _gen_station_name_bits[] = { 0, /* 0 */ @@ -344,7 +343,6 @@ static bool GenerateStationName(Station *st, TileIndex tile, int flag) done: st->string_id = found + STR_SV_STNAME; - return true; } #undef M @@ -966,10 +964,6 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, /* See if there is a deleted station close to us. */ if (st == NULL) st = GetClosestStationFromTile(tile_org); - /* 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. */ - AutoPtrT st_auto_delete; - if (st != NULL) { /* Reuse an existing station. */ if (st->owner != _current_player) @@ -987,17 +981,17 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, if (!st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TEST)) return CMD_ERROR; } else { /* allocate and initialize new station */ - st = new Station(tile_org); - if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); + if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); - /* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */ - st_auto_delete = st; + if (flags & DC_EXEC) { + st = new Station(); - st->town = ClosestTownFromTile(tile_org, (uint)-1); - if (!GenerateStationName(st, tile_org, STATIONNAMING_RAIL)) return CMD_ERROR; + st->town = ClosestTownFromTile(tile_org, (uint)-1); + GenerateStationName(st, tile_org, STATIONNAMING_RAIL); - if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) { - SetBit(st->town->have_ratings, _current_player); + if (IsValidPlayer(_current_player)) { + SetBit(st->town->have_ratings, _current_player); + } } } @@ -1082,8 +1076,6 @@ CommandCost CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, RebuildStationLists(); InvalidateWindow(WC_STATION_LIST, st->owner); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS); - /* success, so don't delete the new station */ - st_auto_delete.Detach(); } return cost; @@ -1388,23 +1380,13 @@ CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) if (st == NULL) st = GetClosestStationFromTile(tile); /* give us a road stop in the list, and check if something went wrong */ - RoadStop *road_stop = new RoadStop(tile); - if (road_stop == NULL) { - return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS); - } - - /* ensure that in case of error (or no DC_EXEC) the new road stop gets deleted upon return */ - AutoPtrT rs_auto_delete(road_stop); + if (!RoadStop::CanAllocateItem()) return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS); if (st != NULL && GetNumRoadStopsInStation(st, RoadStop::BUS) + GetNumRoadStopsInStation(st, RoadStop::TRUCK) >= RoadStop::LIMIT) { return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_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. */ - AutoPtrT st_auto_delete; - if (st != NULL) { if (st->owner != _current_player) { return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); @@ -1413,26 +1395,25 @@ CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) if (!st->rect.BeforeAddTile(tile, StationRect::ADD_TEST)) return CMD_ERROR; } else { /* allocate and initialize new station */ - st = new Station(tile); - if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); + if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); - /* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */ - st_auto_delete = st; + if (flags & DC_EXEC) { + st = new Station(); + st->town = ClosestTownFromTile(tile, (uint)-1); + GenerateStationName(st, tile, STATIONNAMING_ROAD); - Town *t = st->town = ClosestTownFromTile(tile, (uint)-1); - if (!GenerateStationName(st, tile, STATIONNAMING_ROAD)) return CMD_ERROR; - - if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) { - SetBit(t->have_ratings, _current_player); + if (IsValidPlayer(_current_player)) { + SetBit(st->town->have_ratings, _current_player); + } + st->sign.width_1 = 0; } - - st->sign.width_1 = 0; } cost.AddCost((type) ? _price.build_truck_station : _price.build_bus_station); if (flags & DC_EXEC) { + RoadStop *road_stop = new RoadStop(tile); /* Insert into linked list of RoadStops */ RoadStop **currstop = FindRoadStopSpot(type, st); *currstop = road_stop; @@ -1454,9 +1435,6 @@ CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) RebuildStationLists(); InvalidateWindow(WC_STATION_LIST, st->owner); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS); - /* success, so don't delete the new station and the new road stop */ - st_auto_delete.Detach(); - rs_auto_delete.Detach(); } return cost; } @@ -1711,10 +1689,6 @@ CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) return CMD_ERROR; } - /* 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. */ - AutoPtrT st_auto_delete; - if (st != NULL) { if (st->owner != _current_player) return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); @@ -1727,24 +1701,18 @@ CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) airport_upgrade = false; /* allocate and initialize new station */ - st = new Station(tile); - if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); + if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); - /* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */ - st_auto_delete = st; + if (flags & DC_EXEC) { + st = new Station(); - st->town = t; + st->town = ClosestTownFromTile(tile, (uint)-1); + GenerateStationName(st, tile, !(afc->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_HELIPORT : STATIONNAMING_AIRPORT); - if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) { - SetBit(t->have_ratings, _current_player); - } - - st->sign.width_1 = 0; - - /* If only helicopters may use the airport generate a helicopter related (5) - * station name, otherwise generate a normal airport name (1) */ - if (!GenerateStationName(st, tile, !(afc->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_HELIPORT : STATIONNAMING_AIRPORT)) { - return CMD_ERROR; + if (IsValidPlayer(_current_player)) { + SetBit(st->town->have_ratings, _current_player); + } + st->sign.width_1 = 0; } } @@ -1781,8 +1749,6 @@ CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) RebuildStationLists(); InvalidateWindow(WC_STATION_LIST, st->owner); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES); - /* success, so don't delete the new station */ - st_auto_delete.Detach(); } return cost; @@ -1851,18 +1817,18 @@ CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return_cmd_error(STR_304B_SITE_UNSUITABLE); /* allocate and initialize new station */ - Station *st = new Station(tile); - if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); - - /* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */ - AutoPtrT st_auto_delete(st); - - st->town = ClosestTownFromTile(tile, (uint)-1); - st->sign.width_1 = 0; - - if (!GenerateStationName(st, tile, STATIONNAMING_BUOY)) return CMD_ERROR; + if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); if (flags & DC_EXEC) { + Station *st = new Station(); + + st->town = ClosestTownFromTile(tile, (uint)-1); + GenerateStationName(st, tile, STATIONNAMING_BUOY); + + if (IsValidPlayer(_current_player)) { + SetBit(st->town->have_ratings, _current_player); + } + st->sign.width_1 = 0; st->dock_tile = tile; st->facilities |= FACIL_DOCK; /* Buoys are marked in the Station struct by this flag. Yes, it is this @@ -1879,8 +1845,6 @@ CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) RebuildStationLists(); InvalidateWindow(WC_STATION_LIST, st->owner); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS); - /* success, so don't delete the new station */ - st_auto_delete.Detach(); } return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock); @@ -2006,10 +1970,6 @@ CommandCost CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) /* Find a station close to us */ if (st == NULL) st = GetClosestStationFromTile(tile); - /* 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. */ - AutoPtrT st_auto_delete; - if (st != NULL) { if (st->owner != _current_player) return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); @@ -2019,21 +1979,19 @@ CommandCost CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) if (st->dock_tile != 0) return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK); } else { /* allocate and initialize new station */ - st = new Station(tile); - if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); + /* allocate and initialize new station */ + if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); - /* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */ - st_auto_delete = st; + if (flags & DC_EXEC) { + st = new Station(); - Town *t = st->town = ClosestTownFromTile(tile, (uint)-1); + st->town = ClosestTownFromTile(tile, (uint)-1); + GenerateStationName(st, tile, STATIONNAMING_DOCK); - if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) { - SetBit(t->have_ratings, _current_player); + if (IsValidPlayer(_current_player)) { + SetBit(st->town->have_ratings, _current_player); + } } - - st->sign.width_1 = 0; - - if (!GenerateStationName(st, tile, STATIONNAMING_DOCK)) return CMD_ERROR; } if (flags & DC_EXEC) { @@ -2049,8 +2007,6 @@ CommandCost CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) RebuildStationLists(); InvalidateWindow(WC_STATION_LIST, st->owner); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS); - /* success, so don't delete the new station */ - st_auto_delete.Detach(); } return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock); } @@ -2848,11 +2804,7 @@ void BuildOilRig(TileIndex tile) st->town = ClosestTownFromTile(tile, (uint)-1); st->sign.width_1 = 0; - if (!GenerateStationName(st, tile, STATIONNAMING_OILRIG)) { - DEBUG(misc, 0, "Can't allocate station-name for oilrig at 0x%X, reverting to oilrig only", tile); - delete st; - return; - } + GenerateStationName(st, tile, STATIONNAMING_OILRIG); MakeOilrig(tile, st->index); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 35ffed7c33..2b074c99f1 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -31,7 +31,6 @@ #include "newgrf_house.h" #include "newgrf_commons.h" #include "newgrf_townname.h" -#include "misc/autoptr.hpp" #include "autoslope.h" #include "waypoint.h" #include "transparency.h" @@ -44,6 +43,8 @@ #include "table/sprites.h" #include "table/town_land.h" +#include + uint _total_towns; HouseSpec _house_specs[HOUSE_MAX]; @@ -1508,16 +1509,14 @@ CommandCost CmdBuildTown(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) return_cmd_error(STR_023A_TOO_MANY_TOWNS); /* Allocate town struct */ - Town *t = new Town(tile); - if (t == NULL) return_cmd_error(STR_023A_TOO_MANY_TOWNS); - AutoPtrT t_auto_delete = t; + if (!Town::CanAllocateItem()) return_cmd_error(STR_023A_TOO_MANY_TOWNS); /* Create the town */ if (flags & DC_EXEC) { + Town *t = new Town(tile); _generating_world = true; DoCreateTown(t, tile, townnameparts, (TownSizeMode)p2, p1); _generating_world = false; - t_auto_delete.Detach(); } return CommandCost(); } @@ -2410,14 +2409,14 @@ Town *ClosestTownFromTile(TileIndex tile, uint threshold) } static bool _town_rating_test = false; +std::map _town_test_ratings; void SetTownRatingTestMode(bool mode) { static int ref_count = 0; if (mode) { if (ref_count == 0) { - Town *t; - FOR_ALL_TOWNS(t) t->test_rating = t->ratings[_current_player]; + _town_test_ratings.empty(); } ref_count++; } else { @@ -2427,10 +2426,19 @@ void SetTownRatingTestMode(bool mode) _town_rating_test = !(ref_count == 0); } +static int GetRating(const Town *t) +{ + if (_town_rating_test) { + std::map::iterator it = _town_test_ratings.find(t); + if (it != _town_test_ratings.end()) { + return (*it).second; + } + } + return t->ratings[_current_player]; +} + void ChangeTownRating(Town *t, int add, int max) { - int rating; - /* if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff */ if (t == NULL || !IsValidPlayer(_current_player) || @@ -2440,8 +2448,7 @@ void ChangeTownRating(Town *t, int add, int max) SetBit(t->have_ratings, _current_player); - rating = _town_rating_test ? t->test_rating : t->ratings[_current_player]; - + int rating = GetRating(t); if (add < 0) { if (rating > max) { rating += add; @@ -2454,7 +2461,7 @@ void ChangeTownRating(Town *t, int add, int max) } } if (_town_rating_test) { - t->test_rating = rating; + _town_test_ratings[t] = rating; } else { t->ratings[_current_player] = rating; } @@ -2482,7 +2489,7 @@ bool CheckforTownRating(uint32 flags, Town *t, byte type) */ modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type]; - if ((_town_rating_test ? t->test_rating : t->ratings[_current_player]) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { + if (GetRating(t) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { SetDParam(0, t->index); _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; return false; diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index e41773e7e2..6852126987 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -23,7 +23,6 @@ #include "industry_map.h" #include "newgrf.h" #include "newgrf_canal.h" -#include "misc/autoptr.hpp" #include "transparency.h" #include "strings_func.h" #include "functions.h" @@ -196,18 +195,16 @@ CommandCost CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2 ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return CMD_ERROR; - Depot *depot = new Depot(tile); - if (depot == NULL) return CMD_ERROR; - AutoPtrT d_auto_delete = depot; + if (!Depot::CanAllocateItem()) return CMD_ERROR; if (flags & DC_EXEC) { + Depot *depot = new Depot(tile); depot->town_index = ClosestTownFromTile(tile, (uint)-1)->index; MakeShipDepot(tile, _current_player, DEPOT_NORTH, axis, wc1); MakeShipDepot(tile2, _current_player, DEPOT_SOUTH, axis, wc2); MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile2); - d_auto_delete.Detach(); } return CommandCost(EXPENSES_CONSTRUCTION, _price.build_ship_depot); diff --git a/src/waypoint.cpp b/src/waypoint.cpp index 08af0f310d..e0ecb22d61 100644 --- a/src/waypoint.cpp +++ b/src/waypoint.cpp @@ -18,7 +18,6 @@ #include "variables.h" #include "yapf/yapf.h" #include "newgrf.h" -#include "misc/autoptr.hpp" #include "strings_func.h" #include "gfx_func.h" #include "functions.h" @@ -189,7 +188,6 @@ void AfterLoadWaypoints() CommandCost CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { Waypoint *wp; - AutoPtrT wp_auto_delete; Slope tileh; Axis axis; @@ -217,35 +215,34 @@ CommandCost CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint3 /* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */ wp = FindDeletedWaypointCloseTo(tile); - if (wp == NULL) { - wp = new Waypoint(tile); - if (wp == NULL) return CMD_ERROR; - - wp_auto_delete = wp; - - wp->town_index = INVALID_TOWN; - wp->name = NULL; - wp->town_cn = 0; - } else if (flags & DC_EXEC) { - /* Move existing (recently deleted) waypoint to the new location */ - - /* First we update the destination for all vehicles that - * have the old waypoint in their orders. */ - Vehicle *v; - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_TRAIN && - v->First() == v && - v->current_order.type == OT_GOTO_WAYPOINT && - v->dest_tile == wp->xy) { - v->dest_tile = tile; - } - } - - RedrawWaypointSign(wp); - wp->xy = tile; - } + if (wp == NULL && !Waypoint::CanAllocateItem()) return CMD_ERROR; if (flags & DC_EXEC) { + if (wp == NULL) { + wp = new Waypoint(tile); + + wp->town_index = INVALID_TOWN; + wp->name = NULL; + wp->town_cn = 0; + } else { + /* Move existing (recently deleted) waypoint to the new location */ + + /* First we update the destination for all vehicles that + * have the old waypoint in their orders. */ + Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_TRAIN && + v->First() == v && + v->current_order.type == OT_GOTO_WAYPOINT && + v->dest_tile == wp->xy) { + v->dest_tile = tile; + } + } + + RedrawWaypointSign(wp); + wp->xy = tile; + } + const StationSpec* statspec; MakeRailWaypoint(tile, GetTileOwner(tile), axis, GetRailType(tile), wp->index); @@ -272,7 +269,6 @@ CommandCost CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint3 UpdateWaypointSign(wp); RedrawWaypointSign(wp); YapfNotifyTrackLayoutChange(tile, AxisToTrack(axis)); - wp_auto_delete.Detach(); } return CommandCost(EXPENSES_CONSTRUCTION, _price.build_train_depot);