Merge pull request #710 from spixi/call_events_by_id
Allow firing an event by id instead of name.
This commit is contained in:
commit
dc3d22a5e4
14 changed files with 130 additions and 37 deletions
|
@ -188,6 +188,7 @@ Version 1.13.5:
|
|||
* Added new attribute "registered_users_only" to MultiplayerServerWML which indicates
|
||||
that only registered users should be allowed to join the game
|
||||
* wesnoth now does a stricter check for unit type ids.
|
||||
* Added tag id= [fire_event], which allows raising events by id
|
||||
* Lua API:
|
||||
* wesnoth.match_unit can now take a location (rather than a unit) as
|
||||
the optional third parameter. This will cause the filter to consider
|
||||
|
@ -276,7 +277,9 @@ Version 1.13.5:
|
|||
* [lua] tags now also support the [args] subtag outside events.
|
||||
* added lua_function= attribute in location filters
|
||||
* Added on_event.lua which is an eaiser to use wrapper for
|
||||
wesnoth.game_events.on_event
|
||||
wesnoth.game_events.on_event
|
||||
* Added new functions wesnoth.fire_event_by_id and fire_event_by_name. The old
|
||||
function wesnoth.fire_event is now an alias for wesnoth.fire_event_by_name
|
||||
* Multiplayer:
|
||||
* Hornshark Island: simplified multiplayer faction determination
|
||||
* Added "Registered users only" checkbox to multiplayer configuration dialog which
|
||||
|
|
|
@ -141,7 +141,9 @@ function wml_actions.fire_event(cfg)
|
|||
local w2 = helper.get_child(cfg, "secondary_attack")
|
||||
if w2 then w1 = w1 or {} end
|
||||
|
||||
wesnoth.fire_event(cfg.name, x1, y1, x2, y2, w1, w2)
|
||||
if cfg.id and cfg.id ~= "" then wesnoth.fire_event_by_id(cfg.id, x1, y1, x2, y2, w1, w2)
|
||||
elseif cfg.name and cfg.name ~= "" then wesnoth.fire_event_by_name(cfg.name, x1, y1, x2, y2, w1, w2)
|
||||
end
|
||||
end
|
||||
|
||||
function wml_actions.allow_recruit(cfg)
|
||||
|
|
|
@ -216,3 +216,20 @@
|
|||
{RETURN ({VARIABLE_CONDITIONAL pass_test equals 1})}
|
||||
[/event]
|
||||
)}
|
||||
|
||||
{GENERIC_UNIT_TEST "event_handlers_in_events_9" (
|
||||
[event]
|
||||
name=start
|
||||
{VARIABLE pass_test 0}
|
||||
[event]
|
||||
name=foo
|
||||
id=test
|
||||
{VARIABLE pass_test 1}
|
||||
[/event]
|
||||
|
||||
[fire_event]
|
||||
id=test
|
||||
[/fire_event]
|
||||
{RETURN ({VARIABLE_CONDITIONAL pass_test equals 1})}
|
||||
[/event]
|
||||
)}
|
|
@ -110,7 +110,7 @@ namespace {
|
|||
scoped_weapon_info w1("weapon", e.data.child("first"));
|
||||
scoped_weapon_info w2("second_weapon", e.data.child("second"));
|
||||
|
||||
game_events::queued_event q(tag, map_location(x1, y1), map_location(x2, y2), e.data);
|
||||
game_events::queued_event q(tag, "", map_location(x1, y1), map_location(x2, y2), e.data);
|
||||
resources::lua_kernel->run_wml_action("command", vconfig(e.commands), q);
|
||||
|
||||
if(u1) {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "config.hpp"
|
||||
#include "utils/smart_list.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
|
|
|
@ -58,6 +58,11 @@ void manager::remove_event_handler(const std::string & id)
|
|||
event_handlers_->remove_event_handler(id);
|
||||
}
|
||||
|
||||
/** Gets an event handler by id */
|
||||
const handler_ptr manager::get_event_handler_by_id(const std::string & id)
|
||||
{
|
||||
return event_handlers_->get_event_handler_by_id(id);
|
||||
}
|
||||
|
||||
/* ** manager ** */
|
||||
|
||||
|
|
|
@ -109,6 +109,8 @@ namespace game_events {
|
|||
void add_event_handler(const config & handler, bool is_menu_item=false);
|
||||
/// Removes an event handler.
|
||||
void remove_event_handler(const std::string & id);
|
||||
/// Gets an event handler by ID
|
||||
const handler_ptr get_event_handler_by_id(const std::string & id);
|
||||
|
||||
void add_events(const config::const_child_itors &cfgs,
|
||||
const std::string& type = std::string());
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "resources.hpp"
|
||||
#include "scripting/game_lua_kernel.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "soundsource.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
@ -165,4 +164,12 @@ namespace game_events {
|
|||
log_handlers();
|
||||
}
|
||||
|
||||
const handler_ptr t_event_handlers::get_event_handler_by_id(const std::string & id) {
|
||||
id_map_t::iterator find_it = id_map_.find(id);
|
||||
if ( find_it != id_map_.end() && !find_it->second.expired() ) {
|
||||
return handler_ptr( find_it->second );
|
||||
}
|
||||
return handler_ptr( );
|
||||
}
|
||||
|
||||
} // end namespace game_events
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "game_events/handlers.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace game_events {
|
||||
|
@ -60,6 +61,8 @@ namespace game_events {
|
|||
void add_event_handler(const config & cfg, manager & man, bool is_menu_item=false);
|
||||
/// Removes an event handler, identified by its ID.
|
||||
void remove_event_handler(std::string const & id);
|
||||
/// Gets an event handler, identified by its ID.
|
||||
const handler_ptr get_event_handler_by_id(const std::string & id);
|
||||
|
||||
iterator begin() { return active_.begin(); }
|
||||
const_iterator begin() const { return active_.begin(); }
|
||||
|
|
|
@ -267,6 +267,8 @@ namespace { // Support functions
|
|||
*/
|
||||
bool t_pump::process_event(handler_ptr& handler_p, const queued_event& ev)
|
||||
{
|
||||
DBG_EH << "processing event " << ev.name << " with id=" << ev.id << "\n";
|
||||
|
||||
// We currently never pass a null pointer to this function, but to
|
||||
// guard against future modifications:
|
||||
if ( !handler_p )
|
||||
|
@ -466,7 +468,18 @@ bool t_pump::fire(const std::string& event,
|
|||
return (*this)();
|
||||
}
|
||||
|
||||
bool t_pump::fire(const std::string& event,
|
||||
const std::string& id,
|
||||
const entity_location& loc1,
|
||||
const entity_location& loc2,
|
||||
const config& data)
|
||||
{
|
||||
raise(event,id,loc1,loc2,data);
|
||||
return (*this)();
|
||||
}
|
||||
|
||||
void t_pump::raise(const std::string& event,
|
||||
const std::string& id,
|
||||
const entity_location& loc1,
|
||||
const entity_location& loc2,
|
||||
const config& data)
|
||||
|
@ -474,9 +487,9 @@ void t_pump::raise(const std::string& event,
|
|||
if(resources::screen == nullptr)
|
||||
return;
|
||||
|
||||
DBG_EH << "raising event: " << event << "\n";
|
||||
DBG_EH << "raising event name=" << event << ", id=" << id << "\n";
|
||||
|
||||
impl_->events_queue.push_back(queued_event(event, loc1, loc2, data));
|
||||
impl_->events_queue.push_back(queued_event(event, id, loc1, loc2, data));
|
||||
}
|
||||
|
||||
bool t_pump::operator()()
|
||||
|
@ -497,7 +510,7 @@ bool t_pump::operator()()
|
|||
if(!lg::debug().dont_log("event_handler")) {
|
||||
std::stringstream ss;
|
||||
for(const queued_event& ev : impl_->events_queue) {
|
||||
ss << "name=" << ev.name << "; ";
|
||||
ss << "name=" << ev.name << ", " << "id=" << ev.id << "; ";
|
||||
}
|
||||
DBG_EH << "processing queued events: " << ss.str() << "\n";
|
||||
}
|
||||
|
@ -513,7 +526,12 @@ bool t_pump::operator()()
|
|||
while ( !pump_instance.done() )
|
||||
{
|
||||
queued_event & ev = pump_instance.next();
|
||||
|
||||
if( ev.name.empty() and ev.id.empty() )
|
||||
continue;
|
||||
|
||||
const std::string& event_name = ev.name;
|
||||
const std::string& event_id = ev.id;
|
||||
|
||||
// Clear the unit cache, since the best clearing time is hard to figure out
|
||||
// due to status changes by WML. Every event will flush the cache.
|
||||
|
@ -525,30 +543,39 @@ bool t_pump::operator()()
|
|||
++impl_->internal_wml_tracking;
|
||||
}
|
||||
}
|
||||
// Initialize an iteration over event handlers matching this event.
|
||||
|
||||
assert(impl_->my_manager);
|
||||
manager::iteration handler_iter(event_name, *impl_->my_manager);
|
||||
|
||||
// If there are any matching event handlers, initialize variables.
|
||||
// Note: Initializing variables all the time would not be
|
||||
// functionally wrong, merely inefficient. So we do not have
|
||||
// to cache *handler_iter here.
|
||||
if ( *handler_iter ) {
|
||||
resources::gamedata->get_variable("x1") = ev.loc1.filter_x() + 1;
|
||||
resources::gamedata->get_variable("y1") = ev.loc1.filter_y() + 1;
|
||||
resources::gamedata->get_variable("x2") = ev.loc2.filter_x() + 1;
|
||||
resources::gamedata->get_variable("y2") = ev.loc2.filter_y() + 1;
|
||||
handler_ptr cur_handler;
|
||||
|
||||
resources::gamedata->get_variable("x1") = ev.loc1.filter_x() + 1;
|
||||
resources::gamedata->get_variable("y1") = ev.loc1.filter_y() + 1;
|
||||
resources::gamedata->get_variable("x2") = ev.loc2.filter_x() + 1;
|
||||
resources::gamedata->get_variable("y2") = ev.loc2.filter_y() + 1;
|
||||
|
||||
if ( event_id.empty() ) {
|
||||
|
||||
// Initialize an iteration over event handlers matching this event.
|
||||
manager::iteration handler_iter(event_name, *impl_->my_manager);
|
||||
|
||||
// While there is a potential handler for this event name.
|
||||
while ( cur_handler = *handler_iter ) {
|
||||
// Let this handler process our event.
|
||||
process_event(cur_handler, ev);
|
||||
// NOTE: cur_handler may be null at this point!
|
||||
|
||||
++handler_iter;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
// While there is a potential handler for this event name.
|
||||
while ( handler_ptr cur_handler = *handler_iter ) {
|
||||
DBG_EH << "processing event " << event_name << " with id="<<
|
||||
cur_handler->get_config()["id"] << "\n";
|
||||
// Let this handler process our event.
|
||||
process_event(cur_handler, ev);
|
||||
// NOTE: cur_handler may be null at this point!
|
||||
//Get the handler directly via ID
|
||||
cur_handler = impl_->my_manager->get_event_handler_by_id( event_id );
|
||||
|
||||
++handler_iter;
|
||||
if( cur_handler ) {
|
||||
process_event(cur_handler, ev);
|
||||
}
|
||||
}
|
||||
|
||||
// Flush messages when finished iterating over event_handlers.
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
|
||||
#include "config.hpp"
|
||||
|
||||
#include<string>
|
||||
#include<sstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
class game_display;
|
||||
class vconfig;
|
||||
|
@ -44,14 +44,15 @@ namespace lg { class logger; }
|
|||
namespace game_events
|
||||
{
|
||||
struct queued_event {
|
||||
queued_event(const std::string& name, const entity_location& loc1,
|
||||
queued_event(const std::string& name, const std::string& id, const entity_location& loc1,
|
||||
const entity_location& loc2, const config& data)
|
||||
: name(name), loc1(loc1), loc2(loc2), data(data)
|
||||
: name(name), id(id), loc1(loc1), loc2(loc2), data(data)
|
||||
{
|
||||
std::replace(this->name.begin(), this->name.end(), ' ', '_');
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string id;
|
||||
entity_location loc1;
|
||||
entity_location loc2;
|
||||
config data;
|
||||
|
@ -92,11 +93,25 @@ namespace game_events
|
|||
const entity_location& loc2=entity_location::null_entity,
|
||||
const config& data=config());
|
||||
|
||||
bool fire(const std::string& event,
|
||||
const std::string& id,
|
||||
const entity_location& loc1=entity_location::null_entity,
|
||||
const entity_location& loc2=entity_location::null_entity,
|
||||
const config& data=config());
|
||||
|
||||
void raise(const std::string& event,
|
||||
const std::string& id,
|
||||
const entity_location& loc1=entity_location::null_entity,
|
||||
const entity_location& loc2=entity_location::null_entity,
|
||||
const config& data=config());
|
||||
|
||||
inline void raise(const std::string& event,
|
||||
const entity_location& loc1=entity_location::null_entity,
|
||||
const entity_location& loc2=entity_location::null_entity,
|
||||
const config& data=config()) {
|
||||
raise(event,"",loc1,loc2,data);
|
||||
}
|
||||
|
||||
bool operator()();
|
||||
|
||||
/**
|
||||
|
|
|
@ -144,7 +144,7 @@ void menu_handler::objectives(int side_num)
|
|||
config cfg;
|
||||
cfg["side"] = std::to_string(side_num);
|
||||
gamestate().lua_kernel_->run_wml_action("show_objectives", vconfig(cfg),
|
||||
game_events::queued_event("_from_interface", map_location(),
|
||||
game_events::queued_event("_from_interface", "", map_location(),
|
||||
map_location(), config()));
|
||||
team ¤t_team = teams()[side_num - 1];
|
||||
dialogs::show_objectives(pc_.get_scenario_name(), current_team.objectives());
|
||||
|
|
|
@ -1045,14 +1045,14 @@ int game_lua_kernel::intf_get_recall_units(lua_State *L)
|
|||
|
||||
/**
|
||||
* Fires an event.
|
||||
* - Arg 1: string containing the event name.
|
||||
* - Arg 1: string containing the event name or id.
|
||||
* - Arg 2: optional first location.
|
||||
* - Arg 3: optional second location.
|
||||
* - Arg 4: optional WML table used as the [weapon] tag.
|
||||
* - Arg 5: optional WML table used as the [second_weapon] tag.
|
||||
* - Ret 1: boolean indicating whether the event was processed or not.
|
||||
*/
|
||||
int game_lua_kernel::intf_fire_event(lua_State *L)
|
||||
int game_lua_kernel::intf_fire_event(lua_State *L, const bool by_id)
|
||||
{
|
||||
char const *m = luaL_checkstring(L, 1);
|
||||
|
||||
|
@ -1076,11 +1076,19 @@ int game_lua_kernel::intf_fire_event(lua_State *L)
|
|||
data.add_child("second", luaW_checkconfig(L, pos));
|
||||
}
|
||||
|
||||
bool b = play_controller_.pump().fire(m, l1, l2, data);
|
||||
bool b = false;
|
||||
|
||||
if (by_id) {
|
||||
b = play_controller_.pump().fire("", m, l1, l2, data);
|
||||
}
|
||||
else {
|
||||
b = play_controller_.pump().fire(m, l1, l2, data);
|
||||
}
|
||||
lua_pushboolean(L, b);
|
||||
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.
|
||||
|
@ -1737,6 +1745,7 @@ int game_lua_kernel::impl_current_get(lua_State *L)
|
|||
const game_events::queued_event &ev = get_event_info();
|
||||
config cfg;
|
||||
cfg["name"] = ev.name;
|
||||
cfg["id"] = ev.id;
|
||||
if (const config &weapon = ev.data.child("first")) {
|
||||
cfg.add_child("weapon", weapon);
|
||||
}
|
||||
|
@ -4582,7 +4591,7 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
|
|||
, queued_events_()
|
||||
, map_locked_(0)
|
||||
{
|
||||
static game_events::queued_event default_queued_event("_from_lua", map_location(), map_location(), config());
|
||||
static game_events::queued_event default_queued_event("_from_lua", "", map_location(), map_location(), config());
|
||||
queued_events_.push(&default_queued_event);
|
||||
|
||||
lua_State *L = mState;
|
||||
|
@ -4635,7 +4644,9 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
|
|||
{ "find_path", &dispatch<&game_lua_kernel::intf_find_path > },
|
||||
{ "find_reach", &dispatch<&game_lua_kernel::intf_find_reach > },
|
||||
{ "find_vacant_tile", &dispatch<&game_lua_kernel::intf_find_vacant_tile > },
|
||||
{ "fire_event", &dispatch<&game_lua_kernel::intf_fire_event > },
|
||||
{ "fire_event", &dispatch2<&game_lua_kernel::intf_fire_event, false > },
|
||||
{ "fire_event_by_name", &dispatch2<&game_lua_kernel::intf_fire_event, false > },
|
||||
{ "fire_event_by_id", &dispatch2<&game_lua_kernel::intf_fire_event, true > },
|
||||
{ "fire_wml_menu_item", &dispatch<&game_lua_kernel::intf_fire_wml_menu_item > },
|
||||
{ "float_label", &dispatch<&game_lua_kernel::intf_float_label > },
|
||||
{ "gamestate_inspector", &dispatch<&game_lua_kernel::intf_gamestate_inspector > },
|
||||
|
|
|
@ -162,7 +162,7 @@ class game_lua_kernel : public lua_kernel_base
|
|||
int impl_theme_items_set(lua_State *L);
|
||||
int cfun_builtin_effect(lua_State *L);
|
||||
int cfun_wml_action(lua_State *L);
|
||||
int intf_fire_event(lua_State *L);
|
||||
int intf_fire_event(lua_State *L, const bool by_id);
|
||||
int intf_fire_wml_menu_item(lua_State *L);
|
||||
int intf_teleport(lua_State *L);
|
||||
int intf_remove_sound_source(lua_State *L);
|
||||
|
|
Loading…
Add table
Reference in a new issue