From 9089bb4cdb5091b825b0722f07f51bc5a9141209 Mon Sep 17 00:00:00 2001 From: BruceChen Date: Wed, 31 Aug 2022 18:00:00 +0800 Subject: [PATCH] Change how world is stored & Bug fix --- MinecraftClient/Mapping/World.cs | 102 +++--------------- MinecraftClient/McClient.cs | 6 +- .../Protocol/Handlers/Protocol18Terrain.cs | 5 +- .../Protocol/ProfileKey/PlayerKeyPair.cs | 6 +- 4 files changed, 21 insertions(+), 98 deletions(-) diff --git a/MinecraftClient/Mapping/World.cs b/MinecraftClient/Mapping/World.cs index f272ead8..7ce60efe 100644 --- a/MinecraftClient/Mapping/World.cs +++ b/MinecraftClient/Mapping/World.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; @@ -13,19 +14,15 @@ namespace MinecraftClient.Mapping { /// /// The chunks contained into the Minecraft world + /// Tuple: Tuple /// - private Dictionary> chunks = new(); + private ConcurrentDictionary, ChunkColumn> chunks = new(); /// /// The dimension info of the world /// private static Dimension dimension = new(); - /// - /// Lock for thread safety - /// - private readonly ReaderWriterLockSlim chunksLock = new(); - /// /// Chunk data parsing progress /// @@ -42,50 +39,16 @@ namespace MinecraftClient.Mapping { get { - chunksLock.EnterReadLock(); - try - { - //Read a chunk - if (chunks.ContainsKey(chunkX)) - if (chunks[chunkX].ContainsKey(chunkZ)) - return chunks[chunkX][chunkZ]; - return null; - } - finally - { - chunksLock.ExitReadLock(); - } + chunks.TryGetValue(new(chunkX, chunkZ), out ChunkColumn? chunkColumn); + return chunkColumn; } set { - chunksLock.EnterWriteLock(); - try - { - if (value != null) - { - //Update a chunk column - if (!chunks.ContainsKey(chunkX)) - chunks[chunkX] = new Dictionary(); - chunks[chunkX][chunkZ] = value; - } - else - { - //Unload a chunk column - if (chunks.ContainsKey(chunkX)) - { - if (chunks[chunkX].ContainsKey(chunkZ)) - { - chunks[chunkX].Remove(chunkZ); - if (chunks[chunkX].Count == 0) - chunks.Remove(chunkX); - } - } - } - } - finally - { - chunksLock.ExitWriteLock(); - } + Tuple chunkCoord = new(chunkX, chunkZ); + if (value == null) + chunks.Remove(chunkCoord, out _); + else + chunks.AddOrUpdate(chunkCoord, value, (_, _) => value); } } @@ -120,36 +83,7 @@ namespace MinecraftClient.Mapping /// Whether the ChunkColumn has been fully loaded public void StoreChunk(int chunkX, int chunkY, int chunkZ, int chunkColumnSize, Chunk? chunk, bool loadCompleted) { - ChunkColumn? chunkColumn = null; - chunksLock.EnterUpgradeableReadLock(); - try - { - //Read a chunk - if (chunks.ContainsKey(chunkX)) - if (chunks[chunkX].ContainsKey(chunkZ)) - chunkColumn = chunks[chunkX][chunkZ]; - - if (chunkColumn == null) - { - chunkColumn = new ChunkColumn(chunkColumnSize); - chunksLock.EnterWriteLock(); - try - { - //Update a chunk column - if (!chunks.ContainsKey(chunkX)) - chunks[chunkX] = new Dictionary(); - chunks[chunkX][chunkZ] = chunkColumn; - } - finally - { - chunksLock.ExitWriteLock(); - } - } - } - finally - { - chunksLock.ExitUpgradeableReadLock(); - } + ChunkColumn chunkColumn = chunks.GetOrAdd(new(chunkX, chunkZ), (_) => new(chunkColumnSize)); chunkColumn[chunkY] = chunk; if (loadCompleted) chunkColumn.FullyLoaded = true; @@ -249,17 +183,9 @@ namespace MinecraftClient.Mapping /// public void Clear() { - chunksLock.EnterWriteLock(); - try - { - chunks = new Dictionary>(); - chunkCnt = 0; - chunkLoadNotCompleted = 0; - } - finally - { - chunksLock.ExitWriteLock(); - } + chunks = new(); + chunkCnt = 0; + chunkLoadNotCompleted = 0; } /// diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index a133b206..4bdf6535 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -712,10 +712,10 @@ namespace MinecraftClient try { Command cmd = (Command)Activator.CreateInstance(type); - cmds[cmd.CmdName.ToLower()] = cmd; - cmd_names.Add(cmd.CmdName.ToLower()); + cmds[Settings.ToLowerIfNeed(cmd.CmdName)] = cmd; + cmd_names.Add(Settings.ToLowerIfNeed(cmd.CmdName)); foreach (string alias in cmd.getCMDAliases()) - cmds[alias.ToLower()] = cmd; + cmds[Settings.ToLowerIfNeed(alias)] = cmd; } catch (Exception e) { diff --git a/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs b/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs index 023f9946..7357252c 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs @@ -71,14 +71,11 @@ namespace MinecraftClient.Protocol.Handlers // Indirect Mode: For block states with bits per entry <= 4, 4 bits are used to represent a block. if (bitsPerEntry < 4) bitsPerEntry = 4; - int entryPerLong = 64 / bitsPerEntry; // entryPerLong = sizeof(long) / bitsPerEntry - // Direct Mode: Bit mask covering bitsPerEntry bits // EG, if bitsPerEntry = 5, valueMask = 00011111 in binary uint valueMask = (uint)((1 << bitsPerEntry) - 1); - int paletteLength = 0; // Assume zero when length is absent - if (usePalette) paletteLength = dataTypes.ReadNextVarInt(cache); + int paletteLength = usePalette ? dataTypes.ReadNextVarInt(cache) : 0; // Assume zero when length is absent Span palette = paletteLength < 256 ? stackalloc uint[paletteLength] : new uint[paletteLength]; for (int i = 0; i < paletteLength; i++) diff --git a/MinecraftClient/Protocol/ProfileKey/PlayerKeyPair.cs b/MinecraftClient/Protocol/ProfileKey/PlayerKeyPair.cs index 17af3946..5690c78f 100644 --- a/MinecraftClient/Protocol/ProfileKey/PlayerKeyPair.cs +++ b/MinecraftClient/Protocol/ProfileKey/PlayerKeyPair.cs @@ -14,14 +14,14 @@ namespace MinecraftClient.Protocol.Keys public DateTime RefreshedAfter; // Todo: add a timer - private const string DataTimeFormat = "O"; + private const string DataTimeFormat = "yyyy-MM-ddTHH:mm:ss.ffffffZ"; public PlayerKeyPair(PublicKey keyPublic, PrivateKey keyPrivate, string expiresAt, string refreshedAfter) { PublicKey = keyPublic; PrivateKey = keyPrivate; - ExpiresAt = DateTime.ParseExact(expiresAt, "yyyy-MM-ddTHH:mm:ss.fffffffZ", System.Globalization.CultureInfo.InvariantCulture).ToUniversalTime(); - RefreshedAfter = DateTime.ParseExact(refreshedAfter, "yyyy-MM-ddTHH:mm:ss.fffffffZ", System.Globalization.CultureInfo.InvariantCulture).ToUniversalTime(); + ExpiresAt = DateTime.ParseExact(expiresAt, DataTimeFormat, System.Globalization.CultureInfo.InvariantCulture).ToUniversalTime(); + RefreshedAfter = DateTime.ParseExact(refreshedAfter, DataTimeFormat, System.Globalization.CultureInfo.InvariantCulture).ToUniversalTime(); } public bool NeedRefresh()