remove ai.synced_command

fixes #1649 . ai.synced_command could easily be used to implement all types of
undeteced cheats so it was removed. As a replacement this commit adds a
[custom_command] synced command that just calls
wesnoth.game_events.on_synced_command which calls a lua handler that
must first be set.
This commit is contained in:
gfgtdf 2018-03-16 00:35:42 +01:00
parent e752a172d1
commit fef953a48e
15 changed files with 101 additions and 35 deletions

View file

@ -60,6 +60,7 @@
{scenario-story.cfg}
{ai/scenarios/}
{ai/micro_ais/scenarios/}
{ai/utils/custom_command.cfg}
#define DONT_RELOAD_CORE
#enddef

View file

@ -3,6 +3,7 @@ local W = H.set_wml_action_metatable {}
local AH = wesnoth.require "ai/lua/ai_helper.lua"
local LS = wesnoth.require "location_set"
local M = wesnoth.map
local T = H.set_wml_tag_metatable {}
local function get_forest_animals(cfg)
-- We want the deer/rabbits to move first, tuskers afterward
@ -157,8 +158,7 @@ function ca_forest_animals_move:execution(cfg)
-- If this is a rabbit ending on a hole -> disappears
if (unit.type == rabbit_type) and hole_map:get(farthest_hex[1], farthest_hex[2]) then
local command = "wesnoth.erase_unit(x1, y1)"
ai.synced_command(command, farthest_hex[1], farthest_hex[2])
wesnoth.invoke_synced_command("rabbit_despawn", { x = farthest_hex[1], y = farthest_hex[2]})
end
end

View file

@ -1,6 +1,7 @@
local H = wesnoth.require "helper"
local W = H.set_wml_action_metatable {}
local AH = wesnoth.require "ai/lua/ai_helper.lua"
local T = H.set_wml_tag_metatable {}
local ca_forest_animals_new_rabbit = {}
@ -58,12 +59,7 @@ function ca_forest_animals_new_rabbit:execution(cfg)
x, y = wesnoth.find_vacant_tile(holes[i].x, holes[i].y)
end
local command = "wesnoth.put_unit({ side = "
.. wesnoth.current.side
.. ", type = '"
.. cfg.rabbit_type
.. "' }, x1, y1)"
ai.synced_command(command, x, y)
wesnoth.invoke_synced_command("rabbit_spawn", { rabbit_type = cfg.rabbit_type, x = x, y = y})
end
if wesnoth.sides[wesnoth.current.side].shroud then

View file

@ -0,0 +1,18 @@
#define ENABLE_AI_COMMAND_RABBIT_SPAWN
[lua]
code = <<
function wesnoth.custom_synced_commands.rabbit_despawn(cfg)
--TODO: maybe we only want to allow erasing of unit of certain types/sides/locations ?
wesnoth.erase_unit(cfg.x, cfg.y)
end
function wesnoth.custom_synced_commands.rabbit_spawn(cfg)
--TODO: maybe we only want to allow creation of unit of certain types/sides/locations ?
wesnoth.put_unit({ side = wesnoth.current.side, type = cfg.rabbit_type}, cfg.x, cfg.y)
end
>>
[/lua]
#enddef

View file

