Project

General

Profile

Feature #1432 ยป 0089-Add-support-for-government-user-flags.patch

Marko Lindqvist, 06/10/2025 08:07 AM

View differences:

common/government.c
struct government *governments = NULL;
static struct user_flag user_gov_flags[MAX_NUM_USER_GOVERNMENT_FLAGS];
/**********************************************************************//**
Returns the government that has the given (translated) name.
Returns NULL if none match.
......
* in order to know how long anarchy will last. */
return FALSE;
}
return TRUE;
}
/**********************************************************************//**
Return TRUE if the government has this flag, otherwise FALSE
**************************************************************************/
bool government_has_flag(const struct government *pgov,
enum gov_flag_id flag)
{
fc_assert_ret_val(gov_flag_id_is_valid(flag), FALSE);
return BV_ISSET(pgov->flags, flag);
}
/************************************************************************//**
Initialize user government flags.
****************************************************************************/
void user_gov_flags_init(void)
{
int i;
for (i = 0; i < MAX_NUM_USER_GOVERNMENT_FLAGS; i++) {
user_flag_init(&user_gov_flags[i]);
}
}
/************************************************************************//**
Frees the memory associated with all government flags
****************************************************************************/
void gov_flags_free(void)
{
int i;
for (i = 0; i < MAX_NUM_USER_GOVERNMENT_FLAGS; i++) {
user_flag_free(&user_gov_flags[i]);
}
}
/************************************************************************//**
Sets user defined name for government flag.
****************************************************************************/
void set_user_gov_flag_name(enum gov_flag_id id, const char *name,
const char *helptxt)
{
int gfid = id - GOVF_USER_FLAG_1;
fc_assert_ret(id >= GOVF_USER_FLAG_1 && id <= GOVF_LAST_USER_FLAG);
free(user_gov_flags[gfid].name);
user_gov_flags[gfid].name = nullptr;
if (name && name[0] != '\0') {
user_gov_flags[gfid].name = fc_strdup(name);
}
free(user_gov_flags[gfid].helptxt);
user_gov_flags[gfid].helptxt = nullptr;
if (helptxt && helptxt[0] != '\0') {
user_gov_flags[gfid].helptxt = fc_strdup(helptxt);
}
}
/************************************************************************//**
Government flag name callback, called from specenum code.
****************************************************************************/
const char *gov_flag_id_name_cb(enum gov_flag_id flag)
{
if (flag < GOVF_USER_FLAG_1 || flag > GOVF_LAST_USER_FLAG) {
return nullptr;
}
return user_gov_flags[flag - GOVF_USER_FLAG_1].name;
}
/************************************************************************//**
Return the (untranslated) help text of the user government flag.
****************************************************************************/
const char *gov_flag_helptxt(enum gov_flag_id id)
{
fc_assert(id >= GOVF_USER_FLAG_1 && id <= GOVF_LAST_USER_FLAG);
return user_gov_flags[id - GOVF_USER_FLAG_1].helptxt;
}
common/government.h
#include "name_translation.h"
#include "requirements.h"
#include "government_enums_gen.h"
#define GOVF_LAST_USER_FLAG GOVF_USER_FLAG_8
#define MAX_NUM_USER_GOVERNMENT_FLAGS (GOVF_LAST_USER_FLAG - GOVF_USER_FLAG_1 + 1)
struct strvec; /* Actually defined in "utility/string_vector.h". */
......
* protocol, which generally uses government_count()). */
#define G_LAST (127)
/* This is struct government itself. All information about a form of
/* This is struct government itself. All information about a form of
* government is contained inhere. -- SKi */
struct government {
Government_type_id item_number;
......
struct requirement_vector reqs;
struct ruler_title_hash *ruler_titles;
int changed_to_times;
bv_gov_flags flags;
struct strvec *helptext;
/* AI cached data for this government. */
struct {
struct government *better; /* hint: a better government (or NULL) */
struct government *better; /* Hint: A better government (or nullptr) */
} ai;
};
......
bool untargeted_revolution_allowed(void);
/* General government flag accessor routines */
bool government_has_flag(const struct government *pgov,
enum gov_flag_id flag);
void user_gov_flags_init(void);
void gov_flags_free(void);
void set_user_gov_flag_name(enum gov_flag_id id,
const char *name,
const char *helptxt);
const char *gov_flag_helptxt(enum gov_flag_id id);
#ifdef __cplusplus
}
#endif /* __cplusplus */
common/improvement.c
}
/**********************************************************************//**
Return TRUE if the impr has this flag otherwise FALSE
Return TRUE if the impr has this flag, otherwise FALSE
**************************************************************************/
bool improvement_has_flag(const struct impr_type *pimprove,
enum impr_flag_id flag)
{
fc_assert_ret_val(impr_flag_id_is_valid(flag), FALSE);
return BV_ISSET(pimprove->flags, flag);
}
......
Sets user defined name for building flag.
****************************************************************************/
void set_user_impr_flag_name(enum impr_flag_id id, const char *name,
const char *helptxt)
const char *helptxt)
{
int bfid = id - IF_USER_FLAG_1;
data/ruledit/comments-3.4.txt
; (optional)\n\
"
government = "\
; Names for custom government flags. There can be up to 8 of these.\n\
; name = rule name; In some circumstances user may see this\n\
; as part of some sentences, so try to make it descriptive\n\
; and sensible.\n\
; helptxt = displayed in the help for government types with this flag\n\
; (optional)\n\
"
[sectiondoc]
; This section has comments documenting other sections
gen_headers/enums/Makefile.am
city_enums_gen.h \
effects_enums_gen.h \
fc_types_enums_gen.h \
government_enums_gen.h \
manual_enums_gen.h \
terrain_enums_gen.h
......
city_enums.def \
effects_enums.def \
fc_types_enums.def \
government_enums.def \
manual_enums.def \
terrain_enums.def \
$(ENUMS_GEN)
gen_headers/enums/government_enums.def
# Specenum definitions for common/government.h
# See gen_headers/generate_enums.py for syntax
/* Used in the network protocol. */
enum gov_flag_id
prefix GOVF_
name-override
bitvector bv_gov_flags
count
values
USER_FLAG_1
USER_FLAG_2
USER_FLAG_3
USER_FLAG_4
USER_FLAG_5
USER_FLAG_6
USER_FLAG_7
USER_FLAG_8
end
meson.build
'city_enums': ['city_enums.def', 'city_enums_gen.h'],
'effects_enums': ['effects_enums.def', 'effects_enums_gen.h'],
'fc_types_enums': ['fc_types_enums.def', 'fc_types_enums_gen.h'],
'government_enums': ['government_enums.def', 'government_enums_gen.h'],
'terrain_enums': ['terrain_enums.def', 'terrain_enums_gen.h'],
},
'manual': {
server/ruleset/ruleload.c
struct section_list *sec;
const char *filename = secfile_name(file);
bool ok = TRUE;
const char *flag;
int i;
if (!rscompat_check_cap_and_version(file, filename, compat)) {
return FALSE;
......
}
}
/* User government flag names */
for (i = 0;
(flag = secfile_lookup_str_default(file, nullptr,
"control.government_flags%d.name",
i));
i++) {
const char *helptxt = secfile_lookup_str_default(file, nullptr,
"control.government_flags%d.helptxt", i);
if (gov_flag_id_by_name(flag, fc_strcasecmp)
!= gov_flag_id_invalid()) {
ruleset_error(nullptr, LOG_ERROR,
"\"%s\": Duplicate government flag name '%s'",
filename, flag);
ok = FALSE;
break;
}
if (i > MAX_NUM_USER_GOVERNMENT_FLAGS) {
ruleset_error(NULL, LOG_ERROR,
"\"%s\": Too many user government flags!",
filename);
ok = FALSE;
break;
}
set_user_gov_flag_name(GOVF_USER_FLAG_1 + i, flag, helptxt);
}
section_list_destroy(sec);
return ok;
tools/ruleutil/comments.c
char *uflags_extra;
char *uflags_tech;
char *uflags_building;
char *uflags_government;
char *trade_settings;
char *goods;
char *actions;
......
comment_file, "uflag_types.tech");
comment_load(comments_storage.uflags_building,
comment_file, "uflag_types.building");
comment_load(comments_storage.uflags_government,
comment_file, "uflag_types.government");
comment_load(comments_storage.trade_settings,
comment_file, "typedoc.trade_settings");
comment_load(comments_storage.goods, comment_file, "typedoc.goods");
......
comment_entry_write(sfile, comments_storage.uflags_building, "control");
}
/**********************************************************************//**
Write header for government user flags.
**************************************************************************/
void comment_uflags_government(struct section_file *sfile)
{
comment_entry_write(sfile, comments_storage.uflags_government, "control");
}
/**********************************************************************//**
Write trade settings header.
**************************************************************************/
tools/ruleutil/comments.h
void comment_uflags_extra(struct section_file *sfile);
void comment_uflags_tech(struct section_file *sfile);
void comment_uflags_building(struct section_file *sfile);
void comment_uflags_government(struct section_file *sfile);
/* Other section comments */
void comment_trade_settings(struct section_file *sfile);
tools/ruleutil/rulesave.c
{
struct section_file *sfile = create_ruleset_file(name, "government");
int sect_idx;
bool uflags_government = FALSE;
int i;
if (sfile == nullptr) {
return FALSE;
}
for (i = 0; i < MAX_NUM_USER_GOVERNMENT_FLAGS; i++) {
const char *flagname = gov_flag_id_name_cb(i + GOVF_USER_FLAG_1);
const char *helptxt = gov_flag_helptxt(i + GOVF_USER_FLAG_1);
if (flagname != nullptr) {
if (!uflags_government) {
comment_uflags_government(sfile);
uflags_government = TRUE;
}
secfile_insert_str(sfile, flagname, "control.government_flags%d.name", i);
/* Save the user flag help text even when it is undefined. That makes
* the formatting code happy. The resulting "" is ignored when the
* ruleset is loaded. */
secfile_insert_str(sfile, helptxt,
"control.government_flags%d.helptxt", i);
}
}
save_gov_ref(sfile, game.government_during_revolution, "governments",
"during_revolution");
    (1-1/1)