Project

General

Profile

Feature #505 ยป 0061-Add-tilesets-to-the-.modpacks-system.patch

Marko Lindqvist, 04/25/2024 11:29 PM

View differences:

client/client_main.c
#include "idex.h"
#include "map.h"
#include "mapimg.h"
#include "modpack.h"
#include "netintf.h"
#include "packets.h"
#include "player.h"
......
static void fc_interface_init_client(void);
static void cache_tilesets(void);
char *logfile = NULL;
char *scriptfile = NULL;
char *savefile = NULL;
......
argv[1 + ui_options] = NULL;
argc = 1 + ui_options;
/* disallow running as root -- too dangerous */
/* Disallow running as root -- too dangerous */
dont_run_as_root(argv[0], "freeciv_client");
log_init(logfile, loglevel, NULL, NULL, fatal_assertions);
backtrace_init();
/* after log_init: */
/* After log_init: */
(void)user_username(gui_options.default_user_name, MAX_LEN_NAME);
if (!is_valid_username(gui_options.default_user_name)) {
......
}
}
/* initialization */
/* Initialization */
game.all_connections = conn_list_new();
game.est_connections = conn_list_new();
......
fc_init_ow_mutex();
/* register exit handler */
/* Register exit handler */
atexit(at_exit);
fc_at_quick_exit(emergency_exit);
......
helpdata_init();
boot_help_texts();
modpacks_init();
cache_tilesets();
audio_real_init(sound_set_name, music_set_name, sound_plugin_name);
start_menu_music("music_menu", NULL);
......
}
}
/* run gui-specific client */
/* Run gui-specific client */
uret = ui_main(argc, argv);
/* termination */
modpacks_free();
/* Termination */
client_exit(uret);
/* not reached */
/* Not reached */
return EXIT_SUCCESS;
}
......
{
client_quitting = TRUE;
}
/************************************************************************//**
Create cache of available tilesets.
****************************************************************************/
static void cache_tilesets(void)
{
struct fileinfo_list *tileset_choices;
tileset_choices = get_modpacks_list();
fileinfo_list_iterate(tileset_choices, pfile) {
struct section_file *sf;
sf = secfile_load(pfile->fullname, FALSE);
if (sf != NULL) {
modpack_cache_tileset(sf);
secfile_destroy(sf);
}
} fileinfo_list_iterate_end;
fileinfo_list_destroy(tileset_choices);
}
client/tilespec.c
#include "game.h" /* game.control.num_city_styles */
#include "government.h"
#include "map.h"
#include "modpack.h"
#include "movement.h"
#include "nation.h"
#include "player.h"
......
return 0;
}
struct ts_list_data {
struct strvec *list;
int topo;
};
/************************************************************************//**
Callback called from modpack tileset cache iteration.
****************************************************************************/
static void ts_list_cb(const char *modpack_name, const char *filename,
void *data)
{
struct ts_list_data *tsdata = (struct ts_list_data *)data;
const char *target = modpack_tileset_target(modpack_name);
struct tileset *t = tileset_read_toplevel(target,
FALSE, tsdata->topo, 1.0f);
if (t != nullptr) {
strvec_append(tsdata->list, target);
tileset_free(t);
}
}
/************************************************************************//**
Returns a static list of tilesets available on the system by
searching all data directories for files matching TILESPEC_SUFFIX.
Returns a static list of tilesets available on the system.
****************************************************************************/
const struct strvec *get_tileset_list(const struct option *poption)
{
static struct strvec *tilesets[3] = { NULL, NULL, NULL };
static struct strvec *tilesets[3] = { nullptr, nullptr, nullptr };
int topo = option_get_cb_data(poption);
int idx;
idx = ts_topology_index(topo);
fc_assert_ret_val(idx < ARRAY_SIZE(tilesets), NULL);
fc_assert_ret_val(idx < ARRAY_SIZE(tilesets), nullptr);
if (tilesets[idx] == nullptr) {
struct ts_list_data data;
if (tilesets[idx] == NULL) {
/* Note: this means you must restart the client after installing a new
tileset. */
struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
tilesets[idx] = strvec_new();
strvec_iterate(list, file) {
struct tileset *t = tileset_read_toplevel(file, FALSE, topo, 1.0f);
if (t) {
strvec_append(tilesets[idx], file);
tileset_free(t);
}
} strvec_iterate_end;
strvec_destroy(list);
data.list = tilesets[idx];
data.topo = topo;
modpack_tileset_cache_iterate(ts_list_cb, &data);
}
return tilesets[idx];
......
free(t);
}
/************************************************************************//**
Callback called from modpack tileset cache iteration.
****************************************************************************/
static void ts_cb(const char *modpack_name, const char *filename, void *data)
{
int topo_id = *((int *)data);
struct tileset *t = tileset_read_toplevel(modpack_tileset_target(modpack_name),
FALSE, topo_id, 1.0f);
if (t != nullptr) {
if (tileset == nullptr) {
tileset = t;
} else if (t->priority > tileset->priority
|| (topo_id >= 0
&& tileset_topo_index(tileset) != tileset_topo_index(t))) {
tileset_free(tileset);
tileset = t;
} else {
tileset_free(t);
}
}
}
/************************************************************************//**
Read a new tilespec in when first starting the game.
......
{
bool original;
if (tileset_name == NULL
if (tileset_name == nullptr
|| !(tileset = tileset_read_toplevel(tileset_name, verbose,
topo_id, 1.0f))) {
struct strvec *list = fileinfolist(get_data_dirs(), TILESPEC_SUFFIX);
original = FALSE;
strvec_iterate(list, file) {
struct tileset *t = tileset_read_toplevel(file, FALSE, topo_id, 1.0f);
if (t) {
if (!tileset) {
tileset = t;
} else if (t->priority > tileset->priority
|| (topo_id >= 0
&& tileset_topo_index(tileset) != tileset_topo_index(t))) {
tileset_free(tileset);
tileset = t;
} else {
tileset_free(t);
}
}
} strvec_iterate_end;
strvec_destroy(list);
modpack_tileset_cache_iterate(ts_cb, &topo_id);
if (tileset == NULL) {
tileset_error(LOG_FATAL, NULL, _("No usable default tileset found, aborting!"));
if (tileset == nullptr) {
tileset_error(LOG_FATAL, nullptr, _("No usable default tileset found, aborting!"));
}
log_verbose("Trying tileset \"%s\".", tileset->name);
common/game.c
#include "government.h"
#include "idex.h"
#include "map.h"
#include "modpack.h"
#include "multipliers.h"
#include "nation.h"
#include "packets.h"
......
**************************************************************************/
void game_init(bool keep_ruleset_value)
{
modpacks_init();
game_defaults(keep_ruleset_value);
player_slots_init();
map_init(&wld.map, is_server());
......
game_ruleset_free();
researches_free();
cm_free();
modpacks_free();
}
/**********************************************************************//**
common/modpack.c
struct modpack_cache_item {
char *modpack_name;
char *filename;
char *target;
};
/* Get 'struct modpack_cache_list' and related functions: */
......
#define modpack_cache_iterate_end LIST_ITERATE_END
static struct modpack_cache_list *modpack_rulesets;
static struct modpack_cache_list *modpack_tilesets;
/************************************************************************//**
Initialize modpacks system
......
{
if (is_server()) {
modpack_rulesets = modpack_cache_list_new();
} else {
modpack_tilesets = modpack_cache_list_new();
}
}
......
} modpack_cache_iterate_end;
modpack_cache_list_destroy(modpack_rulesets);
} else {
modpack_cache_iterate(modpack_tilesets, item) {
free(item->modpack_name);
free(item->filename);
free(item->target);
free(item);
} modpack_cache_iterate_end;
modpack_cache_list_destroy(modpack_tilesets);
}
}
......
}
/************************************************************************//**
Return name of the modpack if contains a ruleset. If it does not contain
Return name of the modpack if it contains a ruleset. If it does not contain
ruleset, return nullptr.
@param sf Modpack section file
......
return nullptr;
}
/************************************************************************//**
Return name of the modpack if it contains a tileset. If it does not contain
ruleset, return nullptr.
@param sf Modpack section file
@return Name of the modpack, or nullptr
****************************************************************************/
const char *modpack_has_tileset(struct section_file *sf)
{
if (sf != nullptr) {
if (!modpack_check_capabilities(sf, MODPACK_CAPSTR, sf->name,
FALSE)) {
return nullptr;
}
if (secfile_lookup_bool_default(sf, FALSE, "components.tileset")) {
return secfile_lookup_str_default(sf, nullptr, "modpack.name");
}
}
return nullptr;
}
/************************************************************************//**
Return .serv file name for the modpack, if any.
......
return nullptr;
}
/************************************************************************//**
Return tilespec for the modpack, if any.
@param sf Modpack section file
@return Tilespec file name, or nullptr
****************************************************************************/
const char *modpack_tilespec(struct section_file *sf)
{
if (sf != nullptr) {
return secfile_lookup_str_default(sf, nullptr, "tileset.tilespec");
}
return nullptr;
}
/************************************************************************//**
Add modpack/ruleset mapping to cache, if modpack has ruleset.
Return name of the modpack, if the mapping exist.
......
return mp_name;
}
/************************************************************************//**
Add modpack/ruleset mapping to cache, if modpack has tileset.
Return name of the modpack, if the mapping exist.
@param sf Modpack section file to cache
@return Name of the modpack, or nullptr
****************************************************************************/
const char *modpack_cache_tileset(struct section_file *sf)
{
const char *mp_name = modpack_has_tileset(sf);
struct modpack_cache_item *item;
const char *target;
if (mp_name == nullptr) {
return nullptr;
}
fc_assert(sf->name != nullptr);
item = fc_malloc(sizeof(struct modpack_cache_item));
item->modpack_name = fc_strdup(mp_name);
item->filename = fc_strdup(sf->name);
target = secfile_lookup_str_default(sf, nullptr, "tileset.tilespec");
if (target != nullptr) {
item->target = fc_strdup(target);
} else {
item->target = nullptr;
}
modpack_cache_list_append(modpack_tilesets, item);
return mp_name;
}
/************************************************************************//**
Find filename by name of the modpack, from the ruleset cache
......
return nullptr;
}
/************************************************************************//**
Find filename by name of the modpack, from the tileset cache
@param name Modpack name
@return Filename of the modpack
****************************************************************************/
const char *modpack_file_from_tileset_cache(const char *name)
{
modpack_cache_iterate(modpack_tilesets, item) {
if (!fc_strcasecmp(name, item->modpack_name)) {
return item->filename;
}
} modpack_cache_iterate_end;
return nullptr;
}
/************************************************************************//**
Find target by name of the modpack, from the tileset cache
@param name Modpack name
@return Target of the modpack
****************************************************************************/
const char *modpack_tileset_target(const char *name)
{
modpack_cache_iterate(modpack_tilesets, item) {
if (!fc_strcasecmp(name, item->modpack_name)) {
return item->target;
}
} modpack_cache_iterate_end;
return nullptr;
}
/************************************************************************//**
Call callback for each item in the ruleset cache.
......
cb(item->modpack_name, item->filename, data);
} modpack_cache_iterate_end;
}
/************************************************************************//**
Call callback for each item in the tileset cache.
@param cb Callback to call
@param data Data to pass to the callback
****************************************************************************/
void modpack_tileset_cache_iterate(mrc_cb cb, void *data)
{
modpack_cache_iterate(modpack_tilesets, item) {
cb(item->modpack_name, item->filename, data);
} modpack_cache_iterate_end;
}
common/modpack.h
const char *modpack_cache_ruleset(struct section_file *sf);
const char *modpack_file_from_ruleset_cache(const char *name);
const char *modpack_cache_tileset(struct section_file *sf);
const char *modpack_file_from_tileset_cache(const char *name);
const char *modpack_tileset_target(const char *name);
struct fileinfo_list *get_modpacks_list(void);
const char *modpack_has_ruleset(struct section_file *sf);
const char *modpack_has_tileset(struct section_file *sf);
bool modpack_check_capabilities(struct section_file *file, const char *us_capstr,
const char *filename, bool verbose);
const char *modpack_serv_file(struct section_file *sf);
const char *modpack_rulesetdir(struct section_file *sf);
const char *modpack_tilespec(struct section_file *sf);
typedef void (*mrc_cb)(const char*, const char *, void *data);
typedef void (*mrc_cb)(const char *, const char *, void *data);
void modpack_ruleset_cache_iterate(mrc_cb cb, void *data);
void modpack_tileset_cache_iterate(mrc_cb cb, void *data);
#ifdef __cplusplus
}
data/Makefile.am
if CLIENT
CLIENT_FILES = \
amplio2.modpack \
amplio2.tilespec \
cimpletoon.modpack \
cimpletoon.tilespec \
hex2t.modpack \
hex2t.tilespec \
hexemplio.modpack \
hexemplio.tilespec \
isophex.modpack \
isophex.tilespec \
isotrident.modpack \
isotrident.tilespec \
toonhex.modpack \
toonhex.tilespec \
alio.modpack \
alio.tilespec \
trident.modpack \
trident.tilespec \
stdmusic.musicspec \
stdsounds.soundspec \
data/alio.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "alio"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "alio"
data/amplio.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "amplio"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "amplio"
data/amplio2.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "amplio2"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "amplio2"
data/cimpletoon.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "cimpletoon"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "cimpletoon"
data/hex2t.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "hex2t"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "hex2t"
data/hexemplio.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "hexemplio"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "hexemplio"
data/isophex.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "isophex"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "isophex"
data/isotrident.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "isotrident"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "isotrident"
data/toonhex.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "toonhex"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "toonhex"
data/trident.modpack
[datafile]
options = "+Freeciv-modpack-3.3-Devel-2024.Apr.14"
[modpack]
; Name of the modpack
name = "trident"
[components]
; Whether the modpack has a ruleset component
tileset = TRUE
[tileset]
; For modpacks with the tileset component, "tilespec" needs to be defined.
tilespec = "trident"
meson.build
)
install_data('data/helpdata.txt',
'data/cimpletoon.modpack',
'data/cimpletoon.tilespec',
'data/isophex.modpack',
'data/isophex.tilespec',
'data/isotrident.modpack',
'data/isotrident.tilespec',
'data/toonhex.modpack',
'data/toonhex.tilespec',
'data/alio.modpack',
'data/alio.tilespec',
'data/trident.modpack',
'data/trident.tilespec',
'data/hexemplio.modpack',
'data/hexemplio.tilespec',
'data/hex2t.modpack',
'data/hex2t.tilespec',
'data/amplio2.modpack',
'data/amplio2.tilespec',
'data/stdmusic.musicspec',
'data/stdsounds.soundspec',
server/srv_main.c
#include "government.h"
#include "map.h"
#include "mapimg.h"
#include "modpack.h"
#include "nation.h"
#include "packets.h"
#include "player.h"
......
}
#endif /* HAVE_FCDB */
modpacks_free();
settings_free();
stdinhand_free();
edithand_free();
......
int retries = 0;
while (identity_number_is_used(increment_identity_number())) {
/* try again */
/* Try again */
if (++retries >= IDENTITY_NUMBER_SIZE) {
/* Always fails. */
fc_assert_exit_msg(IDENTITY_NUMBER_SIZE > retries,
......
}
#endif /* HAVE_FCDB */
/* make sure it's initialized */
/* Make sure it's initialized */
if (!has_been_srv_init) {
srv_init();
}
fc_init_network();
/* must be before con_log_init() */
/* Must be before con_log_init() */
init_connections();
con_log_init(srvarg.log_filename, srvarg.loglevel,
srvarg.fatal_assertions);
/* logging available after this point */
/* Logging available after this point */
server_open_socket();
......
voting_init();
ai_timer_init();
modpacks_init();
server_game_init(FALSE);
mapimg_init(mapimg_server_tile_known, mapimg_server_tile_terrain,
mapimg_server_tile_owner, mapimg_server_tile_city,
......
**************************************************************************/
void server_game_init(bool keep_ruleset_value)
{
/* was redundantly in game_load() */
/* Was redundantly in game_load() */
server.playable_nations = 0;
server.nbarbarians = 0;
server.identity_number = IDENTITY_NUMBER_SKIP;
    (1-1/1)