From e9dc98f12617a12a723e86848c8c03edc412f754 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Tue, 26 Jul 2022 15:21:15 +0300 Subject: [PATCH 51/51] Move unit tech_req to internal build_reqs vector See osdn #44927 Signed-off-by: Marko Lindqvist --- client/packhand.c | 1 - common/networking/packets.def | 1 - common/unittype.c | 48 +++++++++++------------------------ common/unittype.h | 12 ++++----- fc_version | 2 +- server/ruleset.c | 14 ++++++---- tools/ruledit/edit_utype.cpp | 33 ++++++++++++++++++++++-- tools/ruleutil/rulesave.c | 17 ++++++++++++- 8 files changed, 77 insertions(+), 51 deletions(-) diff --git a/client/packhand.c b/client/packhand.c index a43b4d231c..be31568fdd 100644 --- a/client/packhand.c +++ b/client/packhand.c @@ -3538,7 +3538,6 @@ void handle_ruleset_unit(const struct packet_ruleset_unit *p) u->attack_strength = p->attack_strength; u->defense_strength = p->defense_strength; u->move_rate = p->move_rate; - u->_retire.require_advance = advance_by_number(p->tech_requirement); for (i = 0; i < p->build_reqs_count; i++) { requirement_vector_append(&u->build_reqs, p->build_reqs[i]); } diff --git a/common/networking/packets.def b/common/networking/packets.def index f34dcd97ab..8ec7594f9f 100644 --- a/common/networking/packets.def +++ b/common/networking/packets.def @@ -1382,7 +1382,6 @@ PACKET_RULESET_UNIT = 140; sc, lsend UINT8 attack_strength; UINT8 defense_strength; MOVEFRAGS move_rate; - TECH tech_requirement; UINT8 build_reqs_count; REQUIREMENT build_reqs[MAX_NUM_REQS:build_reqs_count]; UINT16 vision_radius_sq; diff --git a/common/unittype.c b/common/unittype.c index be7fac737b..507d704406 100644 --- a/common/unittype.c +++ b/common/unittype.c @@ -2057,11 +2057,13 @@ bool can_player_build_unit_direct(const struct player *p, return FALSE; } + barbarian = is_barbarian(p); + requirement_vector_iterate(&punittype->build_reqs, preq) { if (preq->source.kind == VUT_IMPROVEMENT && preq->range == REQ_RANGE_CITY && preq->present) { /* If the unit has a building requirement, we check to see if the - * player can build that building. Note that individual cities may + * player can build that building. Note that individual cities may * not have that building, so they still may not be able to build the * unit. */ if (is_great_wonder(preq->source.value.building) @@ -2091,42 +2093,22 @@ bool can_player_build_unit_direct(const struct player *p, /* The question *here* is if the *player* can build this unit */ continue; } - if (!is_req_active(&context, NULL, preq, RPT_CERTAIN)) { - return FALSE; - } - } requirement_vector_iterate_end; - unit_tech_reqs_iterate(punittype, padv) { - if (research_invention_state(research_get(p), advance_number(padv)) - != TECH_KNOWN) { - if (!barbarian) { - /* Normal players can never build units without knowing tech - * requirements. */ + if (preq->source.kind == VUT_ADVANCE && barbarian && preq->range < REQ_RANGE_WORLD + && utype_has_role(punittype, L_BARBARIAN_BUILD)) { + /* Barbarians can build L_BARBARIAN_BUILD when anyone has the tech requirements. */ + struct requirement copy; + + req_copy(©, preq); + copy.range = REQ_RANGE_WORLD; + + if (!is_req_active(&context, NULL, ©, RPT_CERTAIN)) { return FALSE; } - if (!utype_has_role(punittype, L_BARBARIAN_BUILD)) { - /* Even barbarian cannot build this unit without tech */ - - /* Unit has to have L_BARBARIAN_BUILD_TECH role - * In the beginning of this function we checked that - * barbarian player tries to build only role - * L_BARBARIAN_BUILD or L_BARBARIAN_BUILD_TECH units. */ - fc_assert_ret_val(utype_has_role(punittype, L_BARBARIAN_BUILD_TECH), - FALSE); - - /* Client does not know all the advances other players have - * got. So following gives wrong answer in the client. - * This is called at the client when received create_city - * packet for a barbarian city. City initialization tries - * to find L_FIRSTBUILD unit. */ - - if (!game.info.global_advances[advance_index(padv)]) { - /* Nobody knows required tech */ - return FALSE; - } - } + } else if (!is_req_active(&context, NULL, preq, RPT_CERTAIN)) { + return FALSE; } - } unit_tech_reqs_iterate_end; + } requirement_vector_iterate_end; if (utype_player_already_has_this_unique(p, punittype)) { /* A player can only have one unit of each unique unit type. */ diff --git a/common/unittype.h b/common/unittype.h index f2721b44d0..adb427007d 100644 --- a/common/unittype.h +++ b/common/unittype.h @@ -497,10 +497,6 @@ struct unit_type { int move_rate; int unknown_move_cost; /* See utype_unknown_move_cost(). */ - struct { - struct advance *require_advance; /* may be NULL */ - } _retire; /* Do not write new code to rely on things here! */ - struct requirement_vector build_reqs; int vision_radius_sq; @@ -853,11 +849,13 @@ const struct unit_type *unit_type_array_last(void); #define unit_tech_reqs_iterate(_utype_, _p) \ do { \ - struct advance *_p = (_utype_)->_retire.require_advance; \ - if (advance_number(_p) != A_NONE) { + requirement_vector_iterate(&(_utype_)->build_reqs, preq_##_p) { \ + if (preq_##_p->source.kind == VUT_ADVANCE) { \ + struct advance *_p = preq_##_p->source.value.advance; #define unit_tech_reqs_iterate_end \ - } \ + } \ + } requirement_vector_iterate_end; \ } while (FALSE); /* Used on client to show just one req */ diff --git a/fc_version b/fc_version index 7f0092c654..c638ef6e5e 100755 --- a/fc_version +++ b/fc_version @@ -60,7 +60,7 @@ DEFAULT_FOLLOW_TAG=S3_2 # - No new mandatory capabilities can be added to the release branch; doing # so would break network capability of supposedly "compatible" releases. # -NETWORK_CAPSTRING="+Freeciv.Devel-3.2-2022.Jul.24" +NETWORK_CAPSTRING="+Freeciv.Devel-3.2-2022.Jul.26" FREECIV_DISTRIBUTOR="" diff --git a/server/ruleset.c b/server/ruleset.c index 1125f27aff..6b34e2e3d0 100644 --- a/server/ruleset.c +++ b/server/ruleset.c @@ -2140,18 +2140,24 @@ static bool load_ruleset_units(struct section_file *file, const int i = utype_index(u); const struct section *psection = section_list_get(sec, i); const char *sec_name = section_name(psection); + struct advance *adv_req; - if (!lookup_tech(file, &u->_retire.require_advance, sec_name, + if (!lookup_tech(file, &adv_req, sec_name, "tech_req", filename, rule_name_get(&u->name))) { ok = FALSE; break; } - if (u->_retire.require_advance == A_NEVER) { + if (adv_req == A_NEVER) { ruleset_error(LOG_ERROR, "%s lacks valid tech_req.", rule_name_get(&u->name)); ok = FALSE; break; + } else if (adv_req != A_NONE) { + requirement_vector_append(&u->build_reqs, + req_from_values(VUT_ADVANCE, REQ_RANGE_PLAYER, + FALSE, TRUE, FALSE, + advance_number(adv_req))); } /* Read the government build requirement from the old ruleset format @@ -2171,6 +2177,7 @@ static bool load_ruleset_units(struct section_file *file, if (NULL != section_entry_by_name(psection, "gov_req")) { char tmp[200] = "\0"; struct government *need_government; + fc_strlcat(tmp, section_name(psection), sizeof(tmp)); fc_strlcat(tmp, ".gov_req", sizeof(tmp)); need_government = lookup_government(file, tmp, filename, NULL); @@ -7833,9 +7840,6 @@ static void send_ruleset_units(struct conn_list *dest) packet.attack_strength = u->attack_strength; packet.defense_strength = u->defense_strength; packet.move_rate = u->move_rate; - packet.tech_requirement = u->_retire.require_advance - ? advance_number(u->_retire.require_advance) - : advance_count(); i = 0; requirement_vector_iterate(&u->build_reqs, req) { diff --git a/tools/ruledit/edit_utype.cpp b/tools/ruledit/edit_utype.cpp index a39b09559e..cc439464b9 100644 --- a/tools/ruledit/edit_utype.cpp +++ b/tools/ruledit/edit_utype.cpp @@ -121,7 +121,7 @@ void edit_utype::closeEvent(QCloseEvent *cevent) **************************************************************************/ void edit_utype::refresh() { - req_button->setText(tab_tech::tech_name(utype->_retire.require_advance)); + req_button->setText(tab_tech::tech_name(utype_primary_tech_req(utype))); bcost->setValue(utype->build_cost); attack->setValue(utype->attack_strength); defense->setValue(utype->defense_strength); @@ -140,7 +140,36 @@ void edit_utype::req_menu(QAction *action) padv = advance_by_rule_name(an_bytes.data()); if (padv != nullptr) { - utype->_retire.require_advance = padv; + if (padv != advance_by_number(A_NONE)) { + bool found = FALSE; + + requirement_vector_iterate(&utype->build_reqs, preq) { + if (preq->source.kind == VUT_ADVANCE) { + preq->source.value.advance = padv; + found = TRUE; + break; + } + } requirement_vector_iterate_end; + + if (!found) { + requirement_vector_append(&utype->build_reqs, + req_from_values(VUT_ADVANCE, REQ_RANGE_PLAYER, + FALSE, TRUE, FALSE, + advance_number(padv))); + } + } else { + size_t i; + size_t vsize = requirement_vector_size(&utype->build_reqs); + + for (i = 0; i < vsize; i++) { + struct requirement *cur = requirement_vector_get(&utype->build_reqs, i); + + if (cur->source.kind == VUT_ADVANCE) { + requirement_vector_remove(&utype->build_reqs, i); + break; + } + } + } refresh(); } diff --git a/tools/ruleutil/rulesave.c b/tools/ruleutil/rulesave.c index 6370349374..8d066c2b0e 100644 --- a/tools/ruleutil/rulesave.c +++ b/tools/ruleutil/rulesave.c @@ -3089,7 +3089,22 @@ static bool save_units_ruleset(const char *filename, const char *name) secfile_insert_str(sfile, uclass_rule_name(put->uclass), "%s.class", path); - save_tech_ref(sfile, put->_retire.require_advance, path, "tech_req"); + /* Extract the tech requirement from the requirement vector so + * it can be written in the old format. + * The build_reqs requirement vector isn't ready to be exposed in the + * ruleset yet. */ + requirement_vector_iterate(&put->build_reqs, preq) { + if (preq->source.kind == VUT_ADVANCE) { + fc_assert_msg(preq->range == REQ_RANGE_PLAYER, + "can't convert non player range to the rs format"); + fc_assert_msg(preq->present, + "can't convert not present reqs to the rs format"); + secfile_insert_str(sfile, + universal_rule_name(&preq->source), + "%s.tech_req", path); + break; /* We save first one only */ + } + } requirement_vector_iterate_end; /* Extract the government requirement from the requirement vector so * it can be written in the old format. -- 2.35.1