Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Client physics integration #202

Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions source/Craft.Net.Client/Craft.Net.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
<Compile Include="Events\DisconnectEventArgs.cs" />
<Compile Include="Events\EntitySpawnEventArgs.cs" />
<Compile Include="Events\HealthAndFoodEventArgs.cs" />
<Compile Include="MinecraftClient.Physics.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
Expand Down Expand Up @@ -87,5 +88,9 @@
<Project>{E001ADA1-6BCB-420E-B187-07FF361D60B8}</Project>
<Name>Craft.Net.Logic</Name>
</ProjectReference>
<ProjectReference Include="..\Craft.Net.Physics\Craft.Net.Physics.csproj">
<Project>{C04C72EF-5FD5-42DA-B1DC-F232D3E86636}</Project>
<Name>Craft.Net.Physics</Name>
</ProjectReference>
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions source/Craft.Net.Client/Handlers/EntityHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static void PlayerPositionAndLook(MinecraftClient client, IPacket _packet
var packet = (PlayerPositionAndLookPacket)_packet;
if (Math.Abs(packet.X) < 0.01 && Math.Abs(packet.X) > 0)
return; // Sometimes the vanilla server sends weird position updates like this
client._position = new Vector3(packet.X, packet.Y, packet.Z);
client.Position = new Vector3(packet.X, packet.Y, packet.Z);
if (!client.IsSpawned)
{
client.IsSpawned = true;
Expand All @@ -28,7 +28,7 @@ public static void EntityTeleport(MinecraftClient client, IPacket _packet)
{
var packet = (EntityTeleportPacket)_packet;
if (packet.EntityId == client.EntityId)
client._position = new Vector3(packet.X, packet.Y, packet.Z);
client.Position = new Vector3(packet.X, packet.Y, packet.Z);
}
}
}
91 changes: 91 additions & 0 deletions source/Craft.Net.Client/MinecraftClient.Physics.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Threading;
using Craft.Net.Common;
using Craft.Net.Physics;

namespace Craft.Net.Client
{
public partial class MinecraftClient : IAABBEntity
{
#region Constants
public float AccelerationDueToGravity
{
// 32 blocks per second squared / ( ticks per second) = x blocks per tick squared
get { return 0.08f;}
}

public float Drag
{
get { return 1 - 0.02f;}
}

private static Size _size = new Size(0.8, 1.6, 0.8);

public Size Size
{
get
{
return new Size(_size);
}
}
#endregion

private object _velocityLock = new object();
private Vector3 _velocity = new Vector3();
public Vector3 Velocity
{
get
{
Vector3 ret;
lock (_velocityLock)
{
ret = _velocity;
}
return ret;
}

set
{
lock (_velocityLock)
{
_velocity = value;
}
}
}

private static BoundingBox _boundingBox = new BoundingBox(new Vector3(0), new Vector3(_size.Width, _size.Height, _size.Depth));
// Make the magic in PhysicsEngine work
private static Vector3 _positionOffset = new Vector3(_size.Width / 2, _size.Height / 2 , _size.Depth / 2);

public BoundingBox BoundingBox
{
get
{
BoundingBox box;
lock (_positionLock)
{
box = _boundingBox.OffsetBy(_position - _positionOffset);
}
return box;
}
}

public bool BeginUpdate()
{
return true;
}

public void EndUpdate(Vector3 newPosition)
{
Position = newPosition;
}

public void TerrainCollision(PhysicsEngine engine, Vector3 collisionPoint, Vector3 collisionDirection)
{
if (collisionDirection == Vector3.Down)
{
_onGround = true;
}
}
}
}
55 changes: 28 additions & 27 deletions source/Craft.Net.Client/MinecraftClient.Properties.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
using System;
using System.Threading;
using Craft.Net.Anvil;
using Craft.Net.Common;
using Craft.Net.Networking;
using Craft.Net.Logic;
using Craft.Net.Physics;

