diff options
Diffstat (limited to 'src/content_abm.cpp')
-rw-r--r-- | src/content_abm.cpp | 274 |
1 files changed, 205 insertions, 69 deletions
diff --git a/src/content_abm.cpp b/src/content_abm.cpp index 6adcbf708..110ac1eea 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -28,6 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "treegen.h" // For treegen::make_tree #include "main.h" // for g_settings #include "map.h" +#include "cpp_api/scriptapi.h" +#include "log.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -166,86 +168,220 @@ public: } }; -class LiquidFlowABM : public ActiveBlockModifier -{ -private: - std::set<std::string> contents; +class LiquidFlowABM : public ActiveBlockModifier { + private: + std::set<std::string> contents; -public: - LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) - { - std::set<content_t> liquids; - nodemgr->getIds("group:liquid", liquids); - for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++) - contents.insert(nodemgr->get(*k).liquid_alternative_flowing); - - } - virtual std::set<std::string> getTriggerContents() - { - return contents; - } - virtual float getTriggerInterval() - { return 10.0; } - virtual u32 getTriggerChance() - { return 10; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) - { - ServerMap *map = &env->getServerMap(); - if (map->transforming_liquid_size() > 500) - return; - map->transforming_liquid_add(p); - //if ((*map).m_transforming_liquid.size() < 500) (*map).m_transforming_liquid.push_back(p); - } + public: + LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) { + std::set<content_t> liquids; + nodemgr->getIds("group:liquid", liquids); + for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++) + contents.insert(nodemgr->get(*k).liquid_alternative_flowing); + } + virtual std::set<std::string> getTriggerContents() { + return contents; + } + virtual float getTriggerInterval() + { return 10.0; } + virtual u32 getTriggerChance() + { return 10; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + if (map->transforming_liquid_size() > 500) + return; + map->transforming_liquid_add(p); + } }; -class LiquidDropABM : public ActiveBlockModifier -{ -private: - std::set<std::string> contents; +class LiquidDropABM : public ActiveBlockModifier { + private: + std::set<std::string> contents; -public: - LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr) - { - std::set<content_t> liquids; - nodemgr->getIds("group:liquid", liquids); - for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++) - contents.insert(nodemgr->get(*k).liquid_alternative_source); - } - virtual std::set<std::string> getTriggerContents() - { return contents; } - virtual std::set<std::string> getRequiredNeighbors() - { - std::set<std::string> neighbors; - neighbors.insert("mapgen_air"); - return neighbors; - } - virtual float getTriggerInterval() - { return 20.0; } - virtual u32 getTriggerChance() - { return 10; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) - { - ServerMap *map = &env->getServerMap(); - if (map->transforming_liquid_size() > 500) - return; - if ( map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent() != CONTENT_AIR // below - && map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent() != CONTENT_AIR // right - && map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent() != CONTENT_AIR // left - && map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent() != CONTENT_AIR // back - && map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent() != CONTENT_AIR // front - ) - return; - map->transforming_liquid_add(p); - } + public: + LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr) { + std::set<content_t> liquids; + nodemgr->getIds("group:liquid", liquids); + for(std::set<content_t>::const_iterator k = liquids.begin(); k != liquids.end(); k++) + contents.insert(nodemgr->get(*k).liquid_alternative_source); + } + virtual std::set<std::string> getTriggerContents() + { return contents; } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> neighbors; + neighbors.insert("mapgen_air"); + return neighbors; + } + virtual float getTriggerInterval() + { return 20.0; } + virtual u32 getTriggerChance() + { return 10; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + if (map->transforming_liquid_size() > 500) + return; + if ( map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent() != CONTENT_AIR // below + && map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent() != CONTENT_AIR // right + && map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent() != CONTENT_AIR // left + && map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent() != CONTENT_AIR // back + && map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent() != CONTENT_AIR // front + ) + return; + map->transforming_liquid_add(p); + } }; -void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) -{ +class LiquidFreeze : public ActiveBlockModifier { + public: + LiquidFreeze(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set<std::string> getTriggerContents() { + std::set<std::string> s; + s.insert("group:freezes"); + return s; + } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> s; + s.insert("mapgen_air"); + s.insert("group:melts"); + return s; + } + virtual float getTriggerInterval() + { return 10.0; } + virtual u32 getTriggerChance() + { return 20; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + INodeDefManager *ndef = env->getGameDef()->ndef(); + + float heat = map->getHeat(env, p); + //heater = rare + if (heat <= -1 && (heat <= -50 || ((myrand_range(-50, heat)) <= -30))) { + content_t c_self = n.getContent(); + // making freeze not annoying, do not freeze random blocks in center of ocean + // todo: any block not water (dont freeze _source near _flowing) + content_t c; + bool allow = heat < -40; + // todo: make for(...) + if (!allow) { + c = map->getNodeNoEx(p - v3s16(0, 1, 0 )).getContent(); // below + if (c == CONTENT_AIR || c == CONTENT_IGNORE) + return; // do not freeze when falling + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + if (!allow) { + c = map->getNodeNoEx(p - v3s16(1, 0, 0 )).getContent(); // right + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + if (!allow) { + c = map->getNodeNoEx(p - v3s16(-1, 0, 0 )).getContent(); // left + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + if (!allow) { + c = map->getNodeNoEx(p - v3s16(0, 0, 1 )).getContent(); // back + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + if (!allow) { + c = map->getNodeNoEx(p - v3s16(0, 0, -1)).getContent(); // front + if (c != c_self && c != CONTENT_IGNORE) allow = 1; + } + } + } + } + } + if (allow) { + n.setContent(ndef->getId(ndef->get(n).freezemelt)); + map->addNodeWithEvent(p, n); + } + } + } +}; + +class LiquidMeltWeather : public ActiveBlockModifier { + public: + LiquidMeltWeather(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set<std::string> getTriggerContents() { + std::set<std::string> s; + s.insert("group:melts"); + return s; + } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> s; + s.insert("mapgen_air"); + s.insert("group:freezes"); + return s; + } + virtual float getTriggerInterval() + { return 10.0; } + virtual u32 getTriggerChance() + { return 20; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + INodeDefManager *ndef = env->getGameDef()->ndef(); + + float heat = map->getHeat(env, p); + if (heat >= 1 && (heat >= 40 || ((myrand_range(heat, 40)) >= 20))) { + n.setContent(ndef->getId(ndef->get(n).freezemelt)); + if (!n.getLevel(ndef)) + n.addLevel(ndef); + map->addNodeWithEvent(p, n); + env->getScriptIface()->node_falling_update(p); + } + } +}; + +class LiquidMeltHot : public ActiveBlockModifier { + public: + LiquidMeltHot(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set<std::string> getTriggerContents() { + std::set<std::string> s; + s.insert("group:melts"); + return s; + } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> s; + s.insert("group:igniter"); + s.insert("group:hot"); + return s; + } + virtual float getTriggerInterval() + { return 2.0; } + virtual u32 getTriggerChance() + { return 4; } + virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) { + ServerMap *map = &env->getServerMap(); + INodeDefManager *ndef = env->getGameDef()->ndef(); + n.setContent(ndef->getId(ndef->get(n).freezemelt)); + if (!n.getLevel(ndef)) + n.addLevel(ndef); + map->addNodeWithEvent(p, n); + env->getScriptIface()->node_falling_update(p); + } +}; + +class LiquidMeltAround : public LiquidMeltHot { + public: + LiquidMeltAround(ServerEnvironment *env, INodeDefManager *nodemgr) + : LiquidMeltHot(env, nodemgr) { } + virtual std::set<std::string> getRequiredNeighbors() { + std::set<std::string> s; + s.insert("group:melt_around"); + return s; + } + virtual float getTriggerInterval() + { return 40.0; } + virtual u32 getTriggerChance() + { return 60; } +}; + + +void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) { env->addActiveBlockModifier(new GrowGrassABM()); env->addActiveBlockModifier(new RemoveGrassABM()); env->addActiveBlockModifier(new MakeTreesFromSaplingsABM(env, nodedef)); if (g_settings->getBool("liquid_finite")) { env->addActiveBlockModifier(new LiquidFlowABM(env, nodedef)); env->addActiveBlockModifier(new LiquidDropABM(env, nodedef)); + env->addActiveBlockModifier(new LiquidMeltHot(env, nodedef)); + env->addActiveBlockModifier(new LiquidMeltAround(env, nodedef)); + if (g_settings->getBool("weather")) { + env->addActiveBlockModifier(new LiquidFreeze(env, nodedef)); + env->addActiveBlockModifier(new LiquidMeltWeather(env, nodedef)); + } } } |