From ab433775777c4f5055bcf4d2a1cffc506c4f9961 Mon Sep 17 00:00:00 2001 From: sapier Date: Sat, 25 May 2013 00:51:02 +0200 Subject: Move scriptapi to separate folder (by sapier) On the lua side, notably minetest.env:() should now be replaced by minetest.(). The old way is and will stay supported for a long time. Also: Update and clean up lua_api.txt (by celeron55) Move EnvRef to lua and remove add_rat and add_firefly (by kahrl) Add separate src/util/CMakeLists.txt, other minor fixes (by kahrl) --- src/script/lua_api/l_object.cpp | 1095 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1095 insertions(+) create mode 100644 src/script/lua_api/l_object.cpp (limited to 'src/script/lua_api/l_object.cpp') diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp new file mode 100644 index 000000000..6dec3db85 --- /dev/null +++ b/src/script/lua_api/l_object.cpp @@ -0,0 +1,1095 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "cpp_api/scriptapi.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "lua_api/l_object.h" +#include "common/c_internal.h" +#include "lua_api/l_inventory.h" +#include "lua_api/l_item.h" +#include "log.h" +#include "tool.h" +#include "serverobject.h" +#include "content_object.h" +#include "content_sao.h" +#include "server.h" +#include "hud.h" + + +struct EnumString es_HudElementType[] = +{ + {HUD_ELEM_IMAGE, "image"}, + {HUD_ELEM_TEXT, "text"}, + {HUD_ELEM_STATBAR, "statbar"}, + {HUD_ELEM_INVENTORY, "inventory"}, +{0, NULL}, +}; + +struct EnumString es_HudElementStat[] = +{ + {HUD_STAT_POS, "pos"}, + {HUD_STAT_NAME, "name"}, + {HUD_STAT_SCALE, "scale"}, + {HUD_STAT_TEXT, "text"}, + {HUD_STAT_NUMBER, "number"}, + {HUD_STAT_ITEM, "item"}, + {HUD_STAT_DIR, "direction"}, + {HUD_STAT_ALIGN, "alignment"}, + {HUD_STAT_OFFSET, "offset"}, + {0, NULL}, +}; + +struct EnumString es_HudBuiltinElement[] = +{ + {HUD_FLAG_HOTBAR_VISIBLE, "hotbar"}, + {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"}, + {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"}, + {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"}, + {0, NULL}, +}; + +/* + ObjectRef +*/ + + +ObjectRef* ObjectRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(ObjectRef**)ud; // unbox pointer +} + +ServerActiveObject* ObjectRef::getobject(ObjectRef *ref) +{ + ServerActiveObject *co = ref->m_object; + return co; +} + +LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref) +{ + ServerActiveObject *obj = getobject(ref); + if(obj == NULL) + return NULL; + if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY) + return NULL; + return (LuaEntitySAO*)obj; +} + +PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref) +{ + ServerActiveObject *obj = getobject(ref); + if(obj == NULL) + return NULL; + if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) + return NULL; + return (PlayerSAO*)obj; +} + +Player* ObjectRef::getplayer(ObjectRef *ref) +{ + PlayerSAO *playersao = getplayersao(ref); + if(playersao == NULL) + return NULL; + return playersao->getPlayer(); +} + +// Exported functions + +// garbage collector +int ObjectRef::gc_object(lua_State *L) { + ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1)); + //infostream<<"ObjectRef::gc_object: o="<setPos(pos); + return 0; +} + +// moveto(self, pos, continuous=false) +int ObjectRef::l_moveto(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + //LuaEntitySAO *co = getluaobject(ref); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // pos + v3f pos = checkFloatPos(L, 2); + // continuous + bool continuous = lua_toboolean(L, 3); + // Do it + co->moveTo(pos, continuous); + return 0; +} + +// punch(self, puncher, time_from_last_punch, tool_capabilities, dir) +int ObjectRef::l_punch(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ObjectRef *puncher_ref = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *puncher = getobject(puncher_ref); + if(co == NULL) return 0; + if(puncher == NULL) return 0; + v3f dir; + if(lua_type(L, 5) != LUA_TTABLE) + dir = co->getBasePosition() - puncher->getBasePosition(); + else + dir = read_v3f(L, 5); + float time_from_last_punch = 1000000; + if(lua_isnumber(L, 3)) + time_from_last_punch = lua_tonumber(L, 3); + ToolCapabilities toolcap = read_tool_capabilities(L, 4); + dir.normalize(); + // Do it + co->punch(dir, &toolcap, puncher, time_from_last_punch); + return 0; +} + +// right_click(self, clicker); clicker = an another ObjectRef +int ObjectRef::l_right_click(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ObjectRef *ref2 = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *co2 = getobject(ref2); + if(co == NULL) return 0; + if(co2 == NULL) return 0; + // Do it + co->rightClick(co2); + return 0; +} + +// set_hp(self, hp) +// hp = number of hitpoints (2 * number of hearts) +// returns: nil +int ObjectRef::l_set_hp(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + luaL_checknumber(L, 2); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + int hp = lua_tonumber(L, 2); + /*infostream<<"ObjectRef::l_set_hp(): id="<getId() + <<" hp="<setHP(hp); + // Return + return 0; +} + +// get_hp(self) +// returns: number of hitpoints (2 * number of hearts) +// 0 if not applicable to this type of object +int ObjectRef::l_get_hp(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL){ + // Default hp is 1 + lua_pushnumber(L, 1); + return 1; + } + int hp = co->getHP(); + /*infostream<<"ObjectRef::l_get_hp(): id="<getId() + <<" hp="<getInventoryLocation(); + if(STACK_TO_SERVER(L)->getInventory(loc) != NULL) + InvRef::create(L, loc); + else + lua_pushnil(L); // An object may have no inventory (nil) + return 1; +} + +// get_wield_list(self) +int ObjectRef::l_get_wield_list(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + lua_pushstring(L, co->getWieldList().c_str()); + return 1; +} + +// get_wield_index(self) +int ObjectRef::l_get_wield_index(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + lua_pushinteger(L, co->getWieldIndex() + 1); + return 1; +} + +// get_wielded_item(self) +int ObjectRef::l_get_wielded_item(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL){ + // Empty ItemStack + LuaItemStack::create(L, ItemStack()); + return 1; + } + // Do it + LuaItemStack::create(L, co->getWieldedItem()); + return 1; +} + +// set_wielded_item(self, itemstack or itemstring or table or nil) +int ObjectRef::l_set_wielded_item(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + ItemStack item = read_item(L, 2,STACK_TO_SERVER(L)); + bool success = co->setWieldedItem(item); + lua_pushboolean(L, success); + return 1; +} + +// set_armor_groups(self, groups) +int ObjectRef::l_set_armor_groups(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + ItemGroupList groups; + read_groups(L, 2, groups); + co->setArmorGroups(groups); + return 0; +} + +// set_physics_override(self, physics_override_speed, physics_override_jump, physics_override_gravity) +int ObjectRef::l_set_physics_override(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + PlayerSAO *co = (PlayerSAO *) getobject(ref); + if(co == NULL) return 0; + // Do it + if(!lua_isnil(L, 2)){ + co->m_physics_override_speed = lua_tonumber(L, 2); + co->m_physics_override_sent = false; + } + if(!lua_isnil(L, 3)){ + co->m_physics_override_jump = lua_tonumber(L, 3); + co->m_physics_override_sent = false; + } + if(!lua_isnil(L, 4)){ + co->m_physics_override_gravity = lua_tonumber(L, 4); + co->m_physics_override_sent = false; + } + return 0; +} + +// set_animation(self, frame_range, frame_speed, frame_blend) +int ObjectRef::l_set_animation(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + v2f frames = v2f(1, 1); + if(!lua_isnil(L, 2)) + frames = read_v2f(L, 2); + float frame_speed = 15; + if(!lua_isnil(L, 3)) + frame_speed = lua_tonumber(L, 3); + float frame_blend = 0; + if(!lua_isnil(L, 4)) + frame_blend = lua_tonumber(L, 4); + co->setAnimation(frames, frame_speed, frame_blend); + return 0; +} + +// set_bone_position(self, std::string bone, v3f position, v3f rotation) +int ObjectRef::l_set_bone_position(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + std::string bone = ""; + if(!lua_isnil(L, 2)) + bone = lua_tostring(L, 2); + v3f position = v3f(0, 0, 0); + if(!lua_isnil(L, 3)) + position = read_v3f(L, 3); + v3f rotation = v3f(0, 0, 0); + if(!lua_isnil(L, 4)) + rotation = read_v3f(L, 4); + co->setBonePosition(bone, position, rotation); + return 0; +} + +// set_attach(self, parent, bone, position, rotation) +int ObjectRef::l_set_attach(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ObjectRef *parent_ref = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *parent = getobject(parent_ref); + if(co == NULL) return 0; + if(parent == NULL) return 0; + // Do it + std::string bone = ""; + if(!lua_isnil(L, 3)) + bone = lua_tostring(L, 3); + v3f position = v3f(0, 0, 0); + if(!lua_isnil(L, 4)) + position = read_v3f(L, 4); + v3f rotation = v3f(0, 0, 0); + if(!lua_isnil(L, 5)) + rotation = read_v3f(L, 5); + co->setAttachment(parent->getId(), bone, position, rotation); + return 0; +} + +// set_detach(self) +int ObjectRef::l_set_detach(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0)); + return 0; +} + +// set_properties(self, properties) +int ObjectRef::l_set_properties(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + ObjectProperties *prop = co->accessObjectProperties(); + if(!prop) + return 0; + read_object_properties(L, 2, prop); + co->notifyObjectPropertiesModified(); + return 0; +} + +/* LuaEntitySAO-only */ + +// setvelocity(self, {x=num, y=num, z=num}) +int ObjectRef::l_setvelocity(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + v3f pos = checkFloatPos(L, 2); + // Do it + co->setVelocity(pos); + return 0; +} + +// getvelocity(self) +int ObjectRef::l_getvelocity(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + v3f v = co->getVelocity(); + pushFloatPos(L, v); + return 1; +} + +// setacceleration(self, {x=num, y=num, z=num}) +int ObjectRef::l_setacceleration(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // pos + v3f pos = checkFloatPos(L, 2); + // Do it + co->setAcceleration(pos); + return 0; +} + +// getacceleration(self) +int ObjectRef::l_getacceleration(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + v3f v = co->getAcceleration(); + pushFloatPos(L, v); + return 1; +} + +// setyaw(self, radians) +int ObjectRef::l_setyaw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + float yaw = luaL_checknumber(L, 2) * core::RADTODEG; + // Do it + co->setYaw(yaw); + return 0; +} + +// getyaw(self) +int ObjectRef::l_getyaw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + float yaw = co->getYaw() * core::DEGTORAD; + lua_pushnumber(L, yaw); + return 1; +} + +// settexturemod(self, mod) +int ObjectRef::l_settexturemod(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + std::string mod = luaL_checkstring(L, 2); + co->setTextureMod(mod); + return 0; +} + +// setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2, +// select_horiz_by_yawpitch=false) +int ObjectRef::l_setsprite(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + v2s16 p(0,0); + if(!lua_isnil(L, 2)) + p = read_v2s16(L, 2); + int num_frames = 1; + if(!lua_isnil(L, 3)) + num_frames = lua_tonumber(L, 3); + float framelength = 0.2; + if(!lua_isnil(L, 4)) + framelength = lua_tonumber(L, 4); + bool select_horiz_by_yawpitch = false; + if(!lua_isnil(L, 5)) + select_horiz_by_yawpitch = lua_toboolean(L, 5); + co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch); + return 0; +} + +// DEPRECATED +// get_entity_name(self) +int ObjectRef::l_get_entity_name(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + std::string name = co->getName(); + lua_pushstring(L, name.c_str()); + return 1; +} + +// get_luaentity(self) +int ObjectRef::l_get_luaentity(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + LuaEntitySAO *co = getluaobject(ref); + if(co == NULL) return 0; + // Do it + luaentity_get(L, co->getId()); + return 1; +} + +/* Player-only */ + +// is_player(self) +int ObjectRef::l_is_player(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + lua_pushboolean(L, (player != NULL)); + return 1; +} + +// get_player_name(self) +int ObjectRef::l_get_player_name(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + // Do it + lua_pushstring(L, player->getName()); + return 1; +} + +// get_look_dir(self) +int ObjectRef::l_get_look_dir(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + float pitch = player->getRadPitch(); + float yaw = player->getRadYaw(); + v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw)); + push_v3f(L, v); + return 1; +} + +// get_look_pitch(self) +int ObjectRef::l_get_look_pitch(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + lua_pushnumber(L, player->getRadPitch()); + return 1; +} + +// get_look_yaw(self) +int ObjectRef::l_get_look_yaw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + lua_pushnumber(L, player->getRadYaw()); + return 1; +} + +// set_look_pitch(self, radians) +int ObjectRef::l_set_look_pitch(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + PlayerSAO* co = getplayersao(ref); + if(co == NULL) return 0; + float pitch = luaL_checknumber(L, 2) * core::RADTODEG; + // Do it + co->setPitch(pitch); + return 1; +} + +// set_look_yaw(self, radians) +int ObjectRef::l_set_look_yaw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + PlayerSAO* co = getplayersao(ref); + if(co == NULL) return 0; + float yaw = luaL_checknumber(L, 2) * core::RADTODEG; + // Do it + co->setYaw(yaw); + return 1; +} + +// set_inventory_formspec(self, formspec) +int ObjectRef::l_set_inventory_formspec(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + std::string formspec = luaL_checkstring(L, 2); + + player->inventory_formspec = formspec; + STACK_TO_SERVER(L)->reportInventoryFormspecModified(player->getName()); + lua_pushboolean(L, true); + return 1; +} + +// get_inventory_formspec(self) -> formspec +int ObjectRef::l_get_inventory_formspec(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL) return 0; + + std::string formspec = player->inventory_formspec; + lua_pushlstring(L, formspec.c_str(), formspec.size()); + return 1; +} + +// get_player_control(self) +int ObjectRef::l_get_player_control(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + // Do it + PlayerControl control = player->getPlayerControl(); + lua_newtable(L); + lua_pushboolean(L, control.up); + lua_setfield(L, -2, "up"); + lua_pushboolean(L, control.down); + lua_setfield(L, -2, "down"); + lua_pushboolean(L, control.left); + lua_setfield(L, -2, "left"); + lua_pushboolean(L, control.right); + lua_setfield(L, -2, "right"); + lua_pushboolean(L, control.jump); + lua_setfield(L, -2, "jump"); + lua_pushboolean(L, control.aux1); + lua_setfield(L, -2, "aux1"); + lua_pushboolean(L, control.sneak); + lua_setfield(L, -2, "sneak"); + lua_pushboolean(L, control.LMB); + lua_setfield(L, -2, "LMB"); + lua_pushboolean(L, control.RMB); + lua_setfield(L, -2, "RMB"); + return 1; +} + +// get_player_control_bits(self) +int ObjectRef::l_get_player_control_bits(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if(player == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + // Do it + lua_pushnumber(L, player->keyPressed); + return 1; +} + +// hud_add(self, form) +int ObjectRef::l_hud_add(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + HudElement *elem = new HudElement; + + elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type", + es_HudElementType, HUD_ELEM_TEXT); + + lua_getfield(L, 2, "position"); + elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "scale"); + elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + elem->name = getstringfield_default(L, 2, "name", ""); + elem->text = getstringfield_default(L, 2, "text", ""); + elem->number = getintfield_default(L, 2, "number", 0); + elem->item = getintfield_default(L, 2, "item", 0); + elem->dir = getintfield_default(L, 2, "dir", 0); + + lua_getfield(L, 2, "alignment"); + elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + lua_getfield(L, 2, "offset"); + elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); + lua_pop(L, 1); + + u32 id = STACK_TO_SERVER(L)->hudAdd(player, elem); + if (id == (u32)-1) { + delete elem; + return 0; + } + + lua_pushnumber(L, id); + return 1; +} + +// hud_remove(self, id) +int ObjectRef::l_hud_remove(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = -1; + if (!lua_isnil(L, 2)) + id = lua_tonumber(L, 2); + + if (!STACK_TO_SERVER(L)->hudRemove(player, id)) + return 0; + + lua_pushboolean(L, true); + return 1; +} + +// hud_change(self, id, stat, data) +int ObjectRef::l_hud_change(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = -1; + if (!lua_isnil(L, 2)) + id = lua_tonumber(L, 2); + + HudElementStat stat = (HudElementStat)getenumfield(L, 3, "stat", + es_HudElementStat, HUD_STAT_NUMBER); + + if (id >= player->hud.size()) + return 0; + + void *value = NULL; + HudElement *e = player->hud[id]; + if (!e) + return 0; + + switch (stat) { + case HUD_STAT_POS: + e->pos = read_v2f(L, 4); + value = &e->pos; + break; + case HUD_STAT_NAME: + e->name = lua_tostring(L, 4); + value = &e->name; + break; + case HUD_STAT_SCALE: + e->scale = read_v2f(L, 4); + value = &e->scale; + break; + case HUD_STAT_TEXT: + e->text = lua_tostring(L, 4); + value = &e->text; + break; + case HUD_STAT_NUMBER: + e->number = lua_tonumber(L, 4); + value = &e->number; + break; + case HUD_STAT_ITEM: + e->item = lua_tonumber(L, 4); + value = &e->item; + break; + case HUD_STAT_DIR: + e->dir = lua_tonumber(L, 4); + value = &e->dir; + case HUD_STAT_ALIGN: + e->align = read_v2f(L, 4); + value = &e->align; + case HUD_STAT_OFFSET: + e->offset = read_v2f(L, 4); + value = &e->offset; + } + + STACK_TO_SERVER(L)->hudChange(player, id, stat, value); + + lua_pushboolean(L, true); + return 1; +} + +// hud_get(self, id) +int ObjectRef::l_hud_get(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 id = lua_tonumber(L, -1); + if (id >= player->hud.size()) + return 0; + + HudElement *e = player->hud[id]; + if (!e) + return 0; + + lua_newtable(L); + + lua_pushstring(L, es_HudElementType[(u8)e->type].str); + lua_setfield(L, -2, "type"); + + push_v2f(L, e->pos); + lua_setfield(L, -2, "position"); + + lua_pushstring(L, e->name.c_str()); + lua_setfield(L, -2, "name"); + + push_v2f(L, e->scale); + lua_setfield(L, -2, "scale"); + + lua_pushstring(L, e->text.c_str()); + lua_setfield(L, -2, "text"); + + lua_pushnumber(L, e->number); + lua_setfield(L, -2, "number"); + + lua_pushnumber(L, e->item); + lua_setfield(L, -2, "item"); + + lua_pushnumber(L, e->dir); + lua_setfield(L, -2, "dir"); + + return 1; +} + +// hud_set_flags(self, flags) +int ObjectRef::l_hud_set_flags(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + u32 flags = 0; + u32 mask = 0; + bool flag; + + const EnumString *esp = es_HudBuiltinElement; + for (int i = 0; esp[i].str; i++) { + if (getboolfield(L, 2, esp[i].str, flag)) { + flags |= esp[i].num * flag; + mask |= esp[i].num; + } + } + if (!STACK_TO_SERVER(L)->hudSetFlags(player, flags, mask)) + return 0; + + lua_pushboolean(L, true); + return 1; +} + +ObjectRef::ObjectRef(ServerActiveObject *object): + m_object(object) +{ + //infostream<<"ObjectRef created for id="<getId()< Date: Sat, 4 May 2013 02:08:52 +0200 Subject: Add ObjectRef.hud_set_hotbar_itemcount and add TOCLIENT_HUD_SET_PARAM --- doc/lua_api.txt | 2 ++ src/client.cpp | 17 +++++++++++++++++ src/clientserver.h | 8 ++++++++ src/game.cpp | 4 ++-- src/hud.cpp | 2 +- src/hud.h | 6 +++++- src/player.cpp | 2 ++ src/player.h | 1 + src/script/lua_api/l_object.cpp | 18 ++++++++++++++++++ src/script/lua_api/l_object.h | 3 +++ src/server.cpp | 28 ++++++++++++++++++++++++++++ src/server.h | 2 ++ 12 files changed, 89 insertions(+), 4 deletions(-) (limited to 'src/script/lua_api/l_object.cpp') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 260a62763..5143c2ef3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1399,6 +1399,8 @@ Player-only: (no-op for other objects) ^ flags: (is visible) hotbar, healthbar, crosshair, wielditem ^ pass a table containing a true/false value of each flag to be set or unset ^ if a flag is nil, the flag is not modified +- hud_set_hotbar_itemcount(count): sets number of items in builtin hotbar + ^ count: number of items, must be between 1 and 23 InvRef: Reference to an inventory methods: diff --git a/src/client.cpp b/src/client.cpp index e4ca52dd5..6b1789fe0 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2136,6 +2136,23 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) player->hud_flags &= ~mask; player->hud_flags |= flags; } + else if(command == TOCLIENT_HUD_SET_PARAM) + { + std::string datastring((char *)&data[2], datasize - 2); + std::istringstream is(datastring, std::ios_base::binary); + + Player *player = m_env.getLocalPlayer(); + assert(player != NULL); + + u16 param = readU16(is); + std::string value = deSerializeString(is); + + if(param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4){ + s32 hotbar_itemcount = readS32((u8*) value.c_str()); + if(hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX) + player->hud_hotbar_itemcount = hotbar_itemcount; + } + } else { infostream<<"Client: Ignoring unknown command " diff --git a/src/clientserver.h b/src/clientserver.h index ee9271bbc..a43baab23 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -480,6 +480,14 @@ enum ToClientCommand u32 flags u32 mask */ + + TOCLIENT_HUD_SET_PARAM = 0x4d, + /* + u16 command + u16 param + u16 len + u8[len] value + */ }; enum ToServerCommand diff --git a/src/game.cpp b/src/game.cpp index 921cce327..4f0d1b663 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1987,7 +1987,7 @@ void the_game( { s32 wheel = input->getMouseWheel(); u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE-1, - hud.hotbar_itemcount-1); + player->hud_hotbar_itemcount-1); if(wheel < 0) { @@ -2011,7 +2011,7 @@ void the_game( const KeyPress *kp = NumberKey + (i + 1) % 10; if(input->wasKeyDown(*kp)) { - if(i < PLAYER_INVENTORY_SIZE && i < hud.hotbar_itemcount) + if(i < PLAYER_INVENTORY_SIZE && i < player->hud_hotbar_itemcount) { new_playeritem = i; diff --git a/src/hud.cpp b/src/hud.cpp index 65c78ca50..a3ae38bcb 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -43,7 +43,6 @@ Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv, screensize = v2u32(0, 0); displaycenter = v2s32(0, 0); hotbar_imagesize = 48; - hotbar_itemcount = 8; tsrc = gamedef->getTextureSource(); @@ -286,6 +285,7 @@ void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) { return; } + s32 hotbar_itemcount = player->hud_hotbar_itemcount; s32 padding = hotbar_imagesize / 12; s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2); v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2); diff --git a/src/hud.h b/src/hud.h index 54b7e7f36..fa9d33f8b 100644 --- a/src/hud.h +++ b/src/hud.h @@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define HUD_FLAG_CROSSHAIR_VISIBLE (1 << 2) #define HUD_FLAG_WIELDITEM_VISIBLE (1 << 3) +#define HUD_PARAM_HOTBAR_ITEMCOUNT 1 + +#define HUD_HOTBAR_ITEMCOUNT_DEFAULT 8 +#define HUD_HOTBAR_ITEMCOUNT_MAX 23 + class Player; enum HudElementType { @@ -102,7 +107,6 @@ public: v2u32 screensize; v2s32 displaycenter; s32 hotbar_imagesize; - s32 hotbar_itemcount; video::SColor crosshair_argb; video::SColor selectionbox_argb; diff --git a/src/player.cpp b/src/player.cpp index 34f0fda08..4eb5955c0 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -81,6 +81,8 @@ Player::Player(IGameDef *gamedef): hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE; + + hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT; } Player::~Player() diff --git a/src/player.h b/src/player.h index 63e166b4b..d3738fd52 100644 --- a/src/player.h +++ b/src/player.h @@ -250,6 +250,7 @@ public: std::vector hud; u32 hud_flags; + s32 hud_hotbar_itemcount; protected: IGameDef *m_gamedef; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 6dec3db85..1e45610a6 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -978,6 +978,23 @@ int ObjectRef::l_hud_set_flags(lua_State *L) return 1; } +// hud_set_hotbar_itemcount(self, hotbar_itemcount) +int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + s32 hotbar_itemcount = lua_tonumber(L, 2); + + if (!STACK_TO_SERVER(L)->hudSetHotbarItemcount(player, hotbar_itemcount)) + return 0; + + lua_pushboolean(L, true); + return 1; +} + ObjectRef::ObjectRef(ServerActiveObject *object): m_object(object) { @@ -1089,6 +1106,7 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, hud_change), luamethod(ObjectRef, hud_get), luamethod(ObjectRef, hud_set_flags), + luamethod(ObjectRef, hud_set_hotbar_itemcount), {0,0} }; diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index 88f980a27..57dac0e64 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -209,6 +209,9 @@ private: // hud_set_flags(self, flags) static int l_hud_set_flags(lua_State *L); + // hud_set_hotbar_itemcount(self, hotbar_itemcount) + static int l_hud_set_hotbar_itemcount(lua_State *L); + public: ObjectRef(ServerActiveObject *object); diff --git a/src/server.cpp b/src/server.cpp index 12695e1b4..4268bb809 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3687,6 +3687,22 @@ void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask) m_con.Send(peer_id, 0, data, true); } +void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value) +{ + std::ostringstream os(std::ios_base::binary); + + // Write command + writeU16(os, TOCLIENT_HUD_SET_PARAM); + writeU16(os, param); + os< data((u8 *)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + void Server::BroadcastChatMessage(const std::wstring &message) { for(std::map::iterator @@ -4684,6 +4700,18 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) { return true; } +bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) { + if (!player) + return false; + if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX) + return false; + + std::ostringstream os(std::ios::binary); + writeS32(os, hotbar_itemcount); + SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str()); + return true; +} + void Server::notifyPlayers(const std::wstring msg) { BroadcastChatMessage(msg); diff --git a/src/server.h b/src/server.h index 3906f43b8..edc5c4895 100644 --- a/src/server.h +++ b/src/server.h @@ -541,6 +541,7 @@ public: bool hudRemove(Player *player, u32 id); bool hudChange(Player *player, u32 id, HudElementStat stat, void *value); bool hudSetFlags(Player *player, u32 flags, u32 mask); + bool hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount); private: @@ -585,6 +586,7 @@ private: void SendHUDRemove(u16 peer_id, u32 id); void SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value); void SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask); + void SendHUDSetParam(u16 peer_id, u16 param, const std::string &value); /* Send a node removal/addition event to all clients except ignore_id. -- cgit v1.2.3