No longer need to cancel chunk loading

This commit is contained in:
BruceChen 2022-08-30 19:09:07 +08:00
parent e4c77b0fef
commit aceccaf5b5
4 changed files with 12 additions and 66 deletions

View file

@ -61,7 +61,6 @@ namespace MinecraftClient
private float playerYaw; private float playerYaw;
private float playerPitch; private float playerPitch;
private double motionY; private double motionY;
private CancellationTokenSource chunkProcessCancelSource = new();
public enum MovementType { Sneak, Walk, Sprint} public enum MovementType { Sneak, Walk, Sprint}
public int currentMovementSpeed = 4; public int currentMovementSpeed = 4;
private int sequenceId; // User for player block synchronization (Aka. digging, placing blocks, etc..) private int sequenceId; // User for player block synchronization (Aka. digging, placing blocks, etc..)
@ -113,7 +112,6 @@ namespace MinecraftClient
public int GetSequenceId() { return sequenceId; } public int GetSequenceId() { return sequenceId; }
public float GetPitch() { return playerPitch; } public float GetPitch() { return playerPitch; }
public World GetWorld() { return world; } public World GetWorld() { return world; }
public CancellationToken GetChunkProcessCancelToken() { return chunkProcessCancelSource.Token; }
public Double GetServerTPS() { return averageTPS; } public Double GetServerTPS() { return averageTPS; }
public bool GetIsSupportPreviewsChat() { return isSupportPreviewsChat; } public bool GetIsSupportPreviewsChat() { return isSupportPreviewsChat; }
public float GetHealth() { return playerHealth; } public float GetHealth() { return playerHealth; }
@ -478,9 +476,7 @@ namespace MinecraftClient
/// </summary> /// </summary>
public void OnConnectionLost(ChatBot.DisconnectReason reason, string message) public void OnConnectionLost(ChatBot.DisconnectReason reason, string message)
{ {
chunkProcessCancelSource.Cancel();
world.Clear(); world.Clear();
chunkProcessCancelSource = new();
if (timeoutdetector != null) if (timeoutdetector != null)
{ {
@ -908,9 +904,7 @@ namespace MinecraftClient
terrainAndMovementsEnabled = false; terrainAndMovementsEnabled = false;
terrainAndMovementsRequested = false; terrainAndMovementsRequested = false;
locationReceived = false; locationReceived = false;
chunkProcessCancelSource.Cancel();
world.Clear(); world.Clear();
chunkProcessCancelSource = new();
} }
return true; return true;
} }
@ -1951,9 +1945,7 @@ namespace MinecraftClient
if (terrainAndMovementsEnabled) if (terrainAndMovementsEnabled)
{ {
chunkProcessCancelSource.Cancel();
world.Clear(); world.Clear();
chunkProcessCancelSource = new();
} }
entities.Clear(); entities.Clear();

View file

