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
|
|
|
|
--
|
2016-08-07 04:54:08 +02:00
|
|
|
|
2016-04-16 04:21:45 +02:00
|
|
|
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
|
|
|
|
--
|
2016-08-07 04:54:08 +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
|
|
|
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
|
|
|
|
--
|
|
|
|
|
2016-08-07 04:54:08 +02:00
|
|
|
-- Prevent decay of placed leaves
|
2013-05-19 18:43:04 +02:00
|
|
|
|
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
|
|
|
|
|
2016-08-07 04:54:08 +02:00
|
|
|
-- Leafdecay ABM
|
|
|
|
|
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"},
|
2016-08-07 04:54:08 +02:00
|
|
|
neighbors = {"air"},
|
2013-05-19 18:43:04 +02:00
|
|
|
interval = 2,
|
2016-08-07 04:54:08 +02:00
|
|
|
chance = 10,
|
|
|
|
catch_up = false,
|
|
|
|
|
|
|
|
action = function(pos, node, _, _)
|
|
|
|
-- Check if leaf is placed
|
|
|
|
if node.param2 ~= 0 then
|
2013-05-19 18:43:04 +02:00
|
|
|
return
|
|
|
|
end
|
2016-08-07 04:54:08 +02:00
|
|
|
|
|
|
|
local rad = minetest.registered_nodes[node.name].groups.leafdecay
|
|
|
|
-- Assume ignore is a trunk, to make this
|
|
|
|
-- work at the border of a loaded area
|
|
|
|
if minetest.find_node_near(pos, rad, {"ignore", "group:tree"}) then
|
2013-05-19 18:43:04 +02:00
|
|
|
return
|
|
|
|
end
|
2016-08-07 04:54:08 +02:00
|
|
|
-- Drop stuff
|
|
|
|
local itemstacks = minetest.get_node_drops(node.name)
|
|
|
|
for _, itemname in ipairs(itemstacks) do
|
|
|
|
if itemname ~= node.name or
|
|
|
|
minetest.get_item_group(node.name, "leafdecay_drop") ~= 0 then
|
|
|
|
local p_drop = {
|
|
|
|
x = pos.x - 0.5 + math.random(),
|
|
|
|
y = pos.y - 0.5 + math.random(),
|
|
|
|
z = pos.z - 0.5 + math.random(),
|
|
|
|
}
|
|
|
|
minetest.add_item(p_drop, itemname)
|
2013-05-19 18:43:04 +02:00
|
|
|
end
|
|
|
|
end
|
2016-08-07 04:54:08 +02:00
|
|
|
-- Remove node
|
|
|
|
minetest.remove_node(pos)
|
|
|
|
nodeupdate(pos)
|
2013-05-19 18:43:04 +02:00
|
|
|
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 = {
|
2016-09-22 12:56:15 +02:00
|
|
|
"air",
|
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)
|
2016-09-22 12:56:15 +02:00
|
|
|
-- Check for darkness: night, shadow or under a light-blocking node
|
|
|
|
-- Returns if ignore above
|
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
|
|
|
|
|
2016-09-22 12:56:15 +02:00
|
|
|
-- Look for spreading dirt-type neighbours
|
|
|
|
local p2 = minetest.find_node_near(pos, 1, "group:spreading_dirt_type")
|
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 p2 then
|
2016-09-22 12:56:15 +02:00
|
|
|
local n3 = minetest.get_node(p2)
|
|
|
|
minetest.set_node(pos, {name = n3.name})
|
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
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2016-09-22 12:56:15 +02:00
|
|
|
-- Else, any seeding nodes on top?
|
|
|
|
local name = minetest.get_node(above).name
|
|
|
|
-- Snow check is cheapest, so comes first
|
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 name == "default:snow" then
|
|
|
|
minetest.set_node(pos, {name = "default:dirt_with_snow"})
|
2016-09-22 12:56:15 +02:00
|
|
|
-- 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
|
|
|
|
})
|
|
|
|
|
2016-08-07 04:54:08 +02:00
|
|
|
|
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-09-22 12:56:15 +02:00
|
|
|
nodenames = {"group:spreading_dirt_type"},
|
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
|