Skip to content

Commit 69a59f1

Browse files
committedNov 2, 2013
Move the sapling growing and grass adding/removing ABMs to Lua
1 parent b1c82f3 commit 69a59f1

File tree

4 files changed

+134
-139
lines changed

4 files changed

+134
-139
lines changed
 

‎builtin/features.lua

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ minetest.features = {
66
chat_send_player_param3 = true,
77
get_all_craft_recipes_works = true,
88
use_texture_alpha = true,
9+
no_legacy_abms = true,
910
}
1011

1112
function minetest.has_feature(arg)

‎games/minimal/mods/default/init.lua

+123
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,129 @@ minetest.register_node("default:apple", {
15191519
sounds = default.node_sound_defaults(),
15201520
})
15211521

1522+
1523+
local c_air = minetest.get_content_id("air")
1524+
local c_ignore = minetest.get_content_id("ignore")
1525+
local c_tree = minetest.get_content_id("default:tree")
1526+
local c_leaves = minetest.get_content_id("default:leaves")
1527+
local c_apple = minetest.get_content_id("default:apple")
1528+
function default.grow_tree(data, a, pos, is_apple_tree, seed)
1529+
--[[
1530+
NOTE: Tree-placing code is currently duplicated in the engine
1531+
and in games that have saplings; both are deprecated but not
1532+
replaced yet
1533+
]]--
1534+
local pr = PseudoRandom(seed)
1535+
local th = pr:next(4, 5)
1536+
local x, y, z = pos.x, pos.y, pos.z
1537+
for yy = y, y+th-1 do
1538+
local vi = a:index(x, yy, z)
1539+
if a:contains(x, yy, z) and (data[vi] == c_air or yy == y) then
1540+
data[vi] = c_tree
1541+
end
1542+
end
1543+
y = y+th-1 -- (x, y, z) is now last piece of trunk
1544+
local leaves_a = VoxelArea:new{MinEdge={x=-2, y=-1, z=-2}, MaxEdge={x=2, y=2, z=2}}
1545+
local leaves_buffer = {}
1546+
1547+
-- Force leaves near the trunk
1548+
local d = 1
1549+
for xi = -d, d do
1550+
for yi = -d, d do
1551+
for zi = -d, d do
1552+
leaves_buffer[leaves_a:index(xi, yi, zi)] = true
1553+
end
1554+
end
1555+
end
1556+
1557+
-- Add leaves randomly
1558+
for iii = 1, 8 do
1559+
local d = 1
1560+
local xx = pr:next(leaves_a.MinEdge.x, leaves_a.MaxEdge.x - d)
1561+
local yy = pr:next(leaves_a.MinEdge.y, leaves_a.MaxEdge.y - d)
1562+
local zz = pr:next(leaves_a.MinEdge.z, leaves_a.MaxEdge.z - d)
1563+
1564+
for xi = 0, d do
1565+
for yi = 0, d do
1566+
for zi = 0, d do
1567+
leaves_buffer[leaves_a:index(xx+xi, yy+yi, zz+zi)] = true
1568+
end
1569+
end
1570+
end
1571+
end
1572+
1573+
-- Add the leaves
1574+
for xi = leaves_a.MinEdge.x, leaves_a.MaxEdge.x do
1575+
for yi = leaves_a.MinEdge.y, leaves_a.MaxEdge.y do
1576+
for zi = leaves_a.MinEdge.z, leaves_a.MaxEdge.z do
1577+
if a:contains(x+xi, y+yi, z+zi) then
1578+
local vi = a:index(x+xi, y+yi, z+zi)
1579+
if data[vi] == c_air or data[vi] == c_ignore then
1580+
if leaves_buffer[leaves_a:index(xi, yi, zi)] then
1581+
if is_apple_tree and pr:next(1, 100) <= 10 then
1582+
data[vi] = c_apple
1583+
else
1584+
data[vi] = c_leaves
1585+
end
1586+
end
1587+
end
1588+
end
1589+
end
1590+
end
1591+
end
1592+
end
1593+
1594+
minetest.register_abm({
1595+
nodenames = {"default:sapling"},
1596+
interval = 10,
1597+
chance = 50,
1598+
action = function(pos, node)
1599+
local is_soil = minetest.registered_nodes[minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name].groups.soil
1600+
if is_soil == nil or is_soil == 0 then return end
1601+
print("A sapling grows into a tree at "..minetest.pos_to_string(pos))
1602+
local vm = minetest.get_voxel_manip()
1603+
local minp, maxp = vm:read_from_map({x=pos.x-16, y=pos.y, z=pos.z-16}, {x=pos.x+16, y=pos.y+16, z=pos.z+16})
1604+
local a = VoxelArea:new{MinEdge=minp, MaxEdge=maxp}
1605+
local data = vm:get_data()
1606+
default.grow_tree(data, a, pos, math.random(1, 4) == 1, math.random(1,100000))
1607+
vm:set_data(data)
1608+
vm:write_to_map(data)
1609+
vm:update_map()
1610+
end
1611+
})
1612+
1613+
minetest.register_abm({
1614+
nodenames = {"default:dirt"},
1615+
interval = 2,
1616+
chance = 200,
1617+
action = function(pos, node)
1618+
local above = {x=pos.x, y=pos.y+1, z=pos.z}
1619+
local name = minetest.get_node(above).name
1620+
local nodedef = minetest.registered_nodes[name]
1621+
if nodedef and nodedef.sunlight_propagates and nodedef.liquidtype == "none" and minetest.get_node_light(above) >= 13 then
1622+
if name == "default:snow" or name == "default:snowblock" then
1623+
minetest.set_node(pos, {name = "default:dirt_with_snow"})
1624+
else
1625+
minetest.set_node(pos, {name = "default:dirt_with_grass"})
1626+
end
1627+
end
1628+
end
1629+
})
1630+
1631+
minetest.register_abm({
1632+
nodenames = {"default:dirt_with_grass"},
1633+
interval = 2,
1634+
chance = 20,
1635+
action = function(pos, node)
1636+
local above = {x=pos.x, y=pos.y+1, z=pos.z}
1637+
local name = minetest.get_node(above).name
1638+
local nodedef = minetest.registered_nodes[name]
1639+
if name ~= "ignore" and nodedef and not (nodedef.sunlight_propagates and nodedef.liquidtype == "none") then
1640+
minetest.set_node(pos, {name = "default:dirt"})
1641+
end
1642+
end
1643+
})
1644+
15221645
--
15231646
-- Crafting items
15241647
--