@ -1,6 +1,7 @@
local H = wesnoth.require "helper"
local LS = wesnoth.require "location_set"
local M = wesnoth.map
local T = H.set_wml_tag_metatable {}
local ca_transport = {}
@ -110,29 +111,12 @@ function ca_transport:execution()
-- Also unload units
table.sort(best_adj_tiles, function(a, b) return a[3] > b[3] end)
local command = "local unit = wesnoth.get_unit(x1, y1) "
.. "unit.variables.landed = 'yes' "
.. "unit.variables.destination_x = 1 "
.. "unit.variables.destination_y = 30"
ai.synced_command(command, best_unit.x, best_unit.y)
local command_data = { x = best_unit.x, y = best_unit.y }
for i = 1, math.min(#best_adj_tiles, 3) do
table.insert(command_data, T.dst { x = best_adj_tiles[i][1], y = best_adj_tiles[i][2]} )
end
-- Unload 1 level 2 unit
local l2_type = H.rand('Swordsman,Javelineer,Pikeman')
local command = "wesnoth.put_unit({ side = " .. wesnoth.current.side
.. ", type = '" .. l2_type
.. "', moves = 2 }, "
.. best_adj_tiles[1][1] .. "," .. best_adj_tiles[1][2] .. ")"
ai.synced_command(command, best_unit.x, best_unit.y)
-- Unload up to 2 level 1 units
for i = 2, math.min(#best_adj_tiles, 3) do
local l1_type = H.rand('Fencer,Mage,Cavalryman,Bowman,Spearman')
local command = "wesnoth.put_unit({ side = " .. wesnoth.current.side
.. ", type = '" .. l1_type
.. "', moves = 2 }, "
.. best_adj_tiles[i][1] .. "," .. best_adj_tiles[i][2] .. ")"
ai.synced_command(command, best_unit.x, best_unit.y)
end
wesnoth.invoke_synced_command("ship_unload", command_data)
return
end

View file

@ -83,6 +83,7 @@
[/side]
{SOTBE_TRACK {JOURNEY_06_NEW} }
{ENABLE_AI_COMMAND_CA_TRANSPORT_S6}
[event]
name=prestart

View file

@ -199,3 +199,30 @@
[/unstore_unit]
[/event]
#enddef
#define ENABLE_AI_COMMAND_CA_TRANSPORT_S6
[lua]
code = <<
local helper = wesnoth.require "helper"
function wesnoth.custom_synced_commands.ship_unload(cfg)
local unit = wesnoth.get_unit(cfg.x, cfg.y)
unit.variables.landed = 'yes'
unit.variables.destination_x = 1
unit.variables.destination_y = 30
local locs = helper.child_array(cfg, "dst")
local l2_type = helper.rand('Swordsman,Javelineer,Pikeman')
wesnoth.put_unit({ side = wesnoth.current.side, type = l2_type, moves = 2 }, locs[1].x, locs[1].y)
for i = 2, #locs do
local l1_type = helper.rand('Fencer,Mage,Cavalryman,Bowman,Spearman')
wesnoth.put_unit({ side = wesnoth.current.side, type = l1_type, moves = 2 }, locs[i].x, locs[i].y)
end
end
>>
[/lua]
#enddef

View file

@ -8,6 +8,7 @@
wesnoth.dofile 'lua/backwards-compatibility.lua'
wesnoth.dofile 'lua/wml-tags.lua'
wesnoth.dofile 'lua/feeding.lua'
wesnoth.dofile 'lua/custom_command.lua'
>>
[/lua]

View file

@ -0,0 +1,20 @@
local helper = wesnoth.require "helper"
local T = helper.set_wml_tag_metatable {}
wesnoth.custom_synced_commands = {}
function wesnoth.game_events.on_synced_command(cfg)
local handler = wesnoth.custom_synced_commands[cfg.name]
local data = helper.get_child(cfg, "data")
if handler then
handler(data)
end
end
function wesnoth.register_synced_command(name, handler)
wesnoth.custom_synced_commands[name] = handler
end
function wesnoth.invoke_synced_command(name, data)
wesnoth.wml_actions.do_command { T.custom_command { name=name, T.data(data) } }
end

View file

@ -968,7 +968,7 @@ void synced_command_result::do_execute()
}
s << lua_code_;
synced_context::run_in_synced_context_if_not_already("lua_ai", replay_helper::get_lua_ai(s.str()));
//synced_context::run_in_synced_context_if_not_already("lua_ai", replay_helper::get_lua_ai(s.str()));
try {
set_gamestate_changed();

View file

@ -273,6 +273,12 @@ static int cfun_ai_check_stopunit(lua_State *L)
static int ai_synced_command(lua_State *L, bool exec)
{
#if 1
(void)L;
(void)exec;
ERR_LUA << "synced_command was removed, use wesnoth.wml_actions.do_command with [custom_command] instead\n";
return 0;
#else
const char *lua_code = luaL_checkstring(L, 1);
int side = get_readonly_context(L).get_side();
map_location location;
@ -283,6 +289,7 @@ static int ai_synced_command(lua_State *L, bool exec)
ai::synced_command_result_ptr synced_command_result = ai::actions::execute_synced_command_action(side,exec,std::string(lua_code),location);
return transform_ai_action(L,synced_command_result);
#endif
}
static int cfun_ai_execute_synced_command(lua_State *L)

View file

@ -281,7 +281,7 @@ WML_HANDLER_FUNCTION(do_command,, cfg)
return;
}
static const std::set<std::string> allowed_tags {"attack", "move", "recruit", "recall", "disband", "fire_event", "lua_ai"};
static const std::set<std::string> allowed_tags {"attack", "move", "recruit", "recall", "disband", "fire_event", "custom_command"};
const bool is_too_early = resources::gamedata->phase() != game_data::START && resources::gamedata->phase() != game_data::PLAY;
const bool is_unsynced_too_early = resources::gamedata->phase() != game_data::PLAY;

View file

@ -4395,6 +4395,17 @@ bool game_lua_kernel::run_event(const game_events::queued_event& ev)
return true;
}
void game_lua_kernel::custom_command(const config& cfg)
{
lua_State *L = mState;
if (!luaW_getglobal(L, "wesnoth", "game_events", "on_synced_command")) {
return;
}
luaW_pushconfig(L, cfg);
luaW_pcall(L, 1, 0, false);
}
/**
* Applies its upvalue as an effect
* Arg 1: The unit to apply to

View file

@ -200,6 +200,7 @@ public:
void save_game(config & level);
void load_game(const config& level);
bool run_event(const game_events::queued_event&);
void custom_command(const config&);
void push_builtin_effect();
void set_wml_action(const std::string&, game_events::wml_action::handler);
void set_wml_condition(const std::string&, bool(*)(const vconfig&));

View file

@ -344,11 +344,10 @@ SYNCED_COMMAND_HANDLER_FUNCTION(fire_event, child, use_undo, /*show*/, /*error_
return true;
}
SYNCED_COMMAND_HANDLER_FUNCTION(lua_ai, child, /*use_undo*/, /*show*/, /*error_handler*/)
SYNCED_COMMAND_HANDLER_FUNCTION(custom_command, child, /*use_undo*/, /*show*/, /*error_handler*/)
{
const std::string &lua_code = child["code"];
assert(resources::lua_kernel);
resources::lua_kernel->run(lua_code.c_str());
resources::lua_kernel->custom_command(child);
return true;
}