Merge branch 'lua'

This commit is contained in:
Chris Beck 2014-12-26 17:18:22 -05:00
commit 53b1309691
18 changed files with 450 additions and 314 deletions

View file

@ -9,8 +9,6 @@
local pretty_print_limit = 20
local max_depth = 7
local table_clever = true
-- suppress strict warnings
_ = true
-- imported global functions
local sub = string.sub
@ -102,7 +100,6 @@ function ilua._pretty_print(...)
for i,val in ipairs(arg) do
print(ilua.val2str(val))
end
_G['_'] = arg[1]
end
--

View file

@ -0,0 +1,12 @@
{GENERIC_UNIT_TEST "lua_get_sides" (
[event]
name = prestart
[lua]
code = << local s = wesnoth.get_sides({})
local result = (s[1].side == 1) and (s[1].name == "Alice") and (s[2].side == 2) and (s[2].name == "Bob")
wesnoth.set_variable("result", result) >>
[/lua]
{RETURN ({VARIABLE_CONDITIONAL result boolean_equals true})}
[/event]
)}

View file

@ -971,7 +971,9 @@ set(wesnoth-main_SRC
scripting/lua_kernel_base.cpp
scripting/lua_map_location_ops.cpp
scripting/lua_rng.cpp
scripting/lua_team.cpp
scripting/lua_types.cpp
scripting/lua_unit_type.cpp
scripting/mapgen_lua_kernel.cpp
scripting/plugins/context.cpp
scripting/plugins/manager.cpp

View file

@ -544,7 +544,9 @@ wesnoth_sources = Split("""
scripting/lua_kernel_base.cpp
scripting/lua_map_location_ops.cpp
scripting/lua_rng.cpp
scripting/lua_team.cpp
scripting/lua_types.cpp
scripting/lua_unit_type.cpp
scripting/mapgen_lua_kernel.cpp
scripting/plugins/context.cpp
scripting/plugins/manager.cpp

View file

@ -127,9 +127,12 @@ bool application_lua_kernel::thread::is_running() {
return started_ ? (lua_status(T_) == LUA_YIELD) : (lua_status(T_) == LUA_OK);
}
static char * v_threadtableKey = 0;
static void * const threadtableKey = static_cast<void *> (& v_threadtableKey);
static lua_State * get_new_thread(lua_State * L)
{
lua_pushlightuserdata(L , currentscriptKey);
lua_pushlightuserdata(L , threadtableKey);
lua_pushvalue(L,1); // duplicate script key, since we need to store later
// stack is now [script key] [script key]

View file

@ -77,7 +77,9 @@
#include "scripting/lua_common.hpp"
#include "scripting/lua_cpp_function.hpp"
#include "scripting/lua_gui2.hpp" // for show_gamestate_inspector
#include "scripting/lua_team.hpp"
#include "scripting/lua_types.hpp" // for getunitKey, dlgclbkKey, etc
#include "scripting/lua_unit_type.hpp"
#include "sdl/utils.hpp" // for surface
#include "side_filter.hpp" // for side_filter
#include "sound.hpp" // for commit_music_changes, etc
@ -198,33 +200,6 @@ namespace {
};
}//unnamed namespace for queued_event_context
/**
* Gets some data on a unit type (__index metamethod).
* - Arg 1: table containing an "id" field.
* - Arg 2: string containing the name of the property.
* - Ret 1: something containing the attribute.
*/
static int impl_unit_type_get(lua_State *L)
{
char const *m = luaL_checkstring(L, 2);
lua_pushstring(L, "id");
lua_rawget(L, 1);
const unit_type *utp = unit_types.find(lua_tostring(L, -1));
if (!utp) return luaL_argerror(L, 1, "unknown unit type");
unit_type const &ut = *utp;
// Find the corresponding attribute.
return_tstring_attrib("name", ut.type_name());
return_int_attrib("max_hitpoints", ut.hitpoints());
return_int_attrib("max_moves", ut.movement());
return_int_attrib("max_experience", ut.experience_needed());
return_int_attrib("cost", ut.cost());
return_int_attrib("level", ut.level());
return_int_attrib("recall_cost", ut.recall_cost());
return_cfgref_attrib("__cfg", ut.get_cfg());
return 0;
}
/**
* Gets some data on a race (__index metamethod).
* - Arg 1: table containing an "id" field.
@ -483,8 +458,8 @@ static int impl_unit_variables_set(lua_State *L)
v = lua_tostring(L, 3);
break;
case LUA_TUSERDATA:
if (luaW_hasmetatable(L, 3, tstringKey)) {
v = *static_cast<t_string *>(lua_touserdata(L, 3));
if (t_string * t_str = static_cast<t_string *> (luaL_testudata(L, 3, tstringKey))) {
v = *t_str;
break;
}
// no break
@ -777,8 +752,8 @@ int game_lua_kernel::intf_set_variable(lua_State *L)
v.as_scalar() = lua_tostring(L, 2);
break;
case LUA_TUSERDATA:
if (luaW_hasmetatable(L, 2, tstringKey)) {
v.as_scalar() = *static_cast<t_string *>(lua_touserdata(L, 2));
if (t_string * t_str = static_cast<t_string*> (luaL_testudata(L, 2, tstringKey))) {
v.as_scalar() = *t_str;
break;
}
// no break
@ -959,101 +934,6 @@ int game_lua_kernel::intf_lock_view(lua_State *L)
return 0;
}
/**
* Gets some data on a side (__index metamethod).
* - Arg 1: full userdata containing the team.
* - Arg 2: string containing the name of the property.
* - Ret 1: something containing the attribute.
*/
static int impl_side_get(lua_State *L)
{
// Hidden metamethod, so arg1 has to be a pointer to a team.
team &t = **static_cast<team **>(lua_touserdata(L, 1));
char const *m = luaL_checkstring(L, 2);
// Find the corresponding attribute.
return_int_attrib("side", t.side());
return_int_attrib("gold", t.gold());
return_tstring_attrib("objectives", t.objectives());
return_int_attrib("village_gold", t.village_gold());
return_int_attrib("village_support", t.village_support());
return_int_attrib("recall_cost", t.recall_cost());
return_int_attrib("base_income", t.base_income());
return_int_attrib("total_income", t.total_income());
return_bool_attrib("objectives_changed", t.objectives_changed());
return_bool_attrib("fog", t.uses_fog());
return_bool_attrib("shroud", t.uses_shroud());
return_bool_attrib("hidden", t.hidden());
return_bool_attrib("scroll_to_leader", t.get_scroll_to_leader());
return_string_attrib("flag", t.flag());
return_string_attrib("flag_icon", t.flag_icon());
return_tstring_attrib("user_team_name", t.user_team_name());
return_string_attrib("team_name", t.team_name());
return_string_attrib("name", t.name());
return_string_attrib("color", t.color());
return_cstring_attrib("controller", team::CONTROLLER_to_string(t.controller()).c_str());
return_string_attrib("defeat_condition", team::DEFEAT_CONDITION_to_string(t.defeat_condition()));
return_bool_attrib("lost", t.lost());
if (strcmp(m, "recruit") == 0) {
std::set<std::string> const &recruits = t.recruits();
lua_createtable(L, recruits.size(), 0);
int i = 1;
BOOST_FOREACH(std::string const &r, t.recruits()) {
lua_pushstring(L, r.c_str());
lua_rawseti(L, -2, i++);
}
return 1;
}
return_cfg_attrib("__cfg", t.write(cfg));
return 0;
}
/**
* Sets some data on a side (__newindex metamethod).
* - Arg 1: full userdata containing the team.
* - Arg 2: string containing the name of the property.
* - Arg 3: something containing the attribute.
*/
static int impl_side_set(lua_State *L)
{
// Hidden metamethod, so arg1 has to be a pointer to a team.
team &t = **static_cast<team **>(lua_touserdata(L, 1));
char const *m = luaL_checkstring(L, 2);
// Find the corresponding attribute.
modify_int_attrib("gold", t.set_gold(value));
modify_tstring_attrib("objectives", t.set_objectives(value, true));
modify_int_attrib("village_gold", t.set_village_gold(value));
modify_int_attrib("village_support", t.set_village_support(value));
modify_int_attrib("recall_cost", t.set_recall_cost(value));
modify_int_attrib("base_income", t.set_base_income(value));
modify_bool_attrib("objectives_changed", t.set_objectives_changed(value));
modify_bool_attrib("hidden", t.set_hidden(value));
modify_bool_attrib("scroll_to_leader", t.set_scroll_to_leader(value));
modify_tstring_attrib("user_team_name", t.change_team(t.team_name(), value));
modify_string_attrib("team_name", t.change_team(value, t.user_team_name()));
modify_string_attrib("controller", t.change_controller_by_wml(value));
modify_string_attrib("color", t.set_color(value));
modify_string_attrib("defeat_condition", t.set_defeat_condition_string(value));
modify_bool_attrib("lost", t.set_lost(value));
if (strcmp(m, "recruit") == 0) {
t.set_recruits(std::set<std::string>());
if (!lua_istable(L, 3)) return 0;
for (int i = 1;; ++i) {
lua_rawgeti(L, 3, i);
if (lua_isnil(L, -1)) break;
t.add_recruit(lua_tostring(L, -1));
lua_pop(L, 1);
}
return 0;
}
return luaL_argerror(L, 2, "unknown modifiable property");
}
/**
* Gets a terrain code.
* - Args 1,2: map location.
@ -2899,25 +2779,12 @@ int game_lua_kernel::intf_get_sides(lua_State* L)
sides = filter.get_teams();
}
//keep this stack in the loop:
//1: getsideKey getmetatable
//2: return table
//3: userdata for a side
//4: getsideKey metatable copy (of index 1)
lua_settop(L, 0);
lua_pushlightuserdata(L
, getsideKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_createtable(L, sides.size(), 0);
unsigned index = 1;
BOOST_FOREACH(int side, sides) {
// Create a full userdata containing a pointer to the team.
team** t = static_cast<team**>(lua_newuserdata(L, sizeof(team*)));
*t = &(teams()[side - 1]);
lua_pushvalue(L, 1);
lua_setmetatable(L, 3);
lua_rawseti(L, 2, index);
luaW_pushteam(L, teams()[side - 1]);
lua_rawseti(L, -2, index);
++index;
}
@ -3775,30 +3642,10 @@ game_lua_kernel::game_lua_kernel(const config &cfg, CVideo * video, game_state &
lua_setglobal(L, "wesnoth");
// Create the getside metatable.
cmd_log_ << "Adding getside metatable...\n";
lua_pushlightuserdata(L
, getsideKey);
lua_createtable(L, 0, 3);
lua_pushcfunction(L, impl_side_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, impl_side_set);
lua_setfield(L, -2, "__newindex");
lua_pushstring(L, "side");
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);
cmd_log_ << lua_team::register_metatable(L);
// Create the gettype metatable.
cmd_log_ << "Adding gettype metatable...\n";
lua_pushlightuserdata(L
, gettypeKey);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, impl_unit_type_get);
lua_setfield(L, -2, "__index");
lua_pushstring(L, "unit type");
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);
cmd_log_ << lua_unit_type::register_metatable(L);
//Create the getrace metatable
cmd_log_ << "Adding getrace metatable...\n";
@ -3939,45 +3786,34 @@ void game_lua_kernel::initialize()
// Still needed for backwards compatibility.
lua_getglobal(L, "wesnoth");
lua_pushlightuserdata(L
, getsideKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_createtable(L, teams().size(), 0);
for (unsigned i = 0; i != teams().size(); ++i)
{
// Create a full userdata containing a pointer to the team.
team **p = static_cast<team **>(lua_newuserdata(L, sizeof(team *)));
*p = &teams()[i];
lua_pushvalue(L, -3);
lua_setmetatable(L, -2);
lua_rawseti(L, -2, i + 1);
lua_pushstring(L, "get_sides");
lua_rawget(L, -2);
lua_createtable(L, 0, 0);
if (!protected_call(1, 1, boost::bind(&lua_kernel_base::log_error, this, _1, _2))) {
cmd_log_ << "Failed to compute wesnoth.sides\n";
} else {
lua_setfield(L, -2, "sides");
cmd_log_ << "Added wesnoth.sides\n";
}
lua_setfield(L, -3, "sides");
lua_pop(L, 2);
// Create the unit_types table.
cmd_log_ << "Adding unit_types table...\n";
lua_settop(L, 0);
lua_getglobal(L, "wesnoth");
lua_pushlightuserdata(L
, gettypeKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_newtable(L);
BOOST_FOREACH(const unit_type_data::unit_type_map::value_type &ut, unit_types.types())
{
lua_createtable(L, 0, 1);
lua_pushstring(L, ut.first.c_str());
lua_setfield(L, -2, "id");
lua_pushvalue(L, -3);
lua_setmetatable(L, -2);
luaW_pushunittype(L, ut.first);
lua_setfield(L, -2, ut.first.c_str());
}
lua_setfield(L, -3, "unit_types");
lua_pop(L, 2);
lua_setfield(L, -2, "unit_types");
//Create the races table.
cmd_log_ << "Adding races table...\n";
lua_settop(L, 0);
lua_getglobal(L, "wesnoth");
lua_pushlightuserdata(L
, getraceKey);

View file

@ -39,6 +39,10 @@
#include <new> // for operator new
#include <string> // for string, basic_string
static const char * gettextKey = "gettext";
static const char * vconfigKey = "vconfig";
const char * tstringKey = "translatable string";
namespace lua_common {
/**
@ -65,13 +69,11 @@ int intf_textdomain(lua_State *L)
{
size_t l;
char const *m = luaL_checklstring(L, 1, &l);
void *p = lua_newuserdata(L, l + 1);
memcpy(p, m, l + 1);
lua_pushlightuserdata(L
, gettextKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
luaL_setmetatable(L, gettextKey);
return 1;
}
@ -108,17 +110,12 @@ static int impl_tstring_concat(lua_State *L)
{
// Create a new t_string.
t_string *t = new(lua_newuserdata(L, sizeof(t_string))) t_string;
lua_pushlightuserdata(L
, tstringKey);
lua_rawget(L, LUA_REGISTRYINDEX);
luaL_setmetatable(L, tstringKey);
// Append both arguments to t.
tstring_concat_aux(L, *t, 1);
tstring_concat_aux(L, *t, 2);
lua_setmetatable(L, -2);
return 1;
}
@ -159,15 +156,11 @@ static int impl_vconfig_get(lua_State *L)
unsigned pos = lua_tointeger(L, 2) - 1;
if (pos >= len) return 0;
std::advance(i, pos);
lua_createtable(L, 2, 0);
lua_pushstring(L, i.get_key().c_str());
lua_rawseti(L, -2, 1);
new(lua_newuserdata(L, sizeof(vconfig))) vconfig(i.get_child());
lua_pushlightuserdata(L
, vconfigKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
luaW_pushvconfig(L, vconfig(i.get_child()));
lua_rawseti(L, -2, 2);
return 1;
}
@ -254,14 +247,16 @@ int intf_tovconfig(lua_State *L)
*/
std::string register_gettext_metatable(lua_State *L)
{
lua_pushlightuserdata(L
, gettextKey);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lua_common::impl_gettext);
lua_setfield(L, -2, "__call");
luaL_newmetatable(L, gettextKey);
static luaL_Reg const callbacks[] = {
{ "__call", &impl_gettext},
{ NULL, NULL }
};
luaL_setfuncs(L, callbacks, 0);
lua_pushstring(L, "message domain");
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);
return "Adding gettext metatable...\n";
}
@ -271,18 +266,18 @@ std::string register_gettext_metatable(lua_State *L)
*/
std::string register_tstring_metatable(lua_State *L)
{
lua_pushlightuserdata(L
, tstringKey);
lua_createtable(L, 0, 4);
lua_pushcfunction(L, impl_tstring_concat);
lua_setfield(L, -2, "__concat");
lua_pushcfunction(L, impl_tstring_collect);
lua_setfield(L, -2, "__gc");
lua_pushcfunction(L, impl_tstring_tostring);
lua_setfield(L, -2, "__tostring");
luaL_newmetatable(L, tstringKey);
static luaL_Reg const callbacks[] = {
{ "__concat", &impl_tstring_concat},
{ "__gc", &impl_tstring_collect},
{ "__tostring", &impl_tstring_tostring},
{ NULL, NULL }
};
luaL_setfuncs(L, callbacks, 0);
lua_pushstring(L, "translatable string");
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);
return "Adding tstring metatable...\n";
}
@ -292,18 +287,18 @@ std::string register_tstring_metatable(lua_State *L)
*/
std::string register_vconfig_metatable(lua_State *L)
{
lua_pushlightuserdata(L
, vconfigKey);
lua_createtable(L, 0, 4);
lua_pushcfunction(L, impl_vconfig_collect);
lua_setfield(L, -2, "__gc");
lua_pushcfunction(L, impl_vconfig_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, impl_vconfig_size);
lua_setfield(L, -2, "__len");
luaL_newmetatable(L, vconfigKey);
static luaL_Reg const callbacks[] = {
{ "__gc", &impl_vconfig_collect},
{ "__index", &impl_vconfig_get},
{ "__len", &impl_vconfig_size},
{ NULL, NULL }
};
luaL_setfuncs(L, callbacks, 0);
lua_pushstring(L, "wml object");
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);
return "Adding vconfig metatable...\n";
}
@ -313,21 +308,13 @@ std::string register_vconfig_metatable(lua_State *L)
void luaW_pushvconfig(lua_State *L, vconfig const &cfg)
{
new(lua_newuserdata(L, sizeof(vconfig))) vconfig(cfg);
lua_pushlightuserdata(L
, vconfigKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
luaL_setmetatable(L, vconfigKey);
}
void luaW_pushtstring(lua_State *L, t_string const &v)
{
new(lua_newuserdata(L, sizeof(t_string))) t_string(v);
lua_pushlightuserdata(L
, tstringKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
luaL_setmetatable(L, tstringKey);
}
@ -384,9 +371,12 @@ bool luaW_totstring(lua_State *L, int index, t_string &str)
break;
case LUA_TUSERDATA:
{
if (!luaW_hasmetatable(L, index, tstringKey)) return false;
str = *static_cast<t_string *>(lua_touserdata(L, index));
break;
if (t_string * tstr = static_cast<t_string *> (luaL_checkudata(L, index, tstringKey))) {
str = *tstr;
break;
} else {
return false;
}
}
default:
return false;
@ -437,7 +427,7 @@ void luaW_pushconfig(lua_State *L, config const &cfg)
#define return_misformed() \
do { lua_settop(L, initial_top); return false; } while (0)
bool luaW_toconfig(lua_State *L, int index, config &cfg, int tstring_meta)
bool luaW_toconfig(lua_State *L, int index, config &cfg)
{
if (!lua_checkstack(L, LUA_MINSTACK))
return false;
@ -453,10 +443,12 @@ bool luaW_toconfig(lua_State *L, int index, config &cfg, int tstring_meta)
break;
case LUA_TUSERDATA:
{
if (!luaW_hasmetatable(L, index, vconfigKey))
if (vconfig * ptr = static_cast<vconfig *> (luaL_checkudata(L, index, vconfigKey))) {
cfg = ptr->get_parsed_config();
return true;
} else {
return false;
cfg = static_cast<vconfig *>(lua_touserdata(L, index))->get_parsed_config();
return true;
}
}
case LUA_TNONE:
case LUA_TNIL:
@ -465,15 +457,6 @@ bool luaW_toconfig(lua_State *L, int index, config &cfg, int tstring_meta)
return false;
}
// Get t_string's metatable, so that it can be used later to detect t_string object.
if (!tstring_meta) {
lua_pushlightuserdata(L
, tstringKey);
lua_rawget(L, LUA_REGISTRYINDEX);
tstring_meta = initial_top + 1;
}
// First convert the children (integer indices).
for (int i = 1, i_end = lua_rawlen(L, index); i <= i_end; ++i)
{
@ -483,7 +466,7 @@ bool luaW_toconfig(lua_State *L, int index, config &cfg, int tstring_meta)
char const *m = lua_tostring(L, -1);
if (!m) return_misformed();
lua_rawgeti(L, -2, 2);
if (!luaW_toconfig(L, -1, cfg.add_child(m), tstring_meta))
if (!luaW_toconfig(L, -1, cfg.add_child(m)))
return_misformed();
lua_pop(L, 3);
}
@ -506,12 +489,12 @@ bool luaW_toconfig(lua_State *L, int index, config &cfg, int tstring_meta)
break;
case LUA_TUSERDATA:
{
if (!lua_getmetatable(L, -1)) return_misformed();
bool tstr = lua_rawequal(L, -1, tstring_meta) != 0;
lua_pop(L, 1);
if (!tstr) return_misformed();
v = *static_cast<t_string *>(lua_touserdata(L, -1));
break;
if (t_string * tptr = static_cast<t_string *>(luaL_testudata(L, -1, tstringKey))) {
v = *tptr;
break;
} else {
return_misformed();
}
}
default:
return_misformed();
@ -546,10 +529,11 @@ bool luaW_tovconfig(lua_State *L, int index, vconfig &vcfg)
break;
}
case LUA_TUSERDATA:
if (!luaW_hasmetatable(L, index, vconfigKey))
if (vconfig * ptr = static_cast<vconfig *> (luaL_testudata(L, index, vconfigKey))) {
vcfg = *ptr;
} else {
return false;
vcfg = *static_cast<vconfig *>(lua_touserdata(L, index));
break;
}
case LUA_TNONE:
case LUA_TNIL:
break;

View file

@ -34,7 +34,9 @@ namespace lua_common {
std::string register_gettext_metatable(lua_State *L);
std::string register_tstring_metatable(lua_State *L);
std::string register_vconfig_metatable(lua_State *L);
}
extern const char * tstringKey;
/**
* Pushes a vconfig on the top of the stack.
@ -86,7 +88,7 @@ void luaW_pushconfig(lua_State *L, config const &cfg);
* @note If the table has holes in the integer keys or floating-point keys,
* some keys will be ignored and the error will go undetected.
*/
bool luaW_toconfig(lua_State *L, int index, config &cfg, int tstring_meta = 0);
bool luaW_toconfig(lua_State *L, int index, config &cfg);
/**
* Converts an optional table or vconfig to a config object.

View file

@ -54,6 +54,8 @@
static lg::log_domain log_scripting_lua("scripting/lua");
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)
static const char * dlgclbkKey = "dialog callback";
namespace {
struct scoped_dialog
{
@ -75,7 +77,7 @@ namespace {
scoped_dialog::scoped_dialog(lua_State *l, gui2::twindow *w)
: L(l), prev(current), window(w), callbacks()
{
lua_pushlightuserdata(L
lua_pushstring(L
, dlgclbkKey);
lua_createtable(L, 1, 0);
lua_pushvalue(L, -2);
@ -89,7 +91,7 @@ namespace {
{
delete window;
current = prev;
lua_pushlightuserdata(L
lua_pushstring(L
, dlgclbkKey);
lua_pushvalue(L, -1);
lua_rawget(L, LUA_REGISTRYINDEX);
@ -305,7 +307,7 @@ namespace { // helpers of intf_set_dialog_callback()
cb = i->second;
}
lua_State *L = scoped_dialog::current->L;
lua_pushlightuserdata(L
lua_pushstring(L
, dlgclbkKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_rawgeti(L, -1, cb);
@ -337,7 +339,7 @@ int intf_set_dialog_callback(lua_State *L)
scoped_dialog::callback_map::iterator i = m.find(w);
if (i != m.end())
{
lua_pushlightuserdata(L
lua_pushstring(L
, dlgclbkKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushnil(L);
@ -374,7 +376,7 @@ int intf_set_dialog_callback(lua_State *L)
else
return luaL_argerror(L, lua_gettop(L), "unsupported widget");
lua_pushlightuserdata(L
lua_pushstring(L
, dlgclbkKey);
lua_rawget(L, LUA_REGISTRYINDEX);
int n = lua_rawlen(L, -1) + 1;

160
src/scripting/lua_team.cpp Normal file
View file

@ -0,0 +1,160 @@
/*
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "scripting/lua_team.hpp"
#include "lua/lua.h"
#include "lua/lauxlib.h"
#include "scripting/lua_common.hpp"
#include "team.hpp"
#include <boost/foreach.hpp>
#include <string>
/**
* Implementation for a lua reference to a team,
* used by the wesnoth in-game sides table.
*
* (The userdata has type team** because lua holds
* only a pointer to a team, not a full-size team.
* If it were a full object then we would cast to
* type team *, since checkudata returns a pointer
* to the type corresponding to the sizeof expr
* used when we allocated the userdata.)
*/
// Registry key
static const char * Team = "side";
/**
* Gets some data on a side (__index metamethod).
* - Arg 1: full userdata containing the team.
* - Arg 2: string containing the name of the property.
* - Ret 1: something containing the attribute.
*/
static int impl_side_get(lua_State *L)
{
// Hidden metamethod, so arg1 has to be a pointer to a team.
team &t = **static_cast<team **>(luaL_checkudata(L, 1, Team));
char const *m = luaL_checkstring(L, 2);
// Find the corresponding attribute.
return_int_attrib("side", t.side());
return_int_attrib("gold", t.gold());
return_tstring_attrib("objectives", t.objectives());
return_int_attrib("village_gold", t.village_gold());
return_int_attrib("village_support", t.village_support());
return_int_attrib("recall_cost", t.recall_cost());
return_int_attrib("base_income", t.base_income());
return_int_attrib("total_income", t.total_income());
return_bool_attrib("objectives_changed", t.objectives_changed());
return_bool_attrib("fog", t.uses_fog());
return_bool_attrib("shroud", t.uses_shroud());
return_bool_attrib("hidden", t.hidden());
return_bool_attrib("scroll_to_leader", t.get_scroll_to_leader());
return_string_attrib("flag", t.flag());
return_string_attrib("flag_icon", t.flag_icon());
return_tstring_attrib("user_team_name", t.user_team_name());
return_string_attrib("team_name", t.team_name());
return_string_attrib("name", t.name());
return_string_attrib("color", t.color());
return_cstring_attrib("controller", team::CONTROLLER_to_string(t.controller()).c_str());
return_string_attrib("defeat_condition", team::DEFEAT_CONDITION_to_string(t.defeat_condition()));
return_bool_attrib("lost", t.lost());
if (strcmp(m, "recruit") == 0) {
std::set<std::string> const &recruits = t.recruits();
lua_createtable(L, recruits.size(), 0);
int i = 1;
BOOST_FOREACH(std::string const &r, t.recruits()) {
lua_pushstring(L, r.c_str());
lua_rawseti(L, -2, i++);
}
return 1;
}
return_cfg_attrib("__cfg", t.write(cfg));
return 0;
}
/**
* Sets some data on a side (__newindex metamethod).
* - Arg 1: full userdata containing the team.
* - Arg 2: string containing the name of the property.
* - Arg 3: something containing the attribute.
*/
static int impl_side_set(lua_State *L)
{
// Hidden metamethod, so arg1 has to be a pointer to a team.
team &t = **static_cast<team **>(luaL_checkudata(L, 1, Team));
char const *m = luaL_checkstring(L, 2);
// Find the corresponding attribute.
modify_int_attrib("gold", t.set_gold(value));
modify_tstring_attrib("objectives", t.set_objectives(value, true));
modify_int_attrib("village_gold", t.set_village_gold(value));
modify_int_attrib("village_support", t.set_village_support(value));
modify_int_attrib("recall_cost", t.set_recall_cost(value));
modify_int_attrib("base_income", t.set_base_income(value));
modify_bool_attrib("objectives_changed", t.set_objectives_changed(value));
modify_bool_attrib("hidden", t.set_hidden(value));
modify_bool_attrib("scroll_to_leader", t.set_scroll_to_leader(value));
modify_tstring_attrib("user_team_name", t.change_team(t.team_name(), value));
modify_string_attrib("team_name", t.change_team(value, t.user_team_name()));
modify_string_attrib("controller", t.change_controller_by_wml(value));
modify_string_attrib("color", t.set_color(value));
modify_string_attrib("defeat_condition", t.set_defeat_condition_string(value));
modify_bool_attrib("lost", t.set_lost(value));
if (strcmp(m, "recruit") == 0) {
t.set_recruits(std::set<std::string>());
if (!lua_istable(L, 3)) return 0;
for (int i = 1;; ++i) {
lua_rawgeti(L, 3, i);
if (lua_isnil(L, -1)) break;
t.add_recruit(lua_tostring(L, -1));
lua_pop(L, 1);
}
return 0;
}
return luaL_argerror(L, 2, "unknown modifiable property");
}
namespace lua_team {
std::string register_metatable(lua_State * L)
{
luaL_newmetatable(L, Team);
static luaL_Reg const callbacks[] = {
{ "__index", &impl_side_get},
{ "__newindex", &impl_side_set},
{ NULL, NULL }
};
luaL_setfuncs(L, callbacks, 0);
lua_pushstring(L, "side");
lua_setfield(L, -2, "__metatable");
return "Adding getside metatable...\n";
}
}
void luaW_pushteam(lua_State *L, team & tm)
{
team** t = static_cast<team**>(lua_newuserdata(L, sizeof(team*)));
*t = &tm;
luaL_setmetatable(L, Team);
}

View file

@ -0,0 +1,34 @@
/*
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef LUA_TEAM_HPP_INCLUDED
#define LUA_TEAM_HPP_INCLUDED
class team;
struct lua_State;
#include <string>
/**
* This namespace contains bindings for lua to hold a pointer to a team,
* and to access and modify it.
*/
namespace lua_team {
std::string register_metatable(lua_State *);
} //end namespace lua_team
// Create a full userdata containing a pointer to the team.
void luaW_pushteam(lua_State *, team &);
#endif

View file

@ -15,29 +15,15 @@
#include "lua_types.hpp"
/* Dummy pointer for getting unique keys for Lua's registry. */
static char const v_dlgclbkKey = 0;
static char const v_executeKey = 0;
static char const v_getsideKey = 0;
static char const v_gettextKey = 0;
static char const v_gettypeKey = 0;
static char const v_getraceKey = 0;
static char const v_getunitKey = 0;
static char const v_tstringKey = 0;
static char const v_unitvarKey = 0;
static char const v_ustatusKey = 0;
static char const v_vconfigKey = 0;
static char const v_currentscriptKey = 0;
luatypekey const dlgclbkKey = static_cast<void *>(const_cast<char *>(&v_dlgclbkKey));
luatypekey const executeKey = static_cast<void *>(const_cast<char *>(&v_executeKey));
luatypekey const getsideKey = static_cast<void *>(const_cast<char *>(&v_getsideKey));
luatypekey const gettextKey = static_cast<void *>(const_cast<char *>(&v_gettextKey));
luatypekey const gettypeKey = static_cast<void *>(const_cast<char *>(&v_gettypeKey));
luatypekey const getraceKey = static_cast<void *>(const_cast<char *>(&v_getraceKey));
luatypekey const getunitKey = static_cast<void *>(const_cast<char *>(&v_getunitKey));
luatypekey const tstringKey = static_cast<void *>(const_cast<char *>(&v_tstringKey));
luatypekey const unitvarKey = static_cast<void *>(const_cast<char *>(&v_unitvarKey));
luatypekey const ustatusKey = static_cast<void *>(const_cast<char *>(&v_ustatusKey));
luatypekey const vconfigKey = static_cast<void *>(const_cast<char *>(&v_vconfigKey));
luatypekey const currentscriptKey = static_cast<void *>(const_cast<char *>(&v_currentscriptKey));

View file

@ -19,17 +19,10 @@ typedef void* luatypekey;
// i dont want to cast to void* each time ....
// a drawback is, that these are now normal static variables wich are initialised at initialisation time (so you shoudn't use these at/before initialisation time).
extern luatypekey const dlgclbkKey;
extern luatypekey const executeKey;
extern luatypekey const getsideKey;
extern luatypekey const gettextKey;
extern luatypekey const gettypeKey;
extern luatypekey const getraceKey;
extern luatypekey const getunitKey;
extern luatypekey const tstringKey;
extern luatypekey const unitvarKey;
extern luatypekey const ustatusKey;
extern luatypekey const vconfigKey;
extern luatypekey const currentscriptKey;
#endif

View file

@ -0,0 +1,79 @@
/*
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "scripting/lua_unit_type.hpp"
#include "lua/lua.h"
#include "lua/lauxlib.h"
#include "scripting/lua_common.hpp"
#include "unit_types.hpp"
#include <boost/foreach.hpp>
#include <string>
/**
* Implementation for a lua reference to a unit_type.
*/
// Registry key
static const char * UnitType = "unit type";
/**
* Gets some data on a unit type (__index metamethod).
* - Arg 1: table containing an "id" field.
* - Arg 2: string containing the name of the property.
* - Ret 1: something containing the attribute.
*/
static int impl_unit_type_get(lua_State *L)
{
char const *m = luaL_checkstring(L, 2);
lua_pushstring(L, "id");
lua_rawget(L, 1);
const unit_type *utp = unit_types.find(lua_tostring(L, -1));
if (!utp) return luaL_argerror(L, 1, "unknown unit type");
unit_type const &ut = *utp;
// Find the corresponding attribute.
return_tstring_attrib("name", ut.type_name());
return_int_attrib("max_hitpoints", ut.hitpoints());
return_int_attrib("max_moves", ut.movement());
return_int_attrib("max_experience", ut.experience_needed());
return_int_attrib("cost", ut.cost());
return_int_attrib("level", ut.level());
return_int_attrib("recall_cost", ut.recall_cost());
return_cfgref_attrib("__cfg", ut.get_cfg());
return 0;
}
namespace lua_unit_type {
std::string register_metatable(lua_State * L)
{
luaL_newmetatable(L, UnitType);
lua_pushcfunction(L, impl_unit_type_get);
lua_setfield(L, -2, "__index");
lua_pushstring(L, "unit type");
lua_setfield(L, -2, "__metatable");
return "Adding unit type metatable...\n";
}
}
void luaW_pushunittype(lua_State *L, const std::string & id)
{
lua_createtable(L, 0, 1);
lua_pushstring(L, id.c_str());
lua_setfield(L, -2, "id");
luaL_setmetatable(L, UnitType);
}

View file

@ -0,0 +1,34 @@
/*
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef LUA_UNIT_TYPE_HPP_INCLUDED
#define LUA_UNIT_TYPE_HPP_INCLUDED
struct lua_State;
#include <string>
/**
* This namespace contains bindings for lua to hold a reference to a
* unit type and access its stats.
*/
namespace lua_unit_type {
std::string register_metatable(lua_State *);
} //end namespace lua_team
/// Create a lua object containing a reference to a unittype, and a
/// metatable to access the properties.
void luaW_pushunittype(lua_State *, const std::string &);
#endif

View file

@ -26,6 +26,7 @@
//#include "gettext.hpp"
#include "loadscreen.hpp"
#include "log.hpp"
#include "make_enum.hpp"
#include "portrait.hpp"
#include "unit.hpp"
#include "unit_abilities.hpp"
@ -1142,6 +1143,31 @@ bool unit_type::resistance_filter_matches(const config& cfg, bool attacker, cons
if (!unit_abilities::filter_base_matches(cfg, res)) return false;
return true;
}
/** Implementation detail of unit_type::alignment_description */
MAKE_ENUM (ALIGNMENT_FEMALE_VARIATION,
(FEMALE_LAWFUL, N_("female^lawful"))
(FEMALE_NEUTRAL, N_("female^neutral"))
(FEMALE_CHAOTIC, N_("female^chaotic"))
(FEMALE_LIMINAL, N_("female^liminal"))
)
MAKE_ENUM_STREAM_OPS1(ALIGNMENT_FEMALE_VARIATION)
std::string unit_type::alignment_description(ALIGNMENT align, unit_race::GENDER gender)
{
std::string str = std::string();
if (gender == unit_race::FEMALE) {
ALIGNMENT_FEMALE_VARIATION fem = static_cast<ALIGNMENT_FEMALE_VARIATION> (align);
str = lexical_cast<std::string>(fem);
} else {
str = lexical_cast<std::string>(align);
}
return translation::sgettext(str.c_str());
}
/* ** unit_type_data ** */

View file

@ -235,25 +235,9 @@ public:
(CHAOTIC, N_("chaotic"))
(LIMINAL, N_("liminal"))
)
MAKE_ENUM (ALIGNMENT_FEMALE_VARIATION,
(FEMALE_LAWFUL, N_("female^lawful"))
(FEMALE_NEUTRAL, N_("female^neutral"))
(FEMALE_CHAOTIC, N_("female^chaotic"))
(FEMALE_LIMINAL, N_("female^liminal"))
)
ALIGNMENT alignment() const { return alignment_; }
inline static std::string alignment_description(ALIGNMENT align, unit_race::GENDER gender = unit_race::MALE)
{
std::string str = std::string();
if (gender == unit_race::FEMALE) {
ALIGNMENT_FEMALE_VARIATION fem = static_cast<ALIGNMENT_FEMALE_VARIATION> (align);
str = lexical_cast<std::string>(fem);
} else {
str = lexical_cast<std::string>(align);
}
return translation::sgettext(str.c_str());
}
static std::string alignment_description(ALIGNMENT align, unit_race::GENDER gender = unit_race::MALE);
fixed_t alpha() const { return alpha_; }
@ -390,7 +374,6 @@ private:
};
MAKE_ENUM_STREAM_OPS2(unit_type, ALIGNMENT)
MAKE_ENUM_STREAM_OPS2(unit_type, ALIGNMENT_FEMALE_VARIATION)
class unit_type_data
: private boost::noncopyable

View file

@ -87,6 +87,7 @@
#
0 lua_dofile
0 lua_require
0 lua_get_sides
#
# Pathfinding
#