@ -538,8 +538,6 @@ namespace MinecraftClient.Protocol.Handlers
case PacketTypesIn.ChunkData: case PacketTypesIn.ChunkData:
if (handler.GetTerrainEnabled()) if (handler.GetTerrainEnabled())
{ {
CancellationToken cancellationToken = handler.GetChunkProcessCancelToken();
Interlocked.Increment(ref handler.GetWorld().chunkCnt); Interlocked.Increment(ref handler.GetWorld().chunkCnt);
Interlocked.Increment(ref handler.GetWorld().chunkLoadNotCompleted); Interlocked.Increment(ref handler.GetWorld().chunkLoadNotCompleted);
@ -563,8 +561,8 @@ namespace MinecraftClient.Protocol.Handlers
int dataSize = dataTypes.ReadNextVarInt(packetData); // Size int dataSize = dataTypes.ReadNextVarInt(packetData); // Size
if (pTerrain.ProcessChunkColumnData(chunkX, chunkZ, verticalStripBitmask, packetData, cancellationToken)) pTerrain.ProcessChunkColumnData(chunkX, chunkZ, verticalStripBitmask, packetData);
Interlocked.Decrement(ref handler.GetWorld().chunkLoadNotCompleted); Interlocked.Decrement(ref handler.GetWorld().chunkLoadNotCompleted);
// Block Entity data: ignored // Block Entity data: ignored
// Light data: ignored // Light data: ignored
@ -584,8 +582,8 @@ namespace MinecraftClient.Protocol.Handlers
byte[] compressed = dataTypes.ReadData(compressedDataSize, packetData); byte[] compressed = dataTypes.ReadData(compressedDataSize, packetData);
byte[] decompressed = ZlibUtils.Decompress(compressed); byte[] decompressed = ZlibUtils.Decompress(compressed);
if (pTerrain.ProcessChunkColumnData(chunkX, chunkZ, chunkMask, addBitmap, currentDimension == 0, chunksContinuous, currentDimension, new Queue<byte>(decompressed), cancellationToken)) pTerrain.ProcessChunkColumnData(chunkX, chunkZ, chunkMask, addBitmap, currentDimension == 0, chunksContinuous, currentDimension, new Queue<byte>(decompressed));
Interlocked.Decrement(ref handler.GetWorld().chunkLoadNotCompleted); Interlocked.Decrement(ref handler.GetWorld().chunkLoadNotCompleted);
} }
else else
{ {
@ -610,8 +608,8 @@ namespace MinecraftClient.Protocol.Handlers
} }
int dataSize = dataTypes.ReadNextVarInt(packetData); int dataSize = dataTypes.ReadNextVarInt(packetData);
if (pTerrain.ProcessChunkColumnData(chunkX, chunkZ, chunkMask, 0, false, chunksContinuous, currentDimension, packetData, cancellationToken)) pTerrain.ProcessChunkColumnData(chunkX, chunkZ, chunkMask, 0, false, chunksContinuous, currentDimension, packetData);
Interlocked.Decrement(ref handler.GetWorld().chunkLoadNotCompleted); Interlocked.Decrement(ref handler.GetWorld().chunkLoadNotCompleted);
} }
} }
} }
@ -829,8 +827,6 @@ namespace MinecraftClient.Protocol.Handlers
case PacketTypesIn.MapChunkBulk: case PacketTypesIn.MapChunkBulk:
if (protocolversion < MC_1_9_Version && handler.GetTerrainEnabled()) if (protocolversion < MC_1_9_Version && handler.GetTerrainEnabled())
{ {
CancellationToken cancellationToken = handler.GetChunkProcessCancelToken();
int chunkCount; int chunkCount;
bool hasSkyLight; bool hasSkyLight;
Queue<byte> chunkData = packetData; Queue<byte> chunkData = packetData;
@ -867,17 +863,11 @@ namespace MinecraftClient.Protocol.Handlers
} }
//Process chunk records //Process chunk records
Parallel.Invoke(() => for (int chunkColumnNo = 0; chunkColumnNo < chunkCount; chunkColumnNo++)
{ {
for (int chunkColumnNo = 0; chunkColumnNo < chunkCount; chunkColumnNo++) pTerrain.ProcessChunkColumnData(chunkXs[chunkColumnNo], chunkZs[chunkColumnNo], chunkMasks[chunkColumnNo], addBitmaps[chunkColumnNo], hasSkyLight, true, currentDimension, chunkData);
{ Interlocked.Decrement(ref handler.GetWorld().chunkLoadNotCompleted);
if (cancellationToken.IsCancellationRequested) }
break;
bool loaded = pTerrain.ProcessChunkColumnData(chunkXs[chunkColumnNo], chunkZs[chunkColumnNo], chunkMasks[chunkColumnNo], addBitmaps[chunkColumnNo], hasSkyLight, true, currentDimension, chunkData, cancellationToken);
if (loaded)
Interlocked.Decrement(ref handler.GetWorld().chunkLoadNotCompleted);
}
});
} }
break; break;

View file

@ -148,13 +148,9 @@ namespace MinecraftClient.Protocol.Handlers
/// <param name="verticalStripBitmask">Chunk mask for reading data, store in bitset, used in 1.17 and 1.17.1</param> /// <param name="verticalStripBitmask">Chunk mask for reading data, store in bitset, used in 1.17 and 1.17.1</param>
/// <param name="cache">Cache for reading chunk data</param> /// <param name="cache">Cache for reading chunk data</param>
/// <param name="cancellationToken">token to cancel the task</param> /// <param name="cancellationToken">token to cancel the task</param>
/// <returns>true if successfully loaded</returns>
[MethodImpl(MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool ProcessChunkColumnData(int chunkX, int chunkZ, ulong[]? verticalStripBitmask, Queue<byte> cache, CancellationToken cancellationToken) public void ProcessChunkColumnData(int chunkX, int chunkZ, ulong[]? verticalStripBitmask, Queue<byte> cache)
{ {
if (cancellationToken.IsCancellationRequested)
return false;
World world = handler.GetWorld(); World world = handler.GetWorld();
int chunkColumnSize = (World.GetDimension().height + 15) / 16; // Round up int chunkColumnSize = (World.GetDimension().height + 15) / 16; // Round up
@ -184,9 +180,6 @@ namespace MinecraftClient.Protocol.Handlers
lastChunkY = chunkColumnSize - 1; lastChunkY = chunkColumnSize - 1;
} }
if (cancellationToken.IsCancellationRequested)
return false;
// 1.18 and above always contains all chunk section in data // 1.18 and above always contains all chunk section in data
// 1.17 and 1.17.1 need vertical strip bitmask to know if the chunk section is included // 1.17 and 1.17.1 need vertical strip bitmask to know if the chunk section is included
if ((protocolversion >= Protocol18Handler.MC_1_18_1_Version) || if ((protocolversion >= Protocol18Handler.MC_1_18_1_Version) ||
@ -198,10 +191,6 @@ namespace MinecraftClient.Protocol.Handlers
// Read Block states (Type: Paletted Container) // Read Block states (Type: Paletted Container)
Chunk? chunk = ReadBlockStatesField(cache); Chunk? chunk = ReadBlockStatesField(cache);
// check before store chunk
if (cancellationToken.IsCancellationRequested)
return false;
//We have our chunk, save the chunk into the world //We have our chunk, save the chunk into the world
handler.InvokeOnMainThread(() => handler.InvokeOnMainThread(() =>
{ {
@ -235,7 +224,6 @@ namespace MinecraftClient.Protocol.Handlers
// Don't worry about skipping remaining data since there is no useful data afterwards in 1.9 // Don't worry about skipping remaining data since there is no useful data afterwards in 1.9
// (plus, it would require parsing the tile entity lists' NBT) // (plus, it would require parsing the tile entity lists' NBT)
} }
return true;
} }
/// <summary> /// <summary>
@ -250,13 +238,9 @@ namespace MinecraftClient.Protocol.Handlers
/// <param name="currentDimension">Current dimension type (0 = overworld)</param> /// <param name="currentDimension">Current dimension type (0 = overworld)</param>
/// <param name="cache">Cache for reading chunk data</param> /// <param name="cache">Cache for reading chunk data</param>
/// <param name="cancellationToken">token to cancel the task</param> /// <param name="cancellationToken">token to cancel the task</param>
/// <returns>true if successfully loaded</returns>
[MethodImpl(MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveOptimization)]
public bool ProcessChunkColumnData(int chunkX, int chunkZ, ushort chunkMask, ushort chunkMask2, bool hasSkyLight, bool chunksContinuous, int currentDimension, Queue<byte> cache, CancellationToken cancellationToken) public void ProcessChunkColumnData(int chunkX, int chunkZ, ushort chunkMask, ushort chunkMask2, bool hasSkyLight, bool chunksContinuous, int currentDimension, Queue<byte> cache)
{ {
if (cancellationToken.IsCancellationRequested)
return false;
World world = handler.GetWorld(); World world = handler.GetWorld();
const int chunkColumnSize = 16; const int chunkColumnSize = 16;
@ -267,9 +251,6 @@ namespace MinecraftClient.Protocol.Handlers
int maxChunkY = sizeof(int) * 8 - 1 - BitOperations.LeadingZeroCount(chunkMask); int maxChunkY = sizeof(int) * 8 - 1 - BitOperations.LeadingZeroCount(chunkMask);
for (int chunkY = 0; chunkY <= maxChunkY; chunkY++) for (int chunkY = 0; chunkY <= maxChunkY; chunkY++)
{ {
if (cancellationToken.IsCancellationRequested)
return false;
if ((chunkMask & (1 << chunkY)) != 0) if ((chunkMask & (1 << chunkY)) != 0)
{ {
// 1.14 and above Non-air block count inside chunk section, for lighting purposes // 1.14 and above Non-air block count inside chunk section, for lighting purposes
@ -385,10 +366,6 @@ namespace MinecraftClient.Protocol.Handlers
} }
} }
// check before store chunk
if (cancellationToken.IsCancellationRequested)
return false;
//We have our chunk, save the chunk into the world //We have our chunk, save the chunk into the world
handler.InvokeOnMainThread(() => handler.InvokeOnMainThread(() =>
{ {
@ -429,9 +406,6 @@ namespace MinecraftClient.Protocol.Handlers
int maxChunkY = sizeof(int) * 8 - 1 - BitOperations.LeadingZeroCount(chunkMask); int maxChunkY = sizeof(int) * 8 - 1 - BitOperations.LeadingZeroCount(chunkMask);
for (int chunkY = 0; chunkY <= maxChunkY; chunkY++) for (int chunkY = 0; chunkY <= maxChunkY; chunkY++)
{ {
if (cancellationToken.IsCancellationRequested)
return false;
if ((chunkMask & (1 << chunkY)) != 0) if ((chunkMask & (1 << chunkY)) != 0)
{ {
Chunk chunk = new Chunk(); Chunk chunk = new Chunk();
@ -443,10 +417,6 @@ namespace MinecraftClient.Protocol.Handlers
for (int blockX = 0; blockX < Chunk.SizeX; blockX++) for (int blockX = 0; blockX < Chunk.SizeX; blockX++)
chunk.SetWithoutCheck(blockX, blockY, blockZ, new Block(queue.Dequeue())); chunk.SetWithoutCheck(blockX, blockY, blockZ, new Block(queue.Dequeue()));
// check before store chunk
if (cancellationToken.IsCancellationRequested)
return false;
//We have our chunk, save the chunk into the world //We have our chunk, save the chunk into the world
handler.InvokeOnMainThread(() => handler.InvokeOnMainThread(() =>
{ {
@ -530,10 +500,6 @@ namespace MinecraftClient.Protocol.Handlers
for (int blockX = 0; blockX < Chunk.SizeX; blockX++) for (int blockX = 0; blockX < Chunk.SizeX; blockX++)
chunk.SetWithoutCheck(blockX, blockY, blockZ, new Block(blockTypes.Dequeue(), blockMeta.Dequeue())); chunk.SetWithoutCheck(blockX, blockY, blockZ, new Block(blockTypes.Dequeue(), blockMeta.Dequeue()));
// check before store chunk
if (cancellationToken.IsCancellationRequested)
return false;
handler.InvokeOnMainThread(() => handler.InvokeOnMainThread(() =>
{ {
world.StoreChunk(chunkX, chunkY, chunkZ, chunkColumnSize, chunk, chunkY == maxChunkY); world.StoreChunk(chunkX, chunkY, chunkZ, chunkColumnSize, chunk, chunkY == maxChunkY);
@ -542,7 +508,6 @@ namespace MinecraftClient.Protocol.Handlers
} }
} }
} }
return true;
} }
} }
} }

View file

@ -29,7 +29,6 @@ namespace MinecraftClient.Protocol
PlayerInfo? GetPlayerInfo(Guid uuid); PlayerInfo? GetPlayerInfo(Guid uuid);
Location GetCurrentLocation(); Location GetCurrentLocation();
World GetWorld(); World GetWorld();
public System.Threading.CancellationToken GetChunkProcessCancelToken();
bool GetIsSupportPreviewsChat(); bool GetIsSupportPreviewsChat();
bool GetTerrainEnabled(); bool GetTerrainEnabled();
bool SetTerrainEnabled(bool enabled); bool SetTerrainEnabled(bool enabled);