diff --git a/doc/lua_api.txt b/doc/lua_api.txt index c7035bb7..c75800cf 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -5382,6 +5382,11 @@ This is basically a reference to a C++ `ServerActiveObject` * in first person view * in third person view (max. values `{x=-10/10,y=-10,15,z=-5/5}`) * `get_eye_offset()`: returns `offset_first` and `offset_third` +* `send_mapblock(blockpos)`: + * Sends a server-side loaded mapblock to the player. + * Returns `false` if failed. + * Resource intensive - use sparsely + * To get blockpos, integer divide pos by 16 `PcgRandom` ----------- diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 7acf0368..cefdeb59 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -1205,6 +1205,10 @@ void PlayerSAO::setPos(const v3f &pos) if(isAttached()) return; + // Send mapblock of target location + v3s16 blockpos = v3s16(pos.X / MAP_BLOCKSIZE, pos.Y / MAP_BLOCKSIZE, pos.Z / MAP_BLOCKSIZE); + m_env->getGameDef()->SendBlock(m_peer_id, blockpos); + setBasePosition(pos); // Movement caused by this command is always valid m_last_good_position = pos; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 2efcd894..b1f4e3da 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -584,6 +584,24 @@ int ObjectRef::l_get_eye_offset(lua_State *L) return 2; } +// send_mapblock(self, pos) +int ObjectRef::l_send_mapblock(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + + RemotePlayer *player = getplayer(ref); + if (!player) + return 0; + v3s16 p = read_v3s16(L, 2); + + session_t peer_id = player->getPeerId(); + bool r = getServer(L)->SendBlock(peer_id, p); + + lua_pushboolean(L, r); + return 1; +} + // set_animation_frame_speed(self, frame_speed) int ObjectRef::l_set_animation_frame_speed(lua_State *L) { @@ -1958,5 +1976,6 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, get_local_animation), luamethod(ObjectRef, set_eye_offset), luamethod(ObjectRef, get_eye_offset), + luamethod(ObjectRef, send_mapblock), {0,0} }; diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index c7d963d8..653d833f 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -351,4 +351,6 @@ private: // get_nametag_attributes(self) static int l_get_nametag_attributes(lua_State *L); + // send_mapblock(pos) + static int l_send_mapblock(lua_State *L); }; diff --git a/src/server.cpp b/src/server.cpp index 86949896..496170da 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2312,6 +2312,28 @@ void Server::SendBlocks(float dtime) m_clients.unlock(); } +bool Server::SendBlock(session_t peer_id, const v3s16 &blockpos) +{ + MapBlock *block = nullptr; + try { + block = m_env->getMap().getBlockNoCreate(blockpos); + } catch (InvalidPositionException &e) {}; + if (!block) + return false; + + m_clients.lock(); + RemoteClient *client = m_clients.lockedGetClientNoEx(peer_id, CS_Active); + if (!client || client->isBlockSent(blockpos)) { + m_clients.unlock(); + return false; + } + SendBlockNoLock(peer_id, block, client->serialization_version, + client->net_proto_version); + m_clients.unlock(); + + return true; +} + void Server::fillMediaCache() { infostream<<"Server: Calculating media file checksums"<