mirror of
https://github.com/minetest/minetest.git
synced 2024-09-27 15:00:30 +02:00
Move trees generation into Lua mod
This commit is contained in:
parent
8c3ffa3907
commit
757b5963f6
|
@ -22,6 +22,28 @@ minetest.register_on_joinplayer(function(player)
|
|||
minetest.after(2.0, cb, player)
|
||||
end)
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"default:sapling"},
|
||||
interval = 10,
|
||||
chance = 50,
|
||||
action = function(pos, node)
|
||||
if not minetest.env:get_node_light(pos) then
|
||||
return
|
||||
end
|
||||
if minetest.env:get_node_light(pos) < 8 then
|
||||
return
|
||||
end
|
||||
for dy=1,5 do
|
||||
pos.y = pos.y+dy
|
||||
if not minetest.registered_nodes[minetest.env:get_node(pos).name].buildable_to then
|
||||
return
|
||||
end
|
||||
pos.y = pos.y-dy
|
||||
end
|
||||
make_tree(pos, math.random(1,4)==1)
|
||||
end
|
||||
})
|
||||
|
||||
--
|
||||
-- Tool definition
|
||||
--
|
||||
|
|
|
@ -66,6 +66,77 @@ local function generate_ore(name, wherein, minp, maxp, seed, chunks_per_volume,
|
|||
end
|
||||
end
|
||||
--print("generate_ore done")
|
||||
--Generate trees
|
||||
local perlin1 = minetest.env:get_perlin(200, 3, 0.6, 100)
|
||||
-- Assume X and Z lengths are equal
|
||||
local divlen = 16
|
||||
local divs = (maxp.x-minp.x)/divlen+1;
|
||||
for divx=0,divs-1 do
|
||||
for divz=0,divs-1 do
|
||||
local x0 = minp.x + math.floor((divx+0)*divlen)
|
||||
local z0 = minp.z + math.floor((divz+0)*divlen)
|
||||
local x1 = minp.x + math.floor((divx+1)*divlen)
|
||||
local z1 = minp.z + math.floor((divz+1)*divlen)
|
||||
local cobbles_amount = math.floor(perlin1:get2d({x=x0, y=z0}) * 5 + 0)
|
||||
local pr = PseudoRandom(seed+1)
|
||||
for i=0,cobbles_amount do
|
||||
local x = pr:next(x0, x1)
|
||||
local z = pr:next(z0, z1)
|
||||
-- Find ground level (0...15)
|
||||
local ground_y = nil
|
||||
for y=30,0,-1 do
|
||||
if minetest.env:get_node({x=x,y=y,z=z}).name ~= "air" then
|
||||
ground_y = y
|
||||
break
|
||||
end
|
||||
end
|
||||
if ground_y and minetest.env:get_node({x=x,y=ground_y,z=z}).name == "default:dirt_with_grass" then
|
||||
make_tree({x=x,y=ground_y+1,z=z}, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function make_tree(pos, is_apple_tree)
|
||||
for _=1,math.random(4,5) do
|
||||
minetest.env:set_node(pos, {name="default:tree"})
|
||||
pos.y = pos.y+1
|
||||
end
|
||||
|
||||
pos.y = pos.y-1
|
||||
|
||||
local function set_leaves(pos)
|
||||
if minetest.registered_nodes[minetest.env:get_node(pos).name].buildable_to then
|
||||
if is_apple_tree and math.random(1, 10)==1 then
|
||||
minetest.env:set_node(pos, {name="default:apple"})
|
||||
else
|
||||
minetest.env:set_node(pos, {name="default:leaves"})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for dx=-1,1 do
|
||||
for dy=-1,1 do
|
||||
for dz=-1,1 do
|
||||
set_leaves({x=pos.x+dx,y=pos.y+dy,z=pos.z+dz})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _=1,8 do
|
||||
local p = {x=math.random(-2, 1),y=math.random(-1, 1),z=math.random(-2, 1),}
|
||||
p.x = p.x+pos.x
|
||||
p.y = p.y+pos.y
|
||||
p.z = p.z+pos.z
|
||||
for dx=0,1 do
|
||||
for dy=0,1 do
|
||||
for dz=0,1 do
|
||||
set_leaves({x=p.x+dx,y=p.y+dy,z=p.z+dz})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, seed)
|
||||
|
|
|
@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_sao.h"
|
||||
#include "settings.h"
|
||||
#include "mapblock.h" // For getNodeBlockPos
|
||||
#include "mapgen.h" // For mapgen::make_tree
|
||||
#include "map.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
@ -89,67 +88,10 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class MakeTreesFromSaplingsABM : public ActiveBlockModifier
|
||||
{
|
||||
private:
|
||||
public:
|
||||
virtual std::set<std::string> getTriggerContents()
|
||||
{
|
||||
std::set<std::string> s;
|
||||
s.insert("sapling");
|
||||
return s;
|
||||
}
|
||||
virtual float getTriggerInterval()
|
||||
{ return 10.0; }
|
||||
virtual u32 getTriggerChance()
|
||||
{ return 50; }
|
||||
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
|
||||
u32 active_object_count, u32 active_object_count_wider)
|
||||
{
|
||||
INodeDefManager *ndef = env->getGameDef()->ndef();
|
||||
ServerMap *map = &env->getServerMap();
|
||||
|
||||
actionstream<<"A sapling grows into a tree at "
|
||||
<<PP(p)<<std::endl;
|
||||
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
v3s16 tree_p = p;
|
||||
ManualMapVoxelManipulator vmanip(map);
|
||||
v3s16 tree_blockp = getNodeBlockPos(tree_p);
|
||||
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
|
||||
bool is_apple_tree = myrand()%4 == 0;
|
||||
mapgen::make_tree(vmanip, tree_p, is_apple_tree, ndef);
|
||||
vmanip.blitBackAll(&modified_blocks);
|
||||
|
||||
// update lighting
|
||||
core::map<v3s16, MapBlock*> lighting_modified_blocks;
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue());
|
||||
}
|
||||
map->updateLighting(lighting_modified_blocks, modified_blocks);
|
||||
|
||||
// Send a MEET_OTHER event
|
||||
MapEditEvent event;
|
||||
event.type = MEET_OTHER;
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
i = modified_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
event.modified_blocks.insert(p, true);
|
||||
}
|
||||
map->dispatchEvent(&event);
|
||||
}
|
||||
};
|
||||
|
||||
void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
|
||||
{
|
||||
env->addActiveBlockModifier(new GrowGrassABM());
|
||||
env->addActiveBlockModifier(new RemoveGrassABM());
|
||||
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -110,7 +110,6 @@ struct HeightPoint
|
|||
float gh; // ground height
|
||||
float ma; // mud amount
|
||||
float have_sand;
|
||||
float tree_amount;
|
||||
};
|
||||
core::map<v2s16, HeightPoint> g_heights;
|
||||
|
||||
|
@ -126,10 +125,6 @@ HeightPoint ground_height(u64 seed, v2s16 p2d)
|
|||
/*hp.gh = BS*base_rock_level_2d(seed, p2d);
|
||||
hp.ma = BS*get_mud_add_amount(seed, p2d);*/
|
||||
hp.have_sand = mapgen::get_have_beach(seed, p2d);
|
||||
if(hp.gh > BS*WATER_LEVEL)
|
||||
hp.tree_amount = mapgen::tree_amount_2d(seed, p2d);
|
||||
else
|
||||
hp.tree_amount = 0;
|
||||
// No mud has been added if mud amount is less than 1
|
||||
if(hp.ma < 1.0*BS)
|
||||
hp.ma = 0.0;
|
||||
|
@ -244,7 +239,6 @@ void FarMesh::render()
|
|||
float ma_avg = 0;
|
||||
float h_avg = 0;
|
||||
u32 have_sand_count = 0;
|
||||
float tree_amount_avg = 0;
|
||||
for(u32 i=0; i<5; i++)
|
||||
{
|
||||
noise[i] = hps[i].gh + hps[i].ma;
|
||||
|
@ -256,11 +250,9 @@ void FarMesh::render()
|
|||
h_avg += noise[i];
|
||||
if(hps[i].have_sand)
|
||||
have_sand_count++;
|
||||
tree_amount_avg += hps[i].tree_amount;
|
||||
}
|
||||
ma_avg /= 5.0;
|
||||
h_avg /= 5.0;
|
||||
tree_amount_avg /= 5.0;
|
||||
|
||||
float steepness = (h_max - h_min)/grid_size;
|
||||
|
||||
|
@ -315,11 +307,6 @@ void FarMesh::render()
|
|||
}
|
||||
else
|
||||
{
|
||||
/*// Trees if there are over 0.01 trees per MapNode
|
||||
if(tree_amount_avg > 0.01)
|
||||
c = video::SColor(255,50,128,50);
|
||||
else
|
||||
c = video::SColor(255,107,134,51);*/
|
||||
c = video::SColor(255,107,134,51);
|
||||
ground_is_mud = true;
|
||||
}
|
||||
|
@ -351,51 +338,6 @@ void FarMesh::render()
|
|||
u16 indices[] = {0,1,2,2,3,0};
|
||||
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
|
||||
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
|
||||
|
||||
// Add some trees if appropriate
|
||||
if(tree_amount_avg >= 0.0065 && steepness < 1.4
|
||||
&& ground_is_mud == true)
|
||||
{
|
||||
driver->setMaterial(m_materials[1]);
|
||||
|
||||
float b = m_brightness;
|
||||
c = video::SColor(255, b*255, b*255, b*255);
|
||||
|
||||
{
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(p0.X,noise[0],p0.Y,
|
||||
0,0,0, c, 0,1),
|
||||
video::S3DVertex(p0.X,noise[0]+BS*MAP_BLOCKSIZE,p0.Y,
|
||||
0,0,0, c, 0,0),
|
||||
video::S3DVertex(p1.X,noise[2]+BS*MAP_BLOCKSIZE,p1.Y,
|
||||
0,0,0, c, 1,0),
|
||||
video::S3DVertex(p1.X,noise[2],p1.Y,
|
||||
0,0,0, c, 1,1),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
|
||||
video::EVT_STANDARD, scene::EPT_TRIANGLES,
|
||||
video::EIT_16BIT);
|
||||
}
|
||||
{
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
video::S3DVertex(p1.X,noise[3],p0.Y,
|
||||
0,0,0, c, 0,1),
|
||||
video::S3DVertex(p1.X,noise[3]+BS*MAP_BLOCKSIZE,p0.Y,
|
||||
0,0,0, c, 0,0),
|
||||
video::S3DVertex(p0.X,noise[1]+BS*MAP_BLOCKSIZE,p1.Y,
|
||||
0,0,0, c, 1,0),
|
||||
video::S3DVertex(p0.X,noise[1],p1.Y,
|
||||
0,0,0, c, 1,1),
|
||||
};
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
|
||||
video::EVT_STANDARD, scene::EPT_TRIANGLES,
|
||||
video::EIT_16BIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//driver->clearZBuffer();
|
||||
|
|
155
src/mapgen.cpp
155
src/mapgen.cpp
|
@ -120,86 +120,6 @@ static s16 find_stone_level(VoxelManipulator &vmanip, v2s16 p2d,
|
|||
}
|
||||
#endif
|
||||
|
||||
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
|
||||
bool is_apple_tree, INodeDefManager *ndef)
|
||||
{
|
||||
MapNode treenode(ndef->getId("mapgen_tree"));
|
||||
MapNode leavesnode(ndef->getId("mapgen_leaves"));
|
||||
MapNode applenode(ndef->getId("mapgen_apple"));
|
||||
|
||||
s16 trunk_h = myrand_range(4, 5);
|
||||
v3s16 p1 = p0;
|
||||
for(s16 ii=0; ii<trunk_h; ii++)
|
||||
{
|
||||
if(vmanip.m_area.contains(p1))
|
||||
vmanip.m_data[vmanip.m_area.index(p1)] = treenode;
|
||||
p1.Y++;
|
||||
}
|
||||
|
||||
// p1 is now the last piece of the trunk
|
||||
p1.Y -= 1;
|
||||
|
||||
VoxelArea leaves_a(v3s16(-2,-1,-2), v3s16(2,2,2));
|
||||
//SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]);
|
||||
Buffer<u8> leaves_d(leaves_a.getVolume());
|
||||
for(s32 i=0; i<leaves_a.getVolume(); i++)
|
||||
leaves_d[i] = 0;
|
||||
|
||||
// Force leaves at near the end of the trunk
|
||||
{
|
||||
s16 d = 1;
|
||||
for(s16 z=-d; z<=d; z++)
|
||||
for(s16 y=-d; y<=d; y++)
|
||||
for(s16 x=-d; x<=d; x++)
|
||||
{
|
||||
leaves_d[leaves_a.index(v3s16(x,y,z))] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add leaves randomly
|
||||
for(u32 iii=0; iii<7; iii++)
|
||||
{
|
||||
s16 d = 1;
|
||||
|
||||
v3s16 p(
|
||||
myrand_range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X-d),
|
||||
myrand_range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y-d),
|
||||
myrand_range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z-d)
|
||||
);
|
||||
|
||||
for(s16 z=0; z<=d; z++)
|
||||
for(s16 y=0; y<=d; y++)
|
||||
for(s16 x=0; x<=d; x++)
|
||||
{
|
||||
leaves_d[leaves_a.index(p+v3s16(x,y,z))] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Blit leaves to vmanip
|
||||
for(s16 z=leaves_a.MinEdge.Z; z<=leaves_a.MaxEdge.Z; z++)
|
||||
for(s16 y=leaves_a.MinEdge.Y; y<=leaves_a.MaxEdge.Y; y++)
|
||||
for(s16 x=leaves_a.MinEdge.X; x<=leaves_a.MaxEdge.X; x++)
|
||||
{
|
||||
v3s16 p(x,y,z);
|
||||
p += p1;
|
||||
if(vmanip.m_area.contains(p) == false)
|
||||
continue;
|
||||
u32 vi = vmanip.m_area.index(p);
|
||||
if(vmanip.m_data[vi].getContent() != CONTENT_AIR
|
||||
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
|
||||
continue;
|
||||
u32 i = leaves_a.index(x,y,z);
|
||||
if(leaves_d[i] == 1) {
|
||||
bool is_apple = myrand_range(0,99) < 10;
|
||||
if(is_apple_tree && is_apple) {
|
||||
vmanip.m_data[vi] = applenode;
|
||||
} else {
|
||||
vmanip.m_data[vi] = leavesnode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
|
||||
INodeDefManager *ndef)
|
||||
|
@ -1017,22 +937,6 @@ bool is_ground(u64 seed, v3s16 p)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Amount of trees per area in nodes
|
||||
double tree_amount_2d(u64 seed, v2s16 p)
|
||||
{
|
||||
/*double noise = noise2d_perlin(
|
||||
0.5+(float)p.X/250, 0.5+(float)p.Y/250,
|
||||
seed+2, 5, 0.66);*/
|
||||
double noise = noise2d_perlin(
|
||||
0.5+(float)p.X/125, 0.5+(float)p.Y/125,
|
||||
seed+2, 4, 0.66);
|
||||
double zeroval = -0.39;
|
||||
if(noise < zeroval)
|
||||
return 0;
|
||||
else
|
||||
return 0.04 * (noise-zeroval) / (1.0-zeroval);
|
||||
}
|
||||
|
||||
#if 0
|
||||
double surface_humidity_2d(u64 seed, v2s16 p)
|
||||
{
|
||||
|
@ -2184,65 +2088,6 @@ void make_block(BlockMakeData *data)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Generate some trees
|
||||
*/
|
||||
assert(central_area_size.X == central_area_size.Z);
|
||||
{
|
||||
// Divide area into parts
|
||||
s16 div = 8;
|
||||
s16 sidelen = central_area_size.X / div;
|
||||
double area = sidelen * sidelen;
|
||||
for(s16 x0=0; x0<div; x0++)
|
||||
for(s16 z0=0; z0<div; z0++)
|
||||
{
|
||||
// Center position of part of division
|
||||
v2s16 p2d_center(
|
||||
node_min.X + sidelen/2 + sidelen*x0,
|
||||
node_min.Z + sidelen/2 + sidelen*z0
|
||||
);
|
||||
// Minimum edge of part of division
|
||||
v2s16 p2d_min(
|
||||
node_min.X + sidelen*x0,
|
||||
node_min.Z + sidelen*z0
|
||||
);
|
||||
// Maximum edge of part of division
|
||||
v2s16 p2d_max(
|
||||
node_min.X + sidelen + sidelen*x0 - 1,
|
||||
node_min.Z + sidelen + sidelen*z0 - 1
|
||||
);
|
||||
// Amount of trees
|
||||
u32 tree_count = area * tree_amount_2d(data->seed, p2d_center);
|
||||
// Put trees in random places on part of division
|
||||
for(u32 i=0; i<tree_count; i++)
|
||||
{
|
||||
s16 x = myrand_range(p2d_min.X, p2d_max.X);
|
||||
s16 z = myrand_range(p2d_min.Y, p2d_max.Y);
|
||||
s16 y = find_ground_level(vmanip, v2s16(x,z), ndef);
|
||||
// Don't make a tree under water level
|
||||
if(y < WATER_LEVEL)
|
||||
continue;
|
||||
// Don't make a tree so high that it doesn't fit
|
||||
if(y > node_max.Y - 6)
|
||||
continue;
|
||||
v3s16 p(x,y,z);
|
||||
/*
|
||||
Trees grow only on mud and grass
|
||||
*/
|
||||
{
|
||||
u32 i = vmanip.m_area.index(v3s16(p));
|
||||
MapNode *n = &vmanip.m_data[i];
|
||||
if(n->getContent() != c_dirt
|
||||
&& n->getContent() != c_dirt_with_grass)
|
||||
continue;
|
||||
}
|
||||
p.Y++;
|
||||
// Make a tree
|
||||
make_tree(vmanip, p, false, ndef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
Make base ground level
|
||||
|
|
Loading…
Reference in New Issue
Block a user