Fix client bugs preventing use on vanilla servers

This commit is contained in:
Drew DeVault 2015-05-17 16:18:09 -06:00
parent df566e6d76
commit bd132b0d6f
7 changed files with 158 additions and 25 deletions

View File

@ -19,6 +19,7 @@ namespace TrueCraft.API.World
NibbleArray BlockLight { get; }
NibbleArray SkyLight { get; }
int GetHeight(byte x, byte z);
void UpdateHeightMap();
byte GetBlockID(Coordinates3D coordinates);
byte GetMetadata(Coordinates3D coordinates);
byte GetSkyLight(Coordinates3D coordinates);

View File

@ -5,6 +5,7 @@ using TrueCraft.API;
using TrueCraft.Core.World;
using MonoGame.Utilities;
using TrueCraft.Client.Events;
using TrueCraft.API.World;
namespace TrueCraft.Client.Handlers
{
@ -20,15 +21,75 @@ namespace TrueCraft.Client.Handlers
public static void HandleChunkData(IPacket _packet, MultiplayerClient client)
{
var packet = (ChunkDataPacket)_packet;
// TODO: Handle chunk data packets that only include a partial chunk
// This only works with TrueCraft servers unless we fix that
var data = ZlibStream.UncompressBuffer(packet.CompressedData);
var chunk = client.World.FindChunk(new Coordinates2D(packet.X, packet.Z));
Array.Copy(data, 0, chunk.Blocks, 0, chunk.Blocks.Length);
Array.Copy(data, chunk.Blocks.Length, chunk.Metadata.Data, 0, chunk.Metadata.Data.Length);
// TODO: Light
IChunk chunk;
var adjustedCoords = client.World.World.FindBlockPosition(
new Coordinates3D(packet.X, packet.Y, packet.Z), out chunk);
if (packet.Width == Chunk.Width
&& packet.Height == Chunk.Height
&& packet.Depth == Chunk.Depth) // Fast path
{
// Block IDs
Array.Copy(data, 0, chunk.Blocks, 0, chunk.Blocks.Length);
// Block metadata
Array.Copy(data, chunk.Blocks.Length, chunk.Metadata.Data, 0, chunk.Metadata.Data.Length);
// Block light
Array.Copy(data, chunk.Blocks.Length + chunk.Metadata.Data.Length,
chunk.BlockLight.Data, 0, chunk.BlockLight.Data.Length);
// Sky light
Array.Copy(data, chunk.Blocks.Length + chunk.Metadata.Data.Length + chunk.BlockLight.Data.Length,
chunk.SkyLight.Data, 0, chunk.SkyLight.Data.Length);
}
else // Slow path
{
int x = adjustedCoords.X, y = adjustedCoords.Y, z = adjustedCoords.Z;
int fullLength = packet.Width * packet.Height * packet.Depth; // Length of full sized byte section
int nibbleLength = fullLength / 2; // Length of nibble sections
for (int i = 0; i < fullLength; i++) // Iterate through block IDs
{
chunk.SetBlockID(new Coordinates3D(x, y, z), data[i]);
y++;
if (y >= packet.Height)
{
y = 0;
z++;
if (z >= packet.Depth)
{
z = 0;
x++;
if (x >= packet.Width)
{
x = 0;
}
}
}
}
x = adjustedCoords.X; y = adjustedCoords.Y; z = adjustedCoords.Z;
for (int i = fullLength; i < nibbleLength; i++) // Iterate through metadata
{
byte m = data[i];
chunk.SetMetadata(new Coordinates3D(x, y, z), (byte)(m & 0xF));
chunk.SetMetadata(new Coordinates3D(x, y + 1, z), (byte)(m & 0xF0 << 8));
y += 2;
if (y >= packet.Height)
{
y = 0;
z++;
if (z >= packet.Depth)
{
z = 0;
x++;
if (x >= packet.Width)
{
x = 0;
}
}
}
}
// TODO: Lighting
}
chunk.UpdateHeightMap();
client.OnChunkLoaded(new ChunkEventArgs(new ReadOnlyChunk(chunk)));
}
}

View File

@ -14,6 +14,7 @@ namespace TrueCraft.Client.Handlers
client.RegisterPacketHandler(new HandshakeResponsePacket().ID, HandleHandshake);
client.RegisterPacketHandler(new ChatMessagePacket().ID, HandleChatMessage);
client.RegisterPacketHandler(new SetPlayerPositionPacket().ID, HandlePositionAndLook);
client.RegisterPacketHandler(new LoginResponsePacket().ID, HandleLoginResponse);
client.RegisterPacketHandler(new ChunkPreamblePacket().ID, ChunkHandler.HandleChunkPreamble);
client.RegisterPacketHandler(new ChunkDataPacket().ID, ChunkHandler.HandleChunkData);
@ -32,10 +33,18 @@ namespace TrueCraft.Client.Handlers
client.QueuePacket(new LoginRequestPacket(PacketReader.Version, "TestUser"));
}
public static void HandleLoginResponse(IPacket _packet, MultiplayerClient client)
{
client.QueuePacket(new PlayerGroundedPacket());
}
public static void HandlePositionAndLook(IPacket _packet, MultiplayerClient client)
{
var packet = (SetPlayerPositionPacket)_packet;
client._Position = new Vector3(packet.X, packet.Y, packet.Z);
client.QueuePacket(packet);
client.LoggedIn = true;
Console.WriteLine("Got P+L: {0}", client._Position);
// TODO: Pitch and yaw
}
}

View File

@ -26,6 +26,7 @@ namespace TrueCraft.Client
public ReadOnlyWorld World { get; private set; }
public PhysicsEngine Physics { get; set; }
public bool LoggedIn { get; internal set; }
private TcpClient Client { get; set; }
private IMinecraftStream Stream { get; set; }

View File

@ -10,6 +10,8 @@ using TrueCraft.API;
using TrueCraft.Client.Rendering;
using System.Linq;
using System.ComponentModel;
using TrueCraft.Core.Networking.Packets;
using TrueCraft.API.World;
namespace TrueCraft.Client
{
@ -29,6 +31,8 @@ namespace TrueCraft.Client
private Matrix Camera;
private Matrix Perspective;
private BoundingFrustum CameraView;
private bool MouseCaptured;
private KeyboardState PreviousKeyboardState;
private BasicEffect OpaqueEffect, TransparentEffect;
@ -45,6 +49,7 @@ namespace TrueCraft.Client
NextPhysicsUpdate = DateTime.MinValue;
ChunkMeshes = new List<Mesh>();
TransparentChunkMeshes = new List<Mesh>();
MouseCaptured = true;
}
protected override void Initialize()
@ -68,6 +73,7 @@ namespace TrueCraft.Client
var centerY = GraphicsDevice.Viewport.Height / 2;
Mouse.SetPosition(centerX, centerY);
UpdateMatricies();
PreviousKeyboardState = Keyboard.GetState();
}
void HandleClientPropertyChanged(object sender, PropertyChangedEventArgs e)
@ -118,7 +124,7 @@ namespace TrueCraft.Client
base.OnExiting(sender, args);
}
protected virtual void UpdateKeyboard(GameTime gameTime, KeyboardState state)
protected virtual void UpdateKeyboard(GameTime gameTime, KeyboardState state, KeyboardState oldState)
{
if (state.IsKeyDown(Keys.Escape))
Exit();
@ -133,25 +139,31 @@ namespace TrueCraft.Client
delta += Microsoft.Xna.Framework.Vector3.Forward;
if (state.IsKeyDown(Keys.Down) || state.IsKeyDown(Keys.S))
delta += Microsoft.Xna.Framework.Vector3.Backward;
if (state.IsKeyUp(Keys.Tab) && oldState.IsKeyDown(Keys.Tab))
MouseCaptured = !MouseCaptured;
var lookAt = Microsoft.Xna.Framework.Vector3.Transform(
delta, Matrix.CreateRotationY(MathHelper.ToRadians(Client.Yaw)));
delta, Matrix.CreateRotationY(MathHelper.ToRadians(Client.Yaw)));
Client.Position += new TrueCraft.API.Vector3(lookAt.X, lookAt.Y, lookAt.Z) * (gameTime.ElapsedGameTime.TotalSeconds * 4.3717);
var centerX = GraphicsDevice.Viewport.Width / 2;
var centerY = GraphicsDevice.Viewport.Height / 2;
var mouse = Mouse.GetState();
var look = new Vector2(centerX - mouse.Position.X, centerY - mouse.Position.Y)
* (float)(gameTime.ElapsedGameTime.TotalSeconds * 70);
Mouse.SetPosition(centerX, centerY);
Client.Yaw += look.X;
Client.Pitch += look.Y;
Client.Yaw %= 360;
Client.Pitch = MathHelper.Clamp(Client.Pitch, -90, 90);
if (MouseCaptured)
{
var centerX = GraphicsDevice.Viewport.Width / 2;
var centerY = GraphicsDevice.Viewport.Height / 2;
var mouse = Mouse.GetState();
var look = new Vector2(centerX - mouse.Position.X, centerY - mouse.Position.Y)
* (float)(gameTime.ElapsedGameTime.TotalSeconds * 70);
Mouse.SetPosition(centerX, centerY);
Client.Yaw += look.X;
Client.Pitch += look.Y;
Client.Yaw %= 360;
Client.Pitch = MathHelper.Clamp(Client.Pitch, -90, 90);
if (look != Vector2.Zero)
UpdateMatricies();
if (look != Vector2.Zero)
UpdateMatricies();
}
}
protected override void Update(GameTime gameTime)
@ -162,11 +174,28 @@ namespace TrueCraft.Client
}
if (NextPhysicsUpdate < DateTime.Now)
{
if (Client.World.FindChunk(new Coordinates2D((int)Client.Position.X, (int)Client.Position.Z)) != null)
Client.Physics.Update();
IChunk chunk;
var adjusted = Client.World.World.FindBlockPosition(new Coordinates3D((int)Client.Position.X, 0, (int)Client.Position.Z), out chunk);
if (Client.LoggedIn && chunk != null)
{
if (chunk.GetHeight((byte)adjusted.X, (byte)adjusted.Z) != 0)
Client.Physics.Update();
}
if (Client.LoggedIn)
{
// NOTE: This is to make the vanilla server send us chunk packets
// 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
Console.WriteLine("Sending position packet");
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.Now.AddMilliseconds(1000 / 20);
}
UpdateKeyboard(gameTime, Keyboard.GetState());
var state = Keyboard.GetState();
UpdateKeyboard(gameTime, state, PreviousKeyboardState);
PreviousKeyboardState = state;
base.Update(gameTime);
}
@ -195,7 +224,7 @@ namespace TrueCraft.Client
Graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp;
GraphicsDevice.BlendState = BlendState.NonPremultiplied;
GraphicsDevice.BlendState = BlendState.AlphaBlend;
OpaqueEffect.View = TransparentEffect.View = Camera;
OpaqueEffect.Projection = TransparentEffect.Projection = Perspective;

View File

@ -324,4 +324,14 @@
</ProjectReference>
</ItemGroup>
<ItemGroup />
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<TextStylePolicy inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
<CSharpFormattingPolicy IndentSwitchBody="True" IndentBlocksInsideExpressions="True" AnonymousMethodBraceStyle="NextLine" PropertyBraceStyle="NextLine" PropertyGetBraceStyle="NextLine" PropertySetBraceStyle="NextLine" EventBraceStyle="NextLine" EventAddBraceStyle="NextLine" EventRemoveBraceStyle="NextLine" StatementBraceStyle="NextLine" ElseNewLinePlacement="NewLine" CatchNewLinePlacement="NewLine" FinallyNewLinePlacement="NewLine" WhileNewLinePlacement="DoNotCare" ArrayInitializerWrapping="DoNotChange" ArrayInitializerBraceStyle="NextLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
</Project>

View File

@ -210,6 +210,28 @@ namespace TrueCraft.Core.World
HeightMap[(byte)(x * Width) + z] = value;
}
public void UpdateHeightMap()
{
for (byte x = 0; x < Chunk.Width; x++)
{
for (byte z = 0; z < Chunk.Depth; z++)
{
int y;
for (y = Chunk.Height - 1; y >= 0; y--)
{
int index = y + (z * Height) + (x * Height * Width);
if (Blocks[index] != 0)
{
SetHeight(x, z, y);
break;
}
}
if (y == 0)
SetHeight(x, z, 0);
}
}
}
public NbtFile ToNbt()
{
LastAccessed = DateTime.Now;