mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-11-07 17:36:07 +00:00
Add thead safety to terrain data (#1999)
Allow safely reading terrain data from other threads
This commit is contained in:
parent
d6220ff779
commit
aeca6a8f53
3 changed files with 101 additions and 25 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MinecraftClient.Mapping
|
namespace MinecraftClient.Mapping
|
||||||
{
|
{
|
||||||
|
|
@ -19,6 +20,11 @@ namespace MinecraftClient.Mapping
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Block[,,] blocks = new Block[SizeX, SizeY, SizeZ];
|
private readonly Block[,,] blocks = new Block[SizeX, SizeY, SizeZ];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lock for thread safety
|
||||||
|
/// </summary>
|
||||||
|
private readonly ReaderWriterLockSlim blockLock = new ReaderWriterLockSlim();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read, or set the specified block
|
/// Read, or set the specified block
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -36,7 +42,16 @@ namespace MinecraftClient.Mapping
|
||||||
throw new ArgumentOutOfRangeException("blockY", "Must be between 0 and " + (SizeY - 1) + " (inclusive)");
|
throw new ArgumentOutOfRangeException("blockY", "Must be between 0 and " + (SizeY - 1) + " (inclusive)");
|
||||||
if (blockZ < 0 || blockZ >= SizeZ)
|
if (blockZ < 0 || blockZ >= SizeZ)
|
||||||
throw new ArgumentOutOfRangeException("blockZ", "Must be between 0 and " + (SizeZ - 1) + " (inclusive)");
|
throw new ArgumentOutOfRangeException("blockZ", "Must be between 0 and " + (SizeZ - 1) + " (inclusive)");
|
||||||
return blocks[blockX, blockY, blockZ];
|
|
||||||
|
blockLock.EnterReadLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return blocks[blockX, blockY, blockZ];
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
blockLock.ExitReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
|
@ -46,7 +61,16 @@ namespace MinecraftClient.Mapping
|
||||||
throw new ArgumentOutOfRangeException("blockY", "Must be between 0 and " + (SizeY - 1) + " (inclusive)");
|
throw new ArgumentOutOfRangeException("blockY", "Must be between 0 and " + (SizeY - 1) + " (inclusive)");
|
||||||
if (blockZ < 0 || blockZ >= SizeZ)
|
if (blockZ < 0 || blockZ >= SizeZ)
|
||||||
throw new ArgumentOutOfRangeException("blockZ", "Must be between 0 and " + (SizeZ - 1) + " (inclusive)");
|
throw new ArgumentOutOfRangeException("blockZ", "Must be between 0 and " + (SizeZ - 1) + " (inclusive)");
|
||||||
blocks[blockX, blockY, blockZ] = value;
|
|
||||||
|
blockLock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
blocks[blockX, blockY, blockZ] = value;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
blockLock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MinecraftClient.Mapping
|
namespace MinecraftClient.Mapping
|
||||||
{
|
{
|
||||||
|
|
@ -17,6 +18,11 @@ namespace MinecraftClient.Mapping
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Chunk[] chunks = new Chunk[ColumnSize];
|
private readonly Chunk[] chunks = new Chunk[ColumnSize];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lock for thread safety
|
||||||
|
/// </summary>
|
||||||
|
private readonly ReaderWriterLockSlim chunkLock = new ReaderWriterLockSlim();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get or set the specified chunk column
|
/// Get or set the specified chunk column
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -27,11 +33,27 @@ namespace MinecraftClient.Mapping
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return chunks[chunkY];
|
chunkLock.EnterReadLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return chunks[chunkY];
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
chunkLock.ExitReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
chunks[chunkY] = value;
|
chunkLock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
chunks[chunkY] = value;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
chunkLock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MinecraftClient.Mapping
|
namespace MinecraftClient.Mapping
|
||||||
{
|
{
|
||||||
|
|
@ -15,6 +16,11 @@ namespace MinecraftClient.Mapping
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Dictionary<int, Dictionary<int, ChunkColumn>> chunks = new Dictionary<int, Dictionary<int, ChunkColumn>>();
|
private Dictionary<int, Dictionary<int, ChunkColumn>> chunks = new Dictionary<int, Dictionary<int, ChunkColumn>>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lock for thread safety
|
||||||
|
/// </summary>
|
||||||
|
private readonly ReaderWriterLockSlim chunksLock = new ReaderWriterLockSlim();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read, set or unload the specified chunk column
|
/// Read, set or unload the specified chunk column
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -25,34 +31,50 @@ namespace MinecraftClient.Mapping
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
//Read a chunk
|
chunksLock.EnterReadLock();
|
||||||
if (chunks.ContainsKey(chunkX))
|
try
|
||||||
if (chunks[chunkX].ContainsKey(chunkZ))
|
{
|
||||||
return chunks[chunkX][chunkZ];
|
//Read a chunk
|
||||||
return null;
|
if (chunks.ContainsKey(chunkX))
|
||||||
|
if (chunks[chunkX].ContainsKey(chunkZ))
|
||||||
|
return chunks[chunkX][chunkZ];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
chunksLock.ExitReadLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value != null)
|
chunksLock.EnterWriteLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
//Update a chunk column
|
if (value != null)
|
||||||
if (!chunks.ContainsKey(chunkX))
|
|
||||||
chunks[chunkX] = new Dictionary<int, ChunkColumn>();
|
|
||||||
chunks[chunkX][chunkZ] = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Unload a chunk column
|
|
||||||
if (chunks.ContainsKey(chunkX))
|
|
||||||
{
|
{
|
||||||
if (chunks[chunkX].ContainsKey(chunkZ))
|
//Update a chunk column
|
||||||
|
if (!chunks.ContainsKey(chunkX))
|
||||||
|
chunks[chunkX] = new Dictionary<int, ChunkColumn>();
|
||||||
|
chunks[chunkX][chunkZ] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Unload a chunk column
|
||||||
|
if (chunks.ContainsKey(chunkX))
|
||||||
{
|
{
|
||||||
chunks[chunkX].Remove(chunkZ);
|
if (chunks[chunkX].ContainsKey(chunkZ))
|
||||||
if (chunks[chunkX].Count == 0)
|
{
|
||||||
chunks.Remove(chunkX);
|
chunks[chunkX].Remove(chunkZ);
|
||||||
|
if (chunks[chunkX].Count == 0)
|
||||||
|
chunks.Remove(chunkX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
chunksLock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +139,7 @@ namespace MinecraftClient.Mapping
|
||||||
{
|
{
|
||||||
Location doneloc = new Location(x, y, z);
|
Location doneloc = new Location(x, y, z);
|
||||||
Block doneblock = GetBlock(doneloc);
|
Block doneblock = GetBlock(doneloc);
|
||||||
Material blockType = GetBlock(doneloc).Type;
|
Material blockType = doneblock.Type;
|
||||||
if (blockType == block)
|
if (blockType == block)
|
||||||
{
|
{
|
||||||
list.Add(doneloc);
|
list.Add(doneloc);
|
||||||
|
|
@ -150,7 +172,15 @@ namespace MinecraftClient.Mapping
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
chunks = new Dictionary<int, Dictionary<int, ChunkColumn>>();
|
chunksLock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
chunks = new Dictionary<int, Dictionary<int, ChunkColumn>>();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
chunksLock.ExitWriteLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue