diff --git a/res/core/messages.xml b/res/core/messages.xml index c79416c25..b89019aa9 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -14,7 +14,36 @@ your faction with a $resource($item,1). - + + + + + + "$unit($unit) in $region($region): '$order($command)' - Ungültige Zielregion." + "$unit($unit) in $region($region): '$order($command)' - invalid target region." + + + + + + + + + "$unit($unit) in $region($region): '$order($command)' - keine Richtung angegeben." + "$unit($unit) in $region($region): '$order($command)' - no direction was specified." + + + + + + + + + "$unit($unit) in $region($region): '$order($command)' - In der Zielregion befinden sich noch Einheiten." + "$unit($unit) in $region($region): '$order($command)' - There are units in the target region." + + + diff --git a/scripts/eressea/xmasitems.lua b/scripts/eressea/xmasitems.lua index bce82f7e4..4f8a20767 100644 --- a/scripts/eressea/xmasitems.lua +++ b/scripts/eressea/xmasitems.lua @@ -6,7 +6,16 @@ local function get_direction(locale, token) return nil end -function use_snowglobe(u, amount, token) +local function error_message(msg, u, ord) + local msg = message.create(msg) + msg:set_unit("unit", u) + msg:set_region("region", u.region) + msg:set_order("command", ord) + msg:send_faction(u.faction) + return -1 +end + +function use_snowglobe(u, amount, token, ord) local transform = { ocean = "glacier", firewall = "volcano", @@ -17,8 +26,7 @@ function use_snowglobe(u, amount, token) if direction then local r = u.region:next(direction) if r.units() then - -- message "target region not empty" - return -1 + return error_message('target_region_not_empty', u, ord) end if r then local trans = transform[r.terrain] @@ -26,15 +34,13 @@ function use_snowglobe(u, amount, token) r.terrain = trans return 1 else - -- message "invalid terrain" + return error_message('target_region_invalid', u, ord) end else - -- message "invalid terrain" + return error_message('target_region_invalid', u, ord) end - else - -- message "need to specify direction" end - return -1 + return error_message('missing_direction', u, ord) end function use_snowman(u, amount) diff --git a/scripts/tests/xmas.lua b/scripts/tests/xmas.lua index 8c6acb895..7ce416db3 100644 --- a/scripts/tests/xmas.lua +++ b/scripts/tests/xmas.lua @@ -19,6 +19,22 @@ function test_snowglobe_fail() unit.create(f, r2, 1) -- unit in target region => fail process_orders() assert_equal('ocean', r2.terrain) + assert_equal(1, u:get_item('snowglobe')) + assert_equal(1, f:count_msg_type('target_region_not_empty')) +end + +function test_snowglobe_missing_direction() + local r1 = region.create(0, 0, "glacier") + local r2 = region.create(1, 0, "ocean") + local f = faction.create("snowglobe1@eressea.de", "human", "de") + local u = unit.create(f, r1, 1) + u:add_item("snowglobe", 1) + u:clear_orders() + u:add_order("BENUTZEN 1 Schneekugel") + process_orders() + assert_equal('ocean', r2.terrain) + assert_equal(1, u:get_item('snowglobe')) + assert_equal(1, f:count_msg_type('missing_direction')) end function test_snowglobe() @@ -27,6 +43,7 @@ function test_snowglobe() local f = faction.create("snowglobe2@eressea.de", "human", "de") local u = unit.create(f, r1, 1) local have = 6 + local fail = 0 u:add_item("snowglobe", have) local xform = { ocean = "glacier", glacier = "glacier", firewall = "volcano", volcano = "mountain", desert = "plain", plain = "plain" } u:clear_orders() @@ -35,7 +52,12 @@ function test_snowglobe() r2.terrain = k process_orders() assert_equal(v, r2.terrain) - if k~=v then have=have - 1 end + if k~=v then + have=have - 1 + else + fail = fail + 1 + assert_equal(fail, f:count_msg_type('target_region_invalid')) + end assert_equal(have, u:get_item("snowglobe")) end end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 36c728d40..eb603bc0b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -139,6 +139,7 @@ set(SERVER_SRC bind_eressea.c bind_faction.c bind_dict.c + bind_order.c bindings.c bind_message.c bind_monsters.c diff --git a/src/bind_faction.c b/src/bind_faction.c index 8cfc21718..dc06c4057 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -224,6 +224,23 @@ static int tolua_faction_addnotice(lua_State * L) return 0; } +static int tolua_faction_count_msg_type(lua_State *L) { + faction *self = (faction *)tolua_tousertype(L, 1, 0); + const char *str = tolua_tostring(L, 2, 0); + int n = 0; + if (self->msgs) { + mlist * ml = self->msgs->begin; + while (ml) { + if (strcmp(str, ml->msg->type->name) == 0) { + ++n; + } + ml = ml->next; + } + } + lua_pushinteger(L, n); + return 1; +} + static int tolua_faction_get_objects(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); @@ -528,12 +545,12 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "id", tolua_faction_get_id, tolua_faction_set_id); - tolua_variable(L, TOLUA_CAST "uid", &tolua_faction_get_uid, - &tolua_faction_set_uid); - tolua_variable(L, TOLUA_CAST "name", &tolua_faction_get_name, - &tolua_faction_set_name); - tolua_variable(L, TOLUA_CAST "info", &tolua_faction_get_info, - &tolua_faction_set_info); + tolua_variable(L, TOLUA_CAST "uid", tolua_faction_get_uid, + tolua_faction_set_uid); + tolua_variable(L, TOLUA_CAST "name", tolua_faction_get_name, + tolua_faction_set_name); + tolua_variable(L, TOLUA_CAST "info", tolua_faction_get_info, + tolua_faction_set_info); tolua_variable(L, TOLUA_CAST "units", tolua_faction_get_units, NULL); tolua_variable(L, TOLUA_CAST "heroes", tolua_faction_get_heroes, NULL); tolua_variable(L, TOLUA_CAST "maxheroes", tolua_faction_get_maxheroes, @@ -549,7 +566,7 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "alliance", tolua_faction_get_alliance, tolua_faction_set_alliance); tolua_variable(L, TOLUA_CAST "score", tolua_faction_get_score, NULL); - tolua_variable(L, TOLUA_CAST "magic", &tolua_faction_get_magic, + tolua_variable(L, TOLUA_CAST "magic", tolua_faction_get_magic, tolua_faction_set_magic); tolua_variable(L, TOLUA_CAST "age", tolua_faction_get_age, tolua_faction_set_age); @@ -559,11 +576,11 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "lastturn", tolua_faction_get_lastturn, tolua_faction_set_lastturn); - tolua_function(L, TOLUA_CAST "set_policy", &tolua_faction_set_policy); - tolua_function(L, TOLUA_CAST "get_policy", &tolua_faction_get_policy); - tolua_function(L, TOLUA_CAST "get_origin", &tolua_faction_get_origin); - tolua_function(L, TOLUA_CAST "set_origin", &tolua_faction_set_origin); - tolua_function(L, TOLUA_CAST "normalize", &tolua_faction_normalize); + tolua_function(L, TOLUA_CAST "set_policy", tolua_faction_set_policy); + tolua_function(L, TOLUA_CAST "get_policy", tolua_faction_get_policy); + tolua_function(L, TOLUA_CAST "get_origin", tolua_faction_get_origin); + tolua_function(L, TOLUA_CAST "set_origin", tolua_faction_set_origin); + tolua_function(L, TOLUA_CAST "normalize", tolua_faction_normalize); tolua_function(L, TOLUA_CAST "add_item", tolua_faction_add_item); tolua_variable(L, TOLUA_CAST "items", tolua_faction_get_items, NULL); @@ -572,7 +589,10 @@ void tolua_faction_open(lua_State * L) tolua_function(L, TOLUA_CAST "create", tolua_faction_create); tolua_function(L, TOLUA_CAST "get", tolua_faction_get); tolua_function(L, TOLUA_CAST "destroy", tolua_faction_destroy); - tolua_function(L, TOLUA_CAST "add_notice", &tolua_faction_addnotice); + tolua_function(L, TOLUA_CAST "add_notice", tolua_faction_addnotice); + + /* tech debt hack, siehe https://paper.dropbox.com/doc/Weihnachten-2015-5tOx5r1xsgGDBpb0gILrv#:h=Probleme-mit-Tests-(Nachtrag-0 */ + tolua_function(L, TOLUA_CAST "count_msg_type", tolua_faction_count_msg_type); tolua_variable(L, TOLUA_CAST "objects", tolua_faction_get_objects, NULL); diff --git a/src/bind_message.c b/src/bind_message.c index 34e43301a..15673f4f6 100644 --- a/src/bind_message.c +++ b/src/bind_message.c @@ -81,6 +81,23 @@ static int msg_set_resource(lua_message * msg, const char *param, const char *re return E_INVALID_MESSAGE; } +static int msg_set_order(lua_message * msg, const char *param, struct order *ord) +{ + if (msg->mtype) { + int i = mtype_get_param(msg->mtype, param); + if (i == msg->mtype->nparameters) { + return E_INVALID_PARAMETER_NAME; + } + if (strcmp(msg->mtype->types[i]->name, "order") != 0) { + return E_INVALID_PARAMETER_TYPE; + } + + msg->args[i].v = (void *)ord; + return E_OK; + } + return E_INVALID_MESSAGE; +} + static int msg_set_unit(lua_message * msg, const char *param, const unit * u) { if (msg->mtype) { @@ -223,6 +240,16 @@ static int tolua_msg_set_resource(lua_State * L) return 1; } +static int tolua_msg_set_order(lua_State * L) +{ + lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); + const char *param = tolua_tostring(L, 2, 0); + struct order *value = (struct order *)tolua_tousertype(L, 3, 0); + int result = msg_set_order(lmsg, param, value); + lua_pushinteger(L, result); + return 1; +} + static int tolua_msg_set_unit(lua_State * L) { lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); @@ -294,6 +321,13 @@ static int tolua_msg_send_faction(lua_State * L) return 0; } +static int tolua_msg_get_type(lua_State * L) +{ + lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); + lua_pushstring(L, lmsg->msg->type->name); + return 1; +} + static int tolua_msg_render(lua_State * L) { lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); @@ -324,8 +358,10 @@ void tolua_message_open(lua_State * L) tolua_beginmodule(L, TOLUA_CAST "message"); { tolua_function(L, TOLUA_CAST "render", tolua_msg_render); + tolua_variable(L, TOLUA_CAST "type", tolua_msg_get_type, 0); tolua_function(L, TOLUA_CAST "set", tolua_msg_set); tolua_function(L, TOLUA_CAST "set_unit", tolua_msg_set_unit); + tolua_function(L, TOLUA_CAST "set_order", tolua_msg_set_order); tolua_function(L, TOLUA_CAST "set_region", tolua_msg_set_region); tolua_function(L, TOLUA_CAST "set_resource", tolua_msg_set_resource); tolua_function(L, TOLUA_CAST "set_int", tolua_msg_set_int); diff --git a/src/bind_order.c b/src/bind_order.c new file mode 100644 index 000000000..90fc7d3b0 --- /dev/null +++ b/src/bind_order.c @@ -0,0 +1,47 @@ +#include +#include + +/* kernel includes */ +#include +#include + +/* lua includes */ +#include + +#include + +static int tolua_order_get_token(lua_State *L) { + order *ord = (order *)tolua_tousertype(L, 1, 0); + int n = (int)tolua_tonumber(L, 2, 0); + const char * str = 0; + init_order(ord); + while (n-->0) { + str = getstrtoken(); + if (!str) { + return 0; + } + } + + tolua_pushstring(L, str); + return 1; +} + +void tolua_order_open(lua_State * L) +{ + /* register user types */ + tolua_usertype(L, TOLUA_CAST "order"); + + tolua_module(L, NULL, 0); + tolua_beginmodule(L, NULL); + { + tolua_cclass(L, TOLUA_CAST "order", TOLUA_CAST "order", TOLUA_CAST "", + NULL); + tolua_beginmodule(L, TOLUA_CAST "order"); + { + tolua_function(L, TOLUA_CAST "token", tolua_order_get_token); + } + tolua_endmodule(L); + } + tolua_endmodule(L); +} + diff --git a/src/bind_order.h b/src/bind_order.h new file mode 100644 index 000000000..efe1ef373 --- /dev/null +++ b/src/bind_order.h @@ -0,0 +1,14 @@ +#ifndef H_BIND_ORDER_H +#define H_BIND_ORDER_H +#ifdef __cplusplus +extern "C" { +#endif + + struct lua_State; + void tolua_order_open(struct lua_State *L); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/bindings.c b/src/bindings.c index 20a8192e1..cbbd38072 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -19,6 +19,7 @@ without prior permission by the authors of Eressea. #include "bind_message.h" #include "bind_building.h" #include "bind_faction.h" +#include "bind_order.h" #include "bind_ship.h" #include "bind_gmtool.h" #include "bind_region.h" @@ -1157,6 +1158,7 @@ lua_State *lua_init(void) { tolua_faction_open(L); tolua_unit_open(L); tolua_message_open(L); + tolua_order_open(L); tolua_dict_open(L); #ifdef USE_CURSES tolua_gmtool_open(L); diff --git a/src/helpers.c b/src/helpers.c index c784e9901..55cfffb80 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -511,7 +511,8 @@ struct order *ord) tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); lua_pushinteger(L, amount); lua_pushstring(L, getstrtoken()); - if (lua_pcall(L, 3, 1, 0) != 0) { + tolua_pushusertype(L, (void *)ord, TOLUA_CAST "order"); + if (lua_pcall(L, 4, 1, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("use(%s) calling '%s': %s.\n", unitname(u), fname, error); lua_pop(L, 1);