X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fcontent_abm.cpp;h=9289035b8c1557a07ea0a782a0b306adbb9d4200;hb=0a903e69fbd9b19d8d8da0593f31dec5807af566;hp=ce1751117630d7b84488dde3dc93d84595fe17a2;hpb=2c362badd401dc16d32b543ed15bfcad44f9163b;p=minetest.git diff --git a/src/content_abm.cpp b/src/content_abm.cpp index ce1751117..9289035b8 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -1,6 +1,6 @@ /* -Minetest-c55 -Copyright (C) 2011 celeron55, Perttu Ahola +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,132 +25,223 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_sao.h" #include "settings.h" #include "mapblock.h" // For getNodeBlockPos -#include "treegen.h" // For treegen::make_tree +#include "main.h" // for g_settings #include "map.h" +#include "scripting_game.h" +#include "log.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" -class GrowGrassABM : public ActiveBlockModifier -{ -private: -public: - virtual std::set getTriggerContents() - { - std::set s; - s.insert("mapgen_dirt"); - return s; - } - virtual float getTriggerInterval() - { return 2.0; } - virtual u32 getTriggerChance() - { return 200; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) - { - INodeDefManager *ndef = env->getGameDef()->ndef(); - ServerMap *map = &env->getServerMap(); - - MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0)); - if(ndef->get(n_top).light_propagates && - !ndef->get(n_top).isLiquid() && - n_top.getLightBlend(env->getDayNightRatio(), ndef) >= 13) - { - n.setContent(ndef->getId("mapgen_dirt_with_grass")); - map->addNodeWithEvent(p, n); +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) + return; + map->transforming_liquid_add(p); } - } }; -class RemoveGrassABM : public ActiveBlockModifier -{ -private: -public: - virtual std::set getTriggerContents() - { - std::set s; - s.insert("mapgen_dirt_with_grass"); - return s; - } - virtual float getTriggerInterval() - { return 2.0; } - virtual u32 getTriggerChance() - { return 20; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n) - { - INodeDefManager *ndef = env->getGameDef()->ndef(); - ServerMap *map = &env->getServerMap(); - - MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0)); - if((!ndef->get(n_top).light_propagates && - n_top.getContent() != CONTENT_IGNORE) || - ndef->get(n_top).isLiquid()) - { - n.setContent(ndef->getId("mapgen_dirt")); - map->addNodeWithEvent(p, n); +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("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 MakeTreesFromSaplingsABM : public ActiveBlockModifier -{ -private: -public: - virtual std::set getTriggerContents() - { - std::set s; - s.insert("sapling"); - return s; - } - virtual float getTriggerInterval() - { return 10.0; } - virtual u32 getTriggerChance() - { return 50; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, - u32 active_object_count, u32 active_object_count_wider) - { - INodeDefManager *ndef = env->getGameDef()->ndef(); - ServerMap *map = &env->getServerMap(); - - actionstream<<"A sapling grows into a tree at " - < modified_blocks; - v3s16 tree_p = p; - ManualMapVoxelManipulator vmanip(map); - v3s16 tree_blockp = getNodeBlockPos(tree_p); - vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); - bool is_apple_tree = myrand()%4 == 0; - treegen::make_tree(vmanip, tree_p, is_apple_tree, ndef); - vmanip.blitBackAll(&modified_blocks); - - // update lighting - core::map lighting_modified_blocks; - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) - { - lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue()); - } - map->updateLighting(lighting_modified_blocks, modified_blocks); - - // Send a MEET_OTHER event - MapEditEvent event; - event.type = MEET_OTHER; - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - event.modified_blocks.insert(p, true); - } - map->dispatchEvent(&event); - } +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("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->updateBlockHeat(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); + } + } + } }; -void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) -{ - env->addActiveBlockModifier(new GrowGrassABM()); - env->addActiveBlockModifier(new RemoveGrassABM()); - env->addActiveBlockModifier(new MakeTreesFromSaplingsABM()); -} +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("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->updateBlockHeat(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) { + 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 (env->m_use_weather) { + env->addActiveBlockModifier(new LiquidFreeze(env, nodedef)); + env->addActiveBlockModifier(new LiquidMeltWeather(env, nodedef)); + } + } +}