2011-01-19 09:12:05 +00:00
|
|
|
/*
|
2014-04-04 22:03:18 +00:00
|
|
|
* WorldEdit, a Minecraft world manipulation toolkit
|
|
|
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
|
|
* Copyright (C) WorldEdit team and contributors
|
2011-01-19 09:12:05 +00:00
|
|
|
*
|
2014-04-04 22:03:18 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU Lesser General Public License as published by the
|
|
|
|
* Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
2011-01-19 09:12:05 +00:00
|
|
|
*
|
2014-04-04 22:03:18 +00:00
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
|
|
* for more details.
|
2011-01-19 09:12:05 +00:00
|
|
|
*
|
2014-04-04 22:03:18 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2011-01-19 09:12:05 +00:00
|
|
|
|
|
|
|
package com.sk89q.worldedit.util;
|
|
|
|
|
2014-04-05 09:59:38 +00:00
|
|
|
import com.sk89q.worldedit.*;
|
2011-09-19 01:49:45 +00:00
|
|
|
import com.sk89q.worldedit.blocks.BlockID;
|
2011-01-19 09:12:05 +00:00
|
|
|
import com.sk89q.worldedit.blocks.BlockType;
|
2014-04-05 05:40:29 +00:00
|
|
|
import com.sk89q.worldedit.entity.Entity;
|
2014-04-05 09:59:38 +00:00
|
|
|
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
2011-01-19 09:12:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This class uses an inefficient method to figure out what block a player
|
|
|
|
* is looking towards.
|
|
|
|
*
|
|
|
|
* Originally written by toi. It was ported to WorldEdit and trimmed down by
|
|
|
|
* sk89q. Thanks to Raphfrk for optimization of toi's original class.
|
|
|
|
*
|
|
|
|
* @author toi
|
|
|
|
*/
|
|
|
|
public class TargetBlock {
|
|
|
|
private LocalWorld world;
|
|
|
|
private int maxDistance;
|
|
|
|
private double checkDistance, curDistance;
|
|
|
|
private Vector targetPos = new Vector();
|
|
|
|
private Vector targetPosDouble = new Vector();
|
|
|
|
private Vector prevPos = new Vector();
|
|
|
|
private Vector offset = new Vector();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor requiring a player, uses default values
|
|
|
|
*
|
|
|
|
* @param player player to work with
|
|
|
|
*/
|
|
|
|
public TargetBlock(LocalPlayer player) {
|
2014-06-26 23:56:40 +00:00
|
|
|
this.world = LocalWorldAdapter.adapt(player.getWorld());
|
2011-01-19 09:12:05 +00:00
|
|
|
this.setValues(player.getPosition(), player.getYaw(), player.getPitch(),
|
|
|
|
300, 1.65, 0.2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor requiring a player, max distance and a checking distance
|
2014-04-05 05:40:29 +00:00
|
|
|
*
|
2011-01-19 09:12:05 +00:00
|
|
|
* @param player LocalPlayer to work with
|
|
|
|
* @param maxDistance how far it checks for blocks
|
|
|
|
* @param checkDistance how often to check for blocks, the smaller the more precise
|
|
|
|
*/
|
|
|
|
public TargetBlock(LocalPlayer player, int maxDistance, double checkDistance) {
|
2014-04-05 05:40:29 +00:00
|
|
|
this((Entity) player, maxDistance, checkDistance);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor requiring a player, max distance and a checking distance
|
|
|
|
*
|
|
|
|
* @param player LocalPlayer to work with
|
|
|
|
* @param maxDistance how far it checks for blocks
|
|
|
|
* @param checkDistance how often to check for blocks, the smaller the more precise
|
|
|
|
*/
|
|
|
|
public TargetBlock(Entity player, int maxDistance, double checkDistance) {
|
2014-06-26 23:56:40 +00:00
|
|
|
this.world = LocalWorldAdapter.adapt(player.getWorld());
|
2011-01-19 09:12:05 +00:00
|
|
|
this.setValues(player.getPosition(), player.getYaw(), player.getPitch(),
|
|
|
|
maxDistance, 1.65, checkDistance);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the values, all constructors uses this function
|
|
|
|
*
|
|
|
|
* @param loc location of the view
|
|
|
|
* @param xRotation
|
|
|
|
* @param yRotation
|
|
|
|
* @param maxDistance how far it checks for blocks
|
2014-04-05 05:40:29 +00:00
|
|
|
* @param viewHeight where the view is positioned in y-axis
|
2011-01-19 09:12:05 +00:00
|
|
|
* @param checkDistance how often to check for blocks, the smaller the more precise
|
|
|
|
*/
|
|
|
|
private void setValues(Vector loc, double xRotation, double yRotation,
|
|
|
|
int maxDistance, double viewHeight, double checkDistance) {
|
|
|
|
this.maxDistance = maxDistance;
|
|
|
|
this.checkDistance = checkDistance;
|
|
|
|
this.curDistance = 0;
|
|
|
|
xRotation = (xRotation + 90) % 360;
|
|
|
|
yRotation = yRotation * -1;
|
|
|
|
|
|
|
|
double h = (checkDistance * Math.cos(Math.toRadians(yRotation)));
|
2011-11-23 01:29:48 +00:00
|
|
|
|
2011-01-19 09:12:05 +00:00
|
|
|
offset = new Vector((h * Math.cos(Math.toRadians(xRotation))),
|
|
|
|
(checkDistance * Math.sin(Math.toRadians(yRotation))),
|
|
|
|
(h * Math.sin(Math.toRadians(xRotation))));
|
|
|
|
|
|
|
|
targetPosDouble = loc.add(0, viewHeight, 0);
|
|
|
|
targetPos = targetPosDouble.toBlockPoint();
|
|
|
|
prevPos = targetPos;
|
|
|
|
}
|
|
|
|
|
2011-06-22 22:28:56 +00:00
|
|
|
/**
|
|
|
|
* Returns any block at the sight. Returns null if out of range or if no
|
|
|
|
* viable target was found. Will try to return the last valid air block it finds.
|
|
|
|
*
|
|
|
|
* @return Block
|
|
|
|
*/
|
|
|
|
public BlockWorldVector getAnyTargetBlock() {
|
|
|
|
boolean searchForLastBlock = true;
|
|
|
|
BlockWorldVector lastBlock = null;
|
|
|
|
while (getNextBlock() != null) {
|
2011-09-19 01:49:45 +00:00
|
|
|
if (world.getBlockType(getCurrentBlock()) == BlockID.AIR) {
|
2011-11-23 01:29:48 +00:00
|
|
|
if (searchForLastBlock) {
|
2011-06-22 22:28:56 +00:00
|
|
|
lastBlock = getCurrentBlock();
|
2011-12-13 03:20:31 +00:00
|
|
|
if (lastBlock.getBlockY() <= 0 || lastBlock.getBlockY() >= world.getMaxY()) {
|
2011-06-22 22:28:56 +00:00
|
|
|
searchForLastBlock = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BlockWorldVector currentBlock = getCurrentBlock();
|
|
|
|
return (currentBlock != null ? currentBlock : lastBlock);
|
|
|
|
}
|
2011-11-23 01:29:48 +00:00
|
|
|
|
2011-01-19 09:12:05 +00:00
|
|
|
/**
|
|
|
|
* Returns the block at the sight. Returns null if out of range or if no
|
|
|
|
* viable target was found
|
|
|
|
*
|
|
|
|
* @return Block
|
|
|
|
*/
|
|
|
|
public BlockWorldVector getTargetBlock() {
|
2011-11-23 01:29:48 +00:00
|
|
|
while (getNextBlock() != null && world.getBlockType(getCurrentBlock()) == 0) ;
|
2011-01-19 09:12:05 +00:00
|
|
|
return getCurrentBlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the block at the sight. Returns null if out of range or if no
|
|
|
|
* viable target was found
|
|
|
|
*
|
|
|
|
* @return Block
|
|
|
|
*/
|
|
|
|
public BlockWorldVector getSolidTargetBlock() {
|
2013-06-23 19:04:23 +00:00
|
|
|
while (getNextBlock() != null && BlockType.canPassThrough(world.getBlock(getCurrentBlock()))) ;
|
2011-01-19 09:12:05 +00:00
|
|
|
return getCurrentBlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get next block
|
|
|
|
*
|
|
|
|
* @return next block position
|
|
|
|
*/
|
|
|
|
public BlockWorldVector getNextBlock() {
|
|
|
|
prevPos = targetPos;
|
|
|
|
do {
|
|
|
|
curDistance += checkDistance;
|
2011-11-23 01:29:48 +00:00
|
|
|
|
2011-01-19 09:12:05 +00:00
|
|
|
targetPosDouble = offset.add(targetPosDouble.getX(),
|
|
|
|
targetPosDouble.getY(),
|
|
|
|
targetPosDouble.getZ());
|
|
|
|
targetPos = targetPosDouble.toBlockPoint();
|
|
|
|
} while (curDistance <= maxDistance
|
|
|
|
&& targetPos.getBlockX() == prevPos.getBlockX()
|
|
|
|
&& targetPos.getBlockY() == prevPos.getBlockY()
|
|
|
|
&& targetPos.getBlockZ() == prevPos.getBlockZ());
|
2011-11-23 01:29:48 +00:00
|
|
|
|
2011-01-19 09:12:05 +00:00
|
|
|
if (curDistance > maxDistance) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new BlockWorldVector(world, targetPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current block along the line of vision
|
|
|
|
*
|
|
|
|
* @return block position
|
|
|
|
*/
|
|
|
|
public BlockWorldVector getCurrentBlock() {
|
|
|
|
if (curDistance > maxDistance) {
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
return new BlockWorldVector(world, targetPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the previous block in the aimed path
|
|
|
|
*
|
|
|
|
* @return block position
|
|
|
|
*/
|
|
|
|
public BlockWorldVector getPreviousBlock() {
|
|
|
|
return new BlockWorldVector(world, prevPos);
|
|
|
|
}
|
2011-09-19 01:49:45 +00:00
|
|
|
|
|
|
|
public WorldVectorFace getAnyTargetBlockFace() {
|
|
|
|
getAnyTargetBlock();
|
|
|
|
return WorldVectorFace.getWorldVectorFace(world, getCurrentBlock(), getPreviousBlock());
|
|
|
|
}
|
|
|
|
|
|
|
|
public WorldVectorFace getTargetBlockFace() {
|
|
|
|
getAnyTargetBlock();
|
|
|
|
return WorldVectorFace.getWorldVectorFace(world, getCurrentBlock(), getPreviousBlock());
|
|
|
|
}
|
2011-11-23 01:29:48 +00:00
|
|
|
}
|