5812c7b502b0f9d063a63b9f4039e9415f3f4d7c
[oweals/minetest.git] / src / content_abm.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "content_abm.h"
21
22 #include "environment.h"
23 #include "gamedef.h"
24 #include "nodedef.h"
25 #include "content_sao.h"
26 #include "settings.h"
27 #include "mapblock.h" // For getNodeBlockPos
28 #include "treegen.h" // For treegen::make_tree
29 #include "map.h"
30
31 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
32
33 class GrowGrassABM : public ActiveBlockModifier
34 {
35 private:
36 public:
37         virtual std::set<std::string> getTriggerContents()
38         {
39                 std::set<std::string> s;
40                 s.insert("mapgen_dirt");
41                 return s;
42         }
43         virtual float getTriggerInterval()
44         { return 2.0; }
45         virtual u32 getTriggerChance()
46         { return 200; }
47         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
48         {
49                 INodeDefManager *ndef = env->getGameDef()->ndef();
50                 ServerMap *map = &env->getServerMap();
51                 
52                 MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
53                 if(ndef->get(n_top).light_propagates &&
54                                 !ndef->get(n_top).isLiquid() &&
55                                 n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13)
56                 {
57                         n.setContent(ndef->getId("dirt_with_grass"));
58                         map->addNodeWithEvent(p, n);
59                 }
60         }
61 };
62
63 class RemoveGrassABM : public ActiveBlockModifier
64 {
65 private:
66 public:
67         virtual std::set<std::string> getTriggerContents()
68         {
69                 std::set<std::string> s;
70                 s.insert("mapgen_dirt_with_grass");
71                 return s;
72         }
73         virtual float getTriggerInterval()
74         { return 2.0; }
75         virtual u32 getTriggerChance()
76         { return 20; }
77         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
78         {
79                 INodeDefManager *ndef = env->getGameDef()->ndef();
80                 ServerMap *map = &env->getServerMap();
81                 
82                 MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
83                 if(!ndef->get(n_top).light_propagates ||
84                                 ndef->get(n_top).isLiquid())
85                 {
86                         n.setContent(ndef->getId("dirt"));
87                         map->addNodeWithEvent(p, n);
88                 }
89         }
90 };
91
92 class MakeTreesFromSaplingsABM : public ActiveBlockModifier
93 {
94 private:
95 public:
96         virtual std::set<std::string> getTriggerContents()
97         {
98                 std::set<std::string> s;
99                 s.insert("sapling");
100                 return s;
101         }
102         virtual float getTriggerInterval()
103         { return 10.0; }
104         virtual u32 getTriggerChance()
105         { return 50; }
106         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
107                         u32 active_object_count, u32 active_object_count_wider)
108         {
109                 INodeDefManager *ndef = env->getGameDef()->ndef();
110                 ServerMap *map = &env->getServerMap();
111                 
112                 actionstream<<"A sapling grows into a tree at "
113                                 <<PP(p)<<std::endl;
114
115                 core::map<v3s16, MapBlock*> modified_blocks;
116                 v3s16 tree_p = p;
117                 ManualMapVoxelManipulator vmanip(map);
118                 v3s16 tree_blockp = getNodeBlockPos(tree_p);
119                 vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
120                 bool is_apple_tree = myrand()%4 == 0;
121                 treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef);
122                 vmanip.blitBackAll(&modified_blocks);
123
124                 // update lighting
125                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
126                 for(core::map<v3s16, MapBlock*>::Iterator
127                         i = modified_blocks.getIterator();
128                         i.atEnd() == false; i++)
129                 {
130                         lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue());
131                 }
132                 map->updateLighting(lighting_modified_blocks, modified_blocks);
133
134                 // Send a MEET_OTHER event
135                 MapEditEvent event;
136                 event.type = MEET_OTHER;
137                 for(core::map<v3s16, MapBlock*>::Iterator
138                         i = modified_blocks.getIterator();
139                         i.atEnd() == false; i++)
140                 {
141                         v3s16 p = i.getNode()->getKey();
142                         event.modified_blocks.insert(p, true);
143                 }
144                 map->dispatchEvent(&event);
145         }
146 };
147
148 void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
149 {
150         env->addActiveBlockModifier(new GrowGrassABM());
151         env->addActiveBlockModifier(new RemoveGrassABM());
152         env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
153 }
154
155