Use a dedicated thread to process world data (#1585)

This change allow low-end devices to join servers without timeout
This commit is contained in:
ReinforceZwei 2021-05-13 02:07:53 +08:00 committed by GitHub
parent 3b5488a7bf
commit 9e5364a4ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 13 deletions

View file

@ -699,6 +699,7 @@ namespace MinecraftClient
/// Schedule a task to run on the main thread /// Schedule a task to run on the main thread
/// </summary> /// </summary>
/// <param name="task">Task to run</param> /// <param name="task">Task to run</param>
/// <returns>Any result returned from delegate</returns>
public object ScheduleTask(Delegate task) public object ScheduleTask(Delegate task)
{ {
if (!InvokeRequired()) if (!InvokeRequired())

View file

@ -18,6 +18,7 @@ using System.Diagnostics;
using MinecraftClient.Inventory.ItemPalettes; using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.PacketPalettes; using MinecraftClient.Protocol.Handlers.PacketPalettes;
using MinecraftClient.Logger; using MinecraftClient.Logger;
using System.Threading.Tasks;
namespace MinecraftClient.Protocol.Handlers namespace MinecraftClient.Protocol.Handlers
{ {
@ -422,7 +423,10 @@ namespace MinecraftClient.Protocol.Handlers
int compressedDataSize = dataTypes.ReadNextInt(packetData); int compressedDataSize = dataTypes.ReadNextInt(packetData);
byte[] compressed = dataTypes.ReadData(compressedDataSize, packetData); byte[] compressed = dataTypes.ReadData(compressedDataSize, packetData);
byte[] decompressed = ZlibUtils.Decompress(compressed); byte[] decompressed = ZlibUtils.Decompress(compressed);
pTerrain.ProcessChunkColumnData(chunkX, chunkZ, chunkMask, addBitmap, currentDimension == 0, chunksContinuous, currentDimension, new Queue<byte>(decompressed)); new Task(new Action(() =>
{
pTerrain.ProcessChunkColumnData(chunkX, chunkZ, chunkMask, addBitmap, currentDimension == 0, chunksContinuous, currentDimension, new Queue<byte>(decompressed));
})).Start();
} }
else else
{ {
@ -446,7 +450,10 @@ namespace MinecraftClient.Protocol.Handlers
else dataTypes.ReadData(1024 * 4, packetData); // Biomes - 1.15 and above else dataTypes.ReadData(1024 * 4, packetData); // Biomes - 1.15 and above
} }
int dataSize = dataTypes.ReadNextVarInt(packetData); int dataSize = dataTypes.ReadNextVarInt(packetData);
pTerrain.ProcessChunkColumnData(chunkX, chunkZ, chunkMask, 0, false, chunksContinuous, currentDimension, packetData); new Task(new Action(() =>
{
pTerrain.ProcessChunkColumnData(chunkX, chunkZ, chunkMask, 0, false, chunksContinuous, currentDimension, packetData);
})).Start();
} }
} }
break; break;

View file

@ -162,9 +162,12 @@ namespace MinecraftClient.Protocol.Handlers
} }
//We have our chunk, save the chunk into the world //We have our chunk, save the chunk into the world
if (handler.GetWorld()[chunkX, chunkZ] == null) handler.ScheduleTask(new Action(() =>
handler.GetWorld()[chunkX, chunkZ] = new ChunkColumn(); {
handler.GetWorld()[chunkX, chunkZ][chunkY] = chunk; if (handler.GetWorld()[chunkX, chunkZ] == null)
handler.GetWorld()[chunkX, chunkZ] = new ChunkColumn();
handler.GetWorld()[chunkX, chunkZ][chunkY] = chunk;
}));
//Pre-1.14 Lighting data //Pre-1.14 Lighting data
if (protocolversion < Protocol18Handler.MC114Version) if (protocolversion < Protocol18Handler.MC114Version)
@ -189,7 +192,10 @@ namespace MinecraftClient.Protocol.Handlers
if (chunksContinuous && chunkMask == 0) if (chunksContinuous && chunkMask == 0)
{ {
//Unload the entire chunk column //Unload the entire chunk column
handler.GetWorld()[chunkX, chunkZ] = null; handler.ScheduleTask(new Action(() =>
{
handler.GetWorld()[chunkX, chunkZ] = null;
}));
} }
else else
{ {
@ -208,9 +214,12 @@ namespace MinecraftClient.Protocol.Handlers
chunk[blockX, blockY, blockZ] = new Block(queue.Dequeue()); chunk[blockX, blockY, blockZ] = new Block(queue.Dequeue());
//We have our chunk, save the chunk into the world //We have our chunk, save the chunk into the world
if (handler.GetWorld()[chunkX, chunkZ] == null) handler.ScheduleTask(new Action(() =>
handler.GetWorld()[chunkX, chunkZ] = new ChunkColumn(); {
handler.GetWorld()[chunkX, chunkZ][chunkY] = chunk; if (handler.GetWorld()[chunkX, chunkZ] == null)
handler.GetWorld()[chunkX, chunkZ] = new ChunkColumn();
handler.GetWorld()[chunkX, chunkZ][chunkY] = chunk;
}));
} }
} }
@ -239,7 +248,10 @@ namespace MinecraftClient.Protocol.Handlers
if (chunksContinuous && chunkMask == 0) if (chunksContinuous && chunkMask == 0)
{ {
//Unload the entire chunk column //Unload the entire chunk column
handler.GetWorld()[chunkX, chunkZ] = null; handler.ScheduleTask(new Action(() =>
{
handler.GetWorld()[chunkX, chunkZ] = null;
}));
} }
else else
{ {
@ -285,9 +297,12 @@ namespace MinecraftClient.Protocol.Handlers
for (int blockX = 0; blockX < Chunk.SizeX; blockX++) for (int blockX = 0; blockX < Chunk.SizeX; blockX++)
chunk[blockX, blockY, blockZ] = new Block(blockTypes.Dequeue(), blockMeta.Dequeue()); chunk[blockX, blockY, blockZ] = new Block(blockTypes.Dequeue(), blockMeta.Dequeue());
if (handler.GetWorld()[chunkX, chunkZ] == null) handler.ScheduleTask(new Action(() =>
handler.GetWorld()[chunkX, chunkZ] = new ChunkColumn(); {
handler.GetWorld()[chunkX, chunkZ][chunkY] = chunk; if (handler.GetWorld()[chunkX, chunkZ] == null)
handler.GetWorld()[chunkX, chunkZ] = new ChunkColumn();
handler.GetWorld()[chunkX, chunkZ][chunkY] = chunk;
}));
} }
} }
} }

View file

@ -40,6 +40,13 @@ namespace MinecraftClient.Protocol
Container GetInventory(int inventoryID); Container GetInventory(int inventoryID);
ILogger GetLogger(); ILogger GetLogger();
/// <summary>
/// Schedule a task to run on the main thread
/// </summary>
/// <param name="task">Task to run</param>
/// <returns>Any result returned from delegate</returns>
object ScheduleTask(Delegate task);
/// <summary> /// <summary>
/// Called when a network packet received or sent /// Called when a network packet received or sent
/// </summary> /// </summary>