mirror of https://github.com/OpenTTD/OpenTTD.git
Codechange: Use std:: features for NewGRF town names (#10631)
This removes manual memory (de-)allocation and list counting.
This commit is contained in:
parent
4491e45f3c
commit
d949cfab24
|
@ -7725,8 +7725,8 @@ static void FeatureTownName(ByteReader *buf)
|
|||
bool new_scheme = _cur.grffile->grf_version >= 7;
|
||||
|
||||
byte lang = buf->ReadByte();
|
||||
StringID style = STR_UNDEFINED;
|
||||
|
||||
byte nb_gen = townname->nb_gen;
|
||||
do {
|
||||
ClrBit(lang, 7);
|
||||
|
||||
|
@ -7735,53 +7735,48 @@ static void FeatureTownName(ByteReader *buf)
|
|||
std::string lang_name = TranslateTTDPatchCodes(grfid, lang, false, name);
|
||||
grfmsg(6, "FeatureTownName: lang 0x%X -> '%s'", lang, lang_name.c_str());
|
||||
|
||||
townname->name[nb_gen] = AddGRFString(grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
|
||||
style = AddGRFString(grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
|
||||
|
||||
lang = buf->ReadByte();
|
||||
} while (lang != 0);
|
||||
townname->id[nb_gen] = id;
|
||||
townname->nb_gen++;
|
||||
townname->styles.emplace_back(style, id);
|
||||
}
|
||||
|
||||
byte nb = buf->ReadByte();
|
||||
grfmsg(6, "FeatureTownName: %u parts", nb);
|
||||
uint8 parts = buf->ReadByte();
|
||||
grfmsg(6, "FeatureTownName: %u parts", parts);
|
||||
|
||||
townname->nbparts[id] = nb;
|
||||
townname->partlist[id] = CallocT<NamePartList>(nb);
|
||||
townname->partlists[id].reserve(parts);
|
||||
for (uint partnum = 0; partnum < parts; partnum++) {
|
||||
NamePartList &partlist = townname->partlists[id].emplace_back();
|
||||
uint8 texts = buf->ReadByte();
|
||||
partlist.bitstart = buf->ReadByte();
|
||||
partlist.bitcount = buf->ReadByte();
|
||||
partlist.maxprob = 0;
|
||||
grfmsg(6, "FeatureTownName: part %u contains %u texts and will use GB(seed, %u, %u)", partnum, texts, partlist.bitstart, partlist.bitcount);
|
||||
|
||||
for (int i = 0; i < nb; i++) {
|
||||
byte nbtext = buf->ReadByte();
|
||||
townname->partlist[id][i].bitstart = buf->ReadByte();
|
||||
townname->partlist[id][i].bitcount = buf->ReadByte();
|
||||
townname->partlist[id][i].maxprob = 0;
|
||||
townname->partlist[id][i].partcount = nbtext;
|
||||
townname->partlist[id][i].parts = CallocT<NamePart>(nbtext);
|
||||
grfmsg(6, "FeatureTownName: part %d contains %d texts and will use GB(seed, %d, %d)", i, nbtext, townname->partlist[id][i].bitstart, townname->partlist[id][i].bitcount);
|
||||
partlist.parts.reserve(texts);
|
||||
for (uint textnum = 0; textnum < texts; textnum++) {
|
||||
NamePart &part = partlist.parts.emplace_back();
|
||||
part.prob = buf->ReadByte();
|
||||
|
||||
for (int j = 0; j < nbtext; j++) {
|
||||
byte prob = buf->ReadByte();
|
||||
|
||||
if (HasBit(prob, 7)) {
|
||||
if (HasBit(part.prob, 7)) {
|
||||
byte ref_id = buf->ReadByte();
|
||||
|
||||
if (townname->nbparts[ref_id] == 0) {
|
||||
if (ref_id >= GRFTownName::MAX_LISTS || townname->partlists[ref_id].empty()) {
|
||||
grfmsg(0, "FeatureTownName: definition 0x%02X doesn't exist, deactivating", ref_id);
|
||||
DelGRFTownName(grfid);
|
||||
DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
grfmsg(6, "FeatureTownName: part %d, text %d, uses intermediate definition 0x%02X (with probability %d)", i, j, ref_id, prob & 0x7F);
|
||||
townname->partlist[id][i].parts[j].data.id = ref_id;
|
||||
part.id = ref_id;
|
||||
grfmsg(6, "FeatureTownName: part %u, text %u, uses intermediate definition 0x%02X (with probability %u)", partnum, textnum, ref_id, part.prob & 0x7F);
|
||||
} else {
|
||||
const char *text = buf->ReadString();
|
||||
townname->partlist[id][i].parts[j].data.text = stredup(TranslateTTDPatchCodes(grfid, 0, false, text).c_str());
|
||||
grfmsg(6, "FeatureTownName: part %d, text %d, '%s' (with probability %d)", i, j, townname->partlist[id][i].parts[j].data.text, prob);
|
||||
part.text = TranslateTTDPatchCodes(grfid, 0, false, text);
|
||||
grfmsg(6, "FeatureTownName: part %u, text %u, '%s' (with probability %u)", partnum, textnum, part.text.c_str(), part.prob);
|
||||
}
|
||||
townname->partlist[id][i].parts[j].prob = prob;
|
||||
townname->partlist[id][i].maxprob += GB(prob, 0, 7);
|
||||
partlist.maxprob += GB(part.prob, 0, 7);
|
||||
}
|
||||
grfmsg(6, "FeatureTownName: part %d, total probability %d", i, townname->partlist[id][i].maxprob);
|
||||
grfmsg(6, "FeatureTownName: part %u, total probability %u", partnum, partlist.maxprob);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,15 +21,13 @@
|
|||
|
||||
#include "safeguards.h"
|
||||
|
||||
static GRFTownName *_grf_townnames = nullptr;
|
||||
static std::vector<GRFTownName> _grf_townnames;
|
||||
static std::vector<StringID> _grf_townname_names;
|
||||
|
||||
GRFTownName *GetGRFTownName(uint32 grfid)
|
||||
{
|
||||
GRFTownName *t = _grf_townnames;
|
||||
for (; t != nullptr; t = t->next) {
|
||||
if (t->grfid == grfid) return t;
|
||||
}
|
||||
auto found = std::find_if(std::begin(_grf_townnames), std::end(_grf_townnames), [&grfid](const GRFTownName &t){ return t.grfid == grfid; });
|
||||
if (found != std::end(_grf_townnames)) return &*found;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -37,53 +35,31 @@ GRFTownName *AddGRFTownName(uint32 grfid)
|
|||
{
|
||||
GRFTownName *t = GetGRFTownName(grfid);
|
||||
if (t == nullptr) {
|
||||
t = CallocT<GRFTownName>(1);
|
||||
t = &_grf_townnames.emplace_back();
|
||||
t->grfid = grfid;
|
||||
t->next = _grf_townnames;
|
||||
_grf_townnames = t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void DelGRFTownName(uint32 grfid)
|
||||
{
|
||||
GRFTownName *t = _grf_townnames;
|
||||
GRFTownName *p = nullptr;
|
||||
for (;t != nullptr; p = t, t = t->next) if (t->grfid == grfid) break;
|
||||
if (t != nullptr) {
|
||||
for (int i = 0; i < 128; i++) {
|
||||
for (int j = 0; j < t->nbparts[i]; j++) {
|
||||
for (int k = 0; k < t->partlist[i][j].partcount; k++) {
|
||||
if (!HasBit(t->partlist[i][j].parts[k].prob, 7)) free(t->partlist[i][j].parts[k].data.text);
|
||||
}
|
||||
free(t->partlist[i][j].parts);
|
||||
}
|
||||
free(t->partlist[i]);
|
||||
}
|
||||
if (p != nullptr) {
|
||||
p->next = t->next;
|
||||
} else {
|
||||
_grf_townnames = t->next;
|
||||
}
|
||||
free(t);
|
||||
}
|
||||
_grf_townnames.erase(std::find_if(std::begin(_grf_townnames), std::end(_grf_townnames), [&grfid](const GRFTownName &t){ return t.grfid == grfid; }));
|
||||
}
|
||||
|
||||
static char *RandomPart(char *buf, GRFTownName *t, uint32 seed, byte id, const char *last)
|
||||
static char *RandomPart(char *buf, const GRFTownName *t, uint32 seed, byte id, const char *last)
|
||||
{
|
||||
assert(t != nullptr);
|
||||
for (int i = 0; i < t->nbparts[id]; i++) {
|
||||
byte count = t->partlist[id][i].bitcount;
|
||||
uint16 maxprob = t->partlist[id][i].maxprob;
|
||||
uint32 r = (GB(seed, t->partlist[id][i].bitstart, count) * maxprob) >> count;
|
||||
for (int j = 0; j < t->partlist[id][i].partcount; j++) {
|
||||
byte prob = t->partlist[id][i].parts[j].prob;
|
||||
maxprob -= GB(prob, 0, 7);
|
||||
for (const auto &partlist : t->partlists[id]) {
|
||||
byte count = partlist.bitcount;
|
||||
uint16 maxprob = partlist.maxprob;
|
||||
uint32 r = (GB(seed, partlist.bitstart, count) * maxprob) >> count;
|
||||
for (const auto &part : partlist.parts) {
|
||||
maxprob -= GB(part.prob, 0, 7);
|
||||
if (maxprob > r) continue;
|
||||
if (HasBit(prob, 7)) {
|
||||
buf = RandomPart(buf, t, seed, t->partlist[id][i].parts[j].data.id, last);
|
||||
if (HasBit(part.prob, 7)) {
|
||||
buf = RandomPart(buf, t, seed, part.id, last);
|
||||
} else {
|
||||
buf = strecat(buf, t->partlist[id][i].parts[j].data.text, last);
|
||||
buf = strecat(buf, part.text.c_str(), last);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -94,12 +70,10 @@ static char *RandomPart(char *buf, GRFTownName *t, uint32 seed, byte id, const c
|
|||
char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, const char *last)
|
||||
{
|
||||
strecpy(buf, "", last);
|
||||
for (GRFTownName *t = _grf_townnames; t != nullptr; t = t->next) {
|
||||
if (t->grfid == grfid) {
|
||||
assert(gen < t->nb_gen);
|
||||
buf = RandomPart(buf, t, seed, t->id[gen], last);
|
||||
break;
|
||||
}
|
||||
const GRFTownName *t = GetGRFTownName(grfid);
|
||||
if (t != nullptr) {
|
||||
assert(gen < t->styles.size());
|
||||
buf = RandomPart(buf, t, seed, t->styles[gen].id, last);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
@ -109,8 +83,10 @@ char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, cons
|
|||
void InitGRFTownGeneratorNames()
|
||||
{
|
||||
_grf_townname_names.clear();
|
||||
for (GRFTownName *t = _grf_townnames; t != nullptr; t = t->next) {
|
||||
for (int j = 0; j < t->nb_gen; j++) _grf_townname_names.push_back(t->name[j]);
|
||||
for (const auto &t : _grf_townnames) {
|
||||
for (const auto &style : t.styles) {
|
||||
_grf_townname_names.push_back(style.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,31 +95,31 @@ const std::vector<StringID>& GetGRFTownNameList()
|
|||
return _grf_townname_names;
|
||||
}
|
||||
|
||||
StringID GetGRFTownNameName(uint gen)
|
||||
StringID GetGRFTownNameName(uint16 gen)
|
||||
{
|
||||
return gen < _grf_townname_names.size() ? _grf_townname_names[gen] : STR_UNDEFINED;
|
||||
}
|
||||
|
||||
void CleanUpGRFTownNames()
|
||||
{
|
||||
while (_grf_townnames != nullptr) DelGRFTownName(_grf_townnames->grfid);
|
||||
_grf_townnames.clear();
|
||||
}
|
||||
|
||||
uint32 GetGRFTownNameId(int gen)
|
||||
uint32 GetGRFTownNameId(uint16 gen)
|
||||
{
|
||||
for (GRFTownName *t = _grf_townnames; t != nullptr; t = t->next) {
|
||||
if (gen < t->nb_gen) return t->grfid;
|
||||
gen -= t->nb_gen;
|
||||
for (const auto &t : _grf_townnames) {
|
||||
if (gen < t.styles.size()) return t.grfid;
|
||||
gen -= static_cast<uint16>(t.styles.size());
|
||||
}
|
||||
/* Fallback to no NewGRF */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 GetGRFTownNameType(int gen)
|
||||
uint16 GetGRFTownNameType(uint16 gen)
|
||||
{
|
||||
for (GRFTownName *t = _grf_townnames; t != nullptr; t = t->next) {
|
||||
if (gen < t->nb_gen) return gen;
|
||||
gen -= t->nb_gen;
|
||||
for (const auto &t : _grf_townnames) {
|
||||
if (gen < t.styles.size()) return gen;
|
||||
gen -= static_cast<uint16>(t.styles.size());
|
||||
}
|
||||
/* Fallback to english original */
|
||||
return SPECSTR_TOWNNAME_ENGLISH;
|
||||
|
|
|
@ -17,29 +17,31 @@
|
|||
#include "strings_type.h"
|
||||
|
||||
struct NamePart {
|
||||
byte prob; ///< The relative probability of the following name to appear in the bottom 7 bits.
|
||||
union {
|
||||
char *text; ///< If probability bit 7 is clear
|
||||
byte id; ///< If probability bit 7 is set
|
||||
} data;
|
||||
std::string text; ///< If probability bit 7 is clear
|
||||
byte id; ///< If probability bit 7 is set
|
||||
byte prob; ///< The relative probability of the following name to appear in the bottom 7 bits.
|
||||
};
|
||||
|
||||
struct NamePartList {
|
||||
byte partcount;
|
||||
byte bitstart;
|
||||
byte bitcount;
|
||||
uint16 maxprob;
|
||||
NamePart *parts;
|
||||
byte bitstart; ///< Start of random seed bits to use.
|
||||
byte bitcount; ///< Number of bits of random seed to use.
|
||||
uint16 maxprob; ///< Total probability of all parts.
|
||||
std::vector<NamePart> parts; ///< List of parts to choose from.
|
||||
};
|
||||
|
||||
struct TownNameStyle {
|
||||
StringID name; ///< String ID of this town name style.
|
||||
byte id; ///< Index within partlist for this town name style.
|
||||
|
||||
TownNameStyle(StringID name, byte id) : name(name), id(id) { }
|
||||
};
|
||||
|
||||
struct GRFTownName {
|
||||
uint32 grfid;
|
||||
byte nb_gen;
|
||||
byte id[128];
|
||||
StringID name[128];
|
||||
byte nbparts[128];
|
||||
NamePartList *partlist[128];
|
||||
GRFTownName *next;
|
||||
static const uint MAX_LISTS = 128; ///< Maximum number of town name lists that can be defined per GRF.
|
||||
|
||||
uint32 grfid; ///< GRF ID of NewGRF.
|
||||
std::vector<TownNameStyle> styles; ///< Style names defined by the Town Name NewGRF.
|
||||
std::vector<NamePartList> partlists[MAX_LISTS]; ///< Lists of town name parts.
|
||||
};
|
||||
|
||||
GRFTownName *AddGRFTownName(uint32 grfid);
|
||||
|
@ -47,9 +49,9 @@ GRFTownName *GetGRFTownName(uint32 grfid);
|
|||
void DelGRFTownName(uint32 grfid);
|
||||
void CleanUpGRFTownNames();
|
||||
char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, const char *last);
|
||||
uint32 GetGRFTownNameId(int gen);
|
||||
uint16 GetGRFTownNameType(int gen);
|
||||
StringID GetGRFTownNameName(uint gen);
|
||||
uint32 GetGRFTownNameId(uint16 gen);
|
||||
uint16 GetGRFTownNameType(uint16 gen);
|
||||
StringID GetGRFTownNameName(uint16 gen);
|
||||
|
||||
const std::vector<StringID>& GetGRFTownNameList();
|
||||
|
||||
|
|
Loading…
Reference in New Issue