Re-render chunks when they change

This has some weird problems where the chunks will disappear for a
moment. I spent some time investigating it and I'm still not sure why
this happens.
This commit is contained in:
Drew DeVault 2015-09-28 08:19:42 -04:00
parent c25f18619e
commit 512fabf0b5
7 changed files with 48 additions and 19 deletions

View File

@ -26,7 +26,7 @@ namespace TrueCraft.Client.Handlers
// Relevant chunk is not loaded - ignore packet
return;
}
chunk.SetBlockID(adjusted, packet.ID);
chunk.SetBlockID(adjusted, (byte)packet.BlockID);
chunk.SetMetadata(adjusted, (byte)packet.Metadata);
client.OnChunkModified(new ChunkEventArgs(new ReadOnlyChunk(chunk)));
}
@ -41,10 +41,10 @@ namespace TrueCraft.Client.Handlers
public static void HandleChunkData(IPacket _packet, MultiplayerClient client)
{
var packet = (ChunkDataPacket)_packet;
var coords = new Coordinates3D(packet.X, packet.Y, packet.Z);
var data = ZlibStream.UncompressBuffer(packet.CompressedData);
IChunk chunk;
var adjustedCoords = client.World.World.FindBlockPosition(
new Coordinates3D(packet.X, packet.Y, packet.Z), out chunk);
var adjustedCoords = client.World.World.FindBlockPosition(coords, out chunk);
if (packet.Width == Chunk.Width
&& packet.Height == Chunk.Height

View File

@ -6,6 +6,8 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using TrueCraft.API;
using System.Linq;
using System.Threading;
namespace TrueCraft.Client.Modules
{
@ -15,7 +17,8 @@ namespace TrueCraft.Client.Modules
public ChunkRenderer ChunkRenderer { get; set; }
public int ChunksRendered { get; set; }
private List<Mesh> ChunkMeshes { get; set; }
private HashSet<Coordinates2D> ActiveMeshes { get; set; }
private List<ChunkMesh> ChunkMeshes { get; set; }
private ConcurrentBag<Mesh> IncomingChunks { get; set; }
private BasicEffect OpaqueEffect { get; set; }
@ -27,7 +30,8 @@ namespace TrueCraft.Client.Modules
ChunkRenderer = new ChunkRenderer(Game.Client.World, Game, Game.BlockRepository);
Game.Client.ChunkLoaded += (sender, e) => ChunkRenderer.Enqueue(e.Chunk);
//Client.ChunkModified += (sender, e) => ChunkRenderer.Enqueue(e.Chunk, true);
Game.Client.ChunkUnloaded += (sender, e) => UnloadChunk(e.Chunk);
Game.Client.ChunkModified += (sender, e) => ChunkRenderer.Enqueue(e.Chunk, true);
ChunkRenderer.MeshCompleted += MeshCompleted;
ChunkRenderer.Start();
@ -50,8 +54,9 @@ namespace TrueCraft.Client.Modules
TransparentEffect.Texture = Game.TextureMapper.GetTexture("terrain.png");
TransparentEffect.VertexColorEnabled = true;
ChunkMeshes = new List<Mesh>();
ChunkMeshes = new List<ChunkMesh>();
IncomingChunks = new ConcurrentBag<Mesh>();
ActiveMeshes = new HashSet<Coordinates2D>();
}
void MeshCompleted(object sender, RendererEventArgs<ReadOnlyChunk> e)
@ -59,6 +64,15 @@ namespace TrueCraft.Client.Modules
IncomingChunks.Add(e.Result);
}
void UnloadChunk(ReadOnlyChunk chunk)
{
Game.PendingMainThreadActions.Add(() =>
{
ActiveMeshes.Remove(chunk.Coordinates);
ChunkMeshes.RemoveAll(m => m.Chunk.Coordinates == chunk.Coordinates);
});
}
void HandleClientPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
@ -73,10 +87,17 @@ namespace TrueCraft.Client.Modules
public void Update(GameTime gameTime)
{
Mesh mesh;
while (IncomingChunks.TryTake(out mesh))
Mesh _mesh;
while (IncomingChunks.TryTake(out _mesh))
{
var mesh = _mesh as ChunkMesh;
int existing = -1;
if (ActiveMeshes.Contains(mesh.Chunk.Coordinates))
existing = ChunkMeshes.FindIndex(m => m.Chunk.Coordinates == mesh.Chunk.Coordinates);
ActiveMeshes.Add(mesh.Chunk.Coordinates);
ChunkMeshes.Add(mesh);
if (existing != -1)
ChunkMeshes.RemoveAt(existing);
}
}

View File

@ -89,6 +89,9 @@ namespace TrueCraft.Client.Modules
string.Format(ChatColor.Gray + "Looking at {0} ({1})", Game.HighlightedBlock,
Enum.GetName(typeof(BlockFace), Game.HighlightedBlockFace)));
Font.DrawText(SpriteBatch, xOrigin, yOrigin + (yOffset * 3),
string.Format(ChatColor.Gray + "{0} pending chunks", Game.ChunkModule.ChunkRenderer.PendingChunks));
SpriteBatch.End();
}

View File

@ -109,6 +109,8 @@ namespace TrueCraft.Client
return Chunk.GetBlockLight(coordinates);
}
public Coordinates2D Coordinates { get { return Chunk.Coordinates; } }
public int X { get { return Chunk.X; } }
public int Z { get { return Chunk.Z; } }

View File

@ -39,6 +39,14 @@ namespace TrueCraft.Client.Rendering
}
}
public int PendingChunks
{
get
{
return _items.Count + _priorityItems.Count;
}
}
private ReadOnlyWorld World { get; set; }
private TrueCraftGame Game { get; set; }
private IBlockRepository BlockRepository { get; set; }

View File

@ -20,8 +20,8 @@ namespace TrueCraft.Client.Rendering
private volatile bool _isRunning;
private Thread[] _rendererThreads;
private ConcurrentQueue<T> _items, _priorityItems;
private volatile bool _isDisposed;
protected ConcurrentQueue<T> _items, _priorityItems;
/// <summary>
/// Gets whether this renderer is running.
@ -150,13 +150,10 @@ namespace TrueCraft.Client.Rendering
throw new ObjectDisposedException(GetType().Name);
if (!_isRunning) return;
lock (_syncLock)
{
if (hasPriority)
_priorityItems.Enqueue(item);
else
_items.Enqueue(item);
}
if (hasPriority)
_priorityItems.Enqueue(item);
else
_items.Enqueue(item);
}
/// <summary>

View File

@ -269,9 +269,7 @@ namespace TrueCraft.Client
// We should eventually make some means of detecing that we're on a vanilla server to enable this
// It's a waste of bandwidth to do it on a TrueCraft server
Client.QueuePacket(new PlayerGroundedPacket { OnGround = true });
Client.QueuePacket(new PlayerPositionAndLookPacket(Client.Position.X, Client.Position.Y,
Client.Position.Y + MultiplayerClient.Height, Client.Position.Z, Client.Yaw, Client.Pitch, false));
NextPhysicsUpdate = DateTime.UtcNow.AddMilliseconds(1000 / 20);
NextPhysicsUpdate = DateTime.UtcNow.AddMilliseconds(50);
}
foreach (var module in Modules)