1 -- tutorial/creative/init.lua
5 if (minetest
.get_modpath("intllib")) then
8 S
= function ( s
) return s
end
12 local player_inventory
= {}
14 -- Create detached creative inventory after loading all mods
15 creative
.init_creative_inventory
= function(player
)
16 local player_name
= player
:get_player_name()
18 player_inventory
[player_name
] = {}
19 player_inventory
[player_name
].size
= 0
20 player_inventory
[player_name
].filter
= nil
21 player_inventory
[player_name
].start_i
= 1
23 local inv
= minetest
.create_detached_inventory("creative_" .. player_name
, {
24 allow_move
= function(inv
, from_list
, from_index
, to_list
, to_index
, count
, player
)
25 if minetest
.setting_getbool("creative_mode") then
31 allow_put
= function(inv
, listname
, index
, stack
, player
)
34 allow_take
= function(inv
, listname
, index
, stack
, player
)
35 if minetest
.setting_getbool("creative_mode") then
41 on_move
= function(inv
, from_list
, from_index
, to_list
, to_index
, count
, player
)
43 on_put
= function(inv
, listname
, index
, stack
, player
)
45 on_take
= function(inv
, listname
, index
, stack
, player
)
46 --print(player:get_player_name().." takes item from creative inventory; listname="..dump(listname)..", index="..dump(index)..", stack="..dump(stack))
48 minetest
.log("action", player
:get_player_name().." takes "..dump(stack
:get_name()).." from creative inventory")
49 --print("stack:get_name()="..dump(stack:get_name())..", stack:get_count()="..dump(stack:get_count()))
54 creative
.update_creative_inventory(player_name
, nil, 2)
55 --print("creative inventory size: "..dump(player_inventory[player_name].size))
58 local function tab_category(tab_id
)
60 nil, -- Reserved for crafting tab.
61 minetest
.registered_items
,
62 minetest
.registered_nodes
,
63 minetest
.registered_tools
,
64 minetest
.registered_craftitems
67 -- If index out of range, show default ("All") page.
68 return id_category
[tab_id
] or id_category
[2]
71 function creative
.update_creative_inventory(player_name
, filter
, tab_id
)
72 local creative_list
= {}
73 local inv
= minetest
.get_inventory({type = "detached", name
= "creative_" .. player_name
})
75 for name
, def
in pairs(tab_category(tab_id
)) do
76 if not (def
.groups
.not_in_creative_inventory
== 1) and
77 def
.description
and def
.description
~= "" and
78 (not filter
or def
.name
:find(filter
, 1, true) or
79 def
.description
:lower():find(filter
, 1, true)) then
80 creative_list
[#creative_list
+1] = name
84 table.sort(creative_list
)
85 inv
:set_size("main", #creative_list
)
86 inv
:set_list("main", creative_list
)
87 player_inventory
[player_name
].size
= #creative_list
90 -- Create the trash field
91 local trash
= minetest
.create_detached_inventory("creative_trash", {
92 -- Allow the stack to be placed and remove it in on_put()
93 -- This allows the creative inventory to restore the stack
94 allow_put
= function(inv
, listname
, index
, stack
, player
)
95 if minetest
.setting_getbool("creative_mode") then
96 return stack
:get_count()
101 on_put
= function(inv
, listname
, index
, stack
, player
)
102 inv
:set_stack(listname
, index
, "")
105 trash
:set_size("main", 1)
107 creative
.set_creative_formspec
= function(player
, start_i
, pagenum
, tab_id
)
108 local player_name
= player
:get_player_name()
109 local filter
= player_inventory
[player_name
].filter
or ""
110 pagenum
= math
.floor(pagenum
)
111 local pagemax
= math
.floor((player_inventory
[player_name
].size
- 1) / (3*8) + 1)
114 player
:set_inventory_formspec([[
116 image[4.06,3.4;0.8,0.8;creative_trash_icon.png]
117 list[current_player;main;0,4.7;8,1;]
118 list[current_player;main;0,5.85;8,3;8]
119 list[detached:creative_trash;main;4,3.3;1,1;]
120 tablecolumns[color;text;color;text]
121 tableoptions[background=#00000000;highlight=#00000000;border=false]
122 button[5.4,3.2;0.8,0.9;creative_prev;<]
123 button[7.25,3.2;0.8,0.9;creative_next;>]
124 button[2.1,3.4;0.8,0.5;creative_search;?]
125 button[2.75,3.4;0.8,0.5;creative_clear;X]
126 tooltip[creative_search;]]..S("Search")..[[]
127 tooltip[creative_clear;]]..S("Reset")..[[]
128 listring[current_player;main]
130 "field[0.3,3.5;2.2,1;creative_filter;;".. filter
.."]"..
131 "listring[detached:creative_".. player_name
..";main]"..
132 "tabheader[0,0;creative_tabs;"..S("Crafting")..","..S("All")..","..S("Nodes")..","..S("Tools")..","..S("Items")..";".. tostring(tab_id
) ..";true;false]"..
133 "list[detached:creative_".. player_name
..";main;0,0;8,3;".. tostring(start_i
) .."]"..
134 "table[6.05,3.35;1.15,0.5;pagenum;#FFFF00,".. tostring(pagenum
) ..",#FFFFFF,/ ".. tostring(pagemax
) .."]"..
135 default
.get_hotbar_bg(0,4.7)..
136 default
.gui_bg
.. default
.gui_bg_img
.. default
.gui_slots
140 creative
.set_crafting_formspec
= function(player
)
141 player
:set_inventory_formspec([[
143 list[current_player;craft;2,0.75;3,3;]
144 list[current_player;craftpreview;6,1.75;1,1;]
145 list[current_player;main;0,4.7;8,1;]
146 list[current_player;main;0,5.85;8,3;8]
147 list[detached:creative_trash;main;0,2.75;1,1;]
148 image[0.06,2.85;0.8,0.8;creative_trash_icon.png]
149 image[5,1.75;1,1;gui_furnace_arrow_bg.png^[transformR270]
150 tabheader[0,0;creative_tabs;]]..S("Crafting")..","..S("All")..","..S("Nodes")..","..S("Tools")..","..S("Items")..[[;1;true;false]
151 listring[current_player;main]
152 listring[current_player;craft]
154 default
.get_hotbar_bg(0,4.7)..
155 default
.gui_bg
.. default
.gui_bg_img
.. default
.gui_slots
159 minetest
.register_on_joinplayer(function(player
)
160 -- If in creative mode, modify player's inventory forms
161 if not minetest
.setting_getbool("creative_mode") then
164 creative
.init_creative_inventory(player
)
165 creative
.set_creative_formspec(player
, 0, 1, 2)
168 minetest
.register_on_player_receive_fields(function(player
, formname
, fields
)
169 if formname
~= "" or not minetest
.setting_getbool("creative_mode") then
173 local player_name
= player
:get_player_name()
174 local formspec
= player
:get_inventory_formspec()
175 local filter
= formspec
:match("creative_filter;;([%w_:]+)") or ""
176 local start_i
= formspec
:match("list%[.-".. player_name
..";.-;(%d+)%]")
177 local tab_id
= tonumber(formspec
:match("tabheader%[.-;(%d+)%;"))
178 local inv_size
= player_inventory
[player_name
].size
179 start_i
= tonumber(start_i
) or 0
183 creative
.set_crafting_formspec(player
)
185 elseif fields
.creative_tabs
then
186 local tab
= tonumber(fields
.creative_tabs
)
188 creative
.set_crafting_formspec(player
)
190 creative
.update_creative_inventory(player_name
, filter
, tab
)
191 creative
.set_creative_formspec(player
, 0, 1, tab
)
193 elseif fields
.creative_clear
then
194 player_inventory
[player_name
].filter
= ""
195 creative
.update_creative_inventory(player_name
, nil, tab_id
)
196 creative
.set_creative_formspec(player
, 0, 1, tab_id
)
197 elseif fields
.creative_search
then
198 local lowstr
= fields
.creative_filter
:lower()
199 player_inventory
[player_name
].filter
= lowstr
200 creative
.update_creative_inventory(player_name
, lowstr
, tab_id
)
201 creative
.set_creative_formspec(player
, 0, 1, tab_id
)
203 if fields
.creative_prev
then
204 start_i
= start_i
- 3*8
206 start_i
= inv_size
- (inv_size
% (3*8))
207 if inv_size
== start_i
then
208 start_i
= math
.max(0, inv_size
- (3*8))
211 elseif fields
.creative_next
then
212 start_i
= start_i
+ 3*8
213 if start_i
>= inv_size
then
218 creative
.set_creative_formspec(player
, start_i
, start_i
/ (3*8) + 1, tab_id
)
222 if minetest
.setting_getbool("creative_mode") then
224 minetest
.register_item(":", {
226 wield_image
= "wieldhand.png",
227 wield_scale
= {x
=1, y
=1, z
=2.5},
229 tool_capabilities
= {
230 full_punch_interval
= 0.5,
233 crumbly
= {times
={[1]=digtime
, [2]=digtime
, [3]=digtime
}, uses
=0, maxlevel
=3},
234 cracky
= {times
={[1]=digtime
, [2]=digtime
, [3]=digtime
}, uses
=0, maxlevel
=3},
235 snappy
= {times
={[1]=digtime
, [2]=digtime
, [3]=digtime
}, uses
=0, maxlevel
=3},
236 choppy
= {times
={[1]=digtime
, [2]=digtime
, [3]=digtime
}, uses
=0, maxlevel
=3},
237 oddly_breakable_by_hand
= {times
={[1]=digtime
, [2]=digtime
, [3]=digtime
}, uses
=0, maxlevel
=3},
239 damage_groups
= {fleshy
= 10},
243 minetest
.register_on_placenode(function(pos
, newnode
, placer
, oldnode
, itemstack
)
247 function minetest
.handle_node_drops(pos
, drops
, digger
)
248 if not digger
or not digger
:is_player() then
251 local inv
= digger
:get_inventory()
253 for _
, item
in ipairs(drops
) do
254 item
= ItemStack(item
):get_name()
255 if not inv
:contains_item("main", item
) then
256 inv
:add_item("main", item
)