From b0545dc5c2ee3551b08b33bc8c208b27b5230367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Fri, 5 May 2023 07:31:06 +0200 Subject: [PATCH 01/30] bones: bones are now holding 150 item slots and register_transfer_inventory_to_bones_on_player_death callback --- game_api.txt | 10 +++ mods/bones/init.lua | 158 ++++++++++++++++++++++++++++---------------- 2 files changed, 111 insertions(+), 57 deletions(-) diff --git a/game_api.txt b/game_api.txt index e46ea6bd53..add44971af 100644 --- a/game_api.txt +++ b/game_api.txt @@ -83,6 +83,16 @@ in `bones.player_inventory_lists`. e.g. `table.insert(bones.player_inventory_lists, "backpack")` +Additionally, callbacks can be registered to transfer items into the bones on death: + +`bones.public.register_transfer_inventory_to_bones_on_player_death(function(player){})` + +In the above functions this routine should be used to add itmes to the bones inventory: + +`bones.public.transfer_stack_to_bones(stack)` + +please note that the inventory these items were taken from still need to be disposed of. + Creative API ------------ diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 725f662218..669d697fe7 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -5,8 +5,22 @@ -- Load support for MT game translation. local S = minetest.get_translator("bones") - -bones = {} +-- bones are supposed to hold up to 4*8+6+4*3*8+4+3*3 item slots: +-- 4*8 for the main inventory +-- 6 for the 3d_armor +-- (at most) 4*3*8 for 4 backpack worth of items (unified inventory) +-- 4 more for the actual backpacks +-- 3*3 more for the crafting grid +-- that adds up to 147, so 150 slots would be sufficient +local cols=15 +local rows=10 + +bones = { + private={ + dead_player_callbacks={} + }, + public={} +} local function is_owner(pos, name) local owner = minetest.get_meta(pos):get_string("owner") @@ -17,10 +31,10 @@ local function is_owner(pos, name) end local bones_formspec = - "size[8,9]" .. - "list[current_name;main;0,0.3;8,4;]" .. - "list[current_player;main;0,4.85;8,1;]" .. - "list[current_player;main;0,6.08;8,3;8]" .. + "size["..cols..","..(rows+5).."]" .. + "list[current_name;main;0,0.3;"..cols..","..rows..";]" .. + "list[current_player;main;"..((cols-8)/2)..","..rows..".85;8,1;]" .. + "list[current_player;main;"..((cols-8)/2)..","..(rows+2)..".08;8,3;8]" .. "listring[current_name;main]" .. "listring[current_player;main]" .. default.get_hotbar_bg(0,4.85) @@ -194,15 +208,68 @@ local function is_all_empty(player_inv) return true end +--functions registered this way won't becalled if bones_mode is keep +function bones.public.register_transfer_inventory_to_bones_on_player_death(func) + bones.private.dead_player_callbacks[#(bones.private.dead_player_callbacks)]=func +end + +--drop or put into bones based on config and free slots in the bones +--supposed to be called from functions registered to bones.public.register_transfer_inventory_to_bones_on_player_death +function bones.public.transfer_stack_to_bones(stk) + -- check if it's possible to place bones, if not find space near player + if ( ( bones.private.current_dead_player.bones_mode == "bones" ) and ( bones.private.current_dead_player.bones_pos == nil ) ) then + bones.private.current_dead_player.bones_pos = bones.private.current_dead_player.player_pos + local air + if ( may_replace(bones.private.current_dead_player.bones_pos, bones.private.current_dead_player.player) ) then + air = bones.private.current_dead_player.bones_pos + else + air = minetest.find_node_near(bones.private.current_dead_player.bones_pos, 1, {"air"}) + end + + if air and not minetest.is_protected(air, bones.private.current_dead_player.player_name) then + bones.private.current_dead_player.bones_pos = air + local param2 = minetest.dir_to_facedir(bones.private.current_dead_player.player:get_look_dir()) + minetest.set_node(bones.private.current_dead_player.bones_pos, {name = "bones:bones", param2 = param2}) + local meta = minetest.get_meta(bones.private.current_dead_player.bones_pos) + bones.private.current_dead_player.bones_inv = meta:get_inventory() + bones.private.current_dead_player.bones_inv:set_size("main", cols * rows) + else + bones.private.current_dead_player.bones_mode = "drop" + bones.private.current_dead_player.bones_pos = nil + end + end + + if ( ( bones.private.current_dead_player.bones_mode == "bones" ) and ( bones.private.current_dead_player.bones_inv:room_for_item("main", stk) ) ) then + bones.private.current_dead_player.bones_inv:add_item("main", stk) + else + drop(bones.private.current_dead_player.player_pos, stk) + bones.private.current_dead_player.dropped=true + end +end + +local function player_dies_transfer_inventory(player) + local player_inv = player:get_inventory() + for _, list_name in ipairs(player_inventory_lists) do + for i = 1, player_inv:get_size(list_name) do + local stack = player_inv:get_stack(list_name, i) + bones.public.transfer_stack_to_bones(stack) + end + player_inv:set_list(list_name, {}) + end +end + +bones.public.register_transfer_inventory_to_bones_on_player_death(player_dies_transfer_inventory) + minetest.register_on_dieplayer(function(player) + local pos = vector.round(player:get_pos()) local bones_mode = minetest.settings:get("bones_mode") or "bones" if bones_mode ~= "bones" and bones_mode ~= "drop" and bones_mode ~= "keep" then bones_mode = "bones" end + local player_name = player:get_player_name() + bones.private.current_dead_player={player=player, player_name=player_name, bones_inv=nil, bones_pos=nil, bones_mode=bones_mode, player_pos=pos, dropped=false} local bones_position_message = minetest.settings:get_bool("bones_position_message") == true - local player_name = player:get_player_name() - local pos = vector.round(player:get_pos()) local pos_string = minetest.pos_to_string(pos) -- return if keep inventory set or in creative mode @@ -215,67 +282,43 @@ minetest.register_on_dieplayer(function(player) return end - local player_inv = player:get_inventory() - if is_all_empty(player_inv) then - minetest.log("action", player_name .. " dies at " .. pos_string .. - ". No bones placed") - if bones_position_message then - minetest.chat_send_player(player_name, S("@1 died at @2.", player_name, pos_string)) - end - return + for i=0,#bones.private.dead_player_callbacks do + local fun=bones.private.dead_player_callbacks[i] + fun(player) end - -- check if it's possible to place bones, if not find space near player - if bones_mode == "bones" and not may_replace(pos, player) then - local air = minetest.find_node_near(pos, 1, {"air"}) - if air then - pos = air - else - bones_mode = "drop" - end - end + local bones_conclusion="" + local public_conclusion="" - if bones_mode == "drop" then - for _, list_name in ipairs(player_inventory_lists) do - for i = 1, player_inv:get_size(list_name) do - drop(pos, player_inv:get_stack(list_name, i)) - end - player_inv:set_list(list_name, {}) + if(not(bones.private.current_dead_player.bones_pos))then + drop(bones.private.current_dead_player.player_pos, ItemStack("bones:bones")) + if(not(bones.private.current_dead_player.dropped))then + bones_conclusion="No bones placed" + else + bones_conclusion="Inventory dropped" + public_conclusion="dropped their inventory" end - drop(pos, ItemStack("bones:bones")) - minetest.log("action", player_name .. " dies at " .. pos_string .. - ". Inventory dropped") - if bones_position_message then - minetest.chat_send_player(player_name, S("@1 died at @2, and dropped their inventory.", player_name, pos_string)) + else + if(not(bones.private.current_dead_player.dropped))then + bones_conclusion="Bones placed" + public_conclusion="bones were placed" + else + bones_conclusion="Inventory partially dropped" + public_conclusion="partially dropped their inventory" end - return end - local param2 = minetest.dir_to_facedir(player:get_look_dir()) - minetest.set_node(pos, {name = "bones:bones", param2 = param2}) - minetest.log("action", player_name .. " dies at " .. pos_string .. - ". Bones placed") - if bones_position_message then - minetest.chat_send_player(player_name, S("@1 died at @2, and bones were placed.", player_name, pos_string)) - end + ". " .. bones_conclusion) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - inv:set_size("main", 8 * 4) - - for _, list_name in ipairs(player_inventory_lists) do - for i = 1, player_inv:get_size(list_name) do - local stack = player_inv:get_stack(list_name, i) - if inv:room_for_item("main", stack) then - inv:add_item("main", stack) - else -- no space left - drop(pos, stack) - end + if bones_position_message then + if(public_conclusion~="")then + public_conclusion=", and "..public_conclusion end - player_inv:set_list(list_name, {}) + minetest.chat_send_player(player_name, S("@1 died at @2@3.", player_name, pos_string, public_conclusion)) end + local meta = minetest.get_meta(bones.private.current_dead_player.bones_pos) meta:set_string("formspec", bones_formspec) meta:set_string("owner", player_name) @@ -292,4 +335,5 @@ minetest.register_on_dieplayer(function(player) else meta:set_string("infotext", S("@1's bones", player_name)) end + bones.private.current_dead_player=nil end) From 3dad8a530d68f94cc5a34d29cbeae1bfb66229f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Fri, 5 May 2023 17:50:43 +0200 Subject: [PATCH 02/30] fixes as per code review completed --- game_api.txt | 6 +- mods/bones/init.lua | 192 +++++++++++++++++++++++--------------------- 2 files changed, 105 insertions(+), 93 deletions(-) diff --git a/game_api.txt b/game_api.txt index add44971af..953f0e7292 100644 --- a/game_api.txt +++ b/game_api.txt @@ -85,11 +85,11 @@ e.g. `table.insert(bones.player_inventory_lists, "backpack")` Additionally, callbacks can be registered to transfer items into the bones on death: -`bones.public.register_transfer_inventory_to_bones_on_player_death(function(player){})` +`bones.register_dead_player_inv_management(function(player,callback){})` -In the above functions this routine should be used to add itmes to the bones inventory: +In the above functions the provided callback should be used to add items to the bones inventory: -`bones.public.transfer_stack_to_bones(stack)` +`callback(stack)` please note that the inventory these items were taken from still need to be disposed of. diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 669d697fe7..060efebfc3 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -5,22 +5,11 @@ -- Load support for MT game translation. local S = minetest.get_translator("bones") --- bones are supposed to hold up to 4*8+6+4*3*8+4+3*3 item slots: --- 4*8 for the main inventory --- 6 for the 3d_armor --- (at most) 4*3*8 for 4 backpack worth of items (unified inventory) --- 4 more for the actual backpacks --- 3*3 more for the crafting grid --- that adds up to 147, so 150 slots would be sufficient -local cols=15 -local rows=10 - -bones = { - private={ - dead_player_callbacks={} - }, - public={} -} + +local theoretical_max_slots = minetest.settings:get("bones_max_slots") or ( 15 * 10 ) +local dead_player_callbacks={} + +bones = {} local function is_owner(pos, name) local owner = minetest.get_meta(pos):get_string("owner") @@ -30,14 +19,29 @@ local function is_owner(pos, name) return false end -local bones_formspec = - "size["..cols..","..(rows+5).."]" .. - "list[current_name;main;0,0.3;"..cols..","..rows..";]" .. - "list[current_player;main;"..((cols-8)/2)..","..rows..".85;8,1;]" .. - "list[current_player;main;"..((cols-8)/2)..","..(rows+2)..".08;8,3;8]" .. - "listring[current_name;main]" .. - "listring[current_player;main]" .. - default.get_hotbar_bg(0,4.85) +local function get_bones_formspec_wh(cols,rows) + return + "size[" .. cols .. "," .. ( rows + 5 ) .. "]" .. + "list[current_name;main;0,0.3;" .. cols .. "," .. rows .. ";]" .. + "list[current_player;main;" .. ( ( cols - 8 ) / 2 ) .. "," .. rows .. ".85;8,1;]" .. + "list[current_player;main;".. ( ( cols - 8 ) / 2 ) .. "," .. ( rows + 2 ) .. ".08;8,3;8]" .. + "listring[current_name;main]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0,4.85) +end + +local function get_bones_formspec_for_size(numitems) + --the absolute minimum is 4*8 + if numitems <= 4 * 8 then + return get_bones_formspec_wh(8, 4) + end + --if we're over 4*8, but below 4*15 we make it 4 rows and adjust the column count to make everything fit + if numitems <= 4 * 15 then + return get_bones_formspec_wh( math.floor ( ( numitems + 3 ) / 4 ), 4) + end + --if we're over 4*15 we'll make 15 columns and adjust the row count to make everything fit + return get_bones_formspec_wh(15, math.floor ( ( numitems + 14 ) / 15 ) ) +end local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200 local share_bones_time_early = tonumber(minetest.settings:get("share_bones_time_early")) or share_bones_time / 4 @@ -199,66 +203,58 @@ end local player_inventory_lists = { "main", "craft" } bones.player_inventory_lists = player_inventory_lists -local function is_all_empty(player_inv) - for _, list_name in ipairs(player_inventory_lists) do - if not player_inv:is_empty(list_name) then - return false - end - end - return true -end - --functions registered this way won't becalled if bones_mode is keep -function bones.public.register_transfer_inventory_to_bones_on_player_death(func) - bones.private.dead_player_callbacks[#(bones.private.dead_player_callbacks)]=func +function bones.register_dead_player_inv_management(func) + table.insert(dead_player_callbacks, func) end ---drop or put into bones based on config and free slots in the bones ---supposed to be called from functions registered to bones.public.register_transfer_inventory_to_bones_on_player_death -function bones.public.transfer_stack_to_bones(stk) +local function transfer_stack_to_bones(stk,current_dead_player) -- check if it's possible to place bones, if not find space near player - if ( ( bones.private.current_dead_player.bones_mode == "bones" ) and ( bones.private.current_dead_player.bones_pos == nil ) ) then - bones.private.current_dead_player.bones_pos = bones.private.current_dead_player.player_pos + if ( current_dead_player.bones_mode == "bones" ) and + ( current_dead_player.bones_pos == nil ) then + current_dead_player.bones_pos = current_dead_player.player_pos local air - if ( may_replace(bones.private.current_dead_player.bones_pos, bones.private.current_dead_player.player) ) then - air = bones.private.current_dead_player.bones_pos + if may_replace(current_dead_player.bones_pos, current_dead_player.player) then + air = current_dead_player.bones_pos else - air = minetest.find_node_near(bones.private.current_dead_player.bones_pos, 1, {"air"}) + air = minetest.find_node_near(current_dead_player.bones_pos, 1, {"air"}) end - if air and not minetest.is_protected(air, bones.private.current_dead_player.player_name) then - bones.private.current_dead_player.bones_pos = air - local param2 = minetest.dir_to_facedir(bones.private.current_dead_player.player:get_look_dir()) - minetest.set_node(bones.private.current_dead_player.bones_pos, {name = "bones:bones", param2 = param2}) - local meta = minetest.get_meta(bones.private.current_dead_player.bones_pos) - bones.private.current_dead_player.bones_inv = meta:get_inventory() - bones.private.current_dead_player.bones_inv:set_size("main", cols * rows) + if air and not minetest.is_protected(air, current_dead_player.player_name) then + current_dead_player.bones_pos = air + local param2 = minetest.dir_to_facedir(current_dead_player.player:get_look_dir()) + minetest.set_node(current_dead_player.bones_pos, {name = "bones:bones", param2 = param2}) + local meta = minetest.get_meta(current_dead_player.bones_pos) + current_dead_player.bones_inv = meta:get_inventory() + --make it so big that anything reasonable will for sure fit inside + current_dead_player.bones_inv:set_size("main", theoretical_max_slots) else - bones.private.current_dead_player.bones_mode = "drop" - bones.private.current_dead_player.bones_pos = nil + current_dead_player.bones_mode = "drop" + current_dead_player.bones_pos = nil end end - if ( ( bones.private.current_dead_player.bones_mode == "bones" ) and ( bones.private.current_dead_player.bones_inv:room_for_item("main", stk) ) ) then - bones.private.current_dead_player.bones_inv:add_item("main", stk) + if ( current_dead_player.bones_mode == "bones" ) and + ( current_dead_player.bones_inv:room_for_item("main", stk) ) then + current_dead_player.bones_inv:add_item("main", stk) else - drop(bones.private.current_dead_player.player_pos, stk) - bones.private.current_dead_player.dropped=true + drop(current_dead_player.player_pos, stk) + current_dead_player.dropped=true end end -local function player_dies_transfer_inventory(player) +local function player_dies_transfer_inventory(player,transfer_stack) local player_inv = player:get_inventory() for _, list_name in ipairs(player_inventory_lists) do for i = 1, player_inv:get_size(list_name) do local stack = player_inv:get_stack(list_name, i) - bones.public.transfer_stack_to_bones(stack) + transfer_stack(stack) end player_inv:set_list(list_name, {}) end end -bones.public.register_transfer_inventory_to_bones_on_player_death(player_dies_transfer_inventory) +bones.register_dead_player_inv_management(player_dies_transfer_inventory) minetest.register_on_dieplayer(function(player) local pos = vector.round(player:get_pos()) @@ -267,7 +263,8 @@ minetest.register_on_dieplayer(function(player) bones_mode = "bones" end local player_name = player:get_player_name() - bones.private.current_dead_player={player=player, player_name=player_name, bones_inv=nil, bones_pos=nil, bones_mode=bones_mode, player_pos=pos, dropped=false} + local current_dead_player={player=player, player_name=player_name, bones_inv=nil, bones_pos=nil, + bones_mode=bones_mode, player_pos=pos, dropped=false} local bones_position_message = minetest.settings:get_bool("bones_position_message") == true local pos_string = minetest.pos_to_string(pos) @@ -282,58 +279,73 @@ minetest.register_on_dieplayer(function(player) return end - for i=0,#bones.private.dead_player_callbacks do - local fun=bones.private.dead_player_callbacks[i] - fun(player) + local callback=function(stk) + transfer_stack_to_bones(stk,current_dead_player) end - local bones_conclusion="" - local public_conclusion="" + for i=1,#dead_player_callbacks do + local fun=dead_player_callbacks[i] + fun(player,callback) + end + + local bones_conclusion - if(not(bones.private.current_dead_player.bones_pos))then - drop(bones.private.current_dead_player.player_pos, ItemStack("bones:bones")) - if(not(bones.private.current_dead_player.dropped))then + if not ( current_dead_player.bones_pos ) then + drop(current_dead_player.player_pos, ItemStack("bones:bones")) + if not ( current_dead_player.dropped ) then bones_conclusion="No bones placed" + if bones_position_message then + minetest.chat_send_player(player_name, S("@1 died at @2.", player_name, pos_string)) + end else bones_conclusion="Inventory dropped" - public_conclusion="dropped their inventory" + if bones_position_message then + minetest.chat_send_player(player_name, S("@1 died at @2, and dropped their inventory.", player_name, pos_string, public_conclusion)) + end end else - if(not(bones.private.current_dead_player.dropped))then + if not ( current_dead_player.dropped ) then bones_conclusion="Bones placed" - public_conclusion="bones were placed" + if bones_position_message then + minetest.chat_send_player(player_name, S("@1 died at @2, and bones were placed.", player_name, pos_string, public_conclusion)) + end else bones_conclusion="Inventory partially dropped" - public_conclusion="partially dropped their inventory" + if bones_position_message then + minetest.chat_send_player(player_name, S("@1 died at @2, and partially dropped their inventory.", player_name, pos_string, public_conclusion)) + end end end minetest.log("action", player_name .. " dies at " .. pos_string .. ". " .. bones_conclusion) - if bones_position_message then - if(public_conclusion~="")then - public_conclusion=", and "..public_conclusion + local inv = current_dead_player.bones_inv + local inv_size = theoretical_max_slots + if inv then + for i = 1, theoretical_max_slots do + local stack = inv:get_stack("main", i) + if stack:get_count() == 0 then + inv_size = i - 1 + break + end end - minetest.chat_send_player(player_name, S("@1 died at @2@3.", player_name, pos_string, public_conclusion)) - end + local meta = minetest.get_meta(current_dead_player.bones_pos) + meta:set_string("formspec", get_bones_formspec_for_size(inv_size)) + meta:set_string("owner", player_name) - local meta = minetest.get_meta(bones.private.current_dead_player.bones_pos) - meta:set_string("formspec", bones_formspec) - meta:set_string("owner", player_name) + if share_bones_time ~= 0 then + meta:set_string("infotext", S("@1's fresh bones", player_name)) - if share_bones_time ~= 0 then - meta:set_string("infotext", S("@1's fresh bones", player_name)) + if share_bones_time_early == 0 or not minetest.is_protected(pos, player_name) then + meta:set_int("time", 0) + else + meta:set_int("time", (share_bones_time - share_bones_time_early)) + end - if share_bones_time_early == 0 or not minetest.is_protected(pos, player_name) then - meta:set_int("time", 0) + minetest.get_node_timer(pos):start(10) else - meta:set_int("time", (share_bones_time - share_bones_time_early)) + meta:set_string("infotext", S("@1's bones", player_name)) end - - minetest.get_node_timer(pos):start(10) - else - meta:set_string("infotext", S("@1's bones", player_name)) end - bones.private.current_dead_player=nil end) From eeec7d6be0c58092957eee4460a5f0a940b6e9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 6 May 2023 10:24:22 +0200 Subject: [PATCH 03/30] fixes as per code review completed (2) --- game_api.txt | 6 +- mods/bones/init.lua | 174 +++++++++++++++++++++----------------------- 2 files changed, 86 insertions(+), 94 deletions(-) diff --git a/game_api.txt b/game_api.txt index 953f0e7292..5b624131e1 100644 --- a/game_api.txt +++ b/game_api.txt @@ -85,11 +85,9 @@ e.g. `table.insert(bones.player_inventory_lists, "backpack")` Additionally, callbacks can be registered to transfer items into the bones on death: -`bones.register_dead_player_inv_management(function(player,callback){})` +`bones.register_dead_player_inv_management(function(player){})` -In the above functions the provided callback should be used to add items to the bones inventory: - -`callback(stack)` +the registered function is supposed to return with a table of items to be transferred. please note that the inventory these items were taken from still need to be disposed of. diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 060efebfc3..15efb958e7 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -6,7 +6,7 @@ -- Load support for MT game translation. local S = minetest.get_translator("bones") -local theoretical_max_slots = minetest.settings:get("bones_max_slots") or ( 15 * 10 ) +local theoretical_max_slots = minetest.settings:get("bones_max_slots") or 15 * 10 local dead_player_callbacks={} bones = {} @@ -21,10 +21,10 @@ end local function get_bones_formspec_wh(cols,rows) return - "size[" .. cols .. "," .. ( rows + 5 ) .. "]" .. + "size[" .. cols .. "," .. (rows + 5) .. "]" .. "list[current_name;main;0,0.3;" .. cols .. "," .. rows .. ";]" .. - "list[current_player;main;" .. ( ( cols - 8 ) / 2 ) .. "," .. rows .. ".85;8,1;]" .. - "list[current_player;main;".. ( ( cols - 8 ) / 2 ) .. "," .. ( rows + 2 ) .. ".08;8,3;8]" .. + "list[current_player;main;" .. ((cols - 8) / 2) .. "," .. rows .. ".85;8,1;]" .. + "list[current_player;main;".. ((cols - 8) / 2) .. "," .. (rows + 2) .. ".08;8,3;8]" .. "listring[current_name;main]" .. "listring[current_player;main]" .. default.get_hotbar_bg(0,4.85) @@ -37,10 +37,10 @@ local function get_bones_formspec_for_size(numitems) end --if we're over 4*8, but below 4*15 we make it 4 rows and adjust the column count to make everything fit if numitems <= 4 * 15 then - return get_bones_formspec_wh( math.floor ( ( numitems + 3 ) / 4 ), 4) + return get_bones_formspec_wh(math.floor((numitems + 3) / 4), 4) end --if we're over 4*15 we'll make 15 columns and adjust the row count to make everything fit - return get_bones_formspec_wh(15, math.floor ( ( numitems + 14 ) / 15 ) ) + return get_bones_formspec_wh(15, math.floor ((numitems + 14) / 15)) end local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200 @@ -203,71 +203,39 @@ end local player_inventory_lists = { "main", "craft" } bones.player_inventory_lists = player_inventory_lists ---functions registered this way won't becalled if bones_mode is keep +--functions registered this way won't be called if bones_mode is keep function bones.register_dead_player_inv_management(func) table.insert(dead_player_callbacks, func) end -local function transfer_stack_to_bones(stk,current_dead_player) - -- check if it's possible to place bones, if not find space near player - if ( current_dead_player.bones_mode == "bones" ) and - ( current_dead_player.bones_pos == nil ) then - current_dead_player.bones_pos = current_dead_player.player_pos - local air - if may_replace(current_dead_player.bones_pos, current_dead_player.player) then - air = current_dead_player.bones_pos - else - air = minetest.find_node_near(current_dead_player.bones_pos, 1, {"air"}) - end - - if air and not minetest.is_protected(air, current_dead_player.player_name) then - current_dead_player.bones_pos = air - local param2 = minetest.dir_to_facedir(current_dead_player.player:get_look_dir()) - minetest.set_node(current_dead_player.bones_pos, {name = "bones:bones", param2 = param2}) - local meta = minetest.get_meta(current_dead_player.bones_pos) - current_dead_player.bones_inv = meta:get_inventory() - --make it so big that anything reasonable will for sure fit inside - current_dead_player.bones_inv:set_size("main", theoretical_max_slots) - else - current_dead_player.bones_mode = "drop" - current_dead_player.bones_pos = nil - end - end - - if ( current_dead_player.bones_mode == "bones" ) and - ( current_dead_player.bones_inv:room_for_item("main", stk) ) then - current_dead_player.bones_inv:add_item("main", stk) - else - drop(current_dead_player.player_pos, stk) - current_dead_player.dropped=true - end -end - -local function player_dies_transfer_inventory(player,transfer_stack) +local function player_dies_transfer_inventory(player) + local result = {} local player_inv = player:get_inventory() for _, list_name in ipairs(player_inventory_lists) do for i = 1, player_inv:get_size(list_name) do - local stack = player_inv:get_stack(list_name, i) - transfer_stack(stack) + table.insert(result, player_inv:get_stack(list_name, i)) end player_inv:set_list(list_name, {}) end + return result end bones.register_dead_player_inv_management(player_dies_transfer_inventory) minetest.register_on_dieplayer(function(player) - local pos = vector.round(player:get_pos()) + local player_pos = vector.round(player:get_pos()) local bones_mode = minetest.settings:get("bones_mode") or "bones" if bones_mode ~= "bones" and bones_mode ~= "drop" and bones_mode ~= "keep" then bones_mode = "bones" end local player_name = player:get_player_name() - local current_dead_player={player=player, player_name=player_name, bones_inv=nil, bones_pos=nil, - bones_mode=bones_mode, player_pos=pos, dropped=false} + local bones_inv = nil + local bones_pos = nil + local dropped = false + local bones_meta = nil local bones_position_message = minetest.settings:get_bool("bones_position_message") == true - local pos_string = minetest.pos_to_string(pos) + local pos_string = minetest.pos_to_string(player_pos) -- return if keep inventory set or in creative mode if bones_mode == "keep" or minetest.is_creative_enabled(player_name) then @@ -279,73 +247,99 @@ minetest.register_on_dieplayer(function(player) return end - local callback=function(stk) - transfer_stack_to_bones(stk,current_dead_player) - end + for _, fun in ipairs(dead_player_callbacks) do + local items = fun(player) + for _, item in ipairs(items) do + -- check if it's possible to place bones, if not find space near player + if bones_mode == "bones" and bones_pos == nil then + bones_pos = player_pos + local air + if may_replace(bones_pos, player) then + air = bones_pos + else + air = minetest.find_node_near(bones_pos, 1, {"air"}) + end + + if air and not minetest.is_protected(air, player_name) then + bones_pos = air + local param2 = minetest.dir_to_facedir(player:get_look_dir()) + minetest.set_node(bones_pos, {name = "bones:bones", param2 = param2}) + bones_meta = minetest.get_meta(bones_pos) + bones_inv = bones_meta:get_inventory() + --make it so big that anything reasonable will for sure fit inside + bones_inv:set_size("main", theoretical_max_slots) + else + bones_mode = "drop" + bones_pos = nil + end + end - for i=1,#dead_player_callbacks do - local fun=dead_player_callbacks[i] - fun(player,callback) + if bones_mode == "bones" and bones_inv:room_for_item("main", item) then + bones_inv:add_item("main", item) + else + drop(player_pos, item) + dropped=true + end + end end local bones_conclusion + local public_conclusion - if not ( current_dead_player.bones_pos ) then - drop(current_dead_player.player_pos, ItemStack("bones:bones")) - if not ( current_dead_player.dropped ) then - bones_conclusion="No bones placed" - if bones_position_message then - minetest.chat_send_player(player_name, S("@1 died at @2.", player_name, pos_string)) - end + if not bones_pos then + drop(player_pos, ItemStack("bones:bones")) + if not dropped then + bones_conclusion = "No bones placed" + public_conclusion = S("@1 died at @2.", player_name, pos_string) else - bones_conclusion="Inventory dropped" - if bones_position_message then - minetest.chat_send_player(player_name, S("@1 died at @2, and dropped their inventory.", player_name, pos_string, public_conclusion)) - end + bones_conclusion = "Inventory dropped" + public_conclusion = S("@1 died at @2, and dropped their inventory.", player_name, pos_string) end else - if not ( current_dead_player.dropped ) then - bones_conclusion="Bones placed" - if bones_position_message then - minetest.chat_send_player(player_name, S("@1 died at @2, and bones were placed.", player_name, pos_string, public_conclusion)) - end + if not dropped then + bones_conclusion = "Bones placed" + public_conclusion = S("@1 died at @2, and bones were placed.", player_name, pos_string) else - bones_conclusion="Inventory partially dropped" - if bones_position_message then - minetest.chat_send_player(player_name, S("@1 died at @2, and partially dropped their inventory.", player_name, pos_string, public_conclusion)) - end + bones_conclusion = "Inventory partially dropped" + public_conclusion = S("@1 died at @2, and partially dropped their inventory.", player_name, pos_string) end end - minetest.log("action", player_name .. " dies at " .. pos_string .. - ". " .. bones_conclusion) + if bones_position_message then + minetest.chat_send_player(player_name, public_conclusion) + end + + minetest.log("action", player_name .. " dies at " .. pos_string .. ". " .. bones_conclusion) - local inv = current_dead_player.bones_inv - local inv_size = theoretical_max_slots - if inv then + if bones_inv then + local inv_size = theoretical_max_slots for i = 1, theoretical_max_slots do - local stack = inv:get_stack("main", i) + local stack = bones_inv:get_stack("main", i) if stack:get_count() == 0 then inv_size = i - 1 break end end - local meta = minetest.get_meta(current_dead_player.bones_pos) - meta:set_string("formspec", get_bones_formspec_for_size(inv_size)) - meta:set_string("owner", player_name) + if inv_size <= 4 * 8 then + bones_inv:set_size("main", 4 * 8) + else + bones_inv:set_size("main", inv_size) + end + bones_meta:set_string("formspec", get_bones_formspec_for_size(inv_size)) + bones_meta:set_string("owner", player_name) if share_bones_time ~= 0 then - meta:set_string("infotext", S("@1's fresh bones", player_name)) + bones_meta:set_string("infotext", S("@1's fresh bones", player_name)) - if share_bones_time_early == 0 or not minetest.is_protected(pos, player_name) then - meta:set_int("time", 0) + if share_bones_time_early == 0 or not minetest.is_protected(bones_pos, player_name) then + bones_meta:set_int("time", 0) else - meta:set_int("time", (share_bones_time - share_bones_time_early)) + bones_meta:set_int("time", (share_bones_time - share_bones_time_early)) end - minetest.get_node_timer(pos):start(10) + minetest.get_node_timer(bones_pos):start(10) else - meta:set_string("infotext", S("@1's bones", player_name)) + bones_meta:set_string("infotext", S("@1's bones", player_name)) end end end) From 5141c96c01938cc0a9fa2dba4ca3230f37e7bd22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Fri, 12 May 2023 09:37:26 +0200 Subject: [PATCH 04/30] fixes as per code review completed (3) --- mods/bones/init.lua | 53 ++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 15efb958e7..4b43ecedc8 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -6,8 +6,10 @@ -- Load support for MT game translation. local S = minetest.get_translator("bones") -local theoretical_max_slots = minetest.settings:get("bones_max_slots") or 15 * 10 +local bones_max_slots = minetest.settings:get("bones_max_slots") or 15 * 10 local dead_player_callbacks={} +-- we're going to display no less than 4*8 slots, we'll also provide at least 4*8 slots in bones +local min_inv_size = 4 * 8 bones = {} @@ -32,15 +34,15 @@ end local function get_bones_formspec_for_size(numitems) --the absolute minimum is 4*8 - if numitems <= 4 * 8 then + if numitems <= min_inv_size then return get_bones_formspec_wh(8, 4) end --if we're over 4*8, but below 4*15 we make it 4 rows and adjust the column count to make everything fit if numitems <= 4 * 15 then - return get_bones_formspec_wh(math.floor((numitems + 3) / 4), 4) + return get_bones_formspec_wh(math.ceil(numitems / 4), 4) end --if we're over 4*15 we'll make 15 columns and adjust the row count to make everything fit - return get_bones_formspec_wh(15, math.floor ((numitems + 14) / 15)) + return get_bones_formspec_wh(15, math.ceil(numitems / 15)) end local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200 @@ -267,7 +269,7 @@ minetest.register_on_dieplayer(function(player) bones_meta = minetest.get_meta(bones_pos) bones_inv = bones_meta:get_inventory() --make it so big that anything reasonable will for sure fit inside - bones_inv:set_size("main", theoretical_max_slots) + bones_inv:set_size("main", bones_max_slots) else bones_mode = "drop" bones_pos = nil @@ -283,45 +285,46 @@ minetest.register_on_dieplayer(function(player) end end - local bones_conclusion - local public_conclusion + local log_message + local chat_message - if not bones_pos then - drop(player_pos, ItemStack("bones:bones")) - if not dropped then - bones_conclusion = "No bones placed" - public_conclusion = S("@1 died at @2.", player_name, pos_string) + if bones_pos then + if dropped then + log_message = "Inventory partially dropped" + chat_message = "@1 died at @2, and partially dropped their inventory." else - bones_conclusion = "Inventory dropped" - public_conclusion = S("@1 died at @2, and dropped their inventory.", player_name, pos_string) + log_message = "Bones placed" + chat_message = "@1 died at @2, and bones were placed." end else - if not dropped then - bones_conclusion = "Bones placed" - public_conclusion = S("@1 died at @2, and bones were placed.", player_name, pos_string) + drop(player_pos, ItemStack("bones:bones")) + if dropped then + log_message = "Inventory dropped" + chat_message = "@1 died at @2, and dropped their inventory." else - bones_conclusion = "Inventory partially dropped" - public_conclusion = S("@1 died at @2, and partially dropped their inventory.", player_name, pos_string) + log_message = "No bones placed" + chat_message = "@1 died at @2." end end if bones_position_message then - minetest.chat_send_player(player_name, public_conclusion) + chat_message = S(chat_message, player_name, pos_string) + minetest.chat_send_player(player_name, chat_message) end - minetest.log("action", player_name .. " dies at " .. pos_string .. ". " .. bones_conclusion) + minetest.log("action", player_name .. " dies at " .. pos_string .. ". " .. log_message) if bones_inv then - local inv_size = theoretical_max_slots - for i = 1, theoretical_max_slots do + local inv_size = bones_max_slots + for i = 1, bones_max_slots do local stack = bones_inv:get_stack("main", i) if stack:get_count() == 0 then inv_size = i - 1 break end end - if inv_size <= 4 * 8 then - bones_inv:set_size("main", 4 * 8) + if inv_size <= min_inv_size then + bones_inv:set_size("main", min_inv_size) else bones_inv:set_size("main", inv_size) end From 4b2228066fa9b17052f5fd9c3d6fc9937111b1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Mon, 29 May 2023 19:01:11 +0200 Subject: [PATCH 05/30] fixes as per code review completed (4) --- mods/bones/init.lua | 94 ++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 4b43ecedc8..db98da1892 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -224,6 +224,58 @@ end bones.register_dead_player_inv_management(player_dies_transfer_inventory) +local function collect_all_items(player) + local all_inventory = {} + for _, fun in ipairs(dead_player_callbacks) do + local items = fun(player) + -- https://www.programming-idioms.org/idiom/166/concatenate-two-lists/3812/lua + table.move(items, 1, #items, #all_inventory + 1, all_inventory) + end + return all_inventory +end + +-- check if it's possible to place bones, if not find space near player +local function find_node_for_bones_on_player_death(player, player_pos) + local bones_pos = nil + local bones_inv = nil + local bones_meta = nil + local bones_mode = "bones" + bones_pos = player_pos + local air + if may_replace(bones_pos, player) then + air = bones_pos + else + air = minetest.find_node_near(bones_pos, 1, {"air"}) + end + + if air and not minetest.is_protected(air, player_name) then + bones_pos = air + local param2 = minetest.dir_to_facedir(player:get_look_dir()) + minetest.set_node(bones_pos, {name = "bones:bones", param2 = param2}) + bones_meta = minetest.get_meta(bones_pos) + bones_inv = bones_meta:get_inventory() + --make it so big that anything reasonable will for sure fit inside + bones_inv:set_size("main", bones_max_slots) + else + bones_mode = "drop" + bones_pos = nil + end + return bones_mode, bones_pos, bones_inv, bones_meta +end + +local function dump_into(bones_mode, bones_inv, bones_pos, all_inventory) + local dropped = false + for _, item in ipairs(all_inventory) do + if bones_mode == "bones" and bones_inv:room_for_item("main", item) then + bones_inv:add_item("main", item) + else + drop(player_pos, item) + dropped = true + end + end + return dropped +end + minetest.register_on_dieplayer(function(player) local player_pos = vector.round(player:get_pos()) local bones_mode = minetest.settings:get("bones_mode") or "bones" @@ -233,7 +285,6 @@ minetest.register_on_dieplayer(function(player) local player_name = player:get_player_name() local bones_inv = nil local bones_pos = nil - local dropped = false local bones_meta = nil local bones_position_message = minetest.settings:get_bool("bones_position_message") == true @@ -249,41 +300,14 @@ minetest.register_on_dieplayer(function(player) return end - for _, fun in ipairs(dead_player_callbacks) do - local items = fun(player) - for _, item in ipairs(items) do - -- check if it's possible to place bones, if not find space near player - if bones_mode == "bones" and bones_pos == nil then - bones_pos = player_pos - local air - if may_replace(bones_pos, player) then - air = bones_pos - else - air = minetest.find_node_near(bones_pos, 1, {"air"}) - end - - if air and not minetest.is_protected(air, player_name) then - bones_pos = air - local param2 = minetest.dir_to_facedir(player:get_look_dir()) - minetest.set_node(bones_pos, {name = "bones:bones", param2 = param2}) - bones_meta = minetest.get_meta(bones_pos) - bones_inv = bones_meta:get_inventory() - --make it so big that anything reasonable will for sure fit inside - bones_inv:set_size("main", bones_max_slots) - else - bones_mode = "drop" - bones_pos = nil - end - end - - if bones_mode == "bones" and bones_inv:room_for_item("main", item) then - bones_inv:add_item("main", item) - else - drop(player_pos, item) - dropped=true - end - end + local all_inventory = collect_all_items(player) + if bones_mode == "bones" and #all_inventory > 0 then + bones_mode, bones_pos, bones_inv, bones_meta = find_node_for_bones_on_player_death(player, player_pos) + end + if bones_mode == "drop" and #all_inventory > 0 then + all_inventory.insert(all_inventory,ItemStack("bones:bones")) end + local dropped = dump_into(bones_mode, bones_inv, bones_pos, all_inventory) local log_message local chat_message From 224ae80626f6122186160a5b7ad177782b8bbe6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BCller?= <34514239+appgurueu@users.noreply.github.com> Date: Mon, 29 May 2023 20:16:01 +0200 Subject: [PATCH 06/30] Use Minetest's `table.insert_all` --- mods/bones/init.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index db98da1892..a076a905bc 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -225,13 +225,12 @@ end bones.register_dead_player_inv_management(player_dies_transfer_inventory) local function collect_all_items(player) - local all_inventory = {} + local all_items = {} for _, fun in ipairs(dead_player_callbacks) do local items = fun(player) - -- https://www.programming-idioms.org/idiom/166/concatenate-two-lists/3812/lua - table.move(items, 1, #items, #all_inventory + 1, all_inventory) + table.insert_all(all_items, items) end - return all_inventory + return all_items end -- check if it's possible to place bones, if not find space near player From bd60bfb5495fb511a7ce26cac9a4320eccd6709d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20M=C3=BCller?= <34514239+appgurueu@users.noreply.github.com> Date: Mon, 29 May 2023 21:47:56 +0200 Subject: [PATCH 07/30] Fix `table.insert` usage --- mods/bones/init.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index a076a905bc..97237f17fc 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -299,14 +299,14 @@ minetest.register_on_dieplayer(function(player) return end - local all_inventory = collect_all_items(player) - if bones_mode == "bones" and #all_inventory > 0 then + local all_items = collect_all_items(player) + if bones_mode == "bones" and #all_items > 0 then bones_mode, bones_pos, bones_inv, bones_meta = find_node_for_bones_on_player_death(player, player_pos) end - if bones_mode == "drop" and #all_inventory > 0 then - all_inventory.insert(all_inventory,ItemStack("bones:bones")) + if bones_mode == "drop" and #all_items > 0 then + table.insert(all_items, ItemStack("bones:bones")) end - local dropped = dump_into(bones_mode, bones_inv, bones_pos, all_inventory) + local dropped = dump_into(bones_mode, bones_inv, bones_pos, all_items) local log_message local chat_message From 738e0d7292d1e8218753078065df5594f13ce1ff Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Tue, 30 May 2023 10:26:17 +0200 Subject: [PATCH 08/30] Refactor --- game_api.txt | 11 ++- mods/bones/init.lua | 223 ++++++++++++++++++++------------------------ 2 files changed, 108 insertions(+), 126 deletions(-) diff --git a/game_api.txt b/game_api.txt index 5b624131e1..c1ecd05de9 100644 --- a/game_api.txt +++ b/game_api.txt @@ -83,13 +83,16 @@ in `bones.player_inventory_lists`. e.g. `table.insert(bones.player_inventory_lists, "backpack")` -Additionally, callbacks can be registered to transfer items into the bones on death: +Additionally, callbacks can be registered to transfer items to the bones on death: -`bones.register_dead_player_inv_management(function(player){})` +`bones.register_collect_items(callback)` -the registered function is supposed to return with a table of items to be transferred. +Functions registered this way won't be called if `bones_mode` is `keep`. -please note that the inventory these items were taken from still need to be disposed of. +`callback` is a `function(player)` which `return`s a table of items to be transferred. + +Please note that this does not remove the items from the inventory they were taken of. +Disposing of the items in this inventory is the `callback`'s responsibility. Creative API diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 97237f17fc..661eb7958b 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -7,9 +7,7 @@ local S = minetest.get_translator("bones") local bones_max_slots = minetest.settings:get("bones_max_slots") or 15 * 10 -local dead_player_callbacks={} --- we're going to display no less than 4*8 slots, we'll also provide at least 4*8 slots in bones -local min_inv_size = 4 * 8 +local min_inv_size = 4 * 8 -- display and provide at least this many slots bones = {} @@ -21,28 +19,24 @@ local function is_owner(pos, name) return false end -local function get_bones_formspec_wh(cols,rows) - return - "size[" .. cols .. "," .. (rows + 5) .. "]" .. - "list[current_name;main;0,0.3;" .. cols .. "," .. rows .. ";]" .. - "list[current_player;main;" .. ((cols - 8) / 2) .. "," .. rows .. ".85;8,1;]" .. - "list[current_player;main;".. ((cols - 8) / 2) .. "," .. (rows + 2) .. ".08;8,3;8]" .. - "listring[current_name;main]" .. - "listring[current_player;main]" .. - default.get_hotbar_bg(0,4.85) -end - local function get_bones_formspec_for_size(numitems) - --the absolute minimum is 4*8 + local cols, rows if numitems <= min_inv_size then - return get_bones_formspec_wh(8, 4) - end - --if we're over 4*8, but below 4*15 we make it 4 rows and adjust the column count to make everything fit - if numitems <= 4 * 15 then - return get_bones_formspec_wh(math.ceil(numitems / 4), 4) + cols, rows = 8, 4 + elseif numitems <= 4 * 15 then + cols, rows = math.ceil(numitems / 4), 4 + else + cols, rows = 15, math.ceil(numitems / 15) end - --if we're over 4*15 we'll make 15 columns and adjust the row count to make everything fit - return get_bones_formspec_wh(15, math.ceil(numitems / 15)) + return table.concat{ + "size[", cols, ",", rows + 5, "]", + "list[current_name;main;0,0.3;", cols, ",", rows, ";]", + "list[current_player;main;", (cols - 8) / 2, ",", rows + 0.85, ";8,1;]", + "list[current_player;main;", (cols - 8) / 2, ",", rows + 2.08, ";8,3;8]", + "listring[current_name;main]", + "listring[current_player;main]", + default.get_hotbar_bg(0, 4.85) + } end local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200 @@ -202,95 +196,101 @@ local drop = function(pos, itemstack) end end -local player_inventory_lists = { "main", "craft" } -bones.player_inventory_lists = player_inventory_lists +bones.player_inventory_lists = { "main", "craft" } + +local collect_items_callbacks = {} ---functions registered this way won't be called if bones_mode is keep -function bones.register_dead_player_inv_management(func) - table.insert(dead_player_callbacks, func) +function bones.register_collect_items(func) + table.insert(collect_items_callbacks, func) end -local function player_dies_transfer_inventory(player) - local result = {} +bones.register_collect_items(function(player) + local items = {} local player_inv = player:get_inventory() - for _, list_name in ipairs(player_inventory_lists) do - for i = 1, player_inv:get_size(list_name) do - table.insert(result, player_inv:get_stack(list_name, i)) - end + for _, list_name in ipairs(bones.player_inventory_lists) do + table.insert_all(items, player_inv:get_list(list_name) or {}) player_inv:set_list(list_name, {}) end - return result -end - -bones.register_dead_player_inv_management(player_dies_transfer_inventory) + return items +end) -local function collect_all_items(player) - local all_items = {} - for _, fun in ipairs(dead_player_callbacks) do - local items = fun(player) - table.insert_all(all_items, items) +local function collect_items(player) + local items = {} + for _, cb in ipairs(collect_items_callbacks) do + table.insert_all(items, cb(player)) end - return all_items + return items end --- check if it's possible to place bones, if not find space near player -local function find_node_for_bones_on_player_death(player, player_pos) - local bones_pos = nil - local bones_inv = nil - local bones_meta = nil - local bones_mode = "bones" - bones_pos = player_pos - local air - if may_replace(bones_pos, player) then - air = bones_pos +-- Try to find the closest space near the player to place bones +local function find_bones_pos(player) + local rounded_player_pos = vector.round(player:get_pos()) + local bones_pos + if may_replace(rounded_player_pos, player) then + bones_pos = rounded_player_pos else - air = minetest.find_node_near(bones_pos, 1, {"air"}) + bones_pos = minetest.find_node_near(rounded_player_pos, 1, {"air"}) end - - if air and not minetest.is_protected(air, player_name) then - bones_pos = air - local param2 = minetest.dir_to_facedir(player:get_look_dir()) - minetest.set_node(bones_pos, {name = "bones:bones", param2 = param2}) - bones_meta = minetest.get_meta(bones_pos) - bones_inv = bones_meta:get_inventory() - --make it so big that anything reasonable will for sure fit inside - bones_inv:set_size("main", bones_max_slots) - else - bones_mode = "drop" + if minetest.is_protected(bones_pos, player:get_player_name()) then bones_pos = nil end - return bones_mode, bones_pos, bones_inv, bones_meta + return bones_pos end -local function dump_into(bones_mode, bones_inv, bones_pos, all_inventory) - local dropped = false - for _, item in ipairs(all_inventory) do - if bones_mode == "bones" and bones_inv:room_for_item("main", item) then +local function place_bones(player, bones_pos, items) + local param2 = minetest.dir_to_facedir(player:get_look_dir()) + minetest.set_node(bones_pos, {name = "bones:bones", param2 = param2}) + local bones_meta = minetest.get_meta(bones_pos) + local bones_inv = bones_meta:get_inventory() + -- Make it big enough that anything reasonable will fit + bones_inv:set_size("main", bones_max_slots) + local leftover_items = {} + for _, item in ipairs(items) do + if bones_inv:room_for_item("main", item) then bones_inv:add_item("main", item) else - drop(player_pos, item) - dropped = true + table.insert(leftover_items, item) + end + end + local inv_size = bones_max_slots + for i = 1, bones_max_slots do + if bones_inv:get_stack("main", i):get_count() == 0 then + inv_size = i - 1 + break end end - return dropped + bones_inv:set_size("main", math.max(inv_size, min_inv_size)) + bones_meta:set_string("formspec", get_bones_formspec_for_size(inv_size)) + -- "Ownership" + local player_name = player:get_player_name() + bones_meta:set_string("owner", player_name) + if share_bones_time ~= 0 then + bones_meta:set_string("infotext", S("@1's fresh bones", player_name)) + if share_bones_time_early == 0 or not minetest.is_protected(bones_pos, player_name) then + bones_meta:set_int("time", 0) + else + bones_meta:set_int("time", share_bones_time - share_bones_time_early) + end + minetest.get_node_timer(bones_pos):start(10) + else + bones_meta:set_string("infotext", S("@1's bones", player_name)) + end + return leftover_items end minetest.register_on_dieplayer(function(player) - local player_pos = vector.round(player:get_pos()) local bones_mode = minetest.settings:get("bones_mode") or "bones" if bones_mode ~= "bones" and bones_mode ~= "drop" and bones_mode ~= "keep" then bones_mode = "bones" end local player_name = player:get_player_name() - local bones_inv = nil - local bones_pos = nil - local bones_meta = nil local bones_position_message = minetest.settings:get_bool("bones_position_message") == true - local pos_string = minetest.pos_to_string(player_pos) + local pos_string = minetest.pos_to_string(player:get_pos()) + + local items = collect_items(player) - -- return if keep inventory set or in creative mode - if bones_mode == "keep" or minetest.is_creative_enabled(player_name) then + if bones_mode == "keep" or minetest.is_creative_enabled(player_name) or #items == 0 then minetest.log("action", player_name .. " dies at " .. pos_string .. ". No bones placed") if bones_position_message then @@ -299,20 +299,32 @@ minetest.register_on_dieplayer(function(player) return end - local all_items = collect_all_items(player) - if bones_mode == "bones" and #all_items > 0 then - bones_mode, bones_pos, bones_inv, bones_meta = find_node_for_bones_on_player_death(player, player_pos) + local bones_placed, drop_bones = false, false + if bones_mode == "bones" then + local bones_pos = find_bones_pos(player) + if bones_pos then + items = place_bones(player, bones_pos, items) + bones_placed, drop_bones = true, #items ~= 0 + else + drop_bones = true + end + elseif bones_mode == "drop" then + drop_bones = true end - if bones_mode == "drop" and #all_items > 0 then - table.insert(all_items, ItemStack("bones:bones")) + if drop_bones then + if not bones_placed then + table.insert(items, ItemStack("bones:bones")) + end + for _, item in ipairs(items) do + drop(player:get_pos(), item) + end end - local dropped = dump_into(bones_mode, bones_inv, bones_pos, all_items) local log_message local chat_message - if bones_pos then - if dropped then + if bones_placed then + if drop_bones then log_message = "Inventory partially dropped" chat_message = "@1 died at @2, and partially dropped their inventory." else @@ -320,8 +332,7 @@ minetest.register_on_dieplayer(function(player) chat_message = "@1 died at @2, and bones were placed." end else - drop(player_pos, ItemStack("bones:bones")) - if dropped then + if drop_bones then log_message = "Inventory dropped" chat_message = "@1 died at @2, and dropped their inventory." else @@ -336,36 +347,4 @@ minetest.register_on_dieplayer(function(player) end minetest.log("action", player_name .. " dies at " .. pos_string .. ". " .. log_message) - - if bones_inv then - local inv_size = bones_max_slots - for i = 1, bones_max_slots do - local stack = bones_inv:get_stack("main", i) - if stack:get_count() == 0 then - inv_size = i - 1 - break - end - end - if inv_size <= min_inv_size then - bones_inv:set_size("main", min_inv_size) - else - bones_inv:set_size("main", inv_size) - end - bones_meta:set_string("formspec", get_bones_formspec_for_size(inv_size)) - bones_meta:set_string("owner", player_name) - - if share_bones_time ~= 0 then - bones_meta:set_string("infotext", S("@1's fresh bones", player_name)) - - if share_bones_time_early == 0 or not minetest.is_protected(bones_pos, player_name) then - bones_meta:set_int("time", 0) - else - bones_meta:set_int("time", (share_bones_time - share_bones_time_early)) - end - - minetest.get_node_timer(bones_pos):start(10) - else - bones_meta:set_string("infotext", S("@1's bones", player_name)) - end - end end) From 9e52fc11a6fc78fdef516ba8c20f96b9945b4889 Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Tue, 30 May 2023 10:33:07 +0200 Subject: [PATCH 09/30] Make Luacheck happy --- .luacheckrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.luacheckrc b/.luacheckrc index cc54a3ce74..094a2d93c2 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -16,7 +16,7 @@ read_globals = { "Settings", "unpack", -- Silence errors about custom table methods. - table = { fields = { "copy", "indexof" } }, + table = { fields = { "copy", "indexof", "insert_all" } }, -- Silence warnings about accessing undefined fields of global 'math' math = { fields = { "sign" } } } From b62713f0dbb61abe6399d88ff2e351367110eb01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 24 Feb 2024 14:51:17 +0100 Subject: [PATCH 10/30] PR #3030 fix --- mods/bones/init.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 661eb7958b..7dc46bf4ab 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -231,9 +231,6 @@ local function find_bones_pos(player) else bones_pos = minetest.find_node_near(rounded_player_pos, 1, {"air"}) end - if minetest.is_protected(bones_pos, player:get_player_name()) then - bones_pos = nil - end return bones_pos end From 5b35ea553eb12d32005dc5ac8d3a4746bead0183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 24 Feb 2024 15:05:59 +0100 Subject: [PATCH 11/30] as per https://github.com/minetest/minetest_game/pull/3030#pullrequestreview-1899419816 --- mods/bones/init.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 7dc46bf4ab..623e6174af 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -11,6 +11,10 @@ local min_inv_size = 4 * 8 -- display and provide at least this many slots bones = {} +local function TRANSLATEMEPLEASE(s) + return s +end + local function is_owner(pos, name) local owner = minetest.get_meta(pos):get_string("owner") if owner == "" or owner == name or minetest.check_player_privs(name, "protection_bypass") then @@ -323,18 +327,18 @@ minetest.register_on_dieplayer(function(player) if bones_placed then if drop_bones then log_message = "Inventory partially dropped" - chat_message = "@1 died at @2, and partially dropped their inventory." + chat_message = TRANSLATEMEPLEASE("@1 died at @2, and partially dropped their inventory.") else log_message = "Bones placed" - chat_message = "@1 died at @2, and bones were placed." + chat_message = TRANSLATEMEPLEASE("@1 died at @2, and bones were placed.") end else if drop_bones then log_message = "Inventory dropped" - chat_message = "@1 died at @2, and dropped their inventory." + chat_message = TRANSLATEMEPLEASE("@1 died at @2, and dropped their inventory.") else log_message = "No bones placed" - chat_message = "@1 died at @2." + chat_message = TRANSLATEMEPLEASE("@1 died at @2.") end end From da3c36ded88c4b50c8ec1653d777588d72d3cd91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Tue, 27 Feb 2024 12:50:26 +0100 Subject: [PATCH 12/30] NS routine as per code review --- mods/bones/init.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 623e6174af..512c03266c 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -11,7 +11,7 @@ local min_inv_size = 4 * 8 -- display and provide at least this many slots bones = {} -local function TRANSLATEMEPLEASE(s) +local function NS(s) return s end @@ -327,18 +327,18 @@ minetest.register_on_dieplayer(function(player) if bones_placed then if drop_bones then log_message = "Inventory partially dropped" - chat_message = TRANSLATEMEPLEASE("@1 died at @2, and partially dropped their inventory.") + chat_message = NS("@1 died at @2, and partially dropped their inventory.") else log_message = "Bones placed" - chat_message = TRANSLATEMEPLEASE("@1 died at @2, and bones were placed.") + chat_message = NS("@1 died at @2, and bones were placed.") end else if drop_bones then log_message = "Inventory dropped" - chat_message = TRANSLATEMEPLEASE("@1 died at @2, and dropped their inventory.") + chat_message = NS("@1 died at @2, and dropped their inventory.") else log_message = "No bones placed" - chat_message = TRANSLATEMEPLEASE("@1 died at @2.") + chat_message = NS("@1 died at @2.") end end From 25ff3852940f4947f42bd6d587258253af37977f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 23 Mar 2024 15:10:48 +0100 Subject: [PATCH 13/30] fix for https://github.com/minetest/minetest_game/pull/3030#pullrequestreview-1912657094 --- mods/bones/init.lua | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 512c03266c..7a2d8305e4 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -212,13 +212,23 @@ bones.register_collect_items(function(player) local items = {} local player_inv = player:get_inventory() for _, list_name in ipairs(bones.player_inventory_lists) do - table.insert_all(items, player_inv:get_list(list_name) or {}) + local inv_list=player_inv:get_list(list_name) or {} + for _, inv_slot in ipairs(inv_list) do + if inv_slot:get_count() > 0 then + table.insert(items, inv_slot) + end + end + player_inv:set_list(list_name, {}) end return items end) -local function collect_items(player) +local function collect_items(player, player_name) + if minetest.is_creative_enabled(player_name) then + return {} + end + local items = {} for _, cb in ipairs(collect_items_callbacks) do table.insert_all(items, cb(player)) @@ -289,9 +299,9 @@ minetest.register_on_dieplayer(function(player) local bones_position_message = minetest.settings:get_bool("bones_position_message") == true local pos_string = minetest.pos_to_string(player:get_pos()) - local items = collect_items(player) + local items = collect_items(player, player_name) - if bones_mode == "keep" or minetest.is_creative_enabled(player_name) or #items == 0 then + if bones_mode == "keep" or #items == 0 then minetest.log("action", player_name .. " dies at " .. pos_string .. ". No bones placed") if bones_position_message then From 062fc4610b1537de1aceab4613e41f72a7d37bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 23 Mar 2024 16:43:06 +0100 Subject: [PATCH 14/30] doc clarification --- game_api.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game_api.txt b/game_api.txt index c1ecd05de9..70654c2bb9 100644 --- a/game_api.txt +++ b/game_api.txt @@ -87,7 +87,7 @@ Additionally, callbacks can be registered to transfer items to the bones on deat `bones.register_collect_items(callback)` -Functions registered this way won't be called if `bones_mode` is `keep`. +Functions registered this way won't be called if `bones_mode` is `keep` or in case of the death of a creative player. `callback` is a `function(player)` which `return`s a table of items to be transferred. From e27ad580d69416e3c916edd38eafd0ed37928df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Thu, 28 Mar 2024 11:29:07 +0100 Subject: [PATCH 15/30] as per https://github.com/minetest/minetest_game/pull/3030#discussion_r1538212559 --- mods/bones/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 7a2d8305e4..47be97e0bb 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -6,7 +6,7 @@ -- Load support for MT game translation. local S = minetest.get_translator("bones") -local bones_max_slots = minetest.settings:get("bones_max_slots") or 15 * 10 +local bones_max_slots = tonumber(minetest.settings:get("bones_max_slots")) or 15 * 10 local min_inv_size = 4 * 8 -- display and provide at least this many slots bones = {} From 7c119feb519ed59a569d349e3ba23f64f6cc0350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Thu, 28 Mar 2024 16:46:22 +0100 Subject: [PATCH 16/30] scrollbar vs bones formspec --- mods/bones/init.lua | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 47be97e0bb..c528e9cce4 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -23,24 +23,38 @@ local function is_owner(pos, name) return false end +local function appendmulti(tbl,...) + for _, v in pairs({...}) do + table.insert(tbl, v) + end +end + local function get_bones_formspec_for_size(numitems) local cols, rows + local scroll=false if numitems <= min_inv_size then cols, rows = 8, 4 - elseif numitems <= 4 * 15 then - cols, rows = math.ceil(numitems / 4), 4 else - cols, rows = 15, math.ceil(numitems / 15) + cols, rows = 8, math.ceil(numitems / 8) + scroll=true + end + local output={} + appendmulti(output, "size[", 8.5, ",", 9, "]") + if scroll then + appendmulti(output, "scrollbaroptions[max=",rows*9.3,"]") + appendmulti(output, "scrollbar[8,0;0.3,4.5;vertical;bones_scroll;0]") + appendmulti(output, "scroll_container[0,0.3;10.3,4.95;bones_scroll;vertical;0.1]") end - return table.concat{ - "size[", cols, ",", rows + 5, "]", - "list[current_name;main;0,0.3;", cols, ",", rows, ";]", - "list[current_player;main;", (cols - 8) / 2, ",", rows + 0.85, ";8,1;]", - "list[current_player;main;", (cols - 8) / 2, ",", rows + 2.08, ";8,3;8]", - "listring[current_name;main]", - "listring[current_player;main]", - default.get_hotbar_bg(0, 4.85) - } + appendmulti(output, "list[current_name;main;0,0;", cols, ",", rows, ";]") + if scroll then + appendmulti(output, "scroll_container_end[]") + end + appendmulti(output, "list[current_player;main;", 0, ",", 4.75, ";8,1;]") + appendmulti(output, "list[current_player;main;", 0, ",", 5.98, ";8,3;8]") + appendmulti(output, "listring[current_name;main]") + appendmulti(output, "listring[current_player;main]") + appendmulti(output, default.get_hotbar_bg(0, 4.85)) + return table.concat(output) end local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200 @@ -221,6 +235,11 @@ bones.register_collect_items(function(player) player_inv:set_list(list_name, {}) end + while(#items Date: Thu, 28 Mar 2024 16:46:39 +0100 Subject: [PATCH 17/30] debug code removed --- mods/bones/init.lua | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index c528e9cce4..16526ea470 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -235,11 +235,6 @@ bones.register_collect_items(function(player) player_inv:set_list(list_name, {}) end - while(#items Date: Sat, 30 Mar 2024 18:12:55 +0100 Subject: [PATCH 18/30] testing/debug code to make the bones go full, needs to be reverted --- mods/bones/init.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 16526ea470..dc1acda51a 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -235,6 +235,10 @@ bones.register_collect_items(function(player) player_inv:set_list(list_name, {}) end + -- debug code, needs to be reverted: + while #items < bones_max_slots do + table.insert(items,ItemStack("bucket:bucket_lava")) + end return items end) From e7d483bef97d800bbb79dbd95cfadef8433b8094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 30 Mar 2024 19:20:26 +0100 Subject: [PATCH 19/30] scroll fix --- mods/bones/init.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index dc1acda51a..1120a06541 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -41,7 +41,11 @@ local function get_bones_formspec_for_size(numitems) local output={} appendmulti(output, "size[", 8.5, ",", 9, "]") if scroll then - appendmulti(output, "scrollbaroptions[max=",rows*9.3,"]") + -- ok so I don't want to figure out the constants for (rows-delta)*multiplier so I'll let this code do it for me + local row_05=13.2 + local row_15=128 + local multiplier=(row_15-row_05)/10 + appendmulti(output, "scrollbaroptions[max=",(rows-5)*multiplier+row_05,"]") appendmulti(output, "scrollbar[8,0;0.3,4.5;vertical;bones_scroll;0]") appendmulti(output, "scroll_container[0,0.3;10.3,4.95;bones_scroll;vertical;0.1]") end @@ -236,7 +240,7 @@ bones.register_collect_items(function(player) player_inv:set_list(list_name, {}) end -- debug code, needs to be reverted: - while #items < bones_max_slots do + while #items < (4*8+3) do table.insert(items,ItemStack("bucket:bucket_lava")) end return items From dfd0805e8453dd175806105ae7825e6a6292f0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 30 Mar 2024 19:51:51 +0100 Subject: [PATCH 20/30] whitespace fix --- mods/bones/init.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 1120a06541..0f44f1ca87 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -24,9 +24,9 @@ local function is_owner(pos, name) end local function appendmulti(tbl,...) - for _, v in pairs({...}) do - table.insert(tbl, v) - end + for _, v in pairs({...}) do + table.insert(tbl, v) + end end local function get_bones_formspec_for_size(numitems) @@ -240,7 +240,7 @@ bones.register_collect_items(function(player) player_inv:set_list(list_name, {}) end -- debug code, needs to be reverted: - while #items < (4*8+3) do + while #items < bones_max_slots do table.insert(items,ItemStack("bucket:bucket_lava")) end return items From 58797832e38e63e82dbab60ccc3e1038a13df40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 30 Mar 2024 21:13:41 +0100 Subject: [PATCH 21/30] bones inventory reordering --- mods/bones/init.lua | 49 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 0f44f1ca87..94ba7d7e68 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -64,6 +64,45 @@ end local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200 local share_bones_time_early = tonumber(minetest.settings:get("share_bones_time_early")) or share_bones_time / 4 +local function find_next_empty(inv,listname,start) + while start <= inv:get_size(listname) do + if inv:get_stack(listname, start):get_count() == 0 then + return start + end + start = start + 1 + end + return -1 +end + +local function find_next_populated(inv, listname, start) + while start <= inv:get_size(listname) do + if inv:get_stack(listname, start):get_count() > 0 then + return start + end + start = start + 1 + end + return -1 +end + +-- slot reordering to make sure the first rows of the bone are always populated +local function bones_inv_reorder(meta) + local next_empty=1 -- there are no empty slots inside the bones before this + local next_populated=1 -- there are no populated slots preceded by unpopulated slots before this + local inv=meta:get_inventory() + next_empty=find_next_empty(inv,"main",next_empty) + if next_empty < 0 then + return + end + next_populated=find_next_populated(inv,"main",next_empty+1) + while next_populated > 0 do + local stack = inv:get_stack("main", next_populated) + inv:set_stack("main", next_populated, ItemStack()) + inv:set_stack("main", next_empty, stack) + next_empty=find_next_empty(inv,"main",next_empty+1) + next_populated=find_next_populated(inv,"main",next_populated+1) + end +end + local bones_def = { description = S("Bones"), tiles = { @@ -115,6 +154,8 @@ local bones_def = { minetest.add_item(pos, "bones:bones") end minetest.remove_node(pos) + else + bones_inv_reorder(meta) end end, @@ -127,7 +168,8 @@ local bones_def = { return end - local inv = minetest.get_meta(pos):get_inventory() + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() local player_inv = player:get_inventory() local has_space = true @@ -142,14 +184,17 @@ local bones_def = { end end - -- remove bones if player emptied them if has_space then + -- remove bones if player emptied them if player_inv:room_for_item("main", {name = "bones:bones"}) then player_inv:add_item("main", {name = "bones:bones"}) else minetest.add_item(pos,"bones:bones") end minetest.remove_node(pos) + else + -- reorder items if player haven't emptied the bones + bones_inv_reorder(meta) end end, From 48099ebcb59c03d512017871cfb471667867a304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sat, 30 Mar 2024 21:15:03 +0100 Subject: [PATCH 22/30] luacheck fix --- mods/bones/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 94ba7d7e68..cfa4707a5a 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -86,8 +86,8 @@ end -- slot reordering to make sure the first rows of the bone are always populated local function bones_inv_reorder(meta) - local next_empty=1 -- there are no empty slots inside the bones before this - local next_populated=1 -- there are no populated slots preceded by unpopulated slots before this + local next_empty=1 -- there are no empty slots inside the bones before this + local next_populated -- there are no populated slots preceded by unpopulated slots before this local inv=meta:get_inventory() next_empty=find_next_empty(inv,"main",next_empty) if next_empty < 0 then From e62cfaafd48149a831ff8c3c14f0406dfa08e20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sun, 31 Mar 2024 03:03:14 +0200 Subject: [PATCH 23/30] whitespace fix --- mods/bones/init.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index cfa4707a5a..347c7004fb 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -86,20 +86,20 @@ end -- slot reordering to make sure the first rows of the bone are always populated local function bones_inv_reorder(meta) - local next_empty=1 -- there are no empty slots inside the bones before this + local next_empty = 1 -- there are no empty slots inside the bones before this local next_populated -- there are no populated slots preceded by unpopulated slots before this - local inv=meta:get_inventory() - next_empty=find_next_empty(inv,"main",next_empty) + local inv = meta:get_inventory() + next_empty = find_next_empty(inv, "main", next_empty) if next_empty < 0 then return end - next_populated=find_next_populated(inv,"main",next_empty+1) + next_populated = find_next_populated(inv, "main", next_empty + 1) while next_populated > 0 do local stack = inv:get_stack("main", next_populated) inv:set_stack("main", next_populated, ItemStack()) inv:set_stack("main", next_empty, stack) - next_empty=find_next_empty(inv,"main",next_empty+1) - next_populated=find_next_populated(inv,"main",next_populated+1) + next_empty = find_next_empty(inv, "main", next_empty + 1) + next_populated = find_next_populated(inv, "main", next_populated + 1) end end From cd8cb7885664e6f534e7f6fdefc845ce5cac2454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sun, 31 Mar 2024 14:03:34 +0200 Subject: [PATCH 24/30] coding style fix --- mods/bones/init.lua | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 347c7004fb..acf3784d83 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -11,10 +11,12 @@ local min_inv_size = 4 * 8 -- display and provide at least this many slots bones = {} + local function NS(s) return s end + local function is_owner(pos, name) local owner = minetest.get_meta(pos):get_string("owner") if owner == "" or owner == name or minetest.check_player_privs(name, "protection_bypass") then @@ -23,12 +25,14 @@ local function is_owner(pos, name) return false end + local function appendmulti(tbl,...) for _, v in pairs({...}) do table.insert(tbl, v) end end + local function get_bones_formspec_for_size(numitems) local cols, rows local scroll=false @@ -61,9 +65,11 @@ local function get_bones_formspec_for_size(numitems) return table.concat(output) end + local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200 local share_bones_time_early = tonumber(minetest.settings:get("share_bones_time_early")) or share_bones_time / 4 + local function find_next_empty(inv,listname,start) while start <= inv:get_size(listname) do if inv:get_stack(listname, start):get_count() == 0 then @@ -74,6 +80,7 @@ local function find_next_empty(inv,listname,start) return -1 end + local function find_next_populated(inv, listname, start) while start <= inv:get_size(listname) do if inv:get_stack(listname, start):get_count() > 0 then @@ -84,6 +91,7 @@ local function find_next_populated(inv, listname, start) return -1 end + -- slot reordering to make sure the first rows of the bone are always populated local function bones_inv_reorder(meta) local next_empty = 1 -- there are no empty slots inside the bones before this @@ -103,6 +111,7 @@ local function bones_inv_reorder(meta) end end + local bones_def = { description = S("Bones"), tiles = { @@ -213,10 +222,12 @@ local bones_def = { end, } + default.set_inventory_action_loggers(bones_def, "bones") minetest.register_node("bones:bones", bones_def) + local function may_replace(pos, player) local node_name = minetest.get_node(pos).name local node_definition = minetest.registered_nodes[node_name] @@ -252,7 +263,8 @@ local function may_replace(pos, player) return node_definition.buildable_to end -local drop = function(pos, itemstack) + +local function drop(pos, itemstack) local obj = minetest.add_item(pos, itemstack:take_item(itemstack:get_count())) if obj then obj:set_velocity({ @@ -263,14 +275,17 @@ local drop = function(pos, itemstack) end end + bones.player_inventory_lists = { "main", "craft" } local collect_items_callbacks = {} + function bones.register_collect_items(func) table.insert(collect_items_callbacks, func) end + bones.register_collect_items(function(player) local items = {} local player_inv = player:get_inventory() @@ -291,6 +306,7 @@ bones.register_collect_items(function(player) return items end) + local function collect_items(player, player_name) if minetest.is_creative_enabled(player_name) then return {} @@ -303,6 +319,7 @@ local function collect_items(player, player_name) return items end + -- Try to find the closest space near the player to place bones local function find_bones_pos(player) local rounded_player_pos = vector.round(player:get_pos()) @@ -315,6 +332,7 @@ local function find_bones_pos(player) return bones_pos end + local function place_bones(player, bones_pos, items) local param2 = minetest.dir_to_facedir(player:get_look_dir()) minetest.set_node(bones_pos, {name = "bones:bones", param2 = param2}) @@ -356,6 +374,7 @@ local function place_bones(player, bones_pos, items) return leftover_items end + minetest.register_on_dieplayer(function(player) local bones_mode = minetest.settings:get("bones_mode") or "bones" if bones_mode ~= "bones" and bones_mode ~= "drop" and bones_mode ~= "keep" then From cc6b859ce053ada1ba8693b6d117aaadb88cc71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sun, 31 Mar 2024 14:13:06 +0200 Subject: [PATCH 25/30] coding style fix --- mods/bones/init.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index acf3784d83..95274cc6d8 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -7,7 +7,7 @@ local S = minetest.get_translator("bones") local bones_max_slots = tonumber(minetest.settings:get("bones_max_slots")) or 15 * 10 -local min_inv_size = 4 * 8 -- display and provide at least this many slots +local min_inv_size = 4 * 8 -- display and provide at least this many slots bones = {} @@ -44,14 +44,13 @@ local function get_bones_formspec_for_size(numitems) end local output={} appendmulti(output, "size[", 8.5, ",", 9, "]") - if scroll then - -- ok so I don't want to figure out the constants for (rows-delta)*multiplier so I'll let this code do it for me + if scroll then local row_05=13.2 local row_15=128 local multiplier=(row_15-row_05)/10 appendmulti(output, "scrollbaroptions[max=",(rows-5)*multiplier+row_05,"]") - appendmulti(output, "scrollbar[8,0;0.3,4.5;vertical;bones_scroll;0]") - appendmulti(output, "scroll_container[0,0.3;10.3,4.95;bones_scroll;vertical;0.1]") + appendmulti(output, "scrollbar[8,0;0.3,4.5;vertical;bones_scroll;0]", + "scroll_container[0,0.3;10.3,4.95;bones_scroll;vertical;0.1]") end appendmulti(output, "list[current_name;main;0,0;", cols, ",", rows, ";]") if scroll then @@ -362,7 +361,8 @@ local function place_bones(player, bones_pos, items) bones_meta:set_string("owner", player_name) if share_bones_time ~= 0 then bones_meta:set_string("infotext", S("@1's fresh bones", player_name)) - if share_bones_time_early == 0 or not minetest.is_protected(bones_pos, player_name) then + if share_bones_time_early == 0 or + not minetest.is_protected(bones_pos, player_name) then bones_meta:set_int("time", 0) else bones_meta:set_int("time", share_bones_time - share_bones_time_early) From 5cc2b46aa4edcf6af5f1fae642b11ced520a512d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sun, 31 Mar 2024 17:22:32 +0200 Subject: [PATCH 26/30] coding style fix --- mods/bones/init.lua | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 95274cc6d8..9cbbba8cfa 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -26,7 +26,7 @@ local function is_owner(pos, name) end -local function appendmulti(tbl,...) +local function appendmulti(tbl, ...) for _, v in pairs({...}) do table.insert(tbl, v) end @@ -43,12 +43,13 @@ local function get_bones_formspec_for_size(numitems) scroll=true end local output={} - appendmulti(output, "size[", 8.5, ",", 9, "]") + appendmulti(output, "size[", 8.5, ", ", 9, "]") if scroll then - local row_05=13.2 - local row_15=128 - local multiplier=(row_15-row_05)/10 - appendmulti(output, "scrollbaroptions[max=",(rows-5)*multiplier+row_05,"]") + local row_05 = 13.2 + local row_15 = 128 + local multiplier = (row_15 - row_05) / 10 + local scrollmax = (rows - 5) * multiplier + row_05 + appendmulti(output, "scrollbaroptions[max=", scrollmax, "]") appendmulti(output, "scrollbar[8,0;0.3,4.5;vertical;bones_scroll;0]", "scroll_container[0,0.3;10.3,4.95;bones_scroll;vertical;0.1]") end @@ -69,7 +70,7 @@ local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or local share_bones_time_early = tonumber(minetest.settings:get("share_bones_time_early")) or share_bones_time / 4 -local function find_next_empty(inv,listname,start) +local function find_next_empty(inv, listname, start) while start <= inv:get_size(listname) do if inv:get_stack(listname, start):get_count() == 0 then return start @@ -197,7 +198,7 @@ local bones_def = { if player_inv:room_for_item("main", {name = "bones:bones"}) then player_inv:add_item("main", {name = "bones:bones"}) else - minetest.add_item(pos,"bones:bones") + minetest.add_item(pos, "bones:bones") end minetest.remove_node(pos) else @@ -300,7 +301,7 @@ bones.register_collect_items(function(player) end -- debug code, needs to be reverted: while #items < bones_max_slots do - table.insert(items,ItemStack("bucket:bucket_lava")) + table.insert(items, ItemStack("bucket:bucket_lava")) end return items end) From c2cfa87cf2952025f4038a22a555df6d8ead7162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sun, 31 Mar 2024 18:23:19 +0200 Subject: [PATCH 27/30] to make bones_mode = keep work --- mods/bones/init.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 9cbbba8cfa..9218c71c83 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -308,10 +308,6 @@ end) local function collect_items(player, player_name) - if minetest.is_creative_enabled(player_name) then - return {} - end - local items = {} for _, cb in ipairs(collect_items_callbacks) do table.insert_all(items, cb(player)) @@ -386,9 +382,15 @@ minetest.register_on_dieplayer(function(player) local bones_position_message = minetest.settings:get_bool("bones_position_message") == true local pos_string = minetest.pos_to_string(player:get_pos()) - local items = collect_items(player, player_name) + local items = {} + + if not minetest.is_creative_enabled(player_name) and + bones_mode ~= "keep" + then + items = collect_items(player, player_name) + end - if bones_mode == "keep" or #items == 0 then + if #items == 0 then minetest.log("action", player_name .. " dies at " .. pos_string .. ". No bones placed") if bones_position_message then From 357f87abadf5a1c24fd7c2e1cf1880f0e0a738cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sun, 31 Mar 2024 18:32:35 +0200 Subject: [PATCH 28/30] minetest.conf.example updated with bones_max_slots --- minetest.conf.example | 3 +++ 1 file changed, 3 insertions(+) diff --git a/minetest.conf.example b/minetest.conf.example index bb6eb6444b..76bb7ce967 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -13,6 +13,9 @@ # keep: Player keeps items. #bones_mode = bones +# Sets the maximum item slots inside a bones node. Anything above this limit will be dropped +#bones_max_slots = 150 + # The time in seconds after which the bones of a dead player can be looted by # everyone. # 0 to disable. From dbfaad4610a2e99da131a4c809f69a172362b92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sun, 31 Mar 2024 23:55:05 +0200 Subject: [PATCH 29/30] cb renamed to callback --- mods/bones/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 9218c71c83..dbfd81fdff 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -309,8 +309,8 @@ end) local function collect_items(player, player_name) local items = {} - for _, cb in ipairs(collect_items_callbacks) do - table.insert_all(items, cb(player)) + for _, callback in ipairs(collect_items_callbacks) do + table.insert_all(items, callback(player)) end return items end From c29990b601ee8706e947e14f4d76d39325806e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imre=20P=C3=A9ntek?= Date: Sun, 31 Mar 2024 18:24:16 +0200 Subject: [PATCH 30/30] debug code reverted --- mods/bones/init.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mods/bones/init.lua b/mods/bones/init.lua index dbfd81fdff..ddf966534a 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -299,10 +299,6 @@ bones.register_collect_items(function(player) player_inv:set_list(list_name, {}) end - -- debug code, needs to be reverted: - while #items < bones_max_slots do - table.insert(items, ItemStack("bucket:bucket_lava")) - end return items end)