]> git.lizzy.rs Git - minetest.git/blob - src/content_abm.cpp
Fix lava damage on player's upper body
[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                 content_t c_snow = ndef->getId("snow");
55                 if(ndef->get(n_top).light_propagates &&
56                                 !ndef->get(n_top).isLiquid() &&
57                                 n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13)
58                 {
59                         if(c_snow != CONTENT_IGNORE && n_top.getContent() == c_snow)
60                                 n.setContent(ndef->getId("dirt_with_snow"));
61                         else
62                                 n.setContent(ndef->getId("mapgen_dirt_with_grass"));
63                         map->addNodeWithEvent(p, n);
64                 }
65         }
66 };
67
68 class RemoveGrassABM : public ActiveBlockModifier
69 {
70 private:
71 public:
72         virtual std::set<std::string> getTriggerContents()
73         {
74                 std::set<std::string> s;
75                 s.insert("mapgen_dirt_with_grass");
76                 return s;
77         }
78         virtual float getTriggerInterval()
79         { return 2.0; }
80         virtual u32 getTriggerChance()
81         { return 20; }
82         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
83         {
84                 INodeDefManager *ndef = env->getGameDef()->ndef();
85                 ServerMap *map = &env->getServerMap();
86                 
87                 MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0));
88                 if((!ndef->get(n_top).light_propagates &&
89                                 n_top.getContent() != CONTENT_IGNORE) ||
90                                 ndef->get(n_top).isLiquid())
91                 {
92                         n.setContent(ndef->getId("mapgen_dirt"));
93                         map->addNodeWithEvent(p, n);
94                 }
95         }
96 };
97
98 class MakeTreesFromSaplingsABM : public ActiveBlockModifier
99 {
100 private:
101         content_t c_junglesapling;
102         content_t c_dirt;
103         content_t c_dirt_with_grass;
104         
105 public:
106         MakeTreesFromSaplingsABM(ServerEnvironment *env, INodeDefManager *nodemgr) {
107                 c_junglesapling   = nodemgr->getId("junglesapling");
108                 c_dirt            = nodemgr->getId("mapgen_dirt");
109                 c_dirt_with_grass = nodemgr->getId("mapgen_dirt_with_grass");
110         }
111
112         virtual std::set<std::string> getTriggerContents()
113         {
114                 std::set<std::string> s;
115                 s.insert("sapling");
116                 s.insert("junglesapling");
117                 return s;
118         }
119         virtual float getTriggerInterval()
120         { return 10.0; }
121         virtual u32 getTriggerChance()
122         { return 50; }
123         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
124                         u32 active_object_count, u32 active_object_count_wider)
125         {
126                 INodeDefManager *ndef = env->getGameDef()->ndef();
127                 ServerMap *map = &env->getServerMap();
128                 
129                 MapNode n_below = map->getNodeNoEx(p - v3s16(0, 1, 0));
130                 if (n_below.getContent() != c_dirt &&
131                         n_below.getContent() != c_dirt_with_grass)
132                         return;
133                         
134                 bool is_jungle_tree = n.getContent() == c_junglesapling;
135                 
136                 actionstream <<"A " << (is_jungle_tree ? "jungle " : "")
137                                 << "sapling grows into a tree at "
138                                 << PP(p) << std::endl;
139
140                 std::map<v3s16, MapBlock*> modified_blocks;
141                 v3s16 tree_p = p;
142                 ManualMapVoxelManipulator vmanip(map);
143                 v3s16 tree_blockp = getNodeBlockPos(tree_p);
144                 vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1));
145                 
146                 if (is_jungle_tree) {
147                         treegen::make_jungletree(vmanip, tree_p, ndef, myrand());
148                 } else {
149                         bool is_apple_tree = myrand() % 4 == 0;
150                         treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef, myrand());
151                 }
152                 
153                 vmanip.blitBackAll(&modified_blocks);
154
155                 // update lighting
156                 std::map<v3s16, MapBlock*> lighting_modified_blocks;
157                 lighting_modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
158                 map->updateLighting(lighting_modified_blocks, modified_blocks);
159
160                 // Send a MEET_OTHER event
161                 MapEditEvent event;
162                 event.type = MEET_OTHER;
163 //              event.modified_blocks.insert(modified_blocks.begin(), modified_blocks.end());
164                 for(std::map<v3s16, MapBlock*>::iterator
165                         i = modified_blocks.begin();
166                         i != modified_blocks.end(); ++i)
167                 {
168                         event.modified_blocks.insert(i->first);
169                 }
170                 map->dispatchEvent(&event);
171         }
172 };
173
174 class LiquidFlowABM : public ActiveBlockModifier
175 {
176 private:
177         std::set<std::string> contents;
178
179 public:
180         LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) 
181         {
182                 std::set<content_t> liquids;
183                 nodemgr->getIds("group:liquid", liquids);
184                 for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++)
185                         contents.insert(nodemgr->get(*k).liquid_alternative_flowing);
186                 
187         }
188         virtual std::set<std::string> getTriggerContents()
189         {
190                 return contents;
191         }
192         virtual float getTriggerInterval()
193         { return 10.0; }
194         virtual u32 getTriggerChance()
195         { return 10; }
196         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n)
197         {
198                 ServerMap *map = &env->getServerMap();
199                 if (map->transforming_liquid_size() < 500)
200                         map->transforming_liquid_add(p);
201                 //if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p);
202         }
203 };
204
205 void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef)
206 {
207         env->addActiveBlockModifier(new GrowGrassABM());
208         env->addActiveBlockModifier(new RemoveGrassABM());
209         env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef));
210         if (g_settings->getBool("liquid_finite"))
211                 env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef));
212 }