Fix heart + bubble bar size on different texture packs

Add DPI support for statbar
Move heart+bubble bar to Lua HUD
Add statbar size (based upon an idea by blue42u)
Add support for customizing breath and statbar
This commit is contained in:
sapier 2014-04-28 23:41:27 +02:00
parent c80d67f48e
commit d3ee617f37
15 changed files with 325 additions and 51 deletions

@ -29,3 +29,4 @@ dofile(modpath.."/features.lua")
dofile(modpath.."/voxelarea.lua") dofile(modpath.."/voxelarea.lua")
dofile(modpath.."/vector.lua") dofile(modpath.."/vector.lua")
dofile(modpath.."/forceloading.lua") dofile(modpath.."/forceloading.lua")
dofile(modpath.."/statbars.lua")

@ -389,6 +389,7 @@ end
minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration() minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
minetest.registered_globalsteps, minetest.register_globalstep = 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_mapgen_inits, minetest.register_on_mapgen_init = make_registration()
minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration() minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration()
minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration() minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()

160
builtin/statbars.lua Normal file

@ -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)

@ -475,6 +475,7 @@ values can be used.
The offset field specifies a pixel offset from the position. Contrary to position, 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 the offset is not scaled to screen size. This allows for some precisely-positioned
items in the HUD. 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. 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. 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. If odd, will end with a vertically center-split texture.
- direction - direction
- offset: offset in pixels from position. - offset: offset in pixels from position.
- size: If used will force full-image size to this value (override texture pack image size)
- inventory - inventory
- text: The name of the inventory list to be displayed. - text: The name of the inventory list to be displayed.
- number: Number of items in the inventory 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. - text: Distance suffix. Can be blank.
- number: An integer containing the RGB value of the color used to draw the text. - number: An integer containing the RGB value of the color used to draw the text.
- world_pos: World position of the waypoint. - world_pos: World position of the waypoint.
Representations of simple things Representations of simple things
-------------------------------- --------------------------------
Position/vector: Position/vector:
@ -1212,7 +1214,7 @@ minetest.get_player_information(playername)
max_jitter = 0.5, -- maximum packet time jitter max_jitter = 0.5, -- maximum packet time jitter
avg_jitter = 0.03, -- average packet time jitter avg_jitter = 0.03, -- average packet time jitter
connection_uptime = 200, -- seconds since client connected connection_uptime = 200, -- seconds since client connected
-- following information is available on debug build only!!! -- following information is available on debug build only!!!
-- DO NOT USE IN MODS -- DO NOT USE IN MODS
--ser_vers = 26, -- serialization version used by client --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 ^ Dig node with the same effects that a player would cause
minetest.punch_node(pos) minetest.punch_node(pos)
^ Punch node with the same effects that a player would cause ^ Punch node with the same effects that a player would cause
minetest.get_meta(pos) -- Get a NodeMetaRef at that position minetest.get_meta(pos) -- Get a NodeMetaRef at that position
minetest.get_node_timer(pos) -- Get NodeTimerRef minetest.get_node_timer(pos) -- Get NodeTimerRef
@ -1750,7 +1752,7 @@ methods:
- to_table() -> nil or {fields = {...}, inventory = {list1 = {}, ...}} - to_table() -> nil or {fields = {...}, inventory = {list1 = {}, ...}}
- from_table(nil or {}) - from_table(nil or {})
^ See "Node Metadata" ^ See "Node Metadata"
NodeTimerRef: Node Timers - a high resolution persistent per-node timer NodeTimerRef: Node Timers - a high resolution persistent per-node timer
- Can be gotten via minetest.get_node_timer(pos) - Can be gotten via minetest.get_node_timer(pos)
methods: methods:
@ -1853,12 +1855,18 @@ Player-only: (no-op for other objects)
^ flags: (is visible) hotbar, healthbar, crosshair, wielditem ^ flags: (is visible) hotbar, healthbar, crosshair, wielditem
^ pass a table containing a true/false value of each flag to be set or unset ^ 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 ^ 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 - hud_set_hotbar_itemcount(count): sets number of items in builtin hotbar
^ count: number of items, must be between 1 and 23 ^ count: number of items, must be between 1 and 23
- hud_set_hotbar_image(texturename) - hud_set_hotbar_image(texturename)
^ sets background image for hotbar ^ sets background image for hotbar
- hud_set_hotbar_selected_image(texturename) - hud_set_hotbar_selected_image(texturename)
^ sets image for selected item of hotbar ^ 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}) - set_sky(bgcolor, type, {texture names})
^ bgcolor: {r=0...255, g=0...255, b=0...255} or nil, defaults to white ^ bgcolor: {r=0...255, g=0...255, b=0...255} or nil, defaults to white
^ Available types: ^ Available types:
@ -2172,7 +2180,7 @@ Object Properties
Entity definition (register_entity) Entity definition (register_entity)
{ {
(Deprecated: Everything in object properties is read directly from here) (Deprecated: Everything in object properties is read directly from here)
initial_properties = <initial object properties>, initial_properties = <initial object properties>,
on_activate = function(self, staticdata, dtime_s), on_activate = function(self, staticdata, dtime_s),
@ -2182,7 +2190,7 @@ Entity definition (register_entity)
get_staticdata = function(self), get_staticdata = function(self),
^ Called sometimes; the string returned is passed to on_activate when ^ Called sometimes; the string returned is passed to on_activate when
the entity is re-activated from static state the entity is re-activated from static state
# Also you can define arbitrary member variables here # Also you can define arbitrary member variables here
myvariable = whatever, myvariable = whatever,
} }
@ -2345,7 +2353,7 @@ Node definition (register_node)
can_dig = function(pos,player) can_dig = function(pos,player)
^ returns true if node can be dug, or false if not ^ returns true if node can be dug, or false if not
^ default: nil ^ default: nil
on_punch = func(pos, node, puncher, pointed_thing), on_punch = func(pos, node, puncher, pointed_thing),
^ default: minetest.node_punch ^ default: minetest.node_punch
^ By default: Calls minetest.register_on_punchnode callbacks ^ 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 ^ if defined, itemstack will hold clicker's wielded item
^ Shall return the leftover itemstack ^ Shall return the leftover itemstack
^ Note: pointed_thing can be nil, if a mod calls this function ^ Note: pointed_thing can be nil, if a mod calls this function
on_dig = func(pos, node, digger), on_dig = func(pos, node, digger),
^ default: minetest.node_dig ^ default: minetest.node_dig
^ By default: checks privileges, wears out tool and removes node ^ By default: checks privileges, wears out tool and removes node
on_timer = function(pos,elapsed), on_timer = function(pos,elapsed),
^ default: nil ^ default: nil
^ called by NodeTimers, see minetest.get_node_timer and NodeTimerRef ^ called by NodeTimers, see minetest.get_node_timer and NodeTimerRef
@ -2374,12 +2382,12 @@ Node definition (register_node)
to_list, to_index, count, player), to_list, to_index, count, player),
^ Called when a player wants to move items inside the inventory ^ Called when a player wants to move items inside the inventory
^ Return value: number of items allowed to move ^ Return value: number of items allowed to move
allow_metadata_inventory_put = func(pos, listname, index, stack, player), allow_metadata_inventory_put = func(pos, listname, index, stack, player),
^ Called when a player wants to put something into the inventory ^ Called when a player wants to put something into the inventory
^ Return value: number of items allowed to put ^ Return value: number of items allowed to put
^ Return value: -1: Allow and don't modify item count in inventory ^ Return value: -1: Allow and don't modify item count in inventory
allow_metadata_inventory_take = func(pos, listname, index, stack, player), allow_metadata_inventory_take = func(pos, listname, index, stack, player),
^ Called when a player wants to take something out of the inventory ^ Called when a player wants to take something out of the inventory
^ Return value: number of items allowed to take ^ 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), on_metadata_inventory_take = func(pos, listname, index, stack, player),
^ Called after the actual action has happened, according to what was allowed. ^ Called after the actual action has happened, according to what was allowed.
^ No return value ^ No return value
on_blast = func(pos, intensity), on_blast = func(pos, intensity),
^ intensity: 1.0 = mid range of regular TNT ^ intensity: 1.0 = mid range of regular TNT
^ If defined, called when an explosion touches the node, instead of ^ 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), 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 ^ Called when a player wants to move items inside the inventory
^ Return value: number of items allowed to move ^ Return value: number of items allowed to move
allow_put = func(inv, listname, index, stack, player), allow_put = func(inv, listname, index, stack, player),
^ Called when a player wants to put something into the inventory ^ Called when a player wants to put something into the inventory
^ Return value: number of items allowed to put ^ Return value: number of items allowed to put
^ Return value: -1: Allow and don't modify item count in inventory ^ Return value: -1: Allow and don't modify item count in inventory
allow_take = func(inv, listname, index, stack, player), allow_take = func(inv, listname, index, stack, player),
^ Called when a player wants to take something out of the inventory ^ Called when a player wants to take something out of the inventory
^ Return value: number of items allowed to take ^ Return value: number of items allowed to take
^ Return value: -1: Allow and don't modify item count in inventory ^ 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_move = func(inv, from_list, from_index, to_list, to_index, count, player),
on_put = func(inv, listname, index, stack, player), on_put = func(inv, listname, index, stack, player),
on_take = 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" ^ See "HUD Element Types"
offset = {x=0, y=0}, offset = {x=0, y=0},
^ See "HUD Element Types" ^ See "HUD Element Types"
size = { x=100, y=100 },
^ Size of element in pixels
} }
Particle definition (add_particle) Particle definition (add_particle)

