下面列出了org.bukkit.util.Vector#toLocation ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static void buildLightning(Location start, Vector direction, int entries, int branches, double radius, double offset, double offsetRate, double length, double lengthRate, double branch, double branchRate, Consumer<Location> action) {
ThreadLocalRandom random = ThreadLocalRandom.current();
if (entries <= 0) {
return;
}
boolean inRange = true;
while (random.nextDouble() < branch || inRange) {
Vector randomizer = new Vector(random.nextDouble(-radius, radius), random.nextDouble(-radius, radius), random.nextDouble(-radius, radius)).normalize().multiply((random.nextDouble(-radius, radius)) * offset);
Vector endVector = start.clone().toVector().add(direction.clone().multiply(length)).add(randomizer);
Location end = endVector.toLocation(start.getWorld());
if (end.distance(start) <= length) {
inRange = true;
continue;
} else {
inRange = false;
}
int rate = (int) (start.distance(end) / 0.1); // distance * (distance / 10)
Vector rateDir = endVector.clone().subtract(start.toVector()).normalize().multiply(0.1);
for (int i = 0; i < rate; i++) {
Location loc = start.clone().add(rateDir.clone().multiply(i));
action.accept(loc);
}
buildLightning(end.clone(), direction, entries - 1, branches - 1, radius, offset * offsetRate, offsetRate, length * lengthRate, lengthRate, branch * branchRate, branchRate, action);
if (branches <= 0) {
break;
}
}
}
/**
* Returns a spot to run to if running in a certain direction.
* Returns null if can't reasonable run that direction.
*/
public static Location findSpotForRunDirection(Location start, double distance, Vector direction) {
VectorGoal goal = new VectorGoal(start.clone().add(direction.clone().multiply(distance)), 4);
VectorNode startNode = new VectorNode(goal, start, new ChunkBlockSource(start, (float)distance + 10), examiner);
Path resultPath = (Path) ASTAR.runFully(goal, startNode, (int)(distance * 50));
if (resultPath == null || resultPath.isComplete()) {
return null;
}
Vector current = resultPath.getCurrentVector();
while (!resultPath.isComplete()) {
current = resultPath.getCurrentVector();
resultPath.update(null);
}
return current.toLocation(start.getWorld());
}
private boolean safe(ChunkSnapshot chunk, int x, int y, int z, World world) {
Vector newSpot = new Vector(chunk.getX() * 16 + x + 0.5D, y + 1, chunk.getZ() * 16 + z + 0.5D);
if (portal) {
if (bestSpot == null) {
// Stash the best spot
bestSpot = newSpot.toLocation(world);
}
return false;
} else {
teleportEntity(newSpot.toLocation(world));
return true;
}
}
public synchronized void update() {
super.markChanged();
if (this.center == null) {
return;
}
if (this.size < 1) {
return;
}
if (this.world == null) {
this.world = Bukkit.getWorlds().get(0);
}
if (this.world != null) {
int lx = this.center.getBlockX() + this.size;
int lz = this.center.getBlockZ() + this.size;
int px = this.center.getBlockX() - this.size;
int pz = this.center.getBlockZ() - this.size;
Vector l = new Vector(lx, 0, lz);
Vector p = new Vector(px, this.world.getMaxHeight(), pz);
this.firstCorner = l.toLocation(this.world);
this.secondCorner = p.toLocation(this.world);
}
}
public static void spawnFireworks(Vector vec, double radius, int count, Color color, int power) {
Location loc = vec.toLocation(GameHandler.getGameHandler().getMatchWorld());
FireworkEffect effect = getFireworkEffect(color);
for(int i = 0; i < count; i++) {
double angle = (2 * Math.PI / count) * i;
double x = radius * Math.cos(angle);
double z = radius * Math.sin(angle);
spawnFirework(firstEmptyBlock(loc.clone().add(x, 0, z)), effect, power);
}
}
/**
* Spawns a broken line that creates more and extended branches
* as it gets closer to the end length.
* This method doesn't support rotations. Use the direction instead.
*
* @param start the starting point of the new branch. For the first call it's the same location as the displays location.
* @param direction the direction of the lightning. A simple direction would be {@code entity.getLocation().getDirection().normalize()}
* For a simple end point direction would be {@code endLocation.toVector().subtract(start.toVector()).normalize()}
* @param entries the number of entries for the main lightning branch. Recommended is 20
* @param branches the maximum number of branches each entry can have. Recommended is 200
* @param radius the radius of the lightning branches. Recommended is 0.5
* @param offset the offset of the lightning branches. Recommended is 2
* @param offsetRate the offset change rate of the lightning branches. Recommended is 1
* @param length the length of the lightning branch. Recommended is 1.5
* @param lengthRate the length change rate of the lightning branch. Recommended is 1
* @param branch the chance of creating a new branch. Recommended is 0.1
* @param branchRate the chance change of creating a new branch. Recommended is 1
* @since 3.0.0
*/
public static void lightning(Location start, Vector direction, int entries, int branches, double radius,
double offset, double offsetRate,
double length, double lengthRate,
double branch, double branchRate, ParticleDisplay display) {
ThreadLocalRandom random = ThreadLocalRandom.current();
if (entries <= 0) return;
boolean inRange = true;
// Check if we can create new branches or the current branch
// length is already in range.
while (random.nextDouble() < branch || inRange) {
// Break our straight line randomly.
Vector randomizer = new Vector(
random.nextDouble(-radius, radius), random.nextDouble(-radius, radius), random.nextDouble(-radius, radius))
.normalize().multiply((random.nextDouble(-radius, radius)) * offset);
Vector endVector = start.clone().toVector().add(direction.clone().multiply(length)).add(randomizer);
Location end = endVector.toLocation(start.getWorld());
// Check if the broken line length is in our max length range.
if (end.distance(start) <= length) {
inRange = true;
continue;
} else inRange = false;
// Create particle points in our broken straight line.
int rate = (int) (start.distance(end) / 0.1); // distance * (distance / 10)
Vector rateDir = endVector.clone().subtract(start.toVector()).normalize().multiply(0.1);
for (int i = 0; i < rate; i++) {
Location loc = start.clone().add(rateDir.clone().multiply(i));
display.spawn(loc);
}
// Create new entries if possible.
lightning(end.clone(), direction, entries - 1, branches - 1, radius, offset * offsetRate, offsetRate,
length * lengthRate, lengthRate,
branch * branchRate, branchRate, display);
// Check if the maximum number of branches has already been used for this entry.
if (branches <= 0) break;
}
}
public Location getSpawnLocation(World world) {
Vector pos = getVector(world, "spawn.pos", world.getSpawnLocation().toVector());
float yaw = (float) getDouble(world, "spawn.yaw", 0);
float pitch = (float) getDouble(world, "spawn.pitch", 0);
return pos.toLocation(world, yaw, pitch);
}
/**
* Determines if two {@link User}s can see each other.
*/
private boolean canSee(final User observerUser, final User watchedUser)
{
final Player observer = observerUser.getPlayer();
final Player watched = watchedUser.getPlayer();
// Not bypassed
if (observerUser.isBypassed(this.getModuleType()) ||
// Has not logged in recently to prevent bugs
observerUser.hasLoggedInRecently(3000) ||
// Glowing handling
// Glowing does not exist in 1.8.8
(ServerVersion.getActiveServerVersion() != ServerVersion.MC188 &&
// If an entity is glowing it can always be seen.
watched.hasPotionEffect(PotionEffectType.GLOWING)))
{
return true;
}
// ----------------------------------- Calculation ---------------------------------- //
final Vector[] cameraVectors = VectorUtils.getCameraVectors(observer);
// Get the Vectors of the hitbox to check.
final Vector[] watchedHitboxVectors = (watched.isSneaking() ?
Hitbox.ESP_SNEAKING_PLAYER :
Hitbox.ESP_PLAYER).getCalculationVectors(watched.getLocation(), true);
// The distance of the intersections in the same block is equal as of the
// BlockIterator mechanics.
final Set<Double> lastIntersectionsCache = new HashSet<>();
for (Vector cameraVector : cameraVectors) {
for (final Vector destinationVector : watchedHitboxVectors) {
final Location start = cameraVector.toLocation(observer.getWorld());
// The resulting Vector
// The camera is not blocked by non-solid blocks
// Vector is intersecting with some blocks
//
// Cloning IS needed as we are in a second loop.
final Vector between = destinationVector.clone().subtract(cameraVector);
// ---------------------------------------------- FOV ----------------------------------------------- //
final Vector cameraRotation = cameraVector.clone().subtract(observer.getLocation().toVector());
if (cameraRotation.angle(between) > MAX_FOV) {
continue;
}
// ---------------------------------------- Cache Calculation --------------------------------------- //
// Make sure the chunks are loaded.
if (!ChunkUtils.areChunksLoadedBetweenLocations(start, start.clone().add(between))) {
// If the chunks are not loaded assume the players can see each other.
return true;
}
boolean cacheHit = false;
Location cacheLocation;
for (Double length : lastIntersectionsCache) {
cacheLocation = start.clone().add(between.clone().normalize().multiply(length));
// Not yet cached.
if (length == 0) {
continue;
}
final Material type = cacheLocation.getBlock().getType();
if (BlockUtils.isReallyOccluding(type) && type.isSolid()) {
cacheHit = true;
break;
}
}
if (cacheHit) {
continue;
}
// --------------------------------------- Normal Calculation --------------------------------------- //
final double intersect = VectorUtils.getDistanceToFirstIntersectionWithBlock(start, between);
// No intersection found
if (intersect == 0) {
return true;
}
lastIntersectionsCache.add(intersect);
}
}
// Low probability to help after the camera view was changed. -> clearing
lastIntersectionsCache.clear();
return false;
}