PyuTest.util = { tablecopy = function(t) if t == nil then return nil end local t2 = {} for k,v in pairs(t) do t2[k] = v end return t2 end, tableconcat = function (t1, t2) local nt = PyuTest.util.tablecopy(t1) for k, v in pairs(t2) do nt[k] = v end return nt end, tableconcat2 = function(t1, t2) local nt = PyuTest.util.tablecopy(t1) for i = 1, #t2 do nt[#nt+i] = t2[i] end return nt end, } PyuTest.dorange = function(origin, range, action) for dx = -range, range do for dz = -range, range do for dy = -range, range do action(vector.new(origin.x + dx, origin.y + dy, origin.z + dz)) end end end end PyuTest.get_full_neighbours = function(pos) return { vector.new(pos.x + 1, pos.y, pos.z), vector.new(pos.x - 1, pos.y, pos.z), vector.new(pos.x + 1, pos.y + 1, pos.z), vector.new(pos.x + 1, pos.y - 1, pos.z), vector.new(pos.x - 1, pos.y - 1, pos.z), vector.new(pos.x - 1, pos.y + 1, pos.z), vector.new(pos.x, pos.y, pos.z + 1), vector.new(pos.x, pos.y, pos.z - 1), vector.new(pos.x, pos.y + 1, pos.z + 1), vector.new(pos.x, pos.y - 1, pos.z + 1), vector.new(pos.x, pos.y + 1, pos.z - 1), vector.new(pos.x, pos.y - 1, pos.z - 1), vector.new(pos.x, pos.y + 1, pos.z), vector.new(pos.x, pos.y - 1, pos.z), } end PyuTest.node_beside_node = function(pos, name) local n = { pos + vector.new(1, 0, 0), pos - vector.new(1, 0, 0), pos + vector.new(0, 0, 1), pos - vector.new(0, 0, 1), } for _, v in pairs(n) do local node = minetest.get_node(v) if node.name == name then return true end end return false end PyuTest.node_beside_group = function(pos, group) local n = { pos + vector.new(1, 0, 0), pos - vector.new(1, 0, 0), pos + vector.new(0, 0, 1), pos - vector.new(0, 0, 1), } for _, v in pairs(n) do local node = minetest.get_node(v) if minetest.get_item_group(node.name, group) ~= 0 then return true end end return false end PyuTest.create_explosion = function (pos, range, rm_pos, dmg, damage_whitelist) if rm_pos then minetest.remove_node(pos) end PyuTest.dorange(pos, range, function(p) if minetest.get_node(p).name == "pyutest_blocks:tnt" then minetest.after(0.8, function() minetest.remove_node(p) PyuTest.create_explosion(p, range, rm_pos, dmg) end) else minetest.dig_node(p) end end) for _, v in pairs(minetest.get_objects_inside_radius(pos, range)) do local function damage() v:punch(v, nil, { damage_groups = {fleshy = dmg} }, nil) PyuTest.deal_damage(v, dmg, PyuTest.DAMAGE_TYPES.explosion(range)) end if damage_whitelist ~= nil then local unsafe = true for _, v2 in pairs(damage_whitelist) do if v == v2 then unsafe = false break end end if unsafe then damage() end else damage() end end local r = range local minpos = {x = pos.x - r, y = pos.y - r, z = pos.z - r} local maxpos = {x = pos.x + r, y = pos.y + r, z = pos.z + r} minetest.add_particlespawner({ amount = range * 8, time = 0.4, minexptime = 0.4, maxexptime = 1.4, minsize = 16, maxsize = 32, vertical = false, glow = 8, collisiondetection = false, texture = "pyutest-blast.png", minpos = minpos, maxpos = maxpos, minvel = vector.new(-1, -1, 1), maxvel = vector.new(1, 1, 1), }) minetest.add_particlespawner({ amount = range * 18, time = 0.4, minexptime = 0.4, maxexptime = 1.4, minsize = 1, maxsize = 2, vertical = false, glow = 4, collisiondetection = false, texture = "pyutest-blast2.png", minpos = minpos, maxpos = maxpos, minvel = vector.new(-6, -6, -6), maxvel = vector.new( 6, 6, 6), }) minetest.add_particlespawner({ amount = range * 18, time = 0.4, minexptime = 0.4, maxexptime = 1.4, minsize = 1, maxsize = 2, vertical = false, glow = 4, collisiondetection = false, texture = "pyutest-blast3.png", minpos = minpos, maxpos = maxpos, minvel = vector.new(-6, -6, -6), maxvel = vector.new( 6, 6, 6), }) minetest.sound_play("block_break", { pos = pos, gain = 2.5 }) end PyuTest.tool_caps = function(options) local default_uses = 100 local groupcaps = {} for k, v in pairs(options.groupcaps or {}) do groupcaps[k] = { maxlevel = v.maxlevel or options.maxlevel, times = v.times or { [PyuTest.BLOCK_FAST] = options.time or 3, [PyuTest.BLOCK_NORMAL] = options.time or 3, [PyuTest.BLOCK_SLOW] = options.time or 3 }, uses = v.uses or options.uses or default_uses } end return { groupcaps = groupcaps, punch_attack_uses = options.attack_uses, damage_groups = options.damage_groups or {fleshy=3}, full_punch_interval = options.full_punch_interval } end -- https://github.com/minetest/minetest_game/blob/master/mods/stairs/init.lua#L27 PyuTest.rotate_and_place = function(itemstack, placer, pointed_thing) local p0 = pointed_thing.under local p1 = pointed_thing.above local param2 = 0 if placer then local placer_pos = placer:get_pos() if placer_pos then local diff = vector.subtract(p1, placer_pos) param2 = minetest.dir_to_facedir(diff) -- The player places a node on the side face of the node he is standing on if p0.y == p1.y and math.abs(diff.x) <= 0.5 and math.abs(diff.z) <= 0.5 and diff.y < 0 then -- reverse node direction param2 = (param2 + 2) % 4 end end local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing) local fpos = finepos.y % 1 if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5) or (fpos < -0.5 and fpos > -0.999999999) then param2 = param2 + 20 if param2 == 21 then param2 = 23 elseif param2 == 23 then param2 = 21 end end end return minetest.item_place(itemstack, placer, pointed_thing, param2) end PyuTest.register_interval = function(fn, time) local first_run = true local function interval() if first_run then first_run = false else fn() end minetest.after(time, fn) end interval() end PyuTest.give_item_or_drop = function(stack, inventory, listname, pos) local leftover = inventory:add_item(listname, stack) if leftover then minetest.add_item(pos, leftover) end end PyuTest.get_biome_def = function(pos) local data = minetest.get_biome_data(pos) if not data then return end return minetest.registered_biomes[minetest.get_biome_name(data.biome)] end -- https://github.com/minetest/minetest_game/blob/master/mods/default/functions.lua#L184 function PyuTest.get_inventory_drops(pos, inventory, drops) local inv = minetest.get_meta(pos):get_inventory() local n = #drops for i = 1, inv:get_size(inventory) do local stack = inv:get_stack(inventory, i) if stack:get_count() > 0 then drops[n + 1] = stack:to_table() n = n + 1 end end end PyuTest.drop_item = function (pos, name) local o = minetest.add_item(pos, name) if o then o:add_velocity(vector.new(math.random(-2, 2), 5, math.random(-2, 2))) end end