下面列出了org.bukkit.Location#distance ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private boolean hasCleanShot(Location shootHere, Location targetHere) {
double x = shootHere.getX();
double y = shootHere.getY();
double z = shootHere.getZ();
double x1 = targetHere.getX();
double y1 = targetHere.getY();
double z1 = targetHere.getZ();
Vector start = new Vector(x, y, z);
Vector end = new Vector (x1, y1, z1);
BlockIterator bi = new BlockIterator(shootHere.getWorld(), start, end, 0, (int) shootHere.distance(targetHere));
while (bi.hasNext()) {
Block block = bi.next();
// System.out.println(Civs.getPrefix() + ((int) block.getLocation().getX()) +
// ":" + ((int) block.getLocation().getY()) + ":" +
// ((int) block.getLocation().getZ()) + " " + !Util.isSolidBlock(block.getType()));
if (!Util.isSolidBlock(block.getType())) {
return false;
}
}
return true;
}
private void checkForStuck() {
if (this.targetName != null && this.lastLocation != null) {
Location loc = getLocation(entity);
if (loc.distance(this.lastLocation) < 0.5) {
Player player;
try {
player = CivGlobal.getPlayer(this.targetName);
entity.getBukkitEntity().teleport(player.getLocation());
} catch (CivException e) {
/* This player is no longer online. Lose target. */
this.targetName = null;
this.lastLocation = null;
}
}
this.lastLocation = loc;
}
}
private Location getNearestTurret(Location playerLoc) {
double distance = Double.MAX_VALUE;
BlockCoord nearest = null;
for (BlockCoord turretCoord : turrets) {
Location turretLoc = turretCoord.getLocation();
if (playerLoc.getWorld() != turretLoc.getWorld()) {
return null;
}
double tmp = turretLoc.distance(playerLoc);
if (tmp < distance) {
distance = tmp;
nearest = turretCoord;
}
}
if (nearest == null) {
return null;
}
return nearest.getLocation();
}
/**
* Prevent the Nether spawn from being blown up
*
* @param e - event
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onExplosion(final EntityExplodeEvent e) {
if (Settings.newNether) {
// Not used in the new nether
return;
}
// Find out what is exploding
Entity expl = e.getEntity();
if (expl == null) {
return;
}
// Check world
if (!e.getEntity().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_nether")
|| e.getEntity().getWorld().getName().equalsIgnoreCase(Settings.worldName + "_the_end")) {
return;
}
Location spawn = e.getLocation().getWorld().getSpawnLocation();
Location loc = e.getLocation();
if (spawn.distance(loc) < Settings.netherSpawnRadius) {
e.blockList().clear();
}
}
public static void validateDistanceFromSpawn(Location loc) throws CivException {
/* Check distance from spawn. */
double requiredDistance;
try {
requiredDistance = CivSettings.getDouble(CivSettings.civConfig, "global.distance_from_spawn");
} catch (InvalidConfiguration e) {
e.printStackTrace();
return;
}
for (Civilization civ : CivGlobal.getAdminCivs()) {
Location townHallLoc = civ.getCapitolTownHallLocation();
if (townHallLoc == null) {
continue;
}
double distance = townHallLoc.distance(loc);
if (distance < requiredDistance) {
throw new CivException("You must build at least "+requiredDistance+" blocks away from spawn.");
}
}
}
public static double distanceFromRanged(RangedInfo rangedInfo, @Nullable Location deathLocation) {
if (rangedInfo.getOrigin() == null || deathLocation == null) return Double.NaN;
// When players fall in the void, use y=0 as their death location
if (deathLocation.getY() < 0) {
deathLocation = deathLocation.clone();
deathLocation.setY(0);
}
return deathLocation.distance(rangedInfo.getOrigin());
}
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;
}
}
}
default double distanceFrom(@Nullable Location deathLocation) {
if(getOrigin() == null || deathLocation == null) return Double.NaN;
// When players fall in the void, use y=0 as their death location
if(deathLocation.getY() < 0) {
deathLocation = deathLocation.clone();
deathLocation.setY(0);
}
return deathLocation.distance(getOrigin());
}
private void doBack(Player p, User iu, Location curLoc, Location lastLoc) {
if (iu.getWorld() != lastLoc.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !iu.isAuthorized("essentials.worlds." + lastLoc.getWorld().getName())) {
msg(p, "internal.error.no_required_permission", "essentials.worlds." + lastLoc.getWorld().getName());
return;
}
double fee = plugin.cfg.backBase;
if (curLoc.getWorld() != lastLoc.getWorld()) {
fee += plugin.cfg.backWorld;
fee += lastLoc.distance(PlayerSpawn(p, lastLoc.getWorld())) * (double) plugin.cfg.backIncrement / plugin.cfg.backDistance;
} else {
fee += lastLoc.distance(curLoc) * (double) plugin.cfg.backIncrement / plugin.cfg.backDistance;
}
if (fee > plugin.cfg.backMax) fee = plugin.cfg.backMax;
fee = new BigDecimal(fee).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
if (!VaultUtils.withdraw(p, fee)) {
msg(p, "user.teleport.money_insufficient", fee);
return;
}
try {
iu.getTeleport().back(new Trade(0, ess));
msg(p, "user.teleport.ok", fee, I18n.format("user.teleport.back"));
if (plugin.systemBalance != null) {
plugin.systemBalance.deposit(fee, plugin);
}
} catch (Exception e) {
VaultUtils.deposit(p, fee);
p.sendMessage(e.getMessage());
}
}
private void doHome(Player p, User iu, Location homeLoc, Location curLoc) {
if (iu.getWorld() != homeLoc.getWorld() && ess.getSettings().isWorldHomePermissions() && !iu.isAuthorized("essentials.worlds." + homeLoc.getWorld().getName())) {
msg(p, "internal.error.no_required_permission", "essentials.worlds." + homeLoc.getWorld().getName());
return;
}
double fee = plugin.cfg.homeBase;
if (homeLoc.getWorld() != curLoc.getWorld()) {
fee += plugin.cfg.homeWorld;
fee += homeLoc.distance(PlayerSpawn(p, homeLoc.getWorld())) * (double) plugin.cfg.homeIncrement / plugin.cfg.homeDistance;
} else {
fee += homeLoc.distance(curLoc) * (double) plugin.cfg.homeIncrement / plugin.cfg.homeDistance;
}
if (fee > plugin.cfg.homeMax) fee = plugin.cfg.homeMax;
fee = new BigDecimal(fee).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
if (!VaultUtils.withdraw(p, fee)) {
msg(p, "user.teleport.money_insufficient", fee);
return;
}
try {
iu.getTeleport().teleport(homeLoc, new Trade(0, ess), PlayerTeleportEvent.TeleportCause.PLUGIN);
msg(p, "user.teleport.ok", fee, I18n.format("user.teleport.home"));
if (plugin.systemBalance != null) {
plugin.systemBalance.deposit(fee, plugin);
}
} catch (Exception e) {
VaultUtils.deposit(p, fee);
p.sendMessage(e.getMessage());
}
}
@EventHandler
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) {
Block block = event.getBlockClicked().getRelative(event.getBlockFace());
Player player = event.getPlayer();
NovaPlayer nPlayer = PlayerManager.getPlayer(player);
if(nPlayer.getPreferences().getBypass()) {
return;
}
//Fluid protection
NovaRegion fluidProtectRegion = null;
for(NovaRegion region : plugin.getRegionManager().getRegions()) {
if(!region.getWorld().equals(block.getWorld())) {
continue;
}
Location centerLocation = region.getCenter().clone();
Location blockLocation = block.getLocation().clone();
centerLocation.setY(0);
blockLocation.setY(0);
if(blockLocation.distance(centerLocation) <= region.getDiagonal() / 2 + Config.REGION_FLUIDPROTECT.getInt()) {
fluidProtectRegion = region;
break;
}
}
if((fluidProtectRegion != null
&& (!nPlayer.hasGuild()
|| (!fluidProtectRegion.getGuild().isMember(nPlayer)
&& !fluidProtectRegion.getGuild().isAlly(nPlayer.getGuild()))))
|| (RegionManager.get(block) != null
&& (!plugin.getRegionManager().canInteract(player, block)
|| !nPlayer.hasPermission(GuildPermission.BLOCK_PLACE)))) {
event.setCancelled(true);
Message.CHAT_REGION_DENY_INTERACT.send(player);
}
}
/**
* 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;
}
}
private void processDirection(InteractEntityEvent e, float yaw, float pitch) {
Entity entity = e.getEntity();
if (!(entity instanceof Player) && !CHECK_OTHER_ENTITIES)
return;
Player attacker = e.getPlayer();
int ping = ServerUtils.getPing(attacker);
if (ping > PING_LIMIT && PING_LIMIT != -1)
return;
HawkPlayer att = e.getHawkPlayer();
Location attackerEyeLocation = att.getPosition().clone().add(new Vector(0, 1.62, 0)).toLocation(att.getWorld());
Vector attackerDirection = MathPlus.getDirection(yaw, pitch);
double maxReach = MAX_REACH;
if (attacker.getGameMode() == GameMode.CREATIVE)
maxReach += 1.9;
Vector victimLocation;
if (LAG_COMPENSATION)
//No need to add 50ms; the move and attack are already chronologically so close together
victimLocation = hawk.getLagCompensator().getHistoryLocation(ping, e.getEntity()).toVector();
else
victimLocation = e.getEntity().getLocation().toVector();
Vector eyePos = new Vector(attackerEyeLocation.getX(), attacker.isSneaking() ? attackerEyeLocation.getY() - 0.08 : attackerEyeLocation.getY(), attackerEyeLocation.getZ());
Vector direction = new Vector(attackerDirection.getX(), attackerDirection.getY(), attackerDirection.getZ());
Ray attackerRay = new Ray(eyePos, direction);
AABB victimAABB;
victimAABB = WrappedEntity.getWrappedEntity(entity).getHitbox(victimLocation);
victimAABB.expand(BOX_EPSILON, BOX_EPSILON, BOX_EPSILON);
Vector intersectVec3d = victimAABB.intersectsRay(attackerRay, 0, Float.MAX_VALUE);
if (DEBUG_HITBOX) {
victimAABB.highlight(hawk, attacker.getWorld(), 0.29);
}
if (DEBUG_RAY) {
attackerRay.highlight(hawk, attacker.getWorld(), maxReach, 0.1);
}
if (intersectVec3d != null) {
Location intersect = new Location(attacker.getWorld(), intersectVec3d.getX(), intersectVec3d.getY(), intersectVec3d.getZ());
double interDistance = intersect.distance(attackerEyeLocation);
if (interDistance > maxReach) {
punish(att, 1, true, e, new Placeholder("type", "Reach: " + MathPlus.round(interDistance, 2) + "m"));
return;
}
if (CHECK_OCCLUSION && interDistance > 1D) {
BlockIterator iter = new BlockIterator(attacker.getWorld(), eyePos, attackerDirection, 0, (int) interDistance + 1);
while (iter.hasNext()) {
Block bukkitBlock = iter.next();
if (bukkitBlock.getType() == Material.AIR || bukkitBlock.isLiquid())
continue;
WrappedBlock b = WrappedBlock.getWrappedBlock(bukkitBlock, att.getClientVersion());
Vector intersection = b.getHitBox().intersectsRay(new Ray(attackerEyeLocation.toVector(), attackerDirection), 0, Float.MAX_VALUE);
if (intersection != null) {
if (intersection.distance(eyePos) < interDistance) {
punish(att, 1, true, e, new Placeholder("type", "Interacted through " + b.getBukkitBlock().getType()));
return;
}
}
}
}
} else if (CHECK_BOX_INTERSECTION) {
punish(att, 1, true, e, new Placeholder("type", "Did not hit hitbox."));
return;
}
reward(att); //reward player
}
private void swingProcessor(ArmSwingEvent e) {
UUID uuid = e.getPlayer().getUniqueId();
if (!lastAttacked.containsKey(uuid))
return;
HawkPlayer att = e.getHawkPlayer();
HawkPlayer victim = lastAttacked.get(uuid);
if (victim == null)
return;
long lastSwingTick = swingTick.getOrDefault(uuid, 0L);
//proceed if victim's invulnerability is gone
//diff between current client tick and last swing tick should never be negative
//a bypass for this IS possible, but you'd get caught by TickRate if you try to change your tickrate
if (att.getCurrentTick() - lastSwingTick >= victim.getPlayer().getMaximumNoDamageTicks() / 2) {
Map<UUID, FightData> accuracyToVictim = accuracy.getOrDefault(uuid, new HashMap<>());
FightData fightData = accuracyToVictim.getOrDefault(victim.getUuid(), new FightData());
fightData.swings++;
accuracyToVictim.put(victim.getUuid(), fightData);
accuracy.put(uuid, accuracyToVictim);
swingTick.put(uuid, att.getCurrentTick());
}
Location attackerLoc = new Location(att.getWorld(), att.getPosition().getX(), att.getPosition().getY(), att.getPosition().getZ(), att.getYaw(), att.getPitch());
Location victimLoc = new Location(victim.getWorld(), victim.getPosition().getX(), victim.getPosition().getY(), victim.getPosition().getZ(), victim.getYaw(), victim.getPitch());
//determine how far the opponent has moved horizontally on local coordinates and compute required mouse precision
if(!attackerLoc.getWorld().equals(victimLoc.getWorld()))
return;
Vector victimVelocity = victim.getVelocity().clone().setY(0);
Vector attackerDirection = att.getPlayer().getLocation().getDirection().clone().setY(0);
double localMovement = MathPlus.sin((float)MathPlus.angle(victimVelocity, attackerDirection)) * victimVelocity.length();
if(Double.isNaN(localMovement))
localMovement = 0D;
double requiredPrecision = localMovement * attackerLoc.distance(victimLoc);
double effort = this.effort.getOrDefault(uuid, 0D);
if(DEBUG) {
if(requiredPrecision >= MIN_PRECISION_THRESHOLD && effort < EFFORT_THRESHOLD && effort + 0.02 >= EFFORT_THRESHOLD) {
att.getPlayer().sendMessage(ChatColor.GREEN + "You are now eligible to be checked by fightaccuracy because your opponent is moving significantly.");
}
else if(requiredPrecision < MIN_PRECISION_THRESHOLD && effort >= EFFORT_THRESHOLD && effort - 0.01 < EFFORT_THRESHOLD) {
att.getPlayer().sendMessage(ChatColor.RED + "You are no longer eligible to be checked by fightaccuracy because your opponent is not moving enough.");
}
}
if (requiredPrecision >= MIN_PRECISION_THRESHOLD) {
//increase effort
this.effort.put(uuid, Math.min(effort + 0.02, 1));
} else {
//decrease effort
this.effort.put(uuid, Math.max(effort - 0.01, 0));
}
}
public static List<Location> getTargetsPathBlocked(Location tLoc, Location dLoc, boolean useOnlyMaterialListing, boolean ignoreFirstZone) {
final ArrayList<Location> targetsInPath = new ArrayList<Location>();
// check world
if (!dLoc.getWorld().getName().equalsIgnoreCase(tLoc.getWorld().getName())) {
return targetsInPath;
}
// if the distance is too close... the path is not blocked ;)
if (dLoc.distance(tLoc) <= 0.9) {
return targetsInPath;
}
// try to iterate through blocks between dLoc and tLoc
try {
// Create a vector block trace from the detonator location to damaged block's location
final Location tarLoc = tLoc.clone().add(0, 0.25, 0);
final BlockIterator blocksInPath = new BlockIterator(tarLoc.getWorld(), dLoc.toVector(), tarLoc.toVector().subtract(dLoc.toVector()).normalize(), 0.5, (int) dLoc.distance(tarLoc));
// iterate through the blocks in the path
int i = ConfigManager.getInstance().getRadius() + 1;
int over = 0; // prevents rare case of infinite loop and server crash
while (blocksInPath.hasNext() && over < 128) {
if (i > 0) {
i--;
} else {
break;
}
over++;
// the next block
final Block block = blocksInPath.next();
if (block == null) {
continue;
}
// check if next block is the target block
if (tarLoc.getWorld().getName().equals(block.getWorld().getName()) &&
tarLoc.getBlockX() == block.getX() &&
tarLoc.getBlockY() == block.getY() &&
tarLoc.getBlockZ() == block.getZ()) {
// ignore target block
continue;
}
// Ignore first blocks next to explosion
if (ignoreFirstZone && ((i >= ConfigManager.getInstance().getRadius() - 1) || (dLoc.distance(tarLoc) <= 1.5))) {
if (i >= ConfigManager.getInstance().getRadius() - 1 && MaterialManager.getInstance().contains(block.getType().name(), block.getData())) {
targetsInPath.add(block.getLocation());
}
continue;
}
// check if the block material is being handled
if (useOnlyMaterialListing) {
// only handle for certain case as to not interfere with all explosions
if (MaterialManager.getInstance().contains(block.getType().name(), block.getData())) {
targetsInPath.add(block.getLocation());
continue;
} else {
continue;
}
}
// check if the block material is a solid
if (!isNonSolid(block.getType())) {
targetsInPath.add(block.getLocation());
if (targetsInPath.size() > 3) {
break;
}
}
}
} catch (Exception e) {
// ignore the error and return no targets in path
}
return targetsInPath;
}
public static boolean isTargetsPathBlocked(Location tLoc, Location dLoc, boolean useOnlyMaterialListing) {
// check world
if (!dLoc.getWorld().getName().equalsIgnoreCase(tLoc.getWorld().getName())) {
return false;
}
// if the distance is too close... the path is not blocked ;)
if (dLoc.distance(tLoc) <= 0.9) {
return false;
}
// try to iterate through blocks between dLoc and tLoc
try {
// Create a vector block trace from the detonator location to damaged block's location
final BlockIterator blocksInPath = new BlockIterator(tLoc.getWorld(), dLoc.toVector(), tLoc.toVector().subtract(dLoc.toVector()).normalize(), 0.5, (int) dLoc.distance(tLoc));
// iterate through the blocks in the path
int over = 0; // prevents rare case of infinite loop and server crash
while (blocksInPath.hasNext() && over < 128) {
over++;
// the next block
final Block block = blocksInPath.next();
if (block == null) {
continue;
}
// check if next block is the target block
if (tLoc.getWorld().getName().equals(block.getWorld().getName()) &&
tLoc.getBlockX() == block.getX() &&
tLoc.getBlockY() == block.getY() &&
tLoc.getBlockZ() == block.getZ()) {
// ignore target block
continue;
}
// check if the block material is being handled
if (useOnlyMaterialListing) {
// only handle for certain case as to not interfere with all explosions
if (MaterialManager.getInstance().contains(block.getType().name(), block.getData())) {
return true;
} else {
continue;
}
}
// check if the block material is a solid
if (!isNonSolid(block.getType())) {
return true;
}
}
} catch (Exception e) {
// ignore the error and return no targets in path
}
return false;
}
public void process(HashSet<String> alreadyAnnounced) {
count++;
if (count < reportSeconds) {
return;
}
count = 0;
boolean empty = true;
for (PlayerLocationCache pc : proximityComponent.tryGetNearbyPlayers(true)) {
empty = false;
scoutDebug("Inspecting player:"+pc.getName());
Player player;
try {
player = CivGlobal.getPlayer(pc.getName());
} catch (CivException e) {
scoutDebug("not online?");
return;
}
if (player.isOp()) {
scoutDebug("player is op");
continue;
}
Location center = this.getCenterLocation().getLocation();
/* Do not re-announce players announced by other scout towers */
if (alreadyAnnounced.contains(this.getCiv().getName()+":"+player.getName())) {
scoutDebug("already announced:"+pc.getName());
continue;
}
/* Always announce outlaws, so skip down to bottom. */
String relationName = "";
String relationColor = "";
if (!this.getTown().isOutlaw(player.getName())) {
/* do not announce residents in this civ */
Resident resident = CivGlobal.getResident(player);
if (resident != null && resident.hasTown() && resident.getCiv() == this.getCiv()) {
scoutDebug("same civ");
continue;
}
/* Only announce hostile, war, and neutral players */
Relation.Status relation = this.getCiv().getDiplomacyManager().getRelationStatus(player);
switch (relation) {
case PEACE:
case ALLY:
// case VASSAL:
// case MASTER:
scoutDebug("ally or peace");
continue;
default:
break;
}
relationName = relation.name();
relationColor = Relation.getRelationColor(relation);
} else {
relationName = "OUTLAW";
relationColor = CivColor.Yellow;
}
if (center.getWorld() != this.getCorner().getLocation().getWorld()) {
scoutDebug("wrong world");
continue;
}
if (center.distance(player.getLocation()) < range) {
/* Notify the town or civ. */
CivMessage.sendScout(this.getCiv(), "Scout tower detected "+relationColor+
player.getName()+"("+relationName+")"+CivColor.White+
" at ("+player.getLocation().getBlockX()+","+player.getLocation().getBlockY()+","+player.getLocation().getBlockZ()+") in "+
this.getTown().getName());
alreadyAnnounced.add(this.getCiv().getName()+":"+player.getName());
}
}
if (empty) {
scoutDebug("Proximity cache was empty");
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onEntityExplode(EntityExplodeEvent event) {
if (event.isCancelled()) {
return;
}
if (!War.isWarTime()) {
return;
}
if (event.getEntity() == null) {
return;
}
if (event.getEntityType().equals(EntityType.UNKNOWN)) {
return;
}
if (event.getEntityType().equals(EntityType.PRIMED_TNT) ||
event.getEntityType().equals(EntityType.MINECART_TNT)) {
int yield;
try {
yield = CivSettings.getInteger(CivSettings.warConfig, "cannon.yield");
} catch (InvalidConfiguration e) {
e.printStackTrace();
return;
}
yield = yield / 2;
for (int y = -yield; y <= yield; y++) {
for (int x = -yield; x <= yield; x++) {
for (int z = -yield; z <= yield; z++) {
Location loc = event.getLocation().clone().add(new Vector(x,y,z));
if (loc.distance(event.getLocation()) < yield) {
WarRegen.saveBlock(loc.getBlock(), Cannon.RESTORE_NAME, false);
ItemManager.setTypeIdAndData(loc.getBlock(), CivData.AIR, 0, false);
}
}
}
}
event.setCancelled(true);
}
}
private void handleGrapplingHook(Arrow arrow) {
if (arrow != null && arrow.isValid() && arrow.getShooter() instanceof Player) {
Player p = (Player) arrow.getShooter();
GrapplingHookEntity hook = activeHooks.get(p.getUniqueId());
if (hook != null) {
Location target = arrow.getLocation();
hook.drop(target);
Vector velocity = new Vector(0.0, 0.2, 0.0);
if (p.getLocation().distance(target) < 3.0) {
if (target.getY() <= p.getLocation().getY()) {
velocity = target.toVector().subtract(p.getLocation().toVector());
}
}
else {
Location l = p.getLocation();
l.setY(l.getY() + 0.5);
p.teleport(l);
double g = -0.08;
double d = target.distance(l);
double t = d;
double vX = (1.0 + 0.08 * t) * (target.getX() - l.getX()) / t;
double vY = (1.0 + 0.04 * t) * (target.getY() - l.getY()) / t - 0.5D * g * t;
double vZ = (1.0 + 0.08 * t) * (target.getZ() - l.getZ()) / t;
velocity = p.getVelocity();
velocity.setX(vX);
velocity.setY(vY);
velocity.setZ(vZ);
}
p.setVelocity(velocity);
hook.remove();
Slimefun.runSync(() -> activeHooks.remove(p.getUniqueId()), 20L);
}
}
}
public static int distanceFromSpawnLevelIncrease(Location location) {
double distanceUnit = ConfigValues.mobCombatSettingsConfig.getDouble(MobCombatSettingsConfig.DISTANCE_TO_INCREMENT);
double levelToIncrement = ConfigValues.mobCombatSettingsConfig.getDouble(MobCombatSettingsConfig.LEVEL_TO_INCREMENT);
Location spawnLocation = location.getWorld().getSpawnLocation();
Location entityLocation = location;
double distanceFromSpawn = spawnLocation.distance(entityLocation);
int levelIncrease = (int) (distanceFromSpawn / distanceUnit * levelToIncrement);
return levelIncrease;
}