diff --git a/MinecraftClient/Commands/Look.cs b/MinecraftClient/Commands/Look.cs new file mode 100644 index 00000000..2f17c441 --- /dev/null +++ b/MinecraftClient/Commands/Look.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MinecraftClient.Mapping; + +namespace MinecraftClient.Commands +{ + public class Look : Command + { + public override string CMDName { get { return "look"; } } + public override string CMDDesc { get { return "look : look direction or at block."; } } + + public override string Run(McTcpClient handler, string command) + { + if (Settings.TerrainAndMovements) + { + string[] args = getArgs(command); + if (args.Length == 1) + { + return "ok."; + } + else if (args.Length == 2) + { + float yaw = Single.Parse(args[0]), + pitch = Single.Parse(args[1]); + + return $"Looking at YAW: {yaw} PITCH: {pitch}"; + } + else if (args.Length == 3) + { + int x = int.Parse(args[0]), + y = int.Parse(args[1]), + z = int.Parse(args[2]); + + Location block = new Location(x, y, z); + handler.LookAtBlock(block); + + return "Looking at " + block; + } + else return CMDDesc; + } + else return "Please enable terrainandmovements in config to use this command."; + } + } +} diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs index ea43fb49..7e2f651d 100644 --- a/MinecraftClient/McTcpClient.cs +++ b/MinecraftClient/McTcpClient.cs @@ -37,7 +37,8 @@ namespace MinecraftClient private Queue steps; private Queue path; private Location location; - private byte[] yawpitch; + private float? yaw; + private float? pitch; private double motionY; private string host; @@ -412,12 +413,37 @@ namespace MinecraftClient /// /// The new location /// If true, the location is relative to the current location - public void UpdateLocation(Location location, byte[] yawpitch) + public void UpdateLocation(Location location, float yaw, float pitch) { - this.yawpitch = yawpitch; + this.yaw = yaw; + this.pitch = pitch; UpdateLocation(location, false); } + /// + /// Look at specified block + /// + /// The block to look at + public void LookAtBlock(Location block) + { + double dx = block.X - location.X, + dy = block.Y - location.Y, + dz = block.Z - location.Z; + + double r = Math.Sqrt(dx * dx + dy * dy + dz * dz); + + float yaw = Convert.ToSingle(-Math.Atan2(dx, dz) / Math.PI * 180), + pitch = Convert.ToSingle(-Math.Asin(dy / r) / Math.PI * 180); + if (yaw < 0) yaw += 360; + + + ConsoleIO.WriteLineFormatted("YAW: " + yaw); + ConsoleIO.WriteLineFormatted("PITCH: " + pitch); + + UpdateLocation(location, yaw, pitch); + } + + /// /// Move to the specified location /// @@ -533,7 +559,7 @@ namespace MinecraftClient { for (int i = 0; i < 2; i++) //Needs to run at 20 tps; MCC runs at 10 tps { - if (yawpitch == null) + if (yaw == null || pitch == null) { if (steps != null && steps.Count > 0) location = steps.Dequeue(); @@ -541,9 +567,10 @@ namespace MinecraftClient steps = Movement.Move2Steps(location, path.Dequeue(), ref motionY); else location = Movement.HandleGravity(world, location, ref motionY); } - handler.SendLocationUpdate(location, Movement.IsOnGround(world, location), yawpitch); + handler.SendLocationUpdate(location, Movement.IsOnGround(world, location), yaw, pitch); } - yawpitch = null; //First 2 updates must be player position AND look, and player must not move (to conform with vanilla) + yaw = null; + pitch = null; } } } diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 3410ba2c..adddde88 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -88,6 +88,7 @@ + diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index 92f0fc87..150ba7a3 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -635,7 +635,7 @@ namespace MinecraftClient.Protocol.Handlers return false; //Currently not implemented } - public bool SendLocationUpdate(Location location, bool onGround, byte[] yawpitch) + public bool SendLocationUpdate(Location location, bool onGround, float? yaw, float? pitch) { return false; //Currently not implemented } diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index ab6260ff..1bf2051c 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -618,7 +618,8 @@ namespace MinecraftClient.Protocol.Handlers double x = readNextDouble(packetData); double y = readNextDouble(packetData); double z = readNextDouble(packetData); - byte[] yawpitch = readData(8, packetData); + float yaw = readNextFloat(packetData); + float pitch = readNextFloat(packetData); byte locMask = readNextByte(packetData); if (protocolversion >= MC18Version) @@ -627,9 +628,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, yawpitch); + handler.UpdateLocation(location, yaw, pitch); } - else handler.UpdateLocation(new Location(x, y, z), yawpitch); + else handler.UpdateLocation(new Location(x, y, z), yaw, pitch); } if (protocolversion >= MC19Version) @@ -1407,6 +1408,17 @@ namespace MinecraftClient.Protocol.Handlers return BitConverter.ToDouble(rawValue, 0); } + /// + /// Read a float from a cache of bytes and remove it from the cache + /// + /// The float value + private static float readNextFloat(List cache) + { + byte[] rawValue = readData(4, cache); + Array.Reverse(rawValue); //Endianness + return BitConverter.ToSingle(rawValue, 0); + } + /// /// Read an integer from the network /// @@ -1507,6 +1519,19 @@ namespace MinecraftClient.Protocol.Handlers return theDouble; } + /// + /// Get byte array representing a float + /// + /// Floalt to process + /// Array ready to send + private byte[] getFloat(float number) + { + byte[] theFloat = BitConverter.GetBytes(number); + Array.Reverse(theFloat); //Endianness + return theFloat; + } + + /// /// Get byte array with length information prepended to it /// @@ -1889,18 +1914,19 @@ namespace MinecraftClient.Protocol.Handlers /// 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, byte[] yawpitch = null) + public bool SendLocationUpdate(Location location, bool onGround, float? yaw = null, float? pitch = null) { if (Settings.TerrainAndMovements) { PacketOutgoingType packetType; - if (yawpitch != null && yawpitch.Length == 8) + byte[] yawpitch = new byte[0]; + if (yaw != null && pitch != null) { + yawpitch = getFloat((float)yaw).Concat(getFloat((float)pitch)).ToArray(); packetType = PacketOutgoingType.PlayerPositionAndLook; } else { - yawpitch = new byte[0]; packetType = PacketOutgoingType.PlayerPosition; } diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs index 2b9b5502..1a3c8c2e 100644 --- a/MinecraftClient/Protocol/IMinecraftCom.cs +++ b/MinecraftClient/Protocol/IMinecraftCom.cs @@ -72,9 +72,10 @@ namespace MinecraftClient.Protocol /// /// The new location /// True if the player is on the ground - /// Yaw and pitch (optional and currently not parsed) + /// The new yaw (optional) + /// The new pitch (optional) /// True if packet was successfully sent - bool SendLocationUpdate(Location location, bool onGround, byte[] yawpitch); + bool SendLocationUpdate(Location location, bool onGround, float? yaw, float? pitch); /// /// Send a plugin channel packet to the server. diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs index 110e898a..a3d5049e 100644 --- a/MinecraftClient/Protocol/IMinecraftComHandler.cs +++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs @@ -55,8 +55,9 @@ namespace MinecraftClient.Protocol /// Called when the server sets the new location for the player /// /// New location of the player - /// Yaw and pitch (optional and currently not parsed) - void UpdateLocation(Location location, byte[] yawpitch); + /// New yaw + /// New pitch + void UpdateLocation(Location location, float yaw, float pitch); /// /// This method is called when the connection has been lost