‎src/content_abm.cpp

-139
Original file line numberDiff line numberDiff line change
@@ -25,149 +25,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2525
#include "content_sao.h"
2626
#include "settings.h"
2727
#include "mapblock.h" // For getNodeBlockPos
28-
#include "treegen.h" // For treegen::make_tree
2928
#include "main.h" // for g_settings
3029
#include "map.h"
3130
#include "scripting_game.h"
3231
#include "log.h"
3332

3433
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
3534

36-
class GrowGrassABM : public ActiveBlockModifier
37-
{
38-
private:
39-
public:
40-
virtual std::set<std::string> getTriggerContents()
41-
{
42-
std::set<std::string> s;
43-
s.insert("mapgen_dirt");
44-
return s;
45-
}
46-
virtual float getTriggerInterval()
47-
{ return 2.0; }
48-
virtual u32 getTriggerChance()
49-
{ return 200; }
50-
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
51-
{
52-
INodeDefManager *ndef = env->getGameDef()->ndef();
53-
ServerMap *map = &env->getServerMap();
54-
55-
MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
56-
content_t c_snow = ndef->getId("snow");
57-
if(ndef->get(n_top).light_propagates &&
58-
!ndef->get(n_top).isLiquid() &&
59-
n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13)
60-
{
61-
if(c_snow != CONTENT_IGNORE && n_top.getContent() == c_snow)
62-
n.setContent(ndef->getId("dirt_with_snow"));
63-
else
64-
n.setContent(ndef->getId("mapgen_dirt_with_grass"));
65-
map->addNodeWithEvent(p, n);
66-
}
67-
}
68-
};
69-
70-
class RemoveGrassABM : public ActiveBlockModifier
71-
{
72-
private:
73-
public:
74-
virtual std::set<std::string> getTriggerContents()
75-
{
76-
std::set<std::string> s;
77-
s.insert("mapgen_dirt_with_grass");
78-
return s;
79-
}
80-
virtual float getTriggerInterval()
81-
{ return 2.0; }
82-
virtual u32 getTriggerChance()
83-
{ return 20; }
84-
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
85-
{
86-
INodeDefManager *ndef = env->getGameDef()->ndef();
87-
ServerMap *map = &env->getServerMap();
88-
89-
MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
90-
if((!ndef->get(n_top).light_propagates &&
91-
n_top.getContent() != CONTENT_IGNORE) ||
92-
ndef->get(n_top).isLiquid())
93-
{
94-
n.setContent(ndef->getId("mapgen_dirt"));
95-
map->addNodeWithEvent(p, n);
96-
}
97-
}
98-
};
99-
100-
class MakeTreesFromSaplingsABM : public ActiveBlockModifier
101-
{
102-
private:
103-
content_t c_junglesapling;
104-
105-
public:
106-
MakeTreesFromSaplingsABM(ServerEnvironment *env, INodeDefManager *nodemgr) {
107-
c_junglesapling = nodemgr->getId("junglesapling");
108-
}
109-
110-
virtual std::set<std::string> getTriggerContents()
111-
{
112-
std::set<std::string> s;
113-
s.insert("sapling");
114-
s.insert("junglesapling");
115-
return s;
116-
}
117-
virtual float getTriggerInterval()
118-
{ return 10.0; }
119-
virtual u32 getTriggerChance()
120-
{ return 50; }
121-
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
122-
u32 active_object_count, u32 active_object_count_wider)
123-
{
124-
INodeDefManager *ndef = env->getGameDef()->ndef();
125-
ServerMap *map = &env->getServerMap();
126-
127-
MapNode n_below = map->getNodeNoEx(p - v3s16(0, 1, 0));
128-
if (!((ItemGroupList) ndef->get(n_below).groups)["soil"])
129-
return;
130-
131-
bool is_jungle_tree = n.getContent() == c_junglesapling;
132-
133-
actionstream <<"A " << (is_jungle_tree ? "jungle " : "")
134-
<< "sapling grows into a tree at "
135-
<< PP(p) << std::endl;
136-
137-
std::map<v3s16, MapBlock*> modified_blocks;
138-
v3s16 tree_p = p;
139-
ManualMapVoxelManipulator vmanip(map);
140-
v3s16 tree_blockp = getNodeBlockPos(tree_p);
141-
vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
142-
143-
if (is_jungle_tree) {
144-
treegen::make_jungletree(vmanip, tree_p, ndef, myrand());
145-
} else {
146-
bool is_apple_tree = myrand() % 4 == 0;
147-
treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef, myrand());
148-
}
149-
150-
vmanip.blitBackAll(&modified_blocks);
151-
152-
// update lighting
153-
std::map<v3s16, MapBlock*> lighting_modified_blocks;
154-
lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
155-
map->updateLighting(lighting_modified_blocks, modified_blocks);
156-
157-
// Send a MEET_OTHER event
158-
MapEditEvent event;
159-
event.type = MEET_OTHER;
160-
// event.modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
161-
for(std::map<v3s16, MapBlock*>::iterator
162-
i = modified_blocks.begin();
163-
i != modified_blocks.end(); ++i)
164-
{
165-
event.modified_blocks.insert(i->first);
166-
}
167-
map->dispatchEvent(&event);
168-
}
169-
};
170-
17135
class LiquidFlowABM : public ActiveBlockModifier {
17236
private:
17337
std::set<std::string> contents;
@@ -370,9 +234,6 @@ class LiquidMeltAround : public LiquidMeltHot {
370234
*/
371235

372236
void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) {
373-
env->addActiveBlockModifier(new GrowGrassABM());
374-
env->addActiveBlockModifier(new RemoveGrassABM());
375-
env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef));
376237
if (g_settings->getBool("liquid_finite")) {
377238
env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
378239
env->addActiveBlockModifier(new LiquidDropABM(env, nodedef));

‎src/treegen.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ namespace treegen
3333
void make_tree(ManualMapVoxelManipulator &vmanip, v3s16 p0,
3434
bool is_apple_tree, INodeDefManager *ndef, int seed)
3535
{
36+
/*
37+
NOTE: Tree-placing code is currently duplicated in the engine
38+
and in games that have saplings; both are deprecated but not
39+
replaced yet
40+
*/
3641
MapNode treenode(ndef->getId("mapgen_tree"));
3742
MapNode leavesnode(ndef->getId("mapgen_leaves"));
3843
MapNode applenode(ndef->getId("mapgen_apple"));
@@ -511,6 +516,11 @@ v3f transposeMatrix(irr::core::matrix4 M, v3f v)
511516
void make_jungletree(VoxelManipulator &vmanip, v3s16 p0,
512517
INodeDefManager *ndef, int seed)
513518
{
519+
/*
520+
NOTE: Tree-placing code is currently duplicated in the engine
521+
and in games that have saplings; both are deprecated but not
522+
replaced yet
523+
*/
514524
content_t c_tree = ndef->getId("mapgen_jungletree");
515525
content_t c_leaves = ndef->getId("mapgen_jungleleaves");
516526
if (c_tree == CONTENT_IGNORE)

0 commit comments

Comments
 (0)
Please sign in to comment.