diff --git a/src/economy.cpp b/src/economy.cpp index 95bffdc7bb..dcfb1e9b97 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -500,6 +500,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) delete tv; } } + ReindexTemplateReplacements(); } else { for (TemplateVehicle *tv : TemplateVehicle::Iterate()) { if (tv->owner == old_owner) tv->owner = new_owner; diff --git a/src/saveload/tbtr_template_replacement_sl.cpp b/src/saveload/tbtr_template_replacement_sl.cpp index 7b8019f7a0..fa349304d3 100644 --- a/src/saveload/tbtr_template_replacement_sl.cpp +++ b/src/saveload/tbtr_template_replacement_sl.cpp @@ -26,6 +26,7 @@ static void Load_TMPL_RPLS() TemplateReplacement *tr = new (index) TemplateReplacement(); SlObject(tr, _template_replacement_desc); } + ReindexTemplateReplacements(); } extern const ChunkHandler _template_replacement_chunk_handlers[] = { diff --git a/src/tbtr_template_gui_main.cpp b/src/tbtr_template_gui_main.cpp index 2f74b73029..741da77c3c 100644 --- a/src/tbtr_template_gui_main.cpp +++ b/src/tbtr_template_gui_main.cpp @@ -530,13 +530,12 @@ public: /** For a given group (id) find the template that is issued for template replacement for this group and return this template's index * from the gui list */ - short FindTemplateIndexForGroup(short gid) const + short FindTemplateIndex(TemplateID tid) const { - TemplateReplacement *tr = GetTemplateReplacementByGroupID(gid); - if (!tr) return -1; + if (tid == INVALID_TEMPLATE) return -1; for (uint32 i = 0; i < this->templates.size(); ++i) { - if (templates[i]->index == tr->sel_template) { + if (templates[i]->index == tid) { return i; } } @@ -603,19 +602,20 @@ public: StringID str = STR_GROUP_NAME; DrawString(left + ScaleGUITrad(30 + this->indents[i] * 10), right, text_y, str, TC_BLACK); + const TemplateID tid = GetTemplateIDByGroupID(g_id); + /* Draw the template in use for this group, if there is one */ - short template_in_use = FindTemplateIndexForGroup(g_id); + short template_in_use = FindTemplateIndex(tid); if (template_in_use >= 0) { SetDParam(0, template_in_use); DrawString (left, right, text_y, STR_TMPL_GROUP_USES_TEMPLATE, TC_BLACK, SA_HOR_CENTER); - } else if (GetTemplateReplacementByGroupID(g_id)) { /* If there isn't a template applied from the current group, check if there is one for another rail type */ + } else if (tid != INVALID_TEMPLATE) { /* If there isn't a template applied from the current group, check if there is one for another rail type */ DrawString (left, right, text_y, STR_TMPL_TMPLRPL_EX_DIFF_RAILTYPE, TC_SILVER, SA_HOR_CENTER); } /* Draw the number of trains that still need to be treated by the currently selected template replacement */ - const TemplateReplacement *tr = GetTemplateReplacementByGroupID(g_id); - if (tr) { - const TemplateVehicle *tv = TemplateVehicle::Get(tr->sel_template); + if (tid != INVALID_TEMPLATE) { + const TemplateVehicle *tv = TemplateVehicle::Get(tid); const int num_trains = NumTrainsNeedTemplateReplacement(g_id, tv); // Draw number SetDParam(0, num_trains); @@ -770,6 +770,8 @@ public: g_id = g->index; } + const TemplateID tid = GetTemplateIDByGroupID(g_id); + this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_EDIT, this->editInProgress || !selected_ok); this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_DELETE, this->editInProgress || !selected_ok); this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REUSE, this->editInProgress || !selected_ok); @@ -777,8 +779,8 @@ public: this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REFIT, this->editInProgress ||!selected_ok); this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_OLD_ONLY, this->editInProgress ||!selected_ok); - this->SetWidgetDisabledState(TRW_WIDGET_START, this->editInProgress || !(selected_ok && group_ok && FindTemplateIndexForGroup(g_id) != this->selected_template_index)); - this->SetWidgetDisabledState(TRW_WIDGET_STOP, this->editInProgress || !(group_ok && GetTemplateReplacementByGroupID(g_id) != nullptr)); + this->SetWidgetDisabledState(TRW_WIDGET_START, this->editInProgress || !(selected_ok && group_ok && FindTemplateIndex(tid) != this->selected_template_index)); + this->SetWidgetDisabledState(TRW_WIDGET_STOP, this->editInProgress || !(group_ok && tid != INVALID_TEMPLATE)); this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_DEFINE, this->editInProgress); this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CLONE, this->editInProgress); diff --git a/src/tbtr_template_vehicle.cpp b/src/tbtr_template_vehicle.cpp index b118f32725..74867507ae 100644 --- a/src/tbtr_template_vehicle.cpp +++ b/src/tbtr_template_vehicle.cpp @@ -48,6 +48,7 @@ INSTANTIATE_POOL_METHODS(Template) TemplateReplacementPool _template_replacement_pool("TemplateReplacementPool"); INSTANTIATE_POOL_METHODS(TemplateReplacement) +btree::btree_map _template_replacement_index; void TemplateVehicleImageDimensions::SetFromTrain(const Train *t) { @@ -127,8 +128,22 @@ int TemplateVehicle::Length() const return l; } +TemplateReplacement::~TemplateReplacement() +{ + if (CleaningPool()) return; + + _template_replacement_index.erase(this->Group()); +} + +void TemplateReplacement::PreCleanPool() +{ + _template_replacement_index.clear(); +} + TemplateReplacement* GetTemplateReplacementByGroupID(GroupID gid) { + if (GetTemplateIDByGroupID(gid) == INVALID_TEMPLATE) return nullptr; + for (TemplateReplacement *tr : TemplateReplacement::Iterate()) { if (tr->Group() == gid) { return tr; @@ -137,6 +152,13 @@ TemplateReplacement* GetTemplateReplacementByGroupID(GroupID gid) return nullptr; } +TemplateID GetTemplateIDByGroupID(GroupID gid) +{ + auto iter = _template_replacement_index.find(gid); + if (iter == _template_replacement_index.end()) return INVALID_TEMPLATE; + return iter->second; +} + bool IssueTemplateReplacement(GroupID gid, TemplateID tid) { TemplateReplacement *tr = GetTemplateReplacementByGroupID(gid); @@ -144,13 +166,15 @@ bool IssueTemplateReplacement(GroupID gid, TemplateID tid) if (tr) { /* Then set the new TemplateVehicle and return */ tr->SetTemplate(tid); + _template_replacement_index[gid] = tid; return true; } else if (TemplateReplacement::CanAllocateItem()) { tr = new TemplateReplacement(gid, tid); + _template_replacement_index[gid] = tid; return true; + } else { + return false; } - - else return false; } short TemplateVehicle::NumGroupsUsingTemplate() const @@ -166,6 +190,8 @@ short TemplateVehicle::NumGroupsUsingTemplate() const short DeleteTemplateReplacementsByGroupID(GroupID g_id) { + if (GetTemplateIDByGroupID(g_id) == INVALID_TEMPLATE) return 0; + short del_amount = 0; for (const TemplateReplacement *tr : TemplateReplacement::Iterate()) { if (tr->group == g_id) { @@ -175,3 +201,11 @@ short DeleteTemplateReplacementsByGroupID(GroupID g_id) } return del_amount; } + +void ReindexTemplateReplacements() +{ + _template_replacement_index.clear(); + for (const TemplateReplacement *tr : TemplateReplacement::Iterate()) { + _template_replacement_index[tr->group] = tr->sel_template; + } +} diff --git a/src/tbtr_template_vehicle.h b/src/tbtr_template_vehicle.h index 61fac5347d..6178137ce5 100644 --- a/src/tbtr_template_vehicle.h +++ b/src/tbtr_template_vehicle.h @@ -33,13 +33,13 @@ struct TemplateVehicle; struct TemplateReplacement; typedef uint16 TemplateID; - +static const TemplateID INVALID_TEMPLATE = 0xFFFF; static const uint16 CONSIST_HEAD = 0x0; static const uint16 CONSIST_TAIL = 0xffff; /** A pool allowing to store up to ~64k templates */ -typedef Pool TemplatePool; +typedef Pool TemplatePool; extern TemplatePool _template_pool; /// listing/sorting templates @@ -186,7 +186,7 @@ struct TemplateReplacement : TemplateReplacementPool::PoolItem<&_template_replac TemplateReplacement(GroupID gid, TemplateID tid) { this->group=gid; this->sel_template=tid; } TemplateReplacement() {} - ~TemplateReplacement() {} + ~TemplateReplacement(); inline GroupID Group() { return this->group; } inline GroupID Template() { return this->sel_template; } @@ -195,11 +195,16 @@ struct TemplateReplacement : TemplateReplacementPool::PoolItem<&_template_replac inline void SetTemplate(TemplateID tid) { this->sel_template = tid; } inline TemplateID GetTemplateVehicleID() { return sel_template; } + + static void PreCleanPool(); }; TemplateReplacement* GetTemplateReplacementByGroupID(GroupID); +TemplateID GetTemplateIDByGroupID(GroupID); bool IssueTemplateReplacement(GroupID, TemplateID); short DeleteTemplateReplacementsByGroupID(GroupID); +void ReindexTemplateReplacements(); + #endif /* TEMPLATE_VEH_H */ diff --git a/src/tbtr_template_vehicle_func.cpp b/src/tbtr_template_vehicle_func.cpp index aefac90080..d2a68b301f 100644 --- a/src/tbtr_template_vehicle_func.cpp +++ b/src/tbtr_template_vehicle_func.cpp @@ -204,12 +204,8 @@ Train* DeleteVirtualTrain(Train *chain, Train *to_del) { // retrieve template vehicle from template replacement that belongs to the given group TemplateVehicle* GetTemplateVehicleByGroupID(GroupID gid) { if (gid >= NEW_GROUP) return nullptr; - for (TemplateReplacement *tr : TemplateReplacement::Iterate()) { - if (tr->Group() == gid) { - return TemplateVehicle::GetIfValid(tr->Template()); // there can be only one - } - } - return nullptr; + const TemplateID tid = GetTemplateIDByGroupID(gid); + return tid != INVALID_TEMPLATE ? TemplateVehicle::GetIfValid(tid) : nullptr; } /** diff --git a/src/vehicle.cpp b/src/vehicle.cpp index e0e4251378..2197891ece 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1069,8 +1069,7 @@ void Vehicle::PreCleanPool() void VehicleEnteredDepotThisTick(Vehicle *v) { /* Template Replacement Setup stuff */ - TemplateReplacement *tr = GetTemplateReplacementByGroupID(v->group_id); - if (tr != nullptr) { + if (GetTemplateIDByGroupID(v->group_id) != INVALID_TEMPLATE) { /* Vehicle should stop in the depot if it was in 'stopping' state */ _vehicles_to_templatereplace.insert(v->index); }