mirror of
https://github.com/funkemunky/KauriV3.git
synced 2026-06-30 17:58:27 +00:00
Shit
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2018 NGXDEV.COM. Licensed under MIT.
|
||||
*/
|
||||
|
||||
package dev.brighten.ac.packet;
|
||||
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
//Protocol Version numbers: https://wiki.vg/Protocol_version_numbers
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ProtocolVersion {
|
||||
V1_7(4, "v1_7_R3"),
|
||||
V1_7_10(5, "v1_7_R4"),
|
||||
V1_8(45, "v1_8_R1"),
|
||||
V1_8_5(46, "v1_8_R2"),
|
||||
V1_8_9(47, "v1_8_R3"),
|
||||
V1_9(107, "v1_9_R1"),
|
||||
V1_9_1(108, "v1_9_R1"),
|
||||
V1_9_2(109, "v1_9_R2"),
|
||||
V1_9_4(110, "v1_9_R2"),
|
||||
V1_10(210, "v1_10_R1"),
|
||||
V1_10_2(210, "v1_10_R1"),
|
||||
V1_11(316, "v1_11_R1"),
|
||||
V1_12(335, "v1_12_R1"),
|
||||
V1_12_1(338, null),
|
||||
V1_12_2(340, "v1_12_R1"),
|
||||
V1_13(350, "v1_13_R1"),
|
||||
V1_13_1(351, "v1_13_R2"),
|
||||
V1_13_2(352, "v1_13_R2"),
|
||||
V1_14(477, "v1_14_R1"),
|
||||
V1_14_1(480, "v1_14_R1"),
|
||||
V1_14_2(485, "v1_14_R1"),
|
||||
V1_14_3(490, "v1_14_R1"),
|
||||
V1_14_4(498, "v1_14_R1"),
|
||||
V1_15(573, "v1_15_R1"),
|
||||
V1_15_1(575, "v1_15_R1"),
|
||||
V1_15_2(578, "v1_15_R1"),
|
||||
V1_16(735, "v1_16_R1"),
|
||||
V1_16_1(736, "v1_16_R1"),
|
||||
V1_16_2(751, "v1_16_R2"),
|
||||
V1_16_3(753, "v1_16_R2"),
|
||||
V1_16_4(754, "v1_16_R3"),
|
||||
V1_16_5(754, "v1_16_R3"),
|
||||
V1_17(755, "v1_17_R1"),
|
||||
V1_17_1(756, "v1_17_R1"),
|
||||
V1_18(757, "v1_18_R1"),
|
||||
V1_18_2(758, "v1_18_R2"),
|
||||
V1_19(759, "v1_19_R1"),
|
||||
|
||||
v1_19_1(760, "v1_19_R1"),
|
||||
|
||||
UNKNOWN(-1, "UNKNOWN");
|
||||
|
||||
@Getter
|
||||
private static final ProtocolVersion gameVersion = fetchGameVersion();
|
||||
private final int version;
|
||||
@Getter
|
||||
private static boolean paper;
|
||||
private final String serverVersion;
|
||||
|
||||
private static ProtocolVersion fetchGameVersion() {
|
||||
ProtocolVersion toReturn = UNKNOWN;
|
||||
for (ProtocolVersion version : values()) {
|
||||
if (version.getServerVersion() != null && version.getServerVersion().equals(Reflections.VERSION)) {
|
||||
toReturn = version;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(toReturn.isOrAbove(ProtocolVersion.V1_17)) {
|
||||
WrappedClass mv = Reflections.getNMSClass("MinecraftVersion");
|
||||
Object mvObject = mv.getFieldByName("a").get(null);
|
||||
|
||||
String version = mv.getFieldByType(String.class, 1).get(mvObject);
|
||||
|
||||
switch(version) {
|
||||
case "1.19": {
|
||||
toReturn = V1_19;
|
||||
break;
|
||||
}
|
||||
case "1.18.2": {
|
||||
toReturn = V1_18_2;
|
||||
break;
|
||||
}
|
||||
case "1.18.1":
|
||||
case "1.18": {
|
||||
toReturn = V1_18;
|
||||
Bukkit.getLogger().log(Level.INFO, "Version is 1.18");
|
||||
break;
|
||||
}
|
||||
case "1.17.1": {
|
||||
toReturn = V1_17_1;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
toReturn = V1_17;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public static ProtocolVersion getVersion(int versionId) {
|
||||
for (ProtocolVersion version : values()) {
|
||||
if (version.getVersion() == versionId) return version;
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public boolean isBelow(ProtocolVersion version) {
|
||||
return this.getVersion() < version.getVersion();
|
||||
}
|
||||
|
||||
public boolean isOrBelow(ProtocolVersion version) {
|
||||
return this.getVersion() <= version.getVersion();
|
||||
}
|
||||
|
||||
public boolean isAbove(ProtocolVersion version) {
|
||||
return this.getVersion() > version.getVersion();
|
||||
}
|
||||
|
||||
public boolean isOrAbove(ProtocolVersion version) {
|
||||
return this.getVersion() >= version.getVersion();
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
Class.forName("org.github.paperspigot.PaperSpigotConfig");
|
||||
paper = true;
|
||||
} catch(Exception e) {
|
||||
paper = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
public class FastTrig
|
||||
{
|
||||
/** Fast approximation of 1.0 / sqrt(x).
|
||||
* See <a href="http://www.beyond3d.com/content/articles/8/">http://www.beyond3d.com/content/articles/8/</a>
|
||||
* @param x Positive value to estimate inverse of square root of
|
||||
* @return Approximately 1.0 / sqrt(x)
|
||||
**/
|
||||
public static double
|
||||
invSqrt(double x)
|
||||
{
|
||||
double xhalf = 0.5 * x;
|
||||
long i = Double.doubleToRawLongBits(x);
|
||||
i = 0x5FE6EB50C7B537AAL - (i>>1);
|
||||
x = Double.longBitsToDouble(i);
|
||||
x = x * (1.5 - xhalf*x*x);
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Approximation of arctangent.
|
||||
* Slightly faster and substantially less accurate than
|
||||
* {@link Math#atan2(double, double)}.
|
||||
**/
|
||||
public static double fast_atan2(double y, double x)
|
||||
{
|
||||
double d2 = x*x + y*y;
|
||||
|
||||
// Bail out if d2 is NaN, zero or subnormal
|
||||
if (Double.isNaN(d2) ||
|
||||
(Double.doubleToRawLongBits(d2) < 0x10000000000000L))
|
||||
{
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
// Normalise such that 0.0 <= y <= x
|
||||
boolean negY = y < 0.0;
|
||||
if (negY) {y = -y;}
|
||||
boolean negX = x < 0.0;
|
||||
if (negX) {x = -x;}
|
||||
boolean steep = y > x;
|
||||
if (steep)
|
||||
{
|
||||
double t = x;
|
||||
x = y;
|
||||
y = t;
|
||||
}
|
||||
|
||||
// Scale to unit circle (0.0 <= y <= x <= 1.0)
|
||||
double rinv = invSqrt(d2); // rinv ≅ 1.0 / hypot(x, y)
|
||||
x *= rinv; // x ≅ cos θ
|
||||
y *= rinv; // y ≅ sin θ, hence θ ≅ asin y
|
||||
|
||||
// Hack: we want: ind = floor(y * 256)
|
||||
// We deliberately force truncation by adding floating-point numbers whose
|
||||
// exponents differ greatly. The FPU will right-shift y to match exponents,
|
||||
// dropping all but the first 9 significant bits, which become the 9 LSBs
|
||||
// of the resulting mantissa.
|
||||
// Inspired by a similar piece of C code at
|
||||
// http://www.shellandslate.com/computermath101.html
|
||||
double yp = FRAC_BIAS + y;
|
||||
int ind = (int) Double.doubleToRawLongBits(yp);
|
||||
|
||||
// Find φ (a first approximation of θ) from the LUT
|
||||
double φ = ASIN_TAB[ind];
|
||||
double cφ = COS_TAB[ind]; // cos(φ)
|
||||
|
||||
// sin(φ) == ind / 256.0
|
||||
// Note that sφ is truncated, hence not identical to y.
|
||||
double sφ = yp - FRAC_BIAS;
|
||||
double sd = y * cφ - x * sφ; // sin(θ-φ) ≡ sinθ cosφ - cosθ sinφ
|
||||
|
||||
// asin(sd) ≅ sd + ⅙sd³ (from first 2 terms of Maclaurin series)
|
||||
double d = (6.0 + sd * sd) * sd * ONE_SIXTH;
|
||||
double θ = φ + d;
|
||||
|
||||
// Translate back to correct octant
|
||||
if (steep) { θ = Math.PI * 0.5 - θ; }
|
||||
if (negX) { θ = Math.PI - θ; }
|
||||
if (negY) { θ = -θ; }
|
||||
|
||||
return θ;
|
||||
}
|
||||
|
||||
private static final double ONE_SIXTH = 1.0 / 6.0;
|
||||
private static final int FRAC_EXP = 8; // LUT precision == 2 ** -8 == 1/256
|
||||
private static final int LUT_SIZE = (1 << FRAC_EXP) + 1;
|
||||
private static final double FRAC_BIAS =
|
||||
Double.longBitsToDouble((0x433L - FRAC_EXP) << 52);
|
||||
private static final double[] ASIN_TAB = new double[LUT_SIZE];
|
||||
private static final double[] COS_TAB = new double[LUT_SIZE];
|
||||
|
||||
static
|
||||
{
|
||||
/* Populate trig tables */
|
||||
for (int ind = 0; ind < LUT_SIZE; ++ ind)
|
||||
{
|
||||
double v = ind / (double) (1 << FRAC_EXP);
|
||||
double asinv = Math.asin(v);
|
||||
COS_TAB[ind] = Math.cos(asinv);
|
||||
ASIN_TAB[ind] = asinv;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class KLocation implements Cloneable {
|
||||
public double x, y, z;
|
||||
public float yaw, pitch;
|
||||
public long timeStamp;
|
||||
|
||||
public KLocation(double x, double y, double z, float yaw, float pitch, long timeStamp) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.timeStamp = timeStamp;
|
||||
}
|
||||
|
||||
public KLocation(double x, double y, double z, float yaw, float pitch) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.timeStamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public KLocation(double x, double y, double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
|
||||
this.timeStamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public KLocation(Vector vector) {
|
||||
this.x = vector.getX();
|
||||
this.y = vector.getY();
|
||||
this.z = vector.getZ();
|
||||
this.timeStamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public KLocation(Location location) {
|
||||
this.x = location.getX();
|
||||
this.y = location.getY();
|
||||
this.z = location.getZ();
|
||||
this.yaw = location.getYaw();
|
||||
this.pitch = location.getPitch();
|
||||
this.timeStamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public Vector toVector() {
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
public Location toLocation(World world) {
|
||||
return new Location(world, x, y, z, yaw, pitch);
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@Override
|
||||
public KLocation clone() {
|
||||
return new KLocation(x, y, z, yaw, pitch, timeStamp);
|
||||
}
|
||||
|
||||
public double distanceSquared(KLocation other) {
|
||||
double dx = (x - other.x), dy = (y - other.y), dz = (z - other.z);
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
public double distance(KLocation other) {
|
||||
return Math.sqrt(distanceSquared(other));
|
||||
}
|
||||
|
||||
public KLocation add(double x, double y, double z) {
|
||||
this.x+= x;
|
||||
this.y+= y;
|
||||
this.z+= z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public KLocation subtract(double x, double y, double z) {
|
||||
this.x-= x;
|
||||
this.y-= y;
|
||||
this.z-= z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public KLocation setLocation(KLocation loc) {
|
||||
this.x = loc.x;
|
||||
this.y = loc.y;
|
||||
this.z = loc.z;
|
||||
this.yaw = loc.yaw;
|
||||
this.pitch = loc.pitch;
|
||||
this.timeStamp = loc.timeStamp;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector getDirection() {
|
||||
return MathUtils.getDirection(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
KLocation kLocation = (KLocation) o;
|
||||
return Double.compare(kLocation.x, x) == 0 && Double.compare(kLocation.y, y) == 0 && Double.compare(kLocation.z, z) == 0 && Float.compare(kLocation.yaw, yaw) == 0 && Float.compare(kLocation.pitch, pitch) == 0 && timeStamp == kLocation.timeStamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(x, y, z, yaw, pitch, timeStamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KLocation{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", z=" + z +
|
||||
", yaw=" + yaw +
|
||||
", pitch=" + pitch +
|
||||
", timeStamp=" + timeStamp +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,930 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import lombok.val;
|
||||
import me.hydro.emulator.util.mcp.MathHelper;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
//
|
||||
@SuppressWarnings("unused")
|
||||
public class MathUtils {
|
||||
|
||||
public static double GROUND_DIVISOR = 0.015625;
|
||||
|
||||
public static double offset(Vector from, Vector to) {
|
||||
from.setY(0);
|
||||
to.setY(0);
|
||||
|
||||
return to.subtract(from).length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Average
|
||||
*
|
||||
* @return double
|
||||
*/
|
||||
public static double getAverage(List<Double> list) {
|
||||
double sum = 0;
|
||||
for (double d : list) {
|
||||
sum += d;
|
||||
}
|
||||
return sum / list.size();
|
||||
}
|
||||
|
||||
public static double getAverage(double[] list) {
|
||||
double sum = 0;
|
||||
for (double d : list) {
|
||||
sum += d;
|
||||
}
|
||||
return sum / list.length;
|
||||
}
|
||||
|
||||
public static double getAverage(int[] list) {
|
||||
double sum = 0;
|
||||
for (double d : list) {
|
||||
sum += d;
|
||||
}
|
||||
return sum / list.length;
|
||||
}
|
||||
|
||||
public static float getAverage(float[] list) {
|
||||
float sum = 0;
|
||||
for (float d : list) {
|
||||
sum += d;
|
||||
}
|
||||
return sum / list.length;
|
||||
}
|
||||
|
||||
public static int angularDistance(double alpha, double beta) {
|
||||
while (alpha < 0) alpha += 360;
|
||||
while (beta < 0) beta += 360;
|
||||
double phi = Math.abs(beta - alpha) % 360;
|
||||
return (int) (phi > 180 ? 360 - phi : phi);
|
||||
}
|
||||
public static boolean playerMoved(Location from, Location to) {
|
||||
return playerMoved(from.toVector(), to.toVector());
|
||||
}
|
||||
|
||||
public static float gcdSmall(float current, float previous) {
|
||||
if(current < previous) return gcdSmall(Math.abs(previous), Math.abs(current));
|
||||
//The larger number has to be first.
|
||||
return (Math.abs(previous) <= 0.001f) ? current : gcdSmall(previous,
|
||||
current - (float)Math.floor(current / previous) * previous);
|
||||
}
|
||||
|
||||
public static double lerp(double lerpAmount, double start, double end) {
|
||||
return start + lerpAmount * (end - start);
|
||||
}
|
||||
|
||||
public static boolean isScientificNotation(double value) {
|
||||
return String.valueOf(value).contains("E");
|
||||
}
|
||||
|
||||
public static double getDistanceWithoutRoot(KLocation one, KLocation two) {
|
||||
double deltaX = one.x - two.x, deltaY = one.y - two.y, deltaZ = one.z - two.z;
|
||||
|
||||
return (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ);
|
||||
}
|
||||
|
||||
public static boolean isSameLocation(KLocation one, KLocation two) {
|
||||
return one.x == two.x && one.y == two.y && one.z == two.z;
|
||||
}
|
||||
|
||||
|
||||
public static double max(double... values) {
|
||||
return Arrays.stream(values).max().orElse(Double.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static boolean isInteger(String string) {
|
||||
try {
|
||||
Integer.parseInt(string);
|
||||
return true;
|
||||
} catch(NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static int length(double value) {
|
||||
return String.valueOf(value).length();
|
||||
}
|
||||
|
||||
public static double getGrid(final Collection<Float> entry) {
|
||||
double average = 0.0;
|
||||
double min = 0.0, max = 0.0;
|
||||
|
||||
for (final double number : entry) {
|
||||
if (number < min) min = number;
|
||||
if (number > max) max = number;
|
||||
average += number;
|
||||
}
|
||||
|
||||
average /= entry.size();
|
||||
|
||||
return (max - average) - min;
|
||||
}
|
||||
|
||||
public static double getGrid(final float[] entry) {
|
||||
double average = 0.0;
|
||||
double min = 0.0, max = 0.0;
|
||||
|
||||
for (final double number : entry) {
|
||||
if (number < min) min = number;
|
||||
if (number > max) max = number;
|
||||
average += number;
|
||||
}
|
||||
|
||||
average /= entry.length;
|
||||
|
||||
return (max - average) - min;
|
||||
}
|
||||
|
||||
//Skidded from Luke.
|
||||
public static double getAngle(Location loc1, Location loc2) {
|
||||
if (loc1 == null || loc2 == null) return -1;
|
||||
Vector playerRotation = new Vector(loc1.getYaw(), loc1.getPitch(), 0.0f);
|
||||
loc1.setY(0);
|
||||
loc2.setY(0);
|
||||
val rot = MathUtils.getRotation(loc1, loc2);
|
||||
Vector expectedRotation = new Vector(rot[0], rot[1], 0);
|
||||
return MathUtils.yawTo180D(playerRotation.getX() - expectedRotation.getX());
|
||||
}
|
||||
|
||||
public static double getAngle(KLocation loc1, KLocation loc2) {
|
||||
return getAngle(loc1.toLocation(null), loc2.toLocation(null));
|
||||
}
|
||||
|
||||
public static float distanceBetweenAngles(float a, float b) {
|
||||
final float first = a % 360;
|
||||
final float second = b % 360;
|
||||
|
||||
final float delta = Math.abs(first - second);
|
||||
|
||||
return (float) Math.abs(Math.min(360.0 - delta, delta));
|
||||
}
|
||||
|
||||
public static float getDistanceBetweenAngles(final float angle1, final float angle2) {
|
||||
float distance = Math.abs(angle1 - angle2) % 360.0f;
|
||||
if (distance > 180.0f) {
|
||||
distance = 360.0f - distance;
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
//Args: Tuple (a) is low outliers, Tupe (B) is high outliers
|
||||
public static Tuple<List<Double>, List<Double>> getOutliers(List<Double> values) {
|
||||
|
||||
if(values.size() < 4) return new Tuple<>(new ArrayList<>(), new ArrayList<>());
|
||||
|
||||
double q1 = getMedianFloat(values.subList(0, values.size() / 2)),
|
||||
q3 = getMedianFloat(values.subList(values.size() / 2, values.size()));
|
||||
double iqr = Math.abs(q1 - q3);
|
||||
|
||||
double lowThreshold = q1 - 1.5 * iqr, highThreshold = q3 + 1.5 * iqr;
|
||||
|
||||
val tuple = new Tuple<List<Double>, List<Double>>(new ArrayList<>(), new ArrayList<>());
|
||||
|
||||
for (Double value : values) {
|
||||
if(value < lowThreshold) tuple.one.add(value);
|
||||
if(value < lowThreshold) tuple.one.add(value);
|
||||
else if(value > highThreshold) tuple.two.add(value);
|
||||
}
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
public static Tuple<List<Float>, List<Float>> getOutliersFloat(List<Float> values) {
|
||||
if(values.size() < 4) return new Tuple<>(new ArrayList<>(), new ArrayList<>());
|
||||
|
||||
double q1 = MathUtils.getMedianFloat(values.subList(0, values.size() / 2)),
|
||||
q3 = MathUtils.getMedianFloat(values.subList(values.size() / 2, values.size()));
|
||||
double iqr = Math.abs(q1 - q3);
|
||||
|
||||
double lowThreshold = q1 - 1.5 * iqr, highThreshold = q3 + 1.5 * iqr;
|
||||
|
||||
val tuple = new Tuple<List<Float>, List<Float>>(new ArrayList<>(), new ArrayList<>());
|
||||
|
||||
for (Float value : values) {
|
||||
if(value < lowThreshold) tuple.one.add(value);
|
||||
else if(value > highThreshold) tuple.two.add(value);
|
||||
}
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
public static Tuple<List<Long>, List<Long>> getOutliersLong(List<Long> collection) {
|
||||
List<Long> values = new ArrayList<>(collection);
|
||||
|
||||
if(values.size() < 4) return new Tuple<>(new ArrayList<>(), new ArrayList<>());
|
||||
|
||||
double q1 = getMedianFloat(values.subList(0, values.size() / 2)),
|
||||
q3 = getMedianFloat(values.subList(values.size() / 2, values.size()));
|
||||
double iqr = Math.abs(q1 - q3);
|
||||
|
||||
double lowThreshold = q1 - 1.5 * iqr, highThreshold = q3 + 1.5 * iqr;
|
||||
|
||||
val tuple = new Tuple<List<Long>, List<Long>>(new ArrayList<>(), new ArrayList<>());
|
||||
|
||||
for (Long value : values) {
|
||||
if(value < lowThreshold) tuple.one.add(value);
|
||||
else if(value > highThreshold) tuple.two.add(value);
|
||||
}
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
public static double getMedian(List<Double> data) {
|
||||
return calculateDoubleMedian(data);
|
||||
}
|
||||
|
||||
public static float getMedianFloat(List<Float> data) {
|
||||
if(data.size() > 1) {
|
||||
if (data.size() % 2 == 0)
|
||||
return (data.get(data.size() / 2) + data.get(data.size() / 2 - 1)) / 2;
|
||||
else
|
||||
return data.get(Math.round(data.size() / 2f));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static double getMedianFloat(Iterable<? extends Number> iterable) {
|
||||
List<Double> data = new ArrayList<>();
|
||||
|
||||
for (Number number : iterable) {
|
||||
data.add(number.doubleValue());
|
||||
}
|
||||
|
||||
return calculateDoubleMedian(data);
|
||||
}
|
||||
|
||||
private static double calculateDoubleMedian(List<Double> data) {
|
||||
if(data.size() > 1) {
|
||||
if (data.size() % 2 == 0)
|
||||
return (data.get(data.size() / 2) + data.get(data.size() / 2 - 1)) / 2;
|
||||
else
|
||||
return data.get(Math.round(data.size() / 2f));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Copied from apache math Kurtosis class.
|
||||
public static double getKurtosisApache(Iterable<? extends Number> iterable) {
|
||||
List<Double> values = new ArrayList<>();
|
||||
|
||||
double total = 0;
|
||||
double kurt = Double.NaN;
|
||||
for (Number number : iterable) {
|
||||
double v = number.doubleValue();
|
||||
total+= v;
|
||||
values.add(v);
|
||||
}
|
||||
|
||||
if(values.size() < 2) return kurt;
|
||||
|
||||
double mean = total / values.size();
|
||||
double stdDev = MathUtils.stdev(values);
|
||||
double accum3 = 0.0D;
|
||||
|
||||
for (Double value : values) {
|
||||
accum3 += Math.pow(value - mean, 4.0D);
|
||||
}
|
||||
|
||||
accum3 /= Math.pow(stdDev, 4.0D);
|
||||
double n0 = values.size();
|
||||
double coefficientOne = n0 * (n0 + 1.0D) / ((n0 - 1.0D) * (n0 - 2.0D) * (n0 - 3.0D));
|
||||
double termTwo = 3.0D * Math.pow(n0 - 1.0D, 2.0D) / ((n0 - 2.0D) * (n0 - 3.0D));
|
||||
kurt = coefficientOne * accum3 - termTwo;
|
||||
|
||||
return kurt;
|
||||
}
|
||||
|
||||
public static double getKurtosis(final Iterable<? extends Number> iterable) {
|
||||
double n = 0.0;
|
||||
double n2 = 0.0;
|
||||
|
||||
for (Number number : iterable) {
|
||||
n += number.doubleValue();
|
||||
++n2;
|
||||
}
|
||||
|
||||
if (n2 < 3.0) {
|
||||
return 0.0;
|
||||
}
|
||||
final double n3 = n2 * (n2 + 1.0) / ((n2 - 1.0) * (n2 - 2.0) * (n2 - 3.0));
|
||||
final double n4 = 3.0 * Math.pow(n2 - 1.0, 2.0) / ((n2 - 2.0) * (n2 - 3.0));
|
||||
final double n5 = n / n2;
|
||||
double n6 = 0.0;
|
||||
double n7 = 0.0;
|
||||
for (final Number n8 : iterable) {
|
||||
n6 += Math.pow(n5 - n8.doubleValue(), 2.0);
|
||||
n7 += Math.pow(n5 - n8.doubleValue(), 4.0);
|
||||
}
|
||||
return n3 * (n7 / Math.pow(n6 / n2, 2.0)) - n4;
|
||||
}
|
||||
|
||||
public static float pow(float number, int times) {
|
||||
float answer = number;
|
||||
|
||||
if(times <= 0) return 0;
|
||||
|
||||
for(int i = 1 ; i < times ; i++) {
|
||||
answer*= number;
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
public static double varianceSquared(final Number n, final Iterable<? extends Number> iterable) {
|
||||
double n2 = 0.0;
|
||||
int n3 = 0;
|
||||
|
||||
for (Number number : iterable) {
|
||||
n2 += Math.pow((number).doubleValue() - n.doubleValue(), 2.0);
|
||||
++n3;
|
||||
}
|
||||
|
||||
return (n2 == 0.0) ? 0.0 : (n2 / (n3 - 1));
|
||||
}
|
||||
|
||||
public static List<Double> getModes(final Iterable<? extends Number> iterable) {
|
||||
List<Double> numbers = new ArrayList<>();
|
||||
|
||||
for (Number number : iterable) {
|
||||
numbers.add(number.doubleValue());
|
||||
}
|
||||
final Map<Double, Long> countFrequencies = numbers.stream()
|
||||
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
|
||||
|
||||
final double maxFrequency = countFrequencies.values().stream()
|
||||
.mapToDouble(count -> count)
|
||||
.max().orElse(-1);
|
||||
|
||||
return countFrequencies.entrySet().stream()
|
||||
.filter(tuple -> tuple.getValue() == maxFrequency)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
//Copied from apache math Skewness class.
|
||||
public static double getSkewnessApache(Iterable<? extends Number> iterable) {
|
||||
List<Double> values = new ArrayList<>();
|
||||
|
||||
double total = 0;
|
||||
double skew = Double.NaN;
|
||||
for (Number number : iterable) {
|
||||
double v = number.doubleValue();
|
||||
total+= v;
|
||||
values.add(v);
|
||||
}
|
||||
|
||||
if(values.size() < 2) return skew;
|
||||
|
||||
double m = total / values.size();
|
||||
double accum = 0.0D;
|
||||
double accum2 = 0.0D;
|
||||
|
||||
for (Double value : values) {
|
||||
double d = value - m;
|
||||
accum += d * d;
|
||||
accum2 += d;
|
||||
}
|
||||
|
||||
double variance = (accum - accum2 * accum2 / values.size()) / (values.size() - 1);
|
||||
double accum3 = 0.0D;
|
||||
|
||||
for (Double value : values) {
|
||||
double d = value - m;
|
||||
accum3 += d * d * d;
|
||||
}
|
||||
|
||||
accum3 /= variance * Math.sqrt(variance);
|
||||
double n0 = values.size();
|
||||
skew = n0 / ((n0 - 1.0D) * (n0 - 2.0D)) * accum3;
|
||||
|
||||
return skew;
|
||||
}
|
||||
|
||||
public static double getSkewness(final Iterable<? extends Number> iterable) {
|
||||
double sum = 0;
|
||||
int buffer = 0;
|
||||
|
||||
final List<Double> numberList = new ArrayList<>();
|
||||
|
||||
for (Number num : iterable) {
|
||||
sum += num.doubleValue();
|
||||
buffer++;
|
||||
|
||||
numberList.add(num.doubleValue());
|
||||
}
|
||||
|
||||
Collections.sort(numberList);
|
||||
|
||||
final double mean = sum / buffer;
|
||||
final double median = (buffer % 2 != 0) ? numberList.get(buffer / 2) : (numberList.get((buffer - 1) / 2) + numberList.get(buffer / 2)) / 2;
|
||||
|
||||
return 3 * (mean - median) / deviationSquared(iterable);
|
||||
}
|
||||
|
||||
public static double stdev(final Iterable<? extends Number> iterable) {
|
||||
double sum = 0.0f;
|
||||
double num = 0.0f;
|
||||
|
||||
final List<Double> list = new ArrayList<>();
|
||||
|
||||
for (Number number : iterable) {
|
||||
list.add(number.doubleValue());
|
||||
}
|
||||
|
||||
for (Double v : list) {
|
||||
sum+= v;
|
||||
}
|
||||
|
||||
double mean = sum / (float)list.size();
|
||||
|
||||
for (Double v : list) {
|
||||
num+= Math.pow(v - mean, 2.0D);
|
||||
}
|
||||
|
||||
return MathHelper.sqrt_double(num / (double)list.size());
|
||||
}
|
||||
|
||||
public static double deviationSquared(final Iterable<? extends Number> iterable) {
|
||||
double n = 0.0;
|
||||
int n2 = 0;
|
||||
|
||||
for (Number anIterable : iterable) {
|
||||
n += (anIterable).doubleValue();
|
||||
++n2;
|
||||
}
|
||||
final double n3 = n / n2;
|
||||
double n4 = 0.0;
|
||||
|
||||
for (Number anIterable : iterable) {
|
||||
n4 += Math.pow(anIterable.doubleValue() - n3, 2.0);
|
||||
}
|
||||
|
||||
return (n4 == 0.0) ? 0.0 : (n4 / (n2 - 1));
|
||||
}
|
||||
|
||||
public static int getDecimalCount(float number) {
|
||||
return String.valueOf(number).split("\\.")[1].length();
|
||||
}
|
||||
|
||||
public static int getDecimalCount(double number) {
|
||||
return String.valueOf(number).split("\\.")[1].length();
|
||||
}
|
||||
|
||||
public static float clampToVanilla(float s, float angle) {
|
||||
float f = (s * 0.6f + .2f);
|
||||
float f2 = f * f * f * 1.2f;
|
||||
return angle - (angle % f2);
|
||||
}
|
||||
|
||||
public static byte getByte(int num) {
|
||||
if(num > Byte.MAX_VALUE || num < Byte.MIN_VALUE) {
|
||||
throw new NumberFormatException("Integer " + num + " too large to cast to data format byte!"
|
||||
+ " (max=" + Byte.MAX_VALUE + " min=" + Byte.MIN_VALUE + ")");
|
||||
}
|
||||
|
||||
return (byte) num;
|
||||
}
|
||||
|
||||
public static short getShort(int num) {
|
||||
if(num > Short.MAX_VALUE || num < Short.MIN_VALUE) {
|
||||
throw new NumberFormatException("Integer " + num + " too large to cast to data format short!"
|
||||
+ " (max=" + Short.MAX_VALUE + " min=" + Short.MIN_VALUE + ")");
|
||||
}
|
||||
return (short) num;
|
||||
}
|
||||
|
||||
/* Stolen from Bukkit */
|
||||
public static Vector getDirection(KLocation loc) {
|
||||
Vector vector = new Vector();
|
||||
double rotX = loc.yaw;
|
||||
double rotY = loc.pitch;
|
||||
vector.setY(-Math.sin(Math.toRadians(rotY)));
|
||||
double xz = Math.cos(Math.toRadians(rotY));
|
||||
vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
|
||||
vector.setZ(xz * Math.cos(Math.toRadians(rotX)));
|
||||
return vector;
|
||||
}
|
||||
|
||||
|
||||
public static boolean approxEquals(double accuracy, double equalTo, double... equals) {
|
||||
return Arrays.stream(equals).allMatch(equal -> MathUtils.getDelta(equalTo, equal) < accuracy);
|
||||
}
|
||||
|
||||
public static boolean approxEquals(double accuracy, int equalTo, int... equals) {
|
||||
return Arrays.stream(equals).allMatch(equal -> MathUtils.getDelta(equalTo, equal) < accuracy);
|
||||
}
|
||||
|
||||
public static boolean approxEquals(double accuracy, long equalTo, long... equals) {
|
||||
return Arrays.stream(equals).allMatch(equal -> MathUtils.getDelta(equalTo, equal) < accuracy);
|
||||
}
|
||||
|
||||
//Returns -1 if fails.
|
||||
public static Number tryParse(String string) {
|
||||
try {
|
||||
return Double.parseDouble(string);
|
||||
} catch(NumberFormatException exception) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
//A lighter version of the Java hypotenuse function.
|
||||
public static double hypot(double... value) {
|
||||
double total = 0;
|
||||
|
||||
for (double val : value) {
|
||||
total += (val * val);
|
||||
}
|
||||
|
||||
return Math.sqrt(total);
|
||||
}
|
||||
|
||||
public static float hypot(float... value) {
|
||||
float total = 0;
|
||||
|
||||
for (float val : value) {
|
||||
total += (val * val);
|
||||
}
|
||||
|
||||
return (float) Math.sqrt(total);
|
||||
}
|
||||
|
||||
public static double hypotSqrt(double left, double right) {
|
||||
return (left * left) + (right * right);
|
||||
}
|
||||
|
||||
public static float hypotSqrt(float left, float right) {
|
||||
return (left * left) + (right * right);
|
||||
}
|
||||
|
||||
public static double get3DDistance(Vector one, Vector two) {
|
||||
return hypot(one.getX() - two.getX(), one.getY() - two.getY(), one.getZ() - two.getZ());
|
||||
}
|
||||
|
||||
public static boolean playerMoved(Vector from, Vector to) {
|
||||
return from.distance(to) > 0;
|
||||
}
|
||||
|
||||
public static boolean playerLooked(Location from, Location to) {
|
||||
return (from.getYaw() - to.getYaw() != 0) || (from.getPitch() - to.getPitch() != 0);
|
||||
}
|
||||
public static boolean elapsed(long time, long needed) {
|
||||
return Math.abs(System.currentTimeMillis() - time) >= needed;
|
||||
}
|
||||
|
||||
//Euclid's algorithim
|
||||
public static long gcd(long a, long b)
|
||||
{
|
||||
while (b > 0)
|
||||
{
|
||||
long temp = b;
|
||||
b = a % b; // % is remainder
|
||||
a = temp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
//Euclid's algorithim
|
||||
public static long gcd(long... input)
|
||||
{
|
||||
long result = input[0];
|
||||
for(int i = 1; i < input.length; i++) result = gcd(result, input[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns the absolute value of n-mid*mid*mid
|
||||
static double diff(double n,double mid)
|
||||
{
|
||||
if (n > (mid*mid*mid))
|
||||
return (n-(mid*mid*mid));
|
||||
else
|
||||
return ((mid*mid*mid) - n);
|
||||
}
|
||||
|
||||
// Returns cube root of a no n
|
||||
public static double cbrt(double n)
|
||||
{
|
||||
// Set start and end for binary search
|
||||
double start = 0, end = n;
|
||||
|
||||
// Set precision
|
||||
double e = 0.0000001;
|
||||
|
||||
double mid = -1;
|
||||
double error = 1000;
|
||||
|
||||
long ticks = 0;
|
||||
while (error > e)
|
||||
{
|
||||
mid = (start + end)/2;
|
||||
error = diff(n, mid);
|
||||
|
||||
// If error is less than e then mid is
|
||||
// our answer so return mid
|
||||
|
||||
// If mid*mid*mid is greater than n set
|
||||
// end = mid
|
||||
if ((mid*mid*mid) > n)
|
||||
end = mid;
|
||||
|
||||
// If mid*mid*mid is less than n set
|
||||
// start = mid
|
||||
else
|
||||
start = mid;
|
||||
|
||||
if(error > e && ticks++ > 3E4) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return mid;
|
||||
}
|
||||
|
||||
//A much lighter but very slightly less accurate Math.sqrt.
|
||||
@Deprecated
|
||||
public static double sqrt(double number) {
|
||||
if(number == 0) return 0;
|
||||
double t;
|
||||
double squareRoot = number / 2;
|
||||
|
||||
do {
|
||||
t = squareRoot;
|
||||
squareRoot = (t + (number / t)) / 2;
|
||||
} while ((t - squareRoot) != 0);
|
||||
|
||||
return squareRoot;
|
||||
}
|
||||
|
||||
public static Vector getDirection(float yaw, float pitch) {
|
||||
float f = MathHelper.cos(MathHelper.FastMathType.VANILLA, -yaw * 0.017453292F - (float)Math.PI);
|
||||
float f1 = MathHelper.sin(MathHelper.FastMathType.VANILLA, -yaw * 0.017453292F - (float)Math.PI);
|
||||
float f2 = -MathHelper.cos(MathHelper.FastMathType.VANILLA, -pitch * 0.017453292F);
|
||||
float f3 = MathHelper.sin(MathHelper.FastMathType.VANILLA, -pitch * 0.017453292F);
|
||||
return new Vector(f1 * f2, f3, f * f2);
|
||||
}
|
||||
|
||||
public static float sqrt(float number) {
|
||||
if(number == 0) return 0;
|
||||
float t;
|
||||
|
||||
float squareRoot = number / 2;
|
||||
|
||||
do {
|
||||
t = squareRoot;
|
||||
squareRoot = (t + (number / t)) / 2;
|
||||
} while ((t - squareRoot) != 0);
|
||||
|
||||
return squareRoot;
|
||||
}
|
||||
|
||||
public static float normalizeAngle(float yaw) {
|
||||
return yaw % 360;
|
||||
}
|
||||
|
||||
public static double normalizeAngle(double yaw) {
|
||||
return yaw % 360;
|
||||
}
|
||||
|
||||
public static float getAngleDelta(float one, float two) {
|
||||
float delta = getDelta(one, two) % 360f;
|
||||
|
||||
if(delta > 180) delta = 360 - delta;
|
||||
return delta;
|
||||
}
|
||||
|
||||
//Euclid's algorithim
|
||||
public static long lcm(long a, long b)
|
||||
{
|
||||
return a * (b / gcd(a, b));
|
||||
}
|
||||
|
||||
//Euclid's algorithim
|
||||
public static long lcm(long... input)
|
||||
{
|
||||
long result = input[0];
|
||||
for(int i = 1; i < input.length; i++) result = lcm(result, input[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static float getDelta(float one, float two) {
|
||||
return Math.abs(one - two);
|
||||
}
|
||||
|
||||
public static double getDelta(double one, double two) {
|
||||
return Math.abs(one - two);
|
||||
}
|
||||
|
||||
public static long getDelta(long one, long two) {
|
||||
return Math.abs(one - two);
|
||||
}
|
||||
|
||||
public static long getDelta(int one, int two) {
|
||||
return Math.abs(one - two);
|
||||
}
|
||||
|
||||
public static long elapsed(long time) {
|
||||
return Math.abs(System.currentTimeMillis() - time);
|
||||
}
|
||||
|
||||
public static double getHorizontalDistance(Location from, Location to) {
|
||||
double deltaX = to.getX() - from.getX(), deltaZ = to.getZ() - from.getZ();
|
||||
return Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);
|
||||
}
|
||||
|
||||
public static double stdev(Collection<Double> list) {
|
||||
double sum = 0.0;
|
||||
double mean;
|
||||
double num = 0.0;
|
||||
double numi;
|
||||
double deno = 0.0;
|
||||
|
||||
for (double i : list) {
|
||||
sum += i;
|
||||
}
|
||||
mean = sum / list.size();
|
||||
|
||||
for (double i : list) {
|
||||
numi = Math.pow(i - mean, 2);
|
||||
num += numi;
|
||||
}
|
||||
|
||||
return Math.sqrt(num / list.size());
|
||||
}
|
||||
|
||||
public static int millisToTicks(long millis) {
|
||||
return (int) Math.ceil(millis / 50D);
|
||||
}
|
||||
|
||||
public static double getVerticalDistance(Location from, Location to) {
|
||||
return Math.abs(from.getY() - to.getY());
|
||||
}
|
||||
|
||||
public static double trim(int degree, double d) {
|
||||
DecimalFormat twoDForm = new DecimalFormat("#.#" + "#".repeat(Math.max(0, degree - 1)));
|
||||
return Double.parseDouble(twoDForm.format(d).replaceAll(",", "."));
|
||||
}
|
||||
|
||||
public static float trimFloat(int degree, float d) {
|
||||
DecimalFormat twoDForm = new DecimalFormat("#.#" + "#".repeat(Math.max(0, degree - 1)));
|
||||
return Float.parseFloat(twoDForm.format(d).replaceAll(",", "."));
|
||||
}
|
||||
|
||||
public static double getYawDifference(Location one, Location two) {
|
||||
return Math.abs(one.getYaw() - two.getYaw());
|
||||
}
|
||||
|
||||
public static double round(double value, int places) {
|
||||
if (places < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if(Double.isNaN(value) || Double.isInfinite(value)) return value;
|
||||
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(places, RoundingMode.HALF_UP);
|
||||
return bd.doubleValue();
|
||||
}
|
||||
|
||||
//May not be the best on performance. Let me know if you have a better way to calculate mode.
|
||||
public static <T extends Number> T getMode(Collection<T> collect) {
|
||||
Map<T, Integer> repeated = new HashMap<>();
|
||||
|
||||
//Sorting each value by how to repeat into a map.
|
||||
collect.forEach(val -> {
|
||||
int number = repeated.getOrDefault(val, 0);
|
||||
|
||||
repeated.put(val, number + 1);
|
||||
});
|
||||
|
||||
//Calculating the largest value to the key, which would be the mode.
|
||||
return repeated.keySet().stream()
|
||||
.map(key -> new Tuple<>(key, repeated.get(key))) //We map it into a Tuple for easier sorting.
|
||||
.max(Comparator.comparing(tup -> tup.two, Comparator.naturalOrder()))
|
||||
.orElseThrow(NullPointerException::new).one;
|
||||
}
|
||||
|
||||
public static double round(double value, int places, RoundingMode mode) {
|
||||
if (places < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(places, mode);
|
||||
return bd.doubleValue();
|
||||
}
|
||||
|
||||
public static double round(double value) {
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(0, RoundingMode.UP);
|
||||
return bd.doubleValue();
|
||||
}
|
||||
|
||||
public static float round(float value, int places) {
|
||||
if (places < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(places, RoundingMode.HALF_UP);
|
||||
return bd.floatValue();
|
||||
}
|
||||
|
||||
public static float round(float value, int places, RoundingMode mode) {
|
||||
if (places < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(places, mode);
|
||||
return bd.floatValue();
|
||||
}
|
||||
|
||||
public static float round(float value) {
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(0, RoundingMode.UP);
|
||||
return bd.floatValue();
|
||||
}
|
||||
|
||||
public static int floor(double var0) {
|
||||
int var2 = (int) var0;
|
||||
return var0 < var2 ? var2 - 1 : var2;
|
||||
}
|
||||
|
||||
public static float yawTo180F(float flub) {
|
||||
if ((flub %= 360.0f) >= 180.0f) {
|
||||
flub -= 360.0f;
|
||||
}
|
||||
if (flub < -180.0f) {
|
||||
flub += 360.0f;
|
||||
}
|
||||
return flub;
|
||||
}
|
||||
|
||||
public static double yawTo180D(double dub) {
|
||||
if ((dub %= 360.0) >= 180.0) {
|
||||
dub -= 360.0;
|
||||
}
|
||||
if (dub < -180.0) {
|
||||
dub += 360.0;
|
||||
}
|
||||
return dub;
|
||||
}
|
||||
|
||||
public static double getDirection(Location from, Location to) {
|
||||
if (from == null || to == null) {
|
||||
return 0.0;
|
||||
}
|
||||
double difX = to.getX() - from.getX();
|
||||
double difZ = to.getZ() - from.getZ();
|
||||
return MathUtils.yawTo180F((float) (FastTrig.fast_atan2(difZ, difX) * 180.0 / 3.141592653589793) - 90.0f);
|
||||
}
|
||||
|
||||
public static float[] getRotation(Location one, Location two) {
|
||||
return getRotation(new KLocation(one), new KLocation(two));
|
||||
}
|
||||
|
||||
public static float[] getRotation(KLocation one, KLocation two) {
|
||||
double diffX = two.x - one.x;
|
||||
double diffZ = two.z - one.z;
|
||||
double diffY = two.y - one.y;
|
||||
double dist = Math.sqrt(diffX * diffX + diffZ * diffZ);
|
||||
float yaw = (float) (FastTrig.fast_atan2(diffZ, diffX) * 180.0 / 3.141592653589793) - 90.0f;
|
||||
float pitch = (float) (-FastTrig.fast_atan2(diffY, dist) * 180.0 / 3.141592653589793);
|
||||
return new float[]{yaw, pitch};
|
||||
}
|
||||
|
||||
public static float[] getRotation(LivingEntity origin, LivingEntity point) {
|
||||
return getRotation(origin.getLocation(), point.getLocation());
|
||||
}
|
||||
|
||||
public static boolean isLookingTowardsEntity(Location from, Location to, LivingEntity entity) {
|
||||
float[] rotFrom = getRotation(from, entity.getLocation()), rotTo = getRotation(to, entity.getLocation());
|
||||
float deltaOne = getDelta(from.getYaw(), rotTo[0]), deltaTwo = getDelta(to.getYaw(), rotTo[1]);
|
||||
float offsetFrom = getDelta(yawTo180F(from.getYaw()), yawTo180F(rotFrom[0])), offsetTo = getDelta(yawTo180F(to.getYaw()), yawTo180F(rotTo[0]));
|
||||
|
||||
return (deltaOne > deltaTwo && offsetTo > 15) || (MathUtils.getDelta(offsetFrom, offsetTo) < 1 && offsetTo < 10);
|
||||
}
|
||||
|
||||
public static double[] getOffsetFromEntity(Player player, LivingEntity entity) {
|
||||
double yawOffset = Math.abs(MathUtils.yawTo180F(player.getEyeLocation().getYaw()) - MathUtils.yawTo180F(MathUtils.getRotation(player.getLocation(), entity.getLocation())[0]));
|
||||
double pitchOffset = Math.abs(Math.abs(player.getEyeLocation().getPitch()) - Math.abs(MathUtils.getRotation(player.getLocation(), entity.getLocation())[1]));
|
||||
return new double[]{yawOffset, pitchOffset};
|
||||
}
|
||||
|
||||
public static double[] getOffsetFromLocation(Location one, Location two) {
|
||||
double yaw = MathUtils.getRotation(one, two)[0];
|
||||
double pitch = MathUtils.getRotation(one, two)[1];
|
||||
double yawOffset = Math.abs(yaw - MathUtils.yawTo180F(one.getYaw()));
|
||||
double pitchOffset = Math.abs(pitch - one.getPitch());
|
||||
return new double[]{yawOffset, pitchOffset};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package dev.brighten.ac.utils;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class Tuple<A, B> {
|
||||
public A one;
|
||||
public B two;
|
||||
|
||||
public Tuple(A one, B two) {
|
||||
this.one = one;
|
||||
this.two = two;
|
||||
}
|
||||
|
||||
public boolean equals(Object object) {
|
||||
if (this.getClass().isInstance(object)) {
|
||||
var toCompare = (Tuple<?, ?>) object;
|
||||
return one.equals(toCompare.one) && two.equals(toCompare.two);
|
||||
} else return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tuple{" +
|
||||
"one=" + one +
|
||||
", two=" + two +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(one, two);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.brighten.ac.utils.objects;
|
||||
|
||||
import dev.brighten.ac.utils.Tuple;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BiSupplier<T, V> {
|
||||
|
||||
Tuple<T, V> get();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package dev.brighten.ac.utils.objects;
|
||||
|
||||
import dev.brighten.ac.utils.MathUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.DoubleSummaryStatistics;
|
||||
import java.util.LinkedList;
|
||||
import java.util.stream.DoubleStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Interval extends LinkedList<Double> {
|
||||
|
||||
private final long max;
|
||||
|
||||
public Interval(long max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public Interval(Interval in) {
|
||||
this.max = in.max;
|
||||
}
|
||||
|
||||
public double average() {
|
||||
return getDoubleStream().summaryStatistics().getAverage();
|
||||
}
|
||||
|
||||
public DoubleSummaryStatistics getSummary() {
|
||||
return getDoubleStream().summaryStatistics();
|
||||
}
|
||||
public double frequency(double freq) {
|
||||
return Collections.frequency(this, freq);
|
||||
}
|
||||
|
||||
public long distinctCount() {
|
||||
return getDoubleStream().distinct().count();
|
||||
}
|
||||
|
||||
public Stream<Double> distinct() {
|
||||
return stream().distinct();
|
||||
}
|
||||
|
||||
public double std() {
|
||||
return MathUtils.stdev(this);
|
||||
}
|
||||
|
||||
public double max() {
|
||||
return getDoubleStream().summaryStatistics().getMax();
|
||||
}
|
||||
|
||||
public double min() {
|
||||
return getDoubleStream().summaryStatistics().getMin();
|
||||
}
|
||||
|
||||
public boolean add(double x) {
|
||||
if (size() == max) {
|
||||
removeLast();
|
||||
}
|
||||
addFirst(x);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void clearIfMax() {
|
||||
if (size() == max) {
|
||||
this.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public DoubleStream getDoubleStream() {
|
||||
return stream().mapToDouble(val -> val);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package dev.brighten.ac.utils.objects;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class MethodFunction {
|
||||
private Function function;
|
||||
private BiFunction biFunc;
|
||||
private TriFunction triFunc;
|
||||
private QuadFunction quadFunc;
|
||||
private final Method method;
|
||||
|
||||
public MethodFunction(Method method, Function function) {
|
||||
this.function = function;
|
||||
this.method = method;
|
||||
method.setAccessible(true);
|
||||
}
|
||||
|
||||
public MethodFunction(Method method, BiFunction biFunc) {
|
||||
this.biFunc = biFunc;
|
||||
this.method = method;
|
||||
method.setAccessible(true);
|
||||
}
|
||||
|
||||
public MethodFunction(Method method, TriFunction triFunc) {
|
||||
this.triFunc = triFunc;
|
||||
this.method = method;
|
||||
method.setAccessible(true);
|
||||
}
|
||||
|
||||
public MethodFunction(Method method, QuadFunction quadFunc) {
|
||||
this.quadFunc = quadFunc;
|
||||
this.method = method;
|
||||
method.setAccessible(true);
|
||||
}
|
||||
|
||||
public MethodFunction(Method method) {
|
||||
this.method = method;
|
||||
method.setAccessible(true);
|
||||
}
|
||||
|
||||
//Apparently not allowed to convert Function from Object. I guess it's because they're an interface :/.
|
||||
/*public MethodFunction(Method method, Object objFunc) {
|
||||
if(objFunc instanceof Function) {
|
||||
this.function = (Function) objFunc;
|
||||
} else if(objFunc instanceof BiFunction) {
|
||||
this.biFunc = (BiFunction) objFunc;
|
||||
} else if(objFunc instanceof TriFunction) {
|
||||
this.triFunc = (TriFunction) objFunc;
|
||||
} else if(objFunc instanceof QuadFunction) {
|
||||
this.quadFunc = (QuadFunction) objFunc;
|
||||
}
|
||||
}*/
|
||||
|
||||
/** Maximum arguments of 3 **/
|
||||
public <T> T invokeMethod(Object instance, Object... args) {
|
||||
if(args.length <= 3) {
|
||||
if(function != null) {
|
||||
return (T) function.apply(instance);
|
||||
} else if(biFunc != null) {
|
||||
return (T) biFunc.apply(instance, getArgOrNull(args, 0));
|
||||
} else if(triFunc != null) {
|
||||
return (T) triFunc.apply(instance, getArgOrNull(args, 0),
|
||||
getArgOrNull(args, 1));
|
||||
} else if(quadFunc != null) {
|
||||
return (T) quadFunc.apply(instance, getArgOrNull(args, 0),
|
||||
getArgOrNull(args, 1), getArgOrNull(args, 2));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return (T) method.invoke(instance, args);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> T getArgOrNull(T[] array, int index) {
|
||||
if(array.length > index) {
|
||||
return array[index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.brighten.ac.utils.objects;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface MultiFunction<R> {
|
||||
R apply(Object... o);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.brighten.ac.utils.objects;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface QuadFunction<R, T, U, V, G>{
|
||||
|
||||
R apply(T t, U u, V v, G g);
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package dev.brighten.ac.utils.objects;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class RemoteClassLoader extends ClassLoader {
|
||||
|
||||
private final byte[] jarBytes;
|
||||
public final Set<String> names;
|
||||
public Map<String, Class> classes = new HashMap<>();
|
||||
|
||||
public RemoteClassLoader(byte[] jarBytes, ClassLoader parent) throws IOException {
|
||||
super(parent);
|
||||
this.jarBytes = jarBytes;
|
||||
this.names = RemoteClassLoader.loadNames(jarBytes);
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
security.checkCreateClassLoader();
|
||||
}
|
||||
if(names != null) {
|
||||
names.forEach(name -> {
|
||||
try {
|
||||
String shit = name.replace(".class", "shitnibba123@")
|
||||
.replace("/", ".")
|
||||
.replace("shitnibba123@", ".class");
|
||||
classes.put(shit,
|
||||
getClass(shit));
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} else Bukkit.getLogger().warning("names null.");
|
||||
}
|
||||
|
||||
/**
|
||||
* This will put all the entries into a thread-safe Set
|
||||
*/
|
||||
private static Set<String> loadNames(byte[] jarBytes) throws IOException {
|
||||
Set<String> set = new HashSet<>();
|
||||
try (ZipInputStream jis =
|
||||
new ZipInputStream(new ByteArrayInputStream(jarBytes))) {
|
||||
ZipEntry entry;
|
||||
while ((entry = jis.getNextEntry()) != null) {
|
||||
set.add(entry.getName());
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String name) {
|
||||
// I moved the JarInputStream declaration outside the
|
||||
// try-with-resources statement as it must not be closed otherwise
|
||||
// the returned InputStream won't be readable as already closed
|
||||
boolean found = false;
|
||||
ZipInputStream jis = null;
|
||||
try {
|
||||
jis = new ZipInputStream(new ByteArrayInputStream(jarBytes));
|
||||
ZipEntry entry;
|
||||
while ((entry = jis.getNextEntry()) != null) {
|
||||
if (entry.getName().equals(name)) {
|
||||
found = true;
|
||||
return jis;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
// Only close the stream if the entry could not be found
|
||||
if (jis != null && !found) {
|
||||
try {
|
||||
jis.close();
|
||||
} catch (IOException e) {
|
||||
// ignore me
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class findClass(String name) throws ClassNotFoundException {
|
||||
if(!classes.containsKey(name)) {
|
||||
byte[] b = loadClassFromFile(name);
|
||||
return defineClass(name, b, 0, b.length);
|
||||
} else return classes.get(name);
|
||||
}
|
||||
|
||||
private Class getClass(String name) throws ClassNotFoundException {
|
||||
byte[] b = loadClassFromFile(name);
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
|
||||
private byte[] loadClassFromFile(String fileName) {
|
||||
String name = fileName.replace(".class", "shitguy123@").replace('.', File.separatorChar).replace("shitguy123@", ".class") + (!fileName.contains(".class") ? ".class" : "");
|
||||
InputStream inputStream = getResourceAsStream(name);
|
||||
byte[] buffer;
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||
int nextValue = 0;
|
||||
try {
|
||||
if(inputStream != null) {
|
||||
while ( (nextValue = inputStream.read()) != -1 ) {
|
||||
byteStream.write(nextValue);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
buffer = byteStream.toByteArray();
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.brighten.ac.utils.objects;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TriFunction<R, T, U, V> {
|
||||
|
||||
R apply(T t, U u, V v);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.brighten.ac.utils.objects;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class VariableValue<T> {
|
||||
|
||||
private final T isTrue;
|
||||
private final T isFalse;
|
||||
private final BooleanSupplier variable;
|
||||
|
||||
public T get() {
|
||||
return variable.getAsBoolean() ? isTrue : isFalse;
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2018 NGXDEV.COM. Licensed under MIT.
|
||||
* Modified by funkemunky.
|
||||
*/
|
||||
|
||||
package dev.brighten.ac.utils.objects.evicting;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ConcurrentEvictingList<T> extends ConcurrentLinkedDeque<T> {
|
||||
private final int maxSize;
|
||||
|
||||
public ConcurrentEvictingList(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public ConcurrentEvictingList(Collection<? extends T> c, int maxSize) {
|
||||
super(c);
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public int getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T t) {
|
||||
if (size() >= maxSize) remove(0);
|
||||
return super.add(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
return c.stream().anyMatch(this::add);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<T> stream() {
|
||||
return new CopyOnWriteArrayList<>(this).stream();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package dev.brighten.ac.utils.objects.evicting;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ConcurrentEvictingMap<K, V> extends ConcurrentSkipListMap<K, V> {
|
||||
|
||||
@Getter
|
||||
private final int size;
|
||||
|
||||
@Override
|
||||
public V putIfAbsent(K key, V value) {
|
||||
if(!value.equals(get(key)))
|
||||
checkAndRemove();
|
||||
return super.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
checkAndRemove();
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
m.forEach(this::put);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
return super.remove(key);
|
||||
}
|
||||
|
||||
private boolean checkAndRemove() {
|
||||
if(size() >= size) {
|
||||
entrySet().remove(firstEntry());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2018 NGXDEV.COM. Licensed under MIT.
|
||||
* Modified by funkemunky.
|
||||
*/
|
||||
|
||||
package dev.brighten.ac.utils.objects.evicting;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class EvictingList<T> extends LinkedList<T> {
|
||||
private final int maxSize;
|
||||
|
||||
public EvictingList(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public EvictingList(Collection<? extends T> c, int maxSize) {
|
||||
super(c);
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public int getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T t) {
|
||||
if (size() >= maxSize) removeFirst();
|
||||
return super.add(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
return c.stream().anyMatch(this::add);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<T> stream() {
|
||||
return new CopyOnWriteArrayList<>(this).stream();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package dev.brighten.ac.utils.objects.evicting;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class EvictingMap<K, V> extends LinkedHashMap<K, V> {
|
||||
|
||||
@Getter
|
||||
private final int size;
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||
return size() >= size;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package dev.brighten.ac.utils.objects.filtered;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ConcurrentFilteredList<T> extends CopyOnWriteArrayList<T> {
|
||||
|
||||
private final Predicate<T> predicate;
|
||||
|
||||
public ConcurrentFilteredList(Predicate<T> predicate) {
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T t) {
|
||||
if(predicate.test(t)) {
|
||||
return super.add(t);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
List<? extends T> filtered = c.stream().filter(predicate).collect(Collectors.toList());
|
||||
|
||||
return super.addAll(filtered);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends T> c) {
|
||||
List<? extends T> filtered = c.stream().filter(predicate).collect(Collectors.toList());
|
||||
|
||||
return super.addAll(index, filtered);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, T element) {
|
||||
if(predicate.test(element)) {
|
||||
super.add(index, element);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T set(int index, T element) {
|
||||
if(predicate.test(element)) {
|
||||
return super.set(index, element);
|
||||
}
|
||||
return size() > index ? get(index) : null;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package dev.brighten.ac.utils.objects.filtered;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ConcurrentFilteredSet<T> extends ConcurrentSkipListSet<T> {
|
||||
|
||||
private final Predicate<T> predicate;
|
||||
|
||||
public ConcurrentFilteredSet(Predicate<T> predicate) {
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T t) {
|
||||
if(predicate.test(t)) {
|
||||
return super.add(t);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
List<? extends T> filtered = c.stream().filter(predicate).collect(Collectors.toList());
|
||||
|
||||
return super.addAll(filtered);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.brighten.ac.utils.objects.filtered;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FilteredList<T> extends ArrayList<T> {
|
||||
|
||||
private final Predicate<T> predicate;
|
||||
|
||||
public FilteredList(Predicate<T> predicate) {
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T t) {
|
||||
if(predicate.test(t)) {
|
||||
return super.add(t);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
List<? extends T> filtered = c.stream().filter(predicate).collect(Collectors.toList());
|
||||
|
||||
return super.addAll(filtered);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends T> c) {
|
||||
List<? extends T> filtered = c.stream().filter(predicate).collect(Collectors.toList());
|
||||
|
||||
return super.addAll(index, filtered);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, T element) {
|
||||
if(predicate.test(element)) {
|
||||
super.add(index, element);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T set(int index, T element) {
|
||||
if(predicate.test(element)) {
|
||||
return super.set(index, element);
|
||||
}
|
||||
return size() > index ? get(index) : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package dev.brighten.ac.utils.objects.filtered;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FilteredSet<T> extends HashSet<T> {
|
||||
|
||||
private final Predicate<T> predicate;
|
||||
|
||||
public FilteredSet(Predicate<T> predicate) {
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T t) {
|
||||
if(predicate.test(t)) {
|
||||
return super.add(t);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
List<? extends T> filtered = c.stream().filter(predicate).collect(Collectors.toList());
|
||||
|
||||
return super.addAll(filtered);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package dev.brighten.ac.utils.objects.listmap;
|
||||
|
||||
import lombok.val;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ConcurrentListMap<K, V> implements ListMap<K, V> {
|
||||
|
||||
private final Map<K, List<V>> values = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public List<V> getList(K key) {
|
||||
createIfNotExists(key);
|
||||
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createIfNotExists(K key) {
|
||||
if(!values.containsKey(key))
|
||||
values.put(key, new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(K key, V value) {
|
||||
val list = getList(key);
|
||||
|
||||
list.add(value);
|
||||
|
||||
values.put(key, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int remove(V value) {
|
||||
int removed = 0;
|
||||
for (K k : values.keySet()) {
|
||||
List<V> vals = values.get(k);
|
||||
|
||||
for (V val : vals) {
|
||||
if(!val.equals(value)) continue;
|
||||
|
||||
vals.remove(val);
|
||||
values.put(k, vals);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(K key, V value) {
|
||||
val vals = getList(key);
|
||||
|
||||
boolean removed = vals.remove(value);
|
||||
|
||||
if(removed) {
|
||||
values.put(key, vals);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<V> removeKey(K key) {
|
||||
return values.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clear() {
|
||||
if(values.size() > 0) {
|
||||
values.clear();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainsResult containsValue(V value) {
|
||||
for (K key : values.keySet()) {
|
||||
val list = values.get(key);
|
||||
|
||||
for (V v : list) {
|
||||
if(value.equals(v)) return new ContainsResult(key, true);
|
||||
}
|
||||
}
|
||||
return new ContainsResult(null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(K key) {
|
||||
return values.containsKey(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package dev.brighten.ac.utils.objects.listmap;
|
||||
|
||||
import lombok.val;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class HashListMap<K, V> implements ListMap<K, V> {
|
||||
|
||||
private final Map<K, List<V>> values = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public List<V> getList(K key) {
|
||||
createIfNotExists(key);
|
||||
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createIfNotExists(K key) {
|
||||
if(!values.containsKey(key))
|
||||
values.put(key, new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(K key, V value) {
|
||||
val list = getList(key);
|
||||
|
||||
list.add(value);
|
||||
|
||||
values.put(key, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int remove(V value) {
|
||||
int removed = 0;
|
||||
for (K k : values.keySet()) {
|
||||
List<V> vals = values.get(k);
|
||||
|
||||
for (V val : vals) {
|
||||
if(!val.equals(value)) continue;
|
||||
|
||||
vals.remove(val);
|
||||
values.put(k, vals);
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(K key, V value) {
|
||||
val vals = getList(key);
|
||||
|
||||
boolean removed = vals.remove(value);
|
||||
|
||||
if(removed) {
|
||||
values.put(key, vals);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<V> removeKey(K key) {
|
||||
return values.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clear() {
|
||||
if(values.size() > 0) {
|
||||
values.clear();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainsResult containsValue(V value) {
|
||||
for (K key : values.keySet()) {
|
||||
val list = values.get(key);
|
||||
|
||||
for (V v : list) {
|
||||
if(value.equals(v)) return new ContainsResult(key, true);
|
||||
}
|
||||
}
|
||||
return new ContainsResult(null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(K key) {
|
||||
return values.containsKey(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package dev.brighten.ac.utils.objects.listmap;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ListMap<K, V> {
|
||||
|
||||
List<V> getList(K key);
|
||||
|
||||
void createIfNotExists(K key);
|
||||
|
||||
void add(K key, V value);
|
||||
|
||||
int remove(V value);
|
||||
|
||||
boolean remove(K key, V value);
|
||||
|
||||
List<V> removeKey(K key);
|
||||
|
||||
boolean clear();
|
||||
|
||||
ContainsResult containsValue(V value);
|
||||
|
||||
boolean containsKey(K key);
|
||||
|
||||
@Getter
|
||||
class ContainsResult {
|
||||
private final boolean result;
|
||||
private final Object key;
|
||||
protected ContainsResult(Object key, boolean result) {
|
||||
this.key = key;
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Created by Justin Heflin on 4/19/18 8:21 PM
|
||||
* Copyright (c) 2018.
|
||||
*
|
||||
* Can be redistributed non commercially as long as credit is given to original copyright owner.
|
||||
*
|
||||
* last modified: 4/19/18 7:22 PM
|
||||
*/
|
||||
package dev.brighten.ac.utils.reflections;
|
||||
|
||||
import dev.brighten.ac.utils.objects.QuadFunction;
|
||||
import dev.brighten.ac.utils.objects.TriFunction;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.invoke.LambdaMetafactory;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Getter
|
||||
public class Reflections {
|
||||
private static final String craftBukkitString;
|
||||
private static final String netMinecraftServerString;
|
||||
private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
public static String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName();
|
||||
public static String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "")
|
||||
.replace(".", "");
|
||||
|
||||
static {
|
||||
String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
|
||||
craftBukkitString = "org.bukkit.craftbukkit." + version + ".";
|
||||
netMinecraftServerString = "net.minecraft.server." + version + ".";
|
||||
}
|
||||
|
||||
public static boolean classExists(String name) {
|
||||
try {
|
||||
Class.forName(name);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static WrappedClass getCBClass(String name) {
|
||||
return getClass(craftBukkitString + name);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static WrappedClass getNMSClass(String name) {
|
||||
try {
|
||||
return getClass(netMinecraftServerString + name);
|
||||
} catch(Throwable e) {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static WrappedClass getClass(String name) {
|
||||
try {
|
||||
return new WrappedClass(Class.forName(name));
|
||||
} catch (ClassNotFoundException | NoClassDefFoundError e) {
|
||||
throw new NullPointerException("Class" + name + " could not be found!");
|
||||
}
|
||||
}
|
||||
|
||||
public static WrappedClass getUtilClass(String name) {
|
||||
return getClass((ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_8)
|
||||
? "net.minecraft.util." : "") + name.replace("dev.brighten.ac.utils.", ""));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static <T> T createMethodLambda(Method method) {
|
||||
if(!method.isAccessible()) return null;
|
||||
val handle = lookup.unreflect(method);
|
||||
Class<?> functionType;
|
||||
switch(method.getParameterCount()) {
|
||||
case 0:
|
||||
functionType = Function.class;
|
||||
break;
|
||||
case 1:
|
||||
functionType = BiFunction.class;
|
||||
break;
|
||||
case 2:
|
||||
functionType = TriFunction.class;
|
||||
break;
|
||||
case 3:
|
||||
functionType = QuadFunction.class;
|
||||
default:
|
||||
functionType = null;
|
||||
break;
|
||||
}
|
||||
|
||||
if(functionType != null) {
|
||||
return (T) LambdaMetafactory.metafactory(lookup, "apply",
|
||||
MethodType.methodType(functionType),
|
||||
MethodType.methodType(method.getReturnType(), handle.type().parameterArray()),
|
||||
handle, handle.type()).getTarget().invoke();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static WrappedClass getClass(Class clazz) {
|
||||
return new WrappedClass(clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package dev.brighten.ac.utils.reflections.impl;
|
||||
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class CraftReflection {
|
||||
public static WrappedClass craftHumanEntity = Reflections.getCBClass("entity.CraftHumanEntity"); //1.7-1.14
|
||||
public static WrappedClass craftEntity = Reflections.getCBClass("entity.CraftEntity"); //1.7-1.14
|
||||
public static WrappedClass craftItemStack = Reflections.getCBClass("inventory.CraftItemStack"); //1.7-1.14
|
||||
public static WrappedClass craftBlock = Reflections.getCBClass("block.CraftBlock"); //1.7-1.14
|
||||
public static WrappedClass craftPlayer = Reflections.getCBClass("entity.CraftPlayer");
|
||||
public static WrappedClass craftWorld = Reflections.getCBClass("CraftWorld"); //1.7-1.14
|
||||
public static WrappedClass craftInventoryPlayer = Reflections.getCBClass("inventory.CraftInventoryPlayer"); //1.7-1.14
|
||||
public static WrappedClass craftServer = Reflections.getCBClass("CraftServer"); //1.7-1.14\
|
||||
public static WrappedClass craftChunk = Reflections.getCBClass("CraftChunk");
|
||||
public static WrappedClass craftMagicNumbers = Reflections.getCBClass("util.CraftMagicNumbers");
|
||||
public static WrappedClass craftChatMessage = Reflections.getCBClass("util.CraftChatMessage");
|
||||
|
||||
//Vanilla Instances
|
||||
private static final WrappedMethod itemStackInstance = craftItemStack.getMethod("asNMSCopy", ItemStack.class); //1.7-1.14
|
||||
private static final WrappedMethod humanEntityInstance = craftHumanEntity.getMethod("getHandle"); //1.7-1.14
|
||||
private static final WrappedMethod entityInstance = craftEntity.getMethod("getHandle"); //1.7-1.14
|
||||
private static final WrappedMethod blockInstance = craftBlock.getMethod(ProtocolVersion.getGameVersion()
|
||||
.isOrAbove(ProtocolVersion.V1_17_1) ? "getNMS" : "getNMSBlock"); //1.7-1.14
|
||||
private static final WrappedMethod worldInstance = craftWorld.getMethod("getHandle"); //1.7-1.14
|
||||
private static final WrappedMethod bukkitEntity = MinecraftReflection.entity.getMethod("getBukkitEntity"); //1.7-1.14
|
||||
private static final WrappedMethod getInventory = craftInventoryPlayer.getMethod("getInventory"); //1.7-1.14
|
||||
private static final WrappedMethod mcServerInstance = craftServer.getMethod("getServer"); //1.7-1.14
|
||||
private static final WrappedMethod entityPlayerInstance = craftPlayer.getMethod("getHandle");
|
||||
private static final WrappedMethod chunkInstance = craftChunk.getMethod("getHandle");
|
||||
private static final WrappedMethod methodGetBlockFromMaterial = ProtocolVersion.getGameVersion()
|
||||
.isOrAbove(ProtocolVersion.V1_13) ? craftMagicNumbers.getMethod("getBlock", Material.class)
|
||||
: craftMagicNumbers.getMethod("getBlock", int.class);
|
||||
private static WrappedMethod fromComponent;
|
||||
|
||||
public static <T> T getVanillaItemStack(ItemStack stack) {
|
||||
return itemStackInstance.invoke(null, stack);
|
||||
}
|
||||
|
||||
public static <T> T getEntityHuman(HumanEntity entity) {
|
||||
return humanEntityInstance.invoke(entity);
|
||||
}
|
||||
|
||||
public static <T> T getEntity(Entity entity) {
|
||||
return entityInstance.invoke(entity);
|
||||
}
|
||||
|
||||
public static <T> T getEntityPlayer(Player player) {
|
||||
return entityPlayerInstance.invoke(player);
|
||||
}
|
||||
|
||||
public static <T> T getVanillaBlock(Block block) {
|
||||
return blockInstance.invoke(block);
|
||||
}
|
||||
|
||||
public static <T> T getVanillaWorld(World world) {
|
||||
return worldInstance.invoke(world);
|
||||
}
|
||||
|
||||
public static Entity getBukkitEntity(Object vanillaEntity) {
|
||||
return bukkitEntity.invoke(vanillaEntity);
|
||||
}
|
||||
|
||||
public static <T> T getVanillaInventory(Player player) {
|
||||
return getInventory.invoke(player.getInventory());
|
||||
}
|
||||
|
||||
public static <T> T getMinecraftServer() {
|
||||
return mcServerInstance.invoke(Bukkit.getServer());
|
||||
}
|
||||
|
||||
public static <T> T getVanillaChunk(Chunk chunk) {
|
||||
return chunkInstance.invoke(chunk);
|
||||
}
|
||||
|
||||
public static <T> T getVanillaBlock(Material material) {
|
||||
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_13)) {
|
||||
return methodGetBlockFromMaterial.invoke(null, material);
|
||||
} else {
|
||||
return methodGetBlockFromMaterial.invoke(null, material.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMessageFromComp(Object ichatcomp, String defaultColor) {
|
||||
if(fromComponent == null) return "Not a usable version (1.8+ only)";
|
||||
return fromComponent.invoke(null, ichatcomp);
|
||||
}
|
||||
|
||||
static {
|
||||
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_8)) {
|
||||
fromComponent = craftChatMessage.getMethod("fromComponent",
|
||||
MinecraftReflection.iChatBaseComponent.getParent());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
package dev.brighten.ac.utils.reflections.impl;
|
||||
|
||||
import dev.brighten.ac.packet.ProtocolVersion;
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedClass;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedConstructor;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedField;
|
||||
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MinecraftReflection {
|
||||
public static WrappedClass entity = Reflections.getNMSClass("Entity");
|
||||
public static WrappedClass axisAlignedBB = Reflections.getNMSClass("AxisAlignedBB");
|
||||
public static WrappedClass entityHuman = Reflections.getNMSClass("EntityHuman");
|
||||
public static WrappedClass entityLiving = Reflections.getNMSClass("EntityLiving");
|
||||
public static WrappedClass block = Reflections.getNMSClass("Block");
|
||||
public static WrappedClass iBlockData, blockBase,
|
||||
chunkProviderServer = Reflections.getNMSClass("ChunkProviderServer");
|
||||
public static WrappedClass itemClass = Reflections.getNMSClass("Item"),
|
||||
enumChatFormat = Reflections.getNMSClass("EnumChatFormat");
|
||||
public static WrappedClass world = Reflections.getNMSClass("World");
|
||||
public static WrappedClass worldServer = Reflections.getNMSClass("WorldServer");
|
||||
public static WrappedClass playerInventory = Reflections.getNMSClass("PlayerInventory");
|
||||
public static WrappedClass itemStack = Reflections.getNMSClass("ItemStack"),
|
||||
item = Reflections.getNMSClass("Item");
|
||||
public static WrappedClass chunk = Reflections.getNMSClass("Chunk");
|
||||
public static WrappedClass classBlockInfo;
|
||||
public static WrappedClass minecraftServer = Reflections.getNMSClass("MinecraftServer");
|
||||
public static WrappedClass entityPlayer = ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_17)
|
||||
? Reflections.getClass("net.minecraft.server.level.EntityPlayer")
|
||||
: Reflections.getNMSClass("EntityPlayer");
|
||||
public static WrappedClass playerConnection = ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_17)
|
||||
? Reflections.getClass("net.minecraft.server.network.PlayerConnection")
|
||||
: Reflections.getNMSClass("PlayerConnection");
|
||||
public static WrappedClass networkManager = Reflections.getNMSClass("NetworkManager");
|
||||
public static WrappedClass serverConnection = Reflections.getNMSClass("ServerConnection");
|
||||
public static WrappedClass gameProfile = Reflections.getUtilClass("com.mojang.authlib.GameProfile");
|
||||
private static final WrappedClass propertyMap = Reflections.getUtilClass("com.mojang.authlib.properties.PropertyMap");
|
||||
private static final WrappedClass forwardMultiMap = Reflections.getUtilClass("com.google.common.collect.ForwardingMultimap");
|
||||
public static WrappedClass iChatBaseComponent = Reflections.getNMSClass("IChatBaseComponent"),
|
||||
chatComponentText;
|
||||
public static WrappedClass vec3D = Reflections.getNMSClass("Vec3D");
|
||||
|
||||
private static final WrappedMethod getProfile = CraftReflection.craftPlayer.getMethod("getProfile");
|
||||
private static final WrappedMethod methodGetServerConnection = minecraftServer
|
||||
.getMethodByType(serverConnection.getParent(), ProtocolVersion.getGameVersion()
|
||||
.isBelow(ProtocolVersion.V1_13) ? 1 : 0);
|
||||
private static WrappedConstructor chatComponentTextConst;
|
||||
private static final WrappedMethod getProperties = gameProfile.getMethod("getProperties");
|
||||
private static final WrappedMethod removeAll = forwardMultiMap.getMethod("removeAll", Object.class);
|
||||
private static final WrappedMethod putAll = propertyMap.getMethod("putAll", Object.class, Iterable.class);
|
||||
private static final WrappedMethod worldGetType;
|
||||
//SimpleCollisionBoxes
|
||||
private static final WrappedMethod getCubes;
|
||||
private static final WrappedField aBB = axisAlignedBB.getFieldByName("a");
|
||||
private static final WrappedField bBB = axisAlignedBB.getFieldByName("b");
|
||||
private static final WrappedField cBB = axisAlignedBB.getFieldByName("c");
|
||||
private static final WrappedField dBB = axisAlignedBB.getFieldByName("d");
|
||||
private static final WrappedField eBB = axisAlignedBB.getFieldByName("e");
|
||||
private static final WrappedField fBB = axisAlignedBB.getFieldByName("f");
|
||||
private static WrappedConstructor aabbConstructor;
|
||||
private static WrappedMethod idioticOldStaticConstructorAABB, methodBlockCollisionBox;
|
||||
private static final WrappedField entitySimpleCollisionBox = entity.getFirstFieldByType(axisAlignedBB.getParent());
|
||||
public static WrappedClass enumAnimation = Reflections.getNMSClass("EnumAnimation");
|
||||
|
||||
//ItemStack methods and fields
|
||||
private static WrappedMethod enumAnimationStack;
|
||||
private static final WrappedField activeItemField;
|
||||
private static final WrappedMethod getItemMethod = itemStack.getMethodByType(item.getParent(), 0);
|
||||
private static final WrappedMethod getAnimationMethod = itemClass.getMethodByType(enumAnimation.getParent(), 0);
|
||||
private static final WrappedMethod canDestroyMethod;
|
||||
|
||||
//1.13+ only
|
||||
private static WrappedClass voxelShape;
|
||||
private static WrappedClass worldReader;
|
||||
private static WrappedMethod getCubesFromVoxelShape;
|
||||
|
||||
private static final WrappedMethod itemStackAsBukkitCopy = CraftReflection.craftItemStack
|
||||
.getMethod("asBukkitCopy", itemStack.getParent());
|
||||
|
||||
//Blocks
|
||||
private static WrappedMethod addCBoxes;
|
||||
public static WrappedClass blockPos;
|
||||
private static WrappedConstructor blockPosConstructor;
|
||||
private static WrappedMethod getBlockData, getBlock;
|
||||
private static WrappedField blockData;
|
||||
private static final WrappedField frictionFactor;
|
||||
private static final WrappedField strength;
|
||||
private static final WrappedField chunkProvider = MinecraftReflection.worldServer
|
||||
.getFieldByType(Reflections.getNMSClass(ProtocolVersion.getGameVersion()
|
||||
.isBelow(ProtocolVersion.V1_16)
|
||||
&& ProtocolVersion.getGameVersion()
|
||||
.isOrAbove(ProtocolVersion.V1_9) ? "IChunkProvider" : "ChunkProviderServer")
|
||||
.getParent(), 0);
|
||||
|
||||
|
||||
//Entity Player fields
|
||||
private static final WrappedField connectionField = entityPlayer
|
||||
.getFieldByType(playerConnection.getParent(), 0);
|
||||
private static final WrappedField connectionNetworkField = playerConnection
|
||||
.getFieldByType(networkManager.getParent(), 0);
|
||||
private static final WrappedField networkChannelField = networkManager.getFieldByType(Reflections
|
||||
.getUtilClass("io.netty.channel.Channel").getParent(), 0);
|
||||
|
||||
//General Fields
|
||||
private static final WrappedField primaryThread = minecraftServer.getFirstFieldByType(Thread.class);
|
||||
|
||||
public static <T> T getGameProfile(Player player) {
|
||||
return getProfile.invoke(player);
|
||||
}
|
||||
|
||||
//1.7 field is boundingBox
|
||||
//1.8+ method is getBoundingBox.
|
||||
public static <T> T getEntityBoundingBox(Entity entity) {
|
||||
Object vanillaEntity = CraftReflection.getEntity(entity);
|
||||
|
||||
return entitySimpleCollisionBox.get(vanillaEntity);
|
||||
}
|
||||
|
||||
public static <T> T getItemInUse(HumanEntity entity) {
|
||||
Object humanEntity = CraftReflection.getEntityHuman(entity);
|
||||
return activeItemField.get(humanEntity);
|
||||
}
|
||||
|
||||
//Can use either a Bukkit or vanilla object
|
||||
public static <T> T getItemFromStack(Object object) {
|
||||
Object vanillaStack;
|
||||
if(object instanceof ItemStack) {
|
||||
vanillaStack = CraftReflection.getVanillaItemStack((ItemStack)object);
|
||||
} else vanillaStack = object;
|
||||
|
||||
return getItemMethod.invoke(vanillaStack);
|
||||
}
|
||||
|
||||
//Can use either a Bukkit or vanilla object
|
||||
public static <T> T getItemAnimation(Object object) {
|
||||
Object vanillaStack;
|
||||
if(object instanceof ItemStack) {
|
||||
vanillaStack = CraftReflection.getVanillaItemStack((ItemStack)object);
|
||||
} else vanillaStack = object;
|
||||
|
||||
Object item = getItemFromStack(vanillaStack);
|
||||
|
||||
return getAnimationMethod.invoke(item, vanillaStack);
|
||||
}
|
||||
|
||||
public static Object getChatComponentFromText(String string) {
|
||||
return chatComponentTextConst.newInstance(string);
|
||||
}
|
||||
|
||||
public static int getPing(Player player) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static <T> T getServerConnection() {
|
||||
return methodGetServerConnection.invoke(CraftReflection.getMinecraftServer());
|
||||
}
|
||||
|
||||
public static <T> T getServerConnection(Object minecraftServer) {
|
||||
return methodGetServerConnection.invoke(minecraftServer);
|
||||
}
|
||||
|
||||
public static Thread getMainThread(Object minecraftServer) {
|
||||
return primaryThread.get(minecraftServer);
|
||||
}
|
||||
|
||||
public static Thread getMainThread() {
|
||||
return getMainThread(CraftReflection.getMinecraftServer());
|
||||
}
|
||||
|
||||
|
||||
//Can either use Player or EntityPlayer object.
|
||||
public static <T> T getPlayerConnection(Object player) {
|
||||
Object entityPlayer;
|
||||
if(player instanceof Player) {
|
||||
entityPlayer = CraftReflection.getEntityPlayer((Player)player);
|
||||
} else entityPlayer = player;
|
||||
|
||||
return connectionField.get(entityPlayer);
|
||||
}
|
||||
|
||||
//Can either use Player or EntityPlayer object.
|
||||
public static <T> T getNetworkManager(Object player) {
|
||||
return connectionNetworkField.get(getPlayerConnection(player));
|
||||
}
|
||||
|
||||
//Can either use Player or EntityPlayer object.
|
||||
public static <T> T getChannel(Object player) {
|
||||
Object networkManager = getNetworkManager(player);
|
||||
|
||||
return networkChannelField.get(networkManager);
|
||||
}
|
||||
|
||||
//Use the netty Channel class.
|
||||
public static void disconnectChannel(Object channel) {
|
||||
new WrappedClass(channel.getClass()).getMethod("close").invoke(channel);
|
||||
}
|
||||
|
||||
private static WrappedMethod fluidMethod;
|
||||
private static final WrappedMethod getFlowMethod;
|
||||
|
||||
public static ItemStack toBukkitItemStack(Object vanillaItemStack) {
|
||||
return itemStackAsBukkitCopy.invoke(null, vanillaItemStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts AxisAlignedBB Points.
|
||||
* @param aabb AxisAlignedBB
|
||||
* @return double[6] of points.
|
||||
*/
|
||||
public static double[] fromAABB(Object aabb) {
|
||||
double[] boxArray = new double[6];
|
||||
|
||||
boxArray[0] = aBB.get(aabb);
|
||||
boxArray[1] = bBB.get(aabb);
|
||||
boxArray[2] = cBB.get(aabb);
|
||||
boxArray[3] = dBB.get(aabb);
|
||||
boxArray[4] = eBB.get(aabb);
|
||||
boxArray[5] = fBB.get(aabb);
|
||||
|
||||
return boxArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AxisAlignedBB.
|
||||
* @return new AxisAlignedBB
|
||||
*/
|
||||
public static <T> T toAABB(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
|
||||
if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_8)) {
|
||||
return idioticOldStaticConstructorAABB
|
||||
.invoke(null,
|
||||
minX, minY, minZ,
|
||||
maxX, maxY, maxZ);
|
||||
} else return aabbConstructor
|
||||
.newInstance(minX, minY, minZ,
|
||||
maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
//Either bukkit or vanilla world object can be used.
|
||||
public static <T> T getChunkProvider(Object world) {
|
||||
Object vanillaWorld;
|
||||
if(world instanceof World) {
|
||||
vanillaWorld = CraftReflection.getVanillaWorld((World)world);
|
||||
} else vanillaWorld = world;
|
||||
|
||||
return chunkProvider.get(vanillaWorld);
|
||||
}
|
||||
|
||||
public static <T> List<T> getVanillaChunks(World world) {
|
||||
return Arrays.stream(world.getLoadedChunks())
|
||||
.map(c -> (T) CraftReflection.getVanillaChunk(c))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
static {
|
||||
if(ProtocolVersion.getGameVersion().isAbove(ProtocolVersion.V1_7_10)) {
|
||||
iBlockData = Reflections.getNMSClass("IBlockData");
|
||||
blockPos = Reflections.getNMSClass("BlockPosition");
|
||||
blockPosConstructor = blockPos.getConstructor(int.class, int.class, int.class);
|
||||
getBlock = iBlockData.getMethodByType(block.getParent(), 0);
|
||||
blockData = ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_17)
|
||||
? block.getFieldByType(iBlockData.getParent(), 0) : block.getFieldByName("blockData");
|
||||
blockPosConstructor = blockPos.getConstructor(int.class, int.class, int.class);
|
||||
getBlockData = block.getMethodByType(iBlockData.getParent(), 0);
|
||||
aabbConstructor = axisAlignedBB
|
||||
.getConstructor(double.class, double.class, double.class, double.class, double.class, double.class);
|
||||
worldGetType = worldServer.getMethodByType(iBlockData.getParent(), 0, blockPos.getParent());
|
||||
} else {
|
||||
idioticOldStaticConstructorAABB = axisAlignedBB.getMethod("a",
|
||||
double.class, double.class, double.class, double.class, double.class, double.class);
|
||||
worldGetType = worldServer.getMethod("getType", int.class, int.class, int.class);
|
||||
}
|
||||
if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_12)) {
|
||||
getCubes = world.getMethod("a", axisAlignedBB.getParent());
|
||||
|
||||
if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_8)) {
|
||||
//1.7.10 does not have the BlockPosition object yet.
|
||||
addCBoxes = block.getMethod("a", world.getParent(), int.class, int.class, int.class,
|
||||
axisAlignedBB.getParent(), List.class, entity.getParent());
|
||||
methodBlockCollisionBox = block
|
||||
.getMethod("a", world.getParent(), int.class, int.class, int.class);
|
||||
} else {
|
||||
addCBoxes = block.getMethod("a", world.getParent(), blockPos.getParent(), iBlockData.getParent(),
|
||||
axisAlignedBB.getParent(), List.class, entity.getParent());
|
||||
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_9)) {
|
||||
methodBlockCollisionBox = block
|
||||
.getMethod("a", iBlockData.getParent(), world.getParent(), blockPos.getParent());
|
||||
} else methodBlockCollisionBox = block
|
||||
.getMethod("a", world.getParent(), blockPos.getParent(), iBlockData.getParent());
|
||||
}
|
||||
|
||||
getFlowMethod = Reflections.getNMSClass("BlockFluids")
|
||||
.getDeclaredMethodByType(vec3D.getParent(), 0);
|
||||
} else if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_13)) {
|
||||
getCubes = world.getMethod("getCubes", entity.getParent(), axisAlignedBB.getParent());
|
||||
addCBoxes = block.getMethod("a", iBlockData.getParent(), world.getParent(), blockPos.getParent(),
|
||||
axisAlignedBB.getParent(), List.class, entity.getParent(), boolean.class);
|
||||
methodBlockCollisionBox = block
|
||||
.getMethod("a", iBlockData.getParent(), world.getParent(), blockPos.getParent());
|
||||
getFlowMethod = Reflections.getNMSClass("BlockFluids")
|
||||
.getDeclaredMethodByType(vec3D.getParent(), 0);
|
||||
} else {
|
||||
classBlockInfo = ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_16)
|
||||
? Reflections.getNMSClass("BlockBase$Info") : Reflections.getNMSClass("Block$Info");
|
||||
worldReader = Reflections.getNMSClass("IWorldReader");
|
||||
//1.13 and 1.13.1 returns just VoxelShape while 1.13.2+ returns a Stream<VoxelShape>
|
||||
getCubes = ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_18)
|
||||
? worldReader.getMethodByType(List.class, 0, entity.getParent(), axisAlignedBB.getParent())
|
||||
: (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_16) ?
|
||||
worldReader.getMethod("a", entity.getParent(), axisAlignedBB.getParent(),
|
||||
double.class, double.class, double.class)
|
||||
: world.getMethod("c", entity.getParent(), axisAlignedBB.getParent(), Predicate.class));
|
||||
voxelShape = Reflections.getNMSClass("VoxelShape");
|
||||
getCubesFromVoxelShape = voxelShape.getMethodByType(List.class, 0);
|
||||
fluidMethod = world.getMethodByType(Reflections.getNMSClass("Fluid").getParent(), 0, blockPos.getParent());
|
||||
getFlowMethod = Reflections.getNMSClass("Fluid").getMethodByType(vec3D.getParent(), 0);
|
||||
|
||||
if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_19)) {
|
||||
chatComponentText = Reflections.getNMSClass("ChatComponentText");
|
||||
chatComponentTextConst = chatComponentText.getConstructor(String.class);
|
||||
}
|
||||
}
|
||||
|
||||
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_16)) {
|
||||
blockBase = Reflections.getNMSClass("BlockBase");
|
||||
}
|
||||
if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_9)) {
|
||||
activeItemField = entityHuman.getFieldByType(itemStack.getParent(), 0);
|
||||
} else {
|
||||
activeItemField = entityLiving.getFieldByType(itemStack.getParent(), 0);
|
||||
}
|
||||
|
||||
canDestroyMethod = ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_16)
|
||||
? playerInventory.getMethod("b",
|
||||
ProtocolVersion.getGameVersion().isAbove(ProtocolVersion.V1_8_9)
|
||||
? iBlockData.getParent() : itemClass.getParent())
|
||||
: itemStack.getMethodByType(boolean.class, 0, iBlockData.getParent());
|
||||
if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_17)) {
|
||||
frictionFactor = (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_16)
|
||||
? block : blockBase).getFieldByName("frictionFactor");
|
||||
} else frictionFactor = blockBase.getFieldByType(float.class, 1);
|
||||
strength = ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_17)
|
||||
? blockBase.getFieldByType(float.class, 0)
|
||||
: (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_16)
|
||||
? block.getFieldByName("strength") : blockBase.getFieldByName("durability"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Created by Justin Heflin on 4/19/18 8:21 PM
|
||||
* Copyright (c) 2018.
|
||||
*
|
||||
* Can be redistributed non commercially as long as credit is given to original copyright owner.
|
||||
*
|
||||
* last modified: 4/19/18 7:22 PM
|
||||
*/
|
||||
package dev.brighten.ac.utils.reflections.types;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class WrappedClass {
|
||||
private final Class parent;
|
||||
private final Cache<String, WrappedMethod> methodCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(2, TimeUnit.MINUTES).maximumSize(200L).build();
|
||||
private final Cache<String, WrappedField> fieldCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(2, TimeUnit.MINUTES).maximumSize(200L).build();
|
||||
|
||||
public WrappedClass(Class parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public WrappedField getFieldByName(String name) {
|
||||
Optional<WrappedField> cached = Optional.ofNullable(fieldCache.getIfPresent(name));
|
||||
|
||||
if(cached.isPresent()) {
|
||||
return cached.get();
|
||||
}
|
||||
|
||||
Field tempField = null;
|
||||
|
||||
Class<?> clazz = this.parent;
|
||||
|
||||
do {
|
||||
for (Field field : this.parent.getDeclaredFields()) {
|
||||
if (field.getName().equals(name)) {
|
||||
tempField = field;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tempField != null) {
|
||||
tempField.setAccessible(true);
|
||||
WrappedField toReturn = new WrappedField(this, tempField);
|
||||
fieldCache.put(name, toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
if(clazz.equals(this.parent.getSuperclass())) {
|
||||
clazz = null;
|
||||
} else clazz = this.parent.getSuperclass();
|
||||
|
||||
} while(clazz != null && !clazz.getName().contains("Object"));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public WrappedConstructor getConstructor(Class<?>... types) {
|
||||
try {
|
||||
return new WrappedConstructor(this, this.parent.getDeclaredConstructor(types));
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<WrappedField> getFields(Predicate<WrappedField>... parameters) {
|
||||
return getFields()
|
||||
.stream()
|
||||
.filter(field -> Arrays.stream(parameters).allMatch(param -> param.test(field)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<WrappedMethod> getMethods(Predicate<WrappedMethod>... parameters) {
|
||||
return getMethods()
|
||||
.stream()
|
||||
.filter(method -> Arrays.stream(parameters).allMatch(param -> param.test(method)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<WrappedConstructor> getConstructors() {
|
||||
return Arrays.stream(this.parent.getConstructors())
|
||||
.map(construct -> new WrappedConstructor(this, construct))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public WrappedConstructor getConstructor() {
|
||||
val optional = Arrays.stream(this.parent.getConstructors())
|
||||
.filter(cons -> cons.getParameterCount() == 0).findFirst();
|
||||
return optional.map(constructor -> new WrappedConstructor(this, constructor)).orElse(null);
|
||||
}
|
||||
|
||||
public WrappedConstructor getConstructorAtIndex(int index) {
|
||||
return new WrappedConstructor(this, this.parent.getConstructors()[index]);
|
||||
}
|
||||
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annClass) {
|
||||
return parent.isAnnotationPresent(annClass);
|
||||
}
|
||||
|
||||
public boolean hasMethod(String name, Class<?>... args) {
|
||||
for (Method declaredMethod : parent.getDeclaredMethods()) {
|
||||
if(declaredMethod.getName().equals(name)
|
||||
&& Arrays.equals(args, declaredMethod.getParameterTypes()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T> T getAnnotation(Class<T> annClass) {
|
||||
return (T) parent.getDeclaredAnnotation(annClass);
|
||||
}
|
||||
|
||||
public WrappedField getFieldByType(Class<?> type, int index) {
|
||||
String key = type.getName() + ";;" + index;
|
||||
Optional<WrappedField> cached = Optional.ofNullable(fieldCache.getIfPresent(key));
|
||||
|
||||
if(cached.isPresent()) {
|
||||
return cached.get();
|
||||
}
|
||||
|
||||
Class<?> clazz = this.parent;
|
||||
|
||||
do {
|
||||
for (Field[] fields : new Field[][]{clazz.getDeclaredFields()}) {
|
||||
for (Field field : fields) {
|
||||
if (type.isAssignableFrom(field.getType()) && index-- <= 0) {
|
||||
WrappedField toReturn = new WrappedField(this, field);
|
||||
|
||||
fieldCache.put(key, toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(clazz.equals(this.parent.getSuperclass())) {
|
||||
clazz = null;
|
||||
} else clazz = this.parent.getSuperclass();
|
||||
|
||||
} while(clazz != null && !clazz.getName().contains("Object"));
|
||||
throw new NullPointerException("Could not find field with type " + type.getSimpleName() + " at index " + index);
|
||||
}
|
||||
|
||||
public WrappedField getFirstFieldByType(Class<?> type) {
|
||||
return this.getFieldByType(type, 0);
|
||||
}
|
||||
|
||||
public WrappedMethod[] getDeclaredMethods() {
|
||||
return Arrays.stream(getParent().getDeclaredMethods())
|
||||
.map(m -> new WrappedMethod(this, m))
|
||||
.toArray(WrappedMethod[]::new);
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(WrappedClass wrapped) {
|
||||
return wrapped.getParent().isAssignableFrom(getParent());
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(Class<?> paramClass) {
|
||||
return getParent().isAssignableFrom(paramClass);
|
||||
}
|
||||
|
||||
public WrappedMethod getMethod(String name, Class... parameters) {
|
||||
String key = name + ";;" + Arrays.stream(parameters).map(Class::getName)
|
||||
.collect(Collectors.joining(","));
|
||||
Optional<WrappedMethod> cached = Optional.ofNullable(methodCache.getIfPresent(key));
|
||||
|
||||
if(cached.isPresent()) return cached.get();
|
||||
else {
|
||||
for (Method method : this.parent.getDeclaredMethods()) {
|
||||
if (!method.getName().equals(name) || parameters.length != method.getParameterTypes().length) {
|
||||
continue;
|
||||
}
|
||||
boolean same = true;
|
||||
for (int x = 0; x < method.getParameterTypes().length; x++) {
|
||||
if (method.getParameterTypes()[x] != parameters[x]) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same) {
|
||||
WrappedMethod toReturn = new WrappedMethod(this, method);
|
||||
methodCache.put(key, toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
for (Method method : this.parent.getMethods()) {
|
||||
if (!method.getName().equals(name) || parameters.length != method.getParameterTypes().length) {
|
||||
continue;
|
||||
}
|
||||
boolean same = true;
|
||||
for (int x = 0; x < method.getParameterTypes().length; x++) {
|
||||
if (method.getParameterTypes()[x] != parameters[x]) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same) {
|
||||
WrappedMethod toReturn = new WrappedMethod(this, method);
|
||||
methodCache.put(key, toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NullPointerException("Could not find method in " + getParent().getSimpleName() + " with name " + name);
|
||||
}
|
||||
|
||||
public WrappedMethod getDeclaredMethodByType(Class<?> type, int index) {
|
||||
String key = "declared:" + type.getName() + ";;" + index;
|
||||
Optional<WrappedMethod> cached = Optional.ofNullable(methodCache.getIfPresent(key));
|
||||
|
||||
if(cached.isPresent()) {
|
||||
return cached.get();
|
||||
}
|
||||
|
||||
for (Method method : this.parent.getDeclaredMethods()) {
|
||||
if(type.isAssignableFrom(method.getReturnType()) && index-- <= 0) {
|
||||
WrappedMethod toReturn = new WrappedMethod(this, method);
|
||||
|
||||
methodCache.put(key, toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
throw new NullPointerException("Could not find method with return type " + type.getSimpleName() + " at index " + index);
|
||||
}
|
||||
|
||||
public WrappedMethod getMethodByType(Class<?> type, int index) throws NullPointerException {
|
||||
String key = "nondeclared:" + type.getName() + ";;" + index;
|
||||
Optional<WrappedMethod> cached = Optional.ofNullable(methodCache.getIfPresent(key));
|
||||
|
||||
if(cached.isPresent()) {
|
||||
return cached.get();
|
||||
}
|
||||
|
||||
for (Method method : this.parent.getMethods()) {
|
||||
if(type.isAssignableFrom(method.getReturnType()) && index-- <= 0) {
|
||||
WrappedMethod toReturn = new WrappedMethod(this, method);
|
||||
|
||||
methodCache.put(key, toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
throw new NullPointerException("Could not find method with return type " + type.getName()
|
||||
+ " at index " + index);
|
||||
}
|
||||
|
||||
public WrappedMethod getMethodByType(Class<?> type, int index, Class<?>... parameters) throws NullPointerException {
|
||||
for (Method method : this.parent.getMethods()) {
|
||||
if(type.isAssignableFrom(method.getReturnType()) && parameters.length == method.getParameterCount()) {
|
||||
boolean same = true;
|
||||
for (int x = 0; x < method.getParameterTypes().length; x++) {
|
||||
if (method.getParameterTypes()[x] != parameters[x]) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(same && index-- <= 0)
|
||||
return new WrappedMethod(this, method);
|
||||
}
|
||||
}
|
||||
throw new NullPointerException("Could not find method with return type " + type.getName()
|
||||
+ " at index " + index);
|
||||
}
|
||||
|
||||
public WrappedMethod getDeclaredMethodByType(Class<?> type, int index, Class<?>... parameters) throws NullPointerException {
|
||||
for (Method method : this.parent.getDeclaredMethods()) {
|
||||
if(type.isAssignableFrom(method.getReturnType()) && parameters.length == method.getParameterCount()) {
|
||||
boolean same = true;
|
||||
for (int x = 0; x < method.getParameterTypes().length; x++) {
|
||||
if (method.getParameterTypes()[x] != parameters[x]) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(same && index-- <= 0)
|
||||
return new WrappedMethod(this, method);
|
||||
}
|
||||
}
|
||||
throw new NullPointerException("Could not find method with return type " + type.getName()
|
||||
+ " at index " + index);
|
||||
}
|
||||
|
||||
//We have a separate method instead of just calling WrappedClass#getMethods(boolean, boolean)
|
||||
//for performance reasons.
|
||||
public List<WrappedMethod> getMethods() {
|
||||
return Arrays.stream(parent.getMethods())
|
||||
.map(method -> new WrappedMethod(this, method))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<WrappedMethod> getMethods(boolean noStatic, boolean noFinal) {
|
||||
return Arrays.stream(parent.getMethods())
|
||||
.filter(method ->
|
||||
(!noFinal || !Modifier.isFinal(method.getModifiers())
|
||||
&& (!noStatic || !Modifier.isStatic(method.getModifiers()))))
|
||||
.map(method -> new WrappedMethod(this, method))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
public List<WrappedMethod> getMethods(boolean noStatic) {
|
||||
return getMethods(noStatic, false);
|
||||
}
|
||||
|
||||
//We have a separate method instead of just calling WrappedClass#getFields(boolean, boolean)
|
||||
// or performance reasons.
|
||||
public List<WrappedField> getFields() {
|
||||
return Arrays.stream(parent.getDeclaredFields())
|
||||
.map(field -> new WrappedField(this, field))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<WrappedField> getFields(boolean noStatic, boolean noFinal) {
|
||||
return Arrays.stream(parent.getDeclaredFields())
|
||||
.filter(field ->
|
||||
(!noFinal || !Modifier.isFinal(field.getModifiers())
|
||||
&& (!noStatic || !Modifier.isStatic(field.getModifiers()))))
|
||||
.map(field -> new WrappedField(this, field))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<WrappedField> getFields(boolean noStatic) {
|
||||
return getFields(noStatic, false);
|
||||
}
|
||||
|
||||
public Enum getEnum(String name) {
|
||||
return Enum.valueOf(this.parent, name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Created by Justin Heflin on 4/19/18 8:21 PM
|
||||
* Copyright (c) 2018.
|
||||
*
|
||||
* Can be redistributed non commercially as long as credit is given to original copyright owner.
|
||||
*
|
||||
* last modified: 4/19/18 7:22 PM
|
||||
*/
|
||||
package dev.brighten.ac.utils.reflections.types;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class WrappedConstructor {
|
||||
private final WrappedClass parent;
|
||||
private Constructor constructor;
|
||||
|
||||
public <T> T newInstance(Object... args) {
|
||||
try {
|
||||
constructor.setAccessible(true);
|
||||
return (T) constructor.newInstance(args);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T newInstance() {
|
||||
try {
|
||||
constructor.setAccessible(true);
|
||||
return (T) constructor.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Created by Justin Heflin on 4/19/18 8:21 PM
|
||||
* Copyright (c) 2018.
|
||||
*
|
||||
* Can be redistributed non commercially as long as credit is given to original copyright owner.
|
||||
*
|
||||
* last modified: 4/19/18 7:22 PM
|
||||
*/
|
||||
package dev.brighten.ac.utils.reflections.types;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@Getter
|
||||
public class WrappedField {
|
||||
private final WrappedClass parent;
|
||||
private final Field field;
|
||||
private final Class<?> type;
|
||||
|
||||
public WrappedField(WrappedClass parent, Field field) {
|
||||
this.parent = parent;
|
||||
this.field = field;
|
||||
this.type = field.getType();
|
||||
this.field.setAccessible(true);
|
||||
}
|
||||
|
||||
public <T> T get(Object parent) {
|
||||
try {
|
||||
return (T) this.field.get(parent);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(Object parent, Object value) {
|
||||
try {
|
||||
this.field.setAccessible(true);
|
||||
this.field.set(parent, value);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annClass) {
|
||||
return field.isAnnotationPresent(annClass);
|
||||
}
|
||||
|
||||
public <T> T getAnnotation(Class<? extends Annotation> annClass) {
|
||||
return (T) field.getAnnotation(annClass);
|
||||
}
|
||||
|
||||
public int getModifiers() {
|
||||
return this.field.getModifiers();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Created by Justin Heflin on 4/19/18 8:21 PM
|
||||
* Copyright (c) 2018.
|
||||
*
|
||||
* Can be redistributed non commercially as long as credit is given to original copyright owner.
|
||||
*
|
||||
* last modified: 4/19/18 7:22 PM
|
||||
*/
|
||||
package dev.brighten.ac.utils.reflections.types;
|
||||
|
||||
import dev.brighten.ac.utils.objects.MethodFunction;
|
||||
import dev.brighten.ac.utils.objects.QuadFunction;
|
||||
import dev.brighten.ac.utils.objects.TriFunction;
|
||||
import dev.brighten.ac.utils.reflections.Reflections;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Getter
|
||||
public class WrappedMethod {
|
||||
private final WrappedClass parent;
|
||||
private final Method method;
|
||||
private final String name;
|
||||
private MethodFunction mfunc;
|
||||
private final List<Class<?>> parameters;
|
||||
private final boolean isVoid;
|
||||
|
||||
public WrappedMethod(WrappedClass parent, Method method) {
|
||||
this.name = method.getName();
|
||||
this.method = method;
|
||||
this.parent = parent;
|
||||
this.parameters = Arrays.asList(method.getParameterTypes());
|
||||
|
||||
try {
|
||||
int length = method.getParameterCount();
|
||||
switch(length) {
|
||||
case 0:
|
||||
Function func = Reflections.createMethodLambda(method);
|
||||
mfunc = new MethodFunction(method, func);
|
||||
break;
|
||||
case 1:
|
||||
BiFunction bifunc = Reflections.createMethodLambda(method);
|
||||
mfunc = new MethodFunction(method, bifunc);
|
||||
break;
|
||||
case 2:
|
||||
TriFunction trifunc = Reflections.createMethodLambda(method);
|
||||
mfunc = new MethodFunction(method, trifunc);
|
||||
break;
|
||||
case 3:
|
||||
QuadFunction quadFunc = Reflections.createMethodLambda(method);
|
||||
mfunc = new MethodFunction(method, quadFunc);
|
||||
break;
|
||||
default:
|
||||
method.setAccessible(true);
|
||||
mfunc = new MethodFunction(method);
|
||||
break;
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
isVoid = method.getReturnType().equals(void.class);
|
||||
}
|
||||
|
||||
public <T> T invoke(Object object, Object... args) {
|
||||
return mfunc.invokeMethod(object, args);
|
||||
}
|
||||
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
|
||||
return method.isAnnotationPresent(annotation);
|
||||
}
|
||||
|
||||
public Parameter[] getParameters() {
|
||||
return method.getParameters();
|
||||
}
|
||||
|
||||
public Class<?>[] getParameterTypes() {
|
||||
return method.getParameterTypes();
|
||||
}
|
||||
|
||||
public int getModifiers() {
|
||||
return this.method.getModifiers();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user