2013-05-19 18:43:04 +02:00
|
|
|
--
|
|
|
|
-- 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
|
2020-11-08 16:43:04 +01:00
|
|
|
{name = "default_hard_footstep", gain = 0.2}
|
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
|
2020-11-08 16:43:04 +01:00
|
|
|
{name = "default_dirt_footstep", gain = 0.25}
|
|
|
|
table.dig = table.dig or
|
|
|
|
{name = "default_dig_crumbly", gain = 0.4}
|
2013-06-13 16:30:33 +02:00
|
|
|
table.dug = table.dug or
|
2016-12-15 09:13:36 +01:00
|
|
|
{name = "default_dirt_footstep", gain = 1.0}
|
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
|
2020-08-29 02:16:36 +02:00
|
|
|
{name = "default_sand_footstep", gain = 0.05}
|
2013-05-19 18:43:04 +02:00
|
|
|
table.dug = table.dug or
|
2020-08-29 02:16:36 +02:00
|
|
|
{name = "default_sand_footstep", gain = 0.15}
|
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
|
2020-11-08 16:43:04 +01:00
|
|
|
{name = "default_gravel_footstep", gain = 0.25}
|
2020-08-29 02:16:36 +02:00
|
|
|
table.dig = table.dig or
|
|
|
|
{name = "default_gravel_dig", gain = 0.35}
|
2016-04-25 00:10:46 +02:00
|
|
|
table.dug = table.dug or
|
2020-08-29 02:16:36 +02:00
|
|
|
{name = "default_gravel_dug", gain = 1.0}
|
2016-04-25 00:10:46 +02:00
|
|
|
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
|
2020-11-08 16:43:04 +01:00
|
|
|
{name = "default_wood_footstep", gain = 0.15}
|
|
|
|
table.dig = table.dig or
|
|
|
|
{name = "default_dig_choppy", gain = 0.4}
|
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
|
2016-12-15 09:13:36 +01:00
|
|
|
{name = "default_grass_footstep", gain = 0.45}
|
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-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
|
2016-12-15 09:13:36 +01:00
|
|
|
{name = "default_glass_footstep", gain = 0.3}
|
2016-12-10 02:05:16 +01:00
|
|
|
table.dig = table.dig or
|
2016-12-15 09:13:36 +01: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
|
|
|
|
|
2020-08-29 02:16:36 +02:00
|
|
|
function default.node_sound_ice_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2020-11-08 16:43:04 +01:00
|
|
|
{name = "default_ice_footstep", gain = 0.15}
|
2020-08-29 02:16:36 +02:00
|
|
|
table.dig = table.dig or
|
|
|
|
{name = "default_ice_dig", gain = 0.5}
|
|
|
|
table.dug = table.dug or
|
|
|
|
{name = "default_ice_dug", gain = 0.5}
|
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
2016-10-20 01:23:05 +02:00
|
|
|
function default.node_sound_metal_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
2020-11-08 16:43:04 +01:00
|
|
|
{name = "default_metal_footstep", gain = 0.2}
|
2016-10-20 01:23:05 +02:00
|
|
|
table.dig = table.dig or
|
|
|
|
{name = "default_dig_metal", gain = 0.5}
|
|
|
|
table.dug = table.dug or
|
|
|
|
{name = "default_dug_metal", gain = 0.5}
|
|
|
|
table.place = table.place or
|
|
|
|
{name = "default_place_node_metal", gain = 0.5}
|
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
2014-08-26 13:55:53 +02:00
|
|
|
|
2016-11-17 03:41:38 +01:00
|
|
|
function default.node_sound_water_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
|
|
|
{name = "default_water_footstep", gain = 0.2}
|
|
|
|
default.node_sound_defaults(table)
|
|
|
|
return table
|
|
|
|
end
|
|
|
|
|
2017-10-21 08:01:23 +02:00
|
|
|
function default.node_sound_snow_defaults(table)
|
|
|
|
table = table or {}
|
|
|
|
table.footstep = table.footstep or
|
|
|
|
{name = "default_snow_footstep", gain = 0.2}
|
|
|
|
table.dig = table.dig or
|
|
|
|
{name = "default_snow_footstep", gain = 0.3}
|
|
|
|
table.dug = table.dug or
|
|
|
|
{name = "default_snow_footstep", gain = 0.3}
|
|
|
|
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
|
|
|
--
|
|
|
|
-- 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",
|
2020-11-08 16:43:04 +01:00
|
|
|
{pos = pos, max_hear_distance = 16, gain = 0.2}, true)
|
2013-05-19 18:43:04 +02:00
|
|
|
end
|
|
|
|
|
2017-05-22 15:41:17 +02:00
|
|
|
if minetest.settings:get_bool("enable_lavacooling") ~= false then
|
2017-05-07 18:25:53 +02:00
|
|
|
minetest.register_abm({
|
|
|
|
label = "Lava cooling",
|
|
|
|
nodenames = {"default:lava_source", "default:lava_flowing"},
|
|
|
|
neighbors = {"group:cools_lava", "group:water"},
|
2017-07-27 02:16:17 +02:00
|
|
|
interval = 2,
|
2017-05-07 18:25:53 +02:00
|
|
|
chance = 2,
|
|
|
|
catch_up = false,
|
2017-06-06 19:20:58 +02:00
|
|
|
action = function(...)
|
|
|
|
default.cool_lava(...)
|
|
|
|
end,
|
2017-05-07 18:25:53 +02:00
|
|
|
})
|
|
|
|
end
|
2014-08-26 13:55:53 +02:00
|
|
|
|
2017-10-21 08:01:23 +02:00
|
|
|
|
2016-04-16 04:21:45 +02:00
|
|
|
--
|
2017-10-21 08:01:23 +02:00
|
|
|
-- Optimized helper to put all items in an inventory into a drops list
|
2016-04-16 04:21:45 +02:00
|
|
|
--
|
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
|
|
|
|
|
2017-10-21 08:01:23 +02:00
|
|
|
|
2013-05-19 18:43:04 +02:00
|
|
|
--
|
|
|
|
-- Papyrus and cactus growing
|
|
|
|
--
|
|
|
|
|
2017-10-21 08:01:23 +02:00
|
|
|
-- Wrapping the functions in ABM action is necessary to make overriding them possible
|
2015-06-07 23:48:26 +02:00
|
|
|
|
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
|
2016-12-27 16:18:49 +01:00
|
|
|
if minetest.get_node_light(pos) < 13 then
|
|
|
|
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
|
2020-06-22 00:24:56 +02:00
|
|
|
if name ~= "default:dirt" and
|
|
|
|
name ~= "default:dirt_with_grass" and
|
|
|
|
name ~= "default:dirt_with_dry_grass" and
|
|
|
|
name ~= "default:dirt_with_rainforest_litter" and
|
|
|
|
name ~= "default:dry_dirt" and
|
|
|
|
name ~= "default:dry_dirt_with_dry_grass" 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
|
2016-12-27 16:18:49 +01:00
|
|
|
if minetest.get_node_light(pos) < 13 then
|
|
|
|
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,
|
2017-06-06 19:20:58 +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"},
|
2020-06-22 00:24:56 +02:00
|
|
|
-- Grows on the dirt and surface dirt nodes of the biomes papyrus appears in,
|
|
|
|
-- including the old savanna nodes.
|
|
|
|
-- 'default:dirt_with_grass' is here only because it was allowed before.
|
|
|
|
neighbors = {
|
|
|
|
"default:dirt",
|
|
|
|
"default:dirt_with_grass",
|
|
|
|
"default:dirt_with_dry_grass",
|
|
|
|
"default:dirt_with_rainforest_litter",
|
|
|
|
"default:dry_dirt",
|
|
|
|
"default:dry_dirt_with_dry_grass",
|
|
|
|
},
|
2016-02-13 09:33:58 +01:00
|
|
|
interval = 14,
|
|
|
|
chance = 71,
|
2017-06-06 19:20:58 +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
|
|
|
--
|
2017-10-21 08:01:23 +02:00
|
|
|
-- Dig upwards
|
2013-12-02 19:23:29 +01:00
|
|
|
--
|
|
|
|
|
|
|
|
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
|
|
|
|
--
|
2019-09-16 22:38:02 +02:00
|
|
|
local fence_collision_extra = minetest.settings:get_bool("enable_fence_tall") and 3/8 or 0
|
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",
|
2019-09-16 22:38:02 +02:00
|
|
|
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8},
|
2015-12-15 06:49:20 +01:00
|
|
|
-- connect_top =
|
|
|
|
-- connect_bottom =
|
2019-09-16 22:38:02 +02:00
|
|
|
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}}
|
|
|
|
},
|
|
|
|
collision_box = {
|
|
|
|
type = "connected",
|
|
|
|
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2 + fence_collision_extra, 1/8},
|
|
|
|
-- connect_top =
|
|
|
|
-- connect_bottom =
|
|
|
|
connect_front = {-1/8, -1/2, -1/2, 1/8, 1/2 + fence_collision_extra, -1/8},
|
|
|
|
connect_left = {-1/2, -1/2, -1/8, -1/8, 1/2 + fence_collision_extra, 1/8},
|
|
|
|
connect_back = {-1/8, -1/2, 1/8, 1/8, 1/2 + fence_collision_extra, 1/2},
|
|
|
|
connect_right = { 1/8, -1/2, -1/8, 1/2, 1/2 + fence_collision_extra, 1/8}
|
2015-12-15 06:49:20 +01:00
|
|
|
},
|
2018-07-07 20:03:33 +02:00
|
|
|
connects_to = {"group:fence", "group:wood", "group:tree", "group:wall"},
|
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
|
2017-08-13 12:47:43 +02:00
|
|
|
if def[k] == nil then
|
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
|
|
|
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
|
|
|
|
|
|
|
|
|
2018-07-07 20:03:33 +02:00
|
|
|
--
|
|
|
|
-- Fence rail registration helper
|
|
|
|
--
|
|
|
|
|
|
|
|
function default.register_fence_rail(name, def)
|
|
|
|
minetest.register_craft({
|
|
|
|
output = name .. " 16",
|
|
|
|
recipe = {
|
|
|
|
{ def.material, def.material },
|
|
|
|
{ "", ""},
|
|
|
|
{ def.material, def.material },
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
local fence_rail_texture = "default_fence_rail_overlay.png^" .. def.texture ..
|
|
|
|
"^default_fence_rail_overlay.png^[makealpha:255,126,126"
|
|
|
|
-- Allow almost everything to be overridden
|
|
|
|
local default_fields = {
|
|
|
|
paramtype = "light",
|
|
|
|
drawtype = "nodebox",
|
|
|
|
node_box = {
|
|
|
|
type = "connected",
|
2019-09-16 22:38:02 +02:00
|
|
|
fixed = {{-1/16, 3/16, -1/16, 1/16, 5/16, 1/16},
|
|
|
|
{-1/16, -3/16, -1/16, 1/16, -5/16, 1/16}},
|
|
|
|
-- connect_top =
|
|
|
|
-- connect_bottom =
|
|
|
|
connect_front = {{-1/16, 3/16, -1/2, 1/16, 5/16, -1/16},
|
|
|
|
{-1/16, -5/16, -1/2, 1/16, -3/16, -1/16}},
|
|
|
|
connect_left = {{-1/2, 3/16, -1/16, -1/16, 5/16, 1/16},
|
|
|
|
{-1/2, -5/16, -1/16, -1/16, -3/16, 1/16}},
|
|
|
|
connect_back = {{-1/16, 3/16, 1/16, 1/16, 5/16, 1/2 },
|
|
|
|
{-1/16, -5/16, 1/16, 1/16, -3/16, 1/2 }},
|
|
|
|
connect_right = {{ 1/16, 3/16, -1/16, 1/2, 5/16, 1/16},
|
|
|
|
{ 1/16, -5/16, -1/16, 1/2, -3/16, 1/16}}
|
|
|
|
},
|
|
|
|
collision_box = {
|
|
|
|
type = "connected",
|
|
|
|
fixed = {-1/8, -1/2, -1/8, 1/8, 1/2 + fence_collision_extra, 1/8},
|
2018-07-07 20:03:33 +02:00
|
|
|
-- connect_top =
|
|
|
|
-- connect_bottom =
|
2019-09-16 22:38:02 +02:00
|
|
|
connect_front = {-1/8, -1/2, -1/2, 1/8, 1/2 + fence_collision_extra, -1/8},
|
|
|
|
connect_left = {-1/2, -1/2, -1/8, -1/8, 1/2 + fence_collision_extra, 1/8},
|
|
|
|
connect_back = {-1/8, -1/2, 1/8, 1/8, 1/2 + fence_collision_extra, 1/2},
|
|
|
|
connect_right = { 1/8, -1/2, -1/8, 1/2, 1/2 + fence_collision_extra, 1/8}
|
2018-07-07 20:03:33 +02:00
|
|
|
},
|
2018-10-11 20:31:35 +02:00
|
|
|
connects_to = {"group:fence", "group:wall"},
|
2018-07-07 20:03:33 +02:00
|
|
|
inventory_image = fence_rail_texture,
|
|
|
|
wield_image = fence_rail_texture,
|
|
|
|
tiles = {def.texture},
|
|
|
|
sunlight_propagates = true,
|
|
|
|
is_ground_content = false,
|
|
|
|
groups = {},
|
|
|
|
}
|
|
|
|
for k, v in pairs(default_fields) do
|
|
|
|
if def[k] == nil 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
|
|
|
|
|
2020-08-16 13:21:22 +02:00
|
|
|
--
|
|
|
|
-- Mese post registration helper
|
|
|
|
--
|
|
|
|
|
|
|
|
function default.register_mesepost(name, def)
|
|
|
|
minetest.register_craft({
|
|
|
|
output = name .. " 4",
|
|
|
|
recipe = {
|
|
|
|
{'', 'default:glass', ''},
|
|
|
|
{'default:mese_crystal', 'default:mese_crystal', 'default:mese_crystal'},
|
2020-08-23 14:35:12 +02:00
|
|
|
{'', def.material, ''},
|
2020-08-16 13:21:22 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
local post_texture = def.texture .. "^default_mese_post_light_side.png^[makealpha:0,0,0"
|
|
|
|
local post_texture_dark = def.texture .. "^default_mese_post_light_side_dark.png^[makealpha:0,0,0"
|
|
|
|
-- Allow almost everything to be overridden
|
|
|
|
local default_fields = {
|
|
|
|
wield_image = post_texture,
|
|
|
|
drawtype = "nodebox",
|
|
|
|
node_box = {
|
|
|
|
type = "fixed",
|
|
|
|
fixed = {
|
|
|
|
{-2 / 16, -8 / 16, -2 / 16, 2 / 16, 8 / 16, 2 / 16},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
paramtype = "light",
|
|
|
|
tiles = {def.texture, def.texture, post_texture_dark, post_texture_dark, post_texture, post_texture},
|
2021-02-06 15:40:26 +01:00
|
|
|
use_texture_alpha = "opaque",
|
2020-08-16 13:21:22 +02:00
|
|
|
light_source = default.LIGHT_MAX,
|
|
|
|
sunlight_propagates = true,
|
|
|
|
is_ground_content = false,
|
|
|
|
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
|
|
|
sounds = default.node_sound_wood_defaults(),
|
|
|
|
}
|
|
|
|
for k, v in pairs(default_fields) do
|
|
|
|
if def[k] == nil then
|
|
|
|
def[k] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def.texture = nil
|
|
|
|
def.material = nil
|
|
|
|
|
|
|
|
minetest.register_node(name, def)
|
|
|
|
end
|
2018-07-07 20:03:33 +02:00
|
|
|
|
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)
|
2019-09-28 22:10:26 +02:00
|
|
|
if placer and placer:is_player() then
|
2016-02-23 00:28:43 +01:00
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
node.param2 = 1
|
|
|
|
minetest.set_node(pos, node)
|
|
|
|
end
|
2014-12-06 11:08:41 +01:00
|
|
|
end
|
|
|
|
|
Leafdecay: Node timer based implementation, API
This implements a node-timer based leafdecay mechanism, and exposes
an API to use it in mods.
The API is documented in game_api.txt.
`default.register_leafdecay(leafdecaydef)`
`leafdecaydef` is a table, with following members:
{
trunks = { "default:tree"}, -- nodes considered trunks
leaves = { "default:leaves", "default:apple"}, -- nodes considered leaves
radius = 3, -- activates leafdecay this far from the trunk
}
The algorithm will drop `leaves` items in the area if no `trunks` are found
in the `trunk_radius` sized area around the position of the leaf. If a node
listed in `leaves` has a group `leafdecay_drop > 0`, then the item is dropped,
otherwise the item is removed but not dropped.
The algorithm also implements a value `default.leafdecay_speed` (default
15) which can be modified to increase or decrease of the leaf decay. The
algorithm will vary the actual speed a bit to introduce randomness.
Leaf decay is randomized by 0.1 seconds to reduce the chance that
decay happens many times on the same second interval. This requires
nodetimer_interval to be set to values lower than 1.0 to have an
effect.
The leaves will decay between 2 and 10 seconds after digging the trunk,
and happen at non-integer second intervals.
-- The API was added by sofar.
2017-02-08 01:28:02 +01:00
|
|
|
-- Leafdecay
|
|
|
|
local function leafdecay_after_destruct(pos, oldnode, def)
|
|
|
|
for _, v in pairs(minetest.find_nodes_in_area(vector.subtract(pos, def.radius),
|
|
|
|
vector.add(pos, def.radius), def.leaves)) do
|
|
|
|
local node = minetest.get_node(v)
|
2017-03-30 06:06:49 +02:00
|
|
|
local timer = minetest.get_node_timer(v)
|
2019-09-19 03:13:18 +02:00
|
|
|
if node.param2 ~= 1 and not timer:is_started() then
|
2017-03-30 06:06:49 +02:00
|
|
|
timer:start(math.random(20, 120) / 10)
|
2013-05-19 18:43:04 +02:00
|
|
|
end
|
Leafdecay: Node timer based implementation, API
This implements a node-timer based leafdecay mechanism, and exposes
an API to use it in mods.
The API is documented in game_api.txt.
`default.register_leafdecay(leafdecaydef)`
`leafdecaydef` is a table, with following members:
{
trunks = { "default:tree"}, -- nodes considered trunks
leaves = { "default:leaves", "default:apple"}, -- nodes considered leaves
radius = 3, -- activates leafdecay this far from the trunk
}
The algorithm will drop `leaves` items in the area if no `trunks` are found
in the `trunk_radius` sized area around the position of the leaf. If a node
listed in `leaves` has a group `leafdecay_drop > 0`, then the item is dropped,
otherwise the item is removed but not dropped.
The algorithm also implements a value `default.leafdecay_speed` (default
15) which can be modified to increase or decrease of the leaf decay. The
algorithm will vary the actual speed a bit to introduce randomness.
Leaf decay is randomized by 0.1 seconds to reduce the chance that
decay happens many times on the same second interval. This requires
nodetimer_interval to be set to values lower than 1.0 to have an
effect.
The leaves will decay between 2 and 10 seconds after digging the trunk,
and happen at non-integer second intervals.
-- The API was added by sofar.
2017-02-08 01:28:02 +01:00
|
|
|
end
|
|
|
|
end
|
2016-08-07 04:54:08 +02:00
|
|
|
|
2020-05-25 15:56:23 +02:00
|
|
|
local movement_gravity = tonumber(
|
|
|
|
minetest.settings:get("movement_gravity")) or 9.81
|
|
|
|
|
Leafdecay: Node timer based implementation, API
This implements a node-timer based leafdecay mechanism, and exposes
an API to use it in mods.
The API is documented in game_api.txt.
`default.register_leafdecay(leafdecaydef)`
`leafdecaydef` is a table, with following members:
{
trunks = { "default:tree"}, -- nodes considered trunks
leaves = { "default:leaves", "default:apple"}, -- nodes considered leaves
radius = 3, -- activates leafdecay this far from the trunk
}
The algorithm will drop `leaves` items in the area if no `trunks` are found
in the `trunk_radius` sized area around the position of the leaf. If a node
listed in `leaves` has a group `leafdecay_drop > 0`, then the item is dropped,
otherwise the item is removed but not dropped.
The algorithm also implements a value `default.leafdecay_speed` (default
15) which can be modified to increase or decrease of the leaf decay. The
algorithm will vary the actual speed a bit to introduce randomness.
Leaf decay is randomized by 0.1 seconds to reduce the chance that
decay happens many times on the same second interval. This requires
nodetimer_interval to be set to values lower than 1.0 to have an
effect.
The leaves will decay between 2 and 10 seconds after digging the trunk,
and happen at non-integer second intervals.
-- The API was added by sofar.
2017-02-08 01:28:02 +01:00
|
|
|
local function leafdecay_on_timer(pos, def)
|
|
|
|
if minetest.find_node_near(pos, def.radius, def.trunks) then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
local drops = minetest.get_node_drops(node.name)
|
|
|
|
for _, item in ipairs(drops) do
|
|
|
|
local is_leaf
|
|
|
|
for _, v in pairs(def.leaves) do
|
|
|
|
if v == item then
|
|
|
|
is_leaf = true
|
2013-05-19 18:43:04 +02:00
|
|
|
end
|
|
|
|
end
|
Leafdecay: Node timer based implementation, API
This implements a node-timer based leafdecay mechanism, and exposes
an API to use it in mods.
The API is documented in game_api.txt.
`default.register_leafdecay(leafdecaydef)`
`leafdecaydef` is a table, with following members:
{
trunks = { "default:tree"}, -- nodes considered trunks
leaves = { "default:leaves", "default:apple"}, -- nodes considered leaves
radius = 3, -- activates leafdecay this far from the trunk
}
The algorithm will drop `leaves` items in the area if no `trunks` are found
in the `trunk_radius` sized area around the position of the leaf. If a node
listed in `leaves` has a group `leafdecay_drop > 0`, then the item is dropped,
otherwise the item is removed but not dropped.
The algorithm also implements a value `default.leafdecay_speed` (default
15) which can be modified to increase or decrease of the leaf decay. The
algorithm will vary the actual speed a bit to introduce randomness.
Leaf decay is randomized by 0.1 seconds to reduce the chance that
decay happens many times on the same second interval. This requires
nodetimer_interval to be set to values lower than 1.0 to have an
effect.
The leaves will decay between 2 and 10 seconds after digging the trunk,
and happen at non-integer second intervals.
-- The API was added by sofar.
2017-02-08 01:28:02 +01:00
|
|
|
if minetest.get_item_group(item, "leafdecay_drop") ~= 0 or
|
|
|
|
not is_leaf then
|
|
|
|
minetest.add_item({
|
|
|
|
x = pos.x - 0.5 + math.random(),
|
|
|
|
y = pos.y - 0.5 + math.random(),
|
|
|
|
z = pos.z - 0.5 + math.random(),
|
|
|
|
}, item)
|
|
|
|
end
|
2013-05-19 18:43:04 +02:00
|
|
|
end
|
2013-11-07 17:48:00 +01:00
|
|
|
|
Leafdecay: Node timer based implementation, API
This implements a node-timer based leafdecay mechanism, and exposes
an API to use it in mods.
The API is documented in game_api.txt.
`default.register_leafdecay(leafdecaydef)`
`leafdecaydef` is a table, with following members:
{
trunks = { "default:tree"}, -- nodes considered trunks
leaves = { "default:leaves", "default:apple"}, -- nodes considered leaves
radius = 3, -- activates leafdecay this far from the trunk
}
The algorithm will drop `leaves` items in the area if no `trunks` are found
in the `trunk_radius` sized area around the position of the leaf. If a node
listed in `leaves` has a group `leafdecay_drop > 0`, then the item is dropped,
otherwise the item is removed but not dropped.
The algorithm also implements a value `default.leafdecay_speed` (default
15) which can be modified to increase or decrease of the leaf decay. The
algorithm will vary the actual speed a bit to introduce randomness.
Leaf decay is randomized by 0.1 seconds to reduce the chance that
decay happens many times on the same second interval. This requires
nodetimer_interval to be set to values lower than 1.0 to have an
effect.
The leaves will decay between 2 and 10 seconds after digging the trunk,
and happen at non-integer second intervals.
-- The API was added by sofar.
2017-02-08 01:28:02 +01:00
|
|
|
minetest.remove_node(pos)
|
|
|
|
minetest.check_for_falling(pos)
|
2020-05-25 15:56:23 +02:00
|
|
|
|
|
|
|
-- spawn a few particles for the removed node
|
|
|
|
minetest.add_particlespawner({
|
|
|
|
amount = 8,
|
|
|
|
time = 0.001,
|
|
|
|
minpos = vector.subtract(pos, {x=0.5, y=0.5, z=0.5}),
|
|
|
|
maxpos = vector.add(pos, {x=0.5, y=0.5, z=0.5}),
|
|
|
|
minvel = vector.new(-0.5, -1, -0.5),
|
|
|
|
maxvel = vector.new(0.5, 0, 0.5),
|
|
|
|
minacc = vector.new(0, -movement_gravity, 0),
|
|
|
|
maxacc = vector.new(0, -movement_gravity, 0),
|
|
|
|
minsize = 0,
|
|
|
|
maxsize = 0,
|
|
|
|
node = node,
|
|
|
|
})
|
Leafdecay: Node timer based implementation, API
This implements a node-timer based leafdecay mechanism, and exposes
an API to use it in mods.
The API is documented in game_api.txt.
`default.register_leafdecay(leafdecaydef)`
`leafdecaydef` is a table, with following members:
{
trunks = { "default:tree"}, -- nodes considered trunks
leaves = { "default:leaves", "default:apple"}, -- nodes considered leaves
radius = 3, -- activates leafdecay this far from the trunk
}
The algorithm will drop `leaves` items in the area if no `trunks` are found
in the `trunk_radius` sized area around the position of the leaf. If a node
listed in `leaves` has a group `leafdecay_drop > 0`, then the item is dropped,
otherwise the item is removed but not dropped.
The algorithm also implements a value `default.leafdecay_speed` (default
15) which can be modified to increase or decrease of the leaf decay. The
algorithm will vary the actual speed a bit to introduce randomness.
Leaf decay is randomized by 0.1 seconds to reduce the chance that
decay happens many times on the same second interval. This requires
nodetimer_interval to be set to values lower than 1.0 to have an
effect.
The leaves will decay between 2 and 10 seconds after digging the trunk,
and happen at non-integer second intervals.
-- The API was added by sofar.
2017-02-08 01:28:02 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
function default.register_leafdecay(def)
|
|
|
|
assert(def.leaves)
|
|
|
|
assert(def.trunks)
|
|
|
|
assert(def.radius)
|
|
|
|
for _, v in pairs(def.trunks) do
|
|
|
|
minetest.override_item(v, {
|
|
|
|
after_destruct = function(pos, oldnode)
|
|
|
|
leafdecay_after_destruct(pos, oldnode, def)
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
for _, v in pairs(def.leaves) do
|
|
|
|
minetest.override_item(v, {
|
|
|
|
on_timer = function(pos)
|
|
|
|
leafdecay_on_timer(pos, def)
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
2015-06-07 23:48:26 +02:00
|
|
|
|
2017-10-21 08:01:23 +02:00
|
|
|
|
2014-12-07 16:29:36 +01:00
|
|
|
--
|
2020-06-16 21:42:45 +02:00
|
|
|
-- Convert default: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",
|
2020-06-16 21:42:45 +02:00
|
|
|
"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,
|
2016-10-05 22:07:05 +02:00
|
|
|
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)
|
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-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"})
|
2020-06-16 21:42:45 +02:00
|
|
|
elseif minetest.get_item_group(name, "dry_grass") ~= 0 then
|
|
|
|
minetest.set_node(pos, {name = "default:dirt_with_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
|
|
|
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",
|
2019-07-26 18:50:44 +02:00
|
|
|
nodenames = {"group:spreading_dirt_type", "default:dry_dirt_with_dry_grass"},
|
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
|
2019-07-26 18:50:44 +02:00
|
|
|
if node.name == "default:dry_dirt_with_dry_grass" then
|
|
|
|
minetest.set_node(pos, {name = "default:dry_dirt"})
|
|
|
|
else
|
|
|
|
minetest.set_node(pos, {name = "default:dirt"})
|
|
|
|
end
|
2014-12-07 16:29:36 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
})
|
2015-06-07 23:48:26 +02:00
|
|
|
|
2015-10-22 19:54:18 +02:00
|
|
|
|
|
|
|
--
|
|
|
|
-- Moss growth on cobble near water
|
|
|
|
--
|
|
|
|
|
2019-04-06 22:35:48 +02:00
|
|
|
local moss_correspondences = {
|
|
|
|
["default:cobble"] = "default:mossycobble",
|
|
|
|
["stairs:slab_cobble"] = "stairs:slab_mossycobble",
|
|
|
|
["stairs:stair_cobble"] = "stairs:stair_mossycobble",
|
|
|
|
["stairs:stair_inner_cobble"] = "stairs:stair_inner_mossycobble",
|
|
|
|
["stairs:stair_outer_cobble"] = "stairs:stair_outer_mossycobble",
|
|
|
|
["walls:cobble"] = "walls:mossycobble",
|
|
|
|
}
|
2015-10-22 19:54:18 +02:00
|
|
|
minetest.register_abm({
|
2016-08-08 11:56:13 +02:00
|
|
|
label = "Moss growth",
|
2019-04-06 22:35:48 +02:00
|
|
|
nodenames = {"default:cobble", "stairs:slab_cobble", "stairs:stair_cobble",
|
|
|
|
"stairs:stair_inner_cobble", "stairs:stair_outer_cobble",
|
|
|
|
"walls: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)
|
2019-04-06 22:35:48 +02:00
|
|
|
node.name = moss_correspondences[node.name]
|
2019-06-02 19:50:20 +02:00
|
|
|
if node.name then
|
|
|
|
minetest.set_node(pos, node)
|
|
|
|
end
|
2015-10-22 19:54:18 +02:00
|
|
|
end
|
|
|
|
})
|
2016-07-19 02:01:59 +02:00
|
|
|
|
2020-01-04 01:09:58 +01:00
|
|
|
--
|
|
|
|
-- Register a craft to copy the metadata of items
|
|
|
|
--
|
|
|
|
|
|
|
|
function default.register_craft_metadata_copy(ingredient, result)
|
|
|
|
minetest.register_craft({
|
|
|
|
type = "shapeless",
|
|
|
|
output = result,
|
|
|
|
recipe = {ingredient, result}
|
|
|
|
})
|
|
|
|
|
|
|
|
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
|
|
|
|
if itemstack:get_name() ~= result then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local original
|
|
|
|
local index
|
|
|
|
for i = 1, #old_craft_grid do
|
|
|
|
if old_craft_grid[i]:get_name() == result then
|
|
|
|
original = old_craft_grid[i]
|
|
|
|
index = i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if not original then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local copymeta = original:get_meta():to_table()
|
|
|
|
itemstack:get_meta():from_table(copymeta)
|
|
|
|
-- put the book with metadata back in the craft grid
|
|
|
|
craft_inv:set_stack("craft", index, original)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
2022-04-03 00:01:51 +02:00
|
|
|
--
|
|
|
|
-- Log API / helpers
|
|
|
|
--
|
|
|
|
|
|
|
|
local non_player_action_log = minetest.settings:get_bool("enable_non_player_action_log") ~= false
|
|
|
|
|
|
|
|
function default.log_action(player, pos, message)
|
|
|
|
local who = player:get_player_name()
|
|
|
|
if not player.is_fake_player and player:is_player() then
|
|
|
|
-- log action of real player
|
|
|
|
minetest.log("action", who .. " " .. message .. " at " .. minetest.pos_to_string(pos))
|
|
|
|
elseif non_player_action_log then
|
|
|
|
-- log action of non real player
|
|
|
|
who = who .. "(" .. (type(player.is_fake_player) == "string"
|
|
|
|
and player.is_fake_player or "*").. ")"
|
|
|
|
minetest.log("action", who .. " " .. message .. " at " .. minetest.pos_to_string(pos))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function default.set_inventory_action_loggers(def, name)
|
|
|
|
def.on_metadata_inventory_move = function(pos, from_list, from_index,
|
|
|
|
to_list, to_index, count, player)
|
|
|
|
default.log_action(player, pos, "moves stuff in " .. name)
|
|
|
|
end
|
|
|
|
def.on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
|
|
default.log_action(player, pos, "moves " .. stack:get_name() .. " to " .. name)
|
|
|
|
end
|
|
|
|
def.on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
|
|
default.log_action(player, pos, "takes " .. stack:get_name() .. " from " .. name)
|
|
|
|
end
|
|
|
|
end
|
2016-07-19 02:01:59 +02:00
|
|
|
|
2017-02-10 20:35:26 +01:00
|
|
|
--
|
2022-04-04 20:10:24 +02:00
|
|
|
-- NOTICE: This method are not an official part of the API yet.
|
|
|
|
-- This method may change in future.
|
2017-02-10 20:35:26 +01:00
|
|
|
--
|
|
|
|
|
|
|
|
function default.can_interact_with_node(player, pos)
|
2019-08-19 19:24:19 +02:00
|
|
|
if player and player:is_player() then
|
2017-02-10 20:35:26 +01:00
|
|
|
if minetest.check_player_privs(player, "protection_bypass") then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
local meta = minetest.get_meta(pos)
|
2017-03-18 17:19:19 +01:00
|
|
|
local owner = meta:get_string("owner")
|
2017-02-10 20:35:26 +01:00
|
|
|
|
2017-03-18 17:19:19 +01:00
|
|
|
if not owner or owner == "" or owner == player:get_player_name() then
|
2017-03-12 14:03:37 +01:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2017-10-21 08:01:23 +02:00
|
|
|
-- Is player wielding the right key?
|
2017-02-10 20:35:26 +01:00
|
|
|
local item = player:get_wielded_item()
|
2020-01-06 22:16:33 +01:00
|
|
|
if minetest.get_item_group(item:get_name(), "key") == 1 then
|
2017-03-12 14:03:37 +01:00
|
|
|
local key_meta = item:get_meta()
|
2017-02-10 20:35:26 +01:00
|
|
|
|
2017-03-12 14:03:37 +01:00
|
|
|
if key_meta:get_string("secret") == "" then
|
2017-03-16 06:03:52 +01:00
|
|
|
local key_oldmeta = item:get_metadata()
|
|
|
|
if key_oldmeta == "" or not minetest.parse_json(key_oldmeta) then
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
key_meta:set_string("secret", minetest.parse_json(key_oldmeta).secret)
|
2017-03-12 14:03:37 +01:00
|
|
|
item:set_metadata("")
|
|
|
|
end
|
2017-02-10 20:35:26 +01:00
|
|
|
|
2017-03-12 14:03:37 +01:00
|
|
|
return meta:get_string("key_lock_secret") == key_meta:get_string("secret")
|
2017-02-10 20:35:26 +01:00
|
|
|
end
|
|
|
|
|
2017-03-12 14:03:37 +01:00
|
|
|
return false
|
|
|
|
end
|