]> git.lizzy.rs Git - dragonfireclient.git/blob - data/builtin.lua
Working implementation of experimental:luafurnace
[dragonfireclient.git] / data / builtin.lua
1 --
2 -- This file contains built-in stuff in Minetest implemented in Lua.
3 --
4 -- It is always loaded and executed after registration of the C API,
5 -- before loading and running any mods.
6 --
7
8 function basic_dump2(o)
9         if type(o) == "number" then
10                 return tostring(o)
11         elseif type(o) == "string" then
12                 return string.format("%q", o)
13         elseif type(o) == "boolean" then
14                 return tostring(o)
15         elseif type(o) == "function" then
16                 return "<function>"
17         elseif type(o) == "userdata" then
18                 return "<userdata>"
19         elseif type(o) == "nil" then
20                 return "nil"
21         else
22                 error("cannot dump a " .. type(o))
23                 return nil
24         end
25 end
26
27 function dump2(o, name, dumped)
28         name = name or "_"
29         dumped = dumped or {}
30         io.write(name, " = ")
31         if type(o) == "number" or type(o) == "string" or type(o) == "boolean"
32                         or type(o) == "function" or type(o) == "nil"
33                         or type(o) == "userdata" then
34                 io.write(basic_dump2(o), "\n")
35         elseif type(o) == "table" then
36                 if dumped[o] then
37                         io.write(dumped[o], "\n")
38                 else
39                         dumped[o] = name
40                         io.write("{}\n") -- new table
41                         for k,v in pairs(o) do
42                                 local fieldname = string.format("%s[%s]", name, basic_dump2(k))
43                                 dump2(v, fieldname, dumped)
44                         end
45                 end
46         else
47                 error("cannot dump a " .. type(o))
48                 return nil
49         end
50 end
51
52 function dump(o, dumped)
53         dumped = dumped or {}
54         if type(o) == "number" then
55                 return tostring(o)
56         elseif type(o) == "string" then
57                 return string.format("%q", o)
58         elseif type(o) == "table" then
59                 if dumped[o] then
60                         return "<circular reference>"
61                 end
62                 dumped[o] = true
63                 local t = {}
64                 for k,v in pairs(o) do
65                         t[#t+1] = "" .. k .. " = " .. dump(v, dumped)
66                 end
67                 return "{" .. table.concat(t, ", ") .. "}"
68         elseif type(o) == "boolean" then
69                 return tostring(o)
70         elseif type(o) == "function" then
71                 return "<function>"
72         elseif type(o) == "userdata" then
73                 return "<userdata>"
74         elseif type(o) == "nil" then
75                 return "nil"
76         else
77                 error("cannot dump a " .. type(o))
78                 return nil
79         end
80 end
81
82 --
83 -- Built-in node definitions. Also defined in C.
84 --
85
86 minetest.register_nodedef_defaults({
87         -- name intentionally not defined here
88         drawtype = "normal",
89         visual_scale = 1.0,
90         tile_images = {"unknown_block.png"},
91         inventory_image = "unknown_block.png",
92         special_materials = {
93                 {image="", backface_culling=true},
94                 {image="", backface_culling=true},
95         },
96         alpha = 255,
97         post_effect_color = {a=0, r=0, g=0, b=0},
98         paramtype = "none",
99         is_ground_content = false,
100         sunlight_propagates = false,
101         walkable = true,
102         pointable = true,
103         diggable = true,
104         climbable = false,
105         buildable_to = false,
106         wall_mounted = false,
107         often_contains_mineral = false,
108         dug_item = "",
109         extra_dug_item = "",
110         extra_dug_item_rarity = 2,
111         metadata_name = "",
112         liquidtype = "none",
113         liquid_alternative_flowing = "",
114         liquid_alternative_source = "",
115         liquid_viscosity = 0,
116         light_source = 0,
117         damage_per_second = 0,
118         selection_box = {type="regular"},
119         material = {
120                 diggablity = "normal",
121                 weight = 0,
122                 crackiness = 0,
123                 crumbliness = 0,
124                 cuttability = 0,
125                 flammability = 0,
126         },
127         cookresult_item = "", -- Cannot be cooked
128         furnace_cooktime = 3.0,
129         furnace_burntime = -1, -- Cannot be used as fuel
130 })
131
132 minetest.register_node("air", {
133         drawtype = "airlike",
134         paramtype = "light",
135         sunlight_propagates = true,
136         walkable = false,
137         pointable = false,
138         diggable = false,
139         buildable_to = true,
140         air_equivalent = true,
141 })
142
143 minetest.register_node("ignore", {
144         drawtype = "airlike",
145         paramtype = "none",
146         sunlight_propagates = false,
147         walkable = false,
148         pointable = false,
149         diggable = false,
150         buildable_to = true, -- A way to remove accidentally placed ignores
151         air_equivalent = true,
152 })
153
154 --
155 -- stackstring manipulation functions
156 -- example stackstring: 'craft "apple" 4'
157 -- example item: {type="craft", name="apple"}
158 -- example item: {type="tool", name="SteelPick", wear="23272"}
159 --
160
161 function stackstring_take_item(stackstring)
162         if stackstring == nil then
163                 return '', nil
164         end
165         local stacktype = nil
166         stacktype = string.match(stackstring,
167                         '([%a%d]+)')
168         if stacktype == "node" or stacktype == "craft" then
169                 local itemtype = nil
170                 local itemname = nil
171                 local itemcount = nil
172                 itemtype, itemname, itemcount = string.match(stackstring,
173                                 '([%a%d]+) "([^"]*)" (%d+)')
174                 itemcount = tonumber(itemcount)
175                 if itemcount == 0 then
176                         return '', nil
177                 elseif itemcount == 1 then
178                         return '', {type=itemtype, name=itemname}
179                 else
180                         return itemtype.." \""..itemname.."\" "..(itemcount-1),
181                                         {type=itemtype, name=itemname}
182                 end
183         elseif stacktype == "tool" then
184                 local itemtype = nil
185                 local itemname = nil
186                 local itemwear = nil
187                 itemtype, itemname, itemwear = string.match(stackstring,
188                                 '([%a%d]+) "([^"]*)" (%d+)')
189                 itemwear = tonumber(itemwear)
190                 return '', {type=itemtype, name=itemname, wear=itemwear}
191         end
192 end
193
194 function stackstring_put_item(stackstring, item)
195         if item == nil then
196                 return stackstring, false
197         end
198         stackstring = stackstring or ''
199         local stacktype = nil
200         stacktype = string.match(stackstring,
201                         '([%a%d]+)')
202         stacktype = stacktype or ''
203         if stacktype ~= '' and stacktype ~= item.type then
204                 return stackstring, false
205         end
206         if item.type == "node" or item.type == "craft" then
207                 local itemtype = nil
208                 local itemname = nil
209                 local itemcount = nil
210                 itemtype, itemname, itemcount = string.match(stackstring,
211                                 '([%a%d]+) "([^"]*)" (%d+)')
212                 itemtype = itemtype or item.type
213                 itemname = itemname or item.name
214                 if itemcount == nil then
215                         itemcount = 0
216                 end
217                 itemcount = itemcount + 1
218                 return itemtype.." \""..itemname.."\" "..itemcount, true
219         elseif item.type == "tool" then
220                 if stacktype ~= nil then
221                         return stackstring, false
222                 end
223                 local itemtype = nil
224                 local itemname = nil
225                 local itemwear = nil
226                 itemtype, itemname, itemwear = string.match(stackstring,
227                                 '([%a%d]+) "([^"]*)" (%d+)')
228                 itemwear = tonumber(itemwear)
229                 return itemtype.." \""..itemname.."\" "..itemwear, true
230         end
231         return stackstring, false
232 end
233
234 function stackstring_put_stackstring(stackstring, src)
235         while src ~= '' do
236                 --print("src="..dump(src))
237                 src, item = stackstring_take_item(src)
238                 --print("src="..dump(src).." item="..dump(item))
239                 local success
240                 stackstring, success = stackstring_put_item(stackstring, item)
241                 if not success then
242                         return stackstring, false
243                 end
244         end
245         return stackstring, true
246 end
247
248 function test_stackstring()
249         local stack
250         local item
251         local success
252
253         stack, item = stackstring_take_item('node "TNT" 3')
254         assert(stack == 'node "TNT" 2')
255         assert(item.type == 'node')
256         assert(item.name == 'TNT')
257
258         stack, item = stackstring_take_item('craft "with spaces" 2')
259         assert(stack == 'craft "with spaces" 1')
260         assert(item.type == 'craft')
261         assert(item.name == 'with spaces')
262
263         stack, item = stackstring_take_item('craft "with spaces" 1')
264         assert(stack == '')
265         assert(item.type == 'craft')
266         assert(item.name == 'with spaces')
267
268         stack, item = stackstring_take_item('craft "s8df2kj3" 0')
269         assert(stack == '')
270         assert(item == nil)
271
272         stack, item = stackstring_take_item('tool "With Spaces" 32487')
273         assert(stack == '')
274         assert(item.type == 'tool')
275         assert(item.name == 'With Spaces')
276         assert(item.wear == 32487)
277
278         stack, success = stackstring_put_item('node "With Spaces" 40',
279                         {type='node', name='With Spaces'})
280         assert(stack == 'node "With Spaces" 41')
281         assert(success == true)
282
283         stack, success = stackstring_put_item('craft "With Spaces" 40',
284                         {type='craft', name='With Spaces'})
285         assert(stack == 'craft "With Spaces" 41')
286         assert(success == true)
287
288         stack, success = stackstring_put_item('tool "With Spaces" 32487',
289                         {type='tool', name='With Spaces'})
290         assert(stack == 'tool "With Spaces" 32487')
291         assert(success == false)
292
293         stack, success = stackstring_put_item('node "With Spaces" 40',
294                         {type='tool', name='With Spaces'})
295         assert(stack == 'node "With Spaces" 40')
296         assert(success == false)
297         
298         assert(stackstring_put_stackstring('node "With Spaces" 2',
299                         'node "With Spaces" 1') == 'node "With Spaces" 3')
300 end
301 test_stackstring()
302
303 --
304 -- NodeItem helpers
305 --
306
307 minetest.inventorycube = function(img1, img2, img3)
308         img2 = img2 or img1
309         img3 = img3 or img1
310         return "[inventorycube"
311                         .. "{" .. img1:gsub("%^", "&")
312                         .. "{" .. img2:gsub("%^", "&")
313                         .. "{" .. img3:gsub("%^", "&")
314 end
315
316 --
317 -- CraftItem helpers
318 --
319
320 minetest.craftitem_place_item = function(item, placer, pos)
321         --print("craftitem_place_item")
322         --print("item: " .. dump(item))
323         --print("placer: " .. dump(placer))
324         --print("pos: " .. dump(pos))
325         minetest.env:add_item(pos, 'craft "' .. item .. '" 1')
326         return true
327 end
328
329 minetest.craftitem_eat = function(hp_change)
330         return function(item, user, pointed_thing)  -- closure
331                 --print("craftitem_eat(" .. hp_change .. ")")
332                 --print("item: " .. dump(item))
333                 --print("user: " .. dump(user))
334                 --print("pointed_thing: " .. dump(pointed_thing))
335                 user:set_hp(user:get_hp() + hp_change)
336                 return true
337         end
338 end
339
340 --
341 -- Default material types
342 --
343
344 function minetest.digprop_constanttime(time)
345         return {
346                 diggability = "constant",
347                 constant_time = time,
348         }
349 end
350
351 function minetest.digprop_stonelike(toughness)
352         return {
353                 diggablity = "normal",
354                 weight = toughness * 5,
355                 crackiness = 1,
356                 crumbliness = -0.1,
357                 cuttability = -0.2,
358         }
359 end
360
361 function minetest.digprop_dirtlike(toughness)
362         return {
363                 diggablity = "normal",
364                 weight = toughness * 1.2,
365                 crackiness = 0,
366                 crumbliness = 1.2,
367                 cuttability = -0.4,
368         }
369 end
370
371 function minetest.digprop_gravellike(toughness)
372         return {
373                 diggablity = "normal",
374                 weight = toughness * 2,
375                 crackiness = 0.2,
376                 crumbliness = 1.5,
377                 cuttability = -1.0,
378         }
379 end
380
381 function minetest.digprop_woodlike(toughness)
382         return {
383                 diggablity = "normal",
384                 weight = toughness * 1.0,
385                 crackiness = 0.75,
386                 crumbliness = -1.0,
387                 cuttability = 1.5,
388         }
389 end
390
391 function minetest.digprop_leaveslike(toughness)
392         return {
393                 diggablity = "normal",
394                 weight = toughness * (-0.5),
395                 crackiness = 0,
396                 crumbliness = 0,
397                 cuttability = 2.0,
398         }
399 end
400
401 function minetest.digprop_glasslike(toughness)
402         return {
403                 diggablity = "normal",
404                 weight = toughness * 0.1,
405                 crackiness = 2.0,
406                 crumbliness = -1.0,
407                 cuttability = -1.0,
408         }
409 end
410
411 --
412 -- Creative inventory
413 --
414
415 minetest.creative_inventory = {}
416
417 minetest.add_to_creative_inventory = function(itemstring)
418         table.insert(minetest.creative_inventory, itemstring)
419 end
420
421 --
422 -- Callback registration
423 --
424
425 function make_registration()
426         local t = {}
427         local registerfunc = function(func) table.insert(t, func) end
428         return t, registerfunc
429 end
430
431 minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
432 minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
433 minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
434 minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration()
435 minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
436 minetest.registered_on_generateds, minetest.register_on_generated = make_registration()
437 minetest.registered_on_newplayers, minetest.register_on_newplayer = make_registration()
438 minetest.registered_on_respawnplayers, minetest.register_on_respawnplayer = make_registration()
439
440 -- END