X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fcontent_abm.cpp;h=57e4637d4f98a4c83e77a94acd0857b1cfd0ecdd;hb=714a8cef38ed46ddd6ef7c2689c93db2704969eb;hp=f19caf74eddd410fd76d107fa64c19e00922e46b;hpb=127c48835573f9e7bd89137ecb2176c2a8e5f783;p=oweals%2Fminetest.git diff --git a/src/content_abm.cpp b/src/content_abm.cpp index f19caf74e..57e4637d4 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,42 +168,219 @@ public: } }; -class LiquidFlowABM : public ActiveBlockModifier -{ -private: - std::set contents; +class LiquidFlowABM : public ActiveBlockModifier { + private: + std::set contents; -public: - LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) - { - std::set liquids; - nodemgr->getIds("group:liquid", liquids); - for(std::set::const_iterator k = liquids.begin(); k != liquids.end(); k++) - contents.insert(nodemgr->get(*k).liquid_alternative_flowing); - - } - virtual std::set 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) + public: + LiquidFlowABM(ServerEnvironment *env, INodeDefManager *nodemgr) { + std::set liquids; + nodemgr->getIds("group:liquid", liquids); + for(std::set::const_iterator k = liquids.begin(); k != liquids.end(); k++) + contents.insert(nodemgr->get(*k).liquid_alternative_flowing); + } + virtual std::set 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); - } + } }; -void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) -{ +class LiquidDropABM : public ActiveBlockModifier { + private: + std::set contents; + + public: + LiquidDropABM(ServerEnvironment *env, INodeDefManager *nodemgr) { + std::set liquids; + nodemgr->getIds("group:liquid", liquids); + for(std::set::const_iterator k = liquids.begin(); k != liquids.end(); k++) + contents.insert(nodemgr->get(*k).liquid_alternative_source); + } + virtual std::set getTriggerContents() + { return contents; } + virtual std::set getRequiredNeighbors() { + std::set 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); + } +}; + +class LiquidFreeze : public ActiveBlockModifier { + public: + LiquidFreeze(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set getTriggerContents() { + std::set s; + s.insert("group:freezes"); + return s; + } + virtual std::set getRequiredNeighbors() { + std::set 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 + content_t c = map->getNodeNoEx(p - v3s16(0, -1, 0 )).getContent(); // top + //more chance to freeze if air at top + if (heat <= -1 && (heat <= -50 || (myrand_range(-50, heat) <= (c == CONTENT_AIR ? -10 : -40)))) { + 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) + 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.freezeMelt(ndef); + map->addNodeWithEvent(p, n); + } + } + } +}; + +class LiquidMeltWeather : public ActiveBlockModifier { + public: + LiquidMeltWeather(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set getTriggerContents() { + std::set s; + s.insert("group:melts"); + return s; + } + virtual std::set getRequiredNeighbors() { + std::set 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); + content_t c = map->getNodeNoEx(p - v3s16(0, -1, 0 )).getContent(); // top + if (heat >= 1 && (heat >= 40 || ((myrand_range(heat, 40)) >= (c == CONTENT_AIR ? 10 : 20)))) { + n.freezeMelt(ndef); + map->addNodeWithEvent(p, n); + env->getScriptIface()->node_falling_update(p); + } + } +}; + +class LiquidMeltHot : public ActiveBlockModifier { + public: + LiquidMeltHot(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set getTriggerContents() { + std::set s; + s.insert("group:melts"); + return s; + } + virtual std::set getRequiredNeighbors() { + std::set 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.freezeMelt(ndef); + map->addNodeWithEvent(p, n); + env->getScriptIface()->node_falling_update(p); + } +}; + +/* too buggy, later via liquid flow code +class LiquidMeltAround : public LiquidMeltHot { + public: + LiquidMeltAround(ServerEnvironment *env, INodeDefManager *nodemgr) + : LiquidMeltHot(env, nodemgr) { } + virtual std::set getRequiredNeighbors() { + std::set 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")) + 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)); + } + } }