@ -1787,9 +1787,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
v2f align = readV2F1000(is); v2f align = readV2F1000(is);
v2f offset = readV2F1000(is); v2f offset = readV2F1000(is);
v3f world_pos; v3f world_pos;
v2s32 size;
try{ try{
world_pos = readV3F1000(is); world_pos = readV3F1000(is);
}catch(SerializationError &e) {}; }catch(SerializationError &e) {};
try{
size = readV2S32(is);
} catch(SerializationError &e) {};
ClientEvent event; ClientEvent event;
event.type = CE_HUDADD; 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.align = new v2f(align);
event.hudadd.offset = new v2f(offset); event.hudadd.offset = new v2f(offset);
event.hudadd.world_pos = new v3f(world_pos); event.hudadd.world_pos = new v3f(world_pos);
event.hudadd.size = new v2s32(size);
m_client_event_queue.push_back(event); m_client_event_queue.push_back(event);
} }
else if(command == TOCLIENT_HUDRM) else if(command == TOCLIENT_HUDRM)
@ -1825,6 +1830,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
v2f v2fdata; v2f v2fdata;
v3f v3fdata; v3f v3fdata;
u32 intdata = 0; u32 intdata = 0;
v2s32 v2s32data;
std::string datastring((char *)&data[2], datasize - 2); std::string datastring((char *)&data[2], datasize - 2);
std::istringstream is(datastring, std::ios_base::binary); 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); sdata = deSerializeString(is);
else if (stat == HUD_STAT_WORLD_POS) else if (stat == HUD_STAT_WORLD_POS)
v3fdata = readV3F1000(is); v3fdata = readV3F1000(is);
else if (stat == HUD_STAT_SIZE )
v2s32data = readV2S32(is);
else else
intdata = readU32(is); 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.v3fdata = new v3f(v3fdata);
event.hudchange.sdata = new std::string(sdata); event.hudchange.sdata = new std::string(sdata);
event.hudchange.data = intdata; event.hudchange.data = intdata;
event.hudchange.v2s32data = new v2s32(v2s32data);
m_client_event_queue.push_back(event); m_client_event_queue.push_back(event);
} }
else if(command == TOCLIENT_HUD_SET_FLAGS) else if(command == TOCLIENT_HUD_SET_FLAGS)

@ -215,6 +215,7 @@ struct ClientEvent
v2f *align; v2f *align;
v2f *offset; v2f *offset;
v3f *world_pos; v3f *world_pos;
v2s32 * size;
} hudadd; } hudadd;
struct{ struct{
u32 id; u32 id;
@ -226,6 +227,7 @@ struct ClientEvent
std::string *sdata; std::string *sdata;
u32 data; u32 data;
v3f *v3fdata; v3f *v3fdata;
v2s32 * v2s32data;
} hudchange; } hudchange;
struct{ struct{
video::SColor *bgcolor; video::SColor *bgcolor;

@ -150,7 +150,7 @@ enum ToClientCommand
u8 keep_metadata // Added in protocol version 22 u8 keep_metadata // Added in protocol version 22
*/ */
TOCLIENT_REMOVENODE = 0x22, TOCLIENT_REMOVENODE = 0x22,
TOCLIENT_PLAYERPOS = 0x23, // Obsolete TOCLIENT_PLAYERPOS = 0x23, // Obsolete
/* /*
[0] u16 command [0] u16 command
@ -171,7 +171,7 @@ enum ToClientCommand
[N] u16 peer_id [N] u16 peer_id
[N] char[20] name [N] char[20] name
*/ */
TOCLIENT_OPT_BLOCK_NOT_FOUND = 0x25, // Obsolete TOCLIENT_OPT_BLOCK_NOT_FOUND = 0x25, // Obsolete
TOCLIENT_SECTORMETA = 0x26, // Obsolete TOCLIENT_SECTORMETA = 0x26, // Obsolete
@ -186,7 +186,7 @@ enum ToClientCommand
[0] u16 command [0] u16 command
[2] serialized inventory [2] serialized inventory
*/ */
TOCLIENT_OBJECTDATA = 0x28, // Obsolete TOCLIENT_OBJECTDATA = 0x28, // Obsolete
/* /*
Sent as unreliable. Sent as unreliable.
@ -237,7 +237,7 @@ enum ToClientCommand
string initialization data string initialization data
} }
*/ */
TOCLIENT_ACTIVE_OBJECT_MESSAGES = 0x32, TOCLIENT_ACTIVE_OBJECT_MESSAGES = 0x32,
/* /*
u16 command u16 command
@ -303,21 +303,21 @@ enum ToClientCommand
u16 length of remote media server url (if applicable) u16 length of remote media server url (if applicable)
string url string url
*/ */
TOCLIENT_TOOLDEF = 0x39, TOCLIENT_TOOLDEF = 0x39,
/* /*
u16 command u16 command
u32 length of the next item u32 length of the next item
serialized ToolDefManager serialized ToolDefManager
*/ */
TOCLIENT_NODEDEF = 0x3a, TOCLIENT_NODEDEF = 0x3a,
/* /*
u16 command u16 command
u32 length of the next item u32 length of the next item
serialized NodeDefManager serialized NodeDefManager
*/ */
TOCLIENT_CRAFTITEMDEF = 0x3b, TOCLIENT_CRAFTITEMDEF = 0x3b,
/* /*
u16 command u16 command
@ -344,7 +344,7 @@ enum ToClientCommand
u32 length of next item u32 length of next item
serialized ItemDefManager serialized ItemDefManager
*/ */
TOCLIENT_PLAY_SOUND = 0x3f, TOCLIENT_PLAY_SOUND = 0x3f,
/* /*
u16 command u16 command
@ -472,6 +472,8 @@ enum ToClientCommand
u32 dir u32 dir
v2f1000 align v2f1000 align
v2f1000 offset v2f1000 offset
v3f1000 world_pos
v2s32 size
*/ */
TOCLIENT_HUDRM = 0x4a, TOCLIENT_HUDRM = 0x4a,
@ -530,7 +532,7 @@ enum ToClientCommand
u8 do_override (boolean) u8 do_override (boolean)
u16 day-night ratio 0...65535 u16 day-night ratio 0...65535
*/ */
TOCLIENT_LOCAL_PLAYER_ANIMATIONS = 0x51, TOCLIENT_LOCAL_PLAYER_ANIMATIONS = 0x51,
/* /*
u16 command u16 command
@ -634,7 +636,7 @@ enum ToServerCommand
2: stop digging (all parameters ignored) 2: stop digging (all parameters ignored)
3: digging completed 3: digging completed
*/ */
TOSERVER_RELEASE = 0x29, // Obsolete TOSERVER_RELEASE = 0x29, // Obsolete
// (oops, there is some gap here) // (oops, there is some gap here)
@ -676,7 +678,7 @@ enum ToServerCommand
[3] u16 id [3] u16 id
[5] u16 item [5] u16 item
*/ */
TOSERVER_DAMAGE = 0x35, TOSERVER_DAMAGE = 0x35,
/* /*
u16 command u16 command
@ -699,7 +701,7 @@ enum ToServerCommand
[0] u16 TOSERVER_PLAYERITEM [0] u16 TOSERVER_PLAYERITEM
[2] u16 item [2] u16 item
*/ */
TOSERVER_RESPAWN=0x38, TOSERVER_RESPAWN=0x38,
/* /*
u16 TOSERVER_RESPAWN u16 TOSERVER_RESPAWN
@ -721,7 +723,7 @@ enum ToServerCommand
(Obsoletes TOSERVER_GROUND_ACTION and TOSERVER_CLICK_ACTIVEOBJECT.) (Obsoletes TOSERVER_GROUND_ACTION and TOSERVER_CLICK_ACTIVEOBJECT.)
*/ */
TOSERVER_REMOVED_SOUNDS = 0x3a, TOSERVER_REMOVED_SOUNDS = 0x3a,
/* /*
u16 command u16 command

@ -2492,6 +2492,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
delete event.hudadd.align; delete event.hudadd.align;
delete event.hudadd.offset; delete event.hudadd.offset;
delete event.hudadd.world_pos; delete event.hudadd.world_pos;
delete event.hudadd.size;
continue; continue;
} }
@ -2507,6 +2508,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
e->align = *event.hudadd.align; e->align = *event.hudadd.align;
e->offset = *event.hudadd.offset; e->offset = *event.hudadd.offset;
e->world_pos = *event.hudadd.world_pos; e->world_pos = *event.hudadd.world_pos;
e->size = *event.hudadd.size;
if (id == nhudelem) if (id == nhudelem)
player->hud.push_back(e); 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.align;
delete event.hudadd.offset; delete event.hudadd.offset;
delete event.hudadd.world_pos; delete event.hudadd.world_pos;
delete event.hudadd.size;
} }
else if (event.type == CE_HUDRM) 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.v3fdata;
delete event.hudchange.v2fdata; delete event.hudchange.v2fdata;
delete event.hudchange.sdata; delete event.hudchange.sdata;
delete event.hudchange.v2s32data;
continue; continue;
} }
@ -2571,11 +2575,15 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
case HUD_STAT_WORLD_POS: case HUD_STAT_WORLD_POS:
e->world_pos = *event.hudchange.v3fdata; e->world_pos = *event.hudchange.v3fdata;
break; break;
case HUD_STAT_SIZE:
e->size = *event.hudchange.v2s32data;
break;
} }
delete event.hudchange.v3fdata; delete event.hudchange.v3fdata;
delete event.hudchange.v2fdata; delete event.hudchange.v2fdata;
delete event.hudchange.sdata; delete event.hudchange.sdata;
delete event.hudchange.v2s32data;
} }
else if (event.type == CE_SET_SKY) else if (event.type == CE_SET_SKY)
{ {
@ -3563,8 +3571,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
*/ */
if (show_hud) if (show_hud)
{ {
hud.drawHotbar(client.getHP(), client.getPlayerItem(), hud.drawHotbar(client.getPlayerItem());
client.getBreath());
} }
/* /*

@ -228,7 +228,8 @@ void Hud::drawLuaElements(v3s16 camera_offset) {
if (!e) if (!e)
continue; 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) { switch (e->type) {
case HUD_ELEM_IMAGE: { case HUD_ELEM_IMAGE: {
video::ITexture *texture = tsrc->getTexture(e->text); video::ITexture *texture = tsrc->getTexture(e->text);
@ -266,7 +267,7 @@ void Hud::drawLuaElements(v3s16 camera_offset) {
break; } break; }
case HUD_ELEM_STATBAR: { case HUD_ELEM_STATBAR: {
v2s32 offs(e->offset.X, e->offset.Y); 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; } break; }
case HUD_ELEM_INVENTORY: { case HUD_ELEM_INVENTORY: {
InventoryList *inv = inventory->getList(e->text); 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 color(255, 255, 255, 255);
const video::SColor colors[] = {color, color, color, color}; 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; return;
core::dimension2di srcd(stat_texture->getOriginalSize()); 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; v2s32 p = pos;
if (corner & HUD_CORNER_LOWER) if (corner & HUD_CORNER_LOWER)
p -= srcd.Height; p -= dstd.Height;
p += offset; p += offset;
@ -338,13 +356,13 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s
default: default:
steppos = v2s32(1, 0); steppos = v2s32(1, 0);
} }
steppos.X *= srcd.Width; steppos.X *= dstd.Width;
steppos.Y *= srcd.Height; steppos.Y *= dstd.Height;
for (s32 i = 0; i < count / 2; i++) for (s32 i = 0; i < count / 2; i++)
{ {
core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height); core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
core::rect<s32> dstrect(srcrect); core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
dstrect += p; dstrect += p;
driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true); 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) if (count % 2 == 1)
{ {
core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height); core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
core::rect<s32> dstrect(srcrect); core::rect<s32> dstrect(0,0, dstd.Width / 2, dstd.Height);
dstrect += p; dstrect += p;
driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true); 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); 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); 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));
} }

@ -66,7 +66,8 @@ enum HudElementStat {
HUD_STAT_DIR, HUD_STAT_DIR,
HUD_STAT_ALIGN, HUD_STAT_ALIGN,
HUD_STAT_OFFSET, HUD_STAT_OFFSET,
HUD_STAT_WORLD_POS HUD_STAT_WORLD_POS,
HUD_STAT_SIZE
}; };
struct HudElement { struct HudElement {
@ -81,6 +82,7 @@ struct HudElement {
v2f align; v2f align;
v2f offset; v2f offset;
v3f world_pos; v3f world_pos;
v2s32 size;
}; };
#ifndef SERVER #ifndef SERVER
@ -122,14 +124,14 @@ public:
u32 text_height, IGameDef *gamedef, u32 text_height, IGameDef *gamedef,
LocalPlayer *player, Inventory *inventory); LocalPlayer *player, Inventory *inventory);
void drawHotbar(s32 halfheartcount, u16 playeritem, s32 breath); void drawHotbar(u16 playeritem);
void resizeHotbar(); void resizeHotbar();
void drawCrosshair(); void drawCrosshair();
void drawSelectionBoxes(std::vector<aabb3f> &hilightboxes); void drawSelectionBoxes(std::vector<aabb3f> &hilightboxes);
void drawLuaElements(v3s16 camera_offset); void drawLuaElements(v3s16 camera_offset);
private: private:
void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
std::string texture, s32 count, v2s32 offset); s32 count, v2s32 offset, v2s32 size=v2s32());
void drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset, void drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
InventoryList *mainlist, u16 selectitem, u16 direction); InventoryList *mainlist, u16 selectitem, u16 direction);

@ -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) void ScriptApiEnv::environment_OnMapgenInit(MapgenParams *mgparams)
{ {
SCRIPTAPI_PRECHECKHEADER SCRIPTAPI_PRECHECKHEADER

@ -37,6 +37,9 @@ public:
// After initializing mapgens // After initializing mapgens
void environment_OnMapgenInit(MapgenParams *mgparams); void environment_OnMapgenInit(MapgenParams *mgparams);
//called on player event
void player_event(ServerActiveObject* player, std::string type);
void initializeEnvironment(ServerEnvironment *env); void initializeEnvironment(ServerEnvironment *env);
}; };

@ -906,6 +906,10 @@ int ObjectRef::l_hud_add(lua_State *L)
elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f(); elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
lua_pop(L, 1); 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->name = getstringfield_default(L, 2, "name", "");
elem->text = getstringfield_default(L, 2, "text", ""); elem->text = getstringfield_default(L, 2, "text", "");
elem->number = getintfield_default(L, 2, "number", 0); 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(); elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
lua_pop(L, 1); 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); u32 id = getServer(L)->hudAdd(player, elem);
if (id == (u32)-1) { if (id == (u32)-1) {
delete elem; delete elem;
@ -1019,6 +1028,10 @@ int ObjectRef::l_hud_change(lua_State *L)
e->world_pos = read_v3f(L, 4); e->world_pos = read_v3f(L, 4);
value = &e->world_pos; value = &e->world_pos;
break; break;
case HUD_STAT_SIZE:
e->size = read_v2s32(L, 4);
value = &e->size;
break;
} }
getServer(L)->hudChange(player, id, stat, value); getServer(L)->hudChange(player, id, stat, value);
@ -1101,6 +1114,28 @@ int ObjectRef::l_hud_set_flags(lua_State *L)
return 1; 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) // hud_set_hotbar_itemcount(self, hotbar_itemcount)
int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L) 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_change),
luamethod(ObjectRef, hud_get), luamethod(ObjectRef, hud_get),
luamethod(ObjectRef, hud_set_flags), luamethod(ObjectRef, hud_set_flags),
luamethod(ObjectRef, hud_get_flags),
luamethod(ObjectRef, hud_set_hotbar_itemcount), luamethod(ObjectRef, hud_set_hotbar_itemcount),
luamethod(ObjectRef, hud_set_hotbar_image), luamethod(ObjectRef, hud_set_hotbar_image),
luamethod(ObjectRef, hud_set_hotbar_selected_image), luamethod(ObjectRef, hud_set_hotbar_selected_image),

@ -216,6 +216,9 @@ private:
// hud_set_flags(self, flags) // hud_set_flags(self, flags)
static int l_hud_set_flags(lua_State *L); 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) // hud_set_hotbar_itemcount(self, hotbar_itemcount)
static int l_hud_set_hotbar_itemcount(lua_State *L); static int l_hud_set_hotbar_itemcount(lua_State *L);

@ -646,7 +646,7 @@ void Server::AsyncRunStep(bool initial_step)
/* /*
Send player breath if changed Send player breath if changed
*/ */
if(playersao->m_breath_not_sent){ if(playersao->m_breath_not_sent) {
SendPlayerBreath(*i); SendPlayerBreath(*i);
} }
@ -2202,6 +2202,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
std::istringstream is(datastring, std::ios_base::binary); std::istringstream is(datastring, std::ios_base::binary);
u16 breath = readU16(is); u16 breath = readU16(is);
playersao->setBreath(breath); playersao->setBreath(breath);
m_script->player_event(playersao,"breath_changed");
} }
else if(command == TOSERVER_PASSWORD) 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->align);
writeV2F1000(os, form->offset); writeV2F1000(os, form->offset);
writeV3F1000(os, form->world_pos); writeV3F1000(os, form->world_pos);
writeV2S32(os,form->size);
// Make data buffer // Make data buffer
std::string s = os.str(); 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: case HUD_STAT_WORLD_POS:
writeV3F1000(os, *(v3f *)value); writeV3F1000(os, *(v3f *)value);
break; break;
case HUD_STAT_SIZE:
writeV2S32(os,*(v2s32 *)value);
break;
case HUD_STAT_NUMBER: case HUD_STAT_NUMBER:
case HUD_STAT_ITEM: case HUD_STAT_ITEM:
case HUD_STAT_DIR: case HUD_STAT_DIR:
@ -3445,6 +3450,7 @@ void Server::SendPlayerHP(u16 peer_id)
assert(playersao); assert(playersao);
playersao->m_hp_not_sent = false; playersao->m_hp_not_sent = false;
SendHP(peer_id, playersao->getHP()); SendHP(peer_id, playersao->getHP());
m_script->player_event(playersao,"health_changed");
// Send to other clients // Send to other clients
std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP()); 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); PlayerSAO *playersao = getPlayerSAO(peer_id);
assert(playersao); assert(playersao);
playersao->m_breath_not_sent = false; playersao->m_breath_not_sent = false;
m_script->player_event(playersao,"breath_changed");
SendBreath(peer_id, playersao->getBreath()); SendBreath(peer_id, playersao->getBreath());
} }
@ -4588,6 +4595,8 @@ bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
return false; return false;
SendHUDSetFlags(player->peer_id, flags, mask); SendHUDSetFlags(player->peer_id, flags, mask);
m_script->player_event(player->getPlayerSAO(),"hud_changed");
return true; return true;
} }