From a188648c1e825f23f05c51a8d1287e8cc3dfb7de Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Tue, 12 Dec 2023 06:38:46 +0200 Subject: [PATCH] Update to Freeciv server freeciv/freeciv@78e35d10a7 Signed-off-by: Marko Lindqvist --- freeciv/apply_patches.sh | 4 - ...-playertile-extras-dynamic-bitvector.patch | 677 ------------------ freeciv/version.txt | 2 +- 3 files changed, 1 insertion(+), 682 deletions(-) delete mode 100644 freeciv/patches/backports/0002-Make-playertile-extras-dynamic-bitvector.patch diff --git a/freeciv/apply_patches.sh b/freeciv/apply_patches.sh index 167aca429..5068a28b1 100755 --- a/freeciv/apply_patches.sh +++ b/freeciv/apply_patches.sh @@ -6,9 +6,6 @@ # https://osdn.net/projects/freeciv/ticket/????? # https://redmine.freeciv.org/issues/? # -# 0002-Make-playertile-extras-dynamic-bitvector.patch -# Memory usage optimization -# osdn #48798 # 0039-Improve-report.c-coding-style.patch # Baseline for scorelog_filenames.patch # osdn #48949 @@ -46,7 +43,6 @@ declare -a GIT_PATCHLIST=( ) declare -a PATCHLIST=( - "backports/0002-Make-playertile-extras-dynamic-bitvector" "backports/0039-Improve-report.c-coding-style" "backports/0002-Pick-random-nations-before-setting-turn-number-to-1" "backports/0003-Reserve-space-for-terminating-NULL-on-astr_buffer" diff --git a/freeciv/patches/backports/0002-Make-playertile-extras-dynamic-bitvector.patch b/freeciv/patches/backports/0002-Make-playertile-extras-dynamic-bitvector.patch deleted file mode 100644 index b63673775..000000000 --- a/freeciv/patches/backports/0002-Make-playertile-extras-dynamic-bitvector.patch +++ /dev/null @@ -1,677 +0,0 @@ -From 91b466e81487a686984402437485809f25efe5df Mon Sep 17 00:00:00 2001 -From: Marko Lindqvist -Date: Tue, 3 Oct 2023 19:36:35 +0300 -Subject: [PATCH 02/27] Make playertile extras dynamic bitvector - -It was a static one, always reserving memory for freeciv's -internal maximum number of extras. - -See osdn #48798 - -Signed-off-by: Marko Lindqvist ---- - server/maphand.c | 16 +- - server/maphand.h | 2 +- - server/savegame/savegame2.c | 300 ++++++++++++++++++++++++++++++++---- - server/savegame/savegame3.c | 97 ++++++++++-- - server/unittools.c | 19 ++- - 5 files changed, 378 insertions(+), 56 deletions(-) - -diff --git a/server/maphand.c b/server/maphand.c -index 3e744ca381..b07757ac87 100644 ---- a/server/maphand.c -+++ b/server/maphand.c -@@ -549,7 +549,7 @@ void send_tile_info(struct conn_list *dest, struct tile *ptile, - : 0; - - if (pplayer != NULL) { -- info.extras = map_get_player_tile(ptile, pplayer)->extras; -+ dbv_to_bv(info.extras.vec, &(map_get_player_tile(ptile, pplayer)->extras)); - } else { - info.extras = ptile->extras; - } -@@ -587,7 +587,7 @@ void send_tile_info(struct conn_list *dest, struct tile *ptile, - info.placing = -1; - info.place_turn = 0; - -- info.extras = plrtile->extras; -+ dbv_to_bv(info.extras.vec, &(plrtile->extras)); - - /* Labels never change, so they are not subject to fog of war */ - if (ptile->label != NULL) { -@@ -1320,7 +1320,7 @@ static void player_tile_init(struct tile *ptile, struct player *pplayer) - plrtile->owner = NULL; - plrtile->extras_owner = NULL; - plrtile->site = NULL; -- BV_CLR_ALL(plrtile->extras); -+ dbv_init(&(plrtile->extras), extra_count()); - if (!game.server.last_updated_year) { - plrtile->last_updated = game.info.turn; - } else { -@@ -1343,6 +1343,8 @@ static void player_tile_free(struct tile *ptile, struct player *pplayer) - if (plrtile->site != NULL) { - vision_site_destroy(plrtile->site); - } -+ -+ dbv_free(&(plrtile->extras)); - } - - /**********************************************************************//** -@@ -1384,16 +1386,16 @@ bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile) - struct player_tile *plrtile = map_get_player_tile(ptile, pplayer); - - if (plrtile->terrain != ptile->terrain -- || !BV_ARE_EQUAL(plrtile->extras, ptile->extras) -+ || !bv_match_dbv(&(plrtile->extras), ptile->extras.vec) - || plrtile->resource != ptile->resource - || plrtile->owner != tile_owner(ptile) - || plrtile->extras_owner != extra_owner(ptile)) { - plrtile->terrain = ptile->terrain; - extra_type_iterate(pextra) { - if (player_knows_extra_exist(pplayer, pextra, ptile)) { -- BV_SET(plrtile->extras, extra_number(pextra)); -+ dbv_set(&(plrtile->extras), extra_number(pextra)); - } else { -- BV_CLR(plrtile->extras, extra_number(pextra)); -+ dbv_clr(&(plrtile->extras), extra_number(pextra)); - } - } extra_type_iterate_end; - plrtile->resource = ptile->resource; -@@ -1485,7 +1487,7 @@ static bool really_give_tile_info_from_player_to_player(struct player *pfrom, - /* Update and send tile knowledge */ - map_set_known(ptile, pdest); - dest_tile->terrain = from_tile->terrain; -- dest_tile->extras = from_tile->extras; -+ dbv_copy(&(dest_tile->extras), &(from_tile->extras)); - dest_tile->resource = from_tile->resource; - dest_tile->owner = from_tile->owner; - dest_tile->extras_owner = from_tile->extras_owner; -diff --git a/server/maphand.h b/server/maphand.h -index 486751d781..00adf35ed1 100644 ---- a/server/maphand.h -+++ b/server/maphand.h -@@ -33,7 +33,7 @@ struct player_tile { - struct terrain *terrain; /* NULL for unknown tiles */ - struct player *owner; /* NULL for unowned */ - struct player *extras_owner; -- bv_extras extras; -+ struct dbv extras; - - /* If you build a city with an unknown square within city radius - the square stays unknown. However, we still have to keep count -diff --git a/server/savegame/savegame2.c b/server/savegame/savegame2.c -index 3f0b859f1f..55c60ae9e4 100644 ---- a/server/savegame/savegame2.c -+++ b/server/savegame/savegame2.c -@@ -302,12 +302,20 @@ static void worklist_load(struct section_file *file, int wlist_max_length, - struct worklist *pwl, - const char *path, ...); - static void unit_ordering_apply(void); --static void sg_extras_set(bv_extras *extras, char ch, struct extra_type **idx); --static void sg_special_set(struct tile *ptile, bv_extras *extras, char ch, -- const enum tile_special_type *idx, -- bool rivers_overlay); --static void sg_bases_set(bv_extras *extras, char ch, struct base_type **idx); --static void sg_roads_set(bv_extras *extras, char ch, struct road_type **idx); -+static void sg_extras_set_dbv(struct dbv *extras, char ch, -+ struct extra_type **idx); -+static void sg_extras_set_bv(bv_extras *extras, char ch, -+ struct extra_type **idx); -+static void sg_special_set_dbv(struct tile *ptile, struct dbv *extras, char ch, -+ const enum tile_special_type *idx, -+ bool rivers_overlay); -+static void sg_special_set_bv(struct tile *ptile, bv_extras *extras, char ch, -+ const enum tile_special_type *idx, -+ bool rivers_overlay); -+static void sg_bases_set_dbv(struct dbv *extras, char ch, struct base_type **idx); -+static void sg_bases_set_bv(bv_extras *extras, char ch, struct base_type **idx); -+static void sg_roads_set_dbv(struct dbv *extras, char ch, struct road_type **idx); -+static void sg_roads_set_bv(bv_extras *extras, char ch, struct road_type **idx); - static struct extra_type *char2resource(char c); - static struct terrain *char2terrain(char ch); - static Tech_type_id technology_load(struct section_file *file, -@@ -844,7 +852,41 @@ static void unit_ordering_apply(void) - in four to a character in hex notation. 'index' is a mapping of - savegame bit -> base bit. - ****************************************************************************/ --static void sg_extras_set(bv_extras *extras, char ch, struct extra_type **idx) -+static void sg_extras_set_dbv(struct dbv *extras, char ch, -+ struct extra_type **idx) -+{ -+ int i, bin; -+ const char *pch = strchr(hex_chars, ch); -+ -+ if (!pch || ch == '\0') { -+ log_sg("Unknown hex value: '%c' (%d)", ch, ch); -+ bin = 0; -+ } else { -+ bin = pch - hex_chars; -+ } -+ -+ for (i = 0; i < 4; i++) { -+ struct extra_type *pextra = idx[i]; -+ -+ if (pextra == NULL) { -+ continue; -+ } -+ if ((bin & (1 << i)) -+ && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) { -+ dbv_set(extras, extra_index(pextra)); -+ } -+ } -+} -+ -+/************************************************************************//** -+ Helper function for loading extras from a savegame. -+ -+ 'ch' gives the character loaded from the savegame. Extras are packed -+ in four to a character in hex notation. 'index' is a mapping of -+ savegame bit -> base bit. -+****************************************************************************/ -+static void sg_extras_set_bv(bv_extras *extras, char ch, -+ struct extra_type **idx) - { - int i, bin; - const char *pch = strchr(hex_chars, ch); -@@ -876,9 +918,146 @@ static void sg_extras_set(bv_extras *extras, char ch, struct extra_type **idx) - in four to a character in hex notation. 'index' is a mapping of - savegame bit -> special bit. S_LAST is used to mark unused savegame bits. - ****************************************************************************/ --static void sg_special_set(struct tile *ptile, bv_extras *extras, char ch, -- const enum tile_special_type *idx, -- bool rivers_overlay) -+static void sg_special_set_dbv(struct tile *ptile, struct dbv *extras, char ch, -+ const enum tile_special_type *idx, -+ bool rivers_overlay) -+{ -+ int i, bin; -+ const char *pch = strchr(hex_chars, ch); -+ -+ if (!pch || ch == '\0') { -+ log_sg("Unknown hex value: '%c' (%d)", ch, ch); -+ bin = 0; -+ } else { -+ bin = pch - hex_chars; -+ } -+ -+ for (i = 0; i < 4; i++) { -+ enum tile_special_type sp = idx[i]; -+ -+ if (sp == S_LAST) { -+ continue; -+ } -+ if (rivers_overlay && sp != S_OLD_RIVER) { -+ continue; -+ } -+ -+ if (sp == S_HUT && !wld.map.server.have_huts) { -+ /* It would be logical to have this in the saving side - -+ * really not saving the huts in the first place, BUT -+ * 1) They have been saved by older versions, so we -+ * have to deal with such savegames. -+ * 2) This makes scenario author less likely to lose -+ * one's work completely after carefully placing huts -+ * and then saving with 'have_huts' disabled. */ -+ continue; -+ } -+ -+ if (bin & (1 << i)) { -+ if (sp == S_OLD_ROAD) { -+ struct road_type *proad; -+ -+ proad = road_by_compat_special(ROCO_ROAD); -+ if (proad) { -+ BV_SET(*extras, extra_index(road_extra_get(proad))); -+ } -+ } else if (sp == S_OLD_RAILROAD) { -+ struct road_type *proad; -+ -+ proad = road_by_compat_special(ROCO_RAILROAD); -+ if (proad) { -+ BV_SET(*extras, extra_index(road_extra_get(proad))); -+ } -+ } else if (sp == S_OLD_RIVER) { -+ struct road_type *proad; -+ -+ proad = road_by_compat_special(ROCO_RIVER); -+ if (proad) { -+ BV_SET(*extras, extra_index(road_extra_get(proad))); -+ } -+ } else { -+ struct extra_type *pextra = NULL; -+ enum extra_cause cause = EC_COUNT; -+ -+ /* Converting from old hardcoded specials to as sensible extra as we can */ -+ switch (sp) { -+ case S_IRRIGATION: -+ case S_FARMLAND: -+ /* If old savegame has both irrigation and farmland, EC_IRRIGATION -+ * gets applied twice, which hopefully has the correct result. */ -+ cause = EC_IRRIGATION; -+ break; -+ case S_MINE: -+ cause = EC_MINE; -+ break; -+ case S_POLLUTION: -+ cause = EC_POLLUTION; -+ break; -+ case S_HUT: -+ cause = EC_HUT; -+ break; -+ case S_FALLOUT: -+ cause = EC_FALLOUT; -+ break; -+ default: -+ pextra = extra_type_by_rule_name(special_rule_name(sp)); -+ break; -+ } -+ -+ if (cause != EC_COUNT) { -+ struct tile *vtile = tile_virtual_new(ptile); -+ struct terrain *pterr = tile_terrain(vtile); -+ const struct req_context tile_ctxt = { .tile = vtile }; -+ -+ /* Do not let the extras already set to the real tile mess with setup -+ * of the player tiles if that's what we're doing. */ -+ dbv_to_bv(vtile->extras.vec, extras); -+ -+ /* It's ok not to know which player or which unit originally built the extra - -+ * in the rules used when specials were saved these could not have made any -+ * difference. */ -+ /* Can't use next_extra_for_tile() as it works for buildable extras only. */ -+ -+ if ((cause != EC_IRRIGATION || pterr->irrigation_time != 0) -+ && (cause != EC_MINE || pterr->mining_time != 0) -+ && (cause != EC_BASE || pterr->base_time != 0) -+ && (cause != EC_ROAD || pterr->road_time != 0)) { -+ extra_type_by_cause_iterate(cause, candidate) { -+ if (!tile_has_extra(vtile, candidate)) { -+ if ((!is_extra_caused_by(candidate, EC_BASE) -+ || tile_city(vtile) != NULL -+ || extra_base_get(candidate)->border_sq <= 0) -+ && are_reqs_active(&tile_ctxt, tile_owner(vtile), -+ &candidate->reqs, -+ RPT_POSSIBLE)) { -+ pextra = candidate; -+ break; -+ } -+ } -+ } extra_type_by_cause_iterate_end; -+ } -+ -+ tile_virtual_destroy(vtile); -+ } -+ -+ if (pextra) { -+ dbv_set(extras, extra_index(pextra)); -+ } -+ } -+ } -+ } -+} -+ -+/************************************************************************//** -+ Complicated helper function for loading specials from a savegame. -+ -+ 'ch' gives the character loaded from the savegame. Specials are packed -+ in four to a character in hex notation. 'index' is a mapping of -+ savegame bit -> special bit. S_LAST is used to mark unused savegame bits. -+****************************************************************************/ -+static void sg_special_set_bv(struct tile *ptile, bv_extras *extras, char ch, -+ const enum tile_special_type *idx, -+ bool rivers_overlay) - { - int i, bin; - const char *pch = strchr(hex_chars, ch); -@@ -1013,7 +1192,39 @@ static void sg_special_set(struct tile *ptile, bv_extras *extras, char ch, - in four to a character in hex notation. 'index' is a mapping of - savegame bit -> base bit. - ****************************************************************************/ --static void sg_bases_set(bv_extras *extras, char ch, struct base_type **idx) -+static void sg_bases_set_dbv(struct dbv *extras, char ch, -+ struct base_type **idx) -+{ -+ int i, bin; -+ const char *pch = strchr(hex_chars, ch); -+ -+ if (!pch || ch == '\0') { -+ log_sg("Unknown hex value: '%c' (%d)", ch, ch); -+ bin = 0; -+ } else { -+ bin = pch - hex_chars; -+ } -+ -+ for (i = 0; i < 4; i++) { -+ struct base_type *pbase = idx[i]; -+ -+ if (pbase == NULL) { -+ continue; -+ } -+ if (bin & (1 << i)) { -+ dbv_set(extras, extra_index(base_extra_get(pbase))); -+ } -+ } -+} -+ -+/************************************************************************//** -+ Helper function for loading bases from a savegame. -+ -+ 'ch' gives the character loaded from the savegame. Bases are packed -+ in four to a character in hex notation. 'index' is a mapping of -+ savegame bit -> base bit. -+****************************************************************************/ -+static void sg_bases_set_bv(bv_extras *extras, char ch, struct base_type **idx) - { - int i, bin; - const char *pch = strchr(hex_chars, ch); -@@ -1044,7 +1255,38 @@ static void sg_bases_set(bv_extras *extras, char ch, struct base_type **idx) - in four to a character in hex notation. 'index' is a mapping of - savegame bit -> road bit. - ****************************************************************************/ --static void sg_roads_set(bv_extras *extras, char ch, struct road_type **idx) -+static void sg_roads_set_dbv(struct dbv *extras, char ch, struct road_type **idx) -+{ -+ int i, bin; -+ const char *pch = strchr(hex_chars, ch); -+ -+ if (!pch || ch == '\0') { -+ log_sg("Unknown hex value: '%c' (%d)", ch, ch); -+ bin = 0; -+ } else { -+ bin = pch - hex_chars; -+ } -+ -+ for (i = 0; i < 4; i++) { -+ struct road_type *proad = idx[i]; -+ -+ if (proad == NULL) { -+ continue; -+ } -+ if (bin & (1 << i)) { -+ dbv_set(extras, extra_index(road_extra_get(proad))); -+ } -+ } -+} -+ -+/************************************************************************//** -+ Helper function for loading roads from a savegame. -+ -+ 'ch' gives the character loaded from the savegame. Roads are packed -+ in four to a character in hex notation. 'index' is a mapping of -+ savegame bit -> road bit. -+****************************************************************************/ -+static void sg_roads_set_bv(bv_extras *extras, char ch, struct road_type **idx) - { - int i, bin; - const char *pch = strchr(hex_chars, ch); -@@ -2050,7 +2292,8 @@ static void sg_load_map_tiles_extras(struct loaddata *loading) - - /* Load extras. */ - halfbyte_iterate_extras(j, loading->extra.size) { -- LOAD_MAP_CHAR(ch, ptile, sg_extras_set(&ptile->extras, ch, loading->extra.order + 4 * j), -+ LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, -+ ch, loading->extra.order + 4 * j), - loading->file, "map.e%02d_%04d", j); - } halfbyte_iterate_extras_end; - } -@@ -2065,8 +2308,8 @@ static void sg_load_map_tiles_bases(struct loaddata *loading) - - /* Load bases. */ - halfbyte_iterate_bases(j, loading->base.size) { -- LOAD_MAP_CHAR(ch, ptile, sg_bases_set(&ptile->extras, ch, -- loading->base.order + 4 * j), -+ LOAD_MAP_CHAR(ch, ptile, sg_bases_set_bv(&ptile->extras, ch, -+ loading->base.order + 4 * j), - loading->file, "map.b%02d_%04d", j); - } halfbyte_iterate_bases_end; - } -@@ -2081,8 +2324,8 @@ static void sg_load_map_tiles_roads(struct loaddata *loading) - - /* Load roads. */ - halfbyte_iterate_roads(j, loading->road.size) { -- LOAD_MAP_CHAR(ch, ptile, sg_roads_set(&ptile->extras, ch, -- loading->road.order + 4 * j), -+ LOAD_MAP_CHAR(ch, ptile, sg_roads_set_bv(&ptile->extras, ch, -+ loading->road.order + 4 * j), - loading->file, "map.r%02d_%04d", j); - } halfbyte_iterate_roads_end; - } -@@ -2111,9 +2354,9 @@ static void sg_load_map_tiles_specials(struct loaddata *loading, - * the rivers overlay but no other specials. Scenarios that encode things - * this way should have the "riversoverlay" capability. */ - halfbyte_iterate_special(j, loading->special.size) { -- LOAD_MAP_CHAR(ch, ptile, sg_special_set(ptile, &ptile->extras, ch, -- loading->special.order + 4 * j, -- rivers_overlay), -+ LOAD_MAP_CHAR(ch, ptile, sg_special_set_bv(ptile, &ptile->extras, ch, -+ loading->special.order + 4 * j, -+ rivers_overlay), - loading->file, "map.spe%02d_%04d", j); - } halfbyte_iterate_special_end; - } -@@ -4751,24 +4994,25 @@ static void sg_load_player_vision(struct loaddata *loading, - /* Load player map (extras). */ - halfbyte_iterate_extras(j, loading->extra.size) { - LOAD_MAP_CHAR(ch, ptile, -- sg_extras_set(&map_get_player_tile(ptile, plr)->extras, -- ch, loading->extra.order + 4 * j), -+ sg_extras_set_dbv(&(map_get_player_tile(ptile, plr)->extras), -+ ch, loading->extra.order + 4 * j), - loading->file, "player%d.map_e%02d_%04d", plrno, j); - } halfbyte_iterate_extras_end; - } else { - /* Load player map (specials). */ - halfbyte_iterate_special(j, loading->special.size) { - LOAD_MAP_CHAR(ch, ptile, -- sg_special_set(ptile, &map_get_player_tile(ptile, plr)->extras, -- ch, loading->special.order + 4 * j, FALSE), -+ sg_special_set_dbv(ptile, -+ &(map_get_player_tile(ptile, plr)->extras), -+ ch, loading->special.order + 4 * j, FALSE), - loading->file, "player%d.map_spe%02d_%04d", plrno, j); - } halfbyte_iterate_special_end; - - /* Load player map (bases). */ - halfbyte_iterate_bases(j, loading->base.size) { - LOAD_MAP_CHAR(ch, ptile, -- sg_bases_set(&map_get_player_tile(ptile, plr)->extras, -- ch, loading->base.order + 4 * j), -+ sg_bases_set_dbv(&(map_get_player_tile(ptile, plr)->extras), -+ ch, loading->base.order + 4 * j), - loading->file, "player%d.map_b%02d_%04d", plrno, j); - } halfbyte_iterate_bases_end; - -@@ -4777,8 +5021,8 @@ static void sg_load_player_vision(struct loaddata *loading, - /* 2.5.0 or newer */ - halfbyte_iterate_roads(j, loading->road.size) { - LOAD_MAP_CHAR(ch, ptile, -- sg_roads_set(&map_get_player_tile(ptile, plr)->extras, -- ch, loading->road.order + 4 * j), -+ sg_roads_set_dbv(&(map_get_player_tile(ptile, plr)->extras), -+ ch, loading->road.order + 4 * j), - loading->file, "player%d.map_r%02d_%04d", plrno, j); - } halfbyte_iterate_roads_end; - } -diff --git a/server/savegame/savegame3.c b/server/savegame/savegame3.c -index a176f9bab9..8e4f51a54a 100644 ---- a/server/savegame/savegame3.c -+++ b/server/savegame/savegame3.c -@@ -308,9 +308,12 @@ static void worklist_save(struct section_file *file, - int max_length, const char *path, ...); - static void unit_ordering_calc(void); - static void unit_ordering_apply(void); --static void sg_extras_set(bv_extras *extras, char ch, struct extra_type **idx); --static char sg_extras_get(bv_extras extras, struct extra_type *presource, -- const int *idx); -+static void sg_extras_set_dbv(struct dbv *extras, char ch, struct extra_type **idx); -+static void sg_extras_set_bv(bv_extras *extras, char ch, struct extra_type **idx); -+static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, -+ const int *idx); -+static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, -+ const int *idx); - static struct terrain *char2terrain(char ch); - static char terrain2char(const struct terrain *pterrain); - static Tech_type_id technology_load(struct section_file *file, -@@ -1089,7 +1092,41 @@ static void unit_ordering_apply(void) - in four to a character in hex notation. 'index' is a mapping of - savegame bit -> base bit. - ****************************************************************************/ --static void sg_extras_set(bv_extras *extras, char ch, struct extra_type **idx) -+static void sg_extras_set_dbv(struct dbv *extras, char ch, -+ struct extra_type **idx) -+{ -+ int i, bin; -+ const char *pch = strchr(hex_chars, ch); -+ -+ if (!pch || ch == '\0') { -+ log_sg("Unknown hex value: '%c' (%d)", ch, ch); -+ bin = 0; -+ } else { -+ bin = pch - hex_chars; -+ } -+ -+ for (i = 0; i < 4; i++) { -+ struct extra_type *pextra = idx[i]; -+ -+ if (pextra == NULL) { -+ continue; -+ } -+ if ((bin & (1 << i)) -+ && (wld.map.server.have_huts || !is_extra_caused_by(pextra, EC_HUT))) { -+ dbv_set(extras, extra_index(pextra)); -+ } -+ } -+} -+ -+/************************************************************************//** -+ Helper function for loading extras from a savegame. -+ -+ 'ch' gives the character loaded from the savegame. Extras are packed -+ in four to a character in hex notation. 'index' is a mapping of -+ savegame bit -> base bit. -+****************************************************************************/ -+static void sg_extras_set_bv(bv_extras *extras, char ch, -+ struct extra_type **idx) - { - int i, bin; - const char *pch = strchr(hex_chars, ch); -@@ -1120,8 +1157,41 @@ static void sg_extras_set(bv_extras *extras, char ch, struct extra_type **idx) - Extras are packed in four to a character in hex notation. 'index' - specifies which set of extras are included in this character. - ****************************************************************************/ --static char sg_extras_get(bv_extras extras, struct extra_type *presource, -- const int *idx) -+static char sg_extras_get_dbv(struct dbv *extras, struct extra_type *presource, -+ const int *idx) -+{ -+ int i, bin = 0; -+ int max = dbv_bits(extras); -+ -+ for (i = 0; i < 4; i++) { -+ int extra = idx[i]; -+ -+ if (extra < 0) { -+ break; -+ } -+ -+ if (extra < max -+ && (dbv_isset(extras, extra) -+ /* An invalid resource, a resource that can't exist at the tile's -+ * current terrain, isn't in the bit extra vector. Save it so it -+ * can return if the tile's terrain changes to something it can -+ * exist on. */ -+ || extra_by_number(extra) == presource)) { -+ bin |= (1 << i); -+ } -+ } -+ -+ return hex_chars[bin]; -+} -+ -+/************************************************************************//** -+ Helper function for saving extras into a savegame. -+ -+ Extras are packed in four to a character in hex notation. 'index' -+ specifies which set of extras are included in this character. -+****************************************************************************/ -+static char sg_extras_get_bv(bv_extras extras, struct extra_type *presource, -+ const int *idx) - { - int i, bin = 0; - -@@ -2905,7 +2975,8 @@ static void sg_load_map_tiles_extras(struct loaddata *loading) - - /* Load extras. */ - halfbyte_iterate_extras(j, loading->extra.size) { -- LOAD_MAP_CHAR(ch, ptile, sg_extras_set(&ptile->extras, ch, loading->extra.order + 4 * j), -+ LOAD_MAP_CHAR(ch, ptile, sg_extras_set_bv(&ptile->extras, ch, -+ loading->extra.order + 4 * j), - loading->file, "map.e%02d_%04d", j); - } halfbyte_iterate_extras_end; - -@@ -2946,7 +3017,7 @@ static void sg_save_map_tiles_extras(struct savedata *saving) - mod[l] = 4 * j + l; - } - } -- SAVE_MAP_CHAR(ptile, sg_extras_get(ptile->extras, ptile->resource, mod), -+ SAVE_MAP_CHAR(ptile, sg_extras_get_bv(ptile->extras, ptile->resource, mod), - saving->file, "map.e%02d_%04d", j); - } halfbyte_iterate_extras_end; - } -@@ -6980,8 +7051,8 @@ static void sg_load_player_vision(struct loaddata *loading, - /* Load player map (extras). */ - halfbyte_iterate_extras(j, loading->extra.size) { - LOAD_MAP_CHAR(ch, ptile, -- sg_extras_set(&map_get_player_tile(ptile, plr)->extras, -- ch, loading->extra.order + 4 * j), -+ sg_extras_set_dbv(&(map_get_player_tile(ptile, plr)->extras), -+ ch, loading->extra.order + 4 * j), - loading->file, "player%d.map_e%02d_%04d", plrno, j); - } halfbyte_iterate_extras_end; - -@@ -7300,9 +7371,9 @@ static void sg_save_player_vision(struct savedata *saving, - } - - SAVE_MAP_CHAR(ptile, -- sg_extras_get(map_get_player_tile(ptile, plr)->extras, -- map_get_player_tile(ptile, plr)->resource, -- mod), -+ sg_extras_get_dbv(&(map_get_player_tile(ptile, plr)->extras), -+ map_get_player_tile(ptile, plr)->resource, -+ mod), - saving->file, "player%d.map_e%02d_%04d", plrno, j); - } halfbyte_iterate_extras_end; - -diff --git a/server/unittools.c b/server/unittools.c -index 566cbcb4c3..05567041ae 100644 ---- a/server/unittools.c -+++ b/server/unittools.c -@@ -3031,13 +3031,18 @@ bool do_paradrop(struct unit *punit, struct tile *ptile, - /* Only take in account values from player map. */ - const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer); - -- if (NULL == plrtile->site -- && !is_native_to_class(unit_class_get(punit), plrtile->terrain, -- &(plrtile->extras))) { -- notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server, -- _("This unit cannot paradrop into %s."), -- terrain_name_translation(plrtile->terrain)); -- return FALSE; -+ if (NULL == plrtile->site) { -+ bv_extras fbv; -+ -+ dbv_to_bv(fbv.vec, &(plrtile->extras)); -+ -+ if (!is_native_to_class(unit_class_get(punit), plrtile->terrain, -+ &fbv)) { -+ notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server, -+ _("This unit cannot paradrop into %s."), -+ terrain_name_translation(plrtile->terrain)); -+ return FALSE; -+ } - } - - if (NULL != plrtile->site --- -2.42.0 - diff --git a/freeciv/version.txt b/freeciv/version.txt index a785a9a93..b8c1a9650 100644 --- a/freeciv/version.txt +++ b/freeciv/version.txt @@ -1,7 +1,7 @@ # The Git SHA hash for the commit to checkout from # https://github.com/freeciv/freeciv -FCREV=019d0cc3f0ebc9864cb0949f14ed85b04b7aa8d4 +FCREV=78e35d10a7d32ce1d4d0a5dbcfc890ca0980b281 ORIGCAPSTR="+Freeciv.Devel-\${MAIN_VERSION}-2023.Oct.09"