Merge pull request #431 from sapier/dtime_clamping
[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("mapgen_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                                 n_top.getContent() != CONTENT_IGNORE) ||
85                                 ndef->get(n_top).isLiquid())
86                 {
87                         n.setContent(ndef->getId("mapgen_dirt"));
88                         map->addNodeWithEvent(p, n);
89                 }
90         }
91 };
92
93 class MakeTreesFromSaplingsABM : public ActiveBlockModifier
94 {
95 private:
96 public:
97         virtual std::set<std::string> getTriggerContents()
98         {
99                 std::set<std::string> s;
100                 s.insert("sapling");
101                 return s;
102         }
103         virtual float getTriggerInterval()
104         { return 10.0; }
105         virtual u32 getTriggerChance()
106         { return 50; }
107         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
108                         u32 active_object_count, u32 active_object_count_wider)
109         {
110                 INodeDefManager *ndef = env->getGameDef()->ndef();
111                 ServerMap *map = &env->getServerMap();
112                 
113                 actionstream<<"A sapling grows into a tree at "
114                                 <<PP(p)<<std::endl;
115
116                 core::map<v3s16, MapBlock*> modified_blocks;
117                 v3s16 tree_p = p;
118                 ManualMapVoxelManipulator vmanip(map);
119                 v3s16 tree_blockp = getNodeBlockPos(tree_p);
120                 vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
121                 bool is_apple_tree = myrand()%4 == 0;
122                 treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef);
123                 vmanip.blitBackAll(&modified_blocks);
124
125                 // update lighting
126                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
127                 for(core::map<v3s16, MapBlock*>::Iterator
128                         i = modified_blocks.getIterator();
129                         i.atEnd() == false; i++)
130                 {
131                         lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue());
132                 }
133                 map->updateLighting(lighting_modified_blocks, modified_blocks);
134
135                 // Send a MEET_OTHER event
136                 MapEditEvent event;
137                 event.type = MEET_OTHER;
138                 for(core::map<v3s16, MapBlock*>::Iterator
139                         i = modified_blocks.getIterator();
140                         i.atEnd() == false; i++)
141                 {
142                         v3s16 p = i.getNode()->getKey();
143                         event.modified_blocks.insert(p, true);
144                 }
145                 map->dispatchEvent(&event);
146         }
147 };
148
149 void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
150 {
151         env->addActiveBlockModifier(new GrowGrassABM());
152         env->addActiveBlockModifier(new RemoveGrassABM());
153         env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
154 }
155
156