X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fcontent_abm.cpp;h=9289035b8c1557a07ea0a782a0b306adbb9d4200;hb=0a903e69fbd9b19d8d8da0593f31dec5807af566;hp=63867b78b6baff9b8e07f2e386fc66e72031b100;hpb=ccfec0400f1da96ffc7c6fb6f30f4afbd26db535;p=minetest.git diff --git a/src/content_abm.cpp b/src/content_abm.cpp index 63867b78b..9289035b8 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -1,18 +1,18 @@ /* -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 General Public License as published by -the Free Software Foundation; either version 2 of the License, or +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ @@ -25,245 +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 "mapgen.h" // For mapgen::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("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("dirt_with_grass")); - map->addNodeWithEvent(p, n); - } - } -}; +class LiquidFlowABM : public ActiveBlockModifier { + private: + std::set contents; -class RemoveGrassABM : public ActiveBlockModifier -{ -private: -public: - virtual std::set getTriggerContents() - { - std::set s; - s.insert("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 || - ndef->get(n_top).isLiquid()) - { - n.setContent(ndef->getId("dirt")); - map->addNodeWithEvent(p, n); + 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 SpawnRatsAroundTreesABM : public ActiveBlockModifier -{ -private: -public: - virtual std::set getTriggerContents() - { - std::set s; - s.insert("tree"); - s.insert("jungletree"); - return s; - } - virtual float getTriggerInterval() - { return 10.0; } - virtual u32 getTriggerChance() - { return 200; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, - u32 active_object_count, u32 active_object_count_wider) - { - if(active_object_count_wider != 0) - return; +class LiquidDropABM : public ActiveBlockModifier { + private: + std::set contents; - INodeDefManager *ndef = env->getGameDef()->ndef(); - ServerMap *map = &env->getServerMap(); - - v3s16 p1 = p + v3s16(myrand_range(-2, 2), - 0, myrand_range(-2, 2)); - MapNode n1 = map->getNodeNoEx(p1); - MapNode n1b = map->getNodeNoEx(p1+v3s16(0,-1,0)); - if(n1b.getContent() == ndef->getId("dirt_with_grass") && - n1.getContent() == CONTENT_AIR) - { - v3f pos = intToFloat(p1, BS); - ServerActiveObject *obj = new RatSAO(env, pos); - env->addActiveObject(obj); + 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); } - } }; -static void getMob_dungeon_master(Settings &properties) -{ - properties.set("looks", "dungeon_master"); - properties.setFloat("yaw", 1.57); - properties.setFloat("hp", 30); - properties.setBool("bright_shooting", true); - properties.set("shoot_type", "fireball"); - properties.set("shoot_y", "0.7"); - properties.set("player_hit_damage", "1"); - properties.set("player_hit_distance", "1.0"); - properties.set("player_hit_interval", "0.5"); - properties.setBool("mindless_rage", myrand_range(0,100)==0); -} - -class SpawnInCavesABM : public ActiveBlockModifier -{ -private: -public: - virtual std::set getTriggerContents() - { - std::set s; - s.insert("stone"); - s.insert("mossycobble"); - return s; - } - virtual float getTriggerInterval() - { return 2.0; } - virtual u32 getTriggerChance() - { return 1000; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, - u32 active_object_count, u32 active_object_count_wider) - { - if(active_object_count_wider != 0) - return; - - INodeDefManager *ndef = env->getGameDef()->ndef(); - ServerMap *map = &env->getServerMap(); - - v3s16 p1 = p + v3s16(0,1,0); - MapNode n1a = map->getNodeNoEx(p1+v3s16(0,0,0)); - if(n1a.getLightBlend(env->getDayNightRatio(), ndef) <= 3){ - MapNode n1b = map->getNodeNoEx(p1+v3s16(0,1,0)); - if(n1a.getContent() == CONTENT_AIR && - n1b.getContent() == CONTENT_AIR) - { - v3f pos = intToFloat(p1, BS); - int i = myrand()%5; - if(i == 0 || i == 1){ - actionstream<<"A dungeon master spawns at " - <addActiveObject(obj); - } else if(i == 2 || i == 3){ - actionstream<<"Rats spawn at " - <addActiveObject(obj); - } - } else { - actionstream<<"An oerkki spawns at " - <addActiveObject(obj); +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); } } } - } }; -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; - mapgen::make_tree(vmanip, tree_p, is_apple_tree, ndef); - vmanip.blitBackAll(&modified_blocks); +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); + } + } +}; - // 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()); +class LiquidMeltHot : public ActiveBlockModifier { + public: + LiquidMeltHot(ServerEnvironment *env, INodeDefManager *nodemgr) { } + virtual std::set getTriggerContents() { + std::set s; + s.insert("group:melts"); + return s; } - map->updateLighting(lighting_modified_blocks, modified_blocks); + 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); + } +}; - // 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); +/* 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; } - map->dispatchEvent(&event); - } + 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 SpawnRatsAroundTreesABM()); - env->addActiveBlockModifier(new SpawnInCavesABM()); - env->addActiveBlockModifier(new MakeTreesFromSaplingsABM()); +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)); + } + } } - -