Add fancy inventory for bones
[oweals/minetest_game.git] / mods / bones / init.lua
1 -- Minetest 0.4 mod: bones
2 -- See README.txt for licensing and other information. 
3
4 bones = {}
5
6 local function is_owner(pos, name)
7         local owner = minetest.get_meta(pos):get_string("owner")
8         if owner == "" or owner == name then
9                 return true
10         end
11         return false
12 end
13
14 bones.bones_formspec =
15         "size[8,9]"..
16         default.gui_bg..
17         default.gui_bg_img..
18         default.gui_slots..
19         "list[current_name;main;0,0.3;8,4;]"..
20         "list[current_player;main;0,4.85;8,1;]"..
21         "list[current_player;main;0,6.08;8,3;8]"..
22         default.get_hotbar_bg(0,4.85)
23
24 minetest.register_node("bones:bones", {
25         description = "Bones",
26         tiles = {
27                 "bones_top.png",
28                 "bones_bottom.png",
29                 "bones_side.png",
30                 "bones_side.png",
31                 "bones_rear.png",
32                 "bones_front.png"
33         },
34         paramtype2 = "facedir",
35         groups = {dig_immediate=2},
36         sounds = default.node_sound_dirt_defaults({
37                 footstep = {name="default_gravel_footstep", gain=0.5},
38                 dug = {name="default_gravel_footstep", gain=1.0},
39         }),
40         
41         can_dig = function(pos, player)
42                 local inv = minetest.get_meta(pos):get_inventory()
43                 return is_owner(pos, player:get_player_name()) and inv:is_empty("main")
44         end,
45         
46         allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
47                 if is_owner(pos, player:get_player_name()) then
48                         return count
49                 end
50                 return 0
51         end,
52         
53         allow_metadata_inventory_put = function(pos, listname, index, stack, player)
54                 return 0
55         end,
56         
57         allow_metadata_inventory_take = function(pos, listname, index, stack, player)
58                 if is_owner(pos, player:get_player_name()) then
59                         return stack:get_count()
60                 end
61                 return 0
62         end,
63         
64         on_metadata_inventory_take = function(pos, listname, index, stack, player)
65                 local meta = minetest.get_meta(pos)
66                 if meta:get_inventory():is_empty("main") then
67                         minetest.remove_node(pos)
68                 end
69         end,
70         
71         on_punch = function(pos, node, player)
72                 if(not is_owner(pos, player:get_player_name())) then
73                         return
74                 end
75                 
76                 local inv = minetest.get_meta(pos):get_inventory()
77                 local player_inv = player:get_inventory()
78                 local has_space = true
79                 
80                 for i=1,inv:get_size("main") do
81                         local stk = inv:get_stack("main", i)
82                         if player_inv:room_for_item("main", stk) then
83                                 inv:set_stack("main", i, nil)
84                                 player_inv:add_item("main", stk)
85                         else
86                                 has_space = false
87                                 break
88                         end
89                 end
90                 
91                 -- remove bones if player emptied them
92                 if has_space then
93                         minetest.remove_node(pos)
94                 end
95         end,
96         
97         on_timer = function(pos, elapsed)
98                 local meta = minetest.get_meta(pos)
99                 local time = meta:get_int("time")+elapsed
100                 local publish = 1200
101                 if tonumber(minetest.setting_get("share_bones_time")) then
102                         publish = tonumber(minetest.setting_get("share_bones_time"))
103                 end
104                 if publish == 0 then
105                         return
106                 end
107                 if time >= publish then
108                         meta:set_string("infotext", meta:get_string("owner").."'s old bones")
109                         meta:set_string("owner", "")
110                 else
111                         return true
112                 end
113         end,
114 })
115
116 minetest.register_on_dieplayer(function(player)
117         if minetest.setting_getbool("creative_mode") then
118                 return
119         end
120         
121         local player_inv = player:get_inventory()
122         if player_inv:is_empty("main") and
123                 player_inv:is_empty("craft") then
124                 return
125         end
126
127         local pos = player:getpos()
128         pos.x = math.floor(pos.x+0.5)
129         pos.y = math.floor(pos.y+0.5)
130         pos.z = math.floor(pos.z+0.5)
131         local param2 = minetest.dir_to_facedir(player:get_look_dir())
132         local player_name = player:get_player_name()
133         local player_inv = player:get_inventory()
134         
135         local nn = minetest.get_node(pos).name
136         if minetest.registered_nodes[nn].can_dig and
137                 not minetest.registered_nodes[nn].can_dig(pos, player) then
138
139                 -- drop items instead of delete
140                 for i=1,player_inv:get_size("main") do
141                         minetest.add_item(pos, player_inv:get_stack("main", i))
142                 end
143                 for i=1,player_inv:get_size("craft") do
144                         minetest.add_item(pos, player_inv:get_stack("craft", i))
145                 end
146                 -- empty lists main and craft
147                 player_inv:set_list("main", {})
148                 player_inv:set_list("craft", {})
149                 return
150         end
151         
152         minetest.dig_node(pos)
153         minetest.add_node(pos, {name="bones:bones", param2=param2})
154         
155         local meta = minetest.get_meta(pos)
156         local inv = meta:get_inventory()
157         inv:set_size("main", 8*4)
158         inv:set_list("main", player_inv:get_list("main"))
159         
160         for i=1,player_inv:get_size("craft") do
161                 local stack = player_inv:get_stack("craft", i)
162                 if inv:room_for_item("main", stack) then
163                         inv:add_item("main", stack)
164                 else
165                         --drop if no space left
166                         minetest.add_item(pos, stack)
167                 end
168         end
169         
170         player_inv:set_list("main", {})
171         player_inv:set_list("craft", {})
172         
173         meta:set_string("formspec", bones.bones_formspec)
174         meta:set_string("infotext", player_name.."'s fresh bones")
175         meta:set_string("owner", player_name)
176         meta:set_int("time", 0)
177         
178         local timer  = minetest.get_node_timer(pos)
179         timer:start(10)
180 end)