) getApplicableRegionsMethod().invoke((getRegionMethod().invoke(plugin, loc.getWorld())), vectorConstructor.newInstance(loc.getX(), loc.getY(),loc.getZ()));
} catch (final Exception e) {
// Cannot handle world guard
+ e.printStackTrace();
return ImmutableList.of();
}
}
}
- private static BlockVector3 asVector(final Location location) {
- return BlockVector3.at(location.getX(), location.getY(),location.getZ());
+ private static Method getApplicableRegionsMethod() throws Exception {
+ if (applicableRegionsMethod == null) {
+ vectorClass = Class.forName("com.sk89q.worldedit.Vector");
+ vectorConstructor = vectorClass.getConstructor(double.class, double.class, double.class);
+ applicableRegionsMethod = RegionManager.class.getMethod("getApplicableRegionsIDs", vectorClass);
+ }
+ return applicableRegionsMethod;
}
private static Method getRegionMethod() throws Exception {
From ac6020019b16839368aff3227f44c10dcb21b930 Mon Sep 17 00:00:00 2001
From: Sentropic <60368610+Sentropic@users.noreply.github.com>
Date: Sat, 19 Dec 2020 16:55:15 -0600
Subject: [PATCH 4/8] Target Improvements
- Linear and Single targets now they check for a collision with the actual hitbox of the entity, not just their center point
- Linear and Single targets now uses the disguise hitbox, if the entity is disguised, and the disguise is set to modify their hitbox
- Area target now gives priority to the nearest entities if "Random" is false
- Fixed caster sometimes being included in the targets even if "Include Caster" was false
- Fixed NoSuchMethodError under 1.13
---
editor/js/component.js | 8 +-
.../com/sucy/skill/api/player/PlayerData.java | 2 +-
.../java/com/sucy/skill/api/target/AABB.java | 235 ++++++++++++++++++
.../skill/api/{ => target}/TargetHelper.java | 77 +++---
.../java/com/sucy/skill/data/Settings.java | 8 +
.../dynamic/condition/DirectionCondition.java | 2 +-
.../skill/dynamic/mechanic/WarpMechanic.java | 2 +-
.../dynamic/mechanic/WarpRandomMechanic.java | 2 +-
.../sucy/skill/dynamic/target/AreaTarget.java | 2 +-
.../sucy/skill/dynamic/target/ConeTarget.java | 2 +-
.../skill/dynamic/target/LinearTarget.java | 2 +-
.../skill/dynamic/target/LocationTarget.java | 2 +-
.../skill/dynamic/target/SingleTarget.java | 2 +-
.../skill/dynamic/target/TargetComponent.java | 21 +-
.../com/sucy/skill/hook/DisguiseHook.java | 44 ++++
15 files changed, 352 insertions(+), 59 deletions(-)
create mode 100644 src/main/java/com/sucy/skill/api/target/AABB.java
rename src/main/java/com/sucy/skill/api/{ => target}/TargetHelper.java (77%)
diff --git a/editor/js/component.js b/editor/js/component.js
index 1a884308..8ef121f3 100644
--- a/editor/js/component.js
+++ b/editor/js/component.js
@@ -868,8 +868,8 @@ function TargetLinear()
this.data.push(new AttributeValue("Range", "range", 5, 0)
.setTooltip('The max distance away any target can be in blocks')
);
- this.data.push(new AttributeValue("Tolerance", "tolerance", 4, 0)
- .setTooltip('How lenient the targeting is. Larger numbers allow easier targeting. It is essentially how wide a cone is which is where you are targeting.')
+ this.data.push(new AttributeValue("Tolerance", "tolerance", 0, 0)
+ .setTooltip('How much to expand the potential entity\'s hitbox in all directions, in blocks. This makes it easier to aim')
);
this.data.push(new ListValue("Group", "group", ["Ally", "Enemy", "Both"], "Enemy")
.setTooltip('The alignment of targets to get')
@@ -972,8 +972,8 @@ function TargetSingle()
this.data.push(new AttributeValue("Range", "range", 5, 0)
.setTooltip('The max distance away any target can be in blocks')
);
- this.data.push(new AttributeValue("Tolerance", "tolerance", 4, 0)
- .setTooltip('How lenient the targeting is. Larger numbers allow easier targeting. It is essentially how wide a cone is which is where you are targeting.')
+ this.data.push(new AttributeValue("Tolerance", "tolerance", 0, 0)
+ .setTooltip('How much to expand the potential entity\'s hitbox in all directions, in blocks. This makes it easier to aim')
);
this.data.push(new ListValue("Group", "group", ["Ally", "Enemy", "Both"], "Enemy")
.setTooltip('The alignment of targets to get')
diff --git a/src/main/java/com/sucy/skill/api/player/PlayerData.java b/src/main/java/com/sucy/skill/api/player/PlayerData.java
index 67aaea14..42af1464 100644
--- a/src/main/java/com/sucy/skill/api/player/PlayerData.java
+++ b/src/main/java/com/sucy/skill/api/player/PlayerData.java
@@ -29,7 +29,7 @@
import com.rit.sucy.config.Filter;
import com.rit.sucy.config.FilterType;
import com.rit.sucy.config.parse.DataSection;
-import com.sucy.skill.api.TargetHelper;
+import com.sucy.skill.api.target.TargetHelper;
import com.rit.sucy.version.VersionManager;
import com.rit.sucy.version.VersionPlayer;
import com.sucy.skill.SkillAPI;
diff --git a/src/main/java/com/sucy/skill/api/target/AABB.java b/src/main/java/com/sucy/skill/api/target/AABB.java
new file mode 100644
index 00000000..104c832b
--- /dev/null
+++ b/src/main/java/com/sucy/skill/api/target/AABB.java
@@ -0,0 +1,235 @@
+package com.sucy.skill.api.target;
+
+import com.google.common.base.Objects;
+import org.bukkit.Location;
+import org.bukkit.util.Vector;
+
+/**
+ * Represents an axix-aligned bounding box.
+ *
+ * @author Kristian
+ */
+public class AABB {
+ public static class Vec3D {
+ /**
+ * Point with the coordinate (1, 1, 1).
+ */
+ public static final Vec3D UNIT_MAX = new Vec3D(1, 1, 1);
+
+ /** X coordinate. */
+ public final double x;
+ /** Y coordinate. */
+ public final double y;
+ /** Z coordinate. */
+ public final double z;
+
+ /**
+ * Creates a new vector with the given coordinates.
+ * @param x the x
+ * @param y the y
+ * @param z the z
+ */
+ public Vec3D(double x, double y, double z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ /**
+ * Creates a new vector with the coordinates of the given vector.
+ * @param v vector to copy.
+ */
+ public Vec3D(Vec3D v) {
+ this.x = v.x;
+ this.y = v.y;
+ this.z = v.z;
+ }
+
+ /**
+ * Construct a vector from a Bukkit location.
+ * @param loc - the Bukkit location.
+ */
+ public static Vec3D fromLocation(Location loc) {
+ return new Vec3D(loc.getX(), loc.getY(), loc.getZ());
+ }
+
+ /**
+ * Construct a copy of our immutable vector from Bukkit's mutable vector.
+ * @param v - Bukkit vector.
+ * @return A copy of the given vector.
+ */
+ public static Vec3D fromVector(Vector v) {
+ return new Vec3D(v.getX(), v.getY(), v.getZ());
+ }
+
+ /**
+ * Add vector v and returns result as new vector.
+ *
+ * @param v vector to add
+ * @return result as new vector
+ */
+ public final Vec3D add(Vec3D v) {
+ return new Vec3D(x + v.x, y + v.y, z + v.z);
+ }
+
+ /**
+ * Scales vector uniformly and returns result as new vector.
+ *
+ * @param s scale factor
+ *
+ * @return new vector
+ */
+ public Vec3D scale(double s) {
+ return new Vec3D(x * s, y * s, z * s);
+ }
+
+ /**
+ * Normalizes the vector so that its magnitude = 1.
+ * @return The normalized vector.
+ */
+ public Vec3D normalize() {
+ double mag = Math.sqrt(x * x + y * y + z * z);
+
+ if (mag > 0)
+ return scale(1.0 / mag);
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Vec3D) {
+ final Vec3D v = (Vec3D) obj;
+ return x == v.x && y == v.y && z == v.z;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(x, y, z);
+ }
+
+ public String toString() {
+ return String.format("{x: %g, y: %g, z: %g}", x, y, z);
+ }
+ }
+
+ public static class Ray3D extends Vec3D {
+ public final Vec3D dir;
+
+ public Ray3D(Vec3D origin, Vec3D direction) {
+ super(origin);
+ dir = direction.normalize();
+ }
+
+ /**
+ * Construct a 3D ray from a location.
+ * @param loc - the Bukkit location.
+ */
+ public Ray3D(Location loc) {
+ this(Vec3D.fromLocation(loc), Vec3D.fromVector(loc.getDirection()));
+ }
+
+ public Vec3D getDirection() {
+ return dir;
+ }
+
+ public Vec3D getPointAtDistance(double dist) {
+ return add(dir.scale(dist));
+ }
+
+ public String toString() {
+ return "origin: " + super.toString() + " dir: " + dir;
+ }
+ }
+
+ private Vec3D max;
+ private Vec3D min;
+
+ /**
+ * Creates a new instance from a minimum point and a maximum point.
+ */
+ public AABB(Vec3D min, Vec3D max) {
+ this.min = min;
+ this.max = max;
+ }
+
+ /**
+ * Create a new AABB from a given block.
+ * @param block - the block.
+ */
+ public AABB(Location block) {
+ this(Vec3D.fromLocation(block), Vec3D.fromLocation(block).add(Vec3D.UNIT_MAX));
+ }
+
+ public Vec3D getMax() { return max; }
+ public Vec3D getMin() { return min; }
+
+ public void expand(double expand) {
+ min = min.add(new Vec3D(-expand, -expand, -expand));
+ max = max.add(new Vec3D(expand, expand, expand));
+ }
+
+ /**
+ * Calculates intersection with the given ray between a certain distance
+ * interval.
+ *
+ * Ray-box intersection is using IEEE numerical properties to ensure the
+ * test is both robust and efficient, as described in:
+ *
+ * Amy Williams, Steve Barrus, R. Keith Morley, and Peter Shirley: "An
+ * Efficient and Robust Ray-Box Intersection Algorithm" Journal of graphics
+ * tools, 10(1):49-54, 2005
+ *
+ * @param ray incident ray
+ * @param minDist
+ * @param maxDist
+ * @return intersection point on the bounding box (only the first is
+ * returned) or null if no intersection
+ */
+ public Vec3D intersectsRay(Ray3D ray, float minDist, double maxDist) {
+ Vec3D invDir = new Vec3D(1f / ray.dir.x, 1f / ray.dir.y, 1f / ray.dir.z);
+
+ boolean signDirX = invDir.x < 0;
+ boolean signDirY = invDir.y < 0;
+ boolean signDirZ = invDir.z < 0;
+
+ Vec3D bbox = signDirX ? max : min;
+ double tmin = (bbox.x - ray.x) * invDir.x;
+ bbox = signDirX ? min : max;
+ double tmax = (bbox.x - ray.x) * invDir.x;
+ bbox = signDirY ? max : min;
+ double tymin = (bbox.y - ray.y) * invDir.y;
+ bbox = signDirY ? min : max;
+ double tymax = (bbox.y - ray.y) * invDir.y;
+
+ if ((tmin > tymax) || (tymin > tmax)) {
+ return null;
+ }
+ if (tymin > tmin) {
+ tmin = tymin;
+ }
+ if (tymax < tmax) {
+ tmax = tymax;
+ }
+
+ bbox = signDirZ ? max : min;
+ double tzmin = (bbox.z - ray.z) * invDir.z;
+ bbox = signDirZ ? min : max;
+ double tzmax = (bbox.z - ray.z) * invDir.z;
+
+ if ((tmin > tzmax) || (tzmin > tmax)) {
+ return null;
+ }
+ if (tzmin > tmin) {
+ tmin = tzmin;
+ }
+ if (tzmax < tmax) {
+ tmax = tzmax;
+ }
+ if ((tmin < maxDist) && (tmax > minDist)) {
+ return ray.getPointAtDistance(tmin);
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/sucy/skill/api/TargetHelper.java b/src/main/java/com/sucy/skill/api/target/TargetHelper.java
similarity index 77%
rename from src/main/java/com/sucy/skill/api/TargetHelper.java
rename to src/main/java/com/sucy/skill/api/target/TargetHelper.java
index f64cf953..dfe6f771 100644
--- a/src/main/java/com/sucy/skill/api/TargetHelper.java
+++ b/src/main/java/com/sucy/skill/api/target/TargetHelper.java
@@ -1,15 +1,22 @@
-package com.sucy.skill.api;
+package com.sucy.skill.api.target;
+import com.sucy.skill.hook.DisguiseHook;
+import com.sucy.skill.hook.PluginChecker;
+import me.libraryaddict.disguise.DisguiseAPI;
+import me.libraryaddict.disguise.utilities.reflection.FakeBoundingBox;
import org.bukkit.Location;
+import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
+import java.util.TreeMap;
public abstract class TargetHelper {
+
/**
*
Number of pixels that end up displaying about 1 degree of vision in the client window
* Not really useful since you can't get the client's window size, but I added it in case
@@ -44,28 +51,28 @@ public static List getLivingTargets(LivingEntity source, double ra
public static List getLivingTargets(LivingEntity source, double range, double tolerance)
{
List list = source.getNearbyEntities(range, range, range);
- List targets = new ArrayList<>();
+ TreeMap targets = new TreeMap<>();
- Location sourceLocation = source.getEyeLocation();
- Vector facing = sourceLocation.getDirection();
- double fLengthSq = facing.lengthSquared();
+ Location location = source.getEyeLocation();
+ Vector origin = location.toVector();
+ AABB.Ray3D ray = new AABB.Ray3D(location);
for (Entity entity : list)
{
if (!isInFront(source, entity) || !(entity instanceof LivingEntity)) continue;
- Vector relative = entity.getLocation().clone().add(0,entity.getBoundingBox().getHeight()*0.5,0).subtract(sourceLocation).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);
+ AABB aabb = getAABB(entity);
+ aabb.expand(tolerance);
+ AABB.Vec3D min = aabb.getMin();
+ AABB.Vec3D max = aabb.getMax();
+ entity.getWorld().spawnParticle(Particle.CRIT,min.x, min.y, min.z,1,0,0,0,0,null);
+ entity.getWorld().spawnParticle(Particle.CRIT,max.x, max.y, max.z,1,0,0,0,0,null);
+ AABB.Vec3D collision = aabb.intersectsRay(ray, 0, range);
+ if (collision != null) {
+ targets.put(new Vector(collision.x, collision.y, collision.z).distance(origin), (LivingEntity) entity);
+ }
}
-
- return targets;
+ return new ArrayList<>(targets.values());
}
/**
@@ -96,19 +103,7 @@ public static LivingEntity getLivingTarget(LivingEntity source, double range, do
{
List targets = getLivingTargets(source, range, tolerance);
if (targets.size() == 0) return null;
- Location sourceLocation = source.getEyeLocation();
- LivingEntity target = targets.get(0);
- double minDistance = target.getLocation().clone().add(0,target.getBoundingBox().getHeight()*0.5,0).distanceSquared(sourceLocation);
- for (LivingEntity entity : targets)
- {
- double distance = entity.getLocation().distanceSquared(sourceLocation);
- if (distance < minDistance)
- {
- minDistance = distance;
- target = entity;
- }
- }
- return target;
+ return targets.get(0);
}
/**
@@ -148,7 +143,7 @@ public static List getConeTargets(LivingEntity source, double arc,
// Otherwise, select targets based on dot product
else
{
- Vector relative = entity.getLocation().clone().add(0,entity.getBoundingBox().getHeight()*0.5,0).subtract(sourceLocation).toVector();
+ Vector relative = entity.getLocation().clone().add(0, getHeight(entity)*0.5,0).subtract(sourceLocation).toVector();
relative.setY(0);
double dot = relative.dot(dir);
double value = dot * dot / relative.lengthSquared();
@@ -174,7 +169,7 @@ public static boolean isInFront(Entity entity, Entity target)
// Get the necessary vectors
Vector facing = entity.getLocation().getDirection();
- Vector relative = target.getLocation().clone().add(0,target.getBoundingBox().getHeight()*0.5,0).subtract(entity.getLocation()).toVector();
+ Vector relative = target.getLocation().clone().add(0,getHeight(entity)*0.5,0).subtract(entity.getLocation()).toVector();
// If the dot product is positive, the target is in front
return facing.dot(relative) >= 0;
@@ -197,7 +192,7 @@ public static boolean isInFront(Entity entity, Entity target, double angle)
// Get the necessary data
double dotTarget = Math.cos(angle);
Vector facing = entity.getLocation().getDirection();
- Vector relative = target.getLocation().clone().add(0,target.getBoundingBox().getHeight()*0.5,0).subtract(entity.getLocation()).toVector().normalize();
+ Vector relative = target.getLocation().clone().add(0,getHeight(entity)*0.5,0).subtract(entity.getLocation()).toVector().normalize();
// Compare the target dot product with the actual result
return facing.dot(relative) >= dotTarget;
@@ -233,7 +228,7 @@ public static boolean isBehind(Entity entity, Entity target, double angle)
// Get the necessary data
double dotTarget = Math.cos(angle);
Vector facing = entity.getLocation().getDirection();
- Vector relative = entity.getLocation().clone().add(0,entity.getBoundingBox().getHeight()*0.5,0).subtract(target.getLocation()).toVector().normalize();
+ Vector relative = entity.getLocation().clone().add(0,getHeight(entity)*0.5,0).subtract(target.getLocation()).toVector().normalize();
// Compare the target dot product and the actual result
return facing.dot(relative) >= dotTarget;
@@ -321,4 +316,20 @@ public static Location getOpenLocation(Location loc1, Location loc2, boolean thr
return temp;
}
}
+
+ public static AABB getAABB(Entity entity) {
+ AABB.Vec3D origin = AABB.Vec3D.fromLocation(entity.getLocation());
+ try {
+ if (PluginChecker.isDisguiseActive() && DisguiseAPI.isDisguised(entity) && DisguiseAPI.getDisguise(entity).isModifyBoundingBox()) {
+ FakeBoundingBox boundingBox = DisguiseHook.getFakeBoundingBox(entity);
+ return new AABB(origin.add(new AABB.Vec3D(-boundingBox.getX(), 0, -boundingBox.getZ())), origin.add(new AABB.Vec3D(boundingBox.getX(), boundingBox.getY(), boundingBox.getZ())));
+ }
+ } catch (NullPointerException ignored) {}
+ double halfWidth = entity.getWidth()/2;
+ return new AABB(origin.add(new AABB.Vec3D(-halfWidth, 0, -halfWidth)), origin.add(new AABB.Vec3D(halfWidth, entity.getHeight(), halfWidth)));
+ }
+
+ public static double getHeight(Entity entity) {
+ return (PluginChecker.isDisguiseActive() && DisguiseAPI.isDisguised(entity)) ? DisguiseHook.getFakeBoundingBox(entity).getY() : entity.getHeight();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/sucy/skill/data/Settings.java b/src/main/java/com/sucy/skill/data/Settings.java
index d90a2c65..c838a01b 100644
--- a/src/main/java/com/sucy/skill/data/Settings.java
+++ b/src/main/java/com/sucy/skill/data/Settings.java
@@ -67,6 +67,7 @@ public class Settings {
private DataSection config;
private boolean OLD_DURABILITY;
+ private boolean BOUNDING_BOX;
/**
* Initializes a new settings manager.
@@ -97,6 +98,12 @@ public void reload() {
} catch (ClassNotFoundException e) {
OLD_DURABILITY = true;
}
+ try {
+ Entity.class.getMethod("getBoundingBox");
+ BOUNDING_BOX = true;
+ } catch (NoSuchMethodException e) {
+ BOUNDING_BOX = false;
+ }
loadExperienceSettings();
loadAccountSettings();
@@ -117,6 +124,7 @@ public void reload() {
}
public boolean useOldDurability() { return OLD_DURABILITY; }
+ public boolean useBoundingBoxes() { return BOUNDING_BOX; }
///////////////////////////////////////////////////////
// //
diff --git a/src/main/java/com/sucy/skill/dynamic/condition/DirectionCondition.java b/src/main/java/com/sucy/skill/dynamic/condition/DirectionCondition.java
index 1754c5d4..2c1a0713 100644
--- a/src/main/java/com/sucy/skill/dynamic/condition/DirectionCondition.java
+++ b/src/main/java/com/sucy/skill/dynamic/condition/DirectionCondition.java
@@ -27,7 +27,7 @@
package com.sucy.skill.dynamic.condition;
import com.rit.sucy.config.parse.DataSection;
-import com.sucy.skill.api.TargetHelper;
+import com.sucy.skill.api.target.TargetHelper;
import com.sucy.skill.dynamic.DynamicSkill;
import org.bukkit.entity.LivingEntity;
diff --git a/src/main/java/com/sucy/skill/dynamic/mechanic/WarpMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpMechanic.java
index 5da33c24..5cee6482 100644
--- a/src/main/java/com/sucy/skill/dynamic/mechanic/WarpMechanic.java
+++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpMechanic.java
@@ -26,7 +26,7 @@
*/
package com.sucy.skill.dynamic.mechanic;
-import com.sucy.skill.api.TargetHelper;
+import com.sucy.skill.api.target.TargetHelper;
import org.bukkit.Location;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.LivingEntity;
diff --git a/src/main/java/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java
index 3afb81d6..3c0473fa 100644
--- a/src/main/java/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java
+++ b/src/main/java/com/sucy/skill/dynamic/mechanic/WarpRandomMechanic.java
@@ -26,7 +26,7 @@
*/
package com.sucy.skill.dynamic.mechanic;
-import com.sucy.skill.api.TargetHelper;
+import com.sucy.skill.api.target.TargetHelper;
import org.bukkit.Location;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.LivingEntity;
diff --git a/src/main/java/com/sucy/skill/dynamic/target/AreaTarget.java b/src/main/java/com/sucy/skill/dynamic/target/AreaTarget.java
index c52b8d72..c83a62b6 100644
--- a/src/main/java/com/sucy/skill/dynamic/target/AreaTarget.java
+++ b/src/main/java/com/sucy/skill/dynamic/target/AreaTarget.java
@@ -52,7 +52,7 @@ List getTargets(
final double radius = parseValues(caster, RADIUS, level, 3.0);
final boolean random = settings.getBool(RANDOM, false);
- return determineTargets(caster, level, targets, t -> shuffle(Nearby.getLivingNearby(t.getLocation(), radius), random));
+ return determineTargets(caster, level, targets, t -> shuffle(Nearby.getLivingNearby(caster, radius), random));
}
/** {@inheritDoc} */
diff --git a/src/main/java/com/sucy/skill/dynamic/target/ConeTarget.java b/src/main/java/com/sucy/skill/dynamic/target/ConeTarget.java
index 7852fbb5..05782d67 100644
--- a/src/main/java/com/sucy/skill/dynamic/target/ConeTarget.java
+++ b/src/main/java/com/sucy/skill/dynamic/target/ConeTarget.java
@@ -26,7 +26,7 @@
*/
package com.sucy.skill.dynamic.target;
-import com.sucy.skill.api.TargetHelper;
+import com.sucy.skill.api.target.TargetHelper;
import com.sucy.skill.cast.IIndicator;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
diff --git a/src/main/java/com/sucy/skill/dynamic/target/LinearTarget.java b/src/main/java/com/sucy/skill/dynamic/target/LinearTarget.java
index 340c7262..c3636161 100644
--- a/src/main/java/com/sucy/skill/dynamic/target/LinearTarget.java
+++ b/src/main/java/com/sucy/skill/dynamic/target/LinearTarget.java
@@ -26,7 +26,7 @@
*/
package com.sucy.skill.dynamic.target;
-import com.sucy.skill.api.TargetHelper;
+import com.sucy.skill.api.target.TargetHelper;
import com.sucy.skill.cast.IIndicator;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
diff --git a/src/main/java/com/sucy/skill/dynamic/target/LocationTarget.java b/src/main/java/com/sucy/skill/dynamic/target/LocationTarget.java
index 43e43eda..14dc9d62 100644
--- a/src/main/java/com/sucy/skill/dynamic/target/LocationTarget.java
+++ b/src/main/java/com/sucy/skill/dynamic/target/LocationTarget.java
@@ -27,7 +27,7 @@
package com.sucy.skill.dynamic.target;
import com.google.common.collect.ImmutableList;
-import com.sucy.skill.api.TargetHelper;
+import com.sucy.skill.api.target.TargetHelper;
import com.sucy.skill.cast.IIndicator;
import com.sucy.skill.dynamic.TempEntity;
import org.bukkit.Location;
diff --git a/src/main/java/com/sucy/skill/dynamic/target/SingleTarget.java b/src/main/java/com/sucy/skill/dynamic/target/SingleTarget.java
index 077dbd78..ecc995f2 100644
--- a/src/main/java/com/sucy/skill/dynamic/target/SingleTarget.java
+++ b/src/main/java/com/sucy/skill/dynamic/target/SingleTarget.java
@@ -27,7 +27,7 @@
package com.sucy.skill.dynamic.target;
import com.google.common.collect.ImmutableList;
-import com.sucy.skill.api.TargetHelper;
+import com.sucy.skill.api.target.TargetHelper;
import com.sucy.skill.cast.IIndicator;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
diff --git a/src/main/java/com/sucy/skill/dynamic/target/TargetComponent.java b/src/main/java/com/sucy/skill/dynamic/target/TargetComponent.java
index ddc4615c..6bb8f744 100644
--- a/src/main/java/com/sucy/skill/dynamic/target/TargetComponent.java
+++ b/src/main/java/com/sucy/skill/dynamic/target/TargetComponent.java
@@ -1,13 +1,9 @@
package com.sucy.skill.dynamic.target;
import com.rit.sucy.config.parse.DataSection;
-import com.sucy.skill.api.TargetHelper;
import com.sucy.skill.SkillAPI;
-import com.sucy.skill.cast.CircleIndicator;
-import com.sucy.skill.cast.ConeIndicator;
-import com.sucy.skill.cast.IIndicator;
-import com.sucy.skill.cast.IndicatorType;
-import com.sucy.skill.cast.SphereIndicator;
+import com.sucy.skill.api.target.TargetHelper;
+import com.sucy.skill.cast.*;
import com.sucy.skill.dynamic.ComponentType;
import com.sucy.skill.dynamic.DynamicSkill;
import com.sucy.skill.dynamic.EffectComponent;
@@ -131,15 +127,14 @@ List determineTargets(
final List list = new ArrayList<>();
from.forEach(target -> {
- final int count = list.size();
final List found = conversion.apply(target);
+ int count = 0;
+
for (LivingEntity entity : found) {
- if (isValidTarget(caster, target, entity)) {
- list.add(entity);
- if (list.size() - count >= max) {
- break;
- }
- }
+ if (count >= max) break;
+ if (!isValidTarget(caster, target, entity)) continue;
+ list.add(found.get(count));
+ count++;
}
});
if (self) {
diff --git a/src/main/java/com/sucy/skill/hook/DisguiseHook.java b/src/main/java/com/sucy/skill/hook/DisguiseHook.java
index 4053e587..4a221963 100644
--- a/src/main/java/com/sucy/skill/hook/DisguiseHook.java
+++ b/src/main/java/com/sucy/skill/hook/DisguiseHook.java
@@ -29,7 +29,13 @@
import com.sucy.skill.log.Logger;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.disguisetypes.*;
+import me.libraryaddict.disguise.disguisetypes.watchers.ArmorStandWatcher;
+import me.libraryaddict.disguise.disguisetypes.watchers.SlimeWatcher;
+import me.libraryaddict.disguise.utilities.DisguiseValues;
+import me.libraryaddict.disguise.utilities.reflection.FakeBoundingBox;
+import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
/**
* Handles calling functions from Lib's Disguise
@@ -116,4 +122,42 @@ public static void removeDisguise(LivingEntity target)
for (Disguise disguise : DisguiseAPI.getDisguises(target))
disguise.removeDisguise();
}
+
+ public static FakeBoundingBox getFakeBoundingBox(Entity entity) {
+ Disguise disguise = DisguiseAPI.getDisguise(entity);
+ if (disguise instanceof MiscDisguise) {
+ DisguiseValues values = DisguiseValues.getDisguiseValues(disguise.getType());
+ if (values == null) return null;
+ else return values.getAdultBox();
+ } else if (disguise instanceof MobDisguise) {
+ MobDisguise mobDisguise = (MobDisguise) disguise;
+ DisguiseValues values = DisguiseValues.getDisguiseValues(mobDisguise.getType());
+ if (values != null && values.getAdultBox() != null) {
+ if (!mobDisguise.isAdult() && values.getBabyBox() != null) {
+ return values.getBabyBox();
+ } else {
+ if (mobDisguise.getWatcher() != null) {
+ if (mobDisguise.getType() == DisguiseType.ARMOR_STAND) {
+ return (((ArmorStandWatcher)mobDisguise.getWatcher()).isSmall() ? values.getBabyBox() : values.getAdultBox());
+ }
+
+ if (mobDisguise.getType() == DisguiseType.SLIME || mobDisguise.getType() == DisguiseType.MAGMA_CUBE) {
+ double a = 0.51D * 0.255D * (double)((SlimeWatcher)mobDisguise.getWatcher()).getSize();
+ return new FakeBoundingBox(a, a, a);
+ }
+ }
+ return values.getAdultBox();
+ }
+ } else { return null; }
+ } else if (disguise instanceof ModdedDisguise) { return null;
+ } else if (disguise instanceof PlayerDisguise) {
+ if (disguise.getWatcher() == null) {
+ return new FakeBoundingBox(0.6, 0.6, 1.8);
+ } else if (disguise.getEntity() != null && !disguise.getWatcher().getModifiedEntityAnimations()[1]) {
+ return disguise.getEntity() instanceof Player && ((Player)disguise.getEntity()).isSneaking() ? new FakeBoundingBox(0.6, 0.6, 1.5) : new FakeBoundingBox(0.6, 0.6, 1.8);
+ } else {
+ return disguise.getWatcher().isSneaking() ? new FakeBoundingBox(0.6, 0.6, 1.5) : new FakeBoundingBox(0.6, 0.6, 1.8);
+ }
+ } else return null;
+ }
}
From 3f50173a7838a5fc5307d0cf1cbdf349308d943e Mon Sep 17 00:00:00 2001
From: Sentropic <60368610+Sentropic@users.noreply.github.com>
Date: Sat, 19 Dec 2020 16:59:18 -0600
Subject: [PATCH 5/8] Update Nearby.java
---
src/main/java/com/sucy/skill/api/util/Nearby.java | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/main/java/com/sucy/skill/api/util/Nearby.java b/src/main/java/com/sucy/skill/api/util/Nearby.java
index 4f8a2661..9aa8323b 100644
--- a/src/main/java/com/sucy/skill/api/util/Nearby.java
+++ b/src/main/java/com/sucy/skill/api/util/Nearby.java
@@ -32,6 +32,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.TreeMap;
/**
* Fetches nearby entities by going through possible chunks
@@ -80,7 +81,7 @@ public static List getLivingNearby(Location loc, double radius) {
}
private static List getLivingNearby(Entity source, Location loc, double radius) {
- List result = new ArrayList();
+ TreeMap result = new TreeMap<>();
int minX = (int) (loc.getX() - radius) >> 4;
int maxX = (int) (loc.getX() + radius) >> 4;
@@ -96,9 +97,9 @@ private static List getLivingNearby(Entity source, Location loc, d
&& entity instanceof LivingEntity
&& entity.getWorld() == loc.getWorld()
&& entity.getLocation().distanceSquared(loc) < radius)
- result.add((LivingEntity) entity);
+ result.put(entity.getLocation().distance(loc), (LivingEntity) entity);
- return result;
+ return new ArrayList<>(result.values());
}
/**
From 54fc085aef168b1443d40ee03bbbdea90c1cbd8f Mon Sep 17 00:00:00 2001
From: Sentropic <60368610+Sentropic@users.noreply.github.com>
Date: Sat, 19 Dec 2020 18:31:33 -0600
Subject: [PATCH 6/8] Updated PluginChecker
- Now plugin status is stored on enables, and not queried every time methods are used
- Fixed NoSuchMethodError due to not checking whether Parties is enabled
---
src/main/java/com/sucy/skill/SkillAPI.java | 1 +
.../java/com/sucy/skill/data/Settings.java | 3 +-
.../com/sucy/skill/hook/PluginChecker.java | 148 +++++++++++++-----
3 files changed, 112 insertions(+), 40 deletions(-)
diff --git a/src/main/java/com/sucy/skill/SkillAPI.java b/src/main/java/com/sucy/skill/SkillAPI.java
index b7f003ac..c5b652fc 100644
--- a/src/main/java/com/sucy/skill/SkillAPI.java
+++ b/src/main/java/com/sucy/skill/SkillAPI.java
@@ -167,6 +167,7 @@ public void onEnable() {
listen(new DeathListener(), !VersionManager.isVersionAtLeast(11000));
listen(new LingeringPotionListener(), VersionManager.isVersionAtLeast(VersionManager.V1_9_0));
listen(new ExperienceListener(), settings.yieldsEnabled());
+ new PluginChecker(this);
// Set up tasks
if (settings.isManaEnabled()) {
diff --git a/src/main/java/com/sucy/skill/data/Settings.java b/src/main/java/com/sucy/skill/data/Settings.java
index c838a01b..c128c384 100644
--- a/src/main/java/com/sucy/skill/data/Settings.java
+++ b/src/main/java/com/sucy/skill/data/Settings.java
@@ -45,6 +45,7 @@
import com.sucy.skill.data.formula.value.CustomValue;
import com.sucy.skill.dynamic.DynamicSkill;
import com.sucy.skill.gui.tool.GUITool;
+import com.sucy.skill.hook.PluginChecker;
import com.sucy.skill.log.Logger;
import org.bukkit.Material;
import org.bukkit.World;
@@ -379,7 +380,7 @@ public boolean canAttack(LivingEntity attacker, LivingEntity target) {
} else if (target instanceof Player) {
if (playerAlly || playerWorlds.contains(attacker.getWorld().getName())) { return false; }
- if (partiesAlly) {
+ if (PluginChecker.isPartiesActive() && partiesAlly) {
final Parties parties = Parties.getPlugin(Parties.class);
final Party p1 = parties.getJoinedParty(player);
final Party p2 = parties.getJoinedParty((Player) target);
diff --git a/src/main/java/com/sucy/skill/hook/PluginChecker.java b/src/main/java/com/sucy/skill/hook/PluginChecker.java
index 0792067d..72789b43 100644
--- a/src/main/java/com/sucy/skill/hook/PluginChecker.java
+++ b/src/main/java/com/sucy/skill/hook/PluginChecker.java
@@ -26,81 +26,151 @@
*/
package com.sucy.skill.hook;
+import com.sucy.skill.SkillAPI;
import org.bukkit.Bukkit;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.server.PluginDisableEvent;
+import org.bukkit.event.server.PluginEnableEvent;
+import org.bukkit.plugin.PluginManager;
/**
* Handler for checking whether or not hooked plugins are present
* and active before using related code.
*/
-public class PluginChecker
-{
+public class PluginChecker implements Listener {
+ private static PluginChecker singleton;
+
+ private static boolean vault;
+ private static boolean libsDisguises;
+ private static boolean noCheatPlus;
+ private static boolean rpgInventory;
+ private static boolean papi;
+ private static boolean bungee;
+ private static boolean mythicMobs;
+ private static boolean worldGuard;
+ private static boolean parties;
+
+ public PluginChecker(SkillAPI plugin) {
+ if (singleton != null) return;
+ singleton = this;
+ PluginManager pluginManager = Bukkit.getPluginManager();
+ pluginManager.registerEvents(this, plugin);
+
+ vault = pluginManager.isPluginEnabled("Vault") && VaultHook.isValid();
+ libsDisguises = pluginManager.isPluginEnabled("LibsDisguises");
+ noCheatPlus = pluginManager.isPluginEnabled("NoCheatPlus");
+ rpgInventory = pluginManager.isPluginEnabled("RPGInventory");
+ papi = pluginManager.isPluginEnabled("PlaceholderAPI");
+ try {
+ Class.forName("net.md_5.bungee.Util");
+ bungee = true;
+ } catch (Exception ex) { bungee = false; }
+ mythicMobs = pluginManager.isPluginEnabled("MythicMobs");
+ worldGuard = pluginManager.isPluginEnabled("WorldGuard");
+ parties = pluginManager.isPluginEnabled("Parties");
+ }
+
+ @EventHandler
+ public void onPluginEnable(PluginEnableEvent event) {
+ switch (event.getPlugin().getName()) {
+ case "Vault":
+ vault = true;
+ break;
+ case "LibsDisguises":
+ libsDisguises = true;
+ break;
+ case "NoCheatPlus":
+ noCheatPlus = true;
+ break;
+ case "RPGInventory":
+ rpgInventory = true;
+ break;
+ case "PlaceholderAPI":
+ papi = true;
+ break;
+ case "MythicMobs":
+ mythicMobs = true;
+ break;
+ case "WorldGuard":
+ worldGuard = true;
+ break;
+ case "Parties":
+ parties = true;
+ break;
+ }
+ }
+
+ @EventHandler
+ public void onPluginDisable(PluginDisableEvent event) {
+ switch (event.getPlugin().getName()) {
+ case "Vault":
+ vault = false;
+ break;
+ case "LibsDisguises":
+ libsDisguises = false;
+ break;
+ case "NoCheatPlus":
+ noCheatPlus = false;
+ break;
+ case "RPGInventory":
+ rpgInventory = false;
+ break;
+ case "PlaceholderAPI":
+ papi = true;
+ break;
+ case "MythicMobs":
+ mythicMobs = false;
+ break;
+ case "WorldGuard":
+ worldGuard = false;
+ break;
+ case "Parties":
+ parties = false;
+ break;
+ }
+ }
+
/**
* Checks if vault is active on the server
*
* @return true if active with permissions plugin, false otherwise
*/
- public static boolean isVaultActive()
- {
- return Bukkit.getPluginManager().isPluginEnabled("Vault") && VaultHook.isValid();
- }
+ public static boolean isVaultActive() { return vault; }
/**
* Checks whether or not Lib's Disguises is active
*
* @return true if active
*/
- public static boolean isDisguiseActive()
- {
- return Bukkit.getPluginManager().isPluginEnabled("LibsDisguises");
- }
+ public static boolean isDisguiseActive() { return libsDisguises; }
/**
* Checks whether or not NoCheatPlus is active on the server
*
* @return true if active, false otherwise
*/
- public static boolean isNoCheatActive()
- {
- return Bukkit.getPluginManager().isPluginEnabled("NoCheatPlus");
- }
+ public static boolean isNoCheatActive() { return noCheatPlus; }
/**
* Checks whether or not RPGInventory is active on the server
*
* @return true if active, false otherwise
*/
- public static boolean isRPGInventoryActive()
- {
- return Bukkit.getPluginManager().isPluginEnabled("RPGInventory");
- }
+ public static boolean isRPGInventoryActive() { return rpgInventory; }
- public static boolean isPlaceholderAPIActive() {
- return Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
- }
+ public static boolean isPlaceholderAPIActive() { return papi; }
/**
* Checks whether or not bungee is present
*
* @return true if present, false otherwise
*/
- public static boolean isBungeeActive()
- {
- try
- {
- Class.forName("net.md_5.bungee.Util");
- return true;
- }
- catch (Exception ex)
- {
- return false;
- }
- }
+ public static boolean isBungeeActive() { return bungee; }
- public static boolean isMythicMobsActive() {
- return Bukkit.getPluginManager().isPluginEnabled("MythicMobs");
- }
+ public static boolean isMythicMobsActive() { return mythicMobs; }
- public static boolean isWorldGuardActive() {
- return Bukkit.getPluginManager().isPluginEnabled("WorldGuard");
- }
+ public static boolean isWorldGuardActive() { return worldGuard; }
+
+ public static boolean isPartiesActive() { return parties; }
}
From c63fdb52d9804fb3eb868fc36c7ec68b7fa1c0c7 Mon Sep 17 00:00:00 2001
From: Sentropic <60368610+Sentropic@users.noreply.github.com>
Date: Sat, 19 Dec 2020 18:48:49 -0600
Subject: [PATCH 7/8] Added apostrophe (') placeholder (&sq) to Message and
Command Mechanics
---
editor/js/component.js | 6 +++---
src/main/java/com/sucy/skill/dynamic/EffectComponent.java | 5 +++++
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/editor/js/component.js b/editor/js/component.js
index 8ef121f3..6a5a5921 100644
--- a/editor/js/component.js
+++ b/editor/js/component.js
@@ -1765,10 +1765,10 @@ function MechanicCommand()
this.description ='Executes a command for each of the targets.';
this.data.push(new StringValue('Command', 'command', '')
- .setTooltip('The command to execute')
+ .setTooltip('The command to execute. {player} = caster\'s name, {target} = target\'s name, {targetUUID} = target\'s UUID (useful if targets are non players), &lc: "{", &rc: "}", &sq: "\'"')
);
this.data.push(new ListValue('Execute Type', 'type', [ 'Console', 'OP' ], 'OP')
- .setTooltip('Console: executes the command from the console. OP: Only if the target is a player, will have them execute it while given a temporary OP permission (If server closes in the meantime, the permission might stay, not recommended!!). {player} = caster\'s name, {target} = target\'s name, {targetUUID} = target\'s UUID (useful if targets are non players), &lc: "{", &rc: "}"')
+ .setTooltip('Console: executes the command from the console. OP: Only if the target is a player, will have them execute it while given a temporary OP permission (If server closes in the meantime, the permission might stay, not recommended!!)')
);
}
@@ -2229,7 +2229,7 @@ function MechanicMessage()
this.description = 'Sends a message to each player target. To include numbers from Value mechanics, use the filters {} where is the key the value is stored under.'
this.data.push(new StringValue('Message', 'message', 'text')
- .setTooltip('The message to display')
+ .setTooltip('The message to display. {player} = caster\'s name, {target} = target\'s name, {targetUUID} = target\'s UUID (useful if targets are non players), &lc: "{", &rc: "}", &sq: "\'"')
);
}
diff --git a/src/main/java/com/sucy/skill/dynamic/EffectComponent.java b/src/main/java/com/sucy/skill/dynamic/EffectComponent.java
index a5148512..57a83f40 100644
--- a/src/main/java/com/sucy/skill/dynamic/EffectComponent.java
+++ b/src/main/java/com/sucy/skill/dynamic/EffectComponent.java
@@ -300,6 +300,11 @@ private static String filterSpecialChars(String string) {
builder.append('{');
i = j+3;
break;
+ case "sq":
+ builder.append(string, i, j);
+ builder.append('\'');
+ i = j+3;
+ break;
}
j = string.indexOf('&',i);
}
From e9c5dd0a2510c2e42c103cc1610781bdfc6977f1 Mon Sep 17 00:00:00 2001
From: Sentropic <60368610+Sentropic@users.noreply.github.com>
Date: Sat, 19 Dec 2020 19:57:38 -0600
Subject: [PATCH 8/8] Updated PluginChecker
Made more consistent with other listeners
---
src/main/java/com/sucy/skill/SkillAPI.java | 3 ++-
.../java/com/sucy/skill/hook/PluginChecker.java | 13 ++++---------
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/src/main/java/com/sucy/skill/SkillAPI.java b/src/main/java/com/sucy/skill/SkillAPI.java
index c5b652fc..eef0f04e 100644
--- a/src/main/java/com/sucy/skill/SkillAPI.java
+++ b/src/main/java/com/sucy/skill/SkillAPI.java
@@ -167,7 +167,8 @@ public void onEnable() {
listen(new DeathListener(), !VersionManager.isVersionAtLeast(11000));
listen(new LingeringPotionListener(), VersionManager.isVersionAtLeast(VersionManager.V1_9_0));
listen(new ExperienceListener(), settings.yieldsEnabled());
- new PluginChecker(this);
+ listen(new PluginChecker(), true);
+
// Set up tasks
if (settings.isManaEnabled()) {
diff --git a/src/main/java/com/sucy/skill/hook/PluginChecker.java b/src/main/java/com/sucy/skill/hook/PluginChecker.java
index 72789b43..77d1ff2b 100644
--- a/src/main/java/com/sucy/skill/hook/PluginChecker.java
+++ b/src/main/java/com/sucy/skill/hook/PluginChecker.java
@@ -26,10 +26,9 @@
*/
package com.sucy.skill.hook;
-import com.sucy.skill.SkillAPI;
+import com.sucy.skill.listener.SkillAPIListener;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.plugin.PluginManager;
@@ -38,9 +37,7 @@
* Handler for checking whether or not hooked plugins are present
* and active before using related code.
*/
-public class PluginChecker implements Listener {
- private static PluginChecker singleton;
-
+public class PluginChecker extends SkillAPIListener {
private static boolean vault;
private static boolean libsDisguises;
private static boolean noCheatPlus;
@@ -51,11 +48,9 @@ public class PluginChecker implements Listener {
private static boolean worldGuard;
private static boolean parties;
- public PluginChecker(SkillAPI plugin) {
- if (singleton != null) return;
- singleton = this;
+ @Override
+ public void init() {
PluginManager pluginManager = Bukkit.getPluginManager();
- pluginManager.registerEvents(this, plugin);
vault = pluginManager.isPluginEnabled("Vault") && VaultHook.isValid();
libsDisguises = pluginManager.isPluginEnabled("LibsDisguises");