mirror of
https://github.com/zeshan321/ActionHealth.git
synced 2025-03-10 13:49:07 +01:00
New features and bug fixes
Bug fixes: - Showing health message when player hurts itself. New features: - Added an option to blacklist certain entities from being shown in the health action bar. - Added option to show the health action bar when looking at an entity. - Added the ability to customize the message when using /actionhealth toggle.
This commit is contained in:
parent
3b00198c03
commit
8f598ab6b8
12
config.yml
12
config.yml
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
Health Message: '&7&l{name}: {usestyle}'
|
Health Message: '&7&l{name}: {usestyle}'
|
||||||
|
|
||||||
|
# The message the player is sent to the player if they have actionhealth disabled.
|
||||||
|
# {name} shows the name of the player.
|
||||||
|
Toggle Message: ''
|
||||||
|
|
||||||
# Strip Name.
|
# Strip Name.
|
||||||
|
|
||||||
Strip Name: true
|
Strip Name: true
|
||||||
@ -52,3 +56,11 @@ Limit Health: true
|
|||||||
|
|
||||||
# Saves players /actionhealth toggle state.
|
# Saves players /actionhealth toggle state.
|
||||||
Remember Toggle: false
|
Remember Toggle: false
|
||||||
|
|
||||||
|
# Blacklist by entity name or entity display name.
|
||||||
|
Blacklist:
|
||||||
|
- 'CCPD Officer'
|
||||||
|
|
||||||
|
# Show the health of the entity that the player is looking at.
|
||||||
|
Show On Look: false
|
||||||
|
Look Distance: 10
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
name: ActionHealth
|
name: ActionHealth
|
||||||
main: com.zeshanaslam.actionhealth.Main
|
main: com.zeshanaslam.actionhealth.Main
|
||||||
version: 3.1.3
|
version: 3.1.4
|
||||||
commands:
|
commands:
|
||||||
Actionhealth:
|
Actionhealth:
|
||||||
description: Actionhealth main command.
|
description: Actionhealth main command.
|
@ -39,6 +39,9 @@ public class HealthListeners implements Listener {
|
|||||||
|
|
||||||
|
|
||||||
Entity damaged = event.getEntity();
|
Entity damaged = event.getEntity();
|
||||||
|
if (event.getDamager().getUniqueId() == damaged.getUniqueId()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (event.getDamager() instanceof Projectile) {
|
if (event.getDamager() instanceof Projectile) {
|
||||||
Projectile projectile = (Projectile) event.getDamager();
|
Projectile projectile = (Projectile) event.getDamager();
|
||||||
@ -58,13 +61,16 @@ public class HealthListeners implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (plugin.toggle.contains(player.getUniqueId())) {
|
if (plugin.toggle.contains(player.getUniqueId())) {
|
||||||
|
if (plugin.settingsManager.toggleMessage != null && !plugin.settingsManager.toggleMessage.equals("")) {
|
||||||
|
plugin.healthUtil.sendActionBar(player, plugin.settingsManager.toggleMessage.replace("{name}", player.getName()));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send health
|
// Send health
|
||||||
if (damaged instanceof LivingEntity) {
|
if (damaged instanceof LivingEntity) {
|
||||||
LivingEntity livingEntity = (LivingEntity) damaged;
|
LivingEntity livingEntity = (LivingEntity) damaged;
|
||||||
plugin.healthUtil.sendHealth(player, (LivingEntity) damaged, livingEntity.getHealth() - event.getFinalDamage());
|
plugin.healthUtil.sendHealth(player, livingEntity, livingEntity.getHealth() - event.getFinalDamage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,12 +100,12 @@ public class HealthListeners implements Listener {
|
|||||||
// Send health
|
// Send health
|
||||||
if (damaged instanceof LivingEntity) {
|
if (damaged instanceof LivingEntity) {
|
||||||
LivingEntity livingEntity = (LivingEntity) damaged;
|
LivingEntity livingEntity = (LivingEntity) damaged;
|
||||||
plugin.healthUtil.sendHealth(player, (LivingEntity) damaged, livingEntity.getHealth() - event.getFinalDamage());
|
plugin.healthUtil.sendHealth(player, livingEntity, livingEntity.getHealth() - event.getFinalDamage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void onJoin(PlayerJoinEvent event) {
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
@ -112,7 +118,7 @@ public class HealthListeners implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
public void onLeave(PlayerQuitEvent event) {
|
public void onLeave(PlayerQuitEvent event) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
|
@ -24,11 +24,17 @@ public class HealthUtil {
|
|||||||
|
|
||||||
new BukkitRunnable() {
|
new BukkitRunnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
sendActionBar(player, getOutput((int) entity.getHealth(), entity));
|
String output = getOutput(entity.getHealth(), entity);
|
||||||
|
|
||||||
|
if (output != null)
|
||||||
|
sendActionBar(player, output);
|
||||||
}
|
}
|
||||||
}.runTaskLater(plugin, 1L);
|
}.runTaskLater(plugin, 1L);
|
||||||
} else {
|
} else {
|
||||||
sendActionBar(player, getOutput(health, entity));
|
String output = getOutput(health, entity);
|
||||||
|
|
||||||
|
if (output != null)
|
||||||
|
sendActionBar(player, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +50,8 @@ public class HealthUtil {
|
|||||||
name = entity.getCustomName();
|
name = entity.getCustomName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (plugin.settingsManager.blacklist.contains(name)) return null;
|
||||||
|
|
||||||
if (plugin.settingsManager.stripName) name = ChatColor.stripColor(name);
|
if (plugin.settingsManager.stripName) name = ChatColor.stripColor(name);
|
||||||
if (plugin.settingsManager.translate.containsKey(entity.getName()))
|
if (plugin.settingsManager.translate.containsKey(entity.getName()))
|
||||||
name = plugin.settingsManager.translate.get(entity.getName());
|
name = plugin.settingsManager.translate.get(entity.getName());
|
||||||
@ -81,8 +89,14 @@ public class HealthUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < left; i++) {
|
if (maxHealth != health) {
|
||||||
style = style + plugin.settingsManager.emptyHeartIcon;
|
for (int i = 0; i < left; i++) {
|
||||||
|
style = style + plugin.settingsManager.emptyHeartIcon;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < left; i++) {
|
||||||
|
style = style + plugin.settingsManager.filledHeartIcon;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output = output.replace("{usestyle}", style);
|
output = output.replace("{usestyle}", style);
|
||||||
@ -91,7 +105,7 @@ public class HealthUtil {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendActionBar(Player player, String message) {
|
public void sendActionBar(Player player, String message) {
|
||||||
message = ChatColor.translateAlternateColorCodes('&', message);
|
message = ChatColor.translateAlternateColorCodes('&', message);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
46
src/com/zeshanaslam/actionhealth/LookThread.java
Normal file
46
src/com/zeshanaslam/actionhealth/LookThread.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package com.zeshanaslam.actionhealth;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class LookThread extends BukkitRunnable {
|
||||||
|
|
||||||
|
private Main plugin;
|
||||||
|
|
||||||
|
public LookThread(Main plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (plugin.toggle.contains(player.getUniqueId())) {
|
||||||
|
if (plugin.settingsManager.toggleMessage != null && !plugin.settingsManager.toggleMessage.equals("")) {
|
||||||
|
plugin.healthUtil.sendActionBar(player, plugin.settingsManager.toggleMessage.replace("{name}", player.getName()));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LivingEntity> entities = TargetHelper.getLivingTargets(player, plugin.settingsManager.lookDistance);
|
||||||
|
|
||||||
|
if (!entities.isEmpty()) {
|
||||||
|
LivingEntity livingEntity = entities.get(0);
|
||||||
|
String name;
|
||||||
|
|
||||||
|
if (livingEntity.getCustomName() == null) {
|
||||||
|
name = livingEntity.getName();
|
||||||
|
} else {
|
||||||
|
name = livingEntity.getCustomName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!plugin.settingsManager.blacklist.contains(name)) {
|
||||||
|
plugin.healthUtil.sendHealth(player, livingEntity, livingEntity.getHealth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ public class Main extends JavaPlugin {
|
|||||||
public SettingsManager settingsManager;
|
public SettingsManager settingsManager;
|
||||||
public WorldGuardPlugin worldGuardPlugin;
|
public WorldGuardPlugin worldGuardPlugin;
|
||||||
public HealthUtil healthUtil;
|
public HealthUtil healthUtil;
|
||||||
|
public int taskID = -1;
|
||||||
|
|
||||||
public List<UUID> toggle = new ArrayList<>();
|
public List<UUID> toggle = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package com.zeshanaslam.actionhealth;
|
package com.zeshanaslam.actionhealth;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SettingsManager {
|
public class SettingsManager {
|
||||||
|
|
||||||
@ -22,11 +25,22 @@ public class SettingsManager {
|
|||||||
public List<String> worlds = new ArrayList<>();
|
public List<String> worlds = new ArrayList<>();
|
||||||
public HashMap<String, String> translate = new HashMap<>();
|
public HashMap<String, String> translate = new HashMap<>();
|
||||||
public List<String> regions = new ArrayList<>();
|
public List<String> regions = new ArrayList<>();
|
||||||
|
|
||||||
public String mcVersion;
|
public String mcVersion;
|
||||||
public boolean useOldMethods;
|
public boolean useOldMethods;
|
||||||
|
public boolean showOnLook;
|
||||||
|
public double lookDistance;
|
||||||
|
public List<String> blacklist = new ArrayList<>();
|
||||||
|
public String toggleMessage;
|
||||||
|
|
||||||
public SettingsManager(Main plugin) {
|
public SettingsManager(Main plugin) {
|
||||||
|
// Clear settings for reloads
|
||||||
|
worlds.clear();
|
||||||
|
regions.clear();
|
||||||
|
blacklist.clear();
|
||||||
|
|
||||||
|
if (plugin.taskID != -1) Bukkit.getScheduler().cancelTask(plugin.taskID);
|
||||||
|
|
||||||
|
// Get settings from config
|
||||||
healthMessage = plugin.getConfig().getString("Health Message");
|
healthMessage = plugin.getConfig().getString("Health Message");
|
||||||
usePerms = plugin.getConfig().getBoolean("Use Permissions");
|
usePerms = plugin.getConfig().getBoolean("Use Permissions");
|
||||||
showMobs = plugin.getConfig().getBoolean("Show Mob");
|
showMobs = plugin.getConfig().getBoolean("Show Mob");
|
||||||
@ -60,5 +74,27 @@ public class SettingsManager {
|
|||||||
} else {
|
} else {
|
||||||
rememberToggle = false;
|
rememberToggle = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New options
|
||||||
|
if (plugin.getConfig().contains("Blacklist")) {
|
||||||
|
blacklist.addAll(plugin.getConfig().getStringList("Blacklist").stream().map(s -> ChatColor.translateAlternateColorCodes('&', s)).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugin.getConfig().contains("Show On Look")) {
|
||||||
|
showOnLook = plugin.getConfig().getBoolean("Show On Look");
|
||||||
|
lookDistance = plugin.getConfig().getDouble("Look Distance");
|
||||||
|
|
||||||
|
if (showOnLook) {
|
||||||
|
BukkitTask bukkitTask = new LookThread(plugin).runTaskTimerAsynchronously(plugin, 0, 20);
|
||||||
|
plugin.taskID = bukkitTask.getTaskId();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
plugin.taskID = -1;
|
||||||
|
showOnLook = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugin.getConfig().contains("Toggle Message")) {
|
||||||
|
toggleMessage = plugin.getConfig().getString("Toggle Message");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
288
src/com/zeshanaslam/actionhealth/TargetHelper.java
Normal file
288
src/com/zeshanaslam/actionhealth/TargetHelper.java
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
package com.zeshanaslam.actionhealth;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Helper class for getting targets using various methods</p>
|
||||||
|
*/
|
||||||
|
public class TargetHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Number of pixels that end up displaying about 1 degree of vision in the client window</p>
|
||||||
|
* <p>Not really useful since you can't get the client's window size, but I added it in case
|
||||||
|
* it becomes useful sometime</p>
|
||||||
|
*/
|
||||||
|
private static final int PIXELS_PER_DEGREE = 35;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Gets all entities the player is looking at within the range</p>
|
||||||
|
* <p>Has a little bit of tolerance to make targeting easier</p>
|
||||||
|
*
|
||||||
|
* @param source living entity to get the targets of
|
||||||
|
* @param range maximum range to check
|
||||||
|
* @return all entities in the player's vision line
|
||||||
|
*/
|
||||||
|
public static List<LivingEntity> getLivingTargets(LivingEntity source, double range) {
|
||||||
|
return getLivingTargets(source, range, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Gets all entities the player is looking at within the range using
|
||||||
|
* the given tolerance.</p>
|
||||||
|
*
|
||||||
|
* @param source living entity to get the targets of
|
||||||
|
* @param range maximum range to check
|
||||||
|
* @param tolerance tolerance of the line calculation
|
||||||
|
* @return all entities in the player's vision line
|
||||||
|
*/
|
||||||
|
public static List<LivingEntity> getLivingTargets(LivingEntity source, double range, double tolerance) {
|
||||||
|
List<Entity> list = source.getNearbyEntities(range, range, range);
|
||||||
|
List<LivingEntity> targets = new ArrayList<LivingEntity>();
|
||||||
|
|
||||||
|
Vector facing = source.getLocation().getDirection();
|
||||||
|
double fLengthSq = facing.lengthSquared();
|
||||||
|
|
||||||
|
for (Entity entity : list) {
|
||||||
|
if (!isInFront(source, entity) || !(entity instanceof LivingEntity)) continue;
|
||||||
|
|
||||||
|
Vector relative = entity.getLocation().subtract(source.getLocation()).toVector();
|
||||||
|
double dot = relative.dot(facing);
|
||||||
|
double rLengthSq = relative.lengthSquared();
|
||||||
|
double cosSquared = (dot * dot) / (rLengthSq * fLengthSq);
|
||||||
|
double sinSquared = 1 - cosSquared;
|
||||||
|
double dSquared = rLengthSq * sinSquared;
|
||||||
|
|
||||||
|
// If close enough to vision line, return the entity
|
||||||
|
if (dSquared < tolerance) targets.add((LivingEntity) entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Gets the entity the player is looking at</p>
|
||||||
|
* <p>Has a little bit of tolerance to make targeting easier</p>
|
||||||
|
*
|
||||||
|
* @param source living entity to get the target of
|
||||||
|
* @param range maximum range to check
|
||||||
|
* @return entity player is looing at or null if not found
|
||||||
|
*/
|
||||||
|
public static LivingEntity getLivingTarget(LivingEntity source, double range) {
|
||||||
|
return getLivingTarget(source, range, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Gets the entity the player is looking at</p>
|
||||||
|
* <p>Has a little bit of tolerance to make targeting easier</p>
|
||||||
|
*
|
||||||
|
* @param source living entity to get the target of
|
||||||
|
* @param range maximum range to check
|
||||||
|
* @param tolerance tolerance of the line calculation
|
||||||
|
* @return entity player is looking at or null if not found
|
||||||
|
*/
|
||||||
|
public static LivingEntity getLivingTarget(LivingEntity source, double range, double tolerance) {
|
||||||
|
List<LivingEntity> targets = getLivingTargets(source, range, tolerance);
|
||||||
|
if (targets.size() == 0) return null;
|
||||||
|
LivingEntity target = targets.get(0);
|
||||||
|
double minDistance = target.getLocation().distanceSquared(source.getLocation());
|
||||||
|
for (LivingEntity entity : targets) {
|
||||||
|
double distance = entity.getLocation().distanceSquared(source.getLocation());
|
||||||
|
if (distance < minDistance) {
|
||||||
|
minDistance = distance;
|
||||||
|
target = entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the targets in a cone
|
||||||
|
*
|
||||||
|
* @param source entity to get the targets for
|
||||||
|
* @param arc arc angle of the cone
|
||||||
|
* @param range range of the cone
|
||||||
|
* @return list of targets
|
||||||
|
*/
|
||||||
|
public static List<LivingEntity> getConeTargets(LivingEntity source, double arc, double range) {
|
||||||
|
List<LivingEntity> targets = new ArrayList<LivingEntity>();
|
||||||
|
List<Entity> list = source.getNearbyEntities(range, range, range);
|
||||||
|
if (arc <= 0) return targets;
|
||||||
|
|
||||||
|
// Initialize values
|
||||||
|
Vector dir = source.getLocation().getDirection();
|
||||||
|
dir.setY(0);
|
||||||
|
double cos = Math.cos(arc * Math.PI / 180);
|
||||||
|
double cosSq = cos * cos;
|
||||||
|
|
||||||
|
// Get the targets in the cone
|
||||||
|
for (Entity entity : list) {
|
||||||
|
if (entity instanceof LivingEntity) {
|
||||||
|
|
||||||
|
// Greater than 360 degrees is all targets
|
||||||
|
if (arc >= 360) {
|
||||||
|
targets.add((LivingEntity) entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, select targets based on dot product
|
||||||
|
else {
|
||||||
|
Vector relative = entity.getLocation().subtract(source.getLocation()).toVector();
|
||||||
|
relative.setY(0);
|
||||||
|
double dot = relative.dot(dir);
|
||||||
|
double value = dot * dot / relative.lengthSquared();
|
||||||
|
if (arc < 180 && dot > 0 && value >= cosSq) targets.add((LivingEntity) entity);
|
||||||
|
else if (arc >= 180 && (dot > 0 || dot <= cosSq)) targets.add((LivingEntity) entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the entity is in front of the entity
|
||||||
|
*
|
||||||
|
* @param entity entity to check for
|
||||||
|
* @param target target to check against
|
||||||
|
* @return true if the target is in front of the entity
|
||||||
|
*/
|
||||||
|
public static boolean isInFront(Entity entity, Entity target) {
|
||||||
|
|
||||||
|
// Get the necessary vectors
|
||||||
|
Vector facing = entity.getLocation().getDirection();
|
||||||
|
Vector relative = target.getLocation().subtract(entity.getLocation()).toVector();
|
||||||
|
|
||||||
|
// If the dot product is positive, the target is in front
|
||||||
|
return facing.dot(relative) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the entity is in front of the entity restricted to the given angle
|
||||||
|
*
|
||||||
|
* @param entity entity to check for
|
||||||
|
* @param target target to check against
|
||||||
|
* @param angle angle to restrict it to (0-360)
|
||||||
|
* @return true if the target is in front of the entity
|
||||||
|
*/
|
||||||
|
public static boolean isInFront(Entity entity, Entity target, double angle) {
|
||||||
|
if (angle <= 0) return false;
|
||||||
|
if (angle >= 360) return true;
|
||||||
|
|
||||||
|
// Get the necessary data
|
||||||
|
double dotTarget = Math.cos(angle);
|
||||||
|
Vector facing = entity.getLocation().getDirection();
|
||||||
|
Vector relative = target.getLocation().subtract(entity.getLocation()).toVector().normalize();
|
||||||
|
|
||||||
|
// Compare the target dot product with the actual result
|
||||||
|
return facing.dot(relative) >= dotTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the target is behind the entity
|
||||||
|
*
|
||||||
|
* @param entity entity to check for
|
||||||
|
* @param target target to check against
|
||||||
|
* @return true if the target is behind the entity
|
||||||
|
*/
|
||||||
|
public static boolean isBehind(Entity entity, Entity target) {
|
||||||
|
return !isInFront(entity, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the entity is behind the player restricted to the given angle
|
||||||
|
*
|
||||||
|
* @param entity entity to check for
|
||||||
|
* @param target target to check against
|
||||||
|
* @param angle angle to restrict it to (0-360)
|
||||||
|
* @return true if the target is behind the entity
|
||||||
|
*/
|
||||||
|
public static boolean isBehind(Entity entity, Entity target, double angle) {
|
||||||
|
if (angle <= 0) return false;
|
||||||
|
if (angle >= 360) return true;
|
||||||
|
|
||||||
|
// Get the necessary data
|
||||||
|
double dotTarget = Math.cos(angle);
|
||||||
|
Vector facing = entity.getLocation().getDirection();
|
||||||
|
Vector relative = entity.getLocation().subtract(target.getLocation()).toVector().normalize();
|
||||||
|
|
||||||
|
// Compare the target dot product and the actual result
|
||||||
|
return facing.dot(relative) >= dotTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether or not the line between the two points is obstructed
|
||||||
|
*
|
||||||
|
* @param loc1 first location
|
||||||
|
* @param loc2 second location
|
||||||
|
* @return the location of obstruction or null if not obstructed
|
||||||
|
*/
|
||||||
|
public static boolean isObstructed(Location loc1, Location loc2) {
|
||||||
|
if (loc1.getX() == loc2.getX() && loc1.getY() == loc2.getY() && loc1.getZ() == loc2.getZ()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Vector slope = loc2.clone().subtract(loc1).toVector();
|
||||||
|
int steps = (int) (slope.length() * 4) + 1;
|
||||||
|
slope.multiply(1.0 / steps);
|
||||||
|
Location temp = loc1.clone();
|
||||||
|
for (int i = 0; i < steps; i++) {
|
||||||
|
temp.add(slope);
|
||||||
|
if (temp.getBlock().getType().isSolid() && temp.getBlock().getType() != Material.IRON_FENCE && !temp.getBlock().getType().toString().contains("GLASS")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an open location along the line for teleporting or linear targeting
|
||||||
|
*
|
||||||
|
* @param loc1 start location of the path
|
||||||
|
* @param loc2 end location of the path
|
||||||
|
* @param throughWall whether or not going through walls is allowed
|
||||||
|
* @return the farthest open location along the path
|
||||||
|
*/
|
||||||
|
public static Location getOpenLocation(Location loc1, Location loc2, boolean throughWall) {
|
||||||
|
// Special case
|
||||||
|
if (loc1.getX() == loc2.getX() && loc1.getY() == loc2.getY() && loc1.getZ() == loc2.getZ()) {
|
||||||
|
return loc1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common data
|
||||||
|
Vector slope = loc2.clone().subtract(loc1).toVector();
|
||||||
|
int steps = (int) (slope.length() * 4) + 1;
|
||||||
|
slope.multiply(1.0 / steps);
|
||||||
|
|
||||||
|
// Going through walls starts at the end and traverses backwards
|
||||||
|
if (throughWall) {
|
||||||
|
Location temp = loc2.clone();
|
||||||
|
while (temp.getBlock().getType().isSolid() && steps > 0) {
|
||||||
|
temp.subtract(slope);
|
||||||
|
steps--;
|
||||||
|
}
|
||||||
|
temp.setX(temp.getBlockX() + 0.5);
|
||||||
|
temp.setZ(temp.getBlockZ() + 0.5);
|
||||||
|
temp.setY(temp.getBlockY() + 1);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not going through walls starts at the beginning and traverses forward
|
||||||
|
else {
|
||||||
|
Location temp = loc1.clone();
|
||||||
|
while (!temp.getBlock().getType().isSolid() && steps > 0) {
|
||||||
|
temp.add(slope);
|
||||||
|
steps--;
|
||||||
|
}
|
||||||
|
temp.subtract(slope);
|
||||||
|
temp.setX(temp.getBlockX() + 0.5);
|
||||||
|
temp.setZ(temp.getBlockZ() + 0.5);
|
||||||
|
temp.setY(temp.getBlockY() + 1);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user