diff --git a/MinecraftClient/Mapping/MaterialExtensions.cs b/MinecraftClient/Mapping/MaterialExtensions.cs index a3ff5592..e961ebde 100644 --- a/MinecraftClient/Mapping/MaterialExtensions.cs +++ b/MinecraftClient/Mapping/MaterialExtensions.cs @@ -766,6 +766,27 @@ } } + /// + /// Check if the player can climb up this block + /// + /// Material to test + /// True if the material can be climbed on + public static bool CanBeClimbedOn(this Material m) + { + switch (m) + { + case Material.Ladder: + case Material.Vine: + case Material.TwistingVines: + case Material.TwistingVinesPlant: + case Material.WeepingVines: + case Material.WeepingVinesPlant: + return true; + default: + return false; + } + } + /// /// Check if the provided material is a bed /// diff --git a/MinecraftClient/Mapping/Movement.cs b/MinecraftClient/Mapping/Movement.cs index 28de9e7c..2f74cfa6 100644 --- a/MinecraftClient/Mapping/Movement.cs +++ b/MinecraftClient/Mapping/Movement.cs @@ -463,6 +463,8 @@ namespace MinecraftClient.Mapping /* ========= LOCATION PROPERTIES ========= */ + // TODO: Find a way to remove this Hack for Vines here. + /// /// Check if the specified location is on the ground /// @@ -477,7 +479,12 @@ namespace MinecraftClient.Mapping Location down = Move(location, Direction.Down); - bool result = world.GetBlock(down).Type.IsSolid(); + Material currentMaterial = world.GetBlock(down).Type; + + bool result = currentMaterial.IsSolid() + || currentMaterial == Material.TwistingVines || currentMaterial == Material.TwistingVinesPlant + || currentMaterial == Material.WeepingVines || currentMaterial == Material.WeepingVinesPlant + || currentMaterial == Material.Vine; bool northCheck = 1 + Math.Floor(down.Z) - down.Z > 0.7; bool eastCheck = down.X - Math.Floor(down.X) > 0.7; @@ -485,21 +492,95 @@ namespace MinecraftClient.Mapping bool westCheck = 1 + Math.Floor(down.X) - down.X > 0.7; if (!result && northCheck) - result |= world.GetBlock(Move(down, Direction.North)).Type.IsSolid(); + { + Location locationDownNorth = Move(down, Direction.North); + result |= world.GetBlock(locationDownNorth).Type.IsSolid() + || world.GetBlock(locationDownNorth).Type == Material.TwistingVines + || world.GetBlock(locationDownNorth).Type == Material.TwistingVinesPlant + || world.GetBlock(locationDownNorth).Type == Material.WeepingVines + || world.GetBlock(locationDownNorth).Type == Material.WeepingVinesPlant + || world.GetBlock(locationDownNorth).Type == Material.Vine; + } + if (!result && northCheck && eastCheck) - result |= world.GetBlock(Move(down, Direction.NorthEast)).Type.IsSolid(); + { + Location locationDownNorthEast = Move(down, Direction.NorthEast); + result |= world.GetBlock(locationDownNorthEast).Type.IsSolid() + || world.GetBlock(locationDownNorthEast).Type == Material.TwistingVines + || world.GetBlock(locationDownNorthEast).Type == Material.TwistingVinesPlant + || world.GetBlock(locationDownNorthEast).Type == Material.WeepingVines + || world.GetBlock(locationDownNorthEast).Type == Material.WeepingVinesPlant + || world.GetBlock(locationDownNorthEast).Type == Material.Vine; + } + if (!result && eastCheck) - result |= world.GetBlock(Move(down, Direction.East)).Type.IsSolid(); + { + Location locationDownEast = Move(down, Direction.East); + result |= world.GetBlock(locationDownEast).Type.IsSolid() + || world.GetBlock(locationDownEast).Type == Material.TwistingVines + || world.GetBlock(locationDownEast).Type == Material.TwistingVinesPlant + || world.GetBlock(locationDownEast).Type == Material.WeepingVines + || world.GetBlock(locationDownEast).Type == Material.WeepingVinesPlant + || world.GetBlock(locationDownEast).Type == Material.Vine; + } + if (!result && eastCheck && southCheck) - result |= world.GetBlock(Move(down, Direction.SouthEast)).Type.IsSolid(); + { + Location locationDownSouthEast = Move(down, Direction.SouthEast); + result |= world.GetBlock(locationDownSouthEast).Type.IsSolid() + || world.GetBlock(locationDownSouthEast).Type == Material.TwistingVines + || world.GetBlock(locationDownSouthEast).Type == Material.TwistingVinesPlant + || world.GetBlock(locationDownSouthEast).Type == Material.WeepingVines + || world.GetBlock(locationDownSouthEast).Type == Material.WeepingVinesPlant + || world.GetBlock(locationDownSouthEast).Type == Material.Vine; + } + if (!result && southCheck) - result |= world.GetBlock(Move(down, Direction.South)).Type.IsSolid(); + { + Location locationDownSouth = Move(down, Direction.South); + result |= world.GetBlock(locationDownSouth).Type.IsSolid() + || world.GetBlock(locationDownSouth).Type == Material.TwistingVines + || world.GetBlock(locationDownSouth).Type == Material.TwistingVinesPlant + || world.GetBlock(locationDownSouth).Type == Material.WeepingVines + || world.GetBlock(locationDownSouth).Type == Material.WeepingVinesPlant + || world.GetBlock(locationDownSouth).Type == Material.Vine; + } + if (!result && southCheck && westCheck) - result |= world.GetBlock(Move(down, Direction.SouthWest)).Type.IsSolid(); + { + Location locationDownSouthWest = Move(down, Direction.SouthWest); + result |= world.GetBlock(locationDownSouthWest).Type.IsSolid() + || world.GetBlock(locationDownSouthWest).Type == Material.TwistingVines + || world.GetBlock(locationDownSouthWest).Type == Material.TwistingVinesPlant + || world.GetBlock(locationDownSouthWest).Type == Material.WeepingVines + || world.GetBlock(locationDownSouthWest).Type == Material.WeepingVinesPlant + || world.GetBlock(locationDownSouthWest).Type == Material.Vine; + } + + if (!result && westCheck) - result |= world.GetBlock(Move(down, Direction.West)).Type.IsSolid(); + { + Location locationDownWest = Move(down, Direction.West); + result |= world.GetBlock(locationDownWest).Type.IsSolid() + || world.GetBlock(locationDownWest).Type == Material.TwistingVines + || world.GetBlock(locationDownWest).Type == Material.TwistingVinesPlant + || world.GetBlock(locationDownWest).Type == Material.WeepingVines + || world.GetBlock(locationDownWest).Type == Material.WeepingVinesPlant + || world.GetBlock(locationDownWest).Type == Material.Vine; + } + + if (!result && westCheck && northCheck) - result |= world.GetBlock(Move(down, Direction.NorthWest)).Type.IsSolid(); + { + Location locationDownNorthWest = Move(down, Direction.NorthWest); + result |= world.GetBlock(locationDownNorthWest).Type.IsSolid() + || world.GetBlock(locationDownNorthWest).Type == Material.TwistingVines + || world.GetBlock(locationDownNorthWest).Type == Material.TwistingVinesPlant + || world.GetBlock(locationDownNorthWest).Type == Material.WeepingVines + || world.GetBlock(locationDownNorthWest).Type == Material.WeepingVinesPlant + || world.GetBlock(locationDownNorthWest).Type == Material.Vine; + + } return result && (location.Y <= Math.Truncate(location.Y) + 0.0001); } @@ -515,6 +596,17 @@ namespace MinecraftClient.Mapping return world.GetBlock(location).Type.IsLiquid(); } + /// + /// Check if the specified location can be climbed on + /// + /// World for performing check + /// Location to check + /// True if the specified location can be climbed on + public static bool IsClimbing(World world, Location location) + { + return world.GetBlock(location).Type.CanBeClimbedOn(); + } + /// /// Check if the specified location is safe /// @@ -530,9 +622,9 @@ namespace MinecraftClient.Mapping && !world.GetBlock(Move(location, Direction.Down)).Type.CanHarmPlayers() //No fall from a too high place - && (world.GetBlock(Move(location, Direction.Down)).Type.IsSolid() - || world.GetBlock(Move(location, Direction.Down, 2)).Type.IsSolid() - || world.GetBlock(Move(location, Direction.Down, 3)).Type.IsSolid()) + && (world.GetBlock(Move(location, Direction.Down)).Type.IsSolid() || IsClimbing(world, Move(location, Direction.Down)) + || world.GetBlock(Move(location, Direction.Down, 2)).Type.IsSolid() || IsClimbing(world, Move(location, Direction.Down, 2)) + || world.GetBlock(Move(location, Direction.Down, 3)).Type.IsSolid() || IsClimbing(world, Move(location, Direction.Down, 3))) //Not an underwater location && !(world.GetBlock(Move(location, Direction.Up)).Type.IsLiquid()); @@ -553,10 +645,16 @@ namespace MinecraftClient.Mapping { // Move vertical case Direction.Down: - return !IsOnGround(world, location); + return IsClimbing(world, Move(location, Direction.Down)) || !IsOnGround(world, location); case Direction.Up: - return (IsOnGround(world, location) || IsSwimming(world, location)) - && !world.GetBlock(Move(Move(location, Direction.Up), Direction.Up)).Type.IsSolid(); + bool nextTwoBlocks = !world.GetBlock(Move(Move(location, Direction.Up), Direction.Up)).Type.IsSolid(); + + // Check if the current block can be climbed on + if (IsClimbing(world, location)) + // Check if next block after the next one can be climbed uppon + return IsClimbing(world, Move(location, Direction.Up)) || nextTwoBlocks; + + return (IsOnGround(world, location) || IsSwimming(world, location)) && nextTwoBlocks; // Move horizontal case Direction.East: @@ -588,8 +686,8 @@ namespace MinecraftClient.Mapping /// True if a player is able to stand in this location public static bool PlayerFitsHere(World world, Location location) { - return !world.GetBlock(location).Type.IsSolid() - && !world.GetBlock(Move(location, Direction.Up)).Type.IsSolid(); + return (IsClimbing(world, location) && IsClimbing(world, Move(location, Direction.Up))) + || !world.GetBlock(location).Type.IsSolid() && !world.GetBlock(Move(location, Direction.Up)).Type.IsSolid(); } ///