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 BlockLight { get; }
|
||||||
NibbleArray SkyLight { get; }
|
NibbleArray SkyLight { get; }
|
||||||
int GetHeight(byte x, byte z);
|
int GetHeight(byte x, byte z);
|
||||||
|
void UpdateHeightMap();
|
||||||
byte GetBlockID(Coordinates3D coordinates);
|
byte GetBlockID(Coordinates3D coordinates);
|
||||||
byte GetMetadata(Coordinates3D coordinates);
|
byte GetMetadata(Coordinates3D coordinates);
|
||||||
byte GetSkyLight(Coordinates3D coordinates);
|
byte GetSkyLight(Coordinates3D coordinates);
|
||||||
|
@ -5,6 +5,7 @@ using TrueCraft.API;
|
|||||||
using TrueCraft.Core.World;
|
using TrueCraft.Core.World;
|
||||||
using MonoGame.Utilities;
|
using MonoGame.Utilities;
|
||||||
using TrueCraft.Client.Events;
|
using TrueCraft.Client.Events;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
|
||||||
namespace TrueCraft.Client.Handlers
|
namespace TrueCraft.Client.Handlers
|
||||||
{
|
{
|
||||||
@ -20,15 +21,75 @@ namespace TrueCraft.Client.Handlers
|
|||||||
public static void HandleChunkData(IPacket _packet, MultiplayerClient client)
|
public static void HandleChunkData(IPacket _packet, MultiplayerClient client)
|
||||||
{
|
{
|
||||||
var packet = (ChunkDataPacket)_packet;
|
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 data = ZlibStream.UncompressBuffer(packet.CompressedData);
|
||||||
var chunk = client.World.FindChunk(new Coordinates2D(packet.X, packet.Z));
|
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);
|
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);
|
Array.Copy(data, chunk.Blocks.Length, chunk.Metadata.Data, 0, chunk.Metadata.Data.Length);
|
||||||
// TODO: Light
|
// 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)));
|
client.OnChunkLoaded(new ChunkEventArgs(new ReadOnlyChunk(chunk)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ namespace TrueCraft.Client.Handlers
|
|||||||
client.RegisterPacketHandler(new HandshakeResponsePacket().ID, HandleHandshake);
|
client.RegisterPacketHandler(new HandshakeResponsePacket().ID, HandleHandshake);
|
||||||
client.RegisterPacketHandler(new ChatMessagePacket().ID, HandleChatMessage);
|
client.RegisterPacketHandler(new ChatMessagePacket().ID, HandleChatMessage);
|
||||||
client.RegisterPacketHandler(new SetPlayerPositionPacket().ID, HandlePositionAndLook);
|
client.RegisterPacketHandler(new SetPlayerPositionPacket().ID, HandlePositionAndLook);
|
||||||
|
client.RegisterPacketHandler(new LoginResponsePacket().ID, HandleLoginResponse);
|
||||||
|
|
||||||
client.RegisterPacketHandler(new ChunkPreamblePacket().ID, ChunkHandler.HandleChunkPreamble);
|
client.RegisterPacketHandler(new ChunkPreamblePacket().ID, ChunkHandler.HandleChunkPreamble);
|
||||||
client.RegisterPacketHandler(new ChunkDataPacket().ID, ChunkHandler.HandleChunkData);
|
client.RegisterPacketHandler(new ChunkDataPacket().ID, ChunkHandler.HandleChunkData);
|
||||||
@ -32,10 +33,18 @@ namespace TrueCraft.Client.Handlers
|
|||||||
client.QueuePacket(new LoginRequestPacket(PacketReader.Version, "TestUser"));
|
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)
|
public static void HandlePositionAndLook(IPacket _packet, MultiplayerClient client)
|
||||||
{
|
{
|
||||||
var packet = (SetPlayerPositionPacket)_packet;
|
var packet = (SetPlayerPositionPacket)_packet;
|
||||||
client._Position = new Vector3(packet.X, packet.Y, packet.Z);
|
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
|
// TODO: Pitch and yaw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ namespace TrueCraft.Client
|
|||||||
|
|
||||||
public ReadOnlyWorld World { get; private set; }
|
public ReadOnlyWorld World { get; private set; }
|
||||||
public PhysicsEngine Physics { get; set; }
|
public PhysicsEngine Physics { get; set; }
|
||||||
|
public bool LoggedIn { get; internal set; }
|
||||||
|
|
||||||
private TcpClient Client { get; set; }
|
private TcpClient Client { get; set; }
|
||||||
private IMinecraftStream Stream { get; set; }
|
private IMinecraftStream Stream { get; set; }
|
||||||
|
@ -10,6 +10,8 @@ using TrueCraft.API;
|
|||||||
using TrueCraft.Client.Rendering;
|
using TrueCraft.Client.Rendering;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using TrueCraft.Core.Networking.Packets;
|
||||||
|
using TrueCraft.API.World;
|
||||||
|
|
||||||
namespace TrueCraft.Client
|
namespace TrueCraft.Client
|
||||||
{
|
{
|
||||||
@ -29,6 +31,8 @@ namespace TrueCraft.Client
|
|||||||
private Matrix Camera;
|
private Matrix Camera;
|
||||||
private Matrix Perspective;
|
private Matrix Perspective;
|
||||||
private BoundingFrustum CameraView;
|
private BoundingFrustum CameraView;
|
||||||
|
private bool MouseCaptured;
|
||||||
|
private KeyboardState PreviousKeyboardState;
|
||||||
|
|
||||||
private BasicEffect OpaqueEffect, TransparentEffect;
|
private BasicEffect OpaqueEffect, TransparentEffect;
|
||||||
|
|
||||||
@ -45,6 +49,7 @@ namespace TrueCraft.Client
|
|||||||
NextPhysicsUpdate = DateTime.MinValue;
|
NextPhysicsUpdate = DateTime.MinValue;
|
||||||
ChunkMeshes = new List<Mesh>();
|
ChunkMeshes = new List<Mesh>();
|
||||||
TransparentChunkMeshes = new List<Mesh>();
|
TransparentChunkMeshes = new List<Mesh>();
|
||||||
|
MouseCaptured = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Initialize()
|
protected override void Initialize()
|
||||||
@ -68,6 +73,7 @@ namespace TrueCraft.Client
|
|||||||
var centerY = GraphicsDevice.Viewport.Height / 2;
|
var centerY = GraphicsDevice.Viewport.Height / 2;
|
||||||
Mouse.SetPosition(centerX, centerY);
|
Mouse.SetPosition(centerX, centerY);
|
||||||
UpdateMatricies();
|
UpdateMatricies();
|
||||||
|
PreviousKeyboardState = Keyboard.GetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleClientPropertyChanged(object sender, PropertyChangedEventArgs e)
|
void HandleClientPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
@ -118,7 +124,7 @@ namespace TrueCraft.Client
|
|||||||
base.OnExiting(sender, args);
|
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))
|
if (state.IsKeyDown(Keys.Escape))
|
||||||
Exit();
|
Exit();
|
||||||
@ -134,11 +140,16 @@ namespace TrueCraft.Client
|
|||||||
if (state.IsKeyDown(Keys.Down) || state.IsKeyDown(Keys.S))
|
if (state.IsKeyDown(Keys.Down) || state.IsKeyDown(Keys.S))
|
||||||
delta += Microsoft.Xna.Framework.Vector3.Backward;
|
delta += Microsoft.Xna.Framework.Vector3.Backward;
|
||||||
|
|
||||||
|
if (state.IsKeyUp(Keys.Tab) && oldState.IsKeyDown(Keys.Tab))
|
||||||
|
MouseCaptured = !MouseCaptured;
|
||||||
|
|
||||||
var lookAt = Microsoft.Xna.Framework.Vector3.Transform(
|
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);
|
Client.Position += new TrueCraft.API.Vector3(lookAt.X, lookAt.Y, lookAt.Z) * (gameTime.ElapsedGameTime.TotalSeconds * 4.3717);
|
||||||
|
|
||||||
|
if (MouseCaptured)
|
||||||
|
{
|
||||||
var centerX = GraphicsDevice.Viewport.Width / 2;
|
var centerX = GraphicsDevice.Viewport.Width / 2;
|
||||||
var centerY = GraphicsDevice.Viewport.Height / 2;
|
var centerY = GraphicsDevice.Viewport.Height / 2;
|
||||||
var mouse = Mouse.GetState();
|
var mouse = Mouse.GetState();
|
||||||
@ -153,6 +164,7 @@ namespace TrueCraft.Client
|
|||||||
if (look != Vector2.Zero)
|
if (look != Vector2.Zero)
|
||||||
UpdateMatricies();
|
UpdateMatricies();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Update(GameTime gameTime)
|
protected override void Update(GameTime gameTime)
|
||||||
{
|
{
|
||||||
@ -162,11 +174,28 @@ namespace TrueCraft.Client
|
|||||||
}
|
}
|
||||||
if (NextPhysicsUpdate < DateTime.Now)
|
if (NextPhysicsUpdate < DateTime.Now)
|
||||||
{
|
{
|
||||||
if (Client.World.FindChunk(new Coordinates2D((int)Client.Position.X, (int)Client.Position.Z)) != null)
|
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();
|
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);
|
NextPhysicsUpdate = DateTime.Now.AddMilliseconds(1000 / 20);
|
||||||
}
|
}
|
||||||
UpdateKeyboard(gameTime, Keyboard.GetState());
|
var state = Keyboard.GetState();
|
||||||
|
UpdateKeyboard(gameTime, state, PreviousKeyboardState);
|
||||||
|
PreviousKeyboardState = state;
|
||||||
base.Update(gameTime);
|
base.Update(gameTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +224,7 @@ namespace TrueCraft.Client
|
|||||||
Graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
|
Graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||||
GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
|
GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
|
||||||
GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp;
|
GraphicsDevice.SamplerStates[1] = SamplerState.PointClamp;
|
||||||
GraphicsDevice.BlendState = BlendState.NonPremultiplied;
|
GraphicsDevice.BlendState = BlendState.AlphaBlend;
|
||||||
|
|
||||||
OpaqueEffect.View = TransparentEffect.View = Camera;
|
OpaqueEffect.View = TransparentEffect.View = Camera;
|
||||||
OpaqueEffect.Projection = TransparentEffect.Projection = Perspective;
|
OpaqueEffect.Projection = TransparentEffect.Projection = Perspective;
|
||||||
|
@ -324,4 +324,14 @@
|
|||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<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>
|
</Project>
|
@ -210,6 +210,28 @@ namespace TrueCraft.Core.World
|
|||||||
HeightMap[(byte)(x * Width) + z] = value;
|
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()
|
public NbtFile ToNbt()
|
||||||
{
|
{
|
||||||
LastAccessed = DateTime.Now;
|
LastAccessed = DateTime.Now;
|
||||||
|
Reference in New Issue
Block a user