]> git.lizzy.rs Git - minetest.git/blob - src/content_abm.cpp
03fc82ed4d8396f4710b84c1c6e489e9f90eb65f
[minetest.git] / src / content_abm.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 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 "main.h" // for g_settings
30 #include "map.h"
31
32 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
33
34 class GrowGrassABM : public ActiveBlockModifier
35 {
36 private:
37 public:
38         virtual std::set<std::string> getTriggerContents()
39         {
40                 std::set<std::string> s;
41                 s.insert("mapgen_dirt");
42                 return s;
43         }
44         virtual float getTriggerInterval()
45         { return 2.0; }
46         virtual u32 getTriggerChance()
47         { return 200; }
48         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
49         {
50                 INodeDefManager *ndef = env->getGameDef()->ndef();
51                 ServerMap *map = &env->getServerMap();
52                 
53                 MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
54                 if(ndef->get(n_top).light_propagates &&
55                                 !ndef->get(n_top).isLiquid() &&
56                                 n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13)
57                 {
58                         n.setContent(ndef->getId("mapgen_dirt_with_grass"));
59                         map->addNodeWithEvent(p, n);
60                 }
61         }
62 };
63
64 class RemoveGrassABM : public ActiveBlockModifier
65 {
66 private:
67 public:
68         virtual std::set<std::string> getTriggerContents()
69         {
70                 std::set<std::string> s;
71                 s.insert("mapgen_dirt_with_grass");
72                 return s;
73         }
74         virtual float getTriggerInterval()
75         { return 2.0; }
76         virtual u32 getTriggerChance()
77         { return 20; }
78         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
79         {
80                 INodeDefManager *ndef = env->getGameDef()->ndef();
81                 ServerMap *map = &env->getServerMap();
82                 
83                 MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
84                 if((!ndef->get(n_top).light_propagates &&
85                                 n_top.getContent() != CONTENT_IGNORE) ||
86                                 ndef->get(n_top).isLiquid())
87                 {
88                         n.setContent(ndef->getId("mapgen_dirt"));
89                         map->addNodeWithEvent(p, n);
90                 }
91         }
92 };
93
94 class MakeTreesFromSaplingsABM : public ActiveBlockModifier
95 {
96 private:
97 public:
98         virtual std::set<std::string> getTriggerContents()
99         {
100                 std::set<std::string> s;
101                 s.insert("sapling");
102                 return s;
103         }
104         virtual float getTriggerInterval()
105         { return 10.0; }
106         virtual u32 getTriggerChance()
107         { return 50; }
108         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
109                         u32 active_object_count, u32 active_object_count_wider)
110         {
111                 INodeDefManager *ndef = env->getGameDef()->ndef();
112                 ServerMap *map = &env->getServerMap();
113                 
114                 actionstream<<"A sapling grows into a tree at "
115                                 <<PP(p)<<std::endl;
116
117                 core::map<v3s16, MapBlock*> modified_blocks;
118                 v3s16 tree_p = p;
119                 ManualMapVoxelManipulator vmanip(map);
120                 v3s16 tree_blockp = getNodeBlockPos(tree_p);
121                 vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
122                 bool is_apple_tree = myrand()%4 == 0;
123                 treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef, myrand());
124                 vmanip.blitBackAll(&modified_blocks);
125
126                 // update lighting
127                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
128                 for(core::map<v3s16, MapBlock*>::Iterator
129                         i = modified_blocks.getIterator();
130                         i.atEnd() == false; i++)
131                 {
132                         lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue());
133                 }
134                 map->updateLighting(lighting_modified_blocks, modified_blocks);
135
136                 // Send a MEET_OTHER event
137                 MapEditEvent event;
138                 event.type = MEET_OTHER;
139                 for(core::map<v3s16, MapBlock*>::Iterator
140                         i = modified_blocks.getIterator();
141                         i.atEnd() == false; i++)
142                 {
143                         v3s16 p = i.getNode()->getKey();
144                         event.modified_blocks.insert(p, true);
145                 }
146                 map->dispatchEvent(&event);
147         }
148 };
149
150 class LiquidFlowABM : public ActiveBlockModifier
151 {
152 private:
153         std::set<std::string> contents;
154
155 public:
156         LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) 
157         {
158                 std::set<content_t> liquids;
159                 nodemgr->getIds("group:liquid", liquids);
160                 for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
161                         contents.insert(nodemgr->get(*k).liquid_alternative_flowing);
162                 
163         }
164         virtual std::set<std::string> getTriggerContents()
165         {
166                 return contents;
167         }
168         virtual float getTriggerInterval()
169         { return 10.0; }
170         virtual u32 getTriggerChance()
171         { return 10; }
172         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
173         {
174                 ServerMap *map = &env->getServerMap();
175                 if (map->transforming_liquid_size() < 500)
176                         map->transforming_liquid_add(p);
177                 //if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p);
178         }
179 };
180
181 void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
182 {
183         env->addActiveBlockModifier(new GrowGrassABM());
184         env->addActiveBlockModifier(new RemoveGrassABM());
185         env->addActiveBlockModifier(new MakeTreesFromSaplingsABM());
186         if (g_settings->getBool("liquid_finite"))
187                 env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
188 }