diff --git a/MinecraftClient/Mapping/Movement.cs b/MinecraftClient/Mapping/Movement.cs
index a12af234..8590899b 100644
--- a/MinecraftClient/Mapping/Movement.cs
+++ b/MinecraftClient/Mapping/Movement.cs
@@ -17,15 +17,25 @@ namespace MinecraftClient.Mapping
///
/// World the player is currently located in
/// Location the player is currently at
+ /// Current vertical motion speed
/// Updated location after applying gravity
- public static Location HandleGravity(World world, Location location)
+ public static Location HandleGravity(World world, Location location, ref double motionY)
{
Location onFoots = new Location(location.X, Math.Floor(location.Y), location.Z);
Location belowFoots = Move(location, Direction.Down);
+ if (location.Y > Math.Truncate(location.Y) + 0.0001)
+ {
+ belowFoots = location;
+ belowFoots.Y = Math.Truncate(location.Y);
+ }
if (!IsOnGround(world, location) && !IsSwimming(world, location))
- location = Move2Steps(location, belowFoots).Dequeue();
+ {
+ while (!IsOnGround(world, belowFoots) && belowFoots.Y >= 1)
+ belowFoots = Move(belowFoots, Direction.Down);
+ location = Move2Steps(location, belowFoots, ref motionY, true).Dequeue();
+ }
else if (!(world.GetBlock(onFoots).Type.IsSolid()))
- location = Move2Steps(location, onFoots).Dequeue();
+ location = Move2Steps(location, onFoots, ref motionY, true).Dequeue();
return location;
}
@@ -64,25 +74,46 @@ namespace MinecraftClient.Mapping
///
/// Start location
/// Destination location
+ /// Current vertical motion speed
+ /// Specify if performing falling steps
/// Amount of steps by block
/// A list of locations corresponding to the requested steps
- public static Queue Move2Steps(Location start, Location goal, int stepsByBlock = 8)
+ public static Queue Move2Steps(Location start, Location goal, ref double motionY, bool falling = false, int stepsByBlock = 8)
{
if (stepsByBlock <= 0)
stepsByBlock = 1;
- double totalStepsDouble = start.Distance(goal) * stepsByBlock;
- int totalSteps = (int)Math.Ceiling(totalStepsDouble);
- Location step = (goal - start) / totalSteps;
-
- if (totalStepsDouble >= 1)
+ if (falling)
{
- Queue movementSteps = new Queue();
- for (int i = 1; i <= totalSteps; i++)
- movementSteps.Enqueue(start + step * i);
- return movementSteps;
+ //Use MC-Like falling algorithm
+ double Y = start.Y;
+ Queue fallSteps = new Queue();
+ fallSteps.Enqueue(start);
+ double motionPrev = motionY;
+ motionY -= 0.08D;
+ motionY *= 0.9800000190734863D;
+ Y += motionY;
+ if (Y < goal.Y)
+ return new Queue(new[] { goal });
+ else return new Queue(new[] { new Location(start.X, Y, start.Z) });
+ }
+ else
+ {
+ //Regular MCC moving algorithm
+ motionY = 0; //Reset motion speed
+ double totalStepsDouble = start.Distance(goal) * stepsByBlock;
+ int totalSteps = (int)Math.Ceiling(totalStepsDouble);
+ Location step = (goal - start) / totalSteps;
+
+ if (totalStepsDouble >= 1)
+ {
+ Queue movementSteps = new Queue();
+ for (int i = 1; i <= totalSteps; i++)
+ movementSteps.Enqueue(start + step * i);
+ return movementSteps;
+ }
+ else return new Queue(new[] { goal });
}
- else return new Queue(new[] { goal });
}
///
@@ -163,7 +194,8 @@ namespace MinecraftClient.Mapping
/// True if the specified location is on the ground
public static bool IsOnGround(World world, Location location)
{
- return world.GetBlock(Move(location, Direction.Down)).Type.IsSolid();
+ return world.GetBlock(Move(location, Direction.Down)).Type.IsSolid()
+ && (location.Y <= Math.Truncate(location.Y) + 0.0001);
}
///
diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs
index f5a0b291..8374c2a3 100644
--- a/MinecraftClient/McTcpClient.cs
+++ b/MinecraftClient/McTcpClient.cs
@@ -37,6 +37,8 @@ namespace MinecraftClient
private Queue steps;
private Queue path;
private Location location;
+ private byte[] yawpitch;
+ private double motionY;
private string host;
private int port;
@@ -410,8 +412,9 @@ namespace MinecraftClient
///
/// The new location
/// If true, the location is relative to the current location
- public void UpdateLocation(Location location)
+ public void UpdateLocation(Location location, byte[] yawpitch)
{
+ this.yawpitch = yawpitch;
UpdateLocation(location, false);
}
@@ -520,13 +523,17 @@ namespace MinecraftClient
{
for (int i = 0; i < 2; i++) //Needs to run at 20 tps; MCC runs at 10 tps
{
- if (steps != null && steps.Count > 0)
- location = steps.Dequeue();
- else if (path != null && path.Count > 0)
- steps = Movement.Move2Steps(location, path.Dequeue());
- else location = Movement.HandleGravity(world, location);
- handler.SendLocationUpdate(location, Movement.IsOnGround(world, location));
+ if (yawpitch == null)
+ {
+ if (steps != null && steps.Count > 0)
+ location = steps.Dequeue();
+ else if (path != null && path.Count > 0)
+ steps = Movement.Move2Steps(location, path.Dequeue(), ref motionY);
+ else location = Movement.HandleGravity(world, location, ref motionY);
+ }
+ handler.SendLocationUpdate(location, Movement.IsOnGround(world, location), yawpitch);
}
+ yawpitch = null; //First 2 updates must be player position AND look, and player must not move (to conform with vanilla)
}
}
}
diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs
index d79a271e..3e3a5d87 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol16.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs
@@ -637,7 +637,7 @@ namespace MinecraftClient.Protocol.Handlers
return false; //Currently not implemented
}
- public bool SendLocationUpdate(Location location, bool onGround)
+ public bool SendLocationUpdate(Location location, bool onGround, byte[] yawpitch)
{
return false; //Currently not implemented
}
diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs
index 0f8cee2d..a3e569e4 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs
@@ -273,7 +273,7 @@ namespace MinecraftClient.Protocol.Handlers
double x = readNextDouble(packetData);
double y = readNextDouble(packetData);
double z = readNextDouble(packetData);
- readData(8, packetData); //Ignore look
+ byte[] yawpitch = readData(8, packetData);
byte locMask = readNextByte(packetData);
if (protocolversion >= MC18Version)
@@ -282,9 +282,9 @@ namespace MinecraftClient.Protocol.Handlers
location.X = (locMask & 1 << 0) != 0 ? location.X + x : x;
location.Y = (locMask & 1 << 1) != 0 ? location.Y + y : y;
location.Z = (locMask & 1 << 2) != 0 ? location.Z + z : z;
- handler.UpdateLocation(location);
+ handler.UpdateLocation(location, yawpitch);
}
- else handler.UpdateLocation(new Location(x, y, z));
+ else handler.UpdateLocation(new Location(x, y, z), yawpitch);
if (protocolversion >= MC19Version)
{
@@ -1513,20 +1513,33 @@ namespace MinecraftClient.Protocol.Handlers
///
/// The new location of the player
/// True if the player is on the ground
+ /// Yaw and pitch (optional and currently not parsed)
/// True if the location update was successfully sent
- public bool SendLocationUpdate(Location location, bool onGround)
+ public bool SendLocationUpdate(Location location, bool onGround, byte[] yawpitch = null)
{
if (Settings.TerrainAndMovements)
{
+ int packetId;
+ if (yawpitch != null && yawpitch.Length == 8)
+ {
+ packetId = protocolversion >= MC19Version ? 0x0D : 0x06;
+ }
+ else
+ {
+ yawpitch = new byte[0];
+ packetId = protocolversion >= MC19Version ? 0x0C : 0x04;
+ }
+
try
{
- SendPacket(protocolversion >= MC19Version ? 0x0C : 0x04, concatBytes(
+ SendPacket(packetId, concatBytes(
getDouble(location.X),
getDouble(location.Y),
protocolversion < MC18Version
? getDouble(location.Y + 1.62)
: new byte[0],
getDouble(location.Z),
+ yawpitch,
new byte[] { onGround ? (byte)1 : (byte)0 }));
return true;
}
diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs
index d8fa3f61..2b9b5502 100644
--- a/MinecraftClient/Protocol/IMinecraftCom.cs
+++ b/MinecraftClient/Protocol/IMinecraftCom.cs
@@ -71,8 +71,10 @@ namespace MinecraftClient.Protocol
/// Send a location update telling that we moved to that location
///
/// The new location
+ /// True if the player is on the ground
+ /// Yaw and pitch (optional and currently not parsed)
/// True if packet was successfully sent
- bool SendLocationUpdate(Location location, bool onGround);
+ bool SendLocationUpdate(Location location, bool onGround, byte[] yawpitch);
///
/// Send a plugin channel packet to the server.
diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs
index fb6b29fc..32870335 100644
--- a/MinecraftClient/Protocol/IMinecraftComHandler.cs
+++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs
@@ -55,7 +55,8 @@ namespace MinecraftClient.Protocol
/// Called when the server sets the new location for the player
///
/// New location of the player
- void UpdateLocation(Location location);
+ /// Yaw and pitch (optional and currently not parsed)
+ void UpdateLocation(Location location, byte[] yawpitch);
///
/// This method is called when the connection has been lost