--- --- Generated by EmmyLua(https://github.com/EmmyLua) --- Created by lars. --- DateTime: 11.03.19 18:28 --- log.create_channel("deathlist") -- Create log channel local coordinate={type="table", children={ x={type="number"}, y={type="number"} }} local color={type="table", children={ r={type="number", interval={0,255}}, g={type="number", interval={0,255}}, b={type="number", interval={0,255}} }} local node_caused={children={ color=color, method={type="string"}, nodes={type="table", keys={type="string"}, values={type="table", keys={possible_values={name=true, color=true, method=true}}}}, }} local config=conf.import("deathlist",{ type="table", children={ max_messages={type="number", interval={1}}, mode={type="string", possible_values={list=true,stack=true}}, autoremove_interval={func=function(interval) if type(interval) ~= "number" and interval ~= false then return "Wrong type : Expected number or false, found "..type(interval) end if interval <= 0 then return "Too small : Interval has to be > 0" end end}, hud_pos=coordinate, hud_base_offset=coordinate, enable_environmental={type="boolean"}, enable_unknown={type="boolean"}, enable_forbidden_playernames={type="boolean"}, environmental_reasons={ children={ falling={ children={ name={type="string"}, color=color, method={type="string"} } }, unknown={ children={ name={type="string"}, color=color, method={type="string"} } }, drowning=node_caused, node_damage=node_caused } } } }) table_ext.add_all(getfenv(1), config) if enable_forbidden_playernames then player_ext.register_forbidden_name(environmental_reasons.falling.name) if enable_unknown then player_ext.register_forbidden_name(environmental_reasons.unknown.name) end for name, node in pairs(minetest.registered_nodes) do if (node.drowning or 0) > 0 then local title=(environmental_reasons.drowning.nodes[name] or {}).name or node.description player_ext.register_forbidden_name(title) end if (node.damage_per_second or 0) > 0 then local title=(environmental_reasons.node_damage.nodes[name] or {}).name or node.description player_ext.register_forbidden_name(title) end end end table_ext.map(environmental_reasons, function(v) v.color=mt_ext.get_color_int(v.color) return v end) table_ext.map(environmental_reasons.drowning.nodes, function(v) if v.color then v.color=mt_ext.get_color_int(v.color) end return v end) table_ext.map(environmental_reasons.node_damage.nodes, function(v) if v.color then v.color=mt_ext.get_color_int(v.color) end return v end) hud_channels ={ killers={}, items={}, victims={}} -- in order to reduce overhead minetest.register_on_joinplayer(function(player) hud_channels.killers[player:get_player_name()]={} hud_channels.items[player:get_player_name()]={} hud_channels.victims[player:get_player_name()]={} end) minetest.register_on_leaveplayer(function(player) hud_channels.killers[player:get_player_name()]=nil hud_channels.items[player:get_player_name()]=nil hud_channels.victims[player:get_player_name()]=nil end) function remove_last_kill_msg_from_hud(listname, x_offset) local list= hud_channels[listname] for _,player in pairs(minetest.get_connected_players()) do local name=player:get_player_name() local hud_ids=list[name] local i=#list[name] if mode=="list" then player:hud_remove(hud_ids[i]) hud_ids[i]=nil else player:hud_remove(hud_ids[1]) -- Will be replaced for j=2,i do local new={x=hud_base_offset.x+x_offset,y=hud_base_offset.y-((j-2)*20)} player:hud_change(hud_ids[j],"offset",new) hud_ids[j-1]=hud_ids[j] --Perform index shift end hud_ids[i]=nil end list[name]=hud_ids end end function remove_last_kill_message() if not threading_ext.request("deathlist.hud_lists",remove_last_kill_message) then return end remove_last_kill_msg_from_hud("killers",-20) remove_last_kill_msg_from_hud("victims",20) remove_last_kill_msg_from_hud("items",0) threading_ext.free("deathlist.hud_lists") end local last_message=0 if autoremove_interval then minetest.register_globalstep(function(dtime) last_message=last_message+dtime if last_message > autoremove_interval then remove_last_kill_message() last_message=0 end end) end function add_kill_msg_to_hud(msg, listname, hud_def, x_offset) -- MAY NOT BE CALLED SIMULTANEOUSLY local _, value=next(hud_channels[listname]) if table_ext.is_empty(value) then last_message=0 end local list= hud_channels[listname] hud_def.text=msg hud_def.offset={x=x_offset+hud_base_offset.x} for _,player in pairs(minetest.get_connected_players()) do local name=player:get_player_name() local hud_ids=list[name] --Hud elem IDs hud_ids=list[name] or {} local i=#hud_ids if (i == max_messages) then --Have to remove if mode=="list" then player:hud_remove(hud_ids[i]) else player:hud_remove(hud_ids[1]) -- Will be replaced for j=2,i do local new={x=hud_def.offset.x,y=hud_base_offset.y-((j-2)*20)} player:hud_change(hud_ids[j],"offset",new) hud_ids[j-1]=hud_ids[j] --Perform index shift end end i=i-1 end if mode=="list" then for j=i,1,-1 do local new={x=hud_def.offset.x,y=hud_base_offset.y-(j*20)} player:hud_change(hud_ids[j],"offset",new) hud_ids[j+1]=hud_ids[j] --Perform index shift end hud_def.offset.y=hud_base_offset.y hud_ids[1]=player:hud_add(hud_def) else hud_def.offset.y=hud_base_offset.y-(i*20) hud_ids[i+1]=player:hud_add(hud_def) end list[name]=hud_ids --Update IDs end end function add_kill_message(killer, tool_image, victim) if not threading_ext.request("deathlist.hud_lists",add_kill_message, killer, tool_image, victim) then return end add_kill_msg_to_hud(killer.name,"killers",{hud_elem_type="text",position=hud_pos,scale={x=100,y=100}, number=killer.color or 0xFFFFFF, alignment = {x=-1,y=0}},-20) add_kill_msg_to_hud(victim.name,"victims",{hud_elem_type="text",position=hud_pos,number=victim.color or 0xFFFFFF,alignment = {x=1,y=0}},20) add_kill_msg_to_hud((tool_image or "deathlist_tombstone.png").."^[resize:16x16", "items",{hud_elem_type="image",position=hud_pos,scale={x=1,y=1}, alignment = {x=0,y=0}},0) threading_ext.free("deathlist.hud_lists") end function add_environmental_kill_message(cause, victim) --Falling & Unknown add_kill_message({name=environmental_reasons[cause].name, color=environmental_reasons[cause].color}, environmental_reasons[cause].method,victim) end function add_node_kill_message(killing_node, cause, victim) --Drowning & Node Damage local override=environmental_reasons[cause].nodes[killing_node.name] or {} local method=override.method or environmental_reasons[cause].method if method=="generate" then method=mt_ext.get_node_inventory_image(killing_node.name) end add_kill_message({name=override.name or killing_node.description, color=override.color or environmental_reasons[cause].color}, method, victim) end if enable_environmental then minetest.register_on_player_hpchange( function(player, hp_change, reason) if player:get_hp() > 0 and player:get_hp()+hp_change <= 0 then local victim={name=player:get_player_name(), color=player_ext.get_color_int(player)} if reason.type=="fall" then add_environmental_kill_message("falling", victim) log.write("deathlist","Player "..victim.name.." died due to falling") elseif reason.type=="drown" then local eye_pos=vector.add(player:get_pos(), {x=0, z=0, y=player:get_properties().eye_height}) local drowning_node=minetest.registered_nodes[minetest.get_node(eye_pos).name] add_node_kill_message(drowning_node, "drowning", victim) log.write("deathlist","Player "..victim.name.." died due to drowning in "..drowning_node.name) elseif reason.type=="node_damage" then local killing_node_feet=minetest.registered_nodes[minetest.get_node(player:get_pos()).name] local eye_pos=vector.add(player:get_pos(), {x=0, z=0, y=player:get_properties().eye_height}) local killing_node_head=minetest.registered_nodes[minetest.get_node(eye_pos).name] local killing_node=killing_node_feet if (killing_node_head.node_damage or 0) > (killing_node_feet.node_damage or 0) then killing_node=killing_node_head end add_node_kill_message(killing_node, "node_damage", victim) log.write("deathlist","Player "..victim.name.." died due to node damage of "..killing_node.name) elseif reason.type~="punch" and enable_unknown then add_environmental_kill_message("unknown", victim) log.write("deathlist","Player "..victim.name.." died for unknown reasons.") end end end ) end minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage) if player:get_hp() > 0 and player:get_hp()-damage <= 0 and hitter then local wielded_item_name=hitter:get_wielded_item():get_name() local tool if minetest.registered_nodes[wielded_item_name] then tool=mt_ext.get_node_inventory_image(wielded_item_name) else tool=(minetest.registered_items[wielded_item_name] or {inventory_image="deathlist_gravestone.png"}).inventory_image end local killer={name=hitter:get_player_name(), color=player_ext.get_color_int(hitter)} local victim={name=player:get_player_name(), color=player_ext.get_color_int(player)} add_kill_message(killer,tool,victim) log.write("deathlist","Player "..killer.name.." killed "..victim.name.." using "..wielded_item_name) end end )