From d5791eb8fe0b93fb0cf814667be416957f3bf2d4 Mon Sep 17 00:00:00 2001 From: Ihnatus Date: Fri, 3 Jun 2022 23:44:06 +0300 Subject: [PATCH] Unify Lua handling of creating a building in a city with editor: * can move a great wonder; * can't build a Special building; * refreshes cities and auto-arranges workers if their radius changes. See OSDN#44696 Signed-off-by: Ihnatus --- server/citytools.c | 38 +++++++++++++++++++++++++++++ server/citytools.h | 3 +++ server/edithand.c | 27 ++++++++------------- server/scripting/api_server_edit.c | 39 +++++++++++++++++------------- 4 files changed, 73 insertions(+), 34 deletions(-) diff --git a/server/citytools.c b/server/citytools.c index 14f4347a3c..afe5448a94 100644 --- a/server/citytools.c +++ b/server/citytools.c @@ -2839,6 +2839,44 @@ void do_sell_building(struct player *pplayer, struct city *pcity, } } +/************************************************************************//** + Creates an improvement in a city. If the improvement is a present wonder, + moves it from a city it is in now, returns that city. + If it is a wonder not present (never built or destroyed), returns pcity. + If the wonder is great, also tells its owner. + If it is not a wonder (must be a regular improvement), returns NULL. + It's up to the caller to update the necessary cities and emit signals. + FIXME: If governmental center status of a city is changed, check if other + cities of its owner need update. And what's there with trade partners? + FIXME: it is not checked if the improvement is obsolete or obsoletes + other building, should we? +****************************************************************************/ +struct city +*build_or_move_building(struct city *pcity, struct impr_type *pimprove, + struct player **oldcity_owner) +{ + struct city *oldcity = NULL; + + fc_assert_ret_val(!city_has_building(pcity, pimprove), NULL); + if (is_great_wonder(pimprove)) { + if (!(oldcity = city_from_great_wonder(pimprove))) { + oldcity = pcity; + } + *oldcity_owner = city_owner(oldcity); + } else if (is_small_wonder(pimprove)) { + if (!(oldcity + = city_from_small_wonder(city_owner(pcity), pimprove))) { + oldcity = pcity; + } + } + if (oldcity && oldcity != pcity) { + city_remove_improvement(oldcity, pimprove); + } + + city_add_improvement(pcity, pimprove); + return oldcity; +} + /************************************************************************//** Remove building from the city. Emits lua signal. ****************************************************************************/ diff --git a/server/citytools.h b/server/citytools.h index 339af2dea7..8f336da6d5 100644 --- a/server/citytools.h +++ b/server/citytools.h @@ -77,6 +77,9 @@ bool city_illness_strike(struct city *pcity); void do_sell_building(struct player *pplayer, struct city *pcity, struct impr_type *pimprove, const char *reason); +struct city +*build_or_move_building(struct city *pcity, struct impr_type *pimprove, + struct player **oldcity_owner); bool building_removed(struct city *pcity, const struct impr_type *pimprove, const char *reason, struct unit *destroyer); void building_lost(struct city *pcity, const struct impr_type *pimprove, diff --git a/server/edithand.c b/server/edithand.c index eed7016502..d662995f40 100644 --- a/server/edithand.c +++ b/server/edithand.c @@ -790,30 +790,23 @@ void handle_edit_city(struct connection *pc, } else if (!city_has_building(pcity, pimprove) && packet->built[id] >= 0) { + struct player *old_owner = NULL; - if (is_great_wonder(pimprove)) { - oldcity = city_from_great_wonder(pimprove); - if (oldcity != pcity) { - BV_SET(need_player_info, player_index(pplayer)); - } - if (NULL != oldcity && city_owner(oldcity) != pplayer) { - /* Great wonders make more changes. */ - need_game_info = TRUE; - BV_SET(need_player_info, player_index(city_owner(oldcity))); - } - } else if (is_small_wonder(pimprove)) { - oldcity = city_from_small_wonder(pplayer, pimprove); - if (oldcity != pcity) { - BV_SET(need_player_info, player_index(pplayer)); + oldcity = build_or_move_building(pcity, pimprove, &old_owner); + if (oldcity != pcity) { + BV_SET(need_player_info, player_index(pplayer)); + } + if (oldcity && old_owner != pplayer) { + /* Great wonders make more changes. */ + need_game_info = TRUE; + if (old_owner) { + BV_SET(need_player_info, player_index(old_owner)); } } if (oldcity) { - city_remove_improvement(oldcity, pimprove); city_refresh_queue_add(oldcity); } - - city_add_improvement(pcity, pimprove); changed = TRUE; } } improvement_iterate_end; diff --git a/server/scripting/api_server_edit.c b/server/scripting/api_server_edit.c index 609aa9a0e7..97d7bbde22 100644 --- a/server/scripting/api_server_edit.c +++ b/server/scripting/api_server_edit.c @@ -33,6 +33,7 @@ #include "aiiface.h" #include "barbarian.h" #include "citytools.h" +#include "cityturn.h" /* city_refresh() auto_arrange_workers() */ #include "console.h" /* enum rfc_status */ #include "gamehand.h" #include "maphand.h" @@ -682,38 +683,42 @@ void api_edit_create_building(lua_State *L, City *pcity, Building_Type *impr) LUASCRIPT_CHECK_STATE(L); LUASCRIPT_CHECK_ARG_NIL(L, pcity, 2, City); LUASCRIPT_CHECK_ARG_NIL(L, impr, 3, Building_Type); + /* FIXME: may "Special" impr be buildable? */ + LUASCRIPT_CHECK_ARG(L, !is_special_improvement(impr), 3, + "It is a special item, not a city building"); if (!city_has_building(pcity, impr)) { bool need_game_info = FALSE; bool need_plr_info = FALSE; + struct player *old_owner = NULL, *pplayer = city_owner(pcity); + struct city *oldcity; - if (is_great_wonder(impr)) { - if (city_from_great_wonder(impr) != NULL) { - /* Can't rebuild great wonders */ - return; - } - - need_game_info = TRUE; + oldcity = build_or_move_building(pcity, impr, &old_owner); + if (oldcity) { need_plr_info = TRUE; - } else if (is_small_wonder(impr)) { - struct city *oldcity = city_from_small_wonder(city_owner(pcity), impr); + } + if (old_owner && old_owner != pplayer) { + /* Great wonders make more changes. */ + need_game_info = TRUE; + } - /* Since we already checked that pcity does not have the building, - * we can be sure it's not the same as oldcity. */ - city_remove_improvement(oldcity, impr); + if (oldcity) { + if (city_refresh(oldcity)) { + auto_arrange_workers(oldcity); + } send_city_info(NULL, oldcity); - - need_plr_info = TRUE; } - city_add_improvement(pcity, impr); + if (city_refresh(pcity)) { + auto_arrange_workers(pcity); + } send_city_info(NULL, pcity); - if (need_game_info) { send_game_info(NULL); + send_player_info_c(old_owner, NULL); } if (need_plr_info) { - send_player_info_c(city_owner(pcity), NULL); + send_player_info_c(pplayer, NULL); } } } -- 2.34.1