nodecore-skyblock/nc_sky_isgen/init.lua

201 lines
5.7 KiB
Lua

--nothing--
local grass = "nc_terrain:dirt_with_grass"
local dirt = "nc_terrain:dirt"
local tree = "nc_tree:eggcorn_planted"
local stone = "nc_terrain:stone"
local queue = {}
local function maxval(octaves,persistence,scale)
local m = scale
local poc = scale
if octaves > 1 then
for n=2,octaves do
poc = poc*persistence
m=m+poc
end
end
return m
end
local function island(pos,r)
local x,y,z = pos.x,pos.y,pos.z
minetest.emerge_area({x=x-r,y=y-r,z=z-r},{x=x+r,y=y+r,z=z+r},function(bp,act,crem)
if crem > 0 then
return
end
local n = 0
local c = 0
local cm = (r*2+1)^3
local function geto(x,y,z)
local dist = (x*x+y*y+z*z)^0.5
local uvdist = (y+r)/(r*2)
local hdist = (x*x+z*z)^0.5
local uhdist = (math.max(0,r-hdist)/r)^((1-uvdist)^3*5)
local udist = math.max(0,r-dist)/r
local m = ((math.max(r-(hdist),0)/r)^0.1*(uhdist^2))-uhdist*uvdist^3
return m
end
local grasses = {}
for x=-r,r do
for z=-r,r do
for y=-r,r do
local xx,yy,zz = pos.x+x,pos.y+y,pos.z+z
local o,o2 = geto(x,y,z),geto(x,y+1,z)
local oc = (o > 0.4)
local oc2 = o2 > 0.4
local og = (o > 0.6)
if oc then
n=n+1
local nam = dirt
if not og and not oc2 then
nam = grass
table.insert(grasses,{x=xx,y=yy,z=zz})
end
if og then
nam = stone
end
minetest.set_node({x=xx,y=yy,z=zz},{name=nam})
else
n=n+0.01
end
if n > 1000 then
n=0
--coroutine.yield()
end
end
end
end
for n=1,4 do
if #grasses > 1 then
local n = math.random(1,#grasses)
local v = table.remove(grasses,n)
minetest.set_node(v,{name=tree})
local meta = minetest.get_meta(v)
meta:set_float("growth",5000)
end
end
end)
end
local f,abs = math.floor, math.abs
local function spawn_island(name,pos)
local ref = minetest.get_player_by_name(name)
pos = {x=f(pos.x),y=f(pos.y),z=f(pos.z)}
island(pos,16,name)
ref:set_pos({x=pos.x,y=pos.y+256,z=pos.z})
end
local store = minetest.get_mod_storage()
local function pid(x,z)
return "i"..x.."_"..z
end
local function checkpos(x,z)
if store:get_string(pid(x,z)) == "" then
return true
end
end
minetest.override_item("ignore",{
drawtype = "normal",
tiles={"nc_terrain_lava.png","nc_terrain_lava.png","nc_terrain_lava.png","nc_terrain_lava.png","nc_terrain_lava.png","nc_terrain_lava.png"},
walkable=true,
pointable=true
})
local function gen_island_pos(name)
local x,z = 0,0
local ok = checkpos(x,z)
while not ok do
x,z = x+math.random(-1,1),z+math.random(-1,1)
ok = checkpos(x,z)
end
store:set_string(pid(x,z),name)
local range = {min={x=x*128-64,y=256-64,z=z*128-64},max={x=x*128+64,y=256+64,z=z*128+64}}
local ip = {x=x*128+math.random(-32,32),y=256+math.random(-32,32),z=z*128+math.random(-32,32)}
spawn_island(name,ip)
return pid(x,z),ip,range
end
local updrate = 0.5
local to_upd = updrate
minetest.register_globalstep(function(dt)
for f,_ in pairs(queue) do
local ok,err = coroutine.resume(f)
if not ok then
print(err)
queue[f]=nil
end
end
to_upd = to_upd-dt
if to_upd <= 0 then
to_upd = to_upd+updrate
for k,ref in pairs(minetest.get_connected_players()) do
local p = ref:get_pos()
if p.y < 0 then
ref:set_hp(ref:get_hp()-2,{reason="set_hp"})
if p.y < -128 then
local meta = ref:get_meta()
local pos = minetest.string_to_pos(meta:get_string("islandpos"))
if pos then
pos.y=pos.y+256
ref:set_pos(pos)
end
end
end
end
end
end)
minetest.register_chatcommand("reset",{
description = "Reset your island",
func = function(name,param)
local ref = minetest.get_player_by_name(name)
local meta = ref:get_meta()
local r = meta:get_string("islandrange")
r = minetest.deserialize(r)
minetest.emerge_area(r.min,r.max,function(bp,act,crem)
if crem > 0 then
return
end
local ref = minetest.get_player_by_name(name)
local meta = ref:get_meta()
local istr = meta:get_string("islandpos")
local pos = minetest.string_to_pos(istr)
if pos then
local r = meta:get_string("islandrange")
r = minetest.deserialize(r)
print("Resetting island "..istr.." owned by "..name)
air_c = minetest.get_content_id("air")
local vm = VoxelManip(r.min,r.max)
local rmi,rma = vm:get_emerged_area()
local var = VoxelArea:new{MinEdge=rmi,MaxEdge=rma}
local d = vm:get_data()
for x=r.min.x,r.max.x do
for y=r.min.y,r.max.y do
for z=r.min.z,r.max.z do
local i = var:index(x,y,z)
d[i] = air_c
end
end
end
local cpos = {x=(r.min.x+r.max.x)/2,y=(r.min.y+r.max.y)/2,z=(r.min.z+r.max.z)/2};
local r =
(abs(r.min.x-cpos.x)+abs(r.max.x-cpos.x)+
abs(r.min.y-cpos.y)+abs(r.max.y-cpos.y)+
abs(r.min.z-cpos.z)+abs(r.max.z-cpos.z))/6
for k,v in pairs(minetest.get_objects_inside_radius(cpos,r)) do
v:remove()
end
vm:set_data(d)
vm:write_to_map()
spawn_island(name,pos)
end
end)
end
})
minetest.register_on_joinplayer(function(ref)
local meta = ref:get_meta()
local name = ref:get_player_name()
if meta:get_string("island") == "" then
local p,ip,r = gen_island_pos(name)
meta:set_string("island",p)
meta:set_string("islandpos",minetest.pos_to_string(ip))
meta:set_string("islandrange",minetest.serialize(r))
end
end)