summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt5
-rw-r--r--src/content_sao.cpp4
-rw-r--r--src/script/lua_api/l_object.cpp19
-rw-r--r--src/script/lua_api/l_object.h2
-rw-r--r--src/server.cpp22
-rw-r--r--src/server.h3
6 files changed, 55 insertions, 0 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index c7035bb72..c75800cf4 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 7acf03684..cefdeb597 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 2efcd894a..b1f4e3da5 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 c7d963d87..653d833f6 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 869498965..496170da3 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"<<std::endl;
diff --git a/src/server.h b/src/server.h
index 5949d9bf1..5e58ac9e6 100644
--- a/src/server.h
+++ b/src/server.h
@@ -344,6 +344,9 @@ public:
bool sendModChannelMessage(const std::string &channel, const std::string &message);
ModChannel *getModChannel(const std::string &channel);
+ // Send block to specific player only
+ bool SendBlock(session_t peer_id, const v3s16 &blockpos);
+
// Bind address
Address m_bind_addr;