+ v3s16 p;
+ bool success = env->line_of_sight(pos1, pos2, stepsize, &p);
+ lua_pushboolean(L, success);
+ if (!success) {
+ push_v3s16(L, p);
+ return 2;
+ }
+ return 1;
+}
+
+// fix_light(p1, p2)
+int ModApiEnvMod::l_fix_light(lua_State *L)
+{
+ GET_ENV_PTR;
+
+ v3s16 blockpos1 = getContainerPos(read_v3s16(L, 1), MAP_BLOCKSIZE);
+ v3s16 blockpos2 = getContainerPos(read_v3s16(L, 2), MAP_BLOCKSIZE);
+ ServerMap &map = env->getServerMap();
+ std::map<v3s16, MapBlock *> modified_blocks;
+ bool success = true;
+ v3s16 blockpos;
+ for (blockpos.X = blockpos1.X; blockpos.X <= blockpos2.X; blockpos.X++)
+ for (blockpos.Y = blockpos1.Y; blockpos.Y <= blockpos2.Y; blockpos.Y++)
+ for (blockpos.Z = blockpos1.Z; blockpos.Z <= blockpos2.Z; blockpos.Z++) {
+ success = success & map.repairBlockLight(blockpos, &modified_blocks);
+ }
+ if (modified_blocks.size() > 0) {
+ 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);
+
+ map.dispatchEvent(&event);
+ }
+ lua_pushboolean(L, success);
+
+ return 1;
+}
+
+// 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)
+{
+ GET_ENV_PTR;
+
+ EmergeCompletionCallback callback = NULL;
+ ScriptCallbackState *state = NULL;
+
+ EmergeManager *emerge = getServer(L)->getEmergeManager();
+
+ v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1));
+ v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2));
+ sortBoxVerticies(bpmin, bpmax);
+
+ size_t num_blocks = VoxelArea(bpmin, bpmax).getVolume();
+ assert(num_blocks != 0);
+
+ if (lua_isfunction(L, 3)) {
+ callback = LuaEmergeAreaCallback;
+
+ lua_pushvalue(L, 3);
+ int callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ lua_pushvalue(L, 4);
+ int args_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ state = new ScriptCallbackState;
+ state->script = getServer(L)->getScriptIface();
+ state->callback_ref = callback_ref;
+ state->args_ref = args_ref;
+ state->refcount = num_blocks;
+ state->origin = getScriptApiBase(L)->getOrigin();
+ }
+
+ for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
+ for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
+ for (s16 x = bpmin.X; x <= bpmax.X; x++) {
+ emerge->enqueueBlockEmergeEx(v3s16(x, y, z), PEER_ID_INEXISTENT,
+ BLOCK_EMERGE_ALLOW_GEN | BLOCK_EMERGE_FORCE_QUEUE, callback, state);
+ }
+
+ return 0;
+}
+
+// delete_area(p1, p2)
+// delete mapblocks in area p1..p2
+int ModApiEnvMod::l_delete_area(lua_State *L)
+{
+ GET_ENV_PTR;
+
+ v3s16 bpmin = getNodeBlockPos(read_v3s16(L, 1));
+ v3s16 bpmax = getNodeBlockPos(read_v3s16(L, 2));
+ sortBoxVerticies(bpmin, bpmax);
+
+ ServerMap &map = env->getServerMap();
+
+ MapEditEvent event;
+ event.type = MEET_OTHER;
+
+ bool success = true;
+ for (s16 z = bpmin.Z; z <= bpmax.Z; z++)
+ for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
+ for (s16 x = bpmin.X; x <= bpmax.X; x++) {
+ v3s16 bp(x, y, z);
+ if (map.deleteBlock(bp)) {
+ env->setStaticForActiveObjectsInBlock(bp, false);
+ event.modified_blocks.insert(bp);
+ } else {
+ success = false;
+ }
+ }
+
+ map.dispatchEvent(&event);
+ lua_pushboolean(L, success);