55
66-- Load support for MT game translation.
77local S = minetest .get_translator (" bones" )
8-
9- bones = {}
8+ -- bones are supposed to hold up to 4*8+6+4*3*8+4+3*3 item slots:
9+ -- 4*8 for the main inventory
10+ -- 6 for the 3d_armor
11+ -- (at most) 4*3*8 for 4 backpack worth of items (unified inventory)
12+ -- 4 more for the actual backpacks
13+ -- 3*3 more for the crafting grid
14+ -- that adds up to 147, so 150 slots would be sufficient
15+ local cols = 15
16+ local rows = 10
17+
18+ bones = {
19+ private = {
20+ dead_player_callbacks = {}
21+ },
22+ public = {}
23+ }
1024
1125local function is_owner (pos , name )
1226 local owner = minetest .get_meta (pos ):get_string (" owner" )
@@ -38,10 +52,10 @@ local function drop_contents(pos)
3852end
3953
4054local bones_formspec =
41- " size[8,9 ]" ..
42- " list[current_name;main;0,0.3;8,4 ;]" ..
43- " list[current_player;main;0,4 .85;8,1;]" ..
44- " list[current_player;main;0,6 .08;8,3;8]" ..
55+ " size[" .. cols .. " , " .. ( rows + 5 ) .. " ]" ..
56+ " list[current_name;main;0,0.3;" .. cols .. " , " .. rows .. " ;]" ..
57+ " list[current_player;main;" .. (( cols - 8 ) / 2 ) .. " , " .. rows .. " .85;8,1;]" ..
58+ " list[current_player;main;" .. (( cols - 8 ) / 2 ) .. " , " .. ( rows + 2 ) .. " .08;8,3;8]" ..
4559 " listring[current_name;main]" ..
4660 " listring[current_player;main]" ..
4761 default .get_hotbar_bg (0 ,4.85 )
@@ -209,15 +223,68 @@ local function is_all_empty(player_inv)
209223 return true
210224end
211225
226+ -- functions registered this way won't becalled if bones_mode is keep
227+ function bones .public .register_transfer_inventory_to_bones_on_player_death (func )
228+ bones .private .dead_player_callbacks [# (bones .private .dead_player_callbacks )]= func
229+ end
230+
231+ -- drop or put into bones based on config and free slots in the bones
232+ -- supposed to be called from functions registered to bones.public.register_transfer_inventory_to_bones_on_player_death
233+ function bones .public .transfer_stack_to_bones (stk )
234+ -- check if it's possible to place bones, if not find space near player
235+ if ( ( bones .private .current_dead_player .bones_mode == " bones" ) and ( bones .private .current_dead_player .bones_pos == nil ) ) then
236+ bones .private .current_dead_player .bones_pos = bones .private .current_dead_player .player_pos
237+ local air
238+ if ( may_replace (bones .private .current_dead_player .bones_pos , bones .private .current_dead_player .player ) ) then
239+ air = bones .private .current_dead_player .bones_pos
240+ else
241+ air = minetest .find_node_near (bones .private .current_dead_player .bones_pos , 1 , {" air" })
242+ end
243+
244+ if air and not minetest .is_protected (air , bones .private .current_dead_player .player_name ) then
245+ bones .private .current_dead_player .bones_pos = air
246+ local param2 = minetest .dir_to_facedir (bones .private .current_dead_player .player :get_look_dir ())
247+ minetest .set_node (bones .private .current_dead_player .bones_pos , {name = " bones:bones" , param2 = param2 })
248+ local meta = minetest .get_meta (bones .private .current_dead_player .bones_pos )
249+ bones .private .current_dead_player .bones_inv = meta :get_inventory ()
250+ bones .private .current_dead_player .bones_inv :set_size (" main" , cols * rows )
251+ else
252+ bones .private .current_dead_player .bones_mode = " drop"
253+ bones .private .current_dead_player .bones_pos = nil
254+ end
255+ end
256+
257+ if ( ( bones .private .current_dead_player .bones_mode == " bones" ) and ( bones .private .current_dead_player .bones_inv :room_for_item (" main" , stk ) ) ) then
258+ bones .private .current_dead_player .bones_inv :add_item (" main" , stk )
259+ else
260+ drop (bones .private .current_dead_player .player_pos , stk )
261+ bones .private .current_dead_player .dropped = true
262+ end
263+ end
264+
265+ local function player_dies_transfer_inventory (player )
266+ local player_inv = player :get_inventory ()
267+ for _ , list_name in ipairs (player_inventory_lists ) do
268+ for i = 1 , player_inv :get_size (list_name ) do
269+ local stack = player_inv :get_stack (list_name , i )
270+ bones .public .transfer_stack_to_bones (stack )
271+ end
272+ player_inv :set_list (list_name , {})
273+ end
274+ end
275+
276+ bones .public .register_transfer_inventory_to_bones_on_player_death (player_dies_transfer_inventory )
277+
212278minetest .register_on_dieplayer (function (player )
279+ local pos = vector .round (player :get_pos ())
213280 local bones_mode = minetest .settings :get (" bones_mode" ) or " bones"
214281 if bones_mode ~= " bones" and bones_mode ~= " drop" and bones_mode ~= " keep" then
215282 bones_mode = " bones"
216283 end
284+ local player_name = player :get_player_name ()
285+ 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 }
217286
218287 local bones_position_message = minetest .settings :get_bool (" bones_position_message" ) == true
219- local player_name = player :get_player_name ()
220- local pos = vector .round (player :get_pos ())
221288 local pos_string = minetest .pos_to_string (pos )
222289
223290 -- return if keep inventory set or in creative mode
@@ -230,67 +297,43 @@ minetest.register_on_dieplayer(function(player)
230297 return
231298 end
232299
233- local player_inv = player :get_inventory ()
234- if is_all_empty (player_inv ) then
235- minetest .log (" action" , player_name .. " dies at " .. pos_string ..
236- " . No bones placed" )
237- if bones_position_message then
238- minetest .chat_send_player (player_name , S (" @1 died at @2." , player_name , pos_string ))
239- end
240- return
300+ for i = 0 ,# bones .private .dead_player_callbacks do
301+ local fun = bones .private .dead_player_callbacks [i ]
302+ fun (player )
241303 end
242304
243- -- check if it's possible to place bones, if not find space near player
244- if bones_mode == " bones" and not may_replace (pos , player ) then
245- local air = minetest .find_node_near (pos , 1 , {" air" })
246- if air then
247- pos = air
248- else
249- bones_mode = " drop"
250- end
251- end
305+ local bones_conclusion = " "
306+ local public_conclusion = " "
252307
253- if bones_mode == " drop" then
254- for _ , list_name in ipairs (player_inventory_lists ) do
255- for i = 1 , player_inv :get_size (list_name ) do
256- drop (pos , player_inv :get_stack (list_name , i ))
257- end
258- player_inv :set_list (list_name , {})
308+ if (not (bones .private .current_dead_player .bones_pos ))then
309+ drop (bones .private .current_dead_player .player_pos , ItemStack (" bones:bones" ))
310+ if (not (bones .private .current_dead_player .dropped ))then
311+ bones_conclusion = " No bones placed"
312+ else
313+ bones_conclusion = " Inventory dropped"
314+ public_conclusion = " dropped their inventory"
259315 end
260- drop (pos , ItemStack (" bones:bones" ))
261- minetest .log (" action" , player_name .. " dies at " .. pos_string ..
262- " . Inventory dropped" )
263- if bones_position_message then
264- minetest .chat_send_player (player_name , S (" @1 died at @2, and dropped their inventory." , player_name , pos_string ))
316+ else
317+ if (not (bones .private .current_dead_player .dropped ))then
318+ bones_conclusion = " Bones placed"
319+ public_conclusion = " bones were placed"
320+ else
321+ bones_conclusion = " Inventory partially dropped"
322+ public_conclusion = " partially dropped their inventory"
265323 end
266- return
267324 end
268325
269- local param2 = minetest .dir_to_facedir (player :get_look_dir ())
270- minetest .set_node (pos , {name = " bones:bones" , param2 = param2 })
271-
272326 minetest .log (" action" , player_name .. " dies at " .. pos_string ..
273- " . Bones placed" )
274- if bones_position_message then
275- minetest .chat_send_player (player_name , S (" @1 died at @2, and bones were placed." , player_name , pos_string ))
276- end
327+ " . " .. bones_conclusion )
277328
278- local meta = minetest .get_meta (pos )
279- local inv = meta :get_inventory ()
280- inv :set_size (" main" , 8 * 4 )
281-
282- for _ , list_name in ipairs (player_inventory_lists ) do
283- for i = 1 , player_inv :get_size (list_name ) do
284- local stack = player_inv :get_stack (list_name , i )
285- if inv :room_for_item (" main" , stack ) then
286- inv :add_item (" main" , stack )
287- else -- no space left
288- drop (pos , stack )
289- end
329+ if bones_position_message then
330+ if (public_conclusion ~= " " )then
331+ public_conclusion = " , and " .. public_conclusion
290332 end
291- player_inv : set_list ( list_name , {} )
333+ minetest . chat_send_player ( player_name , S ( " @1 died at @2@3. " , player_name , pos_string , public_conclusion ) )
292334 end
293335
336+ local meta = minetest .get_meta (bones .private .current_dead_player .bones_pos )
294337 meta :set_string (" formspec" , bones_formspec )
295338 meta :set_string (" owner" , player_name )
296339
@@ -307,4 +350,5 @@ minetest.register_on_dieplayer(function(player)
307350 else
308351 meta :set_string (" infotext" , S (" @1's bones" , player_name ))
309352 end
353+ bones .private .current_dead_player = nil
310354end )
0 commit comments