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