/**
* HitBlox.java - Class for getting blocks along line of sight
*
* NOTES: This class is designed to handle the annoying parts of the seemingly
* simple task of getting the coordinates of the block a player is currently
* aimed at. This class abstracts the simpler tasks of finding the current
* target block and the adjacent unoccupied block to their own methods, but it
* also provides a public getNextBlock method for processing the entire
* line-of-sight from the player for more specialized tasks. This method can be
* used exactly as it is in getTargetBlock, for instance.
*
* WARNING: Servers with map coordinate bugs may experience a one or more block
* inaccuracy when in affected parts of the world. A good way to test areas for
* the offset bug is to use Chrisinajar's Magic Carpet plugin.
*
* Contact: For questions, contact Ho0ber@gmail.com or channel #hey0 on
* irc.esper.net
*
* @author Ho0ber
*/
public class HitBlox {
private Location player_loc;
private double rot_x, rot_y, view_height;
private double length, h_length, step;
private int range;
private double x_offset, y_offset, z_offset;
private int last_x, last_y, last_z;
private int target_x, target_y, target_z, target_type;
/**
* Constructor requiring player, uses default values
*
* @param in_player
*/
public HitBlox(Player in_player) {
init(in_player.getLocation(), 200, 0.2, 1.65); // Reasonable default
// values
}
/**
* Constructor requiring location, uses default values
*
* @param in_location
*/
public HitBlox(Location in_location) {
init(in_location, 200, 0.2, 0);
}
/**
* Constructor requiring player, max range, and a stepping value
*
* @param in_player
* @param in_range
* @param in_step
*/
public HitBlox(Player in_player, int in_range, double in_step) {
init(in_player.getLocation(), in_range, in_step, 1.65);
}
/**
* Constructor requiring location, max range, and a stepping value
*
* @param in_location
* @param in_range
* @param in_step
*/
public HitBlox(Location in_location, int in_range, double in_step) {
init(in_location, in_range, in_step, 0);
}
/**
* Initialization method
*
* @param in_location
* @param in_range
* @param in_step
* @param in_view_height
*/
public void init(Location in_location, int in_range, double in_step, double in_view_height) {
player_loc = in_location;
view_height = in_view_height;
range = in_range;
step = in_step;
length = 0;
rot_x = (player_loc.rotX + 90) % 360;
rot_y = player_loc.rotY * -1;
target_x = etc.floor(player_loc.x);
target_y = etc.floor(player_loc.y + view_height);
target_z = etc.floor(player_loc.z);
last_x = target_x;
last_y = target_y;
last_z = target_z;
}
/**
* Returns the block at the cursor, or null if out of range
*
* @return Block
*/
public Block getTargetBlock() {
while ((getNextBlock() != null) && (getCurBlock().getType() == 0))
;
return getCurBlock();
}
/**
* Sets the type of the block at the cursor
*
* @param type
*/
public void setTargetBlock(int type) {
while ((getNextBlock() != null) && (getCurBlock().getType() == 0))
;
if (getCurBlock() != null)
etc.getServer().setBlockAt(type, target_x, target_y, target_z);
}
/**
* Returns the block attached to the face at the cursor, or null if out of
* range
*
* @return Block
*/
public Block getFaceBlock() {
while ((getNextBlock() != null) && (getCurBlock().getType() == 0))
;
if (getCurBlock() != null)
return getLastBlock();
else
return null;
}
/**
* Sets the type of the block attached to the face at the cursor
*
* @param type
*/
public void setFaceBlock(int type) {
while ((getNextBlock() != null) && (getCurBlock().getType() == 0))
;
if (getCurBlock() != null)
etc.getServer().setBlockAt(type, last_x, last_y, last_z);
}
/**
* Returns STEPS forward along line of vision and returns block
*
* @return Block
*/
public Block getNextBlock() {
last_x = target_x;
last_y = target_y;
last_z = target_z;
do {
length += step;
h_length = (length * Math.cos(Math.toRadians(rot_y)));
y_offset = (length * Math.sin(Math.toRadians(rot_y)));
x_offset = (h_length * Math.cos(Math.toRadians(rot_x)));
z_offset = (h_length * Math.sin(Math.toRadians(rot_x)));
target_x = etc.floor(x_offset + player_loc.x);
target_y = etc.floor(y_offset + player_loc.y + view_height);
target_z = etc.floor(z_offset + player_loc.z);
} while ((length <= range) && ((target_x == last_x) && (target_y == last_y) && (target_z == last_z)));
if (length > range)
return null;
return etc.getServer().getBlockAt(target_x, target_y, target_z);
}
/**
* Returns the current block along the line of vision
*
* @return Block
*/
public Block getCurBlock() {
if (length > range)
return null;
else
return etc.getServer().getBlockAt(target_x, target_y, target_z);
}
/**
* Sets current block type id
*
* @param type
*/
public void setCurBlock(int type) {
if (getCurBlock() != null)
etc.getServer().setBlockAt(type, target_x, target_y, target_z);
}
/**
* Returns the previous block along the line of vision
*
* @return Block
*/
public Block getLastBlock() {
return etc.getServer().getBlockAt(last_x, last_y, last_z);
}
/**
* Sets previous block type id
*
* @param type
*/
public void setLastBlock(int type) {
if (getLastBlock() != null)
etc.getServer().setBlockAt(type, last_x, last_y, last_z);
}
}