Fix client bugs preventing use on vanilla servers
This commit is contained in:
parent
df566e6d76
commit
bd132b0d6f
@ -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);
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -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>
|
@ -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;
|
||||
|
Reference in New Issue
Block a user