using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Mapping
{
///
/// Represents a location into a Minecraft world
///
public struct Location
{
///
/// The X Coordinate
///
public double X;
///
/// The Y Coordinate (vertical)
///
public double Y;
///
/// The Z coordinate
///
public double Z;
///
/// Get location with zeroed coordinates
///
public static Location Zero
{
get
{
return new Location(0, 0, 0);
}
}
///
/// Create a new location
///
public Location(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
///
/// Create a new location
///
/// Location of the chunk into the world
/// Location of the chunk into the world
/// Location of the block into the chunk
/// Location of the block into the world
/// Location of the block into the chunk
public Location(int chunkX, int chunkZ, int blockX, int blockY, int blockZ)
{
X = chunkX * Chunk.SizeX + blockX;
Y = blockY;
Z = chunkZ * Chunk.SizeZ + blockZ;
}
///
/// The X index of the corresponding chunk in the world
///
public int ChunkX
{
get
{
return (int)Math.Floor(X / Chunk.SizeX);
}
}
///
/// The Y index of the corresponding chunk in the world
///
public int ChunkY
{
get
{
return (int)Math.Floor(Y / Chunk.SizeY);
}
}
///
/// The Z index of the corresponding chunk in the world
///
public int ChunkZ
{
get
{
return (int)Math.Floor(Z / Chunk.SizeZ);
}
}
///
/// The X index of the corresponding block in the corresponding chunk of the world
///
public int ChunkBlockX
{
get
{
return ((int)Math.Floor(X) % Chunk.SizeX + Chunk.SizeX) % Chunk.SizeX;
}
}
///
/// The Y index of the corresponding block in the corresponding chunk of the world
///
public int ChunkBlockY
{
get
{
return ((int)Math.Floor(Y) % Chunk.SizeY + Chunk.SizeY) % Chunk.SizeY;
}
}
///
/// The Z index of the corresponding block in the corresponding chunk of the world
///
public int ChunkBlockZ
{
get
{
return ((int)Math.Floor(Z) % Chunk.SizeZ + Chunk.SizeZ) % Chunk.SizeZ;
}
}
///
/// Get a squared distance to the specified location
///
/// Other location for computing distance
/// Distance to the specified location, without using a square root
public double DistanceSquared(Location location)
{
return ((X - location.X) * (X - location.X))
+ ((Y - location.Y) * (Y - location.Y))
+ ((Z - location.Z) * (Z - location.Z));
}
///
/// Get exact distance to the specified location
///
/// Other location for computing distance
/// Distance to the specified location, with square root so lower performances
public double Distance(Location location)
{
return Math.Sqrt(DistanceSquared(location));
}
///
/// Considering the current location as Feet location, calculate Eyes location
///
/// Player Eyes location
public Location EyesLocation()
{
return this + new Location(0, 1.62, 0);
}
///
/// Compare two locations. Locations are equals if the integer part of their coordinates are equals.
///
/// Object to compare to
/// TRUE if the locations are equals
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (obj is Location)
{
return ((int)this.X) == ((int)((Location)obj).X)
&& ((int)this.Y) == ((int)((Location)obj).Y)
&& ((int)this.Z) == ((int)((Location)obj).Z);
}
return false;
}
///
/// Compare two locations. Locations are equals if the integer part of their coordinates are equals.
///
/// First location to compare
/// Second location to compare
/// TRUE if the locations are equals
public static bool operator ==(Location loc1, Location loc2)
{
if (loc1 == null && loc2 == null)
return true;
if (loc1 == null || loc2 == null)
return false;
return loc1.Equals(loc2);
}
///
/// Compare two locations. Locations are not equals if the integer part of their coordinates are not equals.
///
/// First location to compare
/// Second location to compare
/// TRUE if the locations are equals
public static bool operator !=(Location loc1, Location loc2)
{
if (loc1 == null && loc2 == null)
return true;
if (loc1 == null || loc2 == null)
return false;
return !loc1.Equals(loc2);
}
///
/// Sums two locations and returns the result.
///
///
/// Thrown if one of the provided location is null
///
/// First location to sum
/// Second location to sum
/// Sum of the two locations
public static Location operator +(Location loc1, Location loc2)
{
return new Location
(
loc1.X + loc2.X,
loc1.Y + loc2.Y,
loc1.Z + loc2.Z
);
}
///
/// Substract a location to another
///
///
/// Thrown if one of the provided location is null
///
/// First location
/// Location to substract to the first one
/// Sum of the two locations
public static Location operator -(Location loc1, Location loc2)
{
return new Location
(
loc1.X - loc2.X,
loc1.Y - loc2.Y,
loc1.Z - loc2.Z
);
}
///
/// Multiply a location by a scalar value
///
/// Location to multiply
/// Scalar value
/// Product of the location and the scalar value
public static Location operator *(Location loc, double val)
{
return new Location
(
loc.X * val,
loc.Y * val,
loc.Z * val
);
}
///
/// Divide a location by a scalar value
///
/// Location to divide
/// Scalar value
/// Result of the division
public static Location operator /(Location loc, double val)
{
return new Location
(
loc.X / val,
loc.Y / val,
loc.Z / val
);
}
///
/// DO NOT USE. Defined to comply with C# requirements requiring a GetHashCode() when overriding Equals() or ==
///
///
/// A modulo will be applied if the location is outside the following ranges:
/// X: -4096 to +4095
/// Y: -32 to +31
/// Z: -4096 to +4095
///
/// A simplified version of the location
public override int GetHashCode()
{
return (((int)X) & ~((~0) << 13)) << 19
| (((int)Y) & ~((~0) << 13)) << 13
| (((int)Z) & ~((~0) << 06)) << 00;
}
///
/// Convert the location into a string representation
///
/// String representation of the location
public override string ToString()
{
return String.Format("X:{0} Y:{1} Z:{2}", X, Y, Z);
}
}
}