5f01d8b78815b4c979037e09d84ca12ec371c3d4
[oweals/minetest.git] / data / mods / experimental / init.lua
1 --
2 -- Experimental things
3 --
4
5 -- For testing random stuff
6
7 experimental = {}
8
9 function on_step(dtime)
10         -- print("experimental on_step")
11         --[[
12         objs = minetest.env:get_objects_inside_radius({x=0,y=0,z=0}, 10)
13         for k, obj in pairs(objs) do
14                 name = obj:get_player_name()
15                 if name then
16                         print(name.." at "..dump(obj:getpos()))
17                         print(name.." dir: "..dump(obj:get_look_dir()))
18                         print(name.." pitch: "..dump(obj:get_look_pitch()))
19                         print(name.." yaw: "..dump(obj:get_look_yaw()))
20                 else
21                         print("Some object at "..dump(obj:getpos()))
22                 end
23         end
24         --]]
25         --[[
26         if experimental.t1 == nil then
27                 experimental.t1 = 0
28         end
29         experimental.t1 = experimental.t1 + dtime
30         if experimental.t1 >= 2 then
31                 experimental.t1 = experimental.t1 - 2
32                 minetest.log("time of day is "..minetest.env:get_timeofday())
33                 if experimental.day then
34                         minetest.log("forcing day->night")
35                         experimental.day = false
36                         minetest.env:set_timeofday(0.0)
37                 else
38                         minetest.log("forcing night->day")
39                         experimental.day = true
40                         minetest.env:set_timeofday(0.5)
41                 end
42                 minetest.log("time of day is "..minetest.env:get_timeofday())
43         end
44         --]]
45 end
46 minetest.register_globalstep(on_step)
47
48 -- An example furnace-thing implemented in Lua
49
50 --[[
51 minetest.register_node("experimental:luafurnace", {
52         tile_images = {"default_lava.png", "default_furnace_side.png",
53                 "default_furnace_side.png", "default_furnace_side.png",
54                 "default_furnace_side.png", "default_furnace_front.png"},
55         --inventory_image = "furnace_front.png",
56         inventory_image = minetest.inventorycube("default_furnace_front.png"),
57         paramtype = "facedir_simple",
58         metadata_name = "generic",
59         material = minetest.digprop_stonelike(3.0),
60 })
61
62 minetest.register_on_placenode(function(pos, newnode, placer)
63         if newnode.name == "experimental:luafurnace" then
64                 local meta = minetest.env:get_meta(pos)
65                 meta:inventory_set_list("fuel", {""})
66                 meta:inventory_set_list("src", {""})
67                 meta:inventory_set_list("dst", {"","","",""})
68                 meta:set_inventory_draw_spec(
69                         "invsize[8,9;]"
70                         .."list[current_name;fuel;2,3;1,1;]"
71                         .."list[current_name;src;2,1;1,1;]"
72                         .."list[current_name;dst;5,1;2,2;]"
73                         .."list[current_player;main;0,5;8,4;]"
74                 )
75                 
76                 local total_cooked = 0;
77                 meta:set_string("total_cooked", total_cooked)
78                 meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
79         end
80 end)
81
82 minetest.register_abm({
83         nodenames = {"experimental:luafurnace"},
84         interval = 1.0,
85         chance = 1,
86         action = function(pos, node, active_object_count, active_object_count_wider)
87                 local meta = minetest.env:get_meta(pos)
88                 for i, name in ipairs({
89                                 "fuel_totaltime",
90                                 "fuel_time",
91                                 "src_totaltime",
92                                 "src_time"
93                 }) do
94                         if not meta:get_string(name) then
95                                 meta:set_string(name, 0)
96                         end
97                 end
98
99                 local inv = meta:get_inventory()
100                 
101                 local fuelitem = inv:get_stack("fuel", 1):peek_item()
102                 local srcitem = inv:get_stack("src", 1):peek_item()
103                 --print("fuelitem="..dump(fuelitem))
104                 --print("srcitem="..dump(srcitem))
105                 
106                 local was_active = false
107
108                 local src_cooktime = -1
109                 local result_stackstring = nil
110                 
111                 if srcitem then
112                         local prop = get_item_definition(srcitem)
113                         if prop and prop.cookresult_itemstring ~= "" then
114                                 result_stackstring = prop.cookresult_itemstring
115                                 src_cooktime = prop.furnace_cooktime or 3
116                         end
117                 end
118
119                 print("src_cooktime="..dump(src_cooktime))
120                 print("result_stackstring="..dump(result_stackstring))
121
122                 if tonumber(meta:get_string("fuel_time")) < tonumber(meta:get_string("fuel_totaltime")) then
123                         was_active = true
124                         meta:set_string("fuel_time", tonumber(meta:get_string("fuel_time")) + 1)
125                         meta:set_string("src_time", tonumber(meta:get_string("src_time")) + 1)
126                         --print("result_stackstring="..dump(result_stackstring))
127                         --print('tonumber(meta:get_string("src_time"))='..dump(tonumber(meta:get_string("src_time"))))
128                         --print("src_cooktime="..dump(src_cooktime))
129                         if result_stackstring and tonumber(meta:get_string("src_time")) >= src_cooktime and src_cooktime >= 0 then
130                                 -- Put result in "dst" list
131                                 success = inv:autoinsert_stackstring("dst", result_stackstring)
132                                 if not success then
133                                         print("Could not autoinsert '"..result_stackstring.."'")
134                                 end
135                                 -- If succeeded, take stuff from "src" list
136                                 if success then
137                                         srcstack = inv:get_stack("src", 1)
138                                         srcstack:take_item()
139                                         inv:set_stack("src", 1, srcstack)
140                                 end
141                                 meta:set_string("src_time", 0)
142                         end
143                 end
144                 
145                 if tonumber(meta:get_string("fuel_time")) < tonumber(meta:get_string("fuel_totaltime")) then
146                         meta:set_infotext("Furnace active: "..(tonumber(meta:get_string("fuel_time"))/tonumber(meta:get_string("fuel_totaltime"))*100).."%")
147                         return
148                 end
149
150                 local srcitem = inv:get_stack("src", 1):peek_item()
151
152                 local src_cooktime = 0
153                 local result_stackstring = nil
154                 
155                 if srcitem then
156                         local prop = get_item_definition(srcitem)
157                         if prop and prop.cookresult_itemstring ~= "" then
158                                 result_stackstring = prop.cookresult_itemstring
159                                 src_cooktime = prop.furnace_cooktime or 3
160                         end
161                 end
162
163                 local fuelitem = inv:get_stack("fuel", 1):peek_item()
164
165                 if not result_stackstring or not fuelitem then
166                         if was_active then
167                                 meta:set_infotext("Furnace is empty")
168                         end
169                         return
170                 end
171
172                 local burntime = -1
173                 if fuelitem then
174                         local prop = get_item_definition(fuelitem)
175                         if prop then
176                                 burntime = prop.furnace_burntime or -1
177                         end
178                 end
179
180                 if burntime <= 0 then
181                         meta:set_infotext("Furnace out of fuel")
182                         return
183                 end
184
185                 meta:set_string("fuel_totaltime", burntime)
186                 meta:set_string("fuel_time", 0)
187                 
188                 local stack = inv:get_stack("fuel", 1)
189                 stack:take_item()
190                 inv:set_stack("fuel", 1, stack)
191         end,
192 })
193 minetest.register_abm({
194         nodenames = {"experimental:luafurnace"},
195         interval = 1.0,
196         chance = 1,
197         action = function(pos, node, active_object_count, active_object_count_wider)
198                 local meta = minetest.env:get_meta(pos)
199                 local fuellist = meta:inventory_get_list("fuel")
200                 local srclist = meta:inventory_get_list("src")
201                 local dstlist = meta:inventory_get_list("dst")
202                 if fuellist == nil or srclist == nil or dstlist == nil then
203                         return
204                 end
205                 _, srcitem = stackstring_take_item(srclist[1])
206                 _, fuelitem = stackstring_take_item(fuellist[1])
207                 if not srcitem or not fuelitem then return end
208                 if fuelitem.type == "node" then
209                         local prop = minetest.registered_nodes[fuelitem.name]
210                         if prop == nil then return end
211                         if prop.furnace_burntime < 0 then return end
212                 else
213                         return
214                 end
215                 local resultstack = nil
216                 if srcitem.type == "node" then
217                         local prop = minetest.registered_nodes[srcitem.name]
218                         if prop == nil then return end
219                         if prop.cookresult_item == "" then return end
220                         resultstack = prop.cookresult_item
221                 else
222                         return
223                 end
224
225                 if resultstack == nil then
226                         return
227                 end
228
229                 dstlist[1], success = stackstring_put_stackstring(dstlist[1], resultstack)
230                 if not success then
231                         return
232                 end
233
234                 fuellist[1], _ = stackstring_take_item(fuellist[1])
235                 srclist[1], _ = stackstring_take_item(srclist[1])
236
237                 meta:inventory_set_list("fuel", fuellist)
238                 meta:inventory_set_list("src", srclist)
239                 meta:inventory_set_list("dst", dstlist)
240
241                 local total_cooked = meta:get_string("total_cooked")
242                 total_cooked = tonumber(total_cooked) + 1
243                 meta:set_string("total_cooked", total_cooked)
244                 meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
245         end,
246 })
247 minetest.register_craft({
248         output = 'node "experimental:luafurnace" 1',
249         recipe = {
250                 {'node "default:cobble"', 'node "default:cobble"', 'node "default:cobble"'},
251                 {'node "default:cobble"', 'node "default:steel_ingot"', 'node "default:cobble"'},
252                 {'node "default:cobble"', 'node "default:cobble"', 'node "default:cobble"'},
253         }
254 })
255 --]]
256
257 --
258 -- Random stuff
259 --
260
261 --[[
262 minetest.register_tool("experimental:horribletool", {
263         image = "default_lava.png",
264         basetime = 2.0
265         dt_weight = 0.2
266         dt_crackiness = 0.2
267         dt_crumbliness = 0.2
268         dt_cuttability = 0.2
269         basedurability = 50
270         dd_weight = -5
271         dd_crackiness = -5
272         dd_crumbliness = -5
273         dd_cuttability = -5
274 })
275 --]]
276
277 --
278 -- TNT (not functional)
279 --
280
281 minetest.register_craft({
282         output = 'experimental:tnt',
283         recipe = {
284                 {'default:wood'},
285                 {'default:coal_lump'},
286                 {'default:wood'}
287         }
288 })
289
290 minetest.register_node("experimental:tnt", {
291         tile_images = {"default_tnt_top.png", "default_tnt_bottom.png",
292                         "default_tnt_side.png", "default_tnt_side.png",
293                         "default_tnt_side.png", "default_tnt_side.png"},
294         inventory_image = minetest.inventorycube("default_tnt_top.png",
295                         "default_tnt_side.png", "default_tnt_side.png"),
296         drop = '', -- Get nothing
297         material = {
298                 diggability = "not",
299         },
300 })
301
302 minetest.register_on_punchnode(function(p, node)
303         if node.name == "experimental:tnt" then
304                 minetest.env:remove_node(p)
305                 minetest.env:add_entity(p, "experimental:tnt")
306                 nodeupdate(p)
307         end
308 end)
309
310 local TNT = {
311         -- Static definition
312         physical = true, -- Collides with things
313         -- weight = 5,
314         collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
315         visual = "cube",
316         textures = {"default_tnt_top.png", "default_tnt_bottom.png",
317                         "default_tnt_side.png", "default_tnt_side.png",
318                         "default_tnt_side.png", "default_tnt_side.png"},
319         -- Initial value for our timer
320         timer = 0,
321         -- Number of punches required to defuse
322         health = 1,
323         blinktimer = 0,
324         blinkstatus = true,
325 }
326
327 -- Called when a TNT object is created
328 function TNT:on_activate(staticdata)
329         print("TNT:on_activate()")
330         self.object:setvelocity({x=0, y=4, z=0})
331         self.object:setacceleration({x=0, y=-10, z=0})
332         self.object:settexturemod("^[brighten")
333         self.object:set_armor_groups({immortal=1})
334 end
335
336 -- Called periodically
337 function TNT:on_step(dtime)
338         --print("TNT:on_step()")
339         self.timer = self.timer + dtime
340         self.blinktimer = self.blinktimer + dtime
341         if self.blinktimer > 0.5 then
342                 self.blinktimer = self.blinktimer - 0.5
343                 if self.blinkstatus then
344                         self.object:settexturemod("")
345                 else
346                         self.object:settexturemod("^[brighten")
347                 end
348                 self.blinkstatus = not self.blinkstatus
349         end
350 end
351
352 -- Called when object is punched
353 function TNT:on_punch(hitter)
354         print("TNT:on_punch()")
355         self.health = self.health - 1
356         if self.health <= 0 then
357                 self.object:remove()
358                 hitter:get_inventory():add_item("main", "experimental:tnt")
359                 --hitter:set_hp(hitter:get_hp() - 1)
360         end
361 end
362
363 -- Called when object is right-clicked
364 function TNT:on_rightclick(clicker)
365         --pos = self.object:getpos()
366         --pos = {x=pos.x, y=pos.y+0.1, z=pos.z}
367         --self.object:moveto(pos, false)
368 end
369
370 --print("TNT dump: "..dump(TNT))
371 --print("Registering TNT");
372 minetest.register_entity("experimental:tnt", TNT)
373
374 -- Add TNT's old name also
375 minetest.register_alias("TNT", "experimental:tnt")
376
377 --
378 -- A test entity for testing animated and yaw-modulated sprites
379 --
380
381 minetest.register_entity("experimental:testentity", {
382         -- Static definition
383         physical = true, -- Collides with things
384         -- weight = 5,
385         collisionbox = {-0.7,-1.35,-0.7, 0.7,1.0,0.7},
386         --collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
387         visual = "sprite",
388         visual_size = {x=2, y=3},
389         textures = {"dungeon_master.png^[makealpha:128,0,0^[makealpha:128,128,0"},
390         spritediv = {x=6, y=5},
391         initial_sprite_basepos = {x=0, y=0},
392
393         on_activate = function(self, staticdata)
394                 print("testentity.on_activate")
395                 self.object:setsprite({x=0,y=0}, 1, 0, true)
396                 --self.object:setsprite({x=0,y=0}, 4, 0.3, true)
397
398                 -- Set gravity
399                 self.object:setacceleration({x=0, y=-10, z=0})
400                 -- Jump a bit upwards
401                 self.object:setvelocity({x=0, y=10, z=0})
402         end,
403
404         on_punch = function(self, hitter)
405                 self.object:remove()
406                 hitter:add_to_inventory('craft testobject1 1')
407         end,
408 })
409
410 --
411 -- More random stuff
412 --
413
414 minetest.register_on_respawnplayer(function(player)
415         print("on_respawnplayer")
416         -- player:setpos({x=0, y=30, z=0})
417         -- return true
418 end)
419
420 minetest.register_on_generated(function(minp, maxp)
421         --print("on_generated: minp="..dump(minp).." maxp="..dump(maxp))
422         --cp = {x=(minp.x+maxp.x)/2, y=(minp.y+maxp.y)/2, z=(minp.z+maxp.z)/2}
423         --minetest.env:add_node(cp, {name="sand"})
424 end)
425
426 -- Example setting get
427 --print("setting max_users = " .. dump(minetest.setting_get("max_users")))
428 --print("setting asdf = " .. dump(minetest.setting_get("asdf")))
429
430 minetest.register_on_chat_message(function(name, message)
431         --[[print("on_chat_message: name="..dump(name).." message="..dump(message))
432         local cmd = "/testcommand"
433         if message:sub(0, #cmd) == cmd then
434                 print(cmd.." invoked")
435                 return true
436         end
437         local cmd = "/help"
438         if message:sub(0, #cmd) == cmd then
439                 print("script-overridden help command")
440                 minetest.chat_send_all("script-overridden help command")
441                 return true
442         end]]
443 end)
444
445 -- Grow papyrus on TNT every 10 seconds
446 --[[minetest.register_abm({
447         nodenames = {"TNT"},
448         interval = 10.0,
449         chance = 1,
450         action = function(pos, node, active_object_count, active_object_count_wider)
451                 print("TNT ABM action")
452                 pos.y = pos.y + 1
453                 minetest.env:add_node(pos, {name="papyrus"})
454         end,
455 })]]
456
457 -- Replace texts of alls signs with "foo" every 10 seconds
458 --[[minetest.register_abm({
459         nodenames = {"sign_wall"},
460         interval = 10.0,
461         chance = 1,
462         action = function(pos, node, active_object_count, active_object_count_wider)
463                 print("ABM: Sign text changed")
464                 local meta = minetest.env:get_meta(pos)
465                 meta:set_text("foo")
466         end,
467 })]]
468
469 --[[local ncpos = nil
470 local ncq = 1
471 local ncstuff = {
472     {2, 1, 0, 3}, {3, 0, 1, 2}, {4, -1, 0, 1}, {5, -1, 0, 1}, {6, 0, -1, 0},
473     {7, 0, -1, 0}, {8, 1, 0, 3}, {9, 1, 0, 3}, {10, 1, 0, 3}, {11, 0, 1, 2},
474     {12, 0, 1, 2}, {13, 0, 1, 2}, {14, -1, 0, 1}, {15, -1, 0, 1}, {16, -1, 0, 1},
475     {17, -1, 0, 1}, {18, 0, -1, 0}, {19, 0, -1, 0}, {20, 0, -1, 0}, {21, 0, -1, 0},
476     {22, 1, 0, 3}, {23, 1, 0, 3}, {24, 1, 0, 3}, {25, 1, 0, 3}, {10, 0, 1, 2}
477 }
478 local ncold = {}
479 local nctime = nil
480
481 minetest.register_abm({
482     nodenames = {"dirt_with_grass"},
483     interval = 100000.0,
484     chance = 1,
485     action = function(pos, node, active_object_count, active_object_count_wider)
486         if ncpos ~= nil then
487             return
488         end
489        
490         if pos.x % 16 ~= 8 or pos.z % 16 ~= 8 then
491             return
492         end
493        
494         pos.y = pos.y + 1
495         n = minetest.env:get_node(pos)
496         print(dump(n))
497         if n.name ~= "air" then
498             return
499         end
500
501         pos.y = pos.y + 2
502         ncpos = pos
503         nctime = os.clock()
504         minetest.env:add_node(ncpos, {name="nyancat"})
505     end
506 })
507
508 minetest.register_abm({
509     nodenames = {"nyancat"},
510     interval = 1.0,
511     chance = 1,
512     action = function(pos, node, active_object_count, active_object_count_wider)
513         if ncpos == nil then
514             return
515         end
516         if pos.x == ncpos.x and pos.y == ncpos.y and pos.z == ncpos.z then
517             clock = os.clock()
518             if clock - nctime < 0.1 then
519                 return
520             end
521             nctime = clock
522            
523             s0 = ncstuff[ncq]
524             ncq = s0[1]
525             s1 = ncstuff[ncq]
526             p0 = pos
527             p1 = {x = p0.x + s0[2], y = p0.y, z = p0.z + s0[3]}
528             p2 = {x = p1.x + s1[2], y = p1.y, z = p1.z + s1[3]}
529             table.insert(ncold, 1, p0)
530             while #ncold >= 10 do
531                 minetest.env:add_node(ncold[#ncold], {name="air"})
532                 table.remove(ncold, #ncold)
533             end
534             minetest.env:add_node(p0, {name="nyancat_rainbow"})
535             minetest.env:add_node(p1, {name="nyancat", param1=s0[4]})
536             minetest.env:add_node(p2, {name="air"})
537             ncpos = p1
538         end
539     end,
540 })--]]
541
542 print("experimental modname="..dump(minetest.get_current_modname()))
543 print("experimental modpath="..dump(minetest.get_modpath("experimental")))
544 print("experimental worldpath="..dump(minetest.get_worldpath()))
545
546 -- END