mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 18:13:46 +01:00
Add ABM required neighbor check
This commit is contained in:
parent
ac56053c74
commit
7d37913ea4
@ -73,6 +73,7 @@
|
|||||||
-- minetest.register_node(name, node definition)
|
-- minetest.register_node(name, node definition)
|
||||||
-- minetest.register_craftitem(name, craftitem definition)
|
-- minetest.register_craftitem(name, craftitem definition)
|
||||||
-- minetest.register_craft(recipe)
|
-- minetest.register_craft(recipe)
|
||||||
|
-- minetest.register_abm(abm definition)
|
||||||
-- minetest.register_globalstep(func(dtime))
|
-- minetest.register_globalstep(func(dtime))
|
||||||
-- minetest.register_on_placenode(func(pos, newnode, placer))
|
-- minetest.register_on_placenode(func(pos, newnode, placer))
|
||||||
-- minetest.register_on_dignode(func(pos, oldnode, digger))
|
-- minetest.register_on_dignode(func(pos, oldnode, digger))
|
||||||
@ -285,6 +286,16 @@
|
|||||||
-- }
|
-- }
|
||||||
-- }
|
-- }
|
||||||
--
|
--
|
||||||
|
-- ABM (ActiveBlockModifier) definition:
|
||||||
|
-- {
|
||||||
|
-- nodenames = {"lava_source"},
|
||||||
|
-- neighbors = {"water_source", "water_flowing"}, -- (any of these)
|
||||||
|
-- ^ If left out or empty, any neighbor will do
|
||||||
|
-- ^ This might get removed in the future
|
||||||
|
-- interval = 1.0, -- (operation interval)
|
||||||
|
-- chance = 1, -- (chance of trigger is 1.0/this)
|
||||||
|
-- action = func(pos, node, active_object_count, active_object_count_wider),
|
||||||
|
-- }
|
||||||
|
|
||||||
-- print("minetest dump: "..dump(minetest))
|
-- print("minetest dump: "..dump(minetest))
|
||||||
|
|
||||||
|
@ -565,6 +565,7 @@ struct ActiveABM
|
|||||||
{
|
{
|
||||||
ActiveBlockModifier *abm;
|
ActiveBlockModifier *abm;
|
||||||
int chance;
|
int chance;
|
||||||
|
std::set<content_t> required_neighbors;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ABMHandler
|
class ABMHandler
|
||||||
@ -602,6 +603,18 @@ public:
|
|||||||
aabm.chance = 1.0 / pow((float)1.0/chance, (float)intervals);
|
aabm.chance = 1.0 / pow((float)1.0/chance, (float)intervals);
|
||||||
if(aabm.chance == 0)
|
if(aabm.chance == 0)
|
||||||
aabm.chance = 1;
|
aabm.chance = 1;
|
||||||
|
// Trigger neighbors
|
||||||
|
std::set<std::string> required_neighbors_s
|
||||||
|
= abm->getRequiredNeighbors();
|
||||||
|
for(std::set<std::string>::iterator
|
||||||
|
i = required_neighbors_s.begin();
|
||||||
|
i != required_neighbors_s.end(); i++){
|
||||||
|
content_t c = ndef->getId(*i);
|
||||||
|
if(c == CONTENT_IGNORE)
|
||||||
|
continue;
|
||||||
|
aabm.required_neighbors.insert(c);
|
||||||
|
}
|
||||||
|
// Trigger contents
|
||||||
std::set<std::string> contents_s = abm->getTriggerContents();
|
std::set<std::string> contents_s = abm->getTriggerContents();
|
||||||
for(std::set<std::string>::iterator
|
for(std::set<std::string>::iterator
|
||||||
i = contents_s.begin(); i != contents_s.end(); i++){
|
i = contents_s.begin(); i != contents_s.end(); i++){
|
||||||
@ -646,6 +659,29 @@ public:
|
|||||||
if(myrand() % i->chance != 0)
|
if(myrand() % i->chance != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Check neighbors
|
||||||
|
if(!i->required_neighbors.empty())
|
||||||
|
{
|
||||||
|
v3s16 p1;
|
||||||
|
for(p1.X = p.X-1; p1.X <= p.X+1; p1.X++)
|
||||||
|
for(p1.Y = p.Y-1; p1.Y <= p.Y+1; p1.Y++)
|
||||||
|
for(p1.Z = p.Z-1; p1.Z <= p.Z+1; p1.Z++)
|
||||||
|
{
|
||||||
|
if(p1 == p)
|
||||||
|
continue;
|
||||||
|
MapNode n = map->getNodeNoEx(p1);
|
||||||
|
content_t c = n.getContent();
|
||||||
|
std::set<content_t>::const_iterator k;
|
||||||
|
k = i->required_neighbors.find(c);
|
||||||
|
if(k != i->required_neighbors.end()){
|
||||||
|
goto neighbor_found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No required neighbor found
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
neighbor_found:
|
||||||
|
|
||||||
// Find out how many objects the block contains
|
// Find out how many objects the block contains
|
||||||
u32 active_object_count = block->m_static_objects.m_active.size();
|
u32 active_object_count = block->m_static_objects.m_active.size();
|
||||||
// Find out how many objects this and all the neighbors contain
|
// Find out how many objects this and all the neighbors contain
|
||||||
|
@ -108,9 +108,15 @@ public:
|
|||||||
ActiveBlockModifier(){};
|
ActiveBlockModifier(){};
|
||||||
virtual ~ActiveBlockModifier(){};
|
virtual ~ActiveBlockModifier(){};
|
||||||
|
|
||||||
|
// Set of contents to trigger on
|
||||||
virtual std::set<std::string> getTriggerContents()=0;
|
virtual std::set<std::string> getTriggerContents()=0;
|
||||||
|
// Set of required neighbors (trigger doesn't happen if none are found)
|
||||||
|
// Empty = do not check neighbors
|
||||||
|
virtual std::set<std::string> getRequiredNeighbors()
|
||||||
|
{ return std::set<std::string>(); }
|
||||||
|
// Trigger interval in seconds
|
||||||
virtual float getTriggerInterval() = 0;
|
virtual float getTriggerInterval() = 0;
|
||||||
// chance of (1 / return value), 0 is disallowed
|
// Random chance of (1 / return value), 0 is disallowed
|
||||||
virtual u32 getTriggerChance() = 0;
|
virtual u32 getTriggerChance() = 0;
|
||||||
// This is called usually at interval for 1/chance of the nodes
|
// This is called usually at interval for 1/chance of the nodes
|
||||||
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){};
|
virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){};
|
||||||
|
@ -709,15 +709,18 @@ private:
|
|||||||
int m_id;
|
int m_id;
|
||||||
|
|
||||||
std::set<std::string> m_trigger_contents;
|
std::set<std::string> m_trigger_contents;
|
||||||
|
std::set<std::string> m_required_neighbors;
|
||||||
float m_trigger_interval;
|
float m_trigger_interval;
|
||||||
u32 m_trigger_chance;
|
u32 m_trigger_chance;
|
||||||
public:
|
public:
|
||||||
LuaABM(lua_State *L, int id,
|
LuaABM(lua_State *L, int id,
|
||||||
const std::set<std::string> &trigger_contents,
|
const std::set<std::string> &trigger_contents,
|
||||||
|
const std::set<std::string> &required_neighbors,
|
||||||
float trigger_interval, u32 trigger_chance):
|
float trigger_interval, u32 trigger_chance):
|
||||||
m_lua(L),
|
m_lua(L),
|
||||||
m_id(id),
|
m_id(id),
|
||||||
m_trigger_contents(trigger_contents),
|
m_trigger_contents(trigger_contents),
|
||||||
|
m_required_neighbors(required_neighbors),
|
||||||
m_trigger_interval(trigger_interval),
|
m_trigger_interval(trigger_interval),
|
||||||
m_trigger_chance(trigger_chance)
|
m_trigger_chance(trigger_chance)
|
||||||
{
|
{
|
||||||
@ -726,6 +729,10 @@ public:
|
|||||||
{
|
{
|
||||||
return m_trigger_contents;
|
return m_trigger_contents;
|
||||||
}
|
}
|
||||||
|
virtual std::set<std::string> getRequiredNeighbors()
|
||||||
|
{
|
||||||
|
return m_required_neighbors;
|
||||||
|
}
|
||||||
virtual float getTriggerInterval()
|
virtual float getTriggerInterval()
|
||||||
{
|
{
|
||||||
return m_trigger_interval;
|
return m_trigger_interval;
|
||||||
@ -2575,7 +2582,9 @@ void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
|
|||||||
lua_pushlightuserdata(L, env);
|
lua_pushlightuserdata(L, env);
|
||||||
lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
|
lua_setfield(L, LUA_REGISTRYINDEX, "minetest_env");
|
||||||
|
|
||||||
/* Add ActiveBlockModifiers to environment */
|
/*
|
||||||
|
Add ActiveBlockModifiers to environment
|
||||||
|
*/
|
||||||
|
|
||||||
// Get minetest.registered_abms
|
// Get minetest.registered_abms
|
||||||
lua_getglobal(L, "minetest");
|
lua_getglobal(L, "minetest");
|
||||||
@ -2603,6 +2612,25 @@ void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
|
|||||||
// removes value, keeps key for next iteration
|
// removes value, keeps key for next iteration
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
} else if(lua_isstring(L, -1)){
|
||||||
|
trigger_contents.insert(lua_tostring(L, -1));
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
std::set<std::string> required_neighbors;
|
||||||
|
lua_getfield(L, current_abm, "neighbors");
|
||||||
|
if(lua_istable(L, -1)){
|
||||||
|
int table = lua_gettop(L);
|
||||||
|
lua_pushnil(L);
|
||||||
|
while(lua_next(L, table) != 0){
|
||||||
|
// key at index -2 and value at index -1
|
||||||
|
luaL_checktype(L, -1, LUA_TSTRING);
|
||||||
|
required_neighbors.insert(lua_tostring(L, -1));
|
||||||
|
// removes value, keeps key for next iteration
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
} else if(lua_isstring(L, -1)){
|
||||||
|
required_neighbors.insert(lua_tostring(L, -1));
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
@ -2613,7 +2641,7 @@ void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
|
|||||||
getintfield(L, current_abm, "chance", trigger_chance);
|
getintfield(L, current_abm, "chance", trigger_chance);
|
||||||
|
|
||||||
LuaABM *abm = new LuaABM(L, id, trigger_contents,
|
LuaABM *abm = new LuaABM(L, id, trigger_contents,
|
||||||
trigger_interval, trigger_chance);
|
required_neighbors, trigger_interval, trigger_chance);
|
||||||
|
|
||||||
env->addActiveBlockModifier(abm);
|
env->addActiveBlockModifier(abm);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user