diff --git a/builtin/builtin.lua b/builtin/builtin.lua index a51264618..1babe006f 100644 --- a/builtin/builtin.lua +++ b/builtin/builtin.lua @@ -29,3 +29,4 @@ dofile(modpath.."/features.lua") dofile(modpath.."/voxelarea.lua") dofile(modpath.."/vector.lua") dofile(modpath.."/forceloading.lua") +dofile(modpath.."/statbars.lua") diff --git a/builtin/misc_register.lua b/builtin/misc_register.lua index 4b44b0ad2..99c5115c4 100644 --- a/builtin/misc_register.lua +++ b/builtin/misc_register.lua @@ -389,6 +389,7 @@ end minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration() minetest.registered_globalsteps, minetest.register_globalstep = make_registration() +minetest.registered_playerevents, minetest.register_playerevent = make_registration() minetest.registered_on_mapgen_inits, minetest.register_on_mapgen_init = make_registration() minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration() minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration() diff --git a/builtin/statbars.lua b/builtin/statbars.lua new file mode 100644 index 000000000..ca656a974 --- /dev/null +++ b/builtin/statbars.lua @@ -0,0 +1,160 @@ + +local health_bar_definition = +{ + hud_elem_type = "statbar", + position = { x=0.5, y=1 }, + text = "heart.png", + number = 20, + direction = 0, + size = { x=24, y=24 }, + offset = { x=(-10*24)-25, y=-(48+24+10)}, +} + +local breath_bar_definition = +{ + hud_elem_type = "statbar", + position = { x=0.5, y=1 }, + text = "bubble.png", + number = 20, + direction = 0, + size = { x=24, y=24 }, + offset = {x=25,y=-(48+24+10)}, +} + +local hud_ids = {} + +local function initialize_builtin_statbars(player) + + if not player:is_player() then + return + end + + local name = player:get_player_name() + + if name == "" then + return + end + + if (hud_ids[name] == nil) then + hud_ids[name] = {} + end + + if player:hud_get_flags().healthbar then + if hud_ids[name].id_healthbar == nil then + health_bar_definition.number = player:get_hp() + hud_ids[name].id_healthbar = player:hud_add(health_bar_definition) + end + else + if hud_ids[name].id_healthbar ~= nil then + player:hud_remove(hud_ids[name].id_healthbar) + hud_ids[name].id_healthbar = nil + end + end + + if (player:get_breath() < 11) then + if player:hud_get_flags().breathbar then + if hud_ids[name].id_breathbar == nil then + hud_ids[name].id_breathbar = player:hud_add(breath_bar_definition) + end + else + if hud_ids[name].id_breathbar ~= nil then + player:hud_remove(hud_ids[name].id_breathbar) + hud_ids[name].id_breathbar = nil + end + end + elseif hud_ids[name].id_breathbar ~= nil then + player:hud_remove(hud_ids[name].id_breathbar) + hud_ids[name].id_breathbar = nil + end +end + +local function cleanup_builtin_statbars(player) + + if not player:is_player() then + return + end + + local name = player:get_player_name() + + if name == "" then + return + end + + hud_ids[name] = nil +end + +local function player_event_handler(player,eventname) + assert(player:is_player()) + + local name = player:get_player_name() + + if name == "" then + return + end + + if eventname == "health_changed" then + initialize_builtin_statbars(player) + + if hud_ids[name].id_healthbar ~= nil then + player:hud_change(hud_ids[name].id_healthbar,"number",player:get_hp()) + return true + end + end + + if eventname == "breath_changed" then + initialize_builtin_statbars(player) + + if hud_ids[name].id_breathbar ~= nil then + player:hud_change(hud_ids[name].id_breathbar,"number",player:get_breath()*2) + return true + end + end + + if eventname == "hud_changed" then + initialize_builtin_statbars(player) + return true + end + + return false +end + +function minetest.hud_replace_builtin(name, definition) + + if definition == nil or + type(definition) ~= "table" or + definition.hud_elem_type ~= "statbar" then + return false + end + + if name == "health" then + health_bar_definition = definition + + for name,ids in pairs(hud_ids) do + local player = minetest.get_player_by_name(name) + if player and hud_ids[name].id_healthbar then + player:hud_remove(hud_ids[name].id_healthbar) + initialize_builtin_statbars(player) + end + end + return true + end + + if name == "breath" then + breath_bar_definition = definition + + for name,ids in pairs(hud_ids) do + local player = minetest.get_player_by_name(name) + if player and hud_ids[name].id_breathbar then + player:hud_remove(hud_ids[name].id_breathbar) + initialize_builtin_statbars(player) + end + end + return true + end + + return false +end + +minetest.register_on_joinplayer(initialize_builtin_statbars) +minetest.register_on_leaveplayer(cleanup_builtin_statbars) +minetest.register_playerevent(player_event_handler) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 53740b20a..164aa393e 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -475,6 +475,7 @@ values can be used. The offset field specifies a pixel offset from the position. Contrary to position, the offset is not scaled to screen size. This allows for some precisely-positioned items in the HUD. +Note offset WILL adapt to screen dpi as well as user defined scaling factor! Below are the specific uses for fields in each type; fields not listed for that type are ignored. Note: Future revisions to the HUD API may be incompatible; the HUD API is still in the experimental stages. @@ -504,6 +505,7 @@ Note: Future revisions to the HUD API may be incompatible; the HUD API is still If odd, will end with a vertically center-split texture. - direction - offset: offset in pixels from position. + - size: If used will force full-image size to this value (override texture pack image size) - inventory - text: The name of the inventory list to be displayed. - number: Number of items in the inventory to be displayed. @@ -515,7 +517,7 @@ Note: Future revisions to the HUD API may be incompatible; the HUD API is still - text: Distance suffix. Can be blank. - number: An integer containing the RGB value of the color used to draw the text. - world_pos: World position of the waypoint. - + Representations of simple things -------------------------------- Position/vector: @@ -1212,7 +1214,7 @@ minetest.get_player_information(playername) max_jitter = 0.5, -- maximum packet time jitter avg_jitter = 0.03, -- average packet time jitter connection_uptime = 200, -- seconds since client connected - + -- following information is available on debug build only!!! -- DO NOT USE IN MODS --ser_vers = 26, -- serialization version used by client @@ -1375,7 +1377,7 @@ minetest.dig_node(pos) ^ Dig node with the same effects that a player would cause minetest.punch_node(pos) ^ Punch node with the same effects that a player would cause - + minetest.get_meta(pos) -- Get a NodeMetaRef at that position minetest.get_node_timer(pos) -- Get NodeTimerRef @@ -1750,7 +1752,7 @@ methods: - to_table() -> nil or {fields = {...}, inventory = {list1 = {}, ...}} - from_table(nil or {}) ^ See "Node Metadata" - + NodeTimerRef: Node Timers - a high resolution persistent per-node timer - Can be gotten via minetest.get_node_timer(pos) methods: @@ -1853,12 +1855,18 @@ 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_get_flags(): returns a table containing status of hud flags + ^ returns { hotbar=true, healthbar=true, crosshair=true, wielditem=true, breathbar=true } - hud_set_hotbar_itemcount(count): sets number of items in builtin hotbar ^ count: number of items, must be between 1 and 23 - hud_set_hotbar_image(texturename) ^ sets background image for hotbar - hud_set_hotbar_selected_image(texturename) ^ sets image for selected item of hotbar +- hud_replace_builtin(name, hud definition) + ^ replace definition of a builtin hud element + ^ name: "breath" or "health" + ^ hud definition: definition to replace builtin definition - set_sky(bgcolor, type, {texture names}) ^ bgcolor: {r=0...255, g=0...255, b=0...255} or nil, defaults to white ^ Available types: @@ -2172,7 +2180,7 @@ Object Properties Entity definition (register_entity) { (Deprecated: Everything in object properties is read directly from here) - + initial_properties = , on_activate = function(self, staticdata, dtime_s), @@ -2182,7 +2190,7 @@ Entity definition (register_entity) get_staticdata = function(self), ^ Called sometimes; the string returned is passed to on_activate when the entity is re-activated from static state - + # Also you can define arbitrary member variables here myvariable = whatever, } @@ -2345,7 +2353,7 @@ Node definition (register_node) can_dig = function(pos,player) ^ returns true if node can be dug, or false if not ^ default: nil - + on_punch = func(pos, node, puncher, pointed_thing), ^ default: minetest.node_punch ^ By default: Calls minetest.register_on_punchnode callbacks @@ -2354,11 +2362,11 @@ Node definition (register_node) ^ if defined, itemstack will hold clicker's wielded item ^ Shall return the leftover itemstack ^ Note: pointed_thing can be nil, if a mod calls this function - + on_dig = func(pos, node, digger), ^ default: minetest.node_dig ^ By default: checks privileges, wears out tool and removes node - + on_timer = function(pos,elapsed), ^ default: nil ^ called by NodeTimers, see minetest.get_node_timer and NodeTimerRef @@ -2374,12 +2382,12 @@ Node definition (register_node) to_list, to_index, count, player), ^ Called when a player wants to move items inside the inventory ^ Return value: number of items allowed to move - + allow_metadata_inventory_put = func(pos, listname, index, stack, player), ^ Called when a player wants to put something into the inventory ^ Return value: number of items allowed to put ^ Return value: -1: Allow and don't modify item count in inventory - + allow_metadata_inventory_take = func(pos, listname, index, stack, player), ^ Called when a player wants to take something out of the inventory ^ Return value: number of items allowed to take @@ -2391,7 +2399,7 @@ Node definition (register_node) on_metadata_inventory_take = func(pos, listname, index, stack, player), ^ Called after the actual action has happened, according to what was allowed. ^ No return value - + on_blast = func(pos, intensity), ^ intensity: 1.0 = mid range of regular TNT ^ If defined, called when an explosion touches the node, instead of @@ -2543,17 +2551,17 @@ Detached inventory callbacks allow_move = func(inv, from_list, from_index, to_list, to_index, count, player), ^ Called when a player wants to move items inside the inventory ^ Return value: number of items allowed to move - + allow_put = func(inv, listname, index, stack, player), ^ Called when a player wants to put something into the inventory ^ Return value: number of items allowed to put ^ Return value: -1: Allow and don't modify item count in inventory - + allow_take = func(inv, listname, index, stack, player), ^ Called when a player wants to take something out of the inventory ^ Return value: number of items allowed to take ^ Return value: -1: Allow and don't modify item count in inventory - + on_move = func(inv, from_list, from_index, to_list, to_index, count, player), on_put = func(inv, listname, index, stack, player), on_take = func(inv, listname, index, stack, player), @@ -2579,6 +2587,8 @@ HUD Definition (hud_add, hud_get) ^ See "HUD Element Types" offset = {x=0, y=0}, ^ See "HUD Element Types" + size = { x=100, y=100 }, + ^ Size of element in pixels } Particle definition (add_particle) diff --git a/src/client.cpp b/src/client.cpp index 50162b1e9..b0488500f 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1787,9 +1787,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) v2f align = readV2F1000(is); v2f offset = readV2F1000(is); v3f world_pos; + v2s32 size; try{ world_pos = readV3F1000(is); }catch(SerializationError &e) {}; + try{ + size = readV2S32(is); + } catch(SerializationError &e) {}; ClientEvent event; event.type = CE_HUDADD; @@ -1805,6 +1809,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) event.hudadd.align = new v2f(align); event.hudadd.offset = new v2f(offset); event.hudadd.world_pos = new v3f(world_pos); + event.hudadd.size = new v2s32(size); m_client_event_queue.push_back(event); } else if(command == TOCLIENT_HUDRM) @@ -1825,6 +1830,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) v2f v2fdata; v3f v3fdata; u32 intdata = 0; + v2s32 v2s32data; std::string datastring((char *)&data[2], datasize - 2); std::istringstream is(datastring, std::ios_base::binary); @@ -1839,6 +1845,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) sdata = deSerializeString(is); else if (stat == HUD_STAT_WORLD_POS) v3fdata = readV3F1000(is); + else if (stat == HUD_STAT_SIZE ) + v2s32data = readV2S32(is); else intdata = readU32(is); @@ -1850,6 +1858,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) event.hudchange.v3fdata = new v3f(v3fdata); event.hudchange.sdata = new std::string(sdata); event.hudchange.data = intdata; + event.hudchange.v2s32data = new v2s32(v2s32data); m_client_event_queue.push_back(event); } else if(command == TOCLIENT_HUD_SET_FLAGS) diff --git a/src/client.h b/src/client.h index fd07f26b4..51ce5b8f2 100644 --- a/src/client.h +++ b/src/client.h @@ -215,6 +215,7 @@ struct ClientEvent v2f *align; v2f *offset; v3f *world_pos; + v2s32 * size; } hudadd; struct{ u32 id; @@ -226,6 +227,7 @@ struct ClientEvent std::string *sdata; u32 data; v3f *v3fdata; + v2s32 * v2s32data; } hudchange; struct{ video::SColor *bgcolor; diff --git a/src/clientserver.h b/src/clientserver.h index 1f2e19e45..a995d8b99 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -150,7 +150,7 @@ enum ToClientCommand u8 keep_metadata // Added in protocol version 22 */ TOCLIENT_REMOVENODE = 0x22, - + TOCLIENT_PLAYERPOS = 0x23, // Obsolete /* [0] u16 command @@ -171,7 +171,7 @@ enum ToClientCommand [N] u16 peer_id [N] char[20] name */ - + TOCLIENT_OPT_BLOCK_NOT_FOUND = 0x25, // Obsolete TOCLIENT_SECTORMETA = 0x26, // Obsolete @@ -186,7 +186,7 @@ enum ToClientCommand [0] u16 command [2] serialized inventory */ - + TOCLIENT_OBJECTDATA = 0x28, // Obsolete /* Sent as unreliable. @@ -237,7 +237,7 @@ enum ToClientCommand string initialization data } */ - + TOCLIENT_ACTIVE_OBJECT_MESSAGES = 0x32, /* u16 command @@ -303,21 +303,21 @@ enum ToClientCommand u16 length of remote media server url (if applicable) string url */ - + TOCLIENT_TOOLDEF = 0x39, /* u16 command u32 length of the next item serialized ToolDefManager */ - + TOCLIENT_NODEDEF = 0x3a, /* u16 command u32 length of the next item serialized NodeDefManager */ - + TOCLIENT_CRAFTITEMDEF = 0x3b, /* u16 command @@ -344,7 +344,7 @@ enum ToClientCommand u32 length of next item serialized ItemDefManager */ - + TOCLIENT_PLAY_SOUND = 0x3f, /* u16 command @@ -472,6 +472,8 @@ enum ToClientCommand u32 dir v2f1000 align v2f1000 offset + v3f1000 world_pos + v2s32 size */ TOCLIENT_HUDRM = 0x4a, @@ -530,7 +532,7 @@ enum ToClientCommand u8 do_override (boolean) u16 day-night ratio 0...65535 */ - + TOCLIENT_LOCAL_PLAYER_ANIMATIONS = 0x51, /* u16 command @@ -634,7 +636,7 @@ enum ToServerCommand 2: stop digging (all parameters ignored) 3: digging completed */ - + TOSERVER_RELEASE = 0x29, // Obsolete // (oops, there is some gap here) @@ -676,7 +678,7 @@ enum ToServerCommand [3] u16 id [5] u16 item */ - + TOSERVER_DAMAGE = 0x35, /* u16 command @@ -699,7 +701,7 @@ enum ToServerCommand [0] u16 TOSERVER_PLAYERITEM [2] u16 item */ - + TOSERVER_RESPAWN=0x38, /* u16 TOSERVER_RESPAWN @@ -721,7 +723,7 @@ enum ToServerCommand (Obsoletes TOSERVER_GROUND_ACTION and TOSERVER_CLICK_ACTIVEOBJECT.) */ - + TOSERVER_REMOVED_SOUNDS = 0x3a, /* u16 command diff --git a/src/game.cpp b/src/game.cpp index a9ca38d1d..8a0aa1776 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2492,6 +2492,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete event.hudadd.align; delete event.hudadd.offset; delete event.hudadd.world_pos; + delete event.hudadd.size; continue; } @@ -2507,6 +2508,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, e->align = *event.hudadd.align; e->offset = *event.hudadd.offset; e->world_pos = *event.hudadd.world_pos; + e->size = *event.hudadd.size; if (id == nhudelem) player->hud.push_back(e); @@ -2520,6 +2522,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete event.hudadd.align; delete event.hudadd.offset; delete event.hudadd.world_pos; + delete event.hudadd.size; } else if (event.type == CE_HUDRM) { @@ -2536,6 +2539,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, delete event.hudchange.v3fdata; delete event.hudchange.v2fdata; delete event.hudchange.sdata; + delete event.hudchange.v2s32data; continue; } @@ -2571,11 +2575,15 @@ void the_game(bool &kill, bool random_input, InputHandler *input, case HUD_STAT_WORLD_POS: e->world_pos = *event.hudchange.v3fdata; break; + case HUD_STAT_SIZE: + e->size = *event.hudchange.v2s32data; + break; } delete event.hudchange.v3fdata; delete event.hudchange.v2fdata; delete event.hudchange.sdata; + delete event.hudchange.v2s32data; } else if (event.type == CE_SET_SKY) { @@ -3563,8 +3571,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input, */ if (show_hud) { - hud.drawHotbar(client.getHP(), client.getPlayerItem(), - client.getBreath()); + hud.drawHotbar(client.getPlayerItem()); } /* diff --git a/src/hud.cpp b/src/hud.cpp index c385211f2..7f2f4276c 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -228,7 +228,8 @@ void Hud::drawLuaElements(v3s16 camera_offset) { if (!e) continue; - v2s32 pos(e->pos.X * m_screensize.X, e->pos.Y * m_screensize.Y); + v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5), + floor(e->pos.Y * (float) m_screensize.Y + 0.5)); switch (e->type) { case HUD_ELEM_IMAGE: { video::ITexture *texture = tsrc->getTexture(e->text); @@ -266,7 +267,7 @@ void Hud::drawLuaElements(v3s16 camera_offset) { break; } case HUD_ELEM_STATBAR: { v2s32 offs(e->offset.X, e->offset.Y); - drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs); + drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size); break; } case HUD_ELEM_INVENTORY: { InventoryList *inv = inventory->getList(e->text); @@ -308,7 +309,9 @@ void Hud::drawLuaElements(v3s16 camera_offset) { } -void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count, v2s32 offset) { +void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, + s32 count, v2s32 offset, v2s32 size) +{ const video::SColor color(255, 255, 255, 255); const video::SColor colors[] = {color, color, color, color}; @@ -317,10 +320,25 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s return; core::dimension2di srcd(stat_texture->getOriginalSize()); + core::dimension2di dstd; + if (size == v2s32()) { + dstd = srcd; + } else { + dstd.Height = size.Y * g_settings->getFloat("gui_scaling") * + porting::getDisplayDensity(); + dstd.Width = size.X * g_settings->getFloat("gui_scaling") * + porting::getDisplayDensity(); + + offset.X *= g_settings->getFloat("gui_scaling") * + porting::getDisplayDensity(); + + offset.Y *= g_settings->getFloat("gui_scaling") * + porting::getDisplayDensity(); + } v2s32 p = pos; if (corner & HUD_CORNER_LOWER) - p -= srcd.Height; + p -= dstd.Height; p += offset; @@ -338,13 +356,13 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s default: steppos = v2s32(1, 0); } - steppos.X *= srcd.Width; - steppos.Y *= srcd.Height; + steppos.X *= dstd.Width; + steppos.Y *= dstd.Height; for (s32 i = 0; i < count / 2; i++) { core::rect srcrect(0, 0, srcd.Width, srcd.Height); - core::rect dstrect(srcrect); + core::rect dstrect(0,0, dstd.Width, dstd.Height); dstrect += p; driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true); @@ -354,7 +372,7 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s if (count % 2 == 1) { core::rect srcrect(0, 0, srcd.Width / 2, srcd.Height); - core::rect dstrect(srcrect); + core::rect dstrect(0,0, dstd.Width / 2, dstd.Height); dstrect += p; driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true); @@ -362,7 +380,7 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s } -void Hud::drawHotbar(s32 halfheartcount, u16 playeritem, s32 breath) { +void Hud::drawHotbar(u16 playeritem) { v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y); @@ -393,13 +411,6 @@ void Hud::drawHotbar(s32 halfheartcount, u16 playeritem, s32 breath) { drawItems(secondpos, hotbar_itemcount, hotbar_itemcount/2, mainlist, playeritem + 1, 0); } } - - if (player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE) - drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT, - "heart.png", halfheartcount, v2s32(0, 0)); - if (player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE && breath <= 10) - drawStatbar(pos - v2s32(-180, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT, - "bubble.png", breath*2, v2s32(0, 0)); } diff --git a/src/hud.h b/src/hud.h index 1ace6646f..9969fce73 100644 --- a/src/hud.h +++ b/src/hud.h @@ -66,7 +66,8 @@ enum HudElementStat { HUD_STAT_DIR, HUD_STAT_ALIGN, HUD_STAT_OFFSET, - HUD_STAT_WORLD_POS + HUD_STAT_WORLD_POS, + HUD_STAT_SIZE }; struct HudElement { @@ -81,6 +82,7 @@ struct HudElement { v2f align; v2f offset; v3f world_pos; + v2s32 size; }; #ifndef SERVER @@ -122,14 +124,14 @@ public: u32 text_height, IGameDef *gamedef, LocalPlayer *player, Inventory *inventory); - void drawHotbar(s32 halfheartcount, u16 playeritem, s32 breath); + void drawHotbar(u16 playeritem); void resizeHotbar(); void drawCrosshair(); void drawSelectionBoxes(std::vector &hilightboxes); void drawLuaElements(v3s16 camera_offset); private: - void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, - std::string texture, s32 count, v2s32 offset); + void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, + s32 count, v2s32 offset, v2s32 size=v2s32()); void drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset, InventoryList *mainlist, u16 selectitem, u16 direction); diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp index b0de675ec..ee3783bb9 100644 --- a/src/script/cpp_api/s_env.cpp +++ b/src/script/cpp_api/s_env.cpp @@ -58,6 +58,24 @@ void ScriptApiEnv::environment_Step(float dtime) } } +void ScriptApiEnv::player_event(ServerActiveObject* player, std::string type) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_playerevents + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_playerevents"); + + // Call callbacks + objectrefGetOrCreate(player); // player + lua_pushstring(L,type.c_str()); // event type + try { + script_run_callbacks(L, 2, RUN_CALLBACKS_MODE_FIRST); + } catch (LuaError &e) { + getServer()->setAsyncFatalError(e.what()); + } +} + void ScriptApiEnv::environment_OnMapgenInit(MapgenParams *mgparams) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_env.h b/src/script/cpp_api/s_env.h index 51cf15036..33bd81ab3 100644 --- a/src/script/cpp_api/s_env.h +++ b/src/script/cpp_api/s_env.h @@ -37,6 +37,9 @@ public: // After initializing mapgens void environment_OnMapgenInit(MapgenParams *mgparams); + //called on player event + void player_event(ServerActiveObject* player, std::string type); + void initializeEnvironment(ServerEnvironment *env); }; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 30d423e6a..704037437 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -906,6 +906,10 @@ int ObjectRef::l_hud_add(lua_State *L) elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); lua_pop(L, 1); + lua_getfield(L, 2, "size"); + elem->size = lua_istable(L, -1) ? read_v2s32(L, -1) : v2s32(); + 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); @@ -924,6 +928,11 @@ int ObjectRef::l_hud_add(lua_State *L) elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f(); lua_pop(L, 1); + /* check for known deprecated element usage */ + if ((elem->type == HUD_ELEM_STATBAR) && (elem->size == v2s32())) { + log_deprecated(L,"Deprecated usage of statbar without size!"); + } + u32 id = getServer(L)->hudAdd(player, elem); if (id == (u32)-1) { delete elem; @@ -1019,6 +1028,10 @@ int ObjectRef::l_hud_change(lua_State *L) e->world_pos = read_v3f(L, 4); value = &e->world_pos; break; + case HUD_STAT_SIZE: + e->size = read_v2s32(L, 4); + value = &e->size; + break; } getServer(L)->hudChange(player, id, stat, value); @@ -1101,6 +1114,28 @@ int ObjectRef::l_hud_set_flags(lua_State *L) return 1; } +int ObjectRef::l_hud_get_flags(lua_State *L) +{ + ObjectRef *ref = checkobject(L, 1); + Player *player = getplayer(ref); + if (player == NULL) + return 0; + + lua_newtable(L); + lua_pushboolean(L, player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE); + lua_setfield(L, -2, "hotbar"); + lua_pushboolean(L, player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE); + lua_setfield(L, -2, "healthbar"); + lua_pushboolean(L, player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE); + lua_setfield(L, -2, "crosshair"); + lua_pushboolean(L, player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE); + lua_setfield(L, -2, "wielditem"); + lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE); + lua_setfield(L, -2, "breathbar"); + + return 1; +} + // hud_set_hotbar_itemcount(self, hotbar_itemcount) int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L) { @@ -1321,6 +1356,7 @@ const luaL_reg ObjectRef::methods[] = { luamethod(ObjectRef, hud_change), luamethod(ObjectRef, hud_get), luamethod(ObjectRef, hud_set_flags), + luamethod(ObjectRef, hud_get_flags), luamethod(ObjectRef, hud_set_hotbar_itemcount), luamethod(ObjectRef, hud_set_hotbar_image), luamethod(ObjectRef, hud_set_hotbar_selected_image), diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index f6070585d..d51ca379f 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -216,6 +216,9 @@ private: // hud_set_flags(self, flags) static int l_hud_set_flags(lua_State *L); + // hud_get_flags() + static int l_hud_get_flags(lua_State *L); + // hud_set_hotbar_itemcount(self, hotbar_itemcount) static int l_hud_set_hotbar_itemcount(lua_State *L); diff --git a/src/server.cpp b/src/server.cpp index fc01898cc..ed99a7214 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -646,7 +646,7 @@ void Server::AsyncRunStep(bool initial_step) /* Send player breath if changed */ - if(playersao->m_breath_not_sent){ + if(playersao->m_breath_not_sent) { SendPlayerBreath(*i); } @@ -2202,6 +2202,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) std::istringstream is(datastring, std::ios_base::binary); u16 breath = readU16(is); playersao->setBreath(breath); + m_script->player_event(playersao,"breath_changed"); } else if(command == TOSERVER_PASSWORD) { @@ -3289,6 +3290,7 @@ void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form) writeV2F1000(os, form->align); writeV2F1000(os, form->offset); writeV3F1000(os, form->world_pos); + writeV2S32(os,form->size); // Make data buffer std::string s = os.str(); @@ -3335,6 +3337,9 @@ void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value case HUD_STAT_WORLD_POS: writeV3F1000(os, *(v3f *)value); break; + case HUD_STAT_SIZE: + writeV2S32(os,*(v2s32 *)value); + break; case HUD_STAT_NUMBER: case HUD_STAT_ITEM: case HUD_STAT_DIR: @@ -3445,6 +3450,7 @@ void Server::SendPlayerHP(u16 peer_id) assert(playersao); playersao->m_hp_not_sent = false; SendHP(peer_id, playersao->getHP()); + m_script->player_event(playersao,"health_changed"); // Send to other clients std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP()); @@ -3458,6 +3464,7 @@ void Server::SendPlayerBreath(u16 peer_id) PlayerSAO *playersao = getPlayerSAO(peer_id); assert(playersao); playersao->m_breath_not_sent = false; + m_script->player_event(playersao,"breath_changed"); SendBreath(peer_id, playersao->getBreath()); } @@ -4588,6 +4595,8 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) { return false; SendHUDSetFlags(player->peer_id, flags, mask); + + m_script->player_event(player->getPlayerSAO(),"hud_changed"); return true; }