Epic/mods/trail/init.lua

370 lines
12 KiB
Lua

-- global callbacks
trail = {}
-- Parameters
local FOO = true -- Enable footprints.
local FUNCYC = 0.2 -- Function cycle in seconds.
local TRACHA = minetest.settings:get("trail_hardpack_chance") or 0.1 -- Chance walked dirt/grass is worn and compacted to trail:trail.
local ICECHA = minetest.settings:get("trail_ice_chance") or 0.05 -- Chance walked snowblock is compacted to ice.
local EROSION = minetest.settings:get_bool("trail_erosion", true) -- Enable footprint erosion.
local TRAIL_EROSION = minetest.settings:get_bool("trail_trail_erosion", true) -- Allow hard-packed soil to erode back to dirt
local EROINT = minetest.settings:get("trail_erosion_interval") or 16 -- Erosion interval.
local EROCHA = minetest.settings:get("trail_erosion_chance") or 128 -- Erosion 1/x chance.
-- Utility
local function deep_copy(input)
if type(input) ~= "table" then
return input
end
local output = {}
for index, value in pairs(input) do
output[index] = deep_copy(value)
end
return output
end
-- Player positions
local player_pos_previous = {}
minetest.register_on_joinplayer(function(player)
player_pos_previous[player:get_player_name()] = {x = 0, y = 0, z = 0}
end)
minetest.register_on_leaveplayer(function(player)
player_pos_previous[player:get_player_name()] = nil
end)
local trails = {}
local erosion = {}
trail.register_trample_node = function(trampleable_node_name, trample_def)
if trails[trampleable_node_name] then
minetest.log("error", "[trail] Attempted to call trail.register_trample_node to register trampleable node "
.. trampleable_node_name ..", which has already been registered as trampleable.")
return
end
local trampleable_node_def = minetest.registered_nodes[trampleable_node_name]
if trampleable_node_def == nil then
minetest.log("error", "[trail] Attempted to call trail.register_trample_node with the trampleable node "
.. trampleable_node_name ..", which has not yet been registered as a node.")
return
end
local trampled_node_name = trample_def.trampled_node_name or trampleable_node_name.."_trampled"
if not minetest.registered_nodes[trampled_node_name] then
local trampled_node_def = deep_copy(trampleable_node_def) -- start with a deep copy of the source node's definition
if trample_def.trampled_node_def_override then -- override any values that need to be overridden explicitly
for key, value in pairs(trample_def.trampled_node_def_override) do
trampled_node_def[key] = value
end
end
-- Set up the erosion ABM group
if EROSION and trample_def.erodes ~= false then
local groups = trampled_node_def.groups or {}
groups.trail_erodes = 1
trampled_node_def.groups = groups
erosion[trampled_node_name] = trampleable_node_name
end
-- If the source node doesn't have a special drop, then set drop to drop a source node rather than dropping a node with a footstep.
if trampled_node_def.drop == nil then
trampled_node_def.drop = trampleable_node_name
end
-- Modify the +Y tile with a footprint overlay
if trample_def.add_footprint_overlay ~= false then
local tiles = trampled_node_def.tiles
local first_tile = tiles[1]
local second_tile = tiles[2]
if second_tile == nil then
-- The provided node def only has one tile for all sides. We need to only modify the +Y tile,
-- so we need to copy the original first tile into the second tile slot
tiles[2] = deep_copy(first_tile)
end
if type(first_tile) == "table" then
first_tile.name = first_tile.name .. "^default_footprint.png"
elseif type(first_tile) == "string" then
first_tile = first_tile .. "^default_footprint.png"
end
trampled_node_def.tiles[1] = first_tile
end
minetest.register_node(":"..trampled_node_name, trampled_node_def)
-- If hard pack has been defined for this trail type, add it
local hard_pack_node_name = trample_def.hard_pack_node_name
if hard_pack_node_name then
local hard_pack_probability = trample_def.hard_pack_probability or 0.1
trails[trampled_node_name] = {name=hard_pack_node_name, probability=hard_pack_probability}
end
end
local probability = trample_def.probability or 1
trails[trampleable_node_name] = {name=trampled_node_name, probability=probability, randomize_trampled_param2 = trample_def.randomize_trampled_param2,}
end
trail.register_erosion = function(source_node_name, destination_node_name)
if not EROSION then
return
end
if minetest.registered_nodes[source_node_name] == nil then
minetest.log("error", "[trail] attempted to call trail.register_erosion with unregistered source node "
.. source_node_name)
return
end
if minetest.registered_nodes[destination_node_name] == nil then
minetest.log("error", "[trail] attempted to call trail.register_erosion with unregistered destination node "
.. destination_node_name)
return
end
if minetest.get_item_group(source_node_name, "trail_erodes") == 0 then
minetest.log("error", "[trail] attempted to call trail.register_erosion with source node "
.. destination_node_name .. " that wasn't in group trail_erodes.")
return
end
erosion[source_node_name] = destination_node_name
end
-- Nodes
-- hard-packed soil
local trail_trail_def = {
tiles = {"trail_trailtop.png", "default_dirt.png",
"default_dirt.png^trail_trailside.png"},
groups = {crumbly = 2},
drop = "default:dirt",
sounds = default.node_sound_dirt_defaults(),
}
if TRAIL_EROSION then
trail_trail_def.groups.trail_erodes = 1
end
minetest.register_node("trail:trail", trail_trail_def)
if TRAIL_EROSION then
trail.register_erosion("trail:trail", "default:dirt")
end
-- Default dirt
trail.register_trample_node("default:dirt", {
trampled_node_name = "trail:dirt",
trampled_node_def_override = {description = "Dirt with Footprint",},
hard_pack_node_name = "trail:trail",
hard_pack_probability = TRACHA,
})
trail.register_trample_node("default:dirt_with_grass", {
trampled_node_name = "trail:dirt_with_grass",
trampled_node_def_override = {description = "Dirt with Grass and Footprint",},
hard_pack_node_name = "trail:trail",
hard_pack_probability = TRACHA,
})
trail.register_trample_node("default:dirt_with_dry_grass", {
trampled_node_name = "trail:dirt_with_dry_grass",
trampled_node_def_override = {description = "Dirt with Dry Grass and Footprint",},
hard_pack_node_name = "trail:trail",
hard_pack_probability = TRACHA,
})
trail.register_trample_node("default:dirt_with_snow", {
trampled_node_name = "trail:dirt_with_snow",
trampled_node_def_override = {description = "Dirt with Snow and Footprint",},
hard_pack_node_name = "trail:trail",
hard_pack_probability = TRACHA,
})
trail.register_trample_node("default:dirt_with_rainforest_litter", {
trampled_node_name = "trail:dirt_with_rainforest_litter",
trampled_node_def_override = {description = "Dirt with Rainforest Litter and Footprint",},
hard_pack_node_name = "trail:trail",
hard_pack_probability = TRACHA,
})
trail.register_trample_node("default:dirt_with_coniferous_litter", {
trampled_node_name = "trail:dirt_with_coniferous_litter",
trampled_node_def_override = {description = "Dirt with Coniferous Litter and Footprint",},
hard_pack_node_name = "trail:trail",
hard_pack_probability = TRACHA,
})
-- Default sand
trail.register_trample_node("default:sand", {
trampled_node_name = "trail:sand",
trampled_node_def_override = {description = "Sand with Footprint",},
})
trail.register_trample_node("default:desert_sand", {
trampled_node_name = "trail:desert_sand",
trampled_node_def_override = {description = "Desert Sand with Footprint",},
})
trail.register_trample_node("default:silver_sand", {
trampled_node_name = "trail:silver_sand",
trampled_node_def_override = {description = "Silver Sand with Footprint",},
})
trail.register_trample_node("default:gravel", {
trampled_node_name = "trail:gravel",
trampled_node_def_override = {description = "Gravel with Footprint",},
})
-- Default snow
trail.register_trample_node("default:snowblock", {
trampled_node_name = "trail:snowblock",
trampled_node_def_override = {description = "Snow Block with Footprint",},
hard_pack_node_name = "default:ice",
hard_pack_probability = ICECHA,
})
trail.register_trample_node("default:snow", {
trampled_node_name = "trail:snow",
trampled_node_def_override = {description = "Snow with Footprint",},
})
--[[if minetest.get_modpath("farming") then
-- Flattened wheat
minetest.register_node("trail:wheat", {
description = "Flattened Wheat",
tiles = {"trail_flat_wheat.png"},
inventory_image = "trail_flat_wheat.png",
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "facedir",
buildable_to = true,
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, -3 / 8, 0.5}
},
},
groups = {snappy = 3, flammable = 2, attached_node = 1},
drop = "",
sounds = default.node_sound_leaves_defaults(),
})
trail.register_trample_node("farming:wheat_5", {
trampled_node_name = "trail:wheat",
randomize_trampled_param2 = true,
})
trail.register_trample_node("farming:wheat_6", {
trampled_node_name = "trail:wheat",
randomize_trampled_param2 = true,
})
trail.register_trample_node("farming:wheat_7", {
trampled_node_name = "trail:wheat",
randomize_trampled_param2 = true,
})
trail.register_trample_node("farming:wheat_8", {
trampled_node_name = "trail:wheat",
randomize_trampled_param2 = true,
})
end
--]]
-- Globalstep function
if FOO then
local timer = 0
local get_param2 = function(trail_def)
if trail_def.randomize_trampled_param2 then
return math.random(0,3)
end
return 0
end
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer > FUNCYC then
timer = 0
for _, player in ipairs(minetest.get_connected_players()) do
local pos = player:get_pos()
local player_name = player:get_player_name()
local current_player_pos = {
x = math.floor(pos.x + 0.5),
y = math.floor(pos.y + 0.2),
z = math.floor(pos.z + 0.5)
}
--if player_pos_previous[player_name] == nil then
--break
--end
if current_player_pos.x ~= player_pos_previous[player_name].x or
current_player_pos.y < player_pos_previous[player_name].y or
current_player_pos.z ~= player_pos_previous[player_name].z then
local p_snow = {
x = math.floor(pos.x + 0.5),
y = math.floor(pos.y + 1.2),
z = math.floor(pos.z + 0.5)
}
local n_snow = minetest.get_node(p_snow).name
-- test ground cover first (snow, wheat)
local trail_def = trails[n_snow]
if trail_def then
if math.random() <= trail_def.probability then
local p_snowpl = {
x = math.floor(pos.x + 0.5),
y = math.floor(pos.y + 0.5),
z = math.floor(pos.z + 0.5)
}
minetest.set_node(p_snowpl, {name = trail_def.name, param2 = get_param2(trail_def)})
end
else
local p_ground = {
x = math.floor(pos.x + 0.5),
y = math.floor(pos.y + 0.4),
z = math.floor(pos.z + 0.5)
}
local n_ground = minetest.get_node(p_ground).name
trail_def = trails[n_ground]
if trail_def and math.random() <= trail_def.probability then
local p_groundpl = {
x = math.floor(pos.x + 0.5),
y = math.floor(pos.y - 0.25),
z = math.floor(pos.z + 0.5)
}
minetest.set_node(p_groundpl, {name = trail_def.name, param2 = get_param2(trail_def)})
end
end
end
player_pos_previous[player_name] = current_player_pos
end
end
end)
end
-- ABM
if EROSION then
minetest.register_abm({
nodenames = {"group:trail_erodes"},
interval = EROINT,
chance = EROCHA,
catch_up = true,
action = function(pos, node, _, _)
local nodename = node.name
local erodes_to = erosion[nodename]
if erodes_to then
minetest.set_node(pos, {name = erodes_to})
else
minetest.log("error", "[trail] The node " .. nodename .. " is in group trail_erodes but "
.. " didn't have an erosion target node defined.")
end
end
})
end