mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Change how world is stored & Bug fix
This commit is contained in:
parent
c90ea0e92b
commit
9089bb4cdb
4 changed files with 21 additions and 98 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -13,19 +14,15 @@ namespace MinecraftClient.Mapping
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The chunks contained into the Minecraft world
|
/// The chunks contained into the Minecraft world
|
||||||
|
/// Tuple<int, int>: Tuple<chunkX, chunkZ>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Dictionary<int, Dictionary<int, ChunkColumn>> chunks = new();
|
private ConcurrentDictionary<Tuple<int, int>, ChunkColumn> chunks = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The dimension info of the world
|
/// The dimension info of the world
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Dimension dimension = new();
|
private static Dimension dimension = new();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Lock for thread safety
|
|
||||||
/// </summary>
|
|
||||||
private readonly ReaderWriterLockSlim chunksLock = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Chunk data parsing progress
|
/// Chunk data parsing progress
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -42,50 +39,16 @@ namespace MinecraftClient.Mapping
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
chunksLock.EnterReadLock();
|
chunks.TryGetValue(new(chunkX, chunkZ), out ChunkColumn? chunkColumn);
|
||||||
try
|
return chunkColumn;
|
||||||
{
|
|
||||||
//Read a chunk
|
|
||||||
if (chunks.ContainsKey(chunkX))
|
|
||||||
if (chunks[chunkX].ContainsKey(chunkZ))
|
|
||||||
return chunks[chunkX][chunkZ];
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
chunksLock.ExitReadLock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
chunksLock.EnterWriteLock();
|
Tuple<int, int> chunkCoord = new(chunkX, chunkZ);
|
||||||
try
|
if (value == null)
|
||||||
{
|
chunks.Remove(chunkCoord, out _);
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
//Update a chunk column
|
|
||||||
if (!chunks.ContainsKey(chunkX))
|
|
||||||
chunks[chunkX] = new Dictionary<int, ChunkColumn>();
|
|
||||||
chunks[chunkX][chunkZ] = value;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
chunks.AddOrUpdate(chunkCoord, value, (_, _) => value);
|
||||||
//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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,36 +83,7 @@ namespace MinecraftClient.Mapping
|
||||||
/// <param name="loadCompleted">Whether the ChunkColumn has been fully loaded</param>
|
/// <param name="loadCompleted">Whether the ChunkColumn has been fully loaded</param>
|
||||||
public void StoreChunk(int chunkX, int chunkY, int chunkZ, int chunkColumnSize, Chunk? chunk, bool loadCompleted)
|
public void StoreChunk(int chunkX, int chunkY, int chunkZ, int chunkColumnSize, Chunk? chunk, bool loadCompleted)
|
||||||
{
|
{
|
||||||
ChunkColumn? chunkColumn = null;
|
ChunkColumn chunkColumn = chunks.GetOrAdd(new(chunkX, chunkZ), (_) => new(chunkColumnSize));
|
||||||
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<int, ChunkColumn>();
|
|
||||||
chunks[chunkX][chunkZ] = chunkColumn;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
chunksLock.ExitWriteLock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
chunksLock.ExitUpgradeableReadLock();
|
|
||||||
}
|
|
||||||
chunkColumn[chunkY] = chunk;
|
chunkColumn[chunkY] = chunk;
|
||||||
if (loadCompleted)
|
if (loadCompleted)
|
||||||
chunkColumn.FullyLoaded = true;
|
chunkColumn.FullyLoaded = true;
|
||||||
|
|
@ -249,18 +183,10 @@ namespace MinecraftClient.Mapping
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
chunksLock.EnterWriteLock();
|
chunks = new();
|
||||||
try
|
|
||||||
{
|
|
||||||
chunks = new Dictionary<int, Dictionary<int, ChunkColumn>>();
|
|
||||||
chunkCnt = 0;
|
chunkCnt = 0;
|
||||||
chunkLoadNotCompleted = 0;
|
chunkLoadNotCompleted = 0;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
chunksLock.ExitWriteLock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the location of block of the entity is looking
|
/// Get the location of block of the entity is looking
|
||||||
|
|
|
||||||
|
|
@ -712,10 +712,10 @@ namespace MinecraftClient
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Command cmd = (Command)Activator.CreateInstance(type);
|
Command cmd = (Command)Activator.CreateInstance(type);
|
||||||
cmds[cmd.CmdName.ToLower()] = cmd;
|
cmds[Settings.ToLowerIfNeed(cmd.CmdName)] = cmd;
|
||||||
cmd_names.Add(cmd.CmdName.ToLower());
|
cmd_names.Add(Settings.ToLowerIfNeed(cmd.CmdName));
|
||||||
foreach (string alias in cmd.getCMDAliases())
|
foreach (string alias in cmd.getCMDAliases())
|
||||||
cmds[alias.ToLower()] = cmd;
|
cmds[Settings.ToLowerIfNeed(alias)] = cmd;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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.
|
// Indirect Mode: For block states with bits per entry <= 4, 4 bits are used to represent a block.
|
||||||
if (bitsPerEntry < 4) bitsPerEntry = 4;
|
if (bitsPerEntry < 4) bitsPerEntry = 4;
|
||||||
|
|
||||||
int entryPerLong = 64 / bitsPerEntry; // entryPerLong = sizeof(long) / bitsPerEntry
|
|
||||||
|
|
||||||
// Direct Mode: Bit mask covering bitsPerEntry bits
|
// Direct Mode: Bit mask covering bitsPerEntry bits
|
||||||
// EG, if bitsPerEntry = 5, valueMask = 00011111 in binary
|
// EG, if bitsPerEntry = 5, valueMask = 00011111 in binary
|
||||||
uint valueMask = (uint)((1 << bitsPerEntry) - 1);
|
uint valueMask = (uint)((1 << bitsPerEntry) - 1);
|
||||||
|
|
||||||
int paletteLength = 0; // Assume zero when length is absent
|
int paletteLength = usePalette ? dataTypes.ReadNextVarInt(cache) : 0; // Assume zero when length is absent
|
||||||
if (usePalette) paletteLength = dataTypes.ReadNextVarInt(cache);
|
|
||||||
|
|
||||||
Span<uint> palette = paletteLength < 256 ? stackalloc uint[paletteLength] : new uint[paletteLength];
|
Span<uint> palette = paletteLength < 256 ? stackalloc uint[paletteLength] : new uint[paletteLength];
|
||||||
for (int i = 0; i < paletteLength; i++)
|
for (int i = 0; i < paletteLength; i++)
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,14 @@ namespace MinecraftClient.Protocol.Keys
|
||||||
|
|
||||||
public DateTime RefreshedAfter; // Todo: add a timer
|
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)
|
public PlayerKeyPair(PublicKey keyPublic, PrivateKey keyPrivate, string expiresAt, string refreshedAfter)
|
||||||
{
|
{
|
||||||
PublicKey = keyPublic;
|
PublicKey = keyPublic;
|
||||||
PrivateKey = keyPrivate;
|
PrivateKey = keyPrivate;
|
||||||
ExpiresAt = DateTime.ParseExact(expiresAt, "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, "yyyy-MM-ddTHH:mm:ss.fffffffZ", System.Globalization.CultureInfo.InvariantCulture).ToUniversalTime();
|
RefreshedAfter = DateTime.ParseExact(refreshedAfter, DataTimeFormat, System.Globalization.CultureInfo.InvariantCulture).ToUniversalTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool NeedRefresh()
|
public bool NeedRefresh()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue