From 8459bf7104e6f13bdbea073879bf07862d843b26 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Mon, 5 Jan 2015 20:34:12 -0500 Subject: [PATCH] add lua function "fire_wml_menu_item" and unit tests for menu items this commit also changed slightly the way that wml menu events are synced. previously they were run via "run_in_synced_context", now they are run via "run_in_synced_context_if_not_already", which makes it safe to fire them from lua (a synced context). --- data/test/scenarios/test_menu_items.cfg | 118 ++++++++++++++++++++++++ src/game_events/menu_item.cpp | 2 +- src/scripting/game_lua_kernel.cpp | 26 ++++++ src/scripting/game_lua_kernel.hpp | 1 + wml_test_schedule | 6 ++ 5 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 data/test/scenarios/test_menu_items.cfg diff --git a/data/test/scenarios/test_menu_items.cfg b/data/test/scenarios/test_menu_items.cfg new file mode 100644 index 00000000000..16847145e8c --- /dev/null +++ b/data/test/scenarios/test_menu_items.cfg @@ -0,0 +1,118 @@ +# +# Test if wml menu items are working +# + +{GENERIC_UNIT_TEST "test_wml_menu_items_1" ( + [event] + name = start + + [set_menu_item] + id=test1 + description="store location" + [command] + {VARIABLE mx $x1} + {VARIABLE my $y1} + [/command] + [/set_menu_item] + + [lua] + code = << wesnoth.fire_wml_menu_item("test1", 3, 3) >> + [/lua] + + {ASSERT {VARIABLE_CONDITIONAL mx equals 3}} + {ASSERT {VARIABLE_CONDITIONAL my equals 3}} + {RETURN ([true][/true])} + [/event] +)} + +# +# This test should be failing although you might think it succeeds. +# The test asserts that if filter_location for a menu_item is false, +# it should return false if wesnoth attempts to fire it. However this +# isn't the case, filter_location is normally checked before the +# attempt to fire it. +# +{GENERIC_UNIT_TEST "test_wml_menu_items_2" ( + [event] + name = start + + [set_menu_item] + id=test2 + description="spawn a unit" + [filter_location] + [not] + [have_unit] + x=$x1 + y=$y1 + [/have_unit] + [/not] + [/filter_location] + [command] + {UNIT 2 "Orcish Grunt" $x1 $y1 ()} + [/command] + [/set_menu_item] + + [lua] + code = << r = wesnoth.fire_wml_menu_item("test2", 3, 3) + r = r and not wesnoth.fire_wml_menu_item("test2", 3, 3) + r = r and wesnoth.fire_wml_menu_item("test2", 4, 4) + r = r and not wesnoth.fire_wml_menu_item("test2", 4, 4) + wesnoth.set_variable("result", r) >> + [/lua] + + {RETURN {VARIABLE_CONDITIONAL result boolean_equals true}} + [/event] +)} + +# +# An ammended form of the above test, which checks a menu item which creates a unit, +# being fired twice. +# +{GENERIC_UNIT_TEST "test_wml_menu_items_3" ( + [event] + name = start + + [set_menu_item] + id=test3 + description="Summon Troll" + [show_if] + [not] + [have_unit] + x,y=$x1,$y1 + [/have_unit] + [/not] + [/show_if] + [filter_location] + [/filter_location] + [command] + {NAMED_LOYAL_UNIT $side_number (Troll) $x1 $y1 (MagicTroll) ("Magic Troll")} + [fire_event] + name=apply_troll_skin + [primary_unit] + x=$x1 + y=$y1 + [/primary_unit] + [/fire_event] + [/command] + [/set_menu_item] + + [lua] + code = << r = wesnoth.fire_wml_menu_item("test3", 3, 3) >> + [/lua] + {ASSERT ([have_unit] + x,y = 3,3 + [/have_unit])} + + [lua] + code = << r = r and wesnoth.fire_wml_menu_item("test3", 4, 4) >> + [/lua] + {ASSERT ([have_unit] + x,y = 4,4 + [/have_unit])} + + [lua] + code = << wesnoth.set_variable("result", r) >> + [/lua] + {RETURN {VARIABLE_CONDITIONAL result boolean_equals true}} + [/event] +)} diff --git a/src/game_events/menu_item.cpp b/src/game_events/menu_item.cpp index c9ff9beca2a..713a05700df 100644 --- a/src/game_events/menu_item.cpp +++ b/src/game_events/menu_item.cpp @@ -212,7 +212,7 @@ void wml_menu_item::fire_event(const map_location & event_hex, const game_data & } else { - synced_context::run_in_synced_context("fire_event", replay_helper::get_event(event_name_, event_hex, NULL)); + synced_context::run_in_synced_context_if_not_already("fire_event", replay_helper::get_event(event_name_, event_hex, NULL)); } } diff --git a/src/scripting/game_lua_kernel.cpp b/src/scripting/game_lua_kernel.cpp index 191d83fec7a..0d3f8222f27 100644 --- a/src/scripting/game_lua_kernel.cpp +++ b/src/scripting/game_lua_kernel.cpp @@ -666,6 +666,31 @@ int game_lua_kernel::intf_fire_event(lua_State *L) return 1; } +/** + * Fires a wml menu item. + * - Arg 1: id of the item. it is not possible to fire items that don't have ids with this function. + * - Arg 2,3: optional first location. + * - Ret 1: boolean, true indicating that the event was fired successfully + * + * NOTE: This is not an "official" feature, it may currently cause assertion failures if used with + * menu items which have "needs_select". It is not supported right now to use it this way. + * The purpose of this function right now is to make it possible to have automated sanity tests for + * the wml menu items system. + */ +int game_lua_kernel::intf_fire_wml_menu_item(lua_State *L) +{ + char const *m = luaL_checkstring(L, 1); + + map_location l1; + + l1.x = luaL_checkinteger(L, 2) - 1; + l1.y = luaL_checkinteger(L, 3) - 1; + + bool b = gamedata().get_wml_menu_items().fire_item(m, l1, gamedata(), game_state_, units()); + lua_pushboolean(L, b); + return 1; +} + /** * Gets a WML variable. * - Arg 1: string containing the variable name. @@ -3643,6 +3668,7 @@ game_lua_kernel::game_lua_kernel(const config &cfg, CVideo * video, game_state & { "find_reach", boost::bind(&game_lua_kernel::intf_find_reach, this, _1 )}, { "find_vacant_tile", boost::bind(&game_lua_kernel::intf_find_vacant_tile, this, _1 )}, { "fire_event", boost::bind(&game_lua_kernel::intf_fire_event, this, _1 )}, + { "fire_wml_menu_item", boost::bind(&game_lua_kernel::intf_fire_wml_menu_item, this, _1 )}, { "float_label", boost::bind(&game_lua_kernel::intf_float_label, this, _1 )}, { "gamestate_inspector", boost::bind(&game_lua_kernel::intf_gamestate_inspector, this, _1 )}, { "get_all_vars", boost::bind(&game_lua_kernel::intf_get_all_vars, this, _1 )}, diff --git a/src/scripting/game_lua_kernel.hpp b/src/scripting/game_lua_kernel.hpp index da3b0c83134..de161fbc9db 100644 --- a/src/scripting/game_lua_kernel.hpp +++ b/src/scripting/game_lua_kernel.hpp @@ -151,6 +151,7 @@ class game_lua_kernel : public lua_kernel_base int impl_theme_items_set(lua_State *L); int cfun_wml_action(lua_State *L); int intf_fire_event(lua_State *L); + int intf_fire_wml_menu_item(lua_State *L); //private helpers std::string synced_state(); diff --git a/wml_test_schedule b/wml_test_schedule index 651410c7d45..6d38e975bb5 100644 --- a/wml_test_schedule +++ b/wml_test_schedule @@ -125,3 +125,9 @@ 0 recruit_facing_enemy_two 0 recruit_facing_leader 0 recruit_facing_center +# +# Interface tests +# +0 test_wml_menu_items_1 +1 test_wml_menu_items_2 +0 test_wml_menu_items_3