From 3814efc5a37316ec6543a46eae598b5b3ffdd5f6 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sat, 14 May 2022 11:00:35 +0300 Subject: [PATCH 36/36] Lua create_city(): Check validity of city creation - Only create the city if it's legal - Return boolean telling if the action succeeded - Revive the player assigned as city owner, if dead - Reveal the city tile for the city owner Reported by ihnatus See osdn #44508 Signed-off-by: Marko Lindqvist --- server/citytools.c | 29 +++++++++++++++++++++++++++++ server/citytools.h | 2 ++ server/edithand.c | 16 ++++------------ server/scripting/api_server_edit.c | 14 +++++--------- server/scripting/api_server_edit.h | 2 +- server/scripting/tolua_server.pkg | 2 +- 6 files changed, 42 insertions(+), 23 deletions(-) diff --git a/server/citytools.c b/server/citytools.c index 3f6ea551bb..a54c498aa4 100644 --- a/server/citytools.c +++ b/server/citytools.c @@ -1635,6 +1635,35 @@ void create_city(struct player *pplayer, struct tile *ptile, CALL_PLR_AI_FUNC(city_got, pplayer, pplayer, pcity); } +/************************************************************************//** + Create city for player, doing necessary checks and adjustments. + + Return whether it was legal to create the city. If not, city was not + created. +****************************************************************************/ +bool create_city_for_player(struct player *pplayer, struct tile *ptile, + const char *name) +{ + if (is_enemy_unit_tile(ptile, pplayer) != NULL + || !city_can_be_built_here(ptile, NULL)) { + return FALSE; + } + + if (!pplayer->is_alive) { + pplayer->is_alive = TRUE; + send_player_info_c(pplayer, NULL); + } + + if (name == NULL || name[0] == '\0') { + name = city_name_suggestion(pplayer, ptile); + } + + map_show_tile(pplayer, ptile); + create_city(pplayer, ptile, name, pplayer); + + return TRUE; +} + /************************************************************************//** Remove a city from the game. ****************************************************************************/ diff --git a/server/citytools.h b/server/citytools.h index d57fb28fb7..339af2dea7 100644 --- a/server/citytools.h +++ b/server/citytools.h @@ -65,6 +65,8 @@ void city_build_free_buildings(struct city *pcity); void create_city(struct player *pplayer, struct tile *ptile, const char *name, struct player *nationality); +bool create_city_for_player(struct player *pplayer, struct tile *ptile, + const char *name); void remove_city(struct city *pcity); struct trade_route *remove_trade_route(struct city *pc1, diff --git a/server/edithand.c b/server/edithand.c index 20d605bdaf..eed7016502 100644 --- a/server/edithand.c +++ b/server/edithand.c @@ -683,25 +683,17 @@ void handle_edit_city_create(struct connection *pc, int owner, int tile, } + conn_list_do_buffer(game.est_connections); - if (is_enemy_unit_tile(ptile, pplayer) != NULL - || !city_can_be_built_here(ptile, NULL)) { + if (!create_city_for_player(pplayer, ptile, NULL)) { notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor, /* TRANS: ..." at ." */ _("A city may not be built at %s."), tile_link(ptile)); - return; - } + conn_list_do_unbuffer(game.est_connections); - if (!pplayer->is_alive) { - pplayer->is_alive = TRUE; - send_player_info_c(pplayer, NULL); + return; } - conn_list_do_buffer(game.est_connections); - - map_show_tile(pplayer, ptile); - create_city(pplayer, ptile, city_name_suggestion(pplayer, ptile), - pplayer); pcity = tile_city(ptile); if (size > 1) { diff --git a/server/scripting/api_server_edit.c b/server/scripting/api_server_edit.c index f1b54b8481..9906ad75d9 100644 --- a/server/scripting/api_server_edit.c +++ b/server/scripting/api_server_edit.c @@ -574,19 +574,15 @@ bool api_edit_change_terrain(lua_State *L, Tile *ptile, Terrain *pterr) /**********************************************************************//** Create a new city. **************************************************************************/ -void api_edit_create_city(lua_State *L, Player *pplayer, Tile *ptile, +bool api_edit_create_city(lua_State *L, Player *pplayer, Tile *ptile, const char *name) { - LUASCRIPT_CHECK_STATE(L); - LUASCRIPT_CHECK_ARG_NIL(L, pplayer, 2, Player); - LUASCRIPT_CHECK_ARG_NIL(L, ptile, 3, Tile); - - if (!name || name[0] == '\0') { - name = city_name_suggestion(pplayer, ptile); - } + LUASCRIPT_CHECK_STATE(L, FALSE); + LUASCRIPT_CHECK_ARG_NIL(L, pplayer, 2, Player, FALSE); + LUASCRIPT_CHECK_ARG_NIL(L, ptile, 3, Tile, FALSE); /* TODO: Allow initial citizen to be of nationality other than owner */ - create_city(pplayer, ptile, name, pplayer); + return create_city_for_player(pplayer, ptile, name); } /**********************************************************************//** diff --git a/server/scripting/api_server_edit.h b/server/scripting/api_server_edit.h index e52d00957b..63d1d4d019 100644 --- a/server/scripting/api_server_edit.h +++ b/server/scripting/api_server_edit.h @@ -69,7 +69,7 @@ void api_edit_unit_kill(lua_State *L, Unit *punit, const char *reason, bool api_edit_change_terrain(lua_State *L, Tile *ptile, Terrain *pterr); -void api_edit_create_city(lua_State *L, Player *pplayer, Tile *ptile, +bool api_edit_create_city(lua_State *L, Player *pplayer, Tile *ptile, const char *name); void api_edit_remove_city(lua_State *L, City *pcity); void api_edit_create_building(lua_State *L, City *pcity, Building_Type *impr); diff --git a/server/scripting/tolua_server.pkg b/server/scripting/tolua_server.pkg index 3f5b1defc3..219d0883fd 100644 --- a/server/scripting/tolua_server.pkg +++ b/server/scripting/tolua_server.pkg @@ -126,7 +126,7 @@ module edit { Player *killer); bool api_edit_change_terrain @ change_terrain(lua_State *L, Tile *ptile, Terrain *pterr); - void api_edit_create_city + bool api_edit_create_city @ create_city (lua_State *L, Player *pplayer, Tile *ptile, const char *name); void api_edit_remove_city -- 2.35.1