544 lines
15 KiB
Lua
544 lines
15 KiB
Lua
-- Squaresville deco.lua
|
|
-- Copyright Duane Robertson (duane@duanerobertson.com), 2017
|
|
-- Distributed under the LGPLv2.1 (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
|
|
|
|
|
|
local dangerous = squaresville.dangerous_terrain
|
|
squaresville.decorations = {}
|
|
squaresville.decorations_schem = {}
|
|
|
|
local math_abs = math.abs
|
|
local math_floor = math.floor
|
|
|
|
|
|
for i = 2, 4 do
|
|
minetest.register_decoration({
|
|
deco_type = "schematic",
|
|
place_on = {"default:dirt_with_snow", "default:dirt_with_grass"},
|
|
sidelen = 16,
|
|
noise_params = {
|
|
offset = 0.012,
|
|
scale = 0.022,
|
|
spread = {x = 250, y = 250, z = 250},
|
|
seed = (84 - 7 * i),
|
|
octaves = 3,
|
|
persist = 0.66
|
|
},
|
|
biomes = {"taiga", "coniferous_forest", "floatland_coniferous_forest"},
|
|
y_min = 2,
|
|
y_max = 31000,
|
|
schematic = squaresville.path .. "/schematics/pine_tree"..i..".mts",
|
|
flags = "place_center_x, place_center_z",
|
|
})
|
|
|
|
minetest.register_decoration({
|
|
deco_type = "schematic",
|
|
place_on = {"default:dirt_with_grass"},
|
|
sidelen = 16,
|
|
noise_params = {
|
|
offset = 0.012,
|
|
scale = 0.022,
|
|
spread = {x = 250, y = 250, z = 250},
|
|
seed = (139 - 7 * i),
|
|
octaves = 3,
|
|
persist = 0.66
|
|
},
|
|
biomes = {"deciduous_forest", 'desertstone_grassland'},
|
|
y_min = 1,
|
|
y_max = 31000,
|
|
schematic = squaresville.path .. "/schematics/apple_tree"..i..".mts",
|
|
flags = "place_center_x, place_center_z",
|
|
rotation = "random",
|
|
})
|
|
end
|
|
|
|
minetest.register_decoration({
|
|
deco_type = "schematic",
|
|
place_on = {"default:dirt_with_grass"},
|
|
sidelen = 16,
|
|
noise_params = {
|
|
offset = 0,
|
|
scale = 0.022,
|
|
spread = {x = 250, y = 250, z = 250},
|
|
seed = 119,
|
|
octaves = 3,
|
|
persist = 0.66
|
|
},
|
|
biomes = {"deciduous_forest"},
|
|
y_min = 1,
|
|
y_max = 31000,
|
|
schematic = squaresville.path .. "/schematics/cherry_tree.mts",
|
|
flags = "place_center_x, place_center_z",
|
|
rotation = "random",
|
|
})
|
|
|
|
minetest.register_decoration({
|
|
deco_type = "schematic",
|
|
place_on = {"default:polluted_dirt"},
|
|
sidelen = 16,
|
|
noise_params = {
|
|
offset = 0.036,
|
|
scale = 0.022,
|
|
spread = {x = 250, y = 250, z = 250},
|
|
seed = 666,
|
|
octaves = 3,
|
|
persist = 0.66
|
|
},
|
|
biomes = {"toxic_forest"},
|
|
y_min = 1,
|
|
y_max = 31000,
|
|
schematic = squaresville.path .. "/schematics/decaying_tree.mts",
|
|
flags = "place_center_x, place_center_z",
|
|
rotation = "random",
|
|
})
|
|
|
|
|
|
do
|
|
for _, odeco in pairs(minetest.registered_decorations) do
|
|
local deco = table.copy(odeco)
|
|
deco.place_on = table.copy(odeco.place_on)
|
|
deco.flags = {}
|
|
|
|
if odeco.biomes then
|
|
deco.biomes = {}
|
|
for _, b in pairs(odeco.biomes) do
|
|
deco.biomes[b] = true
|
|
end
|
|
end
|
|
|
|
if odeco.flags then
|
|
for f in odeco.flags:gmatch('[%w_]+') do
|
|
deco.flags[f] = true
|
|
end
|
|
end
|
|
|
|
local nod = minetest.registered_nodes[deco.decoration]
|
|
if nod and nod.groups and nod.groups.flower then
|
|
deco.flower = true
|
|
end
|
|
|
|
if odeco.schematic then
|
|
deco.name = odeco.schematic:match('([%w_]+)%.mts') or odeco.schematic
|
|
elseif odeco.decoration and type(odeco.decoration) == 'string' then
|
|
deco.name = odeco.decoration:match('.*:([%w_]+)') or odeco.decoration
|
|
end
|
|
|
|
if deco.name == 'apple_tree' or deco.name == 'pine_tree' then
|
|
deco.noise_params.offset = 0.012
|
|
if deco.name == 'apple_tree' then
|
|
deco.biomes['desertstone_grassland'] = true
|
|
end
|
|
elseif deco.name == 'junglegrass' then
|
|
deco.biomes['desertstone_grassland'] = true
|
|
deco.place_on[#deco.place_on+1] = 'default:dirt_with_grass'
|
|
elseif deco.name == 'jungle_tree' then
|
|
deco.schematic = squaresville.path..'/schematics/jungle_tree_with_orchids.mts'
|
|
end
|
|
|
|
squaresville.decorations[#squaresville.decorations+1] = deco
|
|
end
|
|
end
|
|
|
|
|
|
squaresville.biomes = {}
|
|
local biomes = squaresville.biomes
|
|
local biome_names = {}
|
|
do
|
|
local biome_mod = {
|
|
tundra = { node_top = 'default:snowblock', depth_top = 1 },
|
|
rainforest = { civ = 'desertstone_grassland' },
|
|
}
|
|
|
|
for i, obiome in pairs(minetest.registered_biomes) do
|
|
local biome = table.copy(obiome)
|
|
biomes[biome.name] = biome
|
|
biome_names[#biome_names+1] = biome.name
|
|
|
|
-- Make changes to biome values from biome_mod.
|
|
for n, bi in pairs(biome_mod) do
|
|
for i, rbi in pairs(biomes) do
|
|
if rbi.name == n then
|
|
for j, prop in pairs(bi) do
|
|
biomes[i][j] = prop
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
biomes["desertstone_grassland"] = {
|
|
name = "desertstone_grassland",
|
|
--node_dust = "",
|
|
node_top = "default:dirt_with_grass",
|
|
depth_top = 1,
|
|
node_filler = "default:dirt",
|
|
depth_filler = 1,
|
|
node_stone = "default:desert_stone",
|
|
node_riverbed = "default:sand",
|
|
depth_riverbed = 2,
|
|
--node_water_top = "",
|
|
--depth_water_top = ,
|
|
--node_water = "",
|
|
--node_river_water = "",
|
|
y_min = squaresville.max_height,
|
|
y_max = squaresville.max_height,
|
|
heat_point = 86,
|
|
humidity_point = 50,
|
|
}
|
|
|
|
if dangerous then
|
|
biomes["toxic_forest"] = {
|
|
name = "toxic_forest",
|
|
node_top = "squaresville:polluted_dirt",
|
|
danger = 3,
|
|
depth_top = 1,
|
|
node_filler = "squaresville:polluted_dirt",
|
|
depth_filler = 1,
|
|
node_riverbed = "squaresville:polluted_dirt",
|
|
depth_riverbed = 1,
|
|
node_water = "squaresville:water_poison_source",
|
|
node_river_water = "squaresville:water_poison_source",
|
|
special_trees = {"decaying_tree"},
|
|
y_min = 1,
|
|
y_max = squaresville.max_height,
|
|
heat_point = 20,
|
|
humidity_point = 50,
|
|
}
|
|
|
|
biomes["toxic_forest_ocean"] = {
|
|
name = "toxic_forest_ocean",
|
|
node_top = "squaresville:polluted_dirt",
|
|
danger = 3,
|
|
depth_top = 1,
|
|
node_filler = "squaresville:polluted_dirt",
|
|
depth_filler = 1,
|
|
node_riverbed = "squaresville:polluted_dirt",
|
|
depth_riverbed = 1,
|
|
node_water = "squaresville:water_poison_source",
|
|
node_river_water = "squaresville:water_poison_source",
|
|
y_min = -10,
|
|
y_max = 0,
|
|
heat_point = 20,
|
|
humidity_point = 50,
|
|
}
|
|
|
|
biomes["draconic"] = {
|
|
name = "draconic",
|
|
--node_dust = "",
|
|
node_top = "squaresville:cracked_stone",
|
|
depth_top = 1,
|
|
node_filler = "squaresville:granite",
|
|
depth_filler = 1,
|
|
node_stone = "squaresville:granite",
|
|
--node_water_top = "",
|
|
--depth_water_top = ,
|
|
--node_water = "",
|
|
node_river_water = "squaresville:basalt",
|
|
node_riverbed = "squaresville:basalt",
|
|
depth_riverbed = 2,
|
|
danger = 3,
|
|
y_min = 1,
|
|
y_max = squaresville.max_height,
|
|
heat_point = 80,
|
|
humidity_point = 20,
|
|
}
|
|
|
|
biomes["draconic_ocean"] = {
|
|
name = "draconic_ocean",
|
|
--node_dust = "",
|
|
node_top = "squaresville:granite",
|
|
depth_top = 1,
|
|
danger = 3,
|
|
node_filler = "squaresville:granite",
|
|
depth_filler = 3,
|
|
node_stone = "squaresville:granite",
|
|
y_min = -20,
|
|
y_max = 0,
|
|
heat_point = 80,
|
|
humidity_point = 20,
|
|
}
|
|
|
|
biomes["bizarre"] = {
|
|
name = "bizarre",
|
|
--node_dust = "",
|
|
node_top = "squaresville:dirt_with_odd_grass",
|
|
depth_top = 1,
|
|
node_filler = "default:dirt",
|
|
depth_filler = 1,
|
|
node_stone = "squaresville:basalt",
|
|
--node_water_top = "",
|
|
--depth_water_top = ,
|
|
--node_water = "",
|
|
--node_river_water = "squaresville:basalt",
|
|
--node_riverbed = "squaresville:basalt",
|
|
--depth_riverbed = 2,
|
|
special_trees = {'fur_tree'},
|
|
danger = 3,
|
|
y_min = 1,
|
|
y_max = squaresville.max_height,
|
|
heat_point = 60,
|
|
humidity_point = 70,
|
|
}
|
|
|
|
biomes["bizarre_ocean"] = {
|
|
name = "bizarre_ocean",
|
|
--node_dust = "",
|
|
node_top = "default:sand",
|
|
depth_top = 1,
|
|
danger = 3,
|
|
node_filler = "default:sand",
|
|
depth_filler = 3,
|
|
node_stone = "squaresville:basalt",
|
|
y_min = -20,
|
|
y_max = 0,
|
|
heat_point = 60,
|
|
humidity_point = 70,
|
|
}
|
|
end
|
|
end
|
|
|
|
|
|
local function register_flower(name, desc, biomes, seed)
|
|
local groups = {}
|
|
groups.snappy = 3
|
|
groups.flammable = 2
|
|
groups.flower = 1
|
|
groups.flora = 1
|
|
groups.attached_node = 1
|
|
|
|
minetest.register_node("squaresville:" .. name, {
|
|
description = desc,
|
|
drawtype = "plantlike",
|
|
waving = 1,
|
|
tiles = {"squaresville_" .. name .. ".png"},
|
|
inventory_image = "squaresville_" .. name .. ".png",
|
|
wield_image = "squaresville_" .. name .. ".png",
|
|
sunlight_propagates = true,
|
|
paramtype = "light",
|
|
walkable = false,
|
|
buildable_to = true,
|
|
stack_max = 99,
|
|
groups = groups,
|
|
sounds = default.node_sound_leaves_defaults(),
|
|
selection_box = {
|
|
type = "fixed",
|
|
fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5},
|
|
}
|
|
})
|
|
|
|
local bi = {}
|
|
if biomes then
|
|
bi = {}
|
|
for _, b in pairs(biomes) do
|
|
bi[b] = true
|
|
end
|
|
end
|
|
|
|
local def = {
|
|
deco_type = "simple",
|
|
place_on = {"default:dirt_with_grass", 'default:dirt_with_rainforest_litter'},
|
|
sidelen = 16,
|
|
noise_params = {
|
|
offset = -0.015,
|
|
scale = 0.025,
|
|
spread = {x = 200, y = 200, z = 200},
|
|
seed = seed,
|
|
octaves = 3,
|
|
persist = 0.6
|
|
},
|
|
biomes = bi,
|
|
y_min = 1,
|
|
y_max = 31000,
|
|
decoration = "squaresville:"..name,
|
|
name = name,
|
|
flower = true,
|
|
}
|
|
squaresville.decorations[#squaresville.decorations+1] = def
|
|
|
|
if bi['rainforest'] then
|
|
def = table.copy(def)
|
|
def.noise_params = table.copy(def.noise_params)
|
|
def.noise_params.offset = 0.015
|
|
def.place_on = {'default:dirt_with_rainforest_litter'}
|
|
def.biomes = {['rainforest'] = true, ['rainforest_swamp'] = true}
|
|
squaresville.decorations[#squaresville.decorations+1] = def
|
|
end
|
|
end
|
|
|
|
register_flower("orchid", "Orchid", {"rainforest", "rainforest_swamp"}, 783)
|
|
register_flower("bird_of_paradise", "Bird of Paradise", {"rainforest", "desertstone_grassland"}, 798)
|
|
register_flower("gerbera", "Gerbera", {"savanna", "rainforest", "desertstone_grassland"}, 911)
|
|
|
|
|
|
local function register_decoration(deco, place_on, biomes, chance)
|
|
local bi = {}
|
|
if biomes then
|
|
bi = {}
|
|
for _, b in pairs(biomes) do
|
|
bi[b] = true
|
|
end
|
|
end
|
|
|
|
squaresville.decorations[#squaresville.decorations+1] = {
|
|
deco_type = "simple",
|
|
place_on = place_on,
|
|
sidelen = 16,
|
|
biomes = bi,
|
|
fill_ratio = chance,
|
|
y_min = 1,
|
|
y_max = 31000,
|
|
decoration = deco,
|
|
name = deco:match('[^:]+$'),
|
|
}
|
|
end
|
|
|
|
|
|
if dangerous then
|
|
--register_decoration('default:lava_source', 'squaresville:cracked_stone', {'draconic'}, 0.0005)
|
|
register_decoration('squaresville:blackened_shrub', 'squaresville:polluted_dirt', {'toxic_forest'}, 0.05)
|
|
register_decoration('flowers:mushroom_red', 'squaresville:polluted_dirt', {'toxic_forest'}, 0.05)
|
|
register_decoration('squaresville:strange_plant_1', 'squaresville:dirt_with_odd_grass', {'bizarre'}, 0.05)
|
|
register_decoration('squaresville:strange_plant_2', 'squaresville:dirt_with_odd_grass', {'bizarre'}, 0.05)
|
|
|
|
for i = 1, 4 do
|
|
register_decoration('squaresville:stone_spike_'..i, 'squaresville:cracked_stone', {'draconic'}, 0.02 / i)
|
|
end
|
|
end
|
|
|
|
|
|
local function place_deco(mg, ps, deco)
|
|
local data, a = mg.data, mg.area
|
|
local minp, maxp = mg.minp, mg.maxp
|
|
local heightmap, biomemap, schem = mg.heightmap, mg.biomemap, mg.schem
|
|
|
|
local csize = mg.csize
|
|
local sidelen = deco.sidelen or csize.x
|
|
local node = squaresville.node
|
|
local max_height = squaresville.max_height
|
|
|
|
local node_air = node['air']
|
|
local node_ignore = node['ignore']
|
|
local node_water = node['default:water_source']
|
|
|
|
if csize.x % sidelen ~= 0 then
|
|
sidelen = csize.x
|
|
end
|
|
|
|
local divlen = csize.x / sidelen
|
|
local area = sidelen * sidelen
|
|
|
|
for z0 = 0, divlen-1 do
|
|
for x0 = 0, divlen-1 do
|
|
local center = {
|
|
x=math_floor(minp.x + sidelen / 2 + sidelen * x0),
|
|
z=math_floor(minp.z + sidelen / 2 + sidelen * z0),
|
|
}
|
|
local min = {
|
|
x=minp.x + sidelen * x0,
|
|
z=minp.z + sidelen * z0,
|
|
}
|
|
local max = {
|
|
x=minp.x + sidelen + sidelen * x0 - 1,
|
|
z=minp.z + sidelen + sidelen * z0 - 1,
|
|
}
|
|
local nval = deco.noise_params and minetest.get_perlin(deco.noise_params):get2d({x=center.x, y=center.z}) or deco.fill_ratio
|
|
local deco_count = area * nval
|
|
if deco_count > 1 then
|
|
deco_count = math_floor(deco_count)
|
|
elseif deco_count > 0 then
|
|
if ps:next(1, 1000) <= deco_count * 1000 then
|
|
deco_count = 1
|
|
else
|
|
deco_count = 0
|
|
end
|
|
end
|
|
for i = 1, deco_count do
|
|
local x = ps:next(min.x, max.x)
|
|
local z = ps:next(min.z, max.z)
|
|
local mapindex = csize.x * (z - minp.z) + (x - minp.x) + 1
|
|
local y = -squaresville.max_height
|
|
if deco.liquid_surface then
|
|
print('Squaresville: Invalid liquid_surface parameter')
|
|
--y = find_liquid_surface()
|
|
elseif heightmap then
|
|
y = heightmap[mapindex]
|
|
else
|
|
print('Squaresville: Cannot generate heightmap')
|
|
--y = find_ground()
|
|
end
|
|
if y > -max_height and y < max_height and y >= minp.y and y <= maxp.y and y - mg.baseline >= (deco.y_min or -max_height) and y - mg.baseline <= (deco.y_max or max_height) then
|
|
local biome
|
|
if biomemap then
|
|
biome = biomemap[mapindex]
|
|
end
|
|
if not deco.biomes or deco.biomes[biome.name] then
|
|
local ivm = a:index(x, y, z)
|
|
if (not deco.place_on) or deco.place_on[data[ivm]] then
|
|
ivm = ivm + a.ystride
|
|
if deco.deco_type == 'schematic' then
|
|
local too_close
|
|
local size_s = deco.size_offset and ((deco.size_offset.x + 1) * (deco.size_offset.z + 1)) or 9
|
|
for _, s in ipairs(schem) do
|
|
local dx, dz = s.pos.x - x, s.pos.z - z
|
|
if dx * dx + dz * dz <= size_s then
|
|
too_close = true
|
|
break
|
|
end
|
|
end
|
|
if not too_close then
|
|
schem[#schem+1] = {def=deco, pos={x=x,y=y,z=z}}
|
|
end
|
|
elseif data[ivm] == node_air then
|
|
data[ivm] = node[deco.decoration]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local first_check = true
|
|
function squaresville.place_all_decorations(mg)
|
|
local ps = PcgRandom(mg.seed + 53)
|
|
|
|
for i, deco in pairs(squaresville.decorations) do
|
|
if first_check and deco.place_on then
|
|
local new_p = {}
|
|
if type(deco.place_on) ~= 'table' then
|
|
deco.place_on = {deco.place_on}
|
|
end
|
|
|
|
for i, d in ipairs(deco.place_on) do
|
|
if type(d) == 'string' then
|
|
new_p[squaresville.node[d]] = squaresville.node[d]
|
|
end
|
|
end
|
|
deco.place_on = new_p
|
|
end
|
|
|
|
place_deco(mg, ps, deco)
|
|
end
|
|
|
|
first_check = nil
|
|
end
|
|
|
|
|
|
-- This lets rarer spawns overwrite the more common.
|
|
table.sort(squaresville.decorations, function(a, b)
|
|
if a.fill_ratio and b.fill_ratio and a.fill_ratio < b.fill_ratio then
|
|
return true
|
|
elseif a.fill_ratio and not b.fill_ratio then
|
|
return true
|
|
elseif b.fill_ratio and not a.fill_ratio then
|
|
return false
|
|
elseif not (a.fill_ratio or b.fill_ratio) and a.noise_params and b.noise_params and a.noise_params.scale + a.noise_params.offset > b.noise_params.scale + b.noise_params.offset then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end)
|