2013-05-19 18:43:04 +02:00
|
|
|
-- mods/default/functions.lua
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Sounds
|
|
|
|
--
|
|
|
|
|
|
|
|
function default.node_sound_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "", gain = 1.0}
|
2013-05-19 18:43:04 +02:00
|
|
|
table.dug = table.dug or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_dug_node", gain = 0.25}
|
2013-05-19 18:43:04 +02:00
|
|
|
table.place = table.place or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_place_node_hard", gain = 1.0}
|
2013-05-19 18:43:04 +02:00
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
|
|
|
function default.node_sound_stone_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_hard_footstep", gain = 0.5}
|
2013-06-13 16:30:33 +02:00
|
|
|
table.dug = table.dug or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_hard_footstep", gain = 1.0}
|
2013-05-19 18:43:04 +02:00
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
|
|
|
function default.node_sound_dirt_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_dirt_footstep", gain = 1.0}
|
2013-06-13 16:30:33 +02:00
|
|
|
table.dug = table.dug or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_dirt_footstep", gain = 1.5}
|
2013-06-11 23:23:10 +02:00
|
|
|
table.place = table.place or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_place_node", gain = 1.0}
|
2013-05-19 18:43:04 +02:00
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
|
|
|
function default.node_sound_sand_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2016-03-24 04:00:43 +01:00
|
|
|
{name = "default_sand_footstep", gain = 0.12}
|
2013-05-19 18:43:04 +02:00
|
|
|
table.dug = table.dug or
|
2016-03-24 04:00:43 +01:00
|
|
|
{name = "default_sand_footstep", gain = 0.24}
|
2013-06-11 23:23:10 +02:00
|
|
|
table.place = table.place or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_place_node", gain = 1.0}
|
2013-05-19 18:43:04 +02:00
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
2016-04-25 00:10:46 +02:00
|
|
|
function default.node_sound_gravel_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
|
|
|
{name = "default_gravel_footstep", gain = 0.5}
|
|
|
|
table.dug = table.dug or
|
|
|
|
{name = "default_gravel_footstep", gain = 1.0}
|
|
|
|
table.place = table.place or
|
|
|
|
{name = "default_place_node", gain = 1.0}
|
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
2013-05-19 18:43:04 +02:00
|
|
|
function default.node_sound_wood_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_wood_footstep", gain = 0.5}
|
2013-06-13 16:30:33 +02:00
|
|
|
table.dug = table.dug or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_wood_footstep", gain = 1.0}
|
2013-05-19 18:43:04 +02:00
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
|
|
|
function default.node_sound_leaves_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_grass_footstep", gain = 0.35}
|
2013-06-13 16:30:33 +02:00
|
|
|
table.dug = table.dug or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_grass_footstep", gain = 0.7}
|
2013-05-19 18:43:04 +02:00
|
|
|
table.dig = table.dig or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_dig_crumbly", gain = 0.4}
|
2013-06-11 23:23:10 +02:00
|
|
|
table.place = table.place or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_place_node", gain = 1.0}
|
2013-05-19 18:43:04 +02:00
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
|
|
|
function default.node_sound_glass_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_glass_footstep", gain = 0.5}
|
2013-05-19 18:43:04 +02:00
|
|
|
table.dug = table.dug or
|
2015-06-07 23:48:26 +02:00
|
|
|
{name = "default_break_glass", gain = 1.0}
|
2013-05-19 18:43:04 +02:00
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
2014-08-26 13:55:53 +02:00
|
|
|
|
2013-05-19 18:43:04 +02:00
|
|
|
--
|
|
|
|
-- Lavacooling
|
|
|
|
--
|
|
|
|
|
2016-02-13 09:33:58 +01:00
|
|
|
default.cool_lava = function(pos, node)
|
|
|
|
if node.name == "default:lava_source" then
|
|
|
|
minetest.set_node(pos, {name = "default:obsidian"})
|
|
|
|
else -- Lava flowing
|
|
|
|
minetest.set_node(pos, {name = "default:stone"})
|
|
|
|
end
|
2015-08-02 06:16:01 +02:00
|
|
|
minetest.sound_play("default_cool_lava",
|
|
|
|
{pos = pos, max_hear_distance = 16, gain = 0.25})
|
2013-05-19 18:43:04 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
minetest.register_abm({
|
2016-08-08 11:56:13 +02:00
|
|
|
label = "Lava cooling",
|
2016-02-13 09:33:58 +01:00
|
|
|
nodenames = {"default:lava_source", "default:lava_flowing"},
|
2013-05-19 18:43:04 +02:00
|
|
|
neighbors = {"group:water"},
|
|
|
|
interval = 1,
|
2016-02-13 09:33:58 +01:00
|
|
|
chance = 1,
|
2015-11-05 02:17:13 +01:00
|
|
|
catch_up = false,
|
2014-08-26 13:55:53 +02:00
|
|
|
action = function(...)
|
2016-02-13 09:33:58 +01:00
|
|
|
default.cool_lava(...)
|
2013-05-19 18:43:04 +02:00
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
2014-08-26 13:55:53 +02:00
|
|
|
|
2016-04-16 04:21:45 +02:00
|
|
|
--
|
|
|
|
-- optimized helper to put all items in an inventory into a drops list
|
|
|
|
--
|
|
|
|
function default.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
|
|
|
|
|
2013-05-19 18:43:04 +02:00
|
|
|
--
|
|
|
|
-- Papyrus and cactus growing
|
|
|
|
--
|
|
|
|
|
2015-06-07 23:48:26 +02:00
|
|
|
-- wrapping the functions in abm action is necessary to make overriding them possible
|
|
|
|
|
2014-08-26 13:55:53 +02:00
|
|
|
function default.grow_cactus(pos, node)
|
2015-06-07 04:31:23 +02:00
|
|
|
if node.param2 >= 4 then
|
2014-08-26 13:55:53 +02:00
|
|
|
return
|
|
|
|
end
|
2015-06-07 23:48:26 +02:00
|
|
|
pos.y = pos.y - 1
|
2014-08-26 13:55:53 +02:00
|
|
|
if minetest.get_item_group(minetest.get_node(pos).name, "sand") == 0 then
|
|
|
|
return
|
|
|
|
end
|
2015-06-07 23:48:26 +02:00
|
|
|
pos.y = pos.y + 1
|
2014-08-26 13:55:53 +02:00
|
|
|
local height = 0
|
2015-06-07 23:48:26 +02:00
|
|
|
while node.name == "default:cactus" and height < 4 do
|
|
|
|
height = height + 1
|
|
|
|
pos.y = pos.y + 1
|
2014-08-26 13:55:53 +02:00
|
|
|
node = minetest.get_node(pos)
|
|
|
|
end
|
2015-06-07 23:48:26 +02:00
|
|
|
if height == 4 or node.name ~= "air" then
|
2014-08-26 13:55:53 +02:00
|
|
|
return
|
|
|
|
end
|
2015-06-07 23:48:26 +02:00
|
|
|
minetest.set_node(pos, {name = "default:cactus"})
|
2014-08-26 13:55:53 +02:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function default.grow_papyrus(pos, node)
|
2015-06-07 23:48:26 +02:00
|
|
|
pos.y = pos.y - 1
|
2014-08-26 13:55:53 +02:00
|
|
|
local name = minetest.get_node(pos).name
|
2015-10-05 02:25:23 +02:00
|
|
|
if name ~= "default:dirt_with_grass" and name ~= "default:dirt" then
|
2014-08-26 13:55:53 +02:00
|
|
|
return
|
|
|
|
end
|
|
|
|
if not minetest.find_node_near(pos, 3, {"group:water"}) then
|
|
|
|
return
|
|
|
|
end
|
2015-06-07 23:48:26 +02:00
|
|
|
pos.y = pos.y + 1
|
2014-08-26 13:55:53 +02:00
|
|
|
local height = 0
|
|
|
|
while node.name == "default:papyrus" and height < 4 do
|
2015-06-07 23:48:26 +02:00
|
|
|
height = height + 1
|
|
|
|
pos.y = pos.y + 1
|
2014-08-26 13:55:53 +02:00
|
|
|
node = minetest.get_node(pos)
|
|
|
|
end
|
2015-06-07 23:48:26 +02:00
|
|
|
if height == 4 or node.name ~= "air" then
|
2014-08-26 13:55:53 +02:00
|
|
|
return
|
|
|
|
end
|
2015-06-07 23:48:26 +02:00
|
|
|
minetest.set_node(pos, {name = "default:papyrus"})
|
2014-08-26 13:55:53 +02:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2013-05-19 18:43:04 +02:00
|
|
|
minetest.register_abm({
|
2016-08-08 11:56:13 +02:00
|
|
|
label = "Grow cactus",
|
2013-05-19 18:43:04 +02:00
|
|
|
nodenames = {"default:cactus"},
|
|
|
|
neighbors = {"group:sand"},
|
2016-02-13 09:33:58 +01:00
|
|
|
interval = 12,
|
|
|
|
chance = 83,
|
2014-08-26 13:55:53 +02:00
|
|
|
action = function(...)
|
|
|
|
default.grow_cactus(...)
|
|
|
|
end
|
2013-05-19 18:43:04 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
minetest.register_abm({
|
2016-08-08 11:56:13 +02:00
|
|
|
label = "Grow papyrus",
|
2013-05-19 18:43:04 +02:00
|
|
|
nodenames = {"default:papyrus"},
|
2016-02-13 09:33:58 +01:00
|
|
|
neighbors = {"default:dirt", "default:dirt_with_grass"},
|
|
|
|
interval = 14,
|
|
|
|
chance = 71,
|
2014-08-26 13:55:53 +02:00
|
|
|
action = function(...)
|
|
|
|
default.grow_papyrus(...)
|
|
|
|
end
|
2013-05-19 18:43:04 +02:00
|
|
|
})
|
|
|
|
|
2014-08-26 13:55:53 +02:00
|
|
|
|
2013-05-19 18:43:04 +02:00
|
|
|
--
|
2013-12-02 19:23:29 +01:00
|
|
|
-- dig upwards
|
|
|
|
--
|
|
|
|
|
|
|
|
function default.dig_up(pos, node, digger)
|
|
|
|
if digger == nil then return end
|
|
|
|
local np = {x = pos.x, y = pos.y + 1, z = pos.z}
|
|
|
|
local nn = minetest.get_node(np)
|
|
|
|
if nn.name == node.name then
|
|
|
|
minetest.node_dig(np, nn, digger)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-08-26 13:55:53 +02:00
|
|
|
|
Create API for fence.register, and use it.
This converts the call to minetest.register() for the default
fence node, so it can be called by other mods to quickly
setup other fences.
Since this creates an API, insert it into the game_api.txt.
The api looks like minetest.register(name, {def}), and has two
uncommon fields: "texture" and "material". Any normal nodedef
property can be passed through, except "drawtype". The "fence"
group will always be added.
The default fence recipe is modified to be as follows:
wood, stick, wood
wood, stick, wood
This recipe yields 4 fence nodes.
This allows us to create according recipes for acacia, pine,
aspen, and junglewood fences without adding new stick types:
pine wood, stick, pine wood
pine wood, stick, pine wood
This is a from-scratch implementation, written by heart but inspired
by (#665 - Add many wooden fences).
Stick and fences nodes are named in a consistent way.
2015-12-15 06:49:20 +01:00
|
|
|
--
|
|
|
|
-- Fence registration helper
|
|
|
|
--
|
|
|
|
function default.register_fence(name, def)
|
|
|
|
minetest.register_craft({
|
|
|
|
output = name .. " 4",
|
|
|
|
recipe = {
|
|
|
|
{ def.material, 'group:stick', def.material },
|
|
|
|
{ def.material, 'group:stick', def.material },
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
local fence_texture = "default_fence_overlay.png^" .. def.texture ..
|
|
|
|
"^default_fence_overlay.png^[makealpha:255,126,126"
|
|
|
|
-- Allow almost everything to be overridden
|
|
|
|
local default_fields = {
|
|
|
|
paramtype = "light",
|
2015-12-15 06:49:20 +01:00
|
|
|
drawtype = "nodebox",
|
|
|
|
node_box = {
|
|
|
|
type = "connected",
|
|
|
|
fixed = {{-1/8, -1/2, -1/8, 1/8, 1/2, 1/8}},
|
|
|
|
-- connect_top =
|
|
|
|
-- connect_bottom =
|
|
|
|
connect_front = {{-1/16,3/16,-1/2,1/16,5/16,-1/8},
|
|
|
|
{-1/16,-5/16,-1/2,1/16,-3/16,-1/8}},
|
|
|
|
connect_left = {{-1/2,3/16,-1/16,-1/8,5/16,1/16},
|
|
|
|
{-1/2,-5/16,-1/16,-1/8,-3/16,1/16}},
|
|
|
|
connect_back = {{-1/16,3/16,1/8,1/16,5/16,1/2},
|
|
|
|
{-1/16,-5/16,1/8,1/16,-3/16,1/2}},
|
|
|
|
connect_right = {{1/8,3/16,-1/16,1/2,5/16,1/16},
|
|
|
|
{1/8,-5/16,-1/16,1/2,-3/16,1/16}},
|
|
|
|
},
|
|
|
|
connects_to = {"group:fence", "group:wood", "group:tree"},
|
Create API for fence.register, and use it.
This converts the call to minetest.register() for the default
fence node, so it can be called by other mods to quickly
setup other fences.
Since this creates an API, insert it into the game_api.txt.
The api looks like minetest.register(name, {def}), and has two
uncommon fields: "texture" and "material". Any normal nodedef
property can be passed through, except "drawtype". The "fence"
group will always be added.
The default fence recipe is modified to be as follows:
wood, stick, wood
wood, stick, wood
This recipe yields 4 fence nodes.
This allows us to create according recipes for acacia, pine,
aspen, and junglewood fences without adding new stick types:
pine wood, stick, pine wood
pine wood, stick, pine wood
This is a from-scratch implementation, written by heart but inspired
by (#665 - Add many wooden fences).
Stick and fences nodes are named in a consistent way.
2015-12-15 06:49:20 +01:00
|
|
|
inventory_image = fence_texture,
|
|
|
|
wield_image = fence_texture,
|
2015-12-15 06:49:20 +01:00
|
|
|
tiles = {def.texture},
|
Create API for fence.register, and use it.
This converts the call to minetest.register() for the default
fence node, so it can be called by other mods to quickly
setup other fences.
Since this creates an API, insert it into the game_api.txt.
The api looks like minetest.register(name, {def}), and has two
uncommon fields: "texture" and "material". Any normal nodedef
property can be passed through, except "drawtype". The "fence"
group will always be added.
The default fence recipe is modified to be as follows:
wood, stick, wood
wood, stick, wood
This recipe yields 4 fence nodes.
This allows us to create according recipes for acacia, pine,
aspen, and junglewood fences without adding new stick types:
pine wood, stick, pine wood
pine wood, stick, pine wood
This is a from-scratch implementation, written by heart but inspired
by (#665 - Add many wooden fences).
Stick and fences nodes are named in a consistent way.
2015-12-15 06:49:20 +01:00
|
|
|
sunlight_propagates = true,
|
|
|
|
is_ground_content = false,
|
|
|
|
groups = {},
|
|
|
|
}
|
|
|
|
for k, v in pairs(default_fields) do
|
|
|
|
if not def[k] then
|
|
|
|
def[k] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Always add to the fence group, even if no group provided
|
|
|
|
def.groups.fence = 1
|
|
|
|
|
|
|
|
def.texture = nil
|
|
|
|
def.material = nil
|
|
|
|
|
|
|
|
minetest.register_node(name, def)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2013-12-02 19:23:29 +01:00
|
|
|
--
|
2013-05-19 18:43:04 +02:00
|
|
|
-- Leafdecay
|
|
|
|
--
|
|
|
|
|
|
|
|
default.leafdecay_trunk_cache = {}
|
|
|
|
default.leafdecay_enable_cache = true
|
|
|
|
-- Spread the load of finding trunks
|
|
|
|
default.leafdecay_trunk_find_allow_accumulator = 0
|
|
|
|
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
|
|
local finds_per_second = 5000
|
|
|
|
default.leafdecay_trunk_find_allow_accumulator =
|
|
|
|
math.floor(dtime * finds_per_second)
|
|
|
|
end)
|
|
|
|
|
2014-12-06 11:08:41 +01:00
|
|
|
default.after_place_leaves = function(pos, placer, itemstack, pointed_thing)
|
2016-02-23 00:28:43 +01:00
|
|
|
if placer and not placer:get_player_control().sneak then
|
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
node.param2 = 1
|
|
|
|
minetest.set_node(pos, node)
|
|
|
|
end
|
2014-12-06 11:08:41 +01:00
|
|
|
end
|
|
|
|
|
2013-05-19 18:43:04 +02:00
|
|
|
minetest.register_abm({
|
2016-08-08 11:56:13 +02:00
|
|
|
label = "Leaf decay",
|
2013-05-19 18:43:04 +02:00
|
|
|
nodenames = {"group:leafdecay"},
|
|
|
|
neighbors = {"air", "group:liquid"},
|
|
|
|
-- A low interval and a high inverse chance spreads the load
|
|
|
|
interval = 2,
|
|
|
|
chance = 5,
|
|
|
|
|
|
|
|
action = function(p0, node, _, _)
|
|
|
|
--print("leafdecay ABM at "..p0.x..", "..p0.y..", "..p0.z..")")
|
|
|
|
local do_preserve = false
|
|
|
|
local d = minetest.registered_nodes[node.name].groups.leafdecay
|
|
|
|
if not d or d == 0 then
|
|
|
|
--print("not groups.leafdecay")
|
|
|
|
return
|
|
|
|
end
|
2013-05-25 00:40:03 +02:00
|
|
|
local n0 = minetest.get_node(p0)
|
2013-05-19 18:43:04 +02:00
|
|
|
if n0.param2 ~= 0 then
|
|
|
|
--print("param2 ~= 0")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local p0_hash = nil
|
|
|
|
if default.leafdecay_enable_cache then
|
|
|
|
p0_hash = minetest.hash_node_position(p0)
|
|
|
|
local trunkp = default.leafdecay_trunk_cache[p0_hash]
|
|
|
|
if trunkp then
|
2013-05-25 00:40:03 +02:00
|
|
|
local n = minetest.get_node(trunkp)
|
2013-05-19 18:43:04 +02:00
|
|
|
local reg = minetest.registered_nodes[n.name]
|
2015-06-07 23:48:26 +02:00
|
|
|
-- Assume ignore is a trunk, to make the thing
|
|
|
|
-- work at the border of the active area
|
|
|
|
if n.name == "ignore" or (reg and reg.groups.tree and
|
|
|
|
reg.groups.tree ~= 0) then
|
2013-05-19 18:43:04 +02:00
|
|
|
--print("cached trunk still exists")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
--print("cached trunk is invalid")
|
|
|
|
-- Cache is invalid
|
|
|
|
table.remove(default.leafdecay_trunk_cache, p0_hash)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if default.leafdecay_trunk_find_allow_accumulator <= 0 then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
default.leafdecay_trunk_find_allow_accumulator =
|
|
|
|
default.leafdecay_trunk_find_allow_accumulator - 1
|
2015-06-07 23:48:26 +02:00
|
|
|
-- Assume ignore is a trunk, to make the thing
|
|
|
|
-- work at the border of the active area
|
2013-05-25 00:40:03 +02:00
|
|
|
local p1 = minetest.find_node_near(p0, d, {"ignore", "group:tree"})
|
2013-05-19 18:43:04 +02:00
|
|
|
if p1 then
|
|
|
|
do_preserve = true
|
|
|
|
if default.leafdecay_enable_cache then
|
|
|
|
--print("caching trunk")
|
|
|
|
-- Cache the trunk
|
|
|
|
default.leafdecay_trunk_cache[p0_hash] = p1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if not do_preserve then
|
|
|
|
-- Drop stuff other than the node itself
|
2014-11-25 21:34:40 +01:00
|
|
|
local itemstacks = minetest.get_node_drops(n0.name)
|
2013-05-19 18:43:04 +02:00
|
|
|
for _, itemname in ipairs(itemstacks) do
|
2013-05-21 16:44:39 +02:00
|
|
|
if minetest.get_item_group(n0.name, "leafdecay_drop") ~= 0 or
|
|
|
|
itemname ~= n0.name then
|
2013-05-19 18:43:04 +02:00
|
|
|
local p_drop = {
|
|
|
|
x = p0.x - 0.5 + math.random(),
|
|
|
|
y = p0.y - 0.5 + math.random(),
|
|
|
|
z = p0.z - 0.5 + math.random(),
|
|
|
|
}
|
2013-05-25 00:40:03 +02:00
|
|
|
minetest.add_item(p_drop, itemname)
|
2013-05-19 18:43:04 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
-- Remove node
|
2013-05-25 00:40:03 +02:00
|
|
|
minetest.remove_node(p0)
|
2013-05-19 18:43:04 +02:00
|
|
|
nodeupdate(p0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
})
|
2013-11-07 17:48:00 +01:00
|
|
|
|
2015-06-07 23:48:26 +02:00
|
|
|
|
2014-12-07 16:29:36 +01:00
|
|
|
--
|
Change how dirt turns to dirt_with_(something)
This changes how dirt blocks turn to dirt_with -grass, -dry_grass
or -snow.
Previously, dirt that was sunlit would turn to dirt_with_grass no
matter what, but this happened without any context, so you could
get green patches of dirt_with_grass in the middle of a savannah or
even desert.
Dirt no longer turns to covered dirt unless it's within 1 node from
another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow.
This makes dirt_with_grass "growback" a lot slower, since it now only
happens on the edges, but it retains the context nicely now.
If there is any dirt with a grass or dry grass plant, or snow on top,
and enough light, we'll convert it sporadically to dirt_with_grass
or dirt_with_dry_grass or dirt_with_snow.
This allows us to plant grass of our choice in a large dirt patch,
or in a region where otherwise that type of grass is not present.
This used to be done by 2 abms, but I've combined them in to a single
ABM that is ordered to run with maximum efficiency, solving for the
most common outcome first before attempting more complex checks.
2016-04-01 06:58:59 +02:00
|
|
|
-- Convert dirt to something that fits the environment
|
2014-12-07 16:29:36 +01:00
|
|
|
--
|
|
|
|
|
|
|
|
minetest.register_abm({
|
2016-08-08 11:56:13 +02:00
|
|
|
label = "Grass spread",
|
2014-12-07 16:29:36 +01:00
|
|
|
nodenames = {"default:dirt"},
|
Change how dirt turns to dirt_with_(something)
This changes how dirt blocks turn to dirt_with -grass, -dry_grass
or -snow.
Previously, dirt that was sunlit would turn to dirt_with_grass no
matter what, but this happened without any context, so you could
get green patches of dirt_with_grass in the middle of a savannah or
even desert.
Dirt no longer turns to covered dirt unless it's within 1 node from
another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow.
This makes dirt_with_grass "growback" a lot slower, since it now only
happens on the edges, but it retains the context nicely now.
If there is any dirt with a grass or dry grass plant, or snow on top,
and enough light, we'll convert it sporadically to dirt_with_grass
or dirt_with_dry_grass or dirt_with_snow.
This allows us to plant grass of our choice in a large dirt patch,
or in a region where otherwise that type of grass is not present.
This used to be done by 2 abms, but I've combined them in to a single
ABM that is ordered to run with maximum efficiency, solving for the
most common outcome first before attempting more complex checks.
2016-04-01 06:58:59 +02:00
|
|
|
neighbors = {
|
|
|
|
"default:dirt_with_grass",
|
|
|
|
"default:dirt_with_dry_grass",
|
|
|
|
"default:dirt_with_snow",
|
2016-04-16 22:53:03 +02:00
|
|
|
"group:grass",
|
|
|
|
"group:dry_grass",
|
Change how dirt turns to dirt_with_(something)
This changes how dirt blocks turn to dirt_with -grass, -dry_grass
or -snow.
Previously, dirt that was sunlit would turn to dirt_with_grass no
matter what, but this happened without any context, so you could
get green patches of dirt_with_grass in the middle of a savannah or
even desert.
Dirt no longer turns to covered dirt unless it's within 1 node from
another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow.
This makes dirt_with_grass "growback" a lot slower, since it now only
happens on the edges, but it retains the context nicely now.
If there is any dirt with a grass or dry grass plant, or snow on top,
and enough light, we'll convert it sporadically to dirt_with_grass
or dirt_with_dry_grass or dirt_with_snow.
This allows us to plant grass of our choice in a large dirt patch,
or in a region where otherwise that type of grass is not present.
This used to be done by 2 abms, but I've combined them in to a single
ABM that is ordered to run with maximum efficiency, solving for the
most common outcome first before attempting more complex checks.
2016-04-01 06:58:59 +02:00
|
|
|
"default:snow",
|
|
|
|
},
|
2016-02-13 09:33:58 +01:00
|
|
|
interval = 6,
|
|
|
|
chance = 67,
|
2015-11-05 02:17:13 +01:00
|
|
|
catch_up = false,
|
2014-12-07 16:29:36 +01:00
|
|
|
action = function(pos, node)
|
Change how dirt turns to dirt_with_(something)
This changes how dirt blocks turn to dirt_with -grass, -dry_grass
or -snow.
Previously, dirt that was sunlit would turn to dirt_with_grass no
matter what, but this happened without any context, so you could
get green patches of dirt_with_grass in the middle of a savannah or
even desert.
Dirt no longer turns to covered dirt unless it's within 1 node from
another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow.
This makes dirt_with_grass "growback" a lot slower, since it now only
happens on the edges, but it retains the context nicely now.
If there is any dirt with a grass or dry grass plant, or snow on top,
and enough light, we'll convert it sporadically to dirt_with_grass
or dirt_with_dry_grass or dirt_with_snow.
This allows us to plant grass of our choice in a large dirt patch,
or in a region where otherwise that type of grass is not present.
This used to be done by 2 abms, but I've combined them in to a single
ABM that is ordered to run with maximum efficiency, solving for the
most common outcome first before attempting more complex checks.
2016-04-01 06:58:59 +02:00
|
|
|
-- Most likely case, half the time it's too dark for this.
|
2015-06-07 23:48:26 +02:00
|
|
|
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
|
Change how dirt turns to dirt_with_(something)
This changes how dirt blocks turn to dirt_with -grass, -dry_grass
or -snow.
Previously, dirt that was sunlit would turn to dirt_with_grass no
matter what, but this happened without any context, so you could
get green patches of dirt_with_grass in the middle of a savannah or
even desert.
Dirt no longer turns to covered dirt unless it's within 1 node from
another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow.
This makes dirt_with_grass "growback" a lot slower, since it now only
happens on the edges, but it retains the context nicely now.
If there is any dirt with a grass or dry grass plant, or snow on top,
and enough light, we'll convert it sporadically to dirt_with_grass
or dirt_with_dry_grass or dirt_with_snow.
This allows us to plant grass of our choice in a large dirt patch,
or in a region where otherwise that type of grass is not present.
This used to be done by 2 abms, but I've combined them in to a single
ABM that is ordered to run with maximum efficiency, solving for the
most common outcome first before attempting more complex checks.
2016-04-01 06:58:59 +02:00
|
|
|
if (minetest.get_node_light(above) or 0) < 13 then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Look for likely neighbors.
|
|
|
|
local p2 = minetest.find_node_near(pos, 1, {"default:dirt_with_grass",
|
|
|
|
"default:dirt_with_dry_grass", "default:dirt_with_snow"})
|
|
|
|
if p2 then
|
|
|
|
-- But the node needs to be under air in this case.
|
|
|
|
local n2 = minetest.get_node(above)
|
|
|
|
if n2 and n2.name == "air" then
|
|
|
|
local n3 = minetest.get_node(p2)
|
|
|
|
minetest.set_node(pos, {name = n3.name})
|
|
|
|
return
|
2014-12-07 16:29:36 +01:00
|
|
|
end
|
|
|
|
end
|
Change how dirt turns to dirt_with_(something)
This changes how dirt blocks turn to dirt_with -grass, -dry_grass
or -snow.
Previously, dirt that was sunlit would turn to dirt_with_grass no
matter what, but this happened without any context, so you could
get green patches of dirt_with_grass in the middle of a savannah or
even desert.
Dirt no longer turns to covered dirt unless it's within 1 node from
another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow.
This makes dirt_with_grass "growback" a lot slower, since it now only
happens on the edges, but it retains the context nicely now.
If there is any dirt with a grass or dry grass plant, or snow on top,
and enough light, we'll convert it sporadically to dirt_with_grass
or dirt_with_dry_grass or dirt_with_snow.
This allows us to plant grass of our choice in a large dirt patch,
or in a region where otherwise that type of grass is not present.
This used to be done by 2 abms, but I've combined them in to a single
ABM that is ordered to run with maximum efficiency, solving for the
most common outcome first before attempting more complex checks.
2016-04-01 06:58:59 +02:00
|
|
|
|
|
|
|
-- Anything on top?
|
|
|
|
local n2 = minetest.get_node(above)
|
|
|
|
if not n2 then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local name = n2.name
|
|
|
|
-- Snow check is cheapest, so comes first.
|
|
|
|
if name == "default:snow" then
|
|
|
|
minetest.set_node(pos, {name = "default:dirt_with_snow"})
|
|
|
|
-- Most likely case first.
|
2016-04-16 22:53:03 +02:00
|
|
|
elseif minetest.get_item_group(name, "grass") ~= 0 then
|
Change how dirt turns to dirt_with_(something)
This changes how dirt blocks turn to dirt_with -grass, -dry_grass
or -snow.
Previously, dirt that was sunlit would turn to dirt_with_grass no
matter what, but this happened without any context, so you could
get green patches of dirt_with_grass in the middle of a savannah or
even desert.
Dirt no longer turns to covered dirt unless it's within 1 node from
another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow.
This makes dirt_with_grass "growback" a lot slower, since it now only
happens on the edges, but it retains the context nicely now.
If there is any dirt with a grass or dry grass plant, or snow on top,
and enough light, we'll convert it sporadically to dirt_with_grass
or dirt_with_dry_grass or dirt_with_snow.
This allows us to plant grass of our choice in a large dirt patch,
or in a region where otherwise that type of grass is not present.
This used to be done by 2 abms, but I've combined them in to a single
ABM that is ordered to run with maximum efficiency, solving for the
most common outcome first before attempting more complex checks.
2016-04-01 06:58:59 +02:00
|
|
|
minetest.set_node(pos, {name = "default:dirt_with_grass"})
|
2016-04-16 22:53:03 +02:00
|
|
|
elseif minetest.get_item_group(name, "dry_grass") ~= 0 then
|
Change how dirt turns to dirt_with_(something)
This changes how dirt blocks turn to dirt_with -grass, -dry_grass
or -snow.
Previously, dirt that was sunlit would turn to dirt_with_grass no
matter what, but this happened without any context, so you could
get green patches of dirt_with_grass in the middle of a savannah or
even desert.
Dirt no longer turns to covered dirt unless it's within 1 node from
another dirt_with_grass or dirt_with_dry_grass or dirt_with_snow.
This makes dirt_with_grass "growback" a lot slower, since it now only
happens on the edges, but it retains the context nicely now.
If there is any dirt with a grass or dry grass plant, or snow on top,
and enough light, we'll convert it sporadically to dirt_with_grass
or dirt_with_dry_grass or dirt_with_snow.
This allows us to plant grass of our choice in a large dirt patch,
or in a region where otherwise that type of grass is not present.
This used to be done by 2 abms, but I've combined them in to a single
ABM that is ordered to run with maximum efficiency, solving for the
most common outcome first before attempting more complex checks.
2016-04-01 06:58:59 +02:00
|
|
|
minetest.set_node(pos, {name = "default:dirt_with_dry_grass"})
|
|
|
|
end
|
2014-12-07 16:29:36 +01:00
|
|
|
end
|
|
|
|
})
|
|
|
|
|
2015-10-22 19:54:18 +02:00
|
|
|
--
|
|
|
|
-- Grass and dry grass removed in darkness
|
|
|
|
--
|
|
|
|
|
2014-12-07 16:29:36 +01:00
|
|
|
minetest.register_abm({
|
2016-08-08 11:56:13 +02:00
|
|
|
label = "Grass covered",
|
2016-04-04 04:52:27 +02:00
|
|
|
nodenames = {
|
|
|
|
"default:dirt_with_grass",
|
|
|
|
"default:dirt_with_dry_grass",
|
|
|
|
"default:dirt_with_snow",
|
|
|
|
},
|
2016-02-13 09:33:58 +01:00
|
|
|
interval = 8,
|
|
|
|
chance = 50,
|
2015-11-05 02:17:13 +01:00
|
|
|
catch_up = false,
|
2014-12-07 16:29:36 +01:00
|
|
|
action = function(pos, node)
|
2015-06-07 23:48:26 +02:00
|
|
|
local above = {x = pos.x, y = pos.y + 1, z = pos.z}
|
2014-12-07 16:29:36 +01:00
|
|
|
local name = minetest.get_node(above).name
|
|
|
|
local nodedef = minetest.registered_nodes[name]
|
2015-06-07 23:48:26 +02:00
|
|
|
if name ~= "ignore" and nodedef and not ((nodedef.sunlight_propagates or
|
|
|
|
nodedef.paramtype == "light") and
|
|
|
|
nodedef.liquidtype == "none") then
|
2014-12-07 16:29:36 +01:00
|
|
|
minetest.set_node(pos, {name = "default:dirt"})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
})
|
2015-06-07 23:48:26 +02:00
|
|
|
|
2015-10-22 19:54:18 +02:00
|
|
|
|
|
|
|
--
|
|
|
|
-- Moss growth on cobble near water
|
|
|
|
--
|
|
|
|
|
|
|
|
minetest.register_abm({
|
2016-08-08 11:56:13 +02:00
|
|
|
label = "Moss growth",
|
2016-05-30 21:03:55 +02:00
|
|
|
nodenames = {"default:cobble", "stairs:slab_cobble", "stairs:stair_cobble"},
|
2015-10-22 19:54:18 +02:00
|
|
|
neighbors = {"group:water"},
|
2016-02-13 09:33:58 +01:00
|
|
|
interval = 16,
|
2015-10-22 19:54:18 +02:00
|
|
|
chance = 200,
|
|
|
|
catch_up = false,
|
|
|
|
action = function(pos, node)
|
2016-05-30 21:03:55 +02:00
|
|
|
if node.name == "default:cobble" then
|
|
|
|
minetest.set_node(pos, {name = "default:mossycobble"})
|
|
|
|
elseif node.name == "stairs:slab_cobble" then
|
|
|
|
minetest.set_node(pos, {name = "stairs:slab_mossycobble", param2 = node.param2})
|
|
|
|
elseif node.name == "stairs:stair_cobble" then
|
|
|
|
minetest.set_node(pos, {name = "stairs:stair_mossycobble", param2 = node.param2})
|
|
|
|
end
|
2015-10-22 19:54:18 +02:00
|
|
|
end
|
|
|
|
})
|
2016-07-19 02:01:59 +02:00
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Checks if specified volume intersects a protected volume
|
|
|
|
--
|
|
|
|
|
|
|
|
function default.intersects_protection(minp, maxp, player_name, interval)
|
|
|
|
-- 'interval' is the largest allowed interval for the 3D lattice of checks
|
|
|
|
|
|
|
|
-- Compute the optimal float step 'd' for each axis so that all corners and
|
|
|
|
-- borders are checked. 'd' will be smaller or equal to 'interval'.
|
|
|
|
-- Subtracting 1e-4 ensures that the max co-ordinate will be reached by the
|
|
|
|
-- for loop (which might otherwise not be the case due to rounding errors).
|
|
|
|
local d = {}
|
|
|
|
for _, c in pairs({"x", "y", "z"}) do
|
|
|
|
if maxp[c] > minp[c] then
|
|
|
|
d[c] = (maxp[c] - minp[c]) / math.ceil((maxp[c] - minp[c]) / interval) - 1e-4
|
|
|
|
elseif maxp[c] == minp[c] then
|
|
|
|
d[c] = 1 -- Any value larger than 0 to avoid division by zero
|
|
|
|
else -- maxp[c] < minp[c], print error and treat as protection intersected
|
|
|
|
minetest.log("error", "maxp < minp in 'default.intersects_protection()'")
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
for zf = minp.z, maxp.z, d.z do
|
|
|
|
local z = math.floor(zf + 0.5)
|
|
|
|
for yf = minp.y, maxp.y, d.y do
|
|
|
|
local y = math.floor(yf + 0.5)
|
|
|
|
for xf = minp.x, maxp.x, d.x do
|
|
|
|
local x = math.floor(xf + 0.5)
|
|
|
|
if minetest.is_protected({x = x, y = y, z = z}, player_name) then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|