local REALM_START = 5000 local REALM_END = 5500 rgt_realms.register_realm { name = "outback", label = "Outback", min = vector.new(-100, REALM_START, -100), max = vector.new(100, REALM_END, 100), sky = { type = "regular", sky_color = { day_sky = "#746ec9", day_horizon = "#94a3ce" }, -- fog = { -- fog_distance = 20, -- fog_start = 0.3, -- fog_color = "#aab" -- } } } local vm_data = {} function rgt.add_tree(pos) local vm = minetest.get_voxel_manip(pos:offset(-50, -50, -50), pos:offset(50, 50, 50)) local area = VoxelArea(vm:get_emerged_area()) vm:get_data(vm_data) local c_air = minetest.get_content_id("air") local c_grass = minetest.get_content_id("dirt_grass") local c_wood = minetest.get_content_id("spruce_planks") local c_root = minetest.get_content_id("path_grass") local up = vector.new(0,1,0) local tree_radius = math.random(2, 4) local canopy_height = math.random(15, 25) local offset = vector.zero() -- local trunk_height = math.random(8, 15) -- Random height for variety -- local initial_radius = math.random(2, 4) * 0.5 -- Start wider (0.5 for smoother scaling) -- local sway_strength = 0.3 -- Max sway offset per height unit -- -- local trunk_path = {} -- local current_pos = vector.new(pos.x, pos.y, pos.z) -- local target_pos = vector.new( -- pos.x + (math.random() - 0.5) * 4, -- Slight random lean -- pos.y + trunk_height, -- pos.z + (math.random() - 0.5) * 4 -- ) -- for h = 0, trunk_height, 0.5 do -- Finer steps for smoothness -- local t = h / trunk_height -- local noise_x = (math.random() - 0.5) * sway_strength * 2 -- Perlin-like noise -- local noise_z = (math.random() - 0.5) * sway_strength * 2 -- local path_pos = current_pos + (target_pos - current_pos):normalize() * 0.5 -- Step along axis -- path_pos.x = path_pos.x + noise_x -- path_pos.z = path_pos.z + noise_z -- table.insert(trunk_path, {pos = path_pos, radius = initial_radius * math.sqrt(1 - t)}) -- Exponential taper -- end -- -- -- Place trunk nodes along path (interpolate between path points for density) -- for i = 1, #trunk_path - 1 do -- local seg_start = trunk_path[i] -- local seg_end = trunk_path[i+1] -- local seg_len = vector.distance(seg_start.pos, seg_end.pos) -- for step = 0, seg_len, 1 do -- Place at integer positions -- local interp_t = step / seg_len -- local trunk_node = { -- pos = seg_start.pos + (seg_end.pos - seg_start.pos) * interp_t, -- radius = seg_start.radius + (seg_end.radius - seg_start.radius) * interp_t -- } -- local node_x, node_y, node_z = math.round(trunk_node.pos.x), math.round(trunk_node.pos.y), math.round(trunk_node.pos.z) -- local r = math.floor(trunk_node.radius + 0.5) -- Round for voxel placement -- for dx = -r, r do -- for dz = -r, r do -- local dist = vector.distance(vector.new(dx, 0, dz), vector.zero()) -- if dist <= r then -- local idx = area:index(node_x + dx, node_y, node_z + dz) -- if vm_data[idx] == c_air then -- Only overwrite air -- vm_data[idx] = c_wood -- end -- end -- end -- end -- end -- end -- Generate the trunk. local r = tree_radius local p = pos for y = 0, canopy_height do for x = -r, r do for z = -r, r do if vector.distance(vector.new(x, 0, z), vector.zero()) <= r then vm_data[area:index(math.round(p.x +x), math.round(p.y), math.round(p.z +z))] = c_wood end end end p = p:offset(0,1,0) --+vector.rotate_around_axis(vector.new(0,0,0.2), up, math.pi *2 *(math.random() -0.5)) end --Generate roots. local num_roots = math.random(3, 6) +math.floor(math.abs(tree_radius -3) ^2) for i = 1, num_roots do local dir = vector.rotate_around_axis(vector.new(0,0,1), up, math.pi *2 /num_roots *i) local length = math.random() *6 +3 p = pos +(dir *math.floor(tree_radius +1)) while length > 0 do local pr = p:round() -- Check up to 3 nodes down for grass. for j = 1, 3 do if vm_data[area:index(pr.x, pr.y, pr.z)] ~= c_air then break end p.y = p.y -1 pr.y = pr.y -1 end -- End the root if it would be too vertical. if vm_data[area:index(pr.x, pr.y, pr.z)] == c_air then break end vm_data[area:index(pr.x, pr.y, pr.z)] = c_root length = length -1 -- Randomly nudge the root direction. -- dir = dir:rotate_around_axis(up, math.random() *1.5 -0.5) p = p +dir:rotate_around_axis(up, math.random() *1.5 -0.5) end end vm:set_data(vm_data) vm:write_to_map() end rgt.register_node("outback_planks", { tiles = {"rgt_outback_planks.png"}, groups = {hand_breakable = 3} }) rgt.register_node("dirt_stony", { tiles = {"rgt_dirt_stony.png", "rgt_dirt.png"}, groups = {hand_breakable = 3} }) rgt.register_node("cobble_mossy", { tiles = {"rgt_cobble_mossy.png"}, groups = {hand_breakable = 3} }) minetest.register_mapgen_script(minetest.get_modpath(minetest.get_current_modname()).."/mapgen.lua")