// Applies pending updates and sends them to players (if applicable).
internal void ProcessUpdates()
{
if (World == null)
{
throw new InvalidOperationException("Map must be assigned to a world to process updates.");
}
if (World.IsLocked)
{
if (World.IsPendingMapUnload)
{
World.UnloadMap(true);
}
return;
}
int packetsSent = 0;
bool canFlush = false;
int maxPacketsPerUpdate = Server.CalculateMaxPacketsPerUpdate(World);
while (packetsSent < maxPacketsPerUpdate)
{
BlockUpdate update;
if (!updates.TryDequeue(out update))
{
if (World.IsFlushing)
{
canFlush = true;
}
break;
}
if (!InBounds(update.X, update.Y, update.Z))
{
continue;
}
int blockIndex = Index(update.X, update.Y, update.Z);
Blocks[blockIndex] = (byte)update.BlockType;
if (!World.IsFlushing)
{
//non classicube players get fallbacks instead of the real blocks
Packet packet = PacketWriter.MakeSetBlock(update.X, update.Y, update.Z, update.BlockType);
Packet fallback = PacketWriter.MakeSetBlock(update.X, update.Y, update.Z, Map.GetFallbackBlock(update.BlockType));
// Not using World.Players.Where(x => usesCpe) here to avoid memory allocations
Player[] players = World.Players;
for (int i = 0; i < players.Length; i++)
{
Player p = players[i];
if (p.UsesCustomBlocks)
{
p.SendLowPriority(packet);
}
else
{
p.SendLowPriority(fallback);
}
}
}
packetsSent++;
}
if (drawOps.Count > 0)
{
lock ( drawOpLock ) {
if (drawOps.Count > 0)
{
packetsSent += ProcessDrawOps(maxPacketsPerUpdate - packetsSent);
}
}
}
else if (canFlush)
{
World.EndFlushMapBuffer();
}
if (packetsSent == 0 && World.IsPendingMapUnload)
{
World.UnloadMap(true);
}
}