Skip to content
Permalink
Browse files

Send ActiveObjects once right after Init2

  • Loading branch information
ClobberXD authored and sfan5 committed Aug 25, 2019
1 parent 9acd36b commit 81c7f0ae044b1131ad082e5e705c5276f82ac6ce
Showing with 141 additions and 119 deletions.
  1. +8 −2 src/client/client.cpp
  2. +3 −0 src/client/client.h
  3. +4 −0 src/network/clientpackethandler.cpp
  4. +19 −7 src/network/serverpackethandler.cpp
  5. +106 −109 src/server.cpp
  6. +1 −1 src/server.h
@@ -1243,8 +1243,14 @@ void Client::sendPlayerPos()
u8 camera_fov = map.getCameraFov();
u8 wanted_range = map.getControl().wanted_range;

// Save bandwidth by only updating position when something changed
if(myplayer->last_position == myplayer->getPosition() &&
// Save bandwidth by only updating position when
// player is not dead and something changed

if (m_activeobjects_received && myplayer->isDead())
return;

if (
myplayer->last_position == myplayer->getPosition() &&
myplayer->last_speed == myplayer->getSpeed() &&
myplayer->last_pitch == myplayer->getPitch() &&
myplayer->last_yaw == myplayer->getYaw() &&
@@ -339,6 +339,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
{ return m_nodedef_received; }
bool mediaReceived()
{ return !m_media_downloader; }
const bool activeObjectsReceived() const
{ return m_activeobjects_received; }

u16 getProtoVersion()
{ return m_proto_ver; }
@@ -539,6 +541,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
std::queue<ClientEvent *> m_client_event_queue;
bool m_itemdef_received = false;
bool m_nodedef_received = false;
bool m_activeobjects_received = false;
bool m_mods_loaded = false;
ClientMediaDownloader *m_media_downloader;

@@ -463,6 +463,10 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
<< ". The packet is unreliable, ignoring" << std::endl;
}

// m_activeobjects_received is false before the first
// TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD packet is received
m_activeobjects_received = true;
}

void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
@@ -298,9 +298,6 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
infostream << "Server: Sending content to "
<< getPlayerName(pkt->getPeerId()) << std::endl;

// Send player movement settings
SendMovement(pkt->getPeerId());

// Send item definitions
SendItemDef(pkt->getPeerId(), m_itemdef, protocol_version);

@@ -312,9 +309,25 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
// Send media announcement
sendMediaAnnouncement(pkt->getPeerId(), lang);

RemoteClient *client;
{
MutexAutoLock(m_con);
client = getClient(pkt->getPeerId(), CS_InitDone);
}

// Send active objects
{
PlayerSAO *sao = getPlayerSAO(pkt->getPeerId());
if (client && sao)
SendActiveObjectRemoveAdd(client, sao);
}

// Send detached inventories
sendDetachedInventories(pkt->getPeerId(), false);

// Send player movement settings
SendMovement(pkt->getPeerId());

// Send time of day
u16 time = m_env->getTimeOfDay();
float time_speed = g_settings->getFloat("time_speed");
@@ -323,11 +336,10 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
SendCSMRestrictionFlags(pkt->getPeerId());

// Warnings about protocol version can be issued here
if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) {
if (client->net_proto_version < LATEST_PROTOCOL_VERSION) {
SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM,
L"# Server: WARNING: YOUR CLIENT'S VERSION MAY NOT BE FULLY COMPATIBLE "
L"WITH THIS SERVER!"));

L"# Server: WARNING: YOUR CLIENT'S VERSION MAY NOT BE FULLY COMPATIBLE "
L"WITH THIS SERVER!"));
}
}

@@ -620,124 +620,27 @@ void Server::AsyncRunStep(bool initial_step)

m_clients.lock();
const RemoteClientMap &clients = m_clients.getClientList();
ScopeProfiler sp(g_profiler, "Server: update visible objects");

// Radius inside which objects are active
static thread_local const s16 radius =
g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;

// Radius inside which players are active
static thread_local const bool is_transfer_limited =
g_settings->exists("unlimited_player_transfer_distance") &&
!g_settings->getBool("unlimited_player_transfer_distance");
static thread_local const s16 player_transfer_dist =
g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
s16 player_radius = player_transfer_dist;
if (player_radius == 0 && is_transfer_limited)
player_radius = radius;
ScopeProfiler sp(g_profiler, "Server: update objects within range");

for (const auto &client_it : clients) {
RemoteClient *client = client_it.second;

// If definitions and textures have not been sent, don't
// send objects either
if (client->getState() < CS_DefinitionsSent)
continue;

RemotePlayer *player = m_env->getPlayer(client->peer_id);
if (!player) {
// This can happen if the client timeouts somehow
// This can happen if the client times out somehow
if (!m_env->getPlayer(client->peer_id))
continue;
}

PlayerSAO *playersao = player->getPlayerSAO();
PlayerSAO *playersao = getPlayerSAO(client->peer_id);
if (!playersao)
continue;

s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
if (my_radius <= 0) my_radius = radius;
//infostream << "Server: Active Radius " << my_radius << std::endl;

std::queue<u16> removed_objects;
std::queue<u16> added_objects;
m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
client->m_known_objects, removed_objects);
m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
client->m_known_objects, added_objects);

// Ignore if nothing happened
if (removed_objects.empty() && added_objects.empty()) {
continue;
}

std::string data_buffer;

char buf[4];

// Handle removed objects
writeU16((u8*)buf, removed_objects.size());
data_buffer.append(buf, 2);
while (!removed_objects.empty()) {
// Get object
u16 id = removed_objects.front();
ServerActiveObject* obj = m_env->getActiveObject(id);

// Add to data buffer for sending
writeU16((u8*)buf, id);
data_buffer.append(buf, 2);

// Remove from known objects
client->m_known_objects.erase(id);

if(obj && obj->m_known_by_count > 0)
obj->m_known_by_count--;
removed_objects.pop();
}

// Handle added objects
writeU16((u8*)buf, added_objects.size());
data_buffer.append(buf, 2);
while (!added_objects.empty()) {
// Get object
u16 id = added_objects.front();
ServerActiveObject* obj = m_env->getActiveObject(id);

// Get object type
u8 type = ACTIVEOBJECT_TYPE_INVALID;
if (!obj)
warningstream << FUNCTION_NAME << ": NULL object" << std::endl;
else
type = obj->getSendType();

// Add to data buffer for sending
writeU16((u8*)buf, id);
data_buffer.append(buf, 2);
writeU8((u8*)buf, type);
data_buffer.append(buf, 1);

if(obj)
data_buffer.append(serializeLongString(
obj->getClientInitializationData(client->net_proto_version)));
else
data_buffer.append(serializeLongString(""));

// Add to known objects
client->m_known_objects.insert(id);

if(obj)
obj->m_known_by_count++;

added_objects.pop();
}

u32 pktSize = SendActiveObjectRemoveAdd(client->peer_id, data_buffer);
verbosestream << "Server: Sent object remove/add: "
<< removed_objects.size() << " removed, "
<< added_objects.size() << " added, "
<< "packet size is " << pktSize << std::endl;
SendActiveObjectRemoveAdd(client, playersao);
}
m_clients.unlock();

// Save mod storages if modified
m_mod_storage_save_timer -= dtime;
if (m_mod_storage_save_timer <= 0.0f) {
infostream << "Saving registered mod storages." << std::endl;
@@ -1089,9 +992,9 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
return playersao;
}

inline void Server::handleCommand(NetworkPacket* pkt)
inline void Server::handleCommand(NetworkPacket *pkt)
{
const ToServerCommandHandler& opHandle = toServerCommandTable[pkt->getCommand()];
const ToServerCommandHandler &opHandle = toServerCommandTable[pkt->getCommand()];
(this->*opHandle.handler)(pkt);
}

@@ -1925,12 +1828,106 @@ void Server::SendPlayerFormspecPrepend(session_t peer_id)
Send(&pkt);
}

u32 Server::SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas)
void Server::SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao)
{
NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
pkt.putRawString(datas.c_str(), datas.size());
// Radius inside which objects are active
static thread_local const s16 radius =
g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;

// Radius inside which players are active
static thread_local const bool is_transfer_limited =
g_settings->exists("unlimited_player_transfer_distance") &&
!g_settings->getBool("unlimited_player_transfer_distance");

static thread_local const s16 player_transfer_dist =
g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;

s16 player_radius = player_transfer_dist == 0 && is_transfer_limited ?
radius : player_transfer_dist;

s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
if (my_radius <= 0)
my_radius = radius;

std::queue<u16> removed_objects, added_objects;
m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
client->m_known_objects, removed_objects);
m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
client->m_known_objects, added_objects);

int removed_count = removed_objects.size();
int added_count = added_objects.size();

if (removed_objects.empty() && added_objects.empty())
return;

char buf[4];
std::string data;

// Handle removed objects
writeU16((u8*)buf, removed_objects.size());
data.append(buf, 2);
while (!removed_objects.empty()) {
// Get object
u16 id = removed_objects.front();
ServerActiveObject* obj = m_env->getActiveObject(id);

// Add to data buffer for sending
writeU16((u8*)buf, id);
data.append(buf, 2);

// Remove from known objects
client->m_known_objects.erase(id);

if (obj && obj->m_known_by_count > 0)
obj->m_known_by_count--;

removed_objects.pop();
}

// Handle added objects
writeU16((u8*)buf, added_objects.size());
data.append(buf, 2);
while (!added_objects.empty()) {
// Get object
u16 id = added_objects.front();
ServerActiveObject* obj = m_env->getActiveObject(id);

// Get object type
u8 type = ACTIVEOBJECT_TYPE_INVALID;
if (!obj)
warningstream << FUNCTION_NAME << ": NULL object" << std::endl;
else
type = obj->getSendType();

// Add to data buffer for sending
writeU16((u8*)buf, id);
data.append(buf, 2);
writeU8((u8*)buf, type);
data.append(buf, 1);

if (obj)
data.append(serializeLongString(
obj->getClientInitializationData(client->net_proto_version)));
else
data.append(serializeLongString(""));

// Add to known objects
client->m_known_objects.insert(id);

if (obj)
obj->m_known_by_count++;

added_objects.pop();
}

NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, data.size(), client->peer_id);
pkt.putRawString(data.c_str(), data.size());
Send(&pkt);
return pkt.getSize();

verbosestream << "Server::SendActiveObjectRemoveAdd: "
<< removed_count << " removed, " << added_count << " added, "
<< "packet size is " << pkt.getSize() << std::endl;
}

void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
@@ -469,7 +469,7 @@ class Server : public con::PeerHandler, public MapEventReceiver,
bool vertical, const std::string &texture,
const struct TileAnimationParams &animation, u8 glow);

u32 SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas);
void SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao);
void SendActiveObjectMessages(session_t peer_id, const std::string &datas,
bool reliable = true);
void SendCSMRestrictionFlags(session_t peer_id);

0 comments on commit 81c7f0a

Please sign in to comment.
You can’t perform that action at this time.