227 lines
8.1 KiB
Java
Raw Normal View History

package net.knarcraft.stargate.container;
import net.knarcraft.stargate.utility.DirectionHelper;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
2021-10-13 13:35:56 +02:00
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.type.Sign;
import org.bukkit.util.Vector;
/**
* This class represents a block location
*
* <p>The BlockLocation class is basically a Location with some extra functionality.
* Warning: Because of differences in the equals methods between Location and BlockLocation, a BlockLocation which
2021-10-13 13:35:56 +02:00
* equals another BlockLocation does not necessarily equal the same BlockLocation if treated as a Location.</p>
*/
public class BlockLocation extends Location {
private BlockLocation parent = null;
/**
* Creates a new block location
*
* @param world <p>The world the block exists in</p>
* @param x <p>The x coordinate of the block</p>
* @param y <p>The y coordinate of the block</p>
* @param z <p>The z coordinate of the block</p>
*/
public BlockLocation(World world, int x, int y, int z) {
super(world, x, y, z);
}
/**
2021-10-13 13:35:56 +02:00
* Creates a block location from a block
*
2021-10-13 13:35:56 +02:00
* @param block <p>The block to get the location of</p>
*/
public BlockLocation(Block block) {
super(block.getWorld(), block.getX(), block.getY(), block.getZ());
}
/**
2021-10-13 13:35:56 +02:00
* Gets a block location from a string
*
* @param world <p>The world the block exists in</p>
2021-10-13 13:35:56 +02:00
* @param string <p>A comma separated list of x, y and z coordinates as integers</p>
*/
public BlockLocation(World world, String string) {
super(world, Integer.parseInt(string.split(",")[0]), Integer.parseInt(string.split(",")[1]),
Integer.parseInt(string.split(",")[2]));
}
/**
2021-10-13 13:35:56 +02:00
* Creates a new block location in a relative position to this block location
*
2021-10-13 13:35:56 +02:00
* @param x <p>The number of blocks to move in the x-direction</p>
* @param y <p>The number of blocks to move in the y-direction</p>
* @param z <p>The number of blocks to move in the z-direction</p>
* @return <p>A new block location</p>
*/
public BlockLocation makeRelativeBlockLocation(int x, int y, int z) {
return (BlockLocation) this.clone().add(x, y, z);
}
/**
2021-10-13 13:35:56 +02:00
* Creates a location in a relative position to this block location
*
2021-10-13 13:35:56 +02:00
* @param x <p>The number of blocks to move in the x-direction</p>
* @param y <p>The number of blocks to move in the y-direction</p>
* @param z <p>The z position relative to this block's position</p>
2021-10-13 13:35:56 +02:00
* @param yaw <p>The number of blocks to move in the z-direction</p>
* @return <p>A new location</p>
*/
public Location makeRelativeLocation(double x, double y, double z, float yaw) {
Location newLocation = this.clone();
newLocation.setYaw(yaw);
newLocation.setPitch(0);
return newLocation.add(x, y, z);
}
/**
* Gets a location relative to this block location
*
* @param relativeVector <p>The relative block vector describing the relative location</p>
* @param yaw <p>The yaw pointing outwards from a portal (in the relative vector's out direction)</p>
* @return <p>A location relative to this location</p>
*/
public BlockLocation getRelativeLocation(RelativeBlockVector relativeVector, double yaw) {
Vector realVector = DirectionHelper.getCoordinateVectorFromRelativeVector(relativeVector.getRight(),
relativeVector.getDown(), relativeVector.getOut(), yaw);
return makeRelativeBlockLocation(realVector.getBlockX(), realVector.getBlockY(), realVector.getBlockZ());
}
/**
* Makes a location relative to the current location according to given parameters
*
* <p>Out goes in the direction of the yaw. Right goes in the direction of (yaw - 90) degrees.
2021-10-13 13:35:56 +02:00
* Depth goes downwards following the -y direction.</p>
*
* @param right <p>The amount of blocks to go right when looking towards a portal</p>
* @param down <p>The amount of blocks to go downwards when looking towards a portal</p>
* @param out <p>The amount of blocks to go outwards when looking towards a portal</p>
* @param portalYaw <p>The yaw when looking out from the portal</p>
* @return A new location relative to this block location
*/
public Location getRelativeLocation(double right, double down, double out, float portalYaw) {
Vector realVector = DirectionHelper.getCoordinateVectorFromRelativeVector(right, down, out, portalYaw);
return makeRelativeLocation(0.5 + realVector.getBlockX(), realVector.getBlockY(),
0.5 + realVector.getBlockZ(), portalYaw);
}
/**
2021-10-13 13:35:56 +02:00
* Gets the type of block at this block location
*
2021-10-13 13:35:56 +02:00
* @return <p>The block's material type</p>
*/
public Material getType() {
return this.getBlock().getType();
}
/**
2021-10-13 13:35:56 +02:00
* Sets the type of block at this location
*
2021-10-13 13:35:56 +02:00
* @param type <p>The block's new material type</p>
*/
public void setType(Material type) {
this.getBlock().setType(type);
}
/**
* Gets the location representing this block location
*
* @return <p>The location representing this block location</p>
*/
public Location getLocation() {
return this.clone();
}
/**
* Gets this block location's parent block
*
2021-10-13 13:35:56 +02:00
* <p>The parent block is the block the item at this block location is attached to. Usually this is the block a
* sign or wall sign is attached to.</p>
*
* @return <p>This block location's parent block</p>
*/
public Block getParent() {
if (parent == null) {
findParent();
}
if (parent == null) {
return null;
}
return parent.getBlock();
}
/**
* Tries to find the parent block location
*
* <p>If this block location is a sign, the parent is the block location of the block the sign is connected to.</p>
*/
private void findParent() {
int offsetX = 0;
int offsetY = 0;
int offsetZ = 0;
BlockData blockData = getBlock().getBlockData();
2021-10-13 13:35:56 +02:00
if (blockData instanceof Directional) {
//Get the offset of the block "behind" this block
BlockFace facing = ((Directional) blockData).getFacing().getOppositeFace();
offsetX = facing.getModX();
offsetZ = facing.getModZ();
} else if (blockData instanceof Sign) {
2021-10-13 13:35:56 +02:00
//Get offset the block beneath the sign
offsetY = -1;
} else {
return;
}
parent = this.makeRelativeBlockLocation(offsetX, offsetY, offsetZ);
}
@Override
public String toString() {
return String.valueOf(this.getBlockX()) + ',' + this.getBlockY() + ',' + this.getBlockZ();
}
@Override
public int hashCode() {
int result = 18;
result = result * 27 + this.getBlockX();
result = result * 27 + this.getBlockY();
result = result * 27 + this.getBlockZ();
if (this.getWorld() != null) {
result = result * 27 + this.getWorld().getName().hashCode();
}
return result;
}
@Override
2021-10-13 13:35:56 +02:00
public boolean equals(Object object) {
if (this == object) {
return true;
}
2021-10-13 13:35:56 +02:00
if (object == null || getClass() != object.getClass()) {
return false;
}
2021-10-13 13:35:56 +02:00
BlockLocation blockLocation = (BlockLocation) object;
World thisWorld = this.getWorld();
World otherWorld = blockLocation.getWorld();
2021-10-13 13:35:56 +02:00
//Check if the worlds of the two locations match
boolean worldsEqual = (thisWorld == null && otherWorld == null) || ((thisWorld != null && otherWorld != null)
&& thisWorld == otherWorld);
2021-10-13 13:35:56 +02:00
//As this is a block location, only the block coordinates are compared
return blockLocation.getBlockX() == this.getBlockX() && blockLocation.getBlockY() == this.getBlockY() &&
blockLocation.getBlockZ() == this.getBlockZ() && worldsEqual;
}
}