/* ========= SIMPLE MOVEMENTS ========= */ /// <summary> /// Check if the player can move in the specified direction /// </summary> /// <param name="world">World the player is currently located in</param> /// <param name="location">Location the player is currently at</param> /// <param name="direction">Direction the player is moving to</param> /// <returns>True if the player can move in the specified direction</returns> public static bool CanMove(World world, Location location, Direction direction) { switch (direction) { // Move vertical case Direction.Down: return(!IsOnGround(world, location)); case Direction.Up: return((IsOnGround(world, location) || IsSwimming(world, location)) && !world.GetBlock(Move(Move(location, Direction.Up), Direction.Up)).Type.IsSolid()); // Move horizontal case Direction.East: case Direction.West: case Direction.South: case Direction.North: return(PlayerFitsHere(world, Move(location, direction))); // Move diagonal case Direction.NorthEast: return(PlayerFitsHere(world, Move(location, Direction.North)) && PlayerFitsHere(world, Move(location, Direction.East)) && PlayerFitsHere(world, Move(location, direction))); case Direction.SouthEast: return(PlayerFitsHere(world, Move(location, Direction.South)) && PlayerFitsHere(world, Move(location, Direction.East)) && PlayerFitsHere(world, Move(location, direction))); case Direction.SouthWest: return(PlayerFitsHere(world, Move(location, Direction.South)) && PlayerFitsHere(world, Move(location, Direction.West)) && PlayerFitsHere(world, Move(location, direction))); case Direction.NorthWest: return(PlayerFitsHere(world, Move(location, Direction.North)) && PlayerFitsHere(world, Move(location, Direction.West)) && PlayerFitsHere(world, Move(location, direction))); default: throw new ArgumentException("Unknown direction", "direction"); } }
/* ========= PATHFINDING METHODS ========= */ /// <summary> /// Handle movements due to gravity /// </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, 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)) { 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, ref motionY, true).Dequeue(); } return(location); }
/// <summary> /// Check if the specified location implies swimming /// </summary> /// <param name="world">World for performing check</param> /// <param name="location">Location to check</param> /// <returns>True if the specified location implies swimming</returns> public static bool IsSwimming(World world, Location location) { return(world.GetBlock(location).Type.IsLiquid()); }
/* ========= LOCATION PROPERTIES ========= */ /// <summary> /// Check if the specified location is on the ground /// </summary> /// <param name="world">World for performing check</param> /// <param name="location">Location to check</param> /// <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() && (location.Y <= Math.Truncate(location.Y) + 0.0001)); }
/// <summary> /// Evaluates if a player fits in this location /// </summary> /// <param name="world">Current world</param> /// <param name="location">Location to check</param> /// <returns>True if a player is able to stand in this location</returns> public static bool PlayerFitsHere(World world, Location location) { return(!world.GetBlock(location).Type.IsSolid() && !world.GetBlock(Move(location, Direction.Up)).Type.IsSolid()); }
/* ========= LOCATION PROPERTIES ========= */ /// <summary> /// Check if the specified location is on the ground /// </summary> /// <param name="world">World for performing check</param> /// <param name="location">Location to check</param> /// <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()); }
/* ========= SIMPLE MOVEMENTS ========= */ /// <summary> /// Check if the player can move in the specified direction /// </summary> /// <param name="world">World the player is currently located in</param> /// <param name="location">Location the player is currently at</param> /// <param name="direction">Direction the player is moving to</param> /// <returns>True if the player can move in the specified direction</returns> public static bool CanMove(World world, Location location, Direction direction) { switch (direction) { case Direction.Down: return !IsOnGround(world, location); case Direction.Up: return (IsOnGround(world, location) || IsSwimming(world, location)) && !world.GetBlock(Move(Move(location, Direction.Up), Direction.Up)).Type.IsSolid(); case Direction.East: case Direction.West: case Direction.South: case Direction.North: return !world.GetBlock(Move(location, direction)).Type.IsSolid() && !world.GetBlock(Move(Move(location, direction), Direction.Up)).Type.IsSolid(); default: throw new ArgumentException("Unknown direction", "direction"); } }
/// <summary> /// Check if the specified location implies swimming /// </summary> /// <param name="world">World for performing check</param> /// <param name="location">Location to check</param> /// <returns>True if the specified location implies swimming</returns> public static bool IsSwimming(World world, Location location) { return world.GetBlock(location).Type.IsLiquid(); }
/// <summary> /// Check if the specified location is safe /// </summary> /// <param name="world">World for performing check</param> /// <param name="location">Location to check</param> /// <returns>True if the destination location won't directly harm the player</returns> public static bool IsSafe(World world, Location location) { return //No block that can harm the player !world.GetBlock(location).Type.CanHarmPlayers() && !world.GetBlock(Move(location, Direction.Up)).Type.CanHarmPlayers() && !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()) //Not an underwater location && !(world.GetBlock(Move(location, Direction.Up)).Type.IsLiquid()); }
/* ========= LOCATION PROPERTIES ========= */ /// <summary> /// Check if the specified location is on the ground /// </summary> /// <param name="world">World for performing check</param> /// <param name="location">Location to check</param> /// <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(); }
/* ========= PATHFINDING METHODS ========= */ /// <summary> /// Handle movements due to gravity /// </summary> /// <param name="world">World the player is currently located in</param> /// <param name="location">Location the player is currently at</param> /// <returns>Updated location after applying gravity</returns> public static Location HandleGravity(World world, Location location) { Location onFoots = new Location(location.X, Math.Floor(location.Y), location.Z); Location belowFoots = Move(location, Direction.Down); if (!IsOnGround(world, location) && !IsSwimming(world, location)) location = Move2Steps(location, belowFoots).Dequeue(); else if (!(world.GetBlock(onFoots).Type.IsSolid())) location = Move2Steps(location, onFoots).Dequeue(); return location; }