Basically, the method PlayerChunkMapEntry.sendToPlayers()
is sometimes called on an entry while it contains no players.
The end of that method looks like this:
else
{
this.changes = 0;
this.changedSectionFilter = 0;
this.sentToPlayers = true;
Packet<?> packet = new SPacketChunkData(this.chunk, 65535);
for (EntityPlayerMP entityplayermp : this.players)
{
entityplayermp.connection.sendPacket(packet);
this.playerChunkMap.getWorldServer().getEntityTracker().sendLeashedEntitiesInChunk(entityplayermp, this.chunk);
}
return true;
}
When that code is run, the SPacketChunkData
packet is created even if the list players
is empty at this point and the packet is not actually needed.
As creating the packet here involves reading all the data for a chunk, including block entity data, it's better to avoid doing so unnecessarily.
The issue can be easily resolved by adding a check to the method like so:
else
{
this.changes = 0;
this.changedSectionFilter = 0;
this.sentToPlayers = true;
if (!this.players.isEmpty())
{
Packet<?> packet = new SPacketChunkData(this.chunk, 65535);
for (EntityPlayerMP entityplayermp : this.players)
{
entityplayermp.connection.sendPacket(packet);
this.playerChunkMap.getWorldServer().getEntityTracker().sendLeashedEntitiesInChunk(entityplayermp, this.chunk);
}
}
return true;
}
Attachments
Comments 3
which you attached looks like good evidence of this happening to me, thanks.
The same optimization could probably also be applied to PlayerChunkMapEntry.update
since that can also create packets when there are no players. (n.b. that also creates a SPacketChunkData
, but that's used to change resend single chunk sections, not whole chunk columns, so I'd say it's not as much of a performance issue).
As for code where this can happen, sendToPlayers
is called by PlayerChunkMap#getOrCreateEntry
if it creates a new entry (as there's no existing one). As the entry has just been created, it has no players attached to it yet.
Then, provided the chunk was successfully loaded, and is a chunk that has previously been populated, the situation described can occur.
I'm not completely familiar with this part of the code. Are you sure that this can actually end up happening (i.e. have actually confirmed it via logging something when it happens or such)?