Example #1
0
// find_nodes_in_area(minp, maxp, nodenames) -> list of positions
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
{
	GET_ENV_PTR;

	INodeDefManager *ndef = getServer(L)->ndef();
	v3s16 minp = read_v3s16(L, 1);
	v3s16 maxp = read_v3s16(L, 2);
	sortBoxVerticies(minp, maxp);

	v3s16 cube = maxp - minp + 1;

	/* Limit for too large areas, assume default values
	 * and give tolerances of 1 node on each side
	 * (chunksize * MAP_BLOCKSIZE + 2)^3 = 551368
	*/
	if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 551368) {
		luaL_error(L, "find_nodes_in_area(): area volume"
				" exceeds allowed value of 551368");
		return 0;
	}

	std::set<content_t> filter;
	if (lua_istable(L, 3)) {
		lua_pushnil(L);
		while (lua_next(L, 3) != 0) {
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if (lua_isstring(L, 3)) {
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	std::unordered_map<content_t, u32> individual_count;

	lua_newtable(L);
	u64 i = 0;
	for (s16 x = minp.X; x <= maxp.X; x++)
	for (s16 y = minp.Y; y <= maxp.Y; y++)
	for (s16 z = minp.Z; z <= maxp.Z; z++) {
		v3s16 p(x, y, z);
		content_t c = env->getMap().getNodeNoEx(p).getContent();
		if (filter.count(c) != 0) {
			push_v3s16(L, p);
			lua_rawseti(L, -2, ++i);
			individual_count[c]++;
		}
	}
	lua_newtable(L);
	for (std::set<content_t>::const_iterator it = filter.begin();
			it != filter.end(); ++it) {
		lua_pushnumber(L, individual_count[*it]);
		lua_setfield(L, -2, ndef->get(*it).name.c_str());
	}
	return 2;
}
Example #2
0
// 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)
{
	/* 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_ENV_PTR;

	INodeDefManager *ndef = getServer(L)->ndef();
	v3s16 minp = read_v3s16(L, 1);
	v3s16 maxp = read_v3s16(L, 2);
	std::set<content_t> filter;

	if (lua_istable(L, 3)) {
		int table = 3;
		lua_pushnil(L);
		while(lua_next(L, table) != 0) {
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if (lua_isstring(L, 3)) {
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	lua_newtable(L);
	u64 i = 0;
	for (s16 x = minp.X; x <= maxp.X; x++)
	for (s16 z = minp.Z; z <= maxp.Z; z++) {
		s16 y = minp.Y;
		v3s16 p(x, y, z);
		content_t c = env->getMap().getNodeNoEx(p).getContent();
		for (; y <= maxp.Y; y++) {
			v3s16 psurf(x, y + 1, z);
			content_t csurf = env->getMap().getNodeNoEx(psurf).getContent();
			if(c != CONTENT_AIR && csurf == CONTENT_AIR &&
					filter.count(c) != 0) {
				push_v3s16(L, v3s16(x, y, z));
				lua_rawseti(L, -2, ++i);
			}
			c = csurf;
		}
	}
	return 1;
}
Example #3
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)
{
	Environment *env = getEnv(L);
	if (!env) {
		return 0;
	}

	INodeDefManager *ndef = getGameDef(L)->ndef();
	v3s16 pos = read_v3s16(L, 1);
	int radius = luaL_checkinteger(L, 2);
	std::vector<content_t> filter;
	if (lua_istable(L, 3)) {
		lua_pushnil(L);
		while (lua_next(L, 3) != 0) {
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if (lua_isstring(L, 3)) {
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	int start_radius = (lua_toboolean(L, 4)) ? 0 : 1;

#ifndef SERVER
	// Client API limitations
	if (getClient(L) &&
			getClient(L)->checkCSMFlavourLimit(CSMFlavourLimit::CSM_FL_LOOKUP_NODES)) {
		radius = std::max<int>(radius, getClient(L)->getCSMNodeRangeLimit());
	}
#endif

	for (int d = start_radius; d <= radius; d++) {
		std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
		for (const v3s16 &i : list) {
			v3s16 p = pos + i;
			content_t c = env->getMap().getNodeNoEx(p).getContent();
			if (CONTAINS(filter, c)) {
				push_v3s16(L, p);
				return 1;
			}
		}
	}
	return 0;
}
Example #4
0
// find_nodes_in_area(minp, maxp, nodenames) -> list of positions
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
{
	GET_ENV_PTR;

	INodeDefManager *ndef = getServer(L)->ndef();
	v3s16 minp = read_v3s16(L, 1);
	v3s16 maxp = read_v3s16(L, 2);
	std::set<content_t> filter;
	if(lua_istable(L, 3)) {
		int table = 3;
		lua_pushnil(L);
		while(lua_next(L, table) != 0) {
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if(lua_isstring(L, 3)) {
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	std::map<content_t, u16> individual_count;

	lua_newtable(L);
	u64 i = 0;
	for (s16 x = minp.X; x <= maxp.X; x++)
		for (s16 y = minp.Y; y <= maxp.Y; y++)
			for (s16 z = minp.Z; z <= maxp.Z; z++) {
				v3s16 p(x, y, z);
				content_t c = env->getMap().getNodeNoEx(p).getContent();
				if (filter.count(c) != 0) {
					push_v3s16(L, p);
					lua_rawseti(L, -2, ++i);
					individual_count[c]++;
				}
	}
	lua_newtable(L);
	for (std::set<content_t>::iterator it = filter.begin();
			it != filter.end(); ++it) {
		lua_pushnumber(L, individual_count[*it]);
		lua_setfield(L, -2, ndef->get(*it).name.c_str());
	}
	return 2;
}
Example #5
0
// minetest.find_nodes_in_area(minp, maxp, nodenames) -> list of positions
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
{
	GET_ENV_PTR;

	INodeDefManager *ndef = getServer(L)->ndef();
	v3s16 minp = read_v3s16(L, 1);
	v3s16 maxp = read_v3s16(L, 2);
	std::set<content_t> filter;
	if(lua_istable(L, 3)){
		int table = 3;
		lua_pushnil(L);
		while(lua_next(L, table) != 0){
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if(lua_isstring(L, 3)){
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	// Get the table insert function
	lua_getglobal(L, "table");
	lua_getfield(L, -1, "insert");
	int table_insert = lua_gettop(L);

	lua_newtable(L);
	int table = lua_gettop(L);
	for(s16 x=minp.X; x<=maxp.X; x++)
	for(s16 y=minp.Y; y<=maxp.Y; y++)
	for(s16 z=minp.Z; z<=maxp.Z; z++)
	{
		v3s16 p(x,y,z);
		content_t c = env->getMap().getNodeNoEx(p).getContent();
		if(filter.count(c) != 0){
			lua_pushvalue(L, table_insert);
			lua_pushvalue(L, table);
			push_v3s16(L, p);
			if(lua_pcall(L, 2, 0, 0))
				script_error(L, "error: %s", lua_tostring(L, -1));
		}
	}
	return 1;
}
Example #6
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)
{
	Environment *env = getEnv(L);
	if (!env) {
		return 0;
	}

	INodeDefManager *ndef = getGameDef(L)->ndef();
	v3s16 pos = read_v3s16(L, 1);
	int radius = luaL_checkinteger(L, 2);
	std::set<content_t> filter;
	if (lua_istable(L, 3)) {
		lua_pushnil(L);
		while (lua_next(L, 3) != 0) {
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if (lua_isstring(L, 3)) {
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	int start_radius = (lua_toboolean(L, 4)) ? 0 : 1;
	for (int d = start_radius; d <= radius; d++) {
		std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
		for (std::vector<v3s16>::iterator i = list.begin();
				i != list.end(); ++i) {
			v3s16 p = pos + (*i);
			content_t c = env->getMap().getNodeNoEx(p).getContent();
			if (filter.count(c) != 0) {
				push_v3s16(L, p);
				return 1;
			}
		}
	}
	return 0;
}
Example #7
0
// find_node_near(pos, radius, nodenames) -> pos or nil
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
int ModApiEnvMod::l_find_node_near(lua_State *L)
{
	GET_ENV_PTR;

	INodeDefManager *ndef = getServer(L)->ndef();
	v3s16 pos = read_v3s16(L, 1);
	int radius = luaL_checkinteger(L, 2);
	std::set<content_t> filter;
	if(lua_istable(L, 3)){
		int table = 3;
		lua_pushnil(L);
		while(lua_next(L, table) != 0){
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if(lua_isstring(L, 3)){
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	for(int d=1; d<=radius; d++){
		std::list<v3s16> list;
		getFacePositions(list, d);
		for(std::list<v3s16>::iterator i = list.begin();
				i != list.end(); ++i){
			v3s16 p = pos + (*i);
			content_t c = env->getMap().getNodeNoEx(p).getContent();
			if(filter.count(c) != 0){
				push_v3s16(L, p);
				return 1;
			}
		}
	}
	return 0;
}
Example #8
0
// find_nodes_in_area(minp, maxp, nodenames) -> list of positions
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
{
	GET_ENV_PTR;

	INodeDefManager *ndef = getServer(L)->ndef();
	v3s16 minp = read_v3s16(L, 1);
	v3s16 maxp = read_v3s16(L, 2);
	std::set<content_t> filter;
	if(lua_istable(L, 3)){
		int table = 3;
		lua_pushnil(L);
		while(lua_next(L, table) != 0){
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if(lua_isstring(L, 3)){
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	lua_newtable(L);
	u64 i = 0;
	for(s16 x = minp.X; x <= maxp.X; x++)
	for(s16 y = minp.Y; y <= maxp.Y; y++)
	for(s16 z = minp.Z; z <= maxp.Z; z++) {
		v3s16 p(x, y, z);
		content_t c = env->getMap().getNodeNoEx(p).getContent();
		if(filter.count(c) != 0) {
			push_v3s16(L, p);
			lua_rawseti(L, -2, ++i);
		}
	}
	return 1;
}
Example #9
0
// 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)
{
	/* 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_ENV_PTR;

	INodeDefManager *ndef = getServer(L)->ndef();
	v3s16 minp = read_v3s16(L, 1);
	v3s16 maxp = read_v3s16(L, 2);
	sortBoxVerticies(minp, maxp);

	v3s16 cube = maxp - minp + 1;

	/* Limit for too large areas, assume default values
	 * and give tolerances of 1 node on each side
	 * (chunksize * MAP_BLOCKSIZE + 2)^3 = 551368
	*/
	if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 551368) {
		luaL_error(L, "find_nodes_in_area_under_air(): area volume"
				" exceeds allowed value of 551368");
		return 0;
	}

	std::vector<content_t> filter;

	if (lua_istable(L, 3)) {
		lua_pushnil(L);
		while (lua_next(L, 3) != 0) {
			// key at index -2 and value at index -1
			luaL_checktype(L, -1, LUA_TSTRING);
			ndef->getIds(lua_tostring(L, -1), filter);
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
		}
	} else if (lua_isstring(L, 3)) {
		ndef->getIds(lua_tostring(L, 3), filter);
	}

	lua_newtable(L);
	u64 i = 0;
	for (s16 x = minp.X; x <= maxp.X; x++)
	for (s16 z = minp.Z; z <= maxp.Z; z++) {
		s16 y = minp.Y;
		v3s16 p(x, y, z);
		content_t c = env->getMap().getNodeNoEx(p).getContent();
		for (; y <= maxp.Y; y++) {
			v3s16 psurf(x, y + 1, z);
			content_t csurf = env->getMap().getNodeNoEx(psurf).getContent();
			if (c != CONTENT_AIR && csurf == CONTENT_AIR &&
					CONTAINS(filter, c)) {
				push_v3s16(L, v3s16(x, y, z));
				lua_rawseti(L, -2, ++i);
			}
			c = csurf;
		}
	}
	return 1;
}