mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Implement more realisic fall to ground
Should help moving around in servers using anti-cheat plugins. See #195
This commit is contained in:
parent
8ccc5d5af2
commit
a344ac4101
6 changed files with 85 additions and 30 deletions
|
|
@ -17,15 +17,25 @@ namespace MinecraftClient.Mapping
|
|||
/// </summary>
|
||||
/// <param name="world">World the player is currently located in</param>
|
||||
/// <param name="location">Location the player is currently at</param>
|
||||
/// <param name="motionY">Current vertical motion speed</param>
|
||||
/// <returns>Updated location after applying gravity</returns>
|
||||
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,13 +74,33 @@ namespace MinecraftClient.Mapping
|
|||
/// </remarks>
|
||||
/// <param name="start">Start location</param>
|
||||
/// <param name="goal">Destination location</param>
|
||||
/// <param name="motionY">Current vertical motion speed</param>
|
||||
/// <param name="falling">Specify if performing falling steps</param>
|
||||
/// <param name="stepsByBlock">Amount of steps by block</param>
|
||||
/// <returns>A list of locations corresponding to the requested steps</returns>
|
||||
public static Queue<Location> Move2Steps(Location start, Location goal, int stepsByBlock = 8)
|
||||
public static Queue<Location> Move2Steps(Location start, Location goal, ref double motionY, bool falling = false, int stepsByBlock = 8)
|
||||
{
|
||||
if (stepsByBlock <= 0)
|
||||
stepsByBlock = 1;
|
||||
|
||||
if (falling)
|
||||
{
|
||||
//Use MC-Like falling algorithm
|
||||
double Y = start.Y;
|
||||
Queue<Location> fallSteps = new Queue<Location>();
|
||||
fallSteps.Enqueue(start);
|
||||
double motionPrev = motionY;
|
||||
motionY -= 0.08D;
|
||||
motionY *= 0.9800000190734863D;
|
||||
Y += motionY;
|
||||
if (Y < goal.Y)
|
||||
return new Queue<Location>(new[] { goal });
|
||||
else return new Queue<Location>(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;
|
||||
|
|
@ -84,6 +114,7 @@ namespace MinecraftClient.Mapping
|
|||
}
|
||||
else return new Queue<Location>(new[] { goal });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate a path from the start location to the destination location
|
||||
|
|
@ -163,7 +194,8 @@ namespace MinecraftClient.Mapping
|
|||
/// <returns>True if the specified location is on the ground</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ namespace MinecraftClient
|
|||
private Queue<Location> steps;
|
||||
private Queue<Location> path;
|
||||
private Location location;
|
||||
private byte[] yawpitch;
|
||||
private double motionY;
|
||||
|
||||
private string host;
|
||||
private int port;
|
||||
|
|
@ -410,8 +412,9 @@ namespace MinecraftClient
|
|||
/// </summary>
|
||||
/// <param name="location">The new location</param>
|
||||
/// <param name="relative">If true, the location is relative to the current location</param>
|
||||
public void UpdateLocation(Location location)
|
||||
public void UpdateLocation(Location location, byte[] yawpitch)
|
||||
{
|
||||
this.yawpitch = yawpitch;
|
||||
UpdateLocation(location, false);
|
||||
}
|
||||
|
||||
|
|
@ -519,14 +522,18 @@ namespace MinecraftClient
|
|||
lock (locationLock)
|
||||
{
|
||||
for (int i = 0; i < 2; i++) //Needs to run at 20 tps; MCC runs at 10 tps
|
||||
{
|
||||
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());
|
||||
else location = Movement.HandleGravity(world, location);
|
||||
handler.SendLocationUpdate(location, Movement.IsOnGround(world, location));
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|||
/// </summary>
|
||||
/// <param name="location">The new location of the player</param>
|
||||
/// <param name="onGround">True if the player is on the ground</param>
|
||||
/// <param name="yawpitch">Yaw and pitch (optional and currently not parsed)</param>
|
||||
/// <returns>True if the location update was successfully sent</returns>
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,8 +71,10 @@ namespace MinecraftClient.Protocol
|
|||
/// Send a location update telling that we moved to that location
|
||||
/// </summary>
|
||||
/// <param name="location">The new location</param>
|
||||
/// <param name="onGround">True if the player is on the ground</param>
|
||||
/// <param name="yawpitch">Yaw and pitch (optional and currently not parsed)</param>
|
||||
/// <returns>True if packet was successfully sent</returns>
|
||||
bool SendLocationUpdate(Location location, bool onGround);
|
||||
bool SendLocationUpdate(Location location, bool onGround, byte[] yawpitch);
|
||||
|
||||
/// <summary>
|
||||
/// Send a plugin channel packet to the server.
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ namespace MinecraftClient.Protocol
|
|||
/// Called when the server sets the new location for the player
|
||||
/// </summary>
|
||||
/// <param name="location">New location of the player</param>
|
||||
void UpdateLocation(Location location);
|
||||
/// <param name="yawpitch">Yaw and pitch (optional and currently not parsed)</param>
|
||||
void UpdateLocation(Location location, byte[] yawpitch);
|
||||
|
||||
/// <summary>
|
||||
/// This method is called when the connection has been lost
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue