mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 09:15:29 +01:00 
			
		
		
		
	Genericize find_node_near and find_node_in implementations in C++
This commit is contained in:
		@@ -46,14 +46,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
#include "client/client.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
const EnumString ModApiEnvMod::es_ClearObjectsMode[] =
 | 
			
		||||
const EnumString ModApiEnvBase::es_ClearObjectsMode[] =
 | 
			
		||||
{
 | 
			
		||||
	{CLEAR_OBJECTS_MODE_FULL,  "full"},
 | 
			
		||||
	{CLEAR_OBJECTS_MODE_QUICK, "quick"},
 | 
			
		||||
	{0, NULL},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const EnumString ModApiEnvMod::es_BlockStatusType[] =
 | 
			
		||||
const EnumString ModApiEnvBase::es_BlockStatusType[] =
 | 
			
		||||
{
 | 
			
		||||
	{ServerEnvironment::BS_UNKNOWN, "unknown"},
 | 
			
		||||
	{ServerEnvironment::BS_EMERGING, "emerging"},
 | 
			
		||||
@@ -796,7 +796,7 @@ int ModApiEnvMod::l_get_gametime(lua_State *L)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModApiEnvMod::collectNodeIds(lua_State *L, int idx, const NodeDefManager *ndef,
 | 
			
		||||
void ModApiEnvBase::collectNodeIds(lua_State *L, int idx, const NodeDefManager *ndef,
 | 
			
		||||
	std::vector<content_t> &filter)
 | 
			
		||||
{
 | 
			
		||||
	if (lua_istable(L, idx)) {
 | 
			
		||||
@@ -809,10 +809,28 @@ void ModApiEnvMod::collectNodeIds(lua_State *L, int idx, const NodeDefManager *n
 | 
			
		||||
			lua_pop(L, 1);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (lua_isstring(L, idx)) {
 | 
			
		||||
		ndef->getIds(readParam<std::string>(L, 3), filter);
 | 
			
		||||
		ndef->getIds(readParam<std::string>(L, idx), filter);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename F>
 | 
			
		||||
int ModApiEnvBase::findNodeNear(lua_State *L, v3s16 pos, int radius,
 | 
			
		||||
		const std::vector<content_t> &filter, int start_radius, F &&getNode)
 | 
			
		||||
{
 | 
			
		||||
	for (int d = start_radius; d <= radius; d++) {
 | 
			
		||||
		const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d);
 | 
			
		||||
		for (const v3s16 &i : list) {
 | 
			
		||||
			v3s16 p = pos + i;
 | 
			
		||||
			content_t c = getNode(p).getContent();
 | 
			
		||||
			if (CONTAINS(filter, c)) {
 | 
			
		||||
				push_v3s16(L, p);
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// find_node_near(pos, radius, nodenames, [search_center]) -> pos or nil
 | 
			
		||||
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
 | 
			
		||||
int ModApiEnvMod::l_find_node_near(lua_State *L)
 | 
			
		||||
@@ -835,21 +853,13 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
 | 
			
		||||
		radius = client->CSMClampRadius(pos, radius);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	for (int d = start_radius; d <= radius; d++) {
 | 
			
		||||
		const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d);
 | 
			
		||||
		for (const v3s16 &i : list) {
 | 
			
		||||
			v3s16 p = pos + i;
 | 
			
		||||
			content_t c = map.getNode(p).getContent();
 | 
			
		||||
			if (CONTAINS(filter, c)) {
 | 
			
		||||
				push_v3s16(L, p);
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
	auto getNode = [&map] (v3s16 p) -> MapNode {
 | 
			
		||||
		return map.getNode(p);
 | 
			
		||||
	};
 | 
			
		||||
	return findNodeNear(L, pos, radius, filter, start_radius, getNode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void checkArea(v3s16 &minp, v3s16 &maxp)
 | 
			
		||||
void ModApiEnvBase::checkArea(v3s16 &minp, v3s16 &maxp)
 | 
			
		||||
{
 | 
			
		||||
	auto volume = VoxelArea(minp, maxp).getVolume();
 | 
			
		||||
	// Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
 | 
			
		||||
@@ -864,32 +874,10 @@ static void checkArea(v3s16 &minp, v3s16 &maxp)
 | 
			
		||||
#undef CLAMP
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// find_nodes_in_area(minp, maxp, nodenames, [grouped])
 | 
			
		||||
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
 | 
			
		||||
template <typename F>
 | 
			
		||||
int ModApiEnvBase::findNodesInArea(lua_State *L, const NodeDefManager *ndef,
 | 
			
		||||
		const std::vector<content_t> &filter, bool grouped, F &&iterate)
 | 
			
		||||
{
 | 
			
		||||
	GET_PLAIN_ENV_PTR;
 | 
			
		||||
 | 
			
		||||
	v3s16 minp = read_v3s16(L, 1);
 | 
			
		||||
	v3s16 maxp = read_v3s16(L, 2);
 | 
			
		||||
	sortBoxVerticies(minp, maxp);
 | 
			
		||||
 | 
			
		||||
	const NodeDefManager *ndef = env->getGameDef()->ndef();
 | 
			
		||||
	Map &map = env->getMap();
 | 
			
		||||
 | 
			
		||||
#ifndef SERVER
 | 
			
		||||
	if (Client *client = getClient(L)) {
 | 
			
		||||
		minp = client->CSMClampPos(minp);
 | 
			
		||||
		maxp = client->CSMClampPos(maxp);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	checkArea(minp, maxp);
 | 
			
		||||
 | 
			
		||||
	std::vector<content_t> filter;
 | 
			
		||||
	collectNodeIds(L, 3, ndef, filter);
 | 
			
		||||
 | 
			
		||||
	bool grouped = lua_isboolean(L, 4) && readParam<bool>(L, 4);
 | 
			
		||||
 | 
			
		||||
	if (grouped) {
 | 
			
		||||
		// create the table we will be returning
 | 
			
		||||
		lua_createtable(L, 0, filter.size());
 | 
			
		||||
@@ -901,7 +889,7 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
 | 
			
		||||
		for (u32 i = 0; i < filter.size(); i++)
 | 
			
		||||
			lua_newtable(L);
 | 
			
		||||
 | 
			
		||||
		map.forEachNodeInArea(minp, maxp, [&](v3s16 p, MapNode n) -> bool {
 | 
			
		||||
		iterate([&](v3s16 p, MapNode n) -> bool {
 | 
			
		||||
			content_t c = n.getContent();
 | 
			
		||||
 | 
			
		||||
			auto it = std::find(filter.begin(), filter.end(), c);
 | 
			
		||||
@@ -935,7 +923,7 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
 | 
			
		||||
 | 
			
		||||
		lua_newtable(L);
 | 
			
		||||
		u32 i = 0;
 | 
			
		||||
		map.forEachNodeInArea(minp, maxp, [&](v3s16 p, MapNode n) -> bool {
 | 
			
		||||
		iterate([&](v3s16 p, MapNode n) -> bool {
 | 
			
		||||
			content_t c = n.getContent();
 | 
			
		||||
 | 
			
		||||
			auto it = std::find(filter.begin(), filter.end(), c);
 | 
			
		||||
@@ -959,17 +947,9 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// find_nodes_in_area_under_air(minp, maxp, nodenames) -> list of positions
 | 
			
		||||
// nodenames: e.g. {"ignore", "group:tree"} or "default:dirt"
 | 
			
		||||
int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
 | 
			
		||||
// find_nodes_in_area(minp, maxp, nodenames, [grouped])
 | 
			
		||||
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
 | 
			
		||||
{
 | 
			
		||||
	/* Note: A similar but generalized (and therefore slower) version of this
 | 
			
		||||
	 * function could be created -- e.g. find_nodes_in_area_under -- which
 | 
			
		||||
	 * would accept a node name (or ID?) or list of names that the "above node"
 | 
			
		||||
	 * should be.
 | 
			
		||||
	 * TODO
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	GET_PLAIN_ENV_PTR;
 | 
			
		||||
 | 
			
		||||
	v3s16 minp = read_v3s16(L, 1);
 | 
			
		||||
@@ -991,16 +971,28 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
 | 
			
		||||
	std::vector<content_t> filter;
 | 
			
		||||
	collectNodeIds(L, 3, ndef, filter);
 | 
			
		||||
 | 
			
		||||
	bool grouped = lua_isboolean(L, 4) && readParam<bool>(L, 4);
 | 
			
		||||
 | 
			
		||||
	auto iterate = [&] (auto &&callback) {
 | 
			
		||||
		map.forEachNodeInArea(minp, maxp, callback);
 | 
			
		||||
	};
 | 
			
		||||
	return findNodesInArea(L, ndef, filter, grouped, iterate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename F>
 | 
			
		||||
int ModApiEnvBase::findNodesInAreaUnderAir(lua_State *L, v3s16 minp, v3s16 maxp,
 | 
			
		||||
	const std::vector<content_t> &filter, F &&getNode)
 | 
			
		||||
{
 | 
			
		||||
	lua_newtable(L);
 | 
			
		||||
	u32 i = 0;
 | 
			
		||||
	v3s16 p;
 | 
			
		||||
	for (p.X = minp.X; p.X <= maxp.X; p.X++)
 | 
			
		||||
	for (p.Z = minp.Z; p.Z <= maxp.Z; p.Z++) {
 | 
			
		||||
		p.Y = minp.Y;
 | 
			
		||||
		content_t c = map.getNode(p).getContent();
 | 
			
		||||
		content_t c = getNode(p).getContent();
 | 
			
		||||
		for (; p.Y <= maxp.Y; p.Y++) {
 | 
			
		||||
			v3s16 psurf(p.X, p.Y + 1, p.Z);
 | 
			
		||||
			content_t csurf = map.getNode(psurf).getContent();
 | 
			
		||||
			content_t csurf = getNode(psurf).getContent();
 | 
			
		||||
			if (c != CONTENT_AIR && csurf == CONTENT_AIR &&
 | 
			
		||||
					CONTAINS(filter, c)) {
 | 
			
		||||
				push_v3s16(L, p);
 | 
			
		||||
@@ -1012,6 +1004,41 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// find_nodes_in_area_under_air(minp, maxp, nodenames) -> list of positions
 | 
			
		||||
// nodenames: e.g. {"ignore", "group:tree"} or "default:dirt"
 | 
			
		||||
int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
 | 
			
		||||
{
 | 
			
		||||
	/* TODO: A similar but generalized (and therefore slower) version of this
 | 
			
		||||
	 * function could be created -- e.g. find_nodes_in_area_under -- which
 | 
			
		||||
	 * would accept a node name or list of names that the "above node" should be.
 | 
			
		||||
	 */
 | 
			
		||||
	GET_PLAIN_ENV_PTR;
 | 
			
		||||
 | 
			
		||||
	v3s16 minp = read_v3s16(L, 1);
 | 
			
		||||
	v3s16 maxp = read_v3s16(L, 2);
 | 
			
		||||
	sortBoxVerticies(minp, maxp);
 | 
			
		||||
 | 
			
		||||
	const NodeDefManager *ndef = env->getGameDef()->ndef();
 | 
			
		||||
	Map &map = env->getMap();
 | 
			
		||||
 | 
			
		||||
#ifndef SERVER
 | 
			
		||||
	if (Client *client = getClient(L)) {
 | 
			
		||||
		minp = client->CSMClampPos(minp);
 | 
			
		||||
		maxp = client->CSMClampPos(maxp);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	checkArea(minp, maxp);
 | 
			
		||||
 | 
			
		||||
	std::vector<content_t> filter;
 | 
			
		||||
	collectNodeIds(L, 3, ndef, filter);
 | 
			
		||||
 | 
			
		||||
	auto getNode = [&map] (v3s16 p) -> MapNode {
 | 
			
		||||
		return map.getNode(p);
 | 
			
		||||
	};
 | 
			
		||||
	return findNodesInAreaUnderAir(L, minp, maxp, filter, getNode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get_perlin(seeddiff, octaves, persistence, scale)
 | 
			
		||||
// returns world-specific PerlinNoise
 | 
			
		||||
int ModApiEnvMod::l_get_perlin(lua_State *L)
 | 
			
		||||
@@ -1279,6 +1306,45 @@ int ModApiEnvMod::l_find_path(lua_State *L)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool read_tree_def(lua_State *L, int idx,
 | 
			
		||||
	const NodeDefManager *ndef, treegen::TreeDef &tree_def)
 | 
			
		||||
{
 | 
			
		||||
	std::string trunk, leaves, fruit;
 | 
			
		||||
	if (!lua_istable(L, idx))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	getstringfield(L, idx, "axiom", tree_def.initial_axiom);
 | 
			
		||||
	getstringfield(L, idx, "rules_a", tree_def.rules_a);
 | 
			
		||||
	getstringfield(L, idx, "rules_b", tree_def.rules_b);
 | 
			
		||||
	getstringfield(L, idx, "rules_c", tree_def.rules_c);
 | 
			
		||||
	getstringfield(L, idx, "rules_d", tree_def.rules_d);
 | 
			
		||||
	getstringfield(L, idx, "trunk", trunk);
 | 
			
		||||
	tree_def.trunknode = ndef->getId(trunk);
 | 
			
		||||
	getstringfield(L, idx, "leaves", leaves);
 | 
			
		||||
	tree_def.leavesnode = ndef->getId(leaves);
 | 
			
		||||
	tree_def.leaves2_chance = 0;
 | 
			
		||||
	getstringfield(L, idx, "leaves2", leaves);
 | 
			
		||||
	if (!leaves.empty()) {
 | 
			
		||||
		tree_def.leaves2node = ndef->getId(leaves);
 | 
			
		||||
		getintfield(L, idx, "leaves2_chance", tree_def.leaves2_chance);
 | 
			
		||||
	}
 | 
			
		||||
	getintfield(L, idx, "angle", tree_def.angle);
 | 
			
		||||
	getintfield(L, idx, "iterations", tree_def.iterations);
 | 
			
		||||
	if (!getintfield(L, idx, "random_level", tree_def.iterations_random_level))
 | 
			
		||||
		tree_def.iterations_random_level = 0;
 | 
			
		||||
	getstringfield(L, idx, "trunk_type", tree_def.trunk_type);
 | 
			
		||||
	getboolfield(L, idx, "thin_branches", tree_def.thin_branches);
 | 
			
		||||
	tree_def.fruit_chance = 0;
 | 
			
		||||
	getstringfield(L, idx, "fruit", fruit);
 | 
			
		||||
	if (!fruit.empty()) {
 | 
			
		||||
		tree_def.fruitnode = ndef->getId(fruit);
 | 
			
		||||
		getintfield(L, idx, "fruit_chance", tree_def.fruit_chance);
 | 
			
		||||
	}
 | 
			
		||||
	tree_def.explicit_seed = getintfield(L, idx, "seed", tree_def.seed);
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// spawn_tree(pos, treedef)
 | 
			
		||||
int ModApiEnvMod::l_spawn_tree(lua_State *L)
 | 
			
		||||
{
 | 
			
		||||
@@ -1287,41 +1353,9 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
 | 
			
		||||
	v3s16 p0 = read_v3s16(L, 1);
 | 
			
		||||
 | 
			
		||||
	treegen::TreeDef tree_def;
 | 
			
		||||
	std::string trunk,leaves,fruit;
 | 
			
		||||
	const NodeDefManager *ndef = env->getGameDef()->ndef();
 | 
			
		||||
 | 
			
		||||
	if(lua_istable(L, 2))
 | 
			
		||||
	{
 | 
			
		||||
		getstringfield(L, 2, "axiom", tree_def.initial_axiom);
 | 
			
		||||
		getstringfield(L, 2, "rules_a", tree_def.rules_a);
 | 
			
		||||
		getstringfield(L, 2, "rules_b", tree_def.rules_b);
 | 
			
		||||
		getstringfield(L, 2, "rules_c", tree_def.rules_c);
 | 
			
		||||
		getstringfield(L, 2, "rules_d", tree_def.rules_d);
 | 
			
		||||
		getstringfield(L, 2, "trunk", trunk);
 | 
			
		||||
		tree_def.trunknode=ndef->getId(trunk);
 | 
			
		||||
		getstringfield(L, 2, "leaves", leaves);
 | 
			
		||||
		tree_def.leavesnode=ndef->getId(leaves);
 | 
			
		||||
		tree_def.leaves2_chance=0;
 | 
			
		||||
		getstringfield(L, 2, "leaves2", leaves);
 | 
			
		||||
		if (!leaves.empty()) {
 | 
			
		||||
			tree_def.leaves2node=ndef->getId(leaves);
 | 
			
		||||
			getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance);
 | 
			
		||||
		}
 | 
			
		||||
		getintfield(L, 2, "angle", tree_def.angle);
 | 
			
		||||
		getintfield(L, 2, "iterations", tree_def.iterations);
 | 
			
		||||
		if (!getintfield(L, 2, "random_level", tree_def.iterations_random_level))
 | 
			
		||||
			tree_def.iterations_random_level = 0;
 | 
			
		||||
		getstringfield(L, 2, "trunk_type", tree_def.trunk_type);
 | 
			
		||||
		getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
 | 
			
		||||
		tree_def.fruit_chance=0;
 | 
			
		||||
		getstringfield(L, 2, "fruit", fruit);
 | 
			
		||||
		if (!fruit.empty()) {
 | 
			
		||||
			tree_def.fruitnode=ndef->getId(fruit);
 | 
			
		||||
			getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
 | 
			
		||||
		}
 | 
			
		||||
		tree_def.explicit_seed = getintfield(L, 2, "seed", tree_def.seed);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (!read_tree_def(L, 2, ndef, tree_def))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	ServerMap *map = &env->getServerMap();
 | 
			
		||||
@@ -1334,6 +1368,7 @@ int ModApiEnvMod::l_spawn_tree(lua_State *L)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lua_pushboolean(L, true);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,38 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
#include "serverenvironment.h"
 | 
			
		||||
#include "raycast.h"
 | 
			
		||||
 | 
			
		||||
class ModApiEnvMod : public ModApiBase {
 | 
			
		||||
// base class containing helpers
 | 
			
		||||
class ModApiEnvBase : public ModApiBase {
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
	static void collectNodeIds(lua_State *L, int idx,
 | 
			
		||||
		const NodeDefManager *ndef, std::vector<content_t> &filter);
 | 
			
		||||
 | 
			
		||||
	static void checkArea(v3s16 &minp, v3s16 &maxp);
 | 
			
		||||
 | 
			
		||||
	// F must be (v3s16 pos) -> MapNode
 | 
			
		||||
	template <typename F>
 | 
			
		||||
	static int findNodeNear(lua_State *L, v3s16 pos, int radius,
 | 
			
		||||
		const std::vector<content_t> &filter, int start_radius, F &&getNode);
 | 
			
		||||
 | 
			
		||||
	// F must be (G callback) -> void
 | 
			
		||||
	// with G being (v3s16 p, MapNode n) -> bool
 | 
			
		||||
	// and behave like Map::forEachNodeInArea
 | 
			
		||||
	template <typename F>
 | 
			
		||||
	static int findNodesInArea(lua_State *L,  const NodeDefManager *ndef,
 | 
			
		||||
		const std::vector<content_t> &filter, bool grouped, F &&iterate);
 | 
			
		||||
 | 
			
		||||
	// F must be (v3s16 pos) -> MapNode
 | 
			
		||||
	template <typename F>
 | 
			
		||||
	static int findNodesInAreaUnderAir(lua_State *L, v3s16 minp, v3s16 maxp,
 | 
			
		||||
		const std::vector<content_t> &filter, F &&getNode);
 | 
			
		||||
 | 
			
		||||
	static const EnumString es_ClearObjectsMode[];
 | 
			
		||||
	static const EnumString es_BlockStatusType[];
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ModApiEnvMod : public ModApiEnvBase {
 | 
			
		||||
private:
 | 
			
		||||
	// set_node(pos, node)
 | 
			
		||||
	// pos = {x=num, y=num, z=num}
 | 
			
		||||
@@ -198,20 +229,12 @@ private:
 | 
			
		||||
	// compare_block_status(nodepos)
 | 
			
		||||
	static int l_compare_block_status(lua_State *L);
 | 
			
		||||
 | 
			
		||||
	// Get a string translated server side
 | 
			
		||||
	// get_translated_string(lang_code, string)
 | 
			
		||||
	static int l_get_translated_string(lua_State * L);
 | 
			
		||||
 | 
			
		||||
	/* Helpers */
 | 
			
		||||
 | 
			
		||||
	static void collectNodeIds(lua_State *L, int idx,
 | 
			
		||||
		const NodeDefManager *ndef, std::vector<content_t> &filter);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	static void Initialize(lua_State *L, int top);
 | 
			
		||||
	static void InitializeClient(lua_State *L, int top);
 | 
			
		||||
 | 
			
		||||
	static const EnumString es_ClearObjectsMode[];
 | 
			
		||||
	static const EnumString es_BlockStatusType[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LuaABM : public ActiveBlockModifier {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user