Add new mg/ dependency
27
ROADMAP
|
@ -103,17 +103,32 @@ with exaltion
|
|||
the player's inventory"
|
||||
|
||||
**** TODO [NPC_village] Testing a NPC village mod
|
||||
CLOCK: [2018-12-14 ven. 15:14]--[2018-12-14 ven. 15:53] => 0:39
|
||||
CLOCK: [2018-12-13 jeu. 15:56]--[2018-12-13 jeu. 16:13] => 0:17
|
||||
- [X] Should switch to v 0.4.17.1 : Not yet, still working with 0.4.16
|
||||
- [X] Must update README.md : no need to download my game, just connect to server
|
||||
- [ ] Maybe remove mods/ambience/music/sounds/SoundLicenses.txt copyrighted songs
|
||||
- [ ] Find some female skins
|
||||
- [ ] May add a NPC village mod : https://github.com/hkzorman/advanced_npc
|
||||
- [X] Maybe remove mods/ambience/music/sounds/SoundLicenses.txt copyrighted songs
|
||||
- [-] May add a NPC village mod : https://github.com/hkzorman/advanced_npc
|
||||
see https://forum.minetest.net/viewtopic.php?t=5120 (best)
|
||||
or (simpler) https://forum.minetest.net/viewtopic.php?t=5120
|
||||
- [ ] Generated a new world. Now flying and testing
|
||||
- [ ] Can't find a NPC village, read further documentation
|
||||
- [ ] Maybe the mg_villages dependency
|
||||
- [-] Testing advanced_pc Generated a new world. Now flying and testing
|
||||
- [ ] Can't find a NPC village, read further documentation
|
||||
- [X] Maybe the mg_villages dependency https://github.com/Sokomine/mg_villages
|
||||
- [ ] Now, must install handle_schematics
|
||||
|
||||
- [ ] Actual mg_villages error
|
||||
ServerError: AsyncErr: Lua: finishGenRuntime error from mod 'mg_villages' in callback environment_OnGenerated(): ...inetest/games/minetest-pvp/mods/mg_villages/villages.lua:27: attempt to call method 'get_2d' (a nil value)
|
||||
stack traceback:
|
||||
...inetest/games/minetest-pvp/mods/mg_villages/villages.lua:27: in function 'villages_at_point'
|
||||
....minetest/games/minetest-pvp/mods/mg_villages/mapgen.lua:81: in function 'villages_in_mapchunk'
|
||||
....minetest/games/minetest-pvp/mods/mg_villages/mapgen.lua:1293: in function <....minetest/games/minetest-pvp/mods/mg_villages/mapgen.lua:1273>
|
||||
/usr/local/share/minetest/builtin/game/register.lua:412: in function </usr/local/share/minetest/builtin/game/register.lua:392>
|
||||
|
||||
|
||||
|
||||
- [ ] Find some female skins
|
||||
- See this error WARNING[Server]: Assignment to undeclared global "p2" inside a function at ...rainbru/.minetest/games/minetest-pvp/mods/ruins/init.lua:99.
|
||||
|
||||
**** DONE Must find back my whole mapper
|
||||
CLOCK: [2018-12-13 jeu. 16:13]--[2018-12-13 jeu. 16:27] => 0:14
|
||||
*it was a C++ program* downloaded and compiled
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
*~
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
mg - Experimental Mapgen for Minetest
|
||||
|
||||
A custom Lua-mapgen, with biomes, caves, villages, cliffs and ore generation.
|
||||
|
||||
Biomes: Ocean, Dry grasslands, Wet grasslands, Forest, Jungle, Savanna, Desert,
|
||||
Tundra, Taiga, Beach.
|
||||
|
||||
To use, enable the mod before playing a world for the first time (do not use it in an already used world).
|
||||
|
||||
License:
|
||||
LGPL >= 2.1 for the code
|
||||
CC-BY-SA for the textures
|
|
@ -0,0 +1,55 @@
|
|||
buildings = {
|
||||
{sizex= 7, sizez= 7, yoff= 0, ysize= 9, scm="house", orients={2}},
|
||||
{sizex= 9, sizez= 9, yoff= 0, ysize= 2, scm="wheat_field"},
|
||||
{sizex= 9, sizez= 9, yoff= 0, ysize= 2, scm="cotton_field"},
|
||||
{sizex= 3, sizez= 3, yoff= 1, ysize= 4, scm="lamp", weight=1/5, no_rotate=true},
|
||||
{sizex= 4, sizez= 4, yoff=-5, ysize=11, scm="well", no_rotate=true, pervillage=1},
|
||||
{sizex= 7, sizez= 7, yoff= 0, ysize= 6, scm="fountain", weight=1/4, pervillage=3},
|
||||
{sizex= 5, sizez= 5, yoff= 0, ysize= 6, scm="small_house", orients={3}},
|
||||
{sizex= 6, sizez=12, yoff= 0, ysize= 7, scm="house_with_garden", orients={1}},
|
||||
{sizex=16, sizez=17, yoff= 0, ysize=12, scm="church", orients={3}, pervillage=1},
|
||||
{sizex= 5, sizez= 5, yoff= 0, ysize=16, scm="tower", orients={0}, weight=1/7},
|
||||
{sizex= 8, sizez= 9, yoff= 0, ysize= 6, scm="forge", orients={0}, pervillage=2},
|
||||
{sizex=11, sizez=12, yoff= 0, ysize= 6, scm="library", orients={1}, pervillage=2},
|
||||
{sizex=15, sizez= 7, yoff= 0, ysize=12, scm="inn", orients={1}, pervillage=4, weight=1/2},
|
||||
{sizex=22, sizez=17, yoff= 0, ysize= 7, scm="pub", orients={3}, pervillage=2, weight=1/3},
|
||||
}
|
||||
|
||||
local gravel = minetest.get_content_id("default:gravel")
|
||||
local rgravel = {}
|
||||
for i = 1, 2000 do
|
||||
rgravel[i] = gravel
|
||||
end
|
||||
local rgravel2 = {}
|
||||
for i = 1, 2000 do
|
||||
rgravel2[i] = rgravel
|
||||
end
|
||||
local rair = {}
|
||||
for i = 1, 2000 do
|
||||
rair[i] = c_air
|
||||
end
|
||||
local rair2 = {}
|
||||
for i = 1, 2000 do
|
||||
rair2[i] = rair
|
||||
end
|
||||
local road_scm = {rgravel2, rair2}
|
||||
buildings["road"] = {yoff = 0, ysize = 2, scm = road_scm}
|
||||
|
||||
local rwall = {{minetest.get_content_id("default:stonebrick")}}
|
||||
local wall = {}
|
||||
for i = 1, 6 do
|
||||
wall[i] = rwall
|
||||
end
|
||||
buildings["wall"] = {yoff = 1, ysize = 6, scm = wall}
|
||||
|
||||
|
||||
local total_weight = 0
|
||||
for _, i in ipairs(buildings) do
|
||||
if i.weight == nil then i.weight = 1 end
|
||||
total_weight = total_weight+i.weight
|
||||
i.max_weight = total_weight
|
||||
end
|
||||
local multiplier = 3000/total_weight
|
||||
for _,i in ipairs(buildings) do
|
||||
i.max_weight = i.max_weight*multiplier
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
default
|
||||
farming
|
||||
wool
|
||||
stairs
|
||||
moretrees?
|
|
@ -0,0 +1,2 @@
|
|||
This mod changes the default map generation: it changes the way ores are placed, add new biomes and villages.
|
||||
Note: do NOT use it in an already generated world!!!
|
|
@ -0,0 +1,805 @@
|
|||
mg = {}
|
||||
|
||||
local ENABLE_SNOW = false
|
||||
local DEBUG = false
|
||||
|
||||
local DMAX = 20
|
||||
local AREA_SIZE = 80
|
||||
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/nodes.lua")
|
||||
|
||||
local function get_content_id(name)
|
||||
name = minetest.registered_aliases[name] or name
|
||||
return minetest.get_content_id(name)
|
||||
end
|
||||
|
||||
c_air = get_content_id("air")
|
||||
c_ignore = get_content_id("ignore")
|
||||
c_water = get_content_id("default:water_source")
|
||||
c_grass = get_content_id("default:dirt_with_grass")
|
||||
c_dry_grass = get_content_id("mg:dirt_with_dry_grass")
|
||||
c_dirt_snow = get_content_id("default:dirt_with_snow")
|
||||
c_snow = get_content_id("default:snow")
|
||||
c_sapling = get_content_id("default:sapling")
|
||||
c_tree = get_content_id("default:tree")
|
||||
c_leaves = get_content_id("default:leaves")
|
||||
c_junglesapling = get_content_id("default:junglesapling")
|
||||
c_jungletree = get_content_id("default:jungletree")
|
||||
c_jungleleaves = get_content_id("default:jungleleaves")
|
||||
c_savannasapling = get_content_id("mg:savannasapling")
|
||||
c_savannatree = get_content_id("mg:savannatree")
|
||||
c_savannaleaves = get_content_id("mg:savannaleaves")
|
||||
c_pinesapling = get_content_id("mg:pinesapling")
|
||||
c_pinetree = get_content_id("mg:pinetree")
|
||||
c_pineleaves = get_content_id("mg:pineleaves")
|
||||
c_dirt = get_content_id("default:dirt")
|
||||
c_stone = get_content_id("default:stone")
|
||||
c_water = get_content_id("default:water_source")
|
||||
c_ice = get_content_id("default:ice")
|
||||
c_sand = get_content_id("default:sand")
|
||||
c_sandstone = get_content_id("default:sandstone")
|
||||
c_desert_sand = get_content_id("default:desert_sand")
|
||||
c_desert_stone = get_content_id("default:desert_stone")
|
||||
c_snowblock = get_content_id("default:snowblock")
|
||||
c_cactus = get_content_id("default:cactus")
|
||||
c_grass_1 = get_content_id("default:grass_1")
|
||||
c_grass_2 = get_content_id("default:grass_2")
|
||||
c_grass_3 = get_content_id("default:grass_3")
|
||||
c_grass_4 = get_content_id("default:grass_4")
|
||||
c_grass_5 = get_content_id("default:grass_5")
|
||||
c_grasses = {c_grass_1, c_grass_2, c_grass_3, c_grass_4, c_grass_5}
|
||||
c_jungle_grass = get_content_id("default:junglegrass")
|
||||
c_dry_shrub = get_content_id("default:dry_shrub")
|
||||
c_papyrus = get_content_id("default:papyrus")
|
||||
|
||||
minetest.register_on_mapgen_init(function(mgparams)
|
||||
minetest.set_mapgen_params({mgname = "singlenode", flags = "nolight"})
|
||||
end)
|
||||
|
||||
local cache = {}
|
||||
|
||||
local function cliff(x, n)
|
||||
return 0.2*x*x - x + n*x - n*n*x*x - 0.01 * math.abs(x*x*x) + math.abs(x)*100*n*n*n*n
|
||||
end
|
||||
|
||||
local function get_vn(x, z, noise, village)
|
||||
local vx, vz, vs = village.vx, village.vz, village.vs
|
||||
return (noise - 2) * 20 +
|
||||
(40 / (vs * vs)) * ((x - vx) * (x - vx) + (z - vz) * (z - vz))
|
||||
end
|
||||
|
||||
local function get_base_surface_at_point(x, z, vnoise, villages, ni, noise1, noise2, noise3, noise4)
|
||||
local index = 65536*x+z
|
||||
if cache[index] ~= nil then return cache[index] end
|
||||
cache[index] = 25*noise1[ni]+noise2[ni]*noise3[ni]/3
|
||||
if noise4[ni] > 0.8 then
|
||||
cache[index] = cliff(cache[index], noise4[ni]-0.8)
|
||||
end
|
||||
local s = 0
|
||||
local t = 0
|
||||
local noise = vnoise[ni]
|
||||
for _, village in ipairs(villages) do
|
||||
local vn = get_vn(x, z, noise, village)
|
||||
if vn < 40 then
|
||||
cache[index] = village.vh
|
||||
return village.vh
|
||||
elseif vn < 200 then
|
||||
s = s + ((cache[index] * (vn - 40) + village.vh * (200 - vn)) / 160) / (vn - 40)
|
||||
t = t + 1 / (vn - 40)
|
||||
end
|
||||
end
|
||||
if t > 0 then
|
||||
cache[index] = s / t
|
||||
end
|
||||
return cache[index]
|
||||
end
|
||||
|
||||
local function surface_at_point(x, z, ...)
|
||||
return get_base_surface_at_point(x, z, unpack({...}))
|
||||
end
|
||||
|
||||
local SMOOTHED = AREA_SIZE+2*DMAX
|
||||
local HSMOOTHED = AREA_SIZE+DMAX
|
||||
local INSIDE = AREA_SIZE-DMAX
|
||||
|
||||
local function smooth(x, z, ...)
|
||||
local s=0
|
||||
local w=0
|
||||
for xi=-DMAX, DMAX do
|
||||
for zi=-DMAX, DMAX do
|
||||
local d2=xi*xi+zi*zi
|
||||
if d2<DMAX*DMAX then
|
||||
local w1 = 1-d2/(DMAX*DMAX)
|
||||
local w2 = 15/16*w1*w1
|
||||
w = w+w2
|
||||
s=s+w2*surface_at_point(x+xi, z+zi, unpack({...}))
|
||||
end
|
||||
end
|
||||
end
|
||||
return s/w
|
||||
end
|
||||
|
||||
function inside_village(x, z, village, vnoise)
|
||||
return get_vn(x, z, vnoise:get2d({x = x, y = z}), village) <= 40
|
||||
end
|
||||
|
||||
local wseed
|
||||
minetest.register_on_mapgen_init(function(mgparams)
|
||||
wseed = math.floor(mgparams.seed/10000000000)
|
||||
end)
|
||||
function get_bseed(minp)
|
||||
return wseed + math.floor(5*minp.x/47) + math.floor(873*minp.z/91)
|
||||
end
|
||||
|
||||
function get_bseed2(minp)
|
||||
return wseed + math.floor(87*minp.x/47) + math.floor(73*minp.z/91) + math.floor(31*minp.y/12)
|
||||
end
|
||||
|
||||
local function add_leaves(data, vi, c_leaves, c_snow)
|
||||
if data[vi]==c_air or data[vi]==c_ignore or data[vi] == c_snow then
|
||||
data[vi] = c_leaves
|
||||
end
|
||||
end
|
||||
|
||||
function add_tree(data, a, x, y, z, minp, maxp, pr)
|
||||
local th = pr:next(3, 4)
|
||||
for yy=math.max(minp.y, y), math.min(maxp.y, y+th) do
|
||||
local vi = a:index(x, yy, z)
|
||||
data[vi] = c_tree
|
||||
end
|
||||
local maxy = y+th
|
||||
for xx=math.max(minp.x, x-1), math.min(maxp.x, x+1) do
|
||||
for yy=math.max(minp.y, maxy-1), math.min(maxp.y, maxy+1) do
|
||||
for zz=math.max(minp.z, z-1), math.min(maxp.z, z+1) do
|
||||
add_leaves(data, a:index(xx, yy, zz), c_leaves)
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1,8 do
|
||||
local xi = pr:next(x-2, x+1)
|
||||
local yi = pr:next(maxy-1, maxy+1)
|
||||
local zi = pr:next(z-2, z+1)
|
||||
for xx=math.max(minp.x, xi), math.min(maxp.x, xi+1) do
|
||||
for yy=math.max(minp.y, yi), math.min(maxp.y, yi+1) do
|
||||
for zz=math.max(minp.z, zi), math.min(maxp.z, zi+1) do
|
||||
add_leaves(data, a:index(xx, yy, zz), c_leaves)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function add_jungletree(data, a, x, y, z, minp, maxp, pr)
|
||||
local th = pr:next(7, 11)
|
||||
for yy=math.max(minp.y, y), math.min(maxp.y, y+th) do
|
||||
local vi = a:index(x, yy, z)
|
||||
data[vi] = c_jungletree
|
||||
end
|
||||
local maxy = y+th
|
||||
for xx=math.max(minp.x, x-1), math.min(maxp.x, x+1) do
|
||||
for yy=math.max(minp.y, maxy-1), math.min(maxp.y, maxy+1) do
|
||||
for zz=math.max(minp.z, z-1), math.min(maxp.z, z+1) do
|
||||
add_leaves(data, a:index(xx, yy, zz), c_jungleleaves)
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1,30 do
|
||||
local xi = pr:next(x-3, x+2)
|
||||
local yi = pr:next(maxy-2, maxy+1)
|
||||
local zi = pr:next(z-3, z+2)
|
||||
for xx=math.max(minp.x, xi), math.min(maxp.x, xi+1) do
|
||||
for yy=math.max(minp.y, yi), math.min(maxp.y, yi+1) do
|
||||
for zz=math.max(minp.z, zi), math.min(maxp.z, zi+1) do
|
||||
add_leaves(data, a:index(xx, yy, zz), c_jungleleaves)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function add_savannatree(data, a, x, y, z, minp, maxp, pr)
|
||||
local th = pr:next(7, 11)
|
||||
for yy=math.max(minp.y, y), math.min(maxp.y, y+th) do
|
||||
local vi = a:index(x, yy, z)
|
||||
data[vi] = c_savannatree
|
||||
end
|
||||
local maxy = y+th
|
||||
for xx=math.max(minp.x, x-1), math.min(maxp.x, x+1) do
|
||||
for yy=math.max(minp.y, maxy-1), math.min(maxp.y, maxy+1) do
|
||||
for zz=math.max(minp.z, z-1), math.min(maxp.z, z+1) do
|
||||
add_leaves(data, a:index(xx, yy, zz), c_savannaleaves)
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1,20 do
|
||||
local xi = pr:next(x-3, x+2)
|
||||
local yi = pr:next(maxy-2, maxy)
|
||||
local zi = pr:next(z-3, z+2)
|
||||
for xx=math.max(minp.x, xi), math.min(maxp.x, xi+1) do
|
||||
for yy=math.max(minp.y, yi), math.min(maxp.y, yi+1) do
|
||||
for zz=math.max(minp.z, zi), math.min(maxp.z, zi+1) do
|
||||
add_leaves(data, a:index(xx, yy, zz), c_savannaleaves)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1,15 do
|
||||
local xi = pr:next(x-3, x+2)
|
||||
local yy = pr:next(maxy-6, maxy-5)
|
||||
local zi = pr:next(z-3, z+2)
|
||||
for xx=math.max(minp.x, xi), math.min(maxp.x, xi+1) do
|
||||
for zz=math.max(minp.z, zi), math.min(maxp.z, zi+1) do
|
||||
if minp.y<=yy and maxp.y>=yy then
|
||||
add_leaves(data, a:index(xx, yy, zz), c_savannaleaves)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function add_savannabush(data, a, x, y, z, minp, maxp, pr)
|
||||
local bh = pr:next(1, 2)
|
||||
local bw = pr:next(2, 4)
|
||||
|
||||
for xx=math.max(minp.x, x-bw), math.min(maxp.x, x+bw) do
|
||||
for zz=math.max(minp.z, z-bw), math.min(maxp.z, z+bw) do
|
||||
for yy=math.max(minp.y, y-bh), math.min(maxp.y, y+bh) do
|
||||
if pr:next(1, 100) < 95 and math.abs(xx-x) < pr:next(bh, bh+2)-math.abs(y-yy) and math.abs(zz-z) < pr:next(bh, bh+2)-math.abs(y-yy) then
|
||||
add_leaves(data, a:index(xx, yy, zz), c_savannaleaves)
|
||||
for yyy=math.max(minp.y, yy-2), yy do
|
||||
add_leaves(data, a:index(xx, yyy, zz), c_savannaleaves)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if x<=maxp.x and x>=minp.x and y<=maxp.y and y>=minp.y and z<=maxp.z and z>=minp.z then
|
||||
local vi = a:index(x, y, z)
|
||||
data[vi] = c_savannatree
|
||||
end
|
||||
end
|
||||
|
||||
function add_pinetree(data, a, x, y, z, minp, maxp, pr, snow)
|
||||
if snow == nil then snow = c_snow end
|
||||
local th = pr:next(9, 13)
|
||||
for yy=math.max(minp.y, y), math.min(maxp.y, y+th) do
|
||||
local vi = a:index(x, yy, z)
|
||||
data[vi] = c_pinetree
|
||||
end
|
||||
local maxy = y+th
|
||||
for xx=math.max(minp.x, x-3), math.min(maxp.x, x+3) do
|
||||
for yy=math.max(minp.y, maxy-1), math.min(maxp.y, maxy-1) do
|
||||
for zz=math.max(minp.z, z-3), math.min(maxp.z, z+3) do
|
||||
if pr:next(1, 100) < 80 then
|
||||
add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow)
|
||||
add_leaves(data, a:index(xx, yy+1, zz), snow)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for xx=math.max(minp.x, x-2), math.min(maxp.x, x+2) do
|
||||
for yy=math.max(minp.y, maxy), math.min(maxp.y, maxy) do
|
||||
for zz=math.max(minp.z, z-2), math.min(maxp.z, z+2) do
|
||||
if pr:next(1, 100) < 85 then
|
||||
add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow)
|
||||
add_leaves(data, a:index(xx, yy+1, zz), snow)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for xx=math.max(minp.x, x-1), math.min(maxp.x, x+1) do
|
||||
for yy=math.max(minp.y, maxy+1), math.min(maxp.y, maxy+1) do
|
||||
for zz=math.max(minp.z, z-1), math.min(maxp.z, z+1) do
|
||||
if pr:next(1, 100) < 90 then
|
||||
add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow)
|
||||
add_leaves(data, a:index(xx, yy+1, zz), snow)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if maxy+1<=maxp.y and maxy+1>=minp.y then
|
||||
add_leaves(data, a:index(x, maxy+1, z), c_pineleaves, snow)
|
||||
add_leaves(data, a:index(x, maxy+2, z), snow)
|
||||
end
|
||||
local my = 0
|
||||
for i=1,20 do
|
||||
local xi = pr:next(x-3, x+2)
|
||||
local yy = pr:next(maxy-6, maxy-5)
|
||||
local zi = pr:next(z-3, z+2)
|
||||
if yy > my then
|
||||
my = yy
|
||||
end
|
||||
for xx=math.max(minp.x, xi), math.min(maxp.x, xi+1) do
|
||||
for zz=math.max(minp.z, zi), math.min(maxp.z, zi+1) do
|
||||
if minp.y<=yy and maxp.y>=yy then
|
||||
add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow)
|
||||
add_leaves(data, a:index(xx, yy+1, zz), snow)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for xx=math.max(minp.x, x-2), math.min(maxp.x, x+2) do
|
||||
for yy=math.max(minp.y, my+1), math.min(maxp.y, my+1) do
|
||||
for zz=math.max(minp.z, z-2), math.min(maxp.z, z+2) do
|
||||
if pr:next(1, 100) < 85 then
|
||||
add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow)
|
||||
add_leaves(data, a:index(xx, yy+1, zz), snow)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for xx=math.max(minp.x, x-1), math.min(maxp.x, x+1) do
|
||||
for yy=math.max(minp.y, my+2), math.min(maxp.y, my+2) do
|
||||
for zz=math.max(minp.z, z-1), math.min(maxp.z, z+1) do
|
||||
if pr:next(1, 100) < 90 then
|
||||
add_leaves(data, a:index(xx, yy, zz), c_pineleaves, snow)
|
||||
add_leaves(data, a:index(xx, yy+1, zz), snow)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/we.lua")
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/rotate.lua")
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/buildings.lua")
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/villages.lua")
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/ores.lua")
|
||||
|
||||
function get_biome_table(minp, humidity, temperature, range)
|
||||
if range == nil then range = 1 end
|
||||
local l = {}
|
||||
for xi = -range, range do
|
||||
for zi = -range, range do
|
||||
local mnp, mxp = {x=minp.x+xi*80,z=minp.z+zi*80}, {x=minp.x+xi*80+80,z=minp.z+zi*80+80}
|
||||
local pr = PseudoRandom(get_bseed(mnp))
|
||||
local bxp, bzp = pr:next(mnp.x, mxp.x), pr:next(mnp.z, mxp.z)
|
||||
local h, t = humidity:get2d({x=bxp, y=bzp}), temperature:get2d({x=bxp, y=bzp})
|
||||
l[#l+1] = {x=bxp, z=bzp, h=h, t=t}
|
||||
end
|
||||
end
|
||||
return l
|
||||
end
|
||||
|
||||
local function get_distance(x1, x2, z1, z2)
|
||||
return (x1-x2)*(x1-x2)+(z1-z2)*(z1-z2)
|
||||
end
|
||||
|
||||
function get_nearest_biome(biome_table, x, z)
|
||||
local m = math.huge
|
||||
local k = 0
|
||||
for key, bdef in ipairs(biome_table) do
|
||||
local dist = get_distance(bdef.x, x, bdef.z, z)
|
||||
if dist<m then
|
||||
m=dist
|
||||
k=key
|
||||
end
|
||||
end
|
||||
return biome_table[k]
|
||||
end
|
||||
|
||||
local function get_perlin_map(seed, octaves, persistance, scale, minp, maxp)
|
||||
local sidelen = maxp.x - minp.x +1
|
||||
local pm = minetest.get_perlin_map(
|
||||
{offset=0, scale=1, spread={x=scale, y=scale, z=scale}, seed=seed, octaves=octaves, persist=persistance},
|
||||
{x=sidelen, y=sidelen, z=sidelen}
|
||||
)
|
||||
return pm:get2dMap_flat({x = minp.x, y = minp.z, z = 0})
|
||||
end
|
||||
|
||||
local function copytable(t)
|
||||
local t2 = {}
|
||||
for key, val in pairs(t) do
|
||||
t2[key] = val
|
||||
end
|
||||
return t2
|
||||
end
|
||||
|
||||
local function mg_generate(minp, maxp, emin, emax, vm)
|
||||
local a = VoxelArea:new{
|
||||
MinEdge={x=emin.x, y=emin.y, z=emin.z},
|
||||
MaxEdge={x=emax.x, y=emax.y, z=emax.z},
|
||||
}
|
||||
|
||||
local treemin = {x=emin.x, y=minp.y, z=emin.z}
|
||||
local treemax = {x=emax.x, y=maxp.y, z=emax.z}
|
||||
|
||||
local sidelen = maxp.x-minp.x+1
|
||||
|
||||
local noise1 = get_perlin_map(12345, 6, 0.5, 256, minp, maxp)
|
||||
local noise2 = get_perlin_map(56789, 6, 0.5, 256, minp, maxp)
|
||||
local noise3 = get_perlin_map(42, 3, 0.5, 32, minp, maxp)
|
||||
local noise4 = get_perlin_map(8954, 8, 0.5, 1024, minp, maxp)
|
||||
|
||||
local noise1raw = minetest.get_perlin(12345, 6, 0.5, 256)
|
||||
|
||||
local vcr = VILLAGE_CHECK_RADIUS
|
||||
local villages = {}
|
||||
for xi = -vcr, vcr do
|
||||
for zi = -vcr, vcr do
|
||||
for _, village in ipairs(villages_at_point({x = minp.x + xi * 80, z = minp.z + zi * 80}, noise1raw)) do
|
||||
village.to_grow = {}
|
||||
villages[#villages+1] = village
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local pr = PseudoRandom(get_bseed(minp))
|
||||
|
||||
local village_noise = minetest.get_perlin(7635, 3, 0.5, 16)
|
||||
local village_noise_map = get_perlin_map(7635, 3, 0.5, 16, minp, maxp)
|
||||
|
||||
local noise_top_layer = get_perlin_map(654, 6, 0.5, 256, minp, maxp)
|
||||
local noise_second_layer = get_perlin_map(123, 6, 0.5, 256, minp, maxp)
|
||||
|
||||
local noise_temperature_raw = minetest.get_perlin(763, 7, 0.5, 512)
|
||||
local noise_humidity_raw = minetest.get_perlin(834, 7, 0.5, 512)
|
||||
local noise_temperature = get_perlin_map(763, 7, 0.5, 512, minp, maxp)
|
||||
local noise_humidity = get_perlin_map(834, 7, 0.5, 512, minp, maxp)
|
||||
local noise_beach = get_perlin_map(452, 6, 0.5, 256, minp, maxp)
|
||||
|
||||
local biome_table = get_biome_table(minp, noise_humidity_raw, noise_temperature_raw)
|
||||
|
||||
local data = vm:get_data()
|
||||
local param2_data = vm:get_param2_data()
|
||||
|
||||
local villages_to_grow = {}
|
||||
local ni = 0
|
||||
for z = minp.z, maxp.z do
|
||||
for x = minp.x, maxp.x do
|
||||
ni = ni + 1
|
||||
local y = math.floor(surface_at_point(x, z, village_noise_map, villages, ni, noise1, noise2, noise3, noise4))
|
||||
local humidity = noise_humidity[ni]
|
||||
local temperature = noise_temperature[ni] - math.max(y, 0) / 50
|
||||
local biome = get_nearest_biome(biome_table, x, z)
|
||||
local biome_humidity = biome.h
|
||||
local biome_temperature = biome.t
|
||||
local liquid_top
|
||||
if biome_temperature < -0.4 then
|
||||
liquid_top = c_ice
|
||||
else
|
||||
liquid_top = c_water
|
||||
end
|
||||
local above_top, top, top_layer, second_layer
|
||||
if y < -1 then
|
||||
above_top = c_air
|
||||
top = c_dirt
|
||||
top_layer = c_dirt
|
||||
second_layer = c_stone
|
||||
elseif y < 3 and noise_beach[ni] < 0.2 then
|
||||
above_top = c_air
|
||||
top = c_sand
|
||||
top_layer = c_sand
|
||||
second_layer = c_sandstone
|
||||
else
|
||||
above_top = c_air
|
||||
if biome_temperature > 0.4 then
|
||||
if biome_humidity < -0.4 then
|
||||
top = c_desert_sand
|
||||
top_layer = c_desert_sand
|
||||
second_layer = c_desert_stone
|
||||
elseif biome_humidity < 0.4 then
|
||||
top = c_dry_grass
|
||||
top_layer = c_dirt
|
||||
second_layer = c_stone
|
||||
else
|
||||
top = c_grass
|
||||
top_layer = c_dirt
|
||||
second_layer = c_stone
|
||||
end
|
||||
elseif biome_temperature < -0.4 then
|
||||
above_top = c_snow
|
||||
top = c_dirt_snow
|
||||
top_layer = c_dirt
|
||||
second_layer = c_stone
|
||||
else
|
||||
top = c_grass
|
||||
top_layer = c_dirt
|
||||
second_layer = c_stone
|
||||
end
|
||||
end
|
||||
if y >= 100 then
|
||||
above_top = c_air
|
||||
top = c_snow
|
||||
top_layer = c_snowblock
|
||||
end
|
||||
if y < 0 then
|
||||
above_top = c_air
|
||||
end
|
||||
if y <= maxp.y and y >= minp.y then
|
||||
local vi = a:index(x, y, z)
|
||||
if y >= 0 then
|
||||
data[vi] = top
|
||||
else
|
||||
data[vi] = top_layer
|
||||
end
|
||||
end
|
||||
local add_above_top = true
|
||||
for id, tree in ipairs(mg.registered_trees) do
|
||||
if tree.min_humidity <= humidity and humidity <= tree.max_humidity
|
||||
and tree.min_temperature <= temperature and temperature <= tree.max_temperature
|
||||
and tree.min_biome_humidity <= biome_humidity and biome_humidity <= tree.max_biome_humidity
|
||||
and tree.min_biome_temperature <= biome_temperature and biome_temperature <= tree.max_biome_temperature
|
||||
and tree.min_height <= y + 1 and y + 1 <= tree.max_height
|
||||
and ((not tree.grows_on) or tree.grows_on == top)
|
||||
and pr:next(1, tree.chance) == 1 then
|
||||
local in_village = false
|
||||
for _, village in ipairs(villages) do
|
||||
if inside_village(x, z, village, village_noise) and not tree.can_be_in_village then
|
||||
village.to_grow[#village.to_grow+1] = {x = x, y = y + 1, z = z, id = id}
|
||||
in_village = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not in_village then
|
||||
tree.grow(data, a, x, y + 1, z, minp, maxp, pr)
|
||||
end
|
||||
add_above_top = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if add_above_top and y + 1 <= maxp.y and y + 1 >= minp.y then
|
||||
local vi = a:index(x, y + 1, z)
|
||||
data[vi] = above_top
|
||||
end
|
||||
if y < 0 and minp.y <= 0 and maxp.y > y then
|
||||
for yy = math.max(y + 1, minp.y), math.min(0, maxp.y) do
|
||||
local vi = a:index(x, yy, z)
|
||||
data[vi] = c_water
|
||||
end
|
||||
if maxp.y >= 0 then
|
||||
data[a:index(x, 0, z)] = liquid_top
|
||||
end
|
||||
end
|
||||
local tl = math.floor((noise_top_layer[ni] + 2.5) * 2)
|
||||
if y - tl - 1 <= maxp.y and y - 1 >= minp.y then
|
||||
for yy = math.max(y - tl - 1, minp.y), math.min(y - 1, maxp.y) do
|
||||
local vi = a:index(x, yy, z)
|
||||
data[vi] = top_layer
|
||||
end
|
||||
end
|
||||
local sl = math.floor((noise_second_layer[ni] + 5) * 3)
|
||||
if y - sl - 1 <= maxp.y and y - tl - 2 >= minp.y then
|
||||
for yy = math.max(y - sl - 1, minp.y), math.min(y - tl - 2, maxp.y) do
|
||||
local vi = a:index(x, yy, z)
|
||||
data[vi] = second_layer
|
||||
end
|
||||
end
|
||||
if y - sl - 2 >= minp.y then
|
||||
for yy = minp.y, math.min(y - sl - 2, maxp.y) do
|
||||
local vi = a:index(x, yy, z)
|
||||
data[vi] = c_stone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local va = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
|
||||
|
||||
for _, ore_sheet in ipairs(mg.registered_ore_sheets) do
|
||||
local sidelen = maxp.x - minp.x + 1
|
||||
local np = copytable(ore_sheet.noise_params)
|
||||
np.seed = np.seed + minp.y
|
||||
local pm = minetest.get_perlin_map(np, {x = sidelen, y = sidelen, z = 1})
|
||||
local map = pm:get2dMap_flat({x = minp.x, y = minp.z})
|
||||
local ni = 0
|
||||
local trh = ore_sheet.threshhold
|
||||
local wherein = minetest.get_content_id(ore_sheet.wherein)
|
||||
local ore = minetest.get_content_id(ore_sheet.name)
|
||||
local hmin = ore_sheet.height_min
|
||||
local hmax = ore_sheet.height_max
|
||||
local tmin = ore_sheet.tmin
|
||||
local tmax = ore_sheet.tmax
|
||||
for z = minp.z, maxp.z do
|
||||
for x = minp.x, maxp.x do
|
||||
ni = ni + 1
|
||||
local noise = map[ni]
|
||||
if noise > trh then
|
||||
local thickness = pr:next(tmin, tmax)
|
||||
local y0 = math.floor(minp.y + (noise - trh) * 4)
|
||||
for y = math.max(y0, hmin), math.min(y0 + thickness - 1, hmax) do
|
||||
local vi = a:index(x, y, z)
|
||||
if data[vi] == wherein or wherein == c_ignore then
|
||||
data[vi] = ore
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, ore in ipairs(mg.registered_ores) do
|
||||
generate_vein(minetest.get_content_id(ore.name), minetest.get_content_id(ore.wherein), minp, maxp, ore.seeddiff, ore, data, a, va)
|
||||
end
|
||||
|
||||
for _, village in ipairs(villages) do
|
||||
village.to_add = generate_village(village, minp, maxp, data, param2_data, a, village_noise)
|
||||
end
|
||||
|
||||
vm:set_data(data)
|
||||
vm:set_param2_data(param2_data)
|
||||
|
||||
vm:calc_lighting(
|
||||
{x = minp.x - 16, y = minp.y, z = minp.z - 16},
|
||||
{x = maxp.x + 16, y = maxp.y, z = maxp.z + 16}
|
||||
)
|
||||
|
||||
vm:write_to_map()
|
||||
|
||||
local meta
|
||||
for _, village in ipairs(villages) do
|
||||
for _, n in pairs(village.to_add) do
|
||||
minetest.set_node(n.pos, n.node)
|
||||
if n.meta ~= nil then
|
||||
meta = minetest.get_meta(n.pos)
|
||||
meta:from_table(n.meta)
|
||||
if n.node.name == "default:chest" then
|
||||
local inv = meta:get_inventory()
|
||||
local items = inv:get_list("main")
|
||||
for i = 1, inv:get_size("main") do
|
||||
inv:set_stack("main", i, ItemStack(""))
|
||||
end
|
||||
local numitems = pr:next(3, 20)
|
||||
for i = 1, numitems do
|
||||
local ii = pr:next(1, #items)
|
||||
local prob = items[ii]:get_count() % 2 ^ 8
|
||||
local stacksz = math.floor(items[ii]:get_count() / 2 ^ 8)
|
||||
if pr:next(0, prob) == 0 and stacksz>0 then
|
||||
local stk = ItemStack({
|
||||
name = items[ii]:get_name(),
|
||||
count = pr:next(1, stacksz),
|
||||
wear = items[ii]:get_wear(),
|
||||
metadata = items[ii]:get_metadata()
|
||||
})
|
||||
local ind = pr:next(1, inv:get_size("main"))
|
||||
while not inv:get_stack("main", ind):is_empty() do
|
||||
ind = pr:next(1, inv:get_size("main"))
|
||||
end
|
||||
inv:set_stack("main", ind, stk)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||
mg_generate(minp, maxp, emin, emax, vm)
|
||||
end)
|
||||
|
||||
local function mg_regenerate(pos, name)
|
||||
local minp = {x = 80 * math.floor((pos.x + 32) / 80) - 32,
|
||||
y = 80 * math.floor((pos.y + 32) / 80) - 32,
|
||||
z = 80 * math.floor((pos.z + 32) / 80) - 32}
|
||||
local maxp = {x = minp.x + 79, y = minp.y + 79, z = minp.z + 79}
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(minp, maxp)
|
||||
local data = {}
|
||||
for i = 1, (maxp.x - minp.x + 1) * (maxp.y - minp.y + 1) * (maxp.z - minp.z + 1) do
|
||||
data[i] = c_air
|
||||
end
|
||||
vm:set_data(data)
|
||||
vm:write_to_map()
|
||||
mg_generate(minp, maxp, emin, emax, vm)
|
||||
|
||||
minetest.chat_send_player(name, "Regenerating done, fixing lighting. This may take a while...")
|
||||
-- Fix lighting
|
||||
local nodes = minetest.find_nodes_in_area(minp, maxp, "air")
|
||||
local nnodes = #nodes
|
||||
local p = math.floor(nnodes / 5)
|
||||
local dig_node = minetest.dig_node
|
||||
for i, pos in ipairs(nodes) do
|
||||
dig_node(pos)
|
||||
if i % p == 0 then
|
||||
minetest.chat_send_player(name, math.floor(i / nnodes * 100).."%")
|
||||
end
|
||||
end
|
||||
minetest.chat_send_player(name, "Done")
|
||||
return minp, maxp
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("mg_regenerate", {
|
||||
privs = {server = true},
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
local pos = player:getpos()
|
||||
local minp, maxp = mg_regenerate(pos, name)
|
||||
if minetest.get_modpath("biome_lib") and minp and maxp then
|
||||
biome_lib.blocklist_aircheck[#biome_lib.blocklist_aircheck + 1] = {minp, maxp}
|
||||
biome_lib.blocklist_no_aircheck[#biome_lib.blocklist_no_aircheck + 1] = {minp, maxp}
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local function spawnplayer(player)
|
||||
if minetest.setting_get("static_spawnpoint") then return end
|
||||
local noise1 = minetest.get_perlin(12345, 6, 0.5, 256)
|
||||
local min_dist = math.huge
|
||||
local min_pos = {x = 0, y = 3, z = 0}
|
||||
for bx = -20, 20 do
|
||||
for bz = -20, 20 do
|
||||
local minp = {x = -32 + 80 * bx, y = -32, z = -32 + 80 * bz}
|
||||
for _, village in ipairs(villages_at_point(minp, noise1)) do
|
||||
if math.abs(village.vx) + math.abs(village.vz) < min_dist then
|
||||
min_pos = {x = village.vx, y = village.vh + 2, z = village.vz}
|
||||
min_dist = math.abs(village.vx) + math.abs(village.vz)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
player:setpos(min_pos)
|
||||
end
|
||||
|
||||
minetest.register_on_newplayer(function(player)
|
||||
spawnplayer(player)
|
||||
end)
|
||||
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
spawnplayer(player)
|
||||
return true
|
||||
end)
|
||||
|
||||
mg.registered_ores = {}
|
||||
function mg.register_ore(oredef)
|
||||
if oredef.wherein == nil then
|
||||
oredef.wherein = "ignore"
|
||||
end
|
||||
if DEBUG then
|
||||
oredef.wherein = "ignore"
|
||||
oredef.maxheight = 31000
|
||||
end
|
||||
mg.registered_ores[#mg.registered_ores+1] = oredef
|
||||
end
|
||||
|
||||
mg.registered_ore_sheets = {}
|
||||
function mg.register_ore_sheet(oredef)
|
||||
if oredef.wherein == nil then
|
||||
oredef.wherein = "ignore"
|
||||
end
|
||||
if DEBUG then
|
||||
oredef.wherein = "ignore"
|
||||
oredef.height_max = 31000
|
||||
end
|
||||
mg.registered_ore_sheets[#mg.registered_ore_sheets + 1] = oredef
|
||||
end
|
||||
|
||||
mg.registered_trees = {}
|
||||
function mg.register_tree(treedef)
|
||||
if treedef.min_humidity == nil then
|
||||
treedef.min_humidity = -2
|
||||
end
|
||||
if treedef.max_humidity == nil then
|
||||
treedef.max_humidity = 2
|
||||
end
|
||||
if treedef.min_biome_humidity == nil then
|
||||
treedef.min_biome_humidity = -2
|
||||
end
|
||||
if treedef.max_biome_humidity == nil then
|
||||
treedef.max_biome_humidity = 2
|
||||
end
|
||||
if treedef.min_temperature == nil then
|
||||
treedef.min_temperature = -2
|
||||
end
|
||||
if treedef.max_temperature == nil then
|
||||
treedef.max_temperature = 2
|
||||
end
|
||||
if treedef.min_biome_temperature == nil then
|
||||
treedef.min_biome_temperature = -2
|
||||
end
|
||||
if treedef.max_biome_temperature == nil then
|
||||
treedef.max_biome_temperature = 2
|
||||
end
|
||||
mg.registered_trees[#mg.registered_trees + 1] = treedef
|
||||
end
|
||||
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/oredesc.lua")
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/trees.lua")
|
||||
|
||||
if ENABLE_SNOW then
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/snow.lua")
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
name = mg
|
|
@ -0,0 +1,200 @@
|
|||
-------------------------
|
||||
-- Savanna tree
|
||||
-------------------------
|
||||
|
||||
minetest.register_node("mg:savannatree", {
|
||||
description = "Savannawood Tree",
|
||||
tiles = {"mg_dry_tree_top.png", "mg_dry_tree_top.png", "mg_dry_tree.png"},
|
||||
groups = {tree=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("mg:savannaleaves", {
|
||||
description = "Savannawood Leaves",
|
||||
drawtype = "allfaces_optional",
|
||||
visual_scale = 1.3,
|
||||
tiles = {"mg_dry_leaves.png"},
|
||||
paramtype = "light",
|
||||
groups = {snappy=3, leafdecay=3, flammable=2, leaves=1},
|
||||
trunk = "mg:savannatree", -- Support for BASE and Voxelgarden
|
||||
waving = 1,
|
||||
drop = {
|
||||
max_items = 1,
|
||||
items = {
|
||||
{
|
||||
items = {'mg:savannasapling'},
|
||||
rarity = 20,
|
||||
},
|
||||
{
|
||||
items = {'mg:savannaleaves'},
|
||||
}
|
||||
}
|
||||
},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("mg:savannawood", {
|
||||
description = "Savannawood Planks",
|
||||
tiles = {"mg_dry_wood.png"},
|
||||
groups = {choppy=2,oddly_breakable_by_hand=2,flammable=3,wood=1},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'mg:savannawood 4',
|
||||
recipe = {
|
||||
{'mg:savannatree'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("mg:savannasapling", {
|
||||
description = "Savannawood Sapling",
|
||||
drawtype = "plantlike",
|
||||
visual_scale = 1.0,
|
||||
tiles = {"mg_dry_sapling.png"},
|
||||
inventory_image = "mg_dry_sapling.png",
|
||||
wield_image = "mg_dry_sapling.png",
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
|
||||
},
|
||||
groups = {snappy=2,dig_immediate=3,flammable=2,attached_node=1},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"mg:savannasapling"},
|
||||
interval = 10,
|
||||
chance = 50,
|
||||
action = function(pos, node)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local minp, maxp = vm:read_from_map({x=pos.x-10, y=pos.y, z=pos.z-10}, {x=pos.x+10, y=pos.y+20, z=pos.z+10})
|
||||
local a = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
|
||||
local data = vm:get_data()
|
||||
add_savannatree(data, a, pos.x, pos.y, pos.z, minp, maxp, PseudoRandom(math.random(1,100000)))
|
||||
vm:set_data(data)
|
||||
vm:write_to_map()
|
||||
vm:update_map()
|
||||
end
|
||||
})
|
||||
|
||||
-------------------------
|
||||
-- Pine tree
|
||||
-------------------------
|
||||
|
||||
if minetest.registered_nodes["default:pine_tree"] ~= nil then
|
||||
minetest.register_alias("mg:pinetree", "default:pine_tree")
|
||||
minetest.register_alias("mg:pineleaves", "default:pine_needles")
|
||||
minetest.register_alias("mg:pinewood", "default:pine_wood")
|
||||
minetest.register_alias("mg:pinesapling", "default:pine_sapling")
|
||||
else
|
||||
|
||||
minetest.register_node("mg:pinetree", {
|
||||
description = "Pine Tree",
|
||||
tiles = {"mg_pine_tree_top.png", "mg_pine_tree_top.png", "mg_pine_tree.png"},
|
||||
groups = {tree=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("mg:pineleaves", {
|
||||
description = "Pine Leaves",
|
||||
drawtype = "allfaces_optional",
|
||||
visual_scale = 1.3,
|
||||
tiles = {"mg_pine_leaves.png"},
|
||||
paramtype = "light",
|
||||
groups = {snappy=3, leafdecay=3, flammable=2, leaves=1},
|
||||
trunk = "mg:pinetree", -- Support for BASE and Voxelgarden
|
||||
waving = 1,
|
||||
drop = {
|
||||
max_items = 1,
|
||||
items = {
|
||||
{
|
||||
items = {'mg:pinesapling'},
|
||||
rarity = 20,
|
||||
},
|
||||
{
|
||||
items = {'mg:pineleaves'},
|
||||
}
|
||||
}
|
||||
},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("mg:pinewood", {
|
||||
description = "Pine Planks",
|
||||
tiles = {"mg_pine_wood.png"},
|
||||
groups = {choppy=2,oddly_breakable_by_hand=2,flammable=3,wood=1},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'mg:pinewood 4',
|
||||
recipe = {
|
||||
{'mg:pinetree'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("mg:pinesapling", {
|
||||
description = "Pine Sapling",
|
||||
drawtype = "plantlike",
|
||||
visual_scale = 1.0,
|
||||
tiles = {"mg_pine_sapling.png"},
|
||||
inventory_image = "mg_pine_sapling.png",
|
||||
wield_image = "mg_pine_sapling.png",
|
||||
paramtype = "light",
|
||||
walkable = false,
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.3, -0.5, -0.3, 0.3, 0.35, 0.3}
|
||||
},
|
||||
groups = {snappy=2,dig_immediate=3,flammable=2,attached_node=1},
|
||||
sounds = default.node_sound_leaves_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"mg:pinesapling"},
|
||||
interval = 10,
|
||||
chance = 50,
|
||||
action = function(pos, node)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local minp, maxp = vm:read_from_map({x=pos.x-10, y=pos.y, z=pos.z-10}, {x=pos.x+10, y=pos.y+30, z=pos.z+10})
|
||||
local a = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
|
||||
local data = vm:get_data()
|
||||
add_pinetree(data, a, pos.x, pos.y, pos.z, minp, maxp, PseudoRandom(math.random(1,100000)), c_air)
|
||||
vm:set_data(data)
|
||||
vm:write_to_map()
|
||||
vm:update_map()
|
||||
end
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
-------------------------
|
||||
-- Other
|
||||
-------------------------
|
||||
|
||||
if minetest.registered_nodes["default:dirt_with_dry_grass"] ~= nil then
|
||||
minetest.register_alias("mg:dirt_with_dry_grass", "default:dirt_with_dry_grass")
|
||||
else
|
||||
|
||||
minetest.register_node("mg:dirt_with_dry_grass", {
|
||||
description = "Dry Grass",
|
||||
tiles = {"mg_dry_grass.png", "default_dirt.png", "default_dirt.png^mg_dry_grass_side.png"},
|
||||
is_ground_content = true,
|
||||
groups = {crumbly=3,soil=1},
|
||||
drop = 'default:dirt',
|
||||
sounds = default.node_sound_dirt_defaults({
|
||||
footstep = {name="default_grass_footstep", gain=0.25},
|
||||
}),
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
minetest.register_node("mg:ignore", {
|
||||
description = "MG Ignore",
|
||||
drawtype = "airlike",
|
||||
sunlight_propagates = true,
|
||||
groups = {snappy=2,not_in_creative_inventory=1},
|
||||
})
|
|
@ -0,0 +1,214 @@
|
|||
mg.register_ore({
|
||||
name = "air",
|
||||
seeddiff = 1234,
|
||||
maxhdistance = 70,
|
||||
maxvdistance = 70,
|
||||
maxheight = -3,
|
||||
seglenghtn = 15,
|
||||
seglenghtdev = 6,
|
||||
segincln = 0.2,
|
||||
segincldev = 0.6,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numperblock = 5,
|
||||
numbranchesn = 2,
|
||||
numbranchesdev = 0,
|
||||
mothersizen = -1,
|
||||
mothersizedev = 0,
|
||||
sizen = 100,
|
||||
sizedev = 30,
|
||||
radius = 2.3
|
||||
})
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:stone_with_iron",
|
||||
wherein = "default:stone",
|
||||
seeddiff = 0,
|
||||
maxvdistance = 10.5,
|
||||
maxheight = -16,
|
||||
seglenghtn = 15,
|
||||
seglenghtdev = 6,
|
||||
segincln = 0,
|
||||
segincldev = 0.6,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numperblock = 2.5
|
||||
})
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:stone_with_coal",
|
||||
wherein = "default:stone",
|
||||
seeddiff = 1,
|
||||
maxvdistance = 10,
|
||||
sizen = 54,
|
||||
sizedev = 27,
|
||||
maxheight = 64,
|
||||
seglenghtn = 15,
|
||||
seglenghtdev = 6,
|
||||
segincln = 0,
|
||||
segincldev = 0.36,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
radius = 1,
|
||||
numperblock = 6
|
||||
})
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:stone_with_mese",
|
||||
wherein = "default:stone",
|
||||
seeddiff = 2,
|
||||
maxvdistance = 50,
|
||||
sizen = 7,
|
||||
sizedev = 3,
|
||||
maxheight = -128,
|
||||
seglenghtn = 2,
|
||||
seglenghtdev = 1,
|
||||
segincln = 4,
|
||||
segincldev = 1,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numperblock = 0.8,
|
||||
numbranchesn = 2,
|
||||
numbranchesdev = 1,
|
||||
fork_chance = 0.1,
|
||||
mothersizen = 0,
|
||||
mothersizedev = 0
|
||||
})
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:mese",
|
||||
wherein = "default:stone",
|
||||
seeddiff = 3,
|
||||
maxvdistance = 50,
|
||||
sizen = 3,
|
||||
sizedev = 1,
|
||||
maxheight = -1024,
|
||||
seglenghtn = 2,
|
||||
seglenghtdev = 1,
|
||||
segincln = 4,
|
||||
segincldev = 1,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numbranchesn = 2,
|
||||
numbranchesdev = 1,
|
||||
fork_chance = 0.1,
|
||||
radius = 1
|
||||
})
|
||||
|
||||
mg.register_ore({ -- Same parameters exactly as the previous one so it spawns inside
|
||||
name = "default:lava_source",
|
||||
wherein = "default:mese",
|
||||
seeddiff = 3,
|
||||
maxvdistance = 50,
|
||||
sizen = 3,
|
||||
sizedev = 1,
|
||||
maxheight = -1024,
|
||||
seglenghtn = 2,
|
||||
seglenghtdev = 1,
|
||||
segincln = 4,
|
||||
segincldev = 1,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numbranchesn = 2,
|
||||
numbranchesdev = 1,
|
||||
fork_chance = 0.1,
|
||||
mothersizen = 0,
|
||||
mothersizedev = 0
|
||||
})
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:stone_with_copper",
|
||||
wherein = "default:stone",
|
||||
seeddiff = 4,
|
||||
maxvdistance = 10.5,
|
||||
maxheight = -16,
|
||||
seglenghtn = 15,
|
||||
seglenghtdev = 6,
|
||||
segincln = 0,
|
||||
segincldev = 0.6,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numperblock = 2
|
||||
})
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:stone_with_diamond",
|
||||
wherein = "default:stone",
|
||||
seeddiff = 5,
|
||||
maxvdistance = 50,
|
||||
sizen = 20,
|
||||
sizedev = 5,
|
||||
maxheight = -256,
|
||||
seglenghtn = 4,
|
||||
seglenghtdev = 2,
|
||||
segincln = 0.3,
|
||||
segincldev = 0.1,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numbranchesn = 2,
|
||||
numbranchesdev = 1,
|
||||
fork_chance = 0.1,
|
||||
radius = 1
|
||||
})
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:stone_with_gold",
|
||||
wherein = "default:stone",
|
||||
seeddiff = 17,
|
||||
maxvdistance = 10,
|
||||
sizen = 30,
|
||||
sizedev = 8,
|
||||
maxheight = -256,
|
||||
seglenghtn = 8,
|
||||
seglenghtdev = 4,
|
||||
segincln = 0.6,
|
||||
segincldev = 0.4,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numbranchesn = 2,
|
||||
numbranchesdev = 1,
|
||||
fork_chance = 0.1,
|
||||
radius = 1
|
||||
})
|
||||
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:clay",
|
||||
wherein = "default:dirt",
|
||||
seeddiff = 6,
|
||||
maxvdistance = 10.5,
|
||||
maxheight = 0,
|
||||
minheight = -50,
|
||||
sizen = 50,
|
||||
sizedev = 20,
|
||||
seglenghtn = 15,
|
||||
seglenghtdev = 6,
|
||||
segincln = 0,
|
||||
segincldev = 0.6,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numperblock = 1,
|
||||
radius = 1.5
|
||||
})
|
||||
|
||||
mg.register_ore({
|
||||
name = "default:lava_source",
|
||||
seeddiff = 7,
|
||||
maxhdistance = 20,
|
||||
maxvdistance = 70,
|
||||
maxheight = -100,
|
||||
seglenghtn = 2,
|
||||
seglenghtdev = 1,
|
||||
segincln = -5,
|
||||
segincldev = 2,
|
||||
turnangle = 57,
|
||||
forkturnangle = 57,
|
||||
numperblock = 1,
|
||||
numbranchesn = 2,
|
||||
numbranchesdev = 1,
|
||||
mothersizen = 5,
|
||||
mothersizedev = 3,
|
||||
sizen = 8,
|
||||
sizedev = 2,
|
||||
radius = 2.3
|
||||
})
|
|
@ -0,0 +1,159 @@
|
|||
function in_cuboid(pos, minp, maxp)
|
||||
return (pos.x>=minp.x and pos.y>= minp.y and pos.z>=minp.z and pos.x<=maxp.x and pos.y<=maxp.y and pos.z<=maxp.z)
|
||||
end
|
||||
|
||||
function round_pos(p)
|
||||
return {x=math.floor(p.x+0.5),y=math.floor(p.y+0.5),z=math.floor(p.z+0.5)}
|
||||
end
|
||||
|
||||
function draw_sphere(name, wherein, center, radius, data, a, insideva)
|
||||
local rad2 = radius * radius
|
||||
radius = math.ceil(radius)
|
||||
local pos0 = {}
|
||||
for x = -radius, radius do
|
||||
pos0.x = center.x + x
|
||||
for y = -radius, radius do
|
||||
pos0.y = center.y + y
|
||||
for z = -radius, radius do
|
||||
pos0.z = center.z + z
|
||||
if x*x + y*y + z*z <= rad2 and insideva:containsp(pos0) and
|
||||
((wherein == c_ignore and data[a:indexp(pos0)] ~= c_water) or
|
||||
data[a:indexp(pos0)] == wherein) then
|
||||
data[a:indexp(pos0)] = name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function place_segment(name, wherein, pos1, pos2, minp, maxp, radius, data, a, insideva)
|
||||
local d = {x = pos2.x - pos1.x, y = pos2.y - pos1.y, z = pos2.z - pos1.z}
|
||||
local N = math.max(math.abs(d.x), math.abs(d.y), math.abs(d.z))
|
||||
local s = {x = d.x / N, y = d.y / N, z = d.z / N}
|
||||
local p = pos1
|
||||
draw_sphere(name, wherein, pos1, radius, data, a, insideva)
|
||||
for i = 1, N do
|
||||
p = {x = p.x + s.x, y = p.y + s.y, z = p.z + s.z}
|
||||
local p0 = round_pos(p)
|
||||
if not in_cuboid(p0, minp, maxp) then return end
|
||||
draw_sphere(name, wherein, p0, radius, data, a, insideva)
|
||||
end
|
||||
end
|
||||
|
||||
function generate_vein_segment(name, wherein, minp, maxp, pr, pos, angle, rem_size, options, data, a, insideva)
|
||||
if rem_size <= 0 then return end
|
||||
local Ln = options.seglenghtn
|
||||
local Ldev = options.seglenghtdev
|
||||
local L = pr:next(Ln - Ldev, Ln + Ldev)
|
||||
local incln = options.segincln * 100
|
||||
local incldev = options.segincldev * 100
|
||||
local incl = pr:next(incln - incldev, incln + incldev) / 100
|
||||
local turnangle = options.turnangle
|
||||
local forkturnangle = options.forkturnangle
|
||||
local fork_chance = options.fork_chance * 100
|
||||
local forkmultn = options.forkmultn * 100
|
||||
local forkmultdev = options.forkmultdev * 100
|
||||
local radius = options.radius
|
||||
|
||||
local end_pos = {x = pos.x + L * math.cos(angle), y = pos.y - L * incl, z = pos.z + L * math.sin(angle)}
|
||||
place_segment(name, wherein, round_pos(pos), round_pos(end_pos), minp, maxp, radius, data, a, insideva)
|
||||
if not in_cuboid(end_pos, minp, maxp) then return end
|
||||
local new_angle=(math.pi * pr:next(-turnangle, turnangle) / 180) + angle
|
||||
generate_vein_segment(name, wherein, minp, maxp, pr, end_pos, new_angle, rem_size - L, options, data, a, insideva)
|
||||
local numforks = math.floor(fork_chance / 100) + 1
|
||||
fork_chance = fork_chance / numforks
|
||||
if pr:next(1, 100) <= fork_chance then
|
||||
for f = 1, numforks do
|
||||
local new_angle = (math.pi * pr:next(-forkturnangle, forkturnangle) / 180) + angle
|
||||
local forkmult = pr:next(forkmultn - forkmultdev, forkmultn + forkmultdev) / 100
|
||||
if forkmult > 1 then forkmult = 1 end
|
||||
generate_vein_segment(name, wherein, minp, maxp, pr, end_pos, new_angle, forkmult * (rem_size - L), options, data, a, insideva)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function generate_vein(name, wherein, minp, maxp, seeddiff, options, data, a, insideva, second_call)
|
||||
local seed = get_bseed2(minp) + seeddiff
|
||||
options = get_or_default(options)
|
||||
|
||||
local numperblock = options.numperblock * 1000
|
||||
local maxhdistance = options.maxhdistance
|
||||
local maxvdistance = options.maxvdistance
|
||||
local numbranchesn = options.numbranchesn
|
||||
local numbranchesdev = options.numbranchesdev
|
||||
local mothersizen = options.mothersizen * 10
|
||||
local mothersizedev = options.mothersizedev * 10
|
||||
local sizen = options.sizen
|
||||
local sizedev = options.sizedev
|
||||
|
||||
if second_call == nil then
|
||||
local hblocks = math.floor(maxhdistance / 80) + 1
|
||||
local vblocks = math.floor(maxvdistance / 80) + 1
|
||||
for xblocksdiff = -hblocks, hblocks do
|
||||
for yblocksdiff = -vblocks, vblocks do
|
||||
for zblocksdiff = -hblocks, hblocks do
|
||||
if xblocksdiff ~= 0 or yblocksdiff ~= 0 or zblocksdiff ~= 0 then
|
||||
local new_minp = {x = minp.x + xblocksdiff * 80, y = minp.y + yblocksdiff * 80, z = minp.z + zblocksdiff * 80}
|
||||
local new_maxp = {x = maxp.x + xblocksdiff * 80, y = maxp.y + yblocksdiff * 80, z = maxp.z + zblocksdiff * 80}
|
||||
generate_vein(name, wherein, new_minp, new_maxp, seeddiff, options, data, a, insideva, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local pr = PseudoRandom(seed)
|
||||
|
||||
local numveins = math.floor(numperblock / 1000)
|
||||
numperblock = numperblock - 1000 * numveins
|
||||
if pr:next(1,1000) <= numperblock then
|
||||
numveins = numveins + 1
|
||||
end
|
||||
if numveins > 0 then
|
||||
local min_y = math.max(options.minheight, minp.y)
|
||||
local max_y = math.min(options.maxheight, maxp.y)
|
||||
if min_y > max_y then return end
|
||||
for v = 1, numveins do
|
||||
local vein_pos = {x = pr:next(minp.x, maxp.x), y = pr:next(min_y, max_y), z = pr:next(minp.z, maxp.z)}
|
||||
local numbranches = pr:next(numbranchesn - numbranchesdev, numbranchesn + numbranchesdev)
|
||||
local mothersize = pr:next(mothersizen - mothersizedev, mothersizen + mothersizedev) / 10
|
||||
|
||||
if mothersize >= 0 then
|
||||
draw_sphere(name, wherein,vein_pos, mothersize, data, a, insideva)
|
||||
end
|
||||
|
||||
local minpos = {x = vein_pos.x - maxhdistance, y = vein_pos.y - maxvdistance, z = vein_pos.z - maxhdistance}
|
||||
local maxpos = {x = vein_pos.x + maxhdistance, y = vein_pos.y + maxvdistance, z = vein_pos.z + maxhdistance}
|
||||
for i = 1, numbranches do
|
||||
local start_angle = math.pi * pr:next(0, 359) / 180
|
||||
local size = pr:next(sizen - sizedev, sizen + sizedev)
|
||||
generate_vein_segment(name, wherein, minpos, maxpos, pr, vein_pos, start_angle, size, options, data, a, insideva)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function get_or_default(options)
|
||||
if options.numperblock == nil then options.numperblock = 0.3 end
|
||||
if options.maxhdistance == nil then options.maxhdistance = 32 end
|
||||
if options.maxvdistance == nil then options.maxvdistance = 32 end
|
||||
if options.numbranchesn == nil then options.numbranchesn = 3 end
|
||||
if options.numbranchesdev == nil then options.numbranchesdev = 2 end
|
||||
if options.mothersizen == nil then options.mothersizen = 1 end
|
||||
if options.mothersizedev == nil then options.mothersizedev = 0.5 end
|
||||
if options.sizen == nil then options.sizen = 120 end
|
||||
if options.sizedev == nil then options.sizedev = 60 end
|
||||
if options.seglenghtn == nil then options.seglenghtn = 6 end
|
||||
if options.seglenghtdev == nil then options.seglenghtdev = 2 end
|
||||
if options.segincln == nil then options.segincln = 0.2 end
|
||||
if options.segincldev == nil then options.segincldev = 0.1 end
|
||||
if options.turnangle == nil then options.turnangle = 20 end
|
||||
if options.forkturnangle == nil then options.forkturnangle = 90 end
|
||||
if options.fork_chance == nil then options.fork_chance = 0.2 end
|
||||
if options.forkmultn == nil then options.forkmultn = 0.75 end
|
||||
if options.forkmultdev == nil then options.forkmultdev = 0.25 end
|
||||
if options.minheight == nil then options.minheight = -31000 end
|
||||
if options.maxheight == nil then options.maxheight = 31000 end
|
||||
if options.radius == nil then options.radius = 0 end
|
||||
return options
|
||||
end
|
|
@ -0,0 +1,58 @@
|
|||
function deepcopy(orig)
|
||||
return minetest.deserialize(minetest.serialize(orig))
|
||||
end
|
||||
|
||||
function rotate_facedir(facedir)
|
||||
return ({1, 2, 3, 0,
|
||||
13, 14, 15, 12,
|
||||
17, 18, 19, 16,
|
||||
9, 10, 11, 8,
|
||||
5, 6, 7, 4,
|
||||
21, 22, 23, 20})[facedir+1]
|
||||
end
|
||||
|
||||
function rotate_wallmounted(wallmounted)
|
||||
return ({0, 1, 5, 4, 2, 3})[wallmounted+1]
|
||||
end
|
||||
|
||||
function rotate_scm(scm)
|
||||
local ysize = #scm
|
||||
local xsize = #scm[1]
|
||||
local zsize = #scm[1][1]
|
||||
local new_scm = {}
|
||||
for i=1, ysize do
|
||||
new_scm[i] = {}
|
||||
for j=1, zsize do
|
||||
new_scm[i][j] = {}
|
||||
end
|
||||
end
|
||||
|
||||
for y = 1, ysize do
|
||||
for x = 1, xsize do
|
||||
for z = 1, zsize do
|
||||
local old = scm[y][x][z]
|
||||
local newx = z
|
||||
local newz = xsize-x+1
|
||||
if type(old) ~= "table" or old.rotation == nil then
|
||||
new_scm[y][newx][newz] = old
|
||||
elseif old.rotation == "wallmounted" then
|
||||
local new = deepcopy(old)
|
||||
new.node.param2 = rotate_wallmounted(new.node.param2)
|
||||
new_scm[y][newx][newz] = new
|
||||
elseif old.rotation == "facedir" then
|
||||
local new = deepcopy(old)
|
||||
new.node.param2 = rotate_facedir(new.node.param2)
|
||||
new_scm[y][newx][newz] = new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return new_scm
|
||||
end
|
||||
|
||||
function rotate(scm, times)
|
||||
for i = 1, times do
|
||||
scm = rotate_scm(scm)
|
||||
end
|
||||
return scm
|
||||
end
|
After Width: | Height: | Size: 402 KiB |
|
@ -0,0 +1,176 @@
|
|||
local function getmp(x)
|
||||
return (80 * math.floor((x + 32) / 80)) - 32
|
||||
end
|
||||
|
||||
local function get_minp(pos)
|
||||
return {x=getmp(pos.x), y=getmp(pos.y), z=getmp(pos.z)}
|
||||
end
|
||||
|
||||
--[[local snow_timer = 0
|
||||
local snow_range = 1
|
||||
minetest.register_globalstep(function(dtime)
|
||||
snow_timer = snow_timer + dtime
|
||||
if snow_timer < 1 then return end
|
||||
snow_timer = 0
|
||||
local noise_temperature_raw = minetest.get_perlin(763, 7, 0.5, 512)
|
||||
local noise_humidity_raw = minetest.get_perlin(834, 7, 0.5, 512)
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local pos = player:getpos()
|
||||
if pos.y > -50 and pos.y < 150 then
|
||||
--local to_update = {}
|
||||
--local to_update_index = 1
|
||||
local minp = get_minp(pos)
|
||||
local biome_table = get_biome_table(minp, noise_humidity_raw, noise_temperature_raw, snow_range+1)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local eminp, emaxp = vm:read_from_map({x=minp.x-80*snow_range, y=-50, z=minp.z-80*snow_range}, {x=minp.x+79+80*snow_range, y=150, z=minp.z+79+80*snow_range})
|
||||
--print(dump(eminp), dump(emaxp))
|
||||
local a = VoxelArea:new{MinEdge=eminp, MaxEdge=emaxp}
|
||||
local data = vm:get_data()
|
||||
for i = 1, 80*(snow_range+1)*(snow_range+1) do
|
||||
local x = math.random(eminp.x, emaxp.x)
|
||||
local z = math.random(eminp.z, emaxp.z)
|
||||
local biome = get_nearest_biome(biome_table, x, z)
|
||||
if biome.t < -0.4 then
|
||||
local y = emaxp.y
|
||||
while y >= eminp.y and data[a:index(x, y, z)] == c_air do
|
||||
y = y - 1
|
||||
end
|
||||
if y >= eminp.y and y < emaxp.y then
|
||||
if data[a:index(x, y, z)] == c_snow then
|
||||
if minetest.add_node_level({x=x, y=y, z=z}, 7) ~= 0 then
|
||||
--data[a:index(x, y+1, z)] = c_snow
|
||||
minetest.set_node({x=x, y=y+1, z=z}, {name = "default:snow"})
|
||||
end
|
||||
else
|
||||
--data[a:index(x, y+1, z)] = c_snow
|
||||
minetest.set_node({x=x, y=y+1, z=z}, {name = "default:snow"})
|
||||
end
|
||||
--to_update[to_update_index] = {x=x,y=y+1,z=z}
|
||||
--to_update_index = to_update_index+1
|
||||
end
|
||||
end
|
||||
end
|
||||
--vm:set_data(data)
|
||||
--vm:write_to_map()
|
||||
--for _, pos in ipairs(to_update) do
|
||||
-- nodeupdate(pos)
|
||||
--end
|
||||
end
|
||||
end
|
||||
end)]]
|
||||
|
||||
local function add_snow_level(pos)
|
||||
local level = minetest.get_node_level(pos)
|
||||
if level <= 28 then
|
||||
minetest.add_node_level(pos, 7)
|
||||
return 0
|
||||
else
|
||||
return 7
|
||||
end
|
||||
end
|
||||
|
||||
local is_snowing = false
|
||||
|
||||
local to_snow = {}
|
||||
local to_snow_index = 0
|
||||
local SNOW_RANGE = 16
|
||||
local SNOW_BLOCK_SIZE = 4
|
||||
local SNOW_STEPS = 10
|
||||
local SNOW_TIMES_PER_BLOCK = 4
|
||||
minetest.register_globalstep(function(dtime)
|
||||
if math.random(1, 5000) == 1 then
|
||||
is_snowing = not is_snowing
|
||||
end
|
||||
if to_snow_index == 0 then
|
||||
if is_snowing then
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local pos = player:getpos()
|
||||
if pos.y > -50 and pos.y < 150 then
|
||||
local x = SNOW_BLOCK_SIZE*math.floor((pos.x/SNOW_BLOCK_SIZE)+0.5)
|
||||
local z = SNOW_BLOCK_SIZE*math.floor((pos.z/SNOW_BLOCK_SIZE)+0.5)
|
||||
for xi = -SNOW_RANGE, SNOW_RANGE do
|
||||
for zi = -SNOW_RANGE, SNOW_RANGE do
|
||||
to_snow_index = to_snow_index + 1
|
||||
to_snow[to_snow_index] = {x=x+SNOW_BLOCK_SIZE*xi, y=0, z=z+SNOW_BLOCK_SIZE*zi}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local noise_temperature_raw = minetest.get_perlin(763, 7, 0.5, 512)
|
||||
local noise_humidity_raw = minetest.get_perlin(834, 7, 0.5, 512)
|
||||
for s = 1, math.min(SNOW_STEPS, to_snow_index) do
|
||||
local pos = to_snow[to_snow_index]
|
||||
--print(dump(pos))
|
||||
to_snow[to_snow_index] = nil
|
||||
to_snow_index = to_snow_index - 1
|
||||
local minp = get_minp(pos)
|
||||
|
||||
local biome_table = get_biome_table(minp, noise_humidity_raw, noise_temperature_raw)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local eminp, emaxp = vm:read_from_map({x=pos.x, y=-50, z=pos.z}, {x=pos.x + SNOW_BLOCK_SIZE - 1, y=150, z=pos.z + SNOW_BLOCK_SIZE - 1})
|
||||
--print(eminp.y, emaxp.y)
|
||||
--print(dump(eminp),dump(emaxp))
|
||||
local a = VoxelArea:new{MinEdge=eminp, MaxEdge=emaxp}
|
||||
local data = vm:get_data()
|
||||
for i = 1, SNOW_TIMES_PER_BLOCK do
|
||||
local x = math.random(pos.x, pos.x + SNOW_BLOCK_SIZE - 1)
|
||||
local z = math.random(pos.z, pos.z + SNOW_BLOCK_SIZE - 1)
|
||||
local biome = get_nearest_biome(biome_table, x, z)
|
||||
if biome.t < -0.4 then
|
||||
local y = emaxp.y
|
||||
while y >= eminp.y and (data[a:index(x, y, z)] == c_air or data[a:index(x, y, z)] == c_ignore) do
|
||||
y = y - 1
|
||||
end
|
||||
if y >= eminp.y and y < emaxp.y then
|
||||
if data[a:index(x, y, z)] == c_snow then
|
||||
--if minetest.add_node_level({x=x, y=y, z=z}, 7) ~= 0 then
|
||||
if add_snow_level({x=x, y=y, z=z}) ~= 0 then
|
||||
-- do nothing, max stack
|
||||
--minetest.set_node({x=x, y=y, z=z}, {name = "default:snowblock"})
|
||||
end
|
||||
elseif data[a:index(x, y, z)] == c_snowblock or data[a:index(x, y, z)] == c_water then
|
||||
-- do nothing
|
||||
else
|
||||
minetest.set_node({x=x, y=y+1, z=z}, {name = "default:snow"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"mg:pineleaves"},
|
||||
interval = 2,
|
||||
chance = 4,
|
||||
action = function(pos, node)
|
||||
local above = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
if minetest.get_node(above).name == "default:snow" then
|
||||
local level = minetest.get_node_level(above)
|
||||
if level >= 14 then
|
||||
for i = 1, 15 do
|
||||
local p = {x=pos.x, y=pos.y-i, z=pos.z}
|
||||
local n = minetest.get_node(p).name
|
||||
if n ~= "air" and n ~= "mg:pineleaves" then
|
||||
if n == "default:snow" then
|
||||
--if minetest.add_node_level(p, 7) == 0 then
|
||||
if add_snow_level(p) == 0 then
|
||||
minetest.add_node_level(above, -7)
|
||||
end
|
||||
else
|
||||
local above_p = {x=p.x, y=p.y+1, z=p.z}
|
||||
if minetest.get_node(above_p).name == "air" then
|
||||
minetest.set_node(above_p, {name = "default:snow"})
|
||||
minetest.add_node_level(above, -7)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
After Width: | Height: | Size: 703 B |
After Width: | Height: | Size: 465 B |
After Width: | Height: | Size: 468 B |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 639 B |
After Width: | Height: | Size: 754 B |
After Width: | Height: | Size: 390 B |
After Width: | Height: | Size: 428 B |
After Width: | Height: | Size: 290 B |
After Width: | Height: | Size: 490 B |
After Width: | Height: | Size: 738 B |
After Width: | Height: | Size: 388 B |
|
@ -0,0 +1,222 @@
|
|||
mg.register_tree({
|
||||
max_biome_humidity = -0.4,
|
||||
min_biome_temperature = 0.4,
|
||||
min_height = 4,
|
||||
max_height = 40,
|
||||
grows_on = c_desert_sand,
|
||||
chance = 50,
|
||||
grow = function(data, a, x, y, z, minp, maxp, pr)
|
||||
-- Cactus
|
||||
local ch = pr:next(1, 4)
|
||||
for yy = math.max(y, minp.y), math.min(y+ch-1, maxp.y) do
|
||||
data[a:index(x, yy, z)] = c_cactus
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
max_biome_humidity = -0.4,
|
||||
min_biome_temperature = 0.4,
|
||||
min_height = 2,
|
||||
max_height = 30,
|
||||
grows_on = c_desert_sand,
|
||||
chance = 50,
|
||||
can_be_in_village = true,
|
||||
grow = function(data, a, x, y, z, minp, maxp, pr)
|
||||
-- Dry shrub
|
||||
if minp.y <= y and y <= maxp.y then
|
||||
data[a:index(x, y, z)] = c_dry_shrub
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = -0.4,
|
||||
max_biome_humidity = 0.4,
|
||||
min_biome_temperature = 0.4,
|
||||
min_height = 2,
|
||||
max_height = 12,
|
||||
grows_on = c_dry_grass,
|
||||
chance = 1000,
|
||||
grow = add_savannatree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = -0.4,
|
||||
max_biome_humidity = 0.4,
|
||||
min_biome_temperature = 0.4,
|
||||
min_height = 13,
|
||||
max_height = 30,
|
||||
grows_on = c_dry_grass,
|
||||
chance = 250,
|
||||
grow = add_savannatree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = -0.4,
|
||||
max_biome_humidity = 0.4,
|
||||
min_biome_temperature = 0.4,
|
||||
min_height = 2,
|
||||
max_height = 40,
|
||||
grows_on = c_dry_grass,
|
||||
chance = 1500,
|
||||
grow = add_savannabush
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = 0.4,
|
||||
min_biome_temperature = 0.4,
|
||||
min_height = 1,
|
||||
max_height = 40,
|
||||
grows_on = c_grass,
|
||||
chance = 14,
|
||||
grow = add_tree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = 0.4,
|
||||
min_biome_temperature = 0.4,
|
||||
min_height = 1,
|
||||
max_height = 25,
|
||||
grows_on = c_grass,
|
||||
chance = 16,
|
||||
grow = add_jungletree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = 0.4,
|
||||
min_biome_temperature = 0.4,
|
||||
min_height = 1,
|
||||
max_height = 25,
|
||||
grows_on = c_grass,
|
||||
chance = 30,
|
||||
can_be_in_village = true,
|
||||
grow = function(data, a, x, y, z, minp, maxp, pr)
|
||||
-- Jungle grass
|
||||
if minp.y <= y and y <= maxp.y then
|
||||
data[a:index(x, y, z)] = c_jungle_grass
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = -0.4,
|
||||
max_biome_temperature = -0.4,
|
||||
min_height = 3,
|
||||
max_height = 55,
|
||||
grows_on = c_dirt_snow,
|
||||
chance = 40,
|
||||
grow = add_pinetree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
max_biome_humidity = -0.4,
|
||||
max_biome_temperature = -0.4,
|
||||
min_height = 3,
|
||||
max_height = 55,
|
||||
grows_on = c_dirt_snow,
|
||||
chance = 500,
|
||||
grow = add_pinetree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
max_biome_humidity = -0.4,
|
||||
min_biome_temperature = -0.4,
|
||||
max_biome_temperature = 0.4,
|
||||
min_height = 1,
|
||||
max_height = 40,
|
||||
grows_on = c_grass,
|
||||
chance = 250,
|
||||
grow = add_tree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
max_biome_humidity = -0.4,
|
||||
min_biome_temperature = -0.4,
|
||||
max_biome_temperature = 0.4,
|
||||
min_height = 1,
|
||||
max_height = 40,
|
||||
grows_on = c_grass,
|
||||
chance = 60,
|
||||
can_be_in_village = true,
|
||||
grow = function(data, a, x, y, z, minp, maxp, pr)
|
||||
-- Grass 1-4
|
||||
if minp.y <= y and y <= maxp.y then
|
||||
data[a:index(x, y, z)] = c_grasses[pr:next(1, 4)]
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = 0.4,
|
||||
min_biome_temperature = -0.4,
|
||||
max_biome_temperature = 0.4,
|
||||
min_height = 1,
|
||||
max_height = 40,
|
||||
grows_on = c_grass,
|
||||
chance = 250,
|
||||
grow = add_tree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = 0.4,
|
||||
min_biome_temperature = -0.4,
|
||||
max_biome_temperature = 0.4,
|
||||
min_height = 3,
|
||||
max_height = 40,
|
||||
grows_on = c_grass,
|
||||
chance = 3,
|
||||
can_be_in_village = true,
|
||||
grow = function(data, a, x, y, z, minp, maxp, pr)
|
||||
-- Grass 3-5
|
||||
if minp.y <= y and y <= maxp.y then
|
||||
data[a:index(x, y, z)] = c_grasses[pr:next(3, 5)]
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_biome_humidity = -0.4,
|
||||
max_biome_humidity = 0.4,
|
||||
min_biome_temperature = -0.4,
|
||||
max_biome_temperature = 0.4,
|
||||
min_height = 3,
|
||||
max_height = 40,
|
||||
grows_on = c_grass,
|
||||
chance = 20,
|
||||
grow = add_tree
|
||||
})
|
||||
|
||||
mg.register_tree({
|
||||
min_height = 1,
|
||||
max_height = 1,
|
||||
grows_on = c_grass,
|
||||
chance = 10,
|
||||
grow = function(data, a, x, y, z, minp, maxp, pr)
|
||||
-- Papyrus
|
||||
local ph = pr:next(2, 4)
|
||||
for yy = math.max(y, minp.y), math.min(y+ph-1, maxp.y) do
|
||||
data[a:index(x, yy, z)] = c_papyrus
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
function mg.get_spawn_tree_func(treedef)
|
||||
return function(data, a, x, y, z, minp, maxp, pr)
|
||||
if minp.y <= y and y <= maxp.y then
|
||||
minetest.after(0, minetest.spawn_tree, {x=x, y=y, z=z}, treedef)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if minetest.get_modpath("moretrees") then
|
||||
mg.register_tree({
|
||||
min_humidity = 0,
|
||||
min_temperature = 0.2,
|
||||
min_height = 1,
|
||||
max_height = 5,
|
||||
grows_on = c_grass,
|
||||
chance = 800,
|
||||
grow = mg.get_spawn_tree_func(moretrees.rubber_tree_model)
|
||||
})
|
||||
end
|
|
@ -0,0 +1,343 @@
|
|||
VILLAGE_CHECK_RADIUS = 2
|
||||
VILLAGE_CHECK_COUNT = 1
|
||||
VILLAGE_CHANCE = 28
|
||||
VILLAGE_MIN_SIZE = 20
|
||||
VILLAGE_MAX_SIZE = 40
|
||||
FIRST_ROADSIZE = 3
|
||||
BIG_ROAD_CHANCE = 0
|
||||
|
||||
-- Enable that for really big villages (there are also really slow to generate)
|
||||
--[[VILLAGE_CHECK_RADIUS = 3
|
||||
VILLAGE_CHECK_COUNT = 3
|
||||
VILLAGE_CHANCE = 28
|
||||
VILLAGE_MIN_SIZE = 100
|
||||
VILLAGE_MAX_SIZE = 150
|
||||
FIRST_ROADSIZE = 5
|
||||
BIG_ROAD_CHANCE = 50]]
|
||||
|
||||
local function is_village_block(minp)
|
||||
local x, z = math.floor(minp.x/80), math.floor(minp.z/80)
|
||||
local vcc = VILLAGE_CHECK_COUNT
|
||||
return (x%vcc == 0) and (z%vcc == 0)
|
||||
end
|
||||
|
||||
function villages_at_point(minp, noise1)
|
||||
if not is_village_block(minp) then return {} end
|
||||
local vcr, vcc = VILLAGE_CHECK_RADIUS, VILLAGE_CHECK_COUNT
|
||||
-- Check if there's another village nearby
|
||||
for xi = -vcr, vcr, vcc do
|
||||
for zi = -vcr, 0, vcc do
|
||||
if xi ~= 0 or zi ~= 0 then
|
||||
local mp = {x = minp.x + 80*xi, z = minp.z + 80*zi}
|
||||
local pi = PseudoRandom(get_bseed(mp))
|
||||
local s = pi:next(1, 400)
|
||||
local x = pi:next(mp.x, mp.x + 79)
|
||||
local z = pi:next(mp.z, mp.z + 79)
|
||||
if s <= VILLAGE_CHANCE and noise1:get2d({x = x, y = z}) >= -0.3 then return {} end
|
||||
end
|
||||
end
|
||||
end
|
||||
local pr = PseudoRandom(get_bseed(minp))
|
||||
if pr:next(1, 400) > VILLAGE_CHANCE then return {} end -- No village here
|
||||
local x = pr:next(minp.x, minp.x + 79)
|
||||
local z = pr:next(minp.z, minp.z + 79)
|
||||
if noise1:get2d({x = x, y = z}) < -0.3 then return {} end -- Deep in the ocean
|
||||
local type = pr:next(1, 1) -- TODO: actually make them
|
||||
local size = pr:next(VILLAGE_MIN_SIZE, VILLAGE_MAX_SIZE) -- TODO: change to type-dependant sizes
|
||||
local height = pr:next(5, 20)
|
||||
--print("A village spawned at: x = "..x..", z = "..z)
|
||||
return {{vx = x, vz = z, vs = size, vh = height, type = type}}
|
||||
end
|
||||
|
||||
--local function dist_center2(ax, bsizex, az, bsizez)
|
||||
-- return math.max((ax+bsizex)*(ax+bsizex),ax*ax)+math.max((az+bsizez)*(az+bsizez),az*az)
|
||||
--end
|
||||
|
||||
local function inside_village2(bx, sx, bz, sz, village, vnoise)
|
||||
return inside_village(bx, bz, village, vnoise) and inside_village(bx+sx, bz, village, vnoise) and inside_village(bx, bz+sz, village, vnoise) and inside_village(bx+sx, bz+sz, village, vnoise)
|
||||
end
|
||||
|
||||
local function choose_building(l, pr)
|
||||
--::choose::
|
||||
local btype
|
||||
while true do
|
||||
local p = pr:next(1, 3000)
|
||||
for b, i in ipairs(buildings) do
|
||||
if i.max_weight >= p then
|
||||
btype = b
|
||||
break
|
||||
end
|
||||
end
|
||||
if buildings[btype].pervillage ~= nil then
|
||||
local n = 0
|
||||
for j=1, #l do
|
||||
if l[j].btype == btype then
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
--if n >= buildings[btype].pervillage then
|
||||
-- goto choose
|
||||
--end
|
||||
if n < buildings[btype].pervillage then
|
||||
return btype
|
||||
end
|
||||
else
|
||||
return btype
|
||||
end
|
||||
end
|
||||
--return btype
|
||||
end
|
||||
|
||||
local function choose_building_rot(l, pr, orient)
|
||||
local btype = choose_building(l, pr)
|
||||
local rotation
|
||||
if buildings[btype].no_rotate then
|
||||
rotation = 0
|
||||
else
|
||||
if buildings[btype].orients == nil then
|
||||
buildings[btype].orients = {0,1,2,3}
|
||||
end
|
||||
rotation = (orient+buildings[btype].orients[pr:next(1, #buildings[btype].orients)])%4
|
||||
end
|
||||
local bsizex = buildings[btype].sizex
|
||||
local bsizez = buildings[btype].sizez
|
||||
if rotation%2 == 1 then
|
||||
bsizex, bsizez = bsizez, bsizex
|
||||
end
|
||||
return btype, rotation, bsizex, bsizez
|
||||
end
|
||||
|
||||
local function placeable(bx, bz, bsizex, bsizez, l, exclude_roads)
|
||||
for _, a in ipairs(l) do
|
||||
if (a.btype ~= "road" or not exclude_roads) and math.abs(bx+bsizex/2-a.x-a.bsizex/2)<=(bsizex+a.bsizex)/2 and math.abs(bz+bsizez/2-a.z-a.bsizez/2)<=(bsizez+a.bsizez)/2 then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function road_in_building(rx, rz, rdx, rdz, roadsize, l)
|
||||
if rdx == 0 then
|
||||
return not placeable(rx-roadsize+1, rz, 2*roadsize-2, 0, l, true)
|
||||
else
|
||||
return not placeable(rx, rz-roadsize+1, 0, 2*roadsize-2, l, true)
|
||||
end
|
||||
end
|
||||
|
||||
local function when(a, b, c)
|
||||
if a then return b else return c end
|
||||
end
|
||||
|
||||
local calls
|
||||
local function generate_road(village, l, pr, roadsize, rx, rz, rdx, rdz, vnoise)
|
||||
local vx, vz, vh, vs = village.vx, village.vz, village.vh, village.vs
|
||||
local calls_to_do = {}
|
||||
local rxx = rx
|
||||
local rzz = rz
|
||||
local mx, m2x, mz, m2z, mmx, mmz
|
||||
mx, m2x, mz, m2z = rx, rx, rz, rz
|
||||
local orient1, orient2
|
||||
if rdx == 0 then
|
||||
orient1 = 0
|
||||
orient2 = 2
|
||||
else
|
||||
orient1 = 3
|
||||
orient2 = 1
|
||||
end
|
||||
while inside_village(rx, rz, village, vnoise) and not road_in_building(rx, rz, rdx, rdz, roadsize, l) do
|
||||
if roadsize > 1 and pr:next(1, 4) == 1 then
|
||||
--generate_road(vx, vz, vs, vh, l, pr, roadsize-1, rx, rz, math.abs(rdz), math.abs(rdx))
|
||||
calls_to_do[#calls_to_do+1] = {rx=rx+(roadsize - 1)*rdx, rz=rz+(roadsize - 1)*rdz, rdx=math.abs(rdz), rdz=math.abs(rdx)}
|
||||
m2x = rx + (roadsize - 1)*rdx
|
||||
m2z = rz + (roadsize - 1)*rdz
|
||||
rx = rx + (2*roadsize - 1)*rdx
|
||||
rz = rz + (2*roadsize - 1)*rdz
|
||||
end
|
||||
--else
|
||||
--::loop::
|
||||
local exitloop = false
|
||||
local tries = 0
|
||||
local btype, rotation, bsizex, bsizez
|
||||
local bx, bz
|
||||
while true do
|
||||
if not inside_village(rx, rz, village, vnoise) or road_in_building(rx, rz, rdx, rdz, roadsize, l) then
|
||||
exitloop = true
|
||||
break
|
||||
end
|
||||
btype, rotation, bsizex, bsizez = choose_building_rot(l, pr, orient1)
|
||||
bx = rx + math.abs(rdz) * (roadsize + 1) - when(rdx == -1, bsizex - 1, 0)
|
||||
bz = rz + math.abs(rdx) * (roadsize + 1) - when(rdz == -1, bsizez - 1, 0)
|
||||
if placeable(bx, bz, bsizex, bsizez, l) and inside_village2(bx, bsizex, bz, bsizez, village, vnoise) then
|
||||
break
|
||||
end
|
||||
if tries > 5 then
|
||||
rx = rx + rdx
|
||||
rz = rz + rdz
|
||||
tries = 0
|
||||
else
|
||||
tries = tries + 1
|
||||
end
|
||||
--goto loop
|
||||
end
|
||||
if exitloop then break end
|
||||
rx = rx + (bsizex + 1) * rdx
|
||||
rz = rz + (bsizez + 1) * rdz
|
||||
mx = rx - 2 * rdx
|
||||
mz = rz - 2 * rdz
|
||||
l[#l + 1] = {x = bx, y = vh, z = bz, btype = btype, bsizex = bsizex, bsizez = bsizez, brotate = rotation}
|
||||
--end
|
||||
end
|
||||
rx = rxx
|
||||
rz = rzz
|
||||
while inside_village(rx, rz, village, vnoise) and not road_in_building(rx, rz, rdx, rdz, roadsize, l) do
|
||||
if roadsize > 1 and pr:next(1, 4) == 1 then
|
||||
--generate_road(vx, vz, vs, vh, l, pr, roadsize-1, rx, rz, -math.abs(rdz), -math.abs(rdx))
|
||||
calls_to_do[#calls_to_do+1] = {rx=rx+(roadsize - 1)*rdx, rz=rz+(roadsize - 1)*rdz, rdx=-math.abs(rdz), rdz=-math.abs(rdx)}
|
||||
m2x = rx + (roadsize - 1)*rdx
|
||||
m2z = rz + (roadsize - 1)*rdz
|
||||
rx = rx + (2*roadsize - 1)*rdx
|
||||
rz = rz + (2*roadsize - 1)*rdz
|
||||
end
|
||||
--else
|
||||
--::loop::
|
||||
local exitloop = false
|
||||
local tries = 0
|
||||
local btype, rotation, bsizex, bsizez
|
||||
local bx, bz
|
||||
while true do
|
||||
if not inside_village(rx, rz, village, vnoise) or road_in_building(rx, rz, rdx, rdz, roadsize, l) then
|
||||
exitloop = true
|
||||
break
|
||||
end
|
||||
btype, rotation, bsizex, bsizez = choose_building_rot(l, pr, orient2)
|
||||
bx = rx - math.abs(rdz) * (bsizex + roadsize) - when(rdx == -1, bsizex - 1, 0)
|
||||
bz = rz - math.abs(rdx) * (bsizez + roadsize) - when(rdz == -1, bsizez - 1, 0)
|
||||
if placeable(bx, bz, bsizex, bsizez, l) and inside_village2(bx, bsizex, bz, bsizez, village, vnoise) then
|
||||
break
|
||||
end
|
||||
if tries > 5 then
|
||||
rx = rx + rdx
|
||||
rz = rz + rdz
|
||||
tries = 0
|
||||
else
|
||||
tries = tries + 1
|
||||
end
|
||||
--goto loop
|
||||
end
|
||||
if exitloop then break end
|
||||
rx = rx + (bsizex + 1) * rdx
|
||||
rz = rz + (bsizez + 1) * rdz
|
||||
m2x = rx - 2 * rdx
|
||||
m2z = rz - 2 * rdz
|
||||
l[#l + 1] = {x = bx, y = vh, z = bz, btype = btype, bsizex = bsizex, bsizez = bsizez, brotate = rotation}
|
||||
--end
|
||||
end
|
||||
if road_in_building(rx, rz, rdx, rdz, roadsize, l) then
|
||||
mmx = rx - 2*rdx
|
||||
mmz = rz - 2*rdz
|
||||
end
|
||||
mx = mmx or rdx*math.max(rdx*mx, rdx*m2x)
|
||||
mz = mmz or rdz*math.max(rdz*mz, rdz*m2z)
|
||||
local rxmin, rxmax, rzmin, rzmax
|
||||
if rdx == 0 then
|
||||
rxmin = rx - roadsize + 1
|
||||
rxmax = rx + roadsize - 1
|
||||
rzmin = math.min(rzz, mz)
|
||||
rzmax = math.max(rzz, mz)
|
||||
else
|
||||
rzmin = rz - roadsize + 1
|
||||
rzmax = rz + roadsize - 1
|
||||
rxmin = math.min(rxx, mx)
|
||||
rxmax = math.max(rxx, mx)
|
||||
end
|
||||
l[#l + 1] = {x = rxmin, y = vh, z = rzmin, btype = "road",
|
||||
bsizex = rxmax - rxmin + 1, bsizez = rzmax - rzmin + 1, brotate = 0}
|
||||
for _, i in ipairs(calls_to_do) do
|
||||
local new_roadsize = roadsize - 1
|
||||
if pr:next(1, 100) <= BIG_ROAD_CHANCE then
|
||||
new_roadsize = roadsize
|
||||
end
|
||||
calls[calls.index] = {village, l, pr, new_roadsize, i.rx, i.rz, i.rdx, i.rdz, vnoise}
|
||||
calls.index = calls.index+1
|
||||
end
|
||||
end
|
||||
|
||||
local function generate_bpos(village, pr, vnoise)
|
||||
local vx, vz, vh, vs = village.vx, village.vz, village.vh, village.vs
|
||||
local l = {}
|
||||
local rx = vx - vs
|
||||
local rz = vz
|
||||
while inside_village(rx, rz, village, vnoise) do
|
||||
rx = rx - 1
|
||||
end
|
||||
rx = rx + 5
|
||||
calls = {index = 1}
|
||||
generate_road(village, l, pr, FIRST_ROADSIZE, rx, rz, 1, 0, vnoise)
|
||||
local i = 1
|
||||
while i < calls.index do
|
||||
generate_road(unpack(calls[i]))
|
||||
i = i + 1
|
||||
end
|
||||
return l
|
||||
end
|
||||
|
||||
local function generate_building(pos, minp, maxp, data, param2_data, a, pr, extranodes)
|
||||
local binfo = buildings[pos.btype]
|
||||
local scm
|
||||
if type(binfo.scm) == "string" then
|
||||
scm = import_scm(binfo.scm)
|
||||
else
|
||||
scm = binfo.scm
|
||||
end
|
||||
scm = rotate(scm, pos.brotate)
|
||||
for x = 0, pos.bsizex - 1 do
|
||||
for y = 0, binfo.ysize - 1 do
|
||||
for z = 0, pos.bsizez - 1 do
|
||||
local ax, ay, az = pos.x + x, pos.y + y + binfo.yoff, pos.z + z
|
||||
if (ax >= minp.x and ax <= maxp.x) and (ay >= minp.y and ay <= maxp.y) and (az >= minp.z and az <= maxp.z) then
|
||||
local t = scm[y +1][x +1][z + 1]
|
||||
if type(t) == "table" then
|
||||
if t.extranode then
|
||||
table.insert(extranodes, {node = t.node, meta = t.meta, pos = {x = ax, y = ay, z = az}})
|
||||
else
|
||||
data[a:index(ax, ay, az)] = t.node.content
|
||||
param2_data[a:index(ax, ay, az)] = t.node.param2
|
||||
end
|
||||
elseif t ~= c_ignore then
|
||||
data[a:index(ax, ay, az)] = t
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local MIN_DIST = 1
|
||||
|
||||
local function pos_far_buildings(x, z, l)
|
||||
for _, a in ipairs(l) do
|
||||
if a.x - MIN_DIST <= x and x <= a.x + a.bsizex + MIN_DIST and
|
||||
a.z - MIN_DIST <= z and z <= a.z + a.bsizez + MIN_DIST then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function generate_village(village, minp, maxp, data, param2_data, a, vnoise)
|
||||
local vx, vz, vs, vh = village.vx, village.vz, village.vs, village.vh
|
||||
local seed = get_bseed({x=vx, z=vz})
|
||||
local pr_village = PseudoRandom(seed)
|
||||
local bpos = generate_bpos(village, pr_village, vnoise)
|
||||
|
||||
local pr = PseudoRandom(seed)
|
||||
for _, g in ipairs(village.to_grow) do
|
||||
if pos_far_buildings(g.x, g.z, bpos) then
|
||||
mg.registered_trees[g.id].grow(data, a, g.x, g.y, g.z, minp, maxp, pr)
|
||||
end
|
||||
end
|
||||
|
||||
local extranodes = {}
|
||||
for _, pos in ipairs(bpos) do
|
||||
generate_building(pos, minp, maxp, data, param2_data, a, pr_village, extranodes)
|
||||
end
|
||||
return extranodes
|
||||
end
|
|
@ -0,0 +1,105 @@
|
|||
local function numk(tbl)
|
||||
local i = 0
|
||||
for a, b in pairs(tbl) do
|
||||
i = i + 1
|
||||
end
|
||||
return i
|
||||
end
|
||||
|
||||
function import_scm(scm)
|
||||
local c_ignore = minetest.get_content_id("ignore")
|
||||
local f, err = io.open(minetest.get_modpath("mg").."/schems/"..scm..".we", "r")
|
||||
if not f then
|
||||
error("Could not open schematic '" .. scm .. ".we': " .. err)
|
||||
end
|
||||
local value = f:read("*a")
|
||||
f:close()
|
||||
if value:sub(1, 2) == "5:" then
|
||||
value = value:sub(3)
|
||||
end
|
||||
value = value:gsub("return%s*{", "", 1):gsub("}%s*$", "", 1)
|
||||
local escaped = value:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end)
|
||||
local startpos, startpos1, endpos = 1, 1
|
||||
local nodes = {}
|
||||
while true do
|
||||
startpos, endpos = escaped:find("},%s*{", startpos)
|
||||
if not startpos then
|
||||
break
|
||||
end
|
||||
local current = value:sub(startpos1, startpos)
|
||||
table.insert(nodes, minetest.deserialize("return " .. current))
|
||||
startpos, startpos1 = endpos, endpos
|
||||
end
|
||||
table.insert(nodes, minetest.deserialize("return " .. value:sub(startpos1)))
|
||||
scm = {}
|
||||
local maxx, maxy, maxz = -1, -1, -1
|
||||
for i = 1, #nodes do
|
||||
local ent = nodes[i]
|
||||
ent.x = ent.x + 1
|
||||
ent.y = ent.y + 1
|
||||
ent.z = ent.z + 1
|
||||
if ent.x > maxx then
|
||||
maxx = ent.x
|
||||
end
|
||||
if ent.y > maxy then
|
||||
maxy = ent.y
|
||||
end
|
||||
if ent.z > maxz then
|
||||
maxz = ent.z
|
||||
end
|
||||
if scm[ent.y] == nil then
|
||||
scm[ent.y] = {}
|
||||
end
|
||||
if scm[ent.y][ent.x] == nil then
|
||||
scm[ent.y][ent.x] = {}
|
||||
end
|
||||
if ent.param2 == nil then
|
||||
ent.param2 = 0
|
||||
end
|
||||
if ent.meta == nil then
|
||||
ent.meta = {fields={}, inventory={}}
|
||||
end
|
||||
local paramtype2 = minetest.registered_nodes[ent.name] and minetest.registered_nodes[ent.name].paramtype2
|
||||
if ent.name == "mg:ignore" or not paramtype2 then
|
||||
scm[ent.y][ent.x][ent.z] = c_ignore
|
||||
elseif numk(ent.meta.fields) == 0 and numk(ent.meta.inventory) == 0 then
|
||||
if paramtype2 ~= "facedir" and paramtype2 ~= "wallmounted" then
|
||||
scm[ent.y][ent.x][ent.z] = minetest.get_content_id(ent.name)
|
||||
else
|
||||
scm[ent.y][ent.x][ent.z] = {
|
||||
node = {
|
||||
content = minetest.get_content_id(ent.name),
|
||||
param2 = ent.param2},
|
||||
rotation = paramtype2}
|
||||
end
|
||||
else
|
||||
if paramtype2 ~= "facedir" and paramtype2 ~= "wallmounted" then
|
||||
scm[ent.y][ent.x][ent.z] = {extranode = true,
|
||||
node = {name = ent.name, param2 = ent.param2},
|
||||
meta = ent.meta}
|
||||
else
|
||||
scm[ent.y][ent.x][ent.z] = {extranode = true,
|
||||
node = {name = ent.name, param2 = ent.param2},
|
||||
meta = ent.meta,
|
||||
rotation = paramtype2}
|
||||
end
|
||||
end
|
||||
end
|
||||
local c_air = minetest.get_content_id("air")
|
||||
for x = 1, maxx do
|
||||
for y = 1, maxy do
|
||||
for z = 1, maxz do
|
||||
if scm[y] == nil then
|
||||
scm[y] = {}
|
||||
end
|
||||
if scm[y][x] == nil then
|
||||
scm[y][x] = {}
|
||||
end
|
||||
if scm[y][x][z] == nil then
|
||||
scm[y][x][z] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return scm
|
||||
end
|