namespace Craft.Net.Client
{
public partial class MinecraftClient
{
internal bool _onGround;
// Private so that silly people won't try to modify it behind our backs - everything should go through the
// Position and OnGround properties

// Lock on all position data
private object _positionLock = new object();
private bool _onGround;
private Vector3 _position;
// We keep track of when the position has been set so that the NetworkWorker can update it properly.
private bool _positionChanged;

public bool OnGround
{
get
{
if (_position.Y > Craft.Net.Anvil.World.Height || _position.Y < 0)
{
_onGround = false;
} else
{
try
{
var feetPosition = new Vector3(_position.X, _position.Y - 1.62 - 1, _position.Z);
var coordinates = new Coordinates3D((int)feetPosition.X, (int)feetPosition.Y, (int)feetPosition.Z);
var blockBoundingBox = LogicManager.GetBoundingBox(World.GetBlockId(coordinates));
_onGround = blockBoundingBox.HasValue && blockBoundingBox.Value.Contains(feetPosition - (Vector3)coordinates);
} catch (ArgumentException)
{
//Sometimes the world isn't loaded when we want it to be, so we pretend we are on the ground to
//prevent falling through the world
_onGround = true;
}
}
return _onGround;
}
get { return _onGround; }
private set { _onGround = value; }
}

internal Vector3 _position;
public Vector3 Position
{
get { return _position; }
get
{
Vector3 ret;
// Make sure that position data is in a consistent state.
lock (_positionLock)
{
ret = _position;
}
return ret;
}
set
{
_position = value;
SendPacket(new PlayerPositionPacket(Position.X, Position.Y, Position.Z, Position.Y - 1.62, OnGround));
lock (_positionLock)
{
_positionChanged = _position != value;
_position = value;
}
}
}

Expand Down
55 changes: 54 additions & 1 deletion source/Craft.Net.Client/MinecraftClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using Craft.Net.Networking;
using Craft.Net.Physics;
using Craft.Net.Logic;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
Expand Down Expand Up @@ -61,12 +63,15 @@ public void Connect(IPEndPoint endPoint)
NetworkManager = new NetworkManager(NetworkStream);
NetworkingReset = new ManualResetEvent(true);
NetworkWorkerThread = new Thread(NetworkWorker);
PhysicsWorkerThread = new Thread(PhysicsWorker);

NetworkWorkerThread.Start();
var handshake = new HandshakePacket(NetworkManager.ProtocolVersion,
EndPoint.Address.ToString(), (ushort)EndPoint.Port, NetworkMode.Login);
SendPacket(handshake);
var login = new LoginStartPacket(Session.SelectedProfile.Name);
SendPacket(login);
PhysicsWorkerThread.Start();
}

public void Disconnect(string reason)
Expand Down Expand Up @@ -100,6 +105,41 @@ public void SendChat(string message)
SendPacket(new ChatMessagePacket(message));
}

private DateTime nextPhysicsUpdate = DateTime.MinValue;
private Thread PhysicsWorkerThread;
private PhysicsEngine engine;
private void PhysicsWorker()
{
while (NetworkWorkerThread.IsAlive)
{
if (nextPhysicsUpdate < DateTime.Now)
{
//We need to wait for a login packet to initialize the physics subsystem
if (World != null && engine == null)
{
engine = new PhysicsEngine(World.World, LogicManager.PhysicsProvider);
engine.AddEntity(this);
}
nextPhysicsUpdate = DateTime.Now.AddMilliseconds(50);
try
{
engine.Update();
} catch (Exception)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting error here.

{
// Sometimes the world hasn't loaded yet, so the Phyics update can't properly read blocks and
// throws an exception.
}
} else
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto. Give this another one-over for style.

{
var sleepTime = (nextPhysicsUpdate - DateTime.Now).Milliseconds;
if (sleepTime > 0)
{
Thread.Sleep(sleepTime);
}
}
}
}

private DateTime nextPlayerUpdate = DateTime.MinValue;
private void NetworkWorker()
{
Expand All @@ -108,7 +148,20 @@ private void NetworkWorker()
if (IsSpawned && nextPlayerUpdate < DateTime.Now)
{
nextPlayerUpdate = DateTime.Now.AddMilliseconds(100);
SendPacket(new PlayerPacket(OnGround));
lock (_positionLock)
{
SendPacket(new PlayerPacket(OnGround));
if (_positionChanged) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use K&R style braces here.

SendPacket(new PlayerPositionPacket(
Position.X,
Position.Y,
Position.Z,
Position.Y - 1.62,
OnGround
));
_positionChanged = false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent is off here.

}
}
}
// Send queued packets
while (PacketQueue.Count != 0)
Expand Down
20 changes: 20 additions & 0 deletions source/Craft.Net.Common/BoundingBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ public BoundingBox(Vector3 min, Vector3 max)
this.Max = max;
}

public BoundingBox(BoundingBox b)
{
this.Min = new Vector3(b.Min);
this.Max = new Vector3(b.Max);
}

#endregion Public Constructors


Expand Down Expand Up @@ -87,6 +93,20 @@ public static BoundingBox CreateFromPoints(IEnumerable<Vector3> points)
return new BoundingBox(vector2, vector1);
}

/// <summary>
/// Offsets this BoundingBox. Does not modify this object, but returns a new one
/// </summary>
/// <returns>
/// The offset bounding box.
/// </returns>
/// <param name='Offset'>
/// The offset.
/// </param>
public BoundingBox OffsetBy(Vector3 Offset)
{
return new BoundingBox(Min + Offset, Max + Offset);
}

public Vector3[] GetCorners()
{
return new Vector3[]
Expand Down
7 changes: 7 additions & 0 deletions source/Craft.Net.Common/Size.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ public Size(double width, double height, double depth)
this.Depth = depth;
}

public Size(Size s)
{
this.Width = s.Width;
this.Height = s.Height;
this.Depth = s.Depth;
}

// TODO: More operators
public static Size operator /(Size a, double b)
{
Expand Down
7 changes: 7 additions & 0 deletions source/Craft.Net.Common/Vector3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ public Vector3(double x, double y, double z)
this.Z = z;
}

public Vector3(Vector3 V)
{
this.X = V.X;
this.Y = V.Y;
this.Z = V.Z;
}

/// <summary>
/// Converts this Vector3 to a string in the format &lt;x, y, z&gt;.
/// </summary>
Expand Down
Loading