#include "lua_api/l_vmanip.h"
#include "common/c_converter.h"
#include "common/c_content.h"
+#include <algorithm>
#include "scripting_server.h"
#include "environment.h"
+#include "mapblock.h"
#include "server.h"
#include "nodedef.h"
#include "daynightratio.h"
#include "util/pointedthing.h"
#include "content_sao.h"
-#include "treegen.h"
+#include "mapgen/treegen.h"
#include "emerge.h"
#include "pathfinder.h"
#include "face_position_cache.h"
+#include "remoteplayer.h"
+#ifndef SERVER
+#include "client.h"
+#endif
struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
{
lua_pop(L, 1); // Pop error handler
}
+int LuaRaycast::l_next(lua_State *L)
+{
+ MAP_LOCK_REQUIRED;
+
+ ScriptApiItem *script = getScriptApi<ScriptApiItem>(L);
+ GET_ENV_PTR;
+
+ LuaRaycast *o = checkobject(L, 1);
+ PointedThing pointed;
+ env->continueRaycast(&o->state, &pointed);
+ if (pointed.type == POINTEDTHING_NOTHING)
+ lua_pushnil(L);
+ else
+ script->pushPointedThing(pointed);
+
+ return 1;
+}
+
+int LuaRaycast::create_object(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ bool objects = true;
+ bool liquids = false;
+
+ v3f pos1 = checkFloatPos(L, 1);
+ v3f pos2 = checkFloatPos(L, 2);
+ if (lua_isboolean(L, 3)) {
+ objects = lua_toboolean(L, 3);
+ }
+ if (lua_isboolean(L, 4)) {
+ liquids = lua_toboolean(L, 4);
+ }
+
+ LuaRaycast *o = new LuaRaycast(core::line3d<f32>(pos1, pos2),
+ objects, liquids);
+
+ *(void **) (lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+LuaRaycast *LuaRaycast::checkobject(lua_State *L, int narg)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+ void *ud = luaL_checkudata(L, narg, className);
+ if (!ud)
+ luaL_typerror(L, narg, className);
+ return *(LuaRaycast **) ud;
+}
+
+int LuaRaycast::gc_object(lua_State *L)
+{
+ LuaRaycast *o = *(LuaRaycast **) (lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+void LuaRaycast::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__call");
+ lua_pushcfunction(L, l_next);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1);
+
+ luaL_openlib(L, 0, methods, 0);
+ lua_pop(L, 1);
+
+ lua_register(L, className, create_object);
+}
+
+const char LuaRaycast::className[] = "Raycast";
+const luaL_Reg LuaRaycast::methods[] =
+{
+ luamethod(LuaRaycast, next),
+ { 0, 0 }
+};
+
void LuaEmergeAreaCallback(v3s16 blockpos, EmergeAction action, void *param)
{
ScriptCallbackState *state = (ScriptCallbackState *)param;
{
GET_ENV_PTR;
- INodeDefManager *ndef = env->getGameDef()->ndef();
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
// parameters
v3s16 pos = read_v3s16(L, 1);
MapNode n = readnode(L, 2, ndef);
return 1;
}
+// bulk_set_node([pos1, pos2, ...], node)
+// pos = {x=num, y=num, z=num}
+int ModApiEnvMod::l_bulk_set_node(lua_State *L)
+{
+ GET_ENV_PTR;
+
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
+ // parameters
+ if (!lua_istable(L, 1)) {
+ return 0;
+ }
+
+ s32 len = lua_objlen(L, 1);
+ if (len == 0) {
+ lua_pushboolean(L, true);
+ return 1;
+ }
+
+ MapNode n = readnode(L, 2, ndef);
+
+ // Do it
+ bool succeeded = true;
+ for (s32 i = 1; i <= len; i++) {
+ lua_rawgeti(L, 1, i);
+ if (!env->setNode(read_v3s16(L, -1), n))
+ succeeded = false;
+ lua_pop(L, 1);
+ }
+
+ lua_pushboolean(L, succeeded);
+ return 1;
+}
+
int ModApiEnvMod::l_add_node(lua_State *L)
{
return l_set_node(L);
{
GET_ENV_PTR;
- INodeDefManager *ndef = env->getGameDef()->ndef();
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
// parameters
v3s16 pos = read_v3s16(L, 1);
MapNode n = readnode(L, 2, ndef);
bool is_position_ok;
MapNode n = env->getMap().getNodeNoEx(pos, &is_position_ok);
if (is_position_ok) {
- INodeDefManager *ndef = env->getGameDef()->ndef();
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
lua_pushinteger(L, n.getLightBlend(dnr, ndef));
} else {
lua_pushnil(L);
ScriptApiItem *scriptIfaceItem = getScriptApi<ScriptApiItem>(L);
Server *server = getServer(L);
- INodeDefManager *ndef = server->ndef();
+ const NodeDefManager *ndef = server->ndef();
IItemDefManager *idef = server->idef();
v3s16 pos = read_v3s16(L, 1);
pointed.type = POINTEDTHING_NODE;
pointed.node_abovesurface = pos;
pointed.node_undersurface = pos + v3s16(0,-1,0);
- // Place it with a NULL placer (appears in Lua as a non-functional
- // ObjectRef)
- bool success = scriptIfaceItem->item_OnPlace(item, NULL, pointed);
+ // Place it with a NULL placer (appears in Lua as nil)
+ bool success = scriptIfaceItem->item_OnPlace(item, nullptr, pointed);
lua_pushboolean(L, success);
return 1;
}
std::vector<u16>::const_iterator iter = ids.begin();
for(u32 i = 0; iter != ids.end(); ++iter) {
ServerActiveObject *obj = env->getActiveObject(*iter);
- // Insert object reference into table
- script->objectrefGetOrCreate(L, obj);
- lua_rawseti(L, -2, ++i);
+ if (!obj->isGone()) {
+ // Insert object reference into table
+ script->objectrefGetOrCreate(L, obj);
+ lua_rawseti(L, -2, ++i);
+ }
}
return 1;
}
return 0;
}
- INodeDefManager *ndef = getGameDef(L)->ndef();
+ const NodeDefManager *ndef = getGameDef(L)->ndef();
v3s16 pos = read_v3s16(L, 1);
int radius = luaL_checkinteger(L, 2);
- std::set<content_t> filter;
+ std::vector<content_t> filter;
if (lua_istable(L, 3)) {
lua_pushnil(L);
while (lua_next(L, 3) != 0) {
}
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 (std::vector<v3s16>::iterator i = list.begin();
- i != list.end(); ++i) {
- v3s16 p = pos + (*i);
+ for (const v3s16 &i : list) {
+ v3s16 p = pos + i;
content_t c = env->getMap().getNodeNoEx(p).getContent();
- if (filter.count(c) != 0) {
+ if (CONTAINS(filter, c)) {
push_v3s16(L, p);
return 1;
}
{
GET_ENV_PTR;
- INodeDefManager *ndef = getServer(L)->ndef();
+ const NodeDefManager *ndef = getServer(L)->ndef();
v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2);
sortBoxVerticies(minp, maxp);
return 0;
}
- std::set<content_t> filter;
+ std::vector<content_t> filter;
if (lua_istable(L, 3)) {
lua_pushnil(L);
while (lua_next(L, 3) != 0) {
ndef->getIds(lua_tostring(L, 3), filter);
}
- std::unordered_map<content_t, u32> individual_count;
+ std::vector<u32> individual_count;
+ individual_count.resize(filter.size());
lua_newtable(L);
u64 i = 0;
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) {
+
+ std::vector<content_t>::iterator it = std::find(filter.begin(), filter.end(), c);
+ if (it != filter.end()) {
push_v3s16(L, p);
lua_rawseti(L, -2, ++i);
- individual_count[c]++;
+
+ u32 filt_index = it - filter.begin();
+ individual_count[filt_index]++;
}
}
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());
+ for (u32 i = 0; i < filter.size(); i++) {
+ lua_pushnumber(L, individual_count[i]);
+ lua_setfield(L, -2, ndef->get(filter[i]).name.c_str());
}
return 2;
}
GET_ENV_PTR;
- INodeDefManager *ndef = getServer(L)->ndef();
+ const NodeDefManager *ndef = getServer(L)->ndef();
v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2);
sortBoxVerticies(minp, maxp);
return 0;
}
- std::set<content_t> filter;
+ std::vector<content_t> filter;
if (lua_istable(L, 3)) {
lua_pushnil(L);
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) {
+ CONTAINS(filter, c)) {
push_v3s16(L, v3s16(x, y, z));
lua_rawseti(L, -2, ++i);
}
{
GET_ENV_PTR;
- ClearObjectsMode mode = CLEAR_OBJECTS_MODE_FULL;
+ ClearObjectsMode mode = CLEAR_OBJECTS_MODE_QUICK;
if (lua_istable(L, 1)) {
mode = (ClearObjectsMode)getenumfield(L, 1, "mode",
ModApiEnvMod::es_ClearObjectsMode, mode);
return 0;
}
-// line_of_sight(pos1, pos2, stepsize) -> true/false, pos
+// line_of_sight(pos1, pos2) -> true/false, pos
int ModApiEnvMod::l_line_of_sight(lua_State *L)
{
- float stepsize = 1.0;
-
GET_ENV_PTR;
// read position 1 from lua
v3f pos1 = checkFloatPos(L, 1);
// read position 2 from lua
v3f pos2 = checkFloatPos(L, 2);
- //read step size from lua
- if (lua_isnumber(L, 3)) {
- stepsize = lua_tonumber(L, 3);
- }
v3s16 p;
- bool success = env->line_of_sight(pos1, pos2, stepsize, &p);
+
+ bool success = env->line_of_sight(pos1, pos2, &p);
lua_pushboolean(L, success);
if (!success) {
push_v3s16(L, p);
for (blockpos.Z = blockpos1.Z; blockpos.Z <= blockpos2.Z; blockpos.Z++) {
success = success & map.repairBlockLight(blockpos, &modified_blocks);
}
- if (modified_blocks.size() > 0) {
+ if (!modified_blocks.empty()) {
MapEditEvent event;
event.type = MEET_OTHER;
- for (std::map<v3s16, MapBlock *>::iterator it = modified_blocks.begin();
- it != modified_blocks.end(); ++it)
- event.modified_blocks.insert(it->first);
+ for (auto &modified_block : modified_blocks)
+ event.modified_blocks.insert(modified_block.first);
map.dispatchEvent(&event);
}
return 1;
}
+int ModApiEnvMod::l_raycast(lua_State *L)
+{
+ return LuaRaycast::create_object(L);
+}
+
// emerge_area(p1, p2, [callback, context])
// emerge mapblocks in area p1..p2, calls callback with context upon completion
int ModApiEnvMod::l_emerge_area(lua_State *L)
std::vector<v3s16> path = get_path(env, pos1, pos2,
searchdistance, max_jump, max_drop, algo);
- if (path.size() > 0)
- {
+ if (!path.empty()) {
lua_newtable(L);
int top = lua_gettop(L);
unsigned int index = 1;
- for (std::vector<v3s16>::iterator i = path.begin(); i != path.end(); ++i) {
+ for (const v3s16 &i : path) {
lua_pushnumber(L,index);
- push_v3s16(L, *i);
+ push_v3s16(L, i);
lua_settable(L, top);
index++;
}
treegen::TreeDef tree_def;
std::string trunk,leaves,fruit;
- INodeDefManager *ndef = env->getGameDef()->ndef();
+ const NodeDefManager *ndef = env->getGameDef()->ndef();
if(lua_istable(L, 2))
{
tree_def.leavesnode=ndef->getId(leaves);
tree_def.leaves2_chance=0;
getstringfield(L, 2, "leaves2", leaves);
- if (leaves !="")
- {
+ if (!leaves.empty()) {
tree_def.leaves2node=ndef->getId(leaves);
getintfield(L, 2, "leaves2_chance", tree_def.leaves2_chance);
}
getboolfield(L, 2, "thin_branches", tree_def.thin_branches);
tree_def.fruit_chance=0;
getstringfield(L, 2, "fruit", fruit);
- if (fruit != "")
- {
+ if (!fruit.empty()) {
tree_def.fruitnode=ndef->getId(fruit);
getintfield(L, 2, "fruit_chance",tree_def.fruit_chance);
}
void ModApiEnvMod::Initialize(lua_State *L, int top)
{
API_FCT(set_node);
+ API_FCT(bulk_set_node);
API_FCT(add_node);
API_FCT(swap_node);
API_FCT(add_item);
API_FCT(spawn_tree);
API_FCT(find_path);
API_FCT(line_of_sight);
+ API_FCT(raycast);
API_FCT(transforming_liquid_add);
API_FCT(forceload_block);
API_FCT(forceload_free_block);