123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- -- 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
|