diff --git a/src/newgrf.cpp b/src/newgrf.cpp index f03fe35712..233085d1d5 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -451,6 +451,17 @@ GRFFile *GetFileByGRFID(uint32 grfid) return nullptr; } +/** + * Obtain a NewGRF file by its grfID, expect it to usually be the current GRF's grfID + * @param grfid The grfID to obtain the file for + * @return The file. + */ +GRFFile *GetFileByGRFIDExpectCurrent(uint32 grfid) +{ + if (_cur.grffile->grfid == grfid) return _cur.grffile; + return GetFileByGRFID(grfid); +} + /** * Obtain a NewGRF file by its filename * @param filename The filename to obtain the file for. @@ -11943,6 +11954,9 @@ void LoadNewGRF(uint load_index, uint num_baseset) /* Pseudo sprite processing is finished; free temporary stuff */ _cur.ClearDataForNextFile(); + for (GRFFile * const file : _grf_files) { + file->string_map.clear(); + } /* Call any functions that should be run after GRFs have been loaded. */ AfterLoadGRFs(); diff --git a/src/newgrf.h b/src/newgrf.h index 1ee20a8dd5..200443a904 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -348,6 +348,8 @@ struct GRFFile : ZeroedMemoryAllocator { byte ctrl_flags; ///< General GRF control flags + btree::btree_map string_map; ///< Map of local GRF string ID to string ID + GRFFile(const struct GRFConfig *config); ~GRFFile(); diff --git a/src/newgrf_text.cpp b/src/newgrf_text.cpp index 9ca7e89f74..432e5b75e2 100644 --- a/src/newgrf_text.cpp +++ b/src/newgrf_text.cpp @@ -573,23 +573,30 @@ StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid_to_add, bool ne } uint id; - for (id = 0; id < _num_grf_texts; id++) { - if (_grf_text[id].grfid == grfid && _grf_text[id].stringid == stringid) { - break; - } - } + extern GRFFile *GetFileByGRFIDExpectCurrent(uint32 grfid); + GRFFile *grf = GetFileByGRFIDExpectCurrent(grfid); + if (grf == nullptr) return STR_EMPTY; - /* Too many strings allocated, return empty */ - if (id == lengthof(_grf_text)) { - _grf_bug_too_many_strings = true; - return STR_EMPTY; + auto iter = grf->string_map.lower_bound(stringid); + if (iter != grf->string_map.end() && iter->first == stringid) { + /* Found */ + id = iter->second; + } else { + /* Allocate new ID */ + id = _num_grf_texts; + + /* Too many strings allocated, return empty */ + if (id == lengthof(_grf_text)) { + _grf_bug_too_many_strings = true; + return STR_EMPTY; + } + + grf->string_map.insert(iter, std::make_pair(stringid, id)); + _num_grf_texts++; } std::string newtext = TranslateTTDPatchCodes(grfid, langid_to_add, allow_newlines, text_to_add); - /* If we didn't find our stringid and grfid in the list, allocate a new id */ - if (id == _num_grf_texts) _num_grf_texts++; - if (_grf_text[id].textholder.empty()) { _grf_text[id].grfid = grfid; _grf_text[id].stringid = stringid;