Project files

This commit is contained in:
Dawson
2022-08-08 14:53:33 -04:00
parent 26813fc4d4
commit 58b49a8976
134 changed files with 15530 additions and 0 deletions
@@ -0,0 +1,196 @@
package dev.brighten.ac;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.BukkitCommandManager;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.packet.listener.PacketProcessor;
import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.objects.RemoteClassLoader;
import dev.brighten.ac.utils.reflections.Reflections;
import dev.brighten.ac.utils.reflections.types.WrappedClass;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@Getter
@Init
public class Anticheat extends JavaPlugin {
public static Anticheat INSTANCE;
private ScheduledExecutorService scheduler;
private PacketProcessor packetProcessor;
private BukkitCommandManager commandManager;
private int currentTicks;
@ConfigSetting(path = "logging", name = "verbose")
private static boolean verboseLogging = true;
public void onEnable() {
INSTANCE = this;
scheduler = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
packetProcessor = new PacketProcessor();
HandlerAbstract.init();
commandManager = new BukkitCommandManager(this);
initializeScanner(getClass(), this,
null,
true,
true);
new BukkitRunnable() {
public void run() {
currentTicks++;
}
}.runTaskTimer(this, 1L, 1L);
}
public void onDisable() {
scheduler.shutdown();
commandManager.unregisterCommands();
HandlerList.unregisterAll(this);
packetProcessor.shutdown();
}
public void initializeScanner(Class<? extends Plugin> mainClass, Plugin plugin, ClassLoader loader,
boolean loadListeners, boolean loadCommands) {
initializeScanner(mainClass, plugin, loader, ClassScanner.scanFile(null, mainClass), loadListeners,
loadCommands);
}
public void initializeScanner(Class<? extends Plugin> mainClass, Plugin plugin, ClassLoader loader, Set<String> names,
boolean loadListeners, boolean loadCommands) {
names.stream()
.map(name -> {
if(loader != null) {
try {
if(loader instanceof RemoteClassLoader) {
return new WrappedClass(((RemoteClassLoader)loader).findClass(name));
} else
return new WrappedClass(Class.forName(name, true, loader));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
} else {
return Reflections.getClass(name);
}
})
.filter(c -> {
if(c == null) return false;
Init init = c.getAnnotation(Init.class);
String[] required = init.requirePlugins();
if(required.length > 0) {
if(init.requireType() == Init.RequireType.ALL) {
return Arrays.stream(required)
.allMatch(name -> {
if(name.contains("||")) {
return Arrays.stream(name.split("\\|\\|"))
.anyMatch(n2 -> Bukkit.getPluginManager().isPluginEnabled(n2));
} else if(name.contains("&&")) {
return Arrays.stream(name.split("\\|\\|"))
.allMatch(n2 -> Bukkit.getPluginManager().isPluginEnabled(n2));
} else return Bukkit.getPluginManager().isPluginEnabled(name);
});
} else {
return Arrays.stream(required)
.anyMatch(name -> {
if(name.contains("||")) {
return Arrays.stream(name.split("\\|\\|"))
.anyMatch(n2 -> Bukkit.getPluginManager().isPluginEnabled(n2));
} else if(name.contains("&&")) {
return Arrays.stream(name.split("\\|\\|"))
.allMatch(n2 -> Bukkit.getPluginManager().isPluginEnabled(n2));
} else return Bukkit.getPluginManager().isPluginEnabled(name);
});
}
}
return true;
})
.sorted(Comparator.comparing(c ->
c.getAnnotation(Init.class).priority().getPriority(), Comparator.reverseOrder()))
.forEach(c -> {
Object obj = c.getParent().equals(mainClass) ? plugin : c.getConstructor().newInstance();
Init annotation = c.getAnnotation(Init.class);
if(loadListeners) {
if(obj instanceof Listener) {
Bukkit.getPluginManager().registerEvents((Listener)obj, plugin);
alog(true,"&7Registered Bukkit listener &e"
+ c.getParent().getSimpleName() + "&7.");
}
}
if(obj instanceof BaseCommand) {
alog(true,"&7Found BaseCommand for class &e"
+ c.getParent().getSimpleName() + "&7! Registering commands...");
commandManager.registerCommand((BaseCommand)obj);
}
for (WrappedMethod method : c.getMethods()) {
if(method.getMethod().isAnnotationPresent(Invoke.class)) {
alog(true,"&7Invoking method &e" + method.getName() + " &7in &e"
+ c.getClass().getSimpleName() + "&7...");
method.invoke(obj);
}
}
for (WrappedField field : c.getFields()) {
if(field.isAnnotationPresent(ConfigSetting.class)) {
ConfigSetting setting = field.getAnnotation(ConfigSetting.class);
String name = setting.name().length() > 0
? setting.name()
: field.getField().getName();
alog(true, "&7Found ConfigSetting &e%s &7(default=&f%s&7).",
field.getField().getName(),
(setting.hide() ? "HIDDEN" : field.get(obj)));
FileConfiguration config = plugin.getConfig();
if(config.get((setting.path().length() > 0 ? setting.path() + "." : "") + name) == null) {
alog(true,"&7Value not set in config! Setting value...");
config.set((setting.path().length() > 0 ? setting.path() + "." : "") + name, field.get(obj));
plugin.saveConfig();
} else {
Object configObj = config.get((setting.path().length() > 0 ? setting.path() + "." : "") + name);
alog(true, "&7Set field to value &e%s&7.",
(setting.hide() ? "HIDDEN" : configObj));
field.set(obj, configObj);
}
}
}
});
}
public void alog(String log, Object... values) {
alog(false, log, values);
}
public void alog(boolean verbose, String log, Object... values) {
if(!verbose || verboseLogging) {
if(values.length > 0)
MiscUtils.printToConsole(log, values);
else MiscUtils.printToConsole(log);
}
}
}
@@ -0,0 +1,41 @@
package dev.brighten.ac.listener;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
import dev.brighten.ac.utils.Init;
import dev.brighten.ac.utils.RunUtils;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
@Init
public class JoinListener implements Listener {
public JoinListener() {
Anticheat.INSTANCE.getPacketProcessor().processAsync(Anticheat.INSTANCE, EventPriority.NORMAL, event -> {
if(event.getType().equals(PacketType.FLYING)) {
WPacketPlayInFlying flying = Anticheat.INSTANCE.getPacketProcessor().getPacketConverter()
.processFlying(event.getPacket());
event.getPlayer().sendMessage(flying.isLooked() + ";" + flying.isMoved() + ";"
+ flying.isOnGround() + ":" + flying.getX() + ":" + flying.getYaw());
}
});
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
Bukkit.broadcastMessage("Joined");
RunUtils.taskLater(() -> HandlerAbstract.getHandler().add(event.getPlayer()), 4L);
}
@EventHandler
public void onLeave(PlayerQuitEvent event) {
HandlerAbstract.getHandler().remove(event.getPlayer());
}
}
@@ -0,0 +1,141 @@
/*
* 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"),
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,33 @@
package dev.brighten.ac.packet.handler;
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.WrappedField;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public abstract class HandlerAbstract {
static WrappedClass classNetworkManager = Reflections.getNMSClass("NetworkManager");
static WrappedField
fieldNetworkManager = Reflections.getNMSClass("PlayerConnection").getFieldByName("networkManager"),
fieldPlayerConnection = Reflections.getNMSClass("EntityPlayer").getFieldByName("playerConnection");
static String handlerName = "brigten-ac-packets";
@Getter
private static HandlerAbstract handler;
public static void init() {
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_8)) {
handler = new ModernHandler();
} else handler = new LegacyHandler();
Bukkit.getOnlinePlayers().forEach(handler::add);
}
public abstract void add(Player player);
public abstract void remove(Player player);
}
@@ -0,0 +1,102 @@
package dev.brighten.ac.packet.handler;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.utils.reflections.types.WrappedClass;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import lombok.AllArgsConstructor;
import net.minecraft.server.v1_7_R4.NetworkManager;
import net.minecraft.server.v1_7_R4.PlayerConnection;
import net.minecraft.util.com.google.common.collect.MapMaker;
import net.minecraft.util.io.netty.channel.Channel;
import net.minecraft.util.io.netty.channel.ChannelDuplexHandler;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
import net.minecraft.util.io.netty.channel.ChannelPromise;
import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class LegacyHandler extends HandlerAbstract {
private final Map<String, Channel> channelCache = new HashMap<>();
private Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
private static WrappedField fieldChannel = new WrappedClass(NetworkManager.class).getFieldByType(Channel.class, 0);
@Override
public void add(Player player) {
try {
Channel channel = getChannel(player);
PacketHandler handler = (PacketHandler) channel.pipeline().get(handlerName);
if(handler == null) {
handler = new PacketHandler(player);
ChannelHandlerContext context = channel.pipeline().context("packet_handler");
if(context != null) {
channel.pipeline().addBefore("packet_handler", handlerName, handler);
uninjectedChannels.remove(channel);
} else uninjectedChannels.add(channel);
}
} catch(IllegalArgumentException e) {
e.printStackTrace();
}
}
@Override
public void remove(Player player) {
Channel channel = getChannel(player);
if(Anticheat.INSTANCE.isEnabled()) {
uninjectedChannels.add(channel);
}
channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName));
}
private Channel getChannel(Player player) {
synchronized (channelCache) {
return channelCache.computeIfAbsent(player.getName(), name -> {
PlayerConnection connection = ((CraftPlayer)player).getHandle().playerConnection;
return fieldChannel.get(connection.networkManager);
});
}
}
@AllArgsConstructor
private static class PacketHandler extends ChannelDuplexHandler {
private Player player;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String name = msg.getClass().getName();
int index = name.lastIndexOf(".");
String packetName = name.substring(index + 1);
boolean allowed = Anticheat.INSTANCE.getPacketProcessor().call(player, msg, PacketType
.getByPacketId(packetName).orElse(PacketType.NONE));
if(allowed) {
super.channelRead(ctx, msg);
}
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
String name = msg.getClass().getName();
int index = name.lastIndexOf(".");
String packetName = name.substring(index + 1);
boolean allowed = Anticheat.INSTANCE.getPacketProcessor().call(player, msg, PacketType
.getByPacketId(packetName).orElse(PacketType.NONE));
if(allowed) {
super.write(ctx, msg, promise);
}
}
}
}
@@ -0,0 +1,102 @@
package dev.brighten.ac.packet.handler;
import com.google.common.collect.MapMaker;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.utils.reflections.Reflections;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import lombok.AllArgsConstructor;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ModernHandler extends HandlerAbstract {
private final Map<String, Channel> channelCache = new HashMap<>();
private Set<Channel> uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
private static WrappedField fieldChannel = classNetworkManager.getFieldByType(Channel.class, 0);
private static WrappedMethod methodHandle = Reflections.getCBClass("entity.CraftPlayer")
.getMethod("getHandle");
@Override
public void add(Player player) {
try {
Channel channel = getChannel(player);
PacketHandler handler = (PacketHandler) channel.pipeline().get(handlerName);
if(handler == null) {
handler = new PacketHandler(player);
ChannelHandlerContext context = channel.pipeline().context("packet_handler");
if(context != null) {
channel.pipeline().addBefore("packet_handler", handlerName, handler);
uninjectedChannels.remove(channel);
} else uninjectedChannels.add(channel);
}
} catch(IllegalArgumentException e) {
e.printStackTrace();
}
}
@Override
public void remove(Player player) {
Channel channel = getChannel(player);
if (Anticheat.INSTANCE.isEnabled()) {
uninjectedChannels.add(channel);
}
channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName));
}
private Channel getChannel(Player player) {
synchronized (channelCache) {
return channelCache.computeIfAbsent(player.getName(), name -> {
Object manager = fieldNetworkManager.get(fieldPlayerConnection.get(methodHandle.invoke(player)));
return fieldChannel.get(manager);
});
}
}
@AllArgsConstructor
private static class PacketHandler extends ChannelDuplexHandler {
private Player player;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
String name = msg.getClass().getName();
int index = name.lastIndexOf(".");
String packetName = name.substring(index + 1);
boolean allowed = Anticheat.INSTANCE.getPacketProcessor().call(player, msg, PacketType
.getByPacketId(packetName).orElse(PacketType.NONE));
if(allowed) {
super.channelRead(ctx, msg);
}
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
String name = msg.getClass().getName();
int index = name.lastIndexOf(".");
String packetName = name.substring(index + 1);
boolean allowed = Anticheat.INSTANCE.getPacketProcessor().call(player, msg, PacketType
.getByPacketId(packetName).orElse(PacketType.NONE));
if(allowed) {
super.write(ctx, msg, promise);
}
}
}
}
@@ -0,0 +1,18 @@
package dev.brighten.ac.packet.listener;
import dev.brighten.ac.packet.listener.functions.PacketListener;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.bukkit.event.EventPriority;
import org.bukkit.plugin.Plugin;
import java.util.UUID;
@RequiredArgsConstructor
@Getter
class ListenerEntry {
private final Plugin plugin;
private final EventPriority priority;
private final PacketListener listener;
private long id = UUID.randomUUID().getMostSignificantBits();
}
@@ -0,0 +1,18 @@
package dev.brighten.ac.packet.listener;
import dev.brighten.ac.packet.wrapper.PacketType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.bukkit.entity.Player;
@RequiredArgsConstructor
@Getter
public class PacketInfo {
private final Player player;
private final Object packet;
private final PacketType type;
private final long timestamp;
@Setter
private boolean cancelled;
}
@@ -0,0 +1,189 @@
package dev.brighten.ac.packet.listener;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.packet.listener.functions.PacketListener;
import dev.brighten.ac.packet.wrapper.PacketConverter;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.packet.wrapper.impl.Processor_18;
import dev.brighten.ac.utils.MiscUtils;
import dev.brighten.ac.utils.RunUtils;
import lombok.Getter;
import lombok.val;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventPriority;
import org.bukkit.plugin.Plugin;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/*
An asynchronous processor for packets.
*/
public class PacketProcessor {
private final Map<PacketType, List<ListenerEntry>>
processors = new HashMap<>();
private final Map<PacketType, List<ListenerEntry>>
asyncProcessors = new HashMap<>();
@Getter
private final PacketConverter packetConverter;
public PacketProcessor() {
switch (ProtocolVersion.getGameVersion()) {
case V1_8_9: {
packetConverter = new Processor_18();
break;
}
default: {
packetConverter = null;
break;
}
}
}
public PacketListener process(Plugin plugin, PacketListener listener, PacketType... types) {
return process(plugin, EventPriority.NORMAL, listener, types);
}
public PacketListener process(Plugin plugin, EventPriority priority, PacketListener listener, PacketType... types) {
ListenerEntry entry = new ListenerEntry(plugin, priority, listener);
synchronized (processors) {
for (PacketType type : types) {
processors.compute(type, (key, list) -> {
if(list == null) list = new CopyOnWriteArrayList<>();
list.add(entry);
list.sort(Comparator.comparing(t -> t.getPriority().getSlot()));
return list;
});
}
}
return listener;
}
public PacketListener process(Plugin plugin, EventPriority priority, PacketListener listener) {
return process(plugin, priority, listener, PacketType.NONE);
}
public PacketListener processAsync(Plugin plugin, PacketListener listener, PacketType... types) {
return processAsync(plugin, EventPriority.NORMAL, listener, types);
}
public PacketListener processAsync(Plugin plugin, EventPriority priority, PacketListener listener) {
return processAsync(plugin, priority, listener, PacketType.NONE);
}
public PacketListener processAsync(Plugin plugin, EventPriority priority, PacketListener listener,
PacketType... types) {
ListenerEntry entry = new ListenerEntry(plugin, priority, listener);
synchronized (asyncProcessors) {
for (PacketType type : types) {
asyncProcessors.compute(type, (key, list) -> {
if(list == null) list = new CopyOnWriteArrayList<>();
list.add(entry);
list.sort(Comparator.comparing(t -> t.getPriority().getSlot()));
return list;
});
}
}
return listener;
}
public boolean removeListener(PacketListener listener) {
boolean removedListener = false;
synchronized (processors) {
int iterations = 0;
for (List<ListenerEntry> list : processors.values()) {
for (Iterator<ListenerEntry> it = list.iterator(); it.hasNext(); ) {
ListenerEntry entry = it.next();
iterations++;
if(entry.getListener() == listener) {
it.remove();
Anticheat.INSTANCE.getLogger().info("Removed listener in " + iterations + " iterations.");
removedListener = true;
break;
}
}
}
}
synchronized (asyncProcessors) {
int iterations = 0;
for (List<ListenerEntry> list : processors.values()) {
for (Iterator<ListenerEntry> it = list.iterator(); it.hasNext(); ) {
ListenerEntry entry = it.next();
iterations++;
if(entry.getListener() == listener) {
it.remove();
Anticheat.INSTANCE.getLogger().info("Removed listener in " + iterations + " iterations.");
removedListener = true;
break;
}
}
}
}
return removedListener;
}
public void removeListeners(Plugin plugin) {
synchronized (processors) {
for (List<ListenerEntry> list : processors.values()) {
list.removeIf(entry -> entry.getPlugin().getName().equals(plugin.getName()));
}
}
synchronized (asyncProcessors) {
for (List<ListenerEntry> list : asyncProcessors.values()) {
list.removeIf(entry -> entry.getPlugin().getName().equals(plugin.getName()));
}
}
}
public boolean call(Player player, Object packet, PacketType type) {
if(packet == null) return false;
PacketInfo info = new PacketInfo(player, packet, type, System.currentTimeMillis());
if(asyncProcessors.containsKey(type) || asyncProcessors.containsKey(PacketType.NONE)) {
RunUtils.taskAsync(() -> {
val list = MiscUtils.combine(asyncProcessors.get(type),
asyncProcessors.get(PacketType.NONE));
for (ListenerEntry tuple : list) {
tuple.getListener().onEvent(info);
}
});
}
if(processors.containsKey(type)) {
val list = MiscUtils.combine(processors.get(type), processors.get(PacketType.NONE));
boolean cancelled = false;
for (ListenerEntry tuple : list) {
try {
tuple.getListener().onEvent(info);
if(info.isCancelled()) {
cancelled = true;
}
} catch(Exception e) {
e.printStackTrace();
}
}
return !cancelled;
} return true;
}
public void shutdown() {
processors.clear();
asyncProcessors.clear();
Bukkit.getOnlinePlayers().forEach(HandlerAbstract.getHandler()::remove);
}
}
@@ -0,0 +1,8 @@
package dev.brighten.ac.packet.listener.functions;
import dev.brighten.ac.packet.listener.PacketInfo;
@FunctionalInterface
public interface PacketListener {
void onEvent(PacketInfo info);
}
@@ -0,0 +1,4 @@
package dev.brighten.ac.packet.packet;
public interface WPacket {
}
@@ -0,0 +1,9 @@
package dev.brighten.ac.packet.wrapper;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity;
public interface PacketConverter {
WPacketPlayInFlying processFlying(Object object);
WPacketPlayInUseEntity processUseEntity(Object object);
}
@@ -0,0 +1,82 @@
package dev.brighten.ac.packet.wrapper;
import lombok.Getter;
import java.util.Optional;
public enum PacketType {
FLYING("PacketPlayInFlying", "PacketPlayInPosition", "PacketPlayInPositionLook",
"PacketPlayInLook", "PacketPlayInFlying$PacketPlayInPositionLook",
"PacketPlayInFlying$PacketPlayInLook", "PacketPlayInFlying$PacketPlayInPosition"),
USE_ENTITY("PacketPlayInUseEntity"),
NONE();
PacketType(String... packetIds) {
this.packetId = packetIds;
}
@Getter
private final String[] packetId;
public static Optional<PacketType> getByPacketId(String packetId) {
for (PacketType value : values()) {
for (String s : value.packetId) {
if(s.equals(packetId))
return Optional.of(value);
}
}
return Optional.empty();
}
public static class ServerOld {
private static final String SERVER = "PacketPlayOut";
public static final String KEEP_ALIVE = SERVER + "KeepAlive";
public static final String CHAT = SERVER + "Chat";
public static final String POSITION = SERVER + "Position";
public static final String TRANSACTION = SERVER + "Transaction";
public static final String NAMED_ENTITY_SPAWN = SERVER + "NamedEntitySpawn";
public static final String SPAWN_ENTITY_LIVING = SERVER + "SpawnEntityLiving";
public static final String SPAWN_ENTITY = SERVER + "SpawnEntity";
public static final String CUSTOM_PAYLOAD = SERVER + "CustomPayload";
public static final String ABILITIES = SERVER + "Abilities";
public static final String ENTITY_METADATA = SERVER + "EntityMetadata";
public static final String ENTITY_VELOCITY = SERVER + "EntityVelocity";
public static final String ENTITY_DESTROY = SERVER + "EntityDestroy";
public static final String SCOREBOARD_DISPLAY_OBJECTIVE = "ScoreboardDisplayObjective";
public static final String SCOREBOARD_OBJECTIVE = "ScoreboardObjective";
public static final String ENTITY_HEAD_ROTATION = SERVER + "EntityHeadRotation";
public static final String ENTITY_TELEPORT = SERVER + "EntityTeleport";
public static final String ENTITY = SERVER + "Entity";
public static final String REL_POSITION = ENTITY + "$" + SERVER + "RelEntityMove";
public static final String REL_POSITION_LOOK = ENTITY + "$" + SERVER + "RelEntityMoveLook";
public static final String REL_LOOK = ENTITY + "$" + SERVER + "EntityLook";
public static final String LEGACY_REL_POSITION = SERVER + "RelEntityMove";
public static final String LEGACY_REL_POSITION_LOOK = SERVER + "RelEntityMoveLook";
public static final String LEGACY_REL_LOOK = SERVER + "EntityLook";
public static final String BLOCK_CHANGE = SERVER + "BlockChange";
public static final String CLOSE_WINDOW = SERVER + "CloseWindow";
public static final String HELD_ITEM = SERVER + "HeldItemSlot";
public static final String TAB_COMPLETE = SERVER + "TabComplete";
public static final String MAP_CHUNK = SERVER + "MapChunk";
public static final String MULTI_BLOCK_CHANGE = SERVER + "MultiBlockChange";
public static final String RESPAWN = SERVER + "Respawn";
public static final String WORLD_PARTICLE = SERVER + "WorldParticles";
public static final String COMMANDS = SERVER + "Commands";
public static final String OPEN_WINDOW = SERVER + "OpenWindow";
public static final String ENTITY_EFFECT = SERVER + "EntityEffect";
public static final String SET_SLOT = SERVER + "SetSlot";
public static final String EXPLOSION = SERVER + "Explosion";
public static final String ATTACH = SERVER + "AttachEntity";
}
public static class Login {
public static final String HANDSHAKE = "PacketHandshakingInSetProtocol";
public static final String PING = "PacketStatusInPing";
public static final String STATUS_START = "PacketStatusInStart";
public static final String LOGIN_START = "PacketLoginInStart";
}
}
@@ -0,0 +1,6 @@
package dev.brighten.ac.packet.wrapper;
public interface WPacket {
PacketType getPacketType();
}
@@ -0,0 +1,31 @@
package dev.brighten.ac.packet.wrapper.impl;
import dev.brighten.ac.packet.wrapper.PacketConverter;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity;
import dev.brighten.ac.utils.reflections.types.WrappedClass;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import net.minecraft.server.v1_8_R3.PacketPlayInFlying;
import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity;
import org.bukkit.util.Vector;
public class Processor_18 implements PacketConverter {
@Override
public WPacketPlayInFlying processFlying(Object object) {
PacketPlayInFlying flying = (PacketPlayInFlying) object;
return WPacketPlayInFlying.builder().x(flying.a()).y(flying.b()).z(flying.c()).yaw(flying.d())
.pitch(flying.e()).onGround(flying.f()).moved(flying.g()).looked(flying.h()).build();
}
private static WrappedClass classUseEntity = new WrappedClass(PacketPlayInUseEntity.class);
private static WrappedField fieldEntityId = classUseEntity.getFieldByName("a");
@Override
public WPacketPlayInUseEntity processUseEntity(Object object) {
PacketPlayInUseEntity useEntity = (PacketPlayInUseEntity) object;
return WPacketPlayInUseEntity.builder().entityId(fieldEntityId.get(useEntity))
.action(WPacketPlayInUseEntity.EnumEntityUseAction.valueOf(useEntity.a().name()))
.vector(new Vector(useEntity.b().a, useEntity.b().b, useEntity.b().c))
.build();
}
}
@@ -0,0 +1,19 @@
package dev.brighten.ac.packet.wrapper.in;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.packet.wrapper.WPacket;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class WPacketPlayInFlying implements WPacket {
private double x, y, z;
private float yaw, pitch;
private boolean looked, moved, onGround;
@Override
public PacketType getPacketType() {
return PacketType.FLYING;
}
}
@@ -0,0 +1,50 @@
package dev.brighten.ac.packet.wrapper.in;
import dev.brighten.ac.packet.wrapper.PacketType;
import dev.brighten.ac.packet.wrapper.WPacket;
import lombok.Builder;
import lombok.Getter;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
@Builder
@Getter
public class WPacketPlayInUseEntity implements WPacket {
private int entityId;
private Vector vector;
private EnumEntityUseAction action;
@Override
public PacketType getPacketType() {
return PacketType.USE_ENTITY;
}
public enum EnumHand {
MAIN_HAND, OFF_HAND;
}
public Entity getEntity(World world) {
for (Entity entity : world.getEntities()) {
if(entity.getEntityId() == entityId) {
return entity;
}
}
return null;
}
public enum EnumEntityUseAction {
INTERACT("INTERACT"),
ATTACK("ATTACK"),
INTERACT_AT("INTERACT_AT");
@Getter
private String name;
EnumEntityUseAction(String name) {
this.name = name;
}
}
}
@@ -0,0 +1,10 @@
package dev.brighten.ac.utils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoLoad {
boolean commands() default true;
boolean listeners() default true;
}
@@ -0,0 +1,14 @@
package dev.brighten.ac.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BlockBounds {
public List<BoundingBox> bounds = new ArrayList<>();
public int id;
public BlockBounds(int id, BoundingBox... boxes) {
bounds.addAll(Arrays.asList(boxes));
}
}
@@ -0,0 +1,483 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.reflections.impl.MinecraftReflection;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class BlockUtils {
public static Map<Material, BoundingBox> collisionBoundingBoxes = new HashMap<>();
@Deprecated
public static Block getBlock(Location location) {
if (location.getWorld().isChunkLoaded(location.getBlockX() >> 4, location.getBlockZ() >> 4)) {
return location.getBlock();
} else {
return null;
}
}
public static Optional<Block> getBlockAsync(Location location) {
if(Bukkit.isPrimaryThread()
|| location.getWorld().isChunkLoaded(location.getBlockX() >> 4, location.getBlockZ() >> 4)) {
return Optional.of(location.getBlock());
}
return Optional.empty();
}
private static WrappedField fieldBlocksMovement;
public static boolean blocksMovement(Block block) {
return blocksMovement(block.getType());
}
public static boolean blocksMovement(Material material) {
return material.isSolid();
}
public static Optional<Block> getRelativeAsync(Block block, BlockFace face) {
return getRelativeAsync(block, face.getModX(), face.getModY(), face.getModZ());
}
public static Optional<Block> getRelativeAsync(Block block, BlockFace face, int distance) {
return getRelativeAsync(block,
face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance);
}
public static Optional<Block> getRelativeAsync(Block block, int modX, int modY, int modZ) {
if(block == null) return Optional.empty();
return getBlockAsync(block.getLocation().clone().add(modX, modY, modZ));
}
public static float getFriction(XMaterial material) {
switch(material) {
case SLIME_BLOCK:
return 0.8f;
case ICE:
case PACKED_ICE:
case FROSTED_ICE:
return 0.98f;
case BLUE_ICE:
return 0.989f;
default:
return 0.6f;
}
}
public static boolean isSolid(Block block) {
return isSolid(block.getType());
}
public static boolean isSolid(Material material) {
int type = material.getId();
switch (type) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 7:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 29:
case 34:
case 33:
case 35:
case 36:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
case 48:
case 49:
case 52:
case 53:
case 54:
case 56:
case 57:
case 58:
case 60:
case 61:
case 62:
case 64:
case 65:
case 67:
case 71:
case 73:
case 74:
case 78:
case 79:
case 80:
case 81:
case 82:
case 84:
case 85:
case 86:
case 87:
case 88:
case 89:
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
case 103:
case 106:
case 107:
case 108:
case 109:
case 110:
case 111:
case 112:
case 113:
case 114:
case 116:
case 117:
case 118:
case 120:
case 121:
case 122:
case 123:
case 124:
case 125:
case 126:
case 127:
case 128:
case 129:
case 130:
case 133:
case 134:
case 135:
case 136:
case 137:
case 138:
case 139:
case 140:
case 144:
case 145:
case 146:
case 149:
case 150:
case 151:
case 152:
case 153:
case 154:
case 155:
case 156:
case 158:
case 159:
case 160:
case 161:
case 162:
case 163:
case 164:
case 165:
case 166:
case 167:
case 168:
case 169:
case 170:
case 171:
case 172:
case 173:
case 174:
case 178:
case 179:
case 180:
case 181:
case 182:
case 183:
case 184:
case 185:
case 186:
case 187:
case 188:
case 189:
case 190:
case 191:
case 192:
case 193:
case 194:
case 195:
case 196:
case 197:
case 198:
case 199:
case 200:
case 201:
case 202:
case 203:
case 204:
case 205:
case 206:
case 207:
case 208:
case 210:
case 211:
case 212:
case 213:
case 214:
case 215:
case 216:
case 218:
case 219:
case 220:
case 221:
case 222:
case 223:
case 224:
case 225:
case 226:
case 227:
case 228:
case 229:
case 230:
case 231:
case 232:
case 233:
case 234:
case 235:
case 236:
case 237:
case 238:
case 239:
case 240:
case 241:
case 242:
case 243:
case 244:
case 245:
case 246:
case 247:
case 248:
case 249:
case 250:
case 251:
case 252:
case 255:
case 397:
case 355:
return true;
}
return false;
}
public static boolean isLiquid(Block block) {
return block.getType().toString().contains("WATER") || block.getType().toString().contains("LAVA");
}
public static boolean isClimbableBlock(Block block) {
return block.getType().toString().contains("LADDER") || block.getType().toString().contains("VINE");
}
public static boolean isIce(Block block) {
return block.getType().toString().contains("ICE");
}
public static boolean isFence(Block block) {
return (block.getType().toString().contains("FENCE") && !block.getType().toString().contains("GATE")) | block.getType().toString().contains("WALL");
}
public static boolean isDoor(Block block) {
return block.getType().toString().contains("DOOR") && !block.getType().toString().contains("TRAP");
}
public static boolean isBed(Block block) {
return block.getType().toString().contains("BED");
}
public static boolean isTrapDoor(Block block) {
return block.getType().toString().contains("DOOR") && block.getType().toString().contains("TRAP");
}
public static boolean isChest(Block block) {
return block.getType().toString().contains("CHEST") || block.getType().toString().contains("SHULKER");
}
public static boolean isWall(Block block) {
return block.getType().toString().contains("WALL");
}
public static boolean isPiston(Block block) {
return block.getType().getId() == 36 || block.getType().getId() == 34 || block.getType().getId() == 33 || block.getType().getId() == 29;
}
public static boolean isFenceGate(Block block) {
return block.getType().toString().contains("FENCE") && block.getType().toString().contains("GATE");
}
public static boolean isStair(Block block) {
return block.getType().toString().contains("STAIR");
}
public static boolean isSlab(Block block) {
return block.getType().toString().contains("STEP") || block.getType().toString().contains("SLAB");
}
public static boolean isTool(ItemStack stack) {
String name = stack.getType().name().toLowerCase();
return name.contains("axe") || name.contains("spade") || name.contains("shovel") || name.contains("shear") || name.contains("sword");
}
public static Location findGround(World world, Location point) {
for (int y = point.toVector().getBlockY(); y > 0; y--) {
Location loc = new Location(world, point.getX(), y, point.getZ());
Block block = BlockUtils.getBlock(loc);
if (block.getType().isBlock() && block.getType().isSolid() && !block.isEmpty()) {
Location toReturn = loc.clone();
toReturn.setY(y + 1);
return toReturn;
}
}
return point;
}
private static void setupCollisionBB() {
if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_13)) {
collisionBoundingBoxes.put(Material.getMaterial("FIRE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("STONE_PLATE"), new BoundingBox((float) 0.0625, (float) 0.0, (float) 0.0625, (float) 0.9375, (float) 0.0625, (float) 0.9375));
collisionBoundingBoxes.put(Material.getMaterial("GRAVEL"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("COBBLESTONE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("NETHER_BRICK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("PUMPKIN"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("CARROT"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.25, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("TNT"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("SOUL_SAND"), new BoundingBox(0f, 0f,0f, 1f, 0.875f, 1f));
collisionBoundingBoxes.put(Material.getMaterial("SAND"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("WOOD_PLATE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("SIGN_POST"), new BoundingBox((float) 0.25, (float) 0.0, (float) 0.25, (float) 0.75, (float) 1.0, (float) 0.75));
collisionBoundingBoxes.put(Material.getMaterial("COCOA"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("DETECTOR_RAIL"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.125, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("HARD_CLAY"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("NETHERRACK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("STONE_BUTTON"), new BoundingBox((float) 0.3125, (float) 0.0, (float) 0.375, (float) 0.6875, (float) 0.125, (float) 0.625));
collisionBoundingBoxes.put(Material.getMaterial("CLAY"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("QUARTZ_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("HUGE_MUSHROOM_1"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("HUGE_MUSHROOM_2"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("LAVA"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("BEACON"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("GRASS"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("DEAD_BUSH"), new BoundingBox((float) 0.09999999403953552, (float) 0.0, (float) 0.09999999403953552, (float) 0.8999999761581421, (float) 0.800000011920929, (float) 0.8999999761581421));
collisionBoundingBoxes.put(Material.getMaterial("GLOWSTONE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("ICE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("BRICK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("REDSTONE_TORCH_ON"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("REDSTONE_TORCH_OFF"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("POWERED_RAIL"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.125, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("DISPENSER"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("JUKEBOX"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("EMERALD_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("STONE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("BOOKSHELF"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("MYCEL"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("OBSIDIAN"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("PORTAL"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("GOLD_PLATE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("COAL_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("GOLD_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("STAINED_CLAY"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("MOB_SPAWNER"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("BEDROCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("IRON_ORE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("REDSTONE_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("SIGN"), new BoundingBox((float) 0.25, (float) 0.0, (float) 0.25, (float) 0.75, (float) 1.0, (float) 0.75));
collisionBoundingBoxes.put(Material.getMaterial("IRON_PLATE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("GOLD_ORE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("POTATO"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.25, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("MOSSY_COBBLESTONE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("RAILS"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.125, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("HAY_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("TORCH"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("CARPET"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.0625, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("DIRT"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("EMERALD_ORE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("REDSTONE_LAMP_ON"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("REDSTONE_LAMP_OFF"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("NETHER_WARTS"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.25, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("SPONGE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("WORKBENCH"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("SANDSTONE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("LAPIS_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("NOTE_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("WOOL"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("COMMAND"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("ENDER_STONE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("TRIPWIRE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.15625, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("SAPLING"), new BoundingBox((float) 0.09999999403953552, (float) 0.0, (float) 0.09999999403953552, (float) 0.8999999761581421, (float) 0.800000011920929, (float) 0.8999999761581421));
collisionBoundingBoxes.put(Material.getMaterial("PACKED_ICE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("LAPIS_ORE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("SMOOTH_BRICK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("RED_MUSHROOM"), new BoundingBox((float) 0.30000001192092896, (float) 0.0, (float) 0.30000001192092896, (float) 0.699999988079071, (float) 0.4000000059604645, (float) 0.699999988079071));
collisionBoundingBoxes.put(Material.getMaterial("BROWN_MUSHROOM"), new BoundingBox((float) 0.30000001192092896, (float) 0.0, (float) 0.30000001192092896, (float) 0.699999988079071, (float) 0.4000000059604645, (float) 0.699999988079071));
collisionBoundingBoxes.put(Material.getMaterial("DIAMOND_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("CROPS"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.25, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("IRON_BLOCK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("MELON"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("DIAMOND_ORE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("LEVER"), new BoundingBox((float) 0.25, (float) 0.0, (float) 0.25, (float) 0.75, (float) 0.6000000238418579, (float) 0.75));
collisionBoundingBoxes.put(Material.getMaterial("SUGAR_CANE"), new BoundingBox((float) 0.125, (float) 0.0, (float) 0.125, (float) 0.875, (float) 1.0, (float) 0.875));
collisionBoundingBoxes.put(Material.getMaterial("COAL_ORE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("WATER_LILY"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 0.015625, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("QUARTZ_ORE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("GLASS"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("TRIPWIRE_HOOK"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("VINE"), new BoundingBox((float) 0.0, (float) 0.0, (float) 0.0, (float) 1.0, (float) 1.0, (float) 1.0));
collisionBoundingBoxes.put(Material.getMaterial("WEB"), new BoundingBox(0, 0, 0, 1, 1, 1));
collisionBoundingBoxes.put(Material.getMaterial("WATER"), new BoundingBox(0, 0, 0, 0.9f, 0.9f, 0.9f));
collisionBoundingBoxes.put(Material.getMaterial("STATIONARY_WATER"), new BoundingBox(0, 0, 0, 0.9f, 0.9f, 0.9f));
collisionBoundingBoxes.put(Material.getMaterial("STATIONARY_LAVA"), new BoundingBox(0, 0, 0, 0.9f, 0.9f, 0.9f));
}
}
static {
setupCollisionBB();
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_13)) {
fieldBlocksMovement = MinecraftReflection.classBlockInfo.getFieldByType(boolean.class, 0);
}
}
}
@@ -0,0 +1,315 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
public class BoundingBox {
public float minX, minY, minZ, maxX, maxY, maxZ;
public BoundingBox(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
}
public BoundingBox(Vector min, Vector max) {
this.minX = (float) Math.min(min.getX(), max.getX());
this.minY = (float) Math.min(min.getY(), max.getY());
this.minZ = (float) Math.min(min.getZ(), max.getZ());
this.maxX = (float) Math.max(min.getX(), max.getX());
this.maxY = (float) Math.max(min.getY(), max.getY());
this.maxZ = (float) Math.max(min.getZ(), max.getZ());
}
public BoundingBox(BoundingBox one, BoundingBox two) {
this.minX = Math.min(one.minX, two.minX);
this.minY = Math.min(one.minY, two.minY);
this.minZ = Math.min(one.minZ, two.minZ);
this.maxX = Math.max(one.maxX, two.maxX);
this.maxY = Math.max(one.maxY, two.maxY);
this.maxZ = Math.max(one.maxZ, two.maxZ);
}
public BoundingBox add(float x, float y, float z) {
float newMinX = minX + x;
float newMaxX = maxX + x;
float newMinY = minY + y;
float newMaxY = maxY + y;
float newMinZ = minZ + z;
float newMaxZ = maxZ + z;
return new BoundingBox(newMinX, newMinY, newMinZ, newMaxX, newMaxY, newMaxZ);
}
public BoundingBox add(Vector vector) {
float x = (float) vector.getX(), y = (float) vector.getY(), z = (float) vector.getZ();
float newMinX = minX + x;
float newMaxX = maxX + x;
float newMinY = minY + y;
float newMaxY = maxY + y;
float newMinZ = minZ + z;
float newMaxZ = maxZ + z;
return new BoundingBox(newMinX, newMinY, newMinZ, newMaxX, newMaxY, newMaxZ);
}
public BoundingBox grow(float x, float y, float z) {
float newMinX = minX - x;
float newMaxX = maxX + x;
float newMinY = minY - y;
float newMaxY = maxY + y;
float newMinZ = minZ - z;
float newMaxZ = maxZ + z;
return new BoundingBox(newMinX, newMinY, newMinZ, newMaxX, newMaxY, newMaxZ);
}
public BoundingBox shrink(float x, float y, float z) {
float newMinX = minX + x;
float newMaxX = maxX - x;
float newMinY = minY + y;
float newMaxY = maxY - y;
float newMinZ = minZ + z;
float newMaxZ = maxZ - z;
return new BoundingBox(newMinX, newMinY, newMinZ, newMaxX, newMaxY, newMaxZ);
}
public BoundingBox add(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return new BoundingBox(this.minX + minX, this.minY + minY, this.minZ + minZ, this.maxX + maxX, this.maxY + maxY, this.maxZ + maxZ);
}
public BoundingBox subtract(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {
return new BoundingBox(this.minX - minX, this.minY - minY, this.minZ - minZ, this.maxX - maxX, this.maxY - maxY, this.maxZ - maxZ);
}
public boolean intersectsWithBox(Vector vector) {
return (vector.getX() > this.minX && vector.getX() < this.maxX) && ((vector.getY() > this.minY && vector.getY() < this.maxY) && (vector.getZ() > this.minZ && vector.getZ() < this.maxZ));
}
public Vector getMinimum() {
return new Vector(minX, minY, minZ);
}
public Vector getMaximum() {
return new Vector(maxX, maxY, maxZ);
}
public List<Block> getAllBlocks(Player player) {
Location min = new Location(player.getWorld(), MathUtils.floor(minX), MathUtils.floor(minY), MathUtils.floor(minZ));
Location max = new Location(player.getWorld(), MathUtils.floor(maxX), MathUtils.floor(maxY), MathUtils.floor(maxZ));
List<Block> all = new ArrayList<>();
for (float x = (float) min.getX(); x < max.getX(); x++) {
for (float y = (float) min.getY(); y < max.getY(); y++) {
for (float z = (float) min.getZ(); z < max.getZ(); z++) {
Block block = BlockUtils.getBlock(new Location(player.getWorld(), x, y, z));
if (block != null && block.getType().getId() != 0) {
all.add(block);
}
}
}
}
return all;
}
public boolean intersectsWithBox(Object other) {
if (other instanceof BoundingBox) {
BoundingBox otherBox = (BoundingBox) other;
return otherBox.maxX > this.minX && otherBox.minX < this.maxX && otherBox.maxY > this.minY && otherBox.minY < this.maxY && otherBox.maxZ > this.minZ && otherBox.minZ < this.maxZ;
} else {
float otherMinX = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "a"), other);
float otherMinY = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "b"), other);
float otherMinZ = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "c"), other);
float otherMaxX = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "d"), other);
float otherMaxY = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "e"), other);
float otherMaxZ = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "f"), other);
return otherMaxX > minX && otherMinX < maxX && otherMaxY > minY && otherMinY < maxY && otherMaxZ > minZ && otherMinZ < maxZ;
}
}
public boolean collides(Vector vector) {
return (vector.getX() >= this.minX && vector.getX() <= this.maxX) && ((vector.getY() >= this.minY && vector.getY() <= this.maxY) && (vector.getZ() >= this.minZ && vector.getZ() <= this.maxZ));
}
public boolean collides(Object other) {
if (other instanceof BoundingBox) {
BoundingBox otherBox = (BoundingBox) other;
return otherBox.maxX >= this.minX && otherBox.minX <= this.maxX && otherBox.maxY >= this.minY && otherBox.minY <= this.maxY && otherBox.maxZ >= this.minZ && otherBox.minZ <= this.maxZ;
} else {
float otherMinX = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "a"), other);
float otherMinY = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "b"), other);
float otherMinZ = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "c"), other);
float otherMaxX = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "d"), other);
float otherMaxY = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "e"), other);
float otherMaxZ = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "f"), other);
return otherMaxX >= minX && otherMinX <= maxX && otherMaxY >= minY && otherMinY <= maxY && otherMaxZ >= minZ && otherMinZ <= maxZ;
}
}
public boolean collidesHorizontally(Vector vector) {
return (vector.getX() >= this.minX && vector.getX() <= this.maxX) && ((vector.getY() > this.minY && vector.getY() < this.maxY) && (vector.getZ() >= this.minZ && vector.getZ() <= this.maxZ));
}
public boolean collidesHorizontally(Object other) {
if (other instanceof BoundingBox) {
BoundingBox otherBox = (BoundingBox) other;
return otherBox.maxX >= this.minX && otherBox.minX <= this.maxX && otherBox.maxY > this.minY && otherBox.minY < this.maxY && otherBox.maxZ >= this.minZ && otherBox.minZ <= this.maxZ;
} else {
float otherMinX = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "a"), other);
float otherMinY = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "b"), other);
float otherMinZ = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "c"), other);
float otherMaxX = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "d"), other);
float otherMaxY = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "e"), other);
float otherMaxZ = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "f"), other);
return otherMaxX >= minX && otherMinX <= maxX && otherMaxY > minY && otherMinY < maxY && otherMaxZ >= minZ && otherMinZ <= maxZ;
}
}
public boolean collidesVertically(Vector vector) {
return (vector.getX() > this.minX && vector.getX() < this.maxX) && ((vector.getY() >= this.minY && vector.getY() <= this.maxY) && (vector.getZ() > this.minZ && vector.getZ() < this.maxZ));
}
public boolean collidesVertically(Object other) {
if (other instanceof BoundingBox) {
BoundingBox otherBox = (BoundingBox) other;
return otherBox.maxX > this.minX && otherBox.minX < this.maxX && otherBox.maxY >= this.minY && otherBox.minY <= this.maxY && otherBox.maxZ > this.minZ && otherBox.minZ < this.maxZ;
} else {
float otherMinX = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "a"), other);
float otherMinY = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "b"), other);
float otherMinZ = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "c"), other);
float otherMaxX = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "d"), other);
float otherMaxY = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "e"), other);
float otherMaxZ = (float) (double) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(other.getClass(), "f"), other);
return otherMaxX > minX && otherMinX < maxX && otherMaxY >= minY && otherMinY <= maxY && otherMaxZ > minZ && otherMinZ < maxZ;
}
}
/**
* if instance and the argument bounding boxes overlap in the Y and Z dimensions, calculate the offset between them
* in the X dimension. return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
* calculated offset. Otherwise return the calculated offset.
*/
public double calculateXOffset(BoundingBox other, double offsetX) {
if (other.maxY > this.minY && other.minY < this.maxY && other.maxZ > this.minZ && other.minZ < this.maxZ) {
if (offsetX > 0.0D && other.maxX <= this.minX) {
double d1 = this.minX - other.maxX;
if (d1 < offsetX) {
offsetX = d1;
}
} else if (offsetX < 0.0D && other.minX >= this.maxX) {
double d0 = this.maxX - other.minX;
if (d0 > offsetX) {
offsetX = d0;
}
}
return offsetX;
} else {
return offsetX;
}
}
/**
* if instance and the argument bounding boxes overlap in the X and Z dimensions, calculate the offset between them
* in the Y dimension. return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
* calculated offset. Otherwise return the calculated offset.
*/
public double calculateYOffset(BoundingBox other, double offsetY) {
if (other.maxX > this.minX && other.minX < this.maxX && other.maxZ > this.minZ && other.minZ < this.maxZ) {
if (offsetY > 0.0D && other.maxY <= this.minY) {
double d1 = this.minY - other.maxY;
if (d1 < offsetY) {
offsetY = d1;
}
} else if (offsetY < 0.0D && other.minY >= this.maxY) {
double d0 = this.maxY - other.minY;
if (d0 > offsetY) {
offsetY = d0;
}
}
return offsetY;
} else {
return offsetY;
}
}
/**
* if instance and the argument bounding boxes overlap in the Y and X dimensions, calculate the offset between them
* in the Z dimension. return var2 if the bounding boxes do not overlap or if var2 is closer to 0 then the
* calculated offset. Otherwise return the calculated offset.
*/
public double calculateZOffset(BoundingBox other, double offsetZ) {
if (other.maxX > this.minX && other.minX < this.maxX && other.maxY > this.minY && other.minY < this.maxY) {
if (offsetZ > 0.0D && other.maxZ <= this.minZ) {
double d1 = this.minZ - other.maxZ;
if (d1 < offsetZ) {
offsetZ = d1;
}
} else if (offsetZ < 0.0D && other.minZ >= this.maxZ) {
double d0 = this.maxZ - other.minZ;
if (d0 > offsetZ) {
offsetZ = d0;
}
}
return offsetZ;
} else {
return offsetZ;
}
}
public BoundingBox addCoord(float x, float y, float z) {
float d0 = this.minX;
float d1 = this.minY;
float d2 = this.minZ;
float d3 = this.maxX;
float d4 = this.maxY;
float d5 = this.maxZ;
if (x < 0.0D) {
d0 += x;
} else if (x > 0.0D) {
d3 += x;
}
if (y < 0.0D) {
d1 += y;
} else if (y > 0.0D) {
d4 += y;
}
if (z < 0.0D) {
d2 += z;
} else if (z > 0.0D) {
d5 += z;
}
return new BoundingBox(d0,d1,d2,d3,d4,d5);
}
public SimpleCollisionBox toCollisionBox() {
return new SimpleCollisionBox(minX, minY, minZ, maxX, maxY, maxZ);
}
public String toString() {
return "[" + minX + ", " + minY + ", " + minZ + ", " + maxX + ", " + maxY + ", " + maxZ + "]";
}
}
@@ -0,0 +1,261 @@
package dev.brighten.ac.utils;
import org.bukkit.Bukkit;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* This is copied from somewhere, can't remember from where though. Modified.
* */
public class ClassScanner {
private static final PathMatcher CLASS_FILE = create("glob:*.class");
private static final PathMatcher ARCHIVE = create("glob:*.{jar}");
public static Set<String> scanFile(String file, File f) {
URL[] urls;
try {
urls = new URL[]{f.toURI().toURL()};
} catch (MalformedURLException e) {
e.printStackTrace();
return new HashSet<>();
}
return scanFile(file, urls);
}
public static Set<String> scanFile(String file, Class<?> clazz) {
return scanFile(file, new URL[]{clazz.getProtectionDomain().getCodeSource().getLocation()});
}
public static Set<String> scanFile2(String file, Class<?> clazz) {
Bukkit.getLogger().info("Found file: " + clazz.getProtectionDomain().getCodeSource().getLocation().toString());
return scanFile2(file, new URL[]{clazz.getProtectionDomain().getCodeSource().getLocation()});
}
public static Set<String> scanFile2(String file, URL[] urls) {
Set<URI> sources = new HashSet<>();
Set<String> plugins = new HashSet<>();
for (URL url : urls) {
if (!url.getProtocol().equals("file")) {
continue;
}
URI source;
try {
source = url.toURI();
} catch (URISyntaxException e) {
continue;
}
if (sources.add(source)) {
scanPath2(file, Paths.get(source), plugins);
}
}
return plugins;
}
public static Set<String> scanFile(String file, URL[] urls) {
Set<URI> sources = new HashSet<>();
Set<String> plugins = new HashSet<>();
for (URL url : urls) {
if (!url.getProtocol().equals("file")) {
continue;
}
URI source;
try {
source = url.toURI();
} catch (URISyntaxException e) {
continue;
}
if (sources.add(source)) {
scanPath(file, Paths.get(source), plugins);
}
}
return plugins;
}
private static void scanPath(String file, Path path, Set<String> plugins) {
if (Files.exists(path)) {
if (Files.isDirectory(path)) {
scanDirectory(file, path, plugins);
} else {
scanZip(file, path, plugins);
}
}
}
private static void scanPath2(String file, Path path, Set<String> plugins) {
if (Files.exists(path)) {
if (Files.isDirectory(path)) {
scanDirectory2(file, path, plugins);
} else {
scanZip2(file, path, plugins);
}
}
}
private static void scanDirectory(String file, Path dir, final Set<String> plugins) {
try {
Files.walkFileTree(dir, newHashSet(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
if (CLASS_FILE.matches(path.getFileName())) {
try (InputStream in = Files.newInputStream(path)) {
String plugin = findPlugin(file, in);
if (plugin != null) {
plugins.add(plugin);
}
}
}
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
private static void scanDirectory2(String file, Path dir, final Set<String> plugins) {
try {
Files.walkFileTree(dir, newHashSet(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
if (CLASS_FILE.matches(path.getFileName())) {
try (InputStream in = Files.newInputStream(path)) {
String plugin = findClasses(file, in);
if (plugin != null) {
plugins.add(plugin);
}
}
}
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
private static <E> HashSet<E> newHashSet(E... elements) {
HashSet<E> set = new HashSet<>();
Collections.addAll(set, elements);
return set;
}
private static void scanZip(String file, Path path, Set<String> plugins) {
if (!ARCHIVE.matches(path.getFileName())) {
return;
}
try (ZipFile zip = new ZipFile(path.toFile())) {
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
continue;
}
try (InputStream in = zip.getInputStream(entry)) {
String plugin = findPlugin(file, in);
if (plugin != null) {
plugins.add(plugin);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void scanZip2(String file, Path path, Set<String> plugins) {
if (!ARCHIVE.matches(path.getFileName())) {
return;
}
try (ZipFile zip = new ZipFile(path.toFile())) {
zip.stream().parallel().forEach(entry -> {
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
try (InputStream in = zip.getInputStream(entry)) {
String plugin = findClasses(file, in);
if (plugin != null) {
plugins.add(plugin);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
public static String findPlugin(String file, InputStream in) {
try {
ClassReader reader = new ClassReader(in);
ClassNode classNode = new ClassNode();
reader.accept(classNode, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
String className = classNode.name.replace('/', '.');
if (classNode.visibleAnnotations != null) {
for (Object node : classNode.visibleAnnotations) {
AnnotationNode annotation = (AnnotationNode) node;
if ((file == null && annotation.desc
.equals("L" + Init.class.getName().replace(".", "/") + ";"))
|| (file != null && annotation.desc
.equals("L" + file.replace(".", "/") + ";")))
return className;
}
}
if (classNode.superName != null && (classNode.superName.equals(file))) return className;
} catch (Exception e) {
//System.out.println("Failed to scan: " + in.toString());
}
return null;
}
public static String findClasses(String file, InputStream in) {
try {
ClassReader reader = new ClassReader(in);
ClassNode classNode = new ClassNode();
reader.accept(classNode, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return classNode.name.replace('/', '.');
} catch (Exception e) {
Bukkit.getLogger().severe("Failed to scan: " + in.toString());
}
return null;
}
public static PathMatcher create(String pattern) {
return FileSystems.getDefault().getPathMatcher(pattern);
}
}
@@ -0,0 +1,181 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.packet.ProtocolVersion;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Color {
public static final String Red = ChatColor.RED.toString();
public static final String Yellow = ChatColor.YELLOW.toString();
public static final String Gold = ChatColor.GOLD.toString();
public static final String Green = ChatColor.GREEN.toString();
public static final String Aqua = ChatColor.AQUA.toString();
public static final String Dark_Aqua = ChatColor.DARK_AQUA.toString();
public static final String Gray = ChatColor.GRAY.toString();
public static final String Dark_Gray = ChatColor.DARK_GRAY.toString();
public static final String Bold = ChatColor.BOLD.toString();
public static final String Italics = ChatColor.ITALIC.toString();
public static final String Strikethrough = ChatColor.STRIKETHROUGH.toString();
public static final String White = ChatColor.WHITE.toString();
public static final String Dark_Red = ChatColor.DARK_RED.toString();
public static final String Dark_Green = ChatColor.DARK_GREEN.toString();
public static final String Blue = ChatColor.BLUE.toString();
public static final String Dark_Blue = ChatColor.DARK_BLUE.toString();
public static final String Pink = ChatColor.LIGHT_PURPLE.toString();
public static final String Purple = ChatColor.DARK_PURPLE.toString();
public static final String Black = ChatColor.BLACK.toString();
public static final String Underline = ChatColor.UNDERLINE.toString();
private static final Pattern pattern = Pattern.compile("#[a-fA-F0-9]{6}");
public static String translate(String string) {
Matcher match = pattern.matcher(string);
if (match.matches())
while (match.find()) {
String colorToTranslate = string.substring(match.start(), match.end());
int rgb;
try {
rgb = Integer.parseInt(colorToTranslate.substring(1), 16);
} catch (NumberFormatException var7) {
throw new IllegalArgumentException("Illegal hex string " + string);
}
if (ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_16)) {
StringBuilder magic = new StringBuilder("§x");
char[] var3 = string.substring(1).toCharArray();
for (char c : var3) {
magic.append('§').append(c);
}
string = string.replace(colorToTranslate, magic.toString());
} else string = string.replace(colorToTranslate, getClosestColor(rgb));
}
return
ChatColor.translateAlternateColorCodes('&', string);
}
public static String strip(String string) {
return ChatColor.stripColor(string);
}
@Deprecated
public static String getColorFromString(String string) {
if (string.contains("&")) {
return Color.translate(string);
} else {
String color = (String) ReflectionsUtil.getFieldValue(ReflectionsUtil.getFieldByName(null, string), null);
if (color == null) {
Bukkit.getLogger().log(Level.WARNING, "The color '" + string + "' does not exist.");
return Strikethrough;
}
return color;
}
}
/** Method from TranslatableRewriter1_16.java in https://github.com/ViaVersion/ViaBackwards **/
public static String getClosestColor(int rgb) {
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
TranslatedColor closest = null;
int smallestDiff = 0;
for (TranslatedColor color : COLORS) {
if (color.rgb == rgb) {
return color.color;
}
// Check by the greatest diff of the 3 values
int rAverage = (color.r + r) / 2;
int rDiff = color.r - r;
int gDiff = color.g - g;
int bDiff = color.b - b;
int diff = ((2 + (rAverage >> 8)) * rDiff * rDiff)
+ (4 * gDiff * gDiff)
+ ((2 + ((255 - rAverage) >> 8)) * bDiff * bDiff);
if (closest == null || diff < smallestDiff) {
closest = color;
smallestDiff = diff;
}
}
return closest.color;
}
/** Method from TranslatableRewriter1_16.java in https://github.com/ViaVersion/ViaBackwards **/
public static ChatColor getClosestChatColor(int rgb) {
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
TranslatedColor closest = null;
int smallestDiff = 0;
for (TranslatedColor color : COLORS) {
if (color.rgb == rgb) {
return color.chatcolor;
}
// Check by the greatest diff of the 3 values
int rAverage = (color.r + r) / 2;
int rDiff = color.r - r;
int gDiff = color.g - g;
int bDiff = color.b - b;
int diff = ((2 + (rAverage >> 8)) * rDiff * rDiff)
+ (4 * gDiff * gDiff)
+ ((2 + ((255 - rAverage) >> 8)) * bDiff * bDiff);
if (closest == null || diff < smallestDiff) {
closest = color;
smallestDiff = diff;
}
}
return closest.chatcolor;
}
/** From TranslatableRewriter1_16.java in https://github.com/ViaVersion/ViaBackwards **/
private static final TranslatedColor[] COLORS = {
new TranslatedColor(Black, ChatColor.BLACK, 0x000000),
new TranslatedColor(Dark_Blue, ChatColor.DARK_BLUE, 0x0000aa),
new TranslatedColor(Dark_Green, ChatColor.DARK_GREEN, 0x00aa00),
new TranslatedColor(Dark_Aqua, ChatColor.DARK_AQUA, 0x00aaaa),
new TranslatedColor(Dark_Red, ChatColor.DARK_RED,0xaa0000),
new TranslatedColor(Purple, ChatColor.DARK_PURPLE,0xaa00aa),
new TranslatedColor(Gold, ChatColor.GOLD,0xffaa00),
new TranslatedColor(Gray, ChatColor.GRAY,0xaaaaaa),
new TranslatedColor(Dark_Gray, ChatColor.DARK_GRAY,0x555555),
new TranslatedColor(Blue, ChatColor.BLUE,0x5555ff),
new TranslatedColor(Green, ChatColor.GREEN,0x55ff55),
new TranslatedColor(Aqua, ChatColor.AQUA,0x55ffff),
new TranslatedColor(Red, ChatColor.RED,0xff5555),
new TranslatedColor(Pink, ChatColor.LIGHT_PURPLE,0xff55ff),
new TranslatedColor(Yellow, ChatColor.YELLOW,0xffff55),
new TranslatedColor(White, ChatColor.WHITE,0xffffff)
};
/** From TranslatableRewriter1_16.java in https://github.com/ViaVersion/ViaBackwards **/
private static final class TranslatedColor {
private final String color;
private final ChatColor chatcolor;
private final int rgb;
private final int r, g, b;
TranslatedColor(String colorName, ChatColor chatColor, int rgb) {
this.color = colorName;
this.chatcolor = chatColor;
this.rgb = rgb;
r = (rgb >> 16) & 0xFF;
g = (rgb >> 8) & 0xFF;
b = rgb & 0xFF;
}
}
}
@@ -0,0 +1,9 @@
package dev.brighten.ac.utils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Commands {
String[] commands() default "";
}
@@ -0,0 +1,28 @@
package dev.brighten.ac.utils;
import lombok.AllArgsConstructor;
import org.bukkit.plugin.Plugin;
@AllArgsConstructor
public class ConfigDefault<A> {
private final A defaultValue;
private final String path;
private final Plugin plugin;
public A get() {
if(plugin.getConfig().get(path) != null)
return (A) plugin.getConfig().get(path);
else {
plugin.getConfig().set(path, defaultValue);
plugin.saveConfig();
return defaultValue;
}
}
public A set(A value) {
plugin.getConfig().set(path, value);
return value;
}
}
@@ -0,0 +1,15 @@
package dev.brighten.ac.utils;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface ConfigSetting {
String path() default "";
String name() default "";
String comment() default "";
boolean hide() default false;
}
@@ -0,0 +1,63 @@
package dev.brighten.ac.utils;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import java.util.concurrent.TimeUnit;
public class ExpTimer {
public final Player player;
public long timerEnd;
public final long extense;
public final Runnable onComplete;
public BukkitTask levelTask, expTask;
private int previousLevel;
private float previousExp;
public ExpTimer(Player player, long time, TimeUnit unit, Runnable onComplete) {
this.player = player;
this.extense = unit.toMillis(time);
this.timerEnd = System.currentTimeMillis() + extense;
this.onComplete = onComplete;
previousExp = player.getExp();
previousLevel = player.getLevel();
levelTask = RunUtils.taskTimer(() -> {
if(getMillisLeft() <= 0) {
levelTask.cancel();
levelTask = null;
return;
}
player.setLevel((int)Math.floor(getMillisLeft() / 1000D));
}, 2, 20);
expTask = RunUtils.taskTimer(() -> {
if(getMillisLeft() <= 0 && levelTask == null) {
expTask.cancel();
expTask = null;
player.setLevel(previousLevel);
player.setExp(previousExp);
onComplete.run();
return;
}
player.setExp(getMillisLeft() / (float)extense);
}, 2, 2);
}
private long getMillisLeft() {
return timerEnd - System.currentTimeMillis();
}
public void stop() {
timerEnd = System.currentTimeMillis();
}
public void cancel() {
levelTask.cancel();
expTask.cancel();
levelTask = expTask = null;
player.setExp(previousExp);
player.setLevel(previousLevel);
}
}
@@ -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 = COS_TAB[ind]; // cos(φ)
// sin(φ) == ind / 256.0
// Note that sφ is truncated, hence not identical to y.
double = yp - FRAC_BIAS;
double sd = y * - x * ; // 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,170 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.handlers.PlayerSizeHandler;
import dev.brighten.ac.utils.world.BlockData;
import dev.brighten.ac.utils.world.CollisionBox;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Helper {
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 Vector vector(double yaw, double pitch) {
Vector vector = new Vector();
vector.setY(-Math.sin(Math.toRadians(pitch)));
double xz = Math.cos(Math.toRadians(pitch));
vector.setX(-xz * Math.sin(Math.toRadians(yaw)));
vector.setZ(xz * Math.cos(Math.toRadians(yaw)));
return vector;
}
public static SimpleCollisionBox getMovementHitbox(Player player, double x, double y, double z) {
return PlayerSizeHandler.instance.bounds(player, x, y, z);
}
public static SimpleCollisionBox getMovementHitbox(Player player) {
return PlayerSizeHandler.instance.bounds(player);
}
public static SimpleCollisionBox getCombatHitbox(Player player, ProtocolVersion version) {
return version.isBelow(ProtocolVersion.V1_9)
? PlayerSizeHandler.instance.bounds(player).expand(.1, 0, .1)
: PlayerSizeHandler.instance.bounds(player);
}
public static Block getBlockAt(World world, int x, int y, int z) {
return world.isChunkLoaded(x >> 4, z >> 4)
? world.getChunkAt(x >> 4, z >> 4).getBlock(x & 15, y, z & 15)
: null;
}
public static SimpleCollisionBox wrap(SimpleCollisionBox a, SimpleCollisionBox b) {
double minX = Math.min(a.xMin, b.xMin);
double minY = Math.min(a.yMin, b.yMin);
double minZ = Math.min(a.zMin, b.zMin);
double maxX = Math.max(a.xMax, b.xMax);
double maxY = Math.max(a.yMax, b.yMax);
double maxZ = Math.max(a.zMax, b.zMax);
return new SimpleCollisionBox(minX, minY, minZ, maxX, maxY, maxZ);
}
public static SimpleCollisionBox wrap(List<SimpleCollisionBox> box) {
if (!box.isEmpty()) {
SimpleCollisionBox wrap = box.get(0).copy();
for (int i = 1; i < box.size(); i++) {
SimpleCollisionBox a = box.get(i);
if (wrap.xMin > a.xMin) wrap.xMin = a.xMin;
if (wrap.yMin > a.yMin) wrap.yMin = a.yMin;
if (wrap.zMin > a.zMin) wrap.zMin = a.zMin;
if (wrap.xMax < a.xMax) wrap.xMax = a.xMax;
if (wrap.yMax < a.yMax) wrap.yMax = a.yMax;
if (wrap.zMax < a.zMax) wrap.zMax = a.zMax;
}
return wrap;
}
return null;
}
public static List<Block> blockCollisions(List<Block> blocks, CollisionBox box) {
return blocks.stream()
.filter(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()).isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static boolean isCollided(SimpleCollisionBox toCheck, CollisionBox other) {
List<SimpleCollisionBox> downcasted = new ArrayList<>();
other.downCast(downcasted);
return downcasted.stream().anyMatch(box -> box.xMax >= toCheck.xMin && box.xMin <= toCheck.xMax
&& box.yMax >= toCheck.yMin && box.yMin <= toCheck.yMax && box.zMax >= toCheck.zMin
&& box.zMin <= toCheck.zMax);
}
public static List<Block> blockCollisions(List<Block> blocks, CollisionBox box, int material) {
return blocks.stream().filter(b -> Materials.checkFlag(b.getType(), material))
.filter(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()).isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static <C extends CollisionBox> List<C> collisions(List<C> boxes, CollisionBox box) {
return boxes.stream().filter(b -> b.isCollided(box))
.collect(Collectors.toCollection(LinkedList::new));
}
public static List<Block> getBlocksNearby2(World world, SimpleCollisionBox collisionBox, int mask) {
int x1 = (int) Math.floor(collisionBox.xMin);
int y1 = (int) Math.floor(collisionBox.yMin);
int z1 = (int) Math.floor(collisionBox.zMin);
int x2 = (int) Math.ceil(collisionBox.xMax);
int y2 = (int) Math.ceil(collisionBox.yMax);
int z2 = (int) Math.ceil(collisionBox.zMax);
List<Block> blocks = new LinkedList<>();
Block block;
for (int x = x1; x <= x2; x++)
for (int y = y1; y <= y2; y++)
for (int z = z1; z <= z2; z++)
if ((block = getBlockAt(world, x, y, z)) != null
&& block.getType()!= XMaterial.AIR.parseMaterial())
if (Materials.checkFlag(block.getType(),mask))
blocks.add(block);
return blocks;
}
private static final int[] decimalPlaces = {0, 10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000};
public static double format(double d, int dec) {
return (long) (d * decimalPlaces[dec] + 0.5) / (double) decimalPlaces[dec];
}
public static String drawUsage(long max, long time) {
double chunk = max / 50.;
String line = IntStream.range(0, 50).mapToObj(i -> (chunk * i < time ? "§c" : "§7") + "")
.collect(Collectors.joining("", "[", ""));
String zeros = "00";
String nums = Integer.toString((int) ((time / (double) max) * 100));
return line + "§f] §c" + zeros.substring(0, 3 - nums.length()) + nums + "% §f❘";
}
public static String drawUsage(long max, double time) {
double chunk = max / 50.;
String line = IntStream.range(0, 50).mapToObj(i -> (chunk * i < time ? "§c" : "§7") + "")
.collect(Collectors.joining("", "[", ""));
String nums = String.valueOf(format((time / (double) max) * 100, 3));
return line + "§f] §c" + nums + "%";
}
public static List<CollisionBox> toCollisions(List<Block> blocks) {
return blocks.stream().map(b -> BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion()))
.collect(Collectors.toCollection(LinkedList::new));
}
public static List<SimpleCollisionBox> toCollisionsDowncasted(List<Block> blocks) {
List<SimpleCollisionBox> collisions = new LinkedList<>();
blocks.forEach(b -> BlockData.getData(b.getType())
.getBox(b, ProtocolVersion.getGameVersion()).downCast(collisions));
return collisions;
}
public static CollisionBox toCollisions(Block b) {
return BlockData.getData(b.getType()).getBox(b, ProtocolVersion.getGameVersion());
}
}
@@ -0,0 +1,16 @@
package dev.brighten.ac.utils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Init {
Priority priority() default Priority.NORMAL;
String[] requirePlugins() default {};
RequireType requireType() default RequireType.ALL;
enum RequireType {
ALL,
ONE
}
}
@@ -0,0 +1,11 @@
package dev.brighten.ac.utils;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Instance {
}
@@ -0,0 +1,11 @@
package dev.brighten.ac.utils;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Invoke {
}
@@ -0,0 +1,241 @@
package dev.brighten.ac.utils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.material.MaterialData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* This is a chainable builder for {@link ItemStack}s in {@link Bukkit} <br>
* Example Usage:<br>
* {@code ItemStack is = new ItemBuilder(Material.LEATHER_HELMET).amount(2).data(4).durability(4).enchantment(Enchantment.ARROW_INFINITE).enchantment(Enchantment.LUCK, 2).name(ChatColor.RED + "the name").lore(ChatColor.GREEN + "line 1").lore(ChatColor.BLUE + "line 2").color(Color.MAROON).build();
*
* @author MiniDigger, edited by Alexandeh
* @version 1.3
*/
public class ItemBuilder {
private ItemStack is;
/**
* Inits the builder with the given {@link Material}
*
* @param mat the {@link Material} to start the builder from
* @since 1.0
*/
public ItemBuilder(Material mat) {
is = new ItemStack(mat);
}
/**
* Inits the builder with the given {@link ItemStack}
*
* @param is the {@link ItemStack} to start the builder from
* @since 1.0
*/
public ItemBuilder(ItemStack is) {
this.is = is;
}
/**
* Changes the amount of the {@link ItemStack}
*
* @param amount the new amount to set
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder amount(int amount) {
is.setAmount(amount);
return this;
}
/**
* Changes the display name of the {@link ItemStack}
*
* @param name the new display name to set
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder name(String name) {
ItemMeta meta = is.getItemMeta();
meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', name));
is.setItemMeta(meta);
return this;
}
public ItemBuilder owner(String name) {
final SkullMeta meta = (SkullMeta) is.getItemMeta();
meta.setOwner(name);
is.setItemMeta(meta);
return this;
}
/**
* Adds a new line to the lore of the {@link ItemStack}
*
* @param name the new line to add
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder lore(String name) {
ItemMeta meta = is.getItemMeta();
List<String> lore = meta.getLore();
if (lore == null) {
lore = new ArrayList<>();
}
lore.add(name);
meta.setLore(lore);
is.setItemMeta(meta);
return this;
}
public ItemBuilder lore(String... lore) {
ItemMeta meta = is.getItemMeta();
List<String> lores = Arrays.stream(lore)
.map(s -> ChatColor.translateAlternateColorCodes('&', s))
.collect(Collectors.toList());
meta.setLore(lores);
is.setItemMeta(meta);
return this;
}
/**
* sets the lore of the {@link ItemStack}
*
* @param lore the loret o set
* @return this builder for chaining
* @since 1.2
*/
public ItemBuilder lore(List<String> lore) {
ItemMeta meta = is.getItemMeta();
meta.setLore(lore);
is.setItemMeta(meta);
return this;
}
/**
* Changes the durability of the {@link ItemStack}
*
* @param durability the new durability to set
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder durability(int durability) {
is.setDurability((short) durability);
return this;
}
/**
* Changes the data of the {@link ItemStack}
*
* @param data the new data to set
* @return this builder for chaining
* @since 1.0
*/
@SuppressWarnings("deprecation")
public ItemBuilder data(int data) {
is.setData(new MaterialData(is.getType(), (byte) data));
return this;
}
/**
* Adds an {@link Enchantment} with the given level to the {@link ItemStack}
*
* @param enchantment the enchantment to add
* @param level the level of the enchantment
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder enchantment(Enchantment enchantment, int level) {
is.addUnsafeEnchantment(enchantment, level);
return this;
}
/**
* Adds an {@link Enchantment} with the level 1 to the {@link ItemStack}
*
* @param enchantment the enchantment to add
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder enchantment(Enchantment enchantment) {
is.addUnsafeEnchantment(enchantment, 1);
return this;
}
/**
* Changes the {@link Material} of the {@link ItemStack}
*
* @param material the new material to set
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder type(Material material) {
is.setType(material);
return this;
}
/**
* Clears the lore of the {@link ItemStack}
*
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder clearLore() {
ItemMeta meta = is.getItemMeta();
meta.setLore(new ArrayList<>());
is.setItemMeta(meta);
return this;
}
/**
* Clears the list of {@link Enchantment}s of the {@link ItemStack}
*
* @return this builder for chaining
* @since 1.0
*/
public ItemBuilder clearEnchantments() {
is.getEnchantments().keySet().forEach(e -> is.removeEnchantment(e));
return this;
}
/**
* Sets the {@link Color} of a part of leather armor
*
* @param color the {@link Color} to use
* @return this builder for chaining
* @since 1.1
*/
public ItemBuilder color(Color color) {
if (is.getType() == XMaterial.LEATHER_BOOTS.parseMaterial()
|| is.getType() == XMaterial.LEATHER_CHESTPLATE .parseMaterial()
|| is.getType() == XMaterial.LEATHER_HELMET.parseMaterial()
|| is.getType() == XMaterial.LEATHER_LEGGINGS.parseMaterial()) {
LeatherArmorMeta meta = (LeatherArmorMeta) is.getItemMeta();
meta.setColor(color);
is.setItemMeta(meta);
return this;
} else {
throw new IllegalArgumentException("color() only applicable for leather armor!");
}
}
/**
* Builds the {@link ItemStack}
*
* @return the created {@link ItemStack}
* @since 1.0
*/
public ItemStack build() {
return is;
}
}
@@ -0,0 +1,58 @@
package dev.brighten.ac.utils;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.util.Vector;
public class KLocation {
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(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);
}
public KLocation clone() {
return new KLocation(x, y, z, yaw, pitch, timeStamp);
}
}
@@ -0,0 +1,97 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.packet.ProtocolVersion;
import org.bukkit.Material;
public class Materials {
private static final int[] MATERIAL_FLAGS = new int[Material.values().length];
public static final int SOLID = 0b00000000000000000000000000001;
public static final int LADDER = 0b00000000000000000000000000010;
public static final int WALL = 0b00000000000000000000000000100;
public static final int STAIRS = 0b00000000000000000000000001000;
public static final int SLABS = 0b00000000000000000000000010000;
public static final int WATER = 0b00000000000000000000000100000;
public static final int LAVA = 0b00000000000000000000001000000;
public static final int LIQUID = 0b00000000000000000000010000000;
public static final int ICE = 0b00000000000000000000100000000;
public static final int FENCE = 0b00000000000000000001000000000;
static {
for (int i = 0; i < MATERIAL_FLAGS.length; i++) {
Material material = Material.values()[i];
//We use the one in BlockUtils also since we can't trust Material to include everything.
if (material.isSolid() || material.name().contains("COMPARATOR") || material.name().contains("DIODE")) {
MATERIAL_FLAGS[i] |= SOLID;
}
if (material.name().endsWith("_STAIRS")) {
MATERIAL_FLAGS[i] |= STAIRS;
}
if (material.name().contains("SLAB") || material.name().contains("STEP")) {
MATERIAL_FLAGS[i] |= SLABS;
}
if(material.name().contains("SKULL"))
MATERIAL_FLAGS[i] = SOLID;
if(material.name().contains("STATIONARY") || material.name().contains("LAVA") || material.name().contains("WATER")) {
if(material.name().contains("LAVA")) {
MATERIAL_FLAGS[i] |= LIQUID | LAVA;
} else MATERIAL_FLAGS[i] |= LIQUID | WATER;
}
}
// fix some types where isSolid() returns the wrong value
MATERIAL_FLAGS[XMaterial.REPEATER.parseMaterial().ordinal()] = SOLID;
MATERIAL_FLAGS[XMaterial.SNOW.parseMaterial().ordinal()] = SOLID;
MATERIAL_FLAGS[XMaterial.ANVIL.parseMaterial().ordinal()] = SOLID;
MATERIAL_FLAGS[XMaterial.LILY_PAD.parseMaterial().ordinal()] = SOLID;
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_8)) {
MATERIAL_FLAGS[XMaterial.SLIME_BLOCK.parseMaterial().ordinal()] = SOLID;
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_14)) {
MATERIAL_FLAGS[XMaterial.SCAFFOLDING.parseMaterial().ordinal()] = SOLID;
}
}
// ladders
MATERIAL_FLAGS[XMaterial.LADDER.parseMaterial().ordinal()] |= LADDER | SOLID;
MATERIAL_FLAGS[XMaterial.VINE.parseMaterial().ordinal()] |= LADDER | SOLID;
for (Material mat : Material.values()) {
if(!mat.isBlock()) continue;
if (mat.name().contains("FENCE")) {
if(!mat.name().contains("GATE")) MATERIAL_FLAGS[mat.ordinal()] |= FENCE;
}
if(mat.name().contains("WALL")) MATERIAL_FLAGS[mat.ordinal()] |= WALL;
if(mat.name().contains("PLATE")) MATERIAL_FLAGS[mat.ordinal()] = 0;
if(mat.name().contains("BED") && !mat.name().contains("ROCK")) MATERIAL_FLAGS[mat.ordinal()] |= SLABS;
if(mat.name().contains("ICE")) MATERIAL_FLAGS[mat.ordinal()] |= ICE;
if(mat.name().contains("CARPET")) MATERIAL_FLAGS[mat.ordinal()] = SOLID;
if(mat.name().contains("SIGN")) MATERIAL_FLAGS[mat.ordinal()] = 0;
}
}
public static int getBitmask(Material material) {
return MATERIAL_FLAGS[material.ordinal()];
}
private Materials() {
}
public static boolean checkFlag(Material material, int flag) {
return (MATERIAL_FLAGS[material.ordinal()] & flag) == flag;
}
public static boolean isUsable(Material material) {
String nameLower = material.name().toLowerCase();
return material.isEdible()
|| nameLower.contains("bow")
|| nameLower.contains("sword")
|| nameLower.contains("trident");
}
}
@@ -0,0 +1,501 @@
package dev.brighten.ac.utils;
import java.util.Random;
import java.util.UUID;
public class MathHelper {
public static final float SQRT_2 = sqrt_float(2.0F);
public static final float PI = (float) Math.PI;
public static final float PI2 = ((float) Math.PI * 2F);
public static final float PId2 = ((float) Math.PI / 2F);
public static final float deg2Rad = 0.017453292F;
private static final int SIN_BITS = 12;
private static final int SIN_MASK = 4095;
private static final int SIN_COUNT = 4096;
private static final float radFull = ((float) Math.PI * 2F);
private static final float degFull = 360.0F;
private static final float radToIndex = 651.8986F;
private static final float degToIndex = 11.377778F;
private static final float[] SIN_TABLE_FAST = new float[4096];
/**
* A table of sin values computed from 0 (inclusive) to 2*pi (exclusive), with steps of 2*PI / 65536.
*/
private static final float[] SIN_TABLE = new float[65536];
/**
* Though it looks like an array, this is really more like a mapping. Key (index of this array) is the upper 5 bits
* of the result of multiplying a 32-bit unsigned integer by the B(2, 5) De Bruijn sequence 0x077CB531. Value
* (value stored in the array) is the unique index (from the right) of the leftmost one-bit in a 32-bit unsigned
* integer that can cause the upper 5 bits to get that value. Used for highly optimized "find the log-base-2 of
* this number" calculations.
*/
private static final int[] multiplyDeBruijnBitPosition;
private static final double field_181163_d;
private static final double[] field_181164_e;
private static final double[] field_181165_f;
private static final String __OBFID = "CL_00001496";
public static boolean fastMath = false;
static {
for (int i = 0; i < 65536; ++i) {
SIN_TABLE[i] = (float) Math.sin((double) i * Math.PI * 2.0D / 65536.0D);
}
for (int j = 0; j < 4096; ++j) {
SIN_TABLE_FAST[j] = (float) Math.sin((double) (((float) j + 0.5F) / 4096.0F * ((float) Math.PI * 2F)));
}
for (int l = 0; l < 360; l += 90) {
SIN_TABLE_FAST[(int) ((float) l * 11.377778F) & 4095] = (float) Math.sin((double) ((float) l * 0.017453292F));
}
multiplyDeBruijnBitPosition = new int[]{0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9};
field_181163_d = Double.longBitsToDouble(4805340802404319232L);
field_181164_e = new double[257];
field_181165_f = new double[257];
for (int k = 0; k < 257; ++k) {
double d1 = (double) k / 256.0D;
double d0 = Math.asin(d1);
field_181165_f[k] = Math.cos(d0);
field_181164_e[k] = d0;
}
}
/**
* sin looked up in a table
*/
public static float sin(float p_76126_0_) {
return fastMath ? SIN_TABLE_FAST[(int) (p_76126_0_ * 651.8986F) & 4095] : SIN_TABLE[(int) (p_76126_0_ * 10430.378F) & 65535];
}
/**
* cos looked up in the sin table with the appropriate offset
*/
public static float cos(float value) {
return fastMath ? SIN_TABLE_FAST[(int) ((value + ((float) Math.PI / 2F)) * 651.8986F) & 4095] : SIN_TABLE[(int) (value * 10430.378F + 16384.0F) & 65535];
}
public static float sqrt_float(float value) {
return (float) Math.sqrt((double) value);
}
public static float sqrt_double(double value) {
return (float) Math.sqrt(value);
}
/**
* Returns the greatest integer less than or equal to the float argument
*/
public static int floor_float(float value) {
int i = (int) value;
return value < (float) i ? i - 1 : i;
}
/**
* returns par0 cast as an int, and no greater than Integer.MAX_VALUE-1024
*/
public static int truncateDoubleToInt(double value) {
return (int) (value + 1024.0D) - 1024;
}
/**
* Returns the greatest integer less than or equal to the double argument
*/
public static int floor_double(double value) {
int i = (int) value;
return value < (double) i ? i - 1 : i;
}
/**
* Long version of floor_double
*/
public static long floor_double_long(double value) {
long i = (long) value;
return value < (double) i ? i - 1L : i;
}
public static int func_154353_e(double value) {
return (int) (value >= 0.0D ? value : -value + 1.0D);
}
public static float abs(float value) {
return value >= 0.0F ? value : -value;
}
/**
* Returns the unsigned value of an int.
*/
public static int abs_int(int value) {
return value >= 0 ? value : -value;
}
public static int ceiling_float_int(float value) {
int i = (int) value;
return value > (float) i ? i + 1 : i;
}
public static int ceiling_double_int(double value) {
int i = (int) value;
return value > (double) i ? i + 1 : i;
}
/**
* Returns the value of the first parameter, clamped to be within the lower and upper limits given by the second and
* third parameters.
*/
public static int clamp_int(int num, int min, int max) {
return num < min ? min : (num > max ? max : num);
}
/**
* Returns the value of the first parameter, clamped to be within the lower and upper limits given by the second and
* third parameters
*/
public static float clamp_float(float num, float min, float max) {
return num < min ? min : (num > max ? max : num);
}
public static double clamp_double(double num, double min, double max) {
return num < min ? min : (num > max ? max : num);
}
public static double denormalizeClamp(double p_151238_0_, double p_151238_2_, double p_151238_4_) {
return p_151238_4_ < 0.0D ? p_151238_0_ : (p_151238_4_ > 1.0D ? p_151238_2_ : p_151238_0_ + (p_151238_2_ - p_151238_0_) * p_151238_4_);
}
/**
* Maximum of the absolute value of two numbers.
*/
public static double abs_max(double p_76132_0_, double p_76132_2_) {
if (p_76132_0_ < 0.0D) {
p_76132_0_ = -p_76132_0_;
}
if (p_76132_2_ < 0.0D) {
p_76132_2_ = -p_76132_2_;
}
return p_76132_0_ > p_76132_2_ ? p_76132_0_ : p_76132_2_;
}
/**
* Buckets an integer with specifed bucket sizes. Args: i, bucketSize
*/
public static int bucketInt(int p_76137_0_, int p_76137_1_) {
return p_76137_0_ < 0 ? -((-p_76137_0_ - 1) / p_76137_1_) - 1 : p_76137_0_ / p_76137_1_;
}
public static int getRandomIntegerInRange(Random p_76136_0_, int p_76136_1_, int p_76136_2_) {
return p_76136_1_ >= p_76136_2_ ? p_76136_1_ : p_76136_0_.nextInt(p_76136_2_ - p_76136_1_ + 1) + p_76136_1_;
}
public static float randomFloatClamp(Random p_151240_0_, float p_151240_1_, float p_151240_2_) {
return p_151240_1_ >= p_151240_2_ ? p_151240_1_ : p_151240_0_.nextFloat() * (p_151240_2_ - p_151240_1_) + p_151240_1_;
}
public static double getRandomDoubleInRange(Random p_82716_0_, double p_82716_1_, double p_82716_3_) {
return p_82716_1_ >= p_82716_3_ ? p_82716_1_ : p_82716_0_.nextDouble() * (p_82716_3_ - p_82716_1_) + p_82716_1_;
}
public static double average(long[] values) {
long i = 0L;
for (long j : values) {
i += j;
}
return (double) i / (double) values.length;
}
public static boolean epsilonEquals(float p_180185_0_, float p_180185_1_) {
return abs(p_180185_1_ - p_180185_0_) < 1.0E-5F;
}
public static int normalizeAngle(int p_180184_0_, int p_180184_1_) {
return (p_180184_0_ % p_180184_1_ + p_180184_1_) % p_180184_1_;
}
/**
* the angle is reduced to an angle between -180 and +180 by mod, and a 360 check
*/
public static float wrapAngleTo180_float(float value) {
value = value % 360.0F;
if (value >= 180.0F) {
value -= 360.0F;
}
if (value < -180.0F) {
value += 360.0F;
}
return value;
}
/**
* the angle is reduced to an angle between -180 and +180 by mod, and a 360 check
*/
public static double wrapAngleTo180_double(double value) {
value = value % 360.0D;
if (value >= 180.0D) {
value -= 360.0D;
}
if (value < -180.0D) {
value += 360.0D;
}
return value;
}
/**
* parses the string as integer or returns the second parameter if it fails
*/
public static int parseIntWithDefault(String p_82715_0_, int p_82715_1_) {
try {
return Integer.parseInt(p_82715_0_);
} catch (Throwable var3) {
return p_82715_1_;
}
}
/**
* parses the string as integer or returns the second parameter if it fails. this value is capped to par2
*/
public static int parseIntWithDefaultAndMax(String p_82714_0_, int p_82714_1_, int p_82714_2_) {
return Math.max(p_82714_2_, parseIntWithDefault(p_82714_0_, p_82714_1_));
}
/**
* parses the string as double or returns the second parameter if it fails.
*/
public static double parseDoubleWithDefault(String p_82712_0_, double p_82712_1_) {
try {
return Double.parseDouble(p_82712_0_);
} catch (Throwable var4) {
return p_82712_1_;
}
}
public static double parseDoubleWithDefaultAndMax(String p_82713_0_, double p_82713_1_, double p_82713_3_) {
return Math.max(p_82713_3_, parseDoubleWithDefault(p_82713_0_, p_82713_1_));
}
/**
* Returns the input value rounded up to the next highest power of two.
*/
public static int roundUpToPowerOfTwo(int value) {
int i = value - 1;
i = i | i >> 1;
i = i | i >> 2;
i = i | i >> 4;
i = i | i >> 8;
i = i | i >> 16;
return i + 1;
}
/**
* Is the given value a power of two? (1, 2, 4, 8, 16, ...)
*/
private static boolean isPowerOfTwo(int value) {
return value != 0 && (value & value - 1) == 0;
}
/**
* Uses a B(2, 5) De Bruijn sequence and a lookup table to efficiently calculate the log-base-two of the given
* value. Optimized for cases where the input value is a power-of-two. If the input value is not a power-of-two,
* then subtract 1 from the return value.
*/
private static int calculateLogBaseTwoDeBruijn(int value) {
value = isPowerOfTwo(value) ? value : roundUpToPowerOfTwo(value);
return multiplyDeBruijnBitPosition[(int) ((long) value * 125613361L >> 27) & 31];
}
/**
* Efficiently calculates the floor of the base-2 log of an integer value. This is effectively the index of the
* highest bit that is set. For example, if the number in binary is 0...100101, this will return 5.
*/
public static int calculateLogBaseTwo(int value) {
return calculateLogBaseTwoDeBruijn(value) - (isPowerOfTwo(value) ? 0 : 1);
}
public static int func_154354_b(int p_154354_0_, int p_154354_1_) {
if (p_154354_1_ == 0) {
return 0;
} else if (p_154354_0_ == 0) {
return p_154354_1_;
} else {
if (p_154354_0_ < 0) {
p_154354_1_ *= -1;
}
int i = p_154354_0_ % p_154354_1_;
return i == 0 ? p_154354_0_ : p_154354_0_ + p_154354_1_ - i;
}
}
public static int func_180183_b(float p_180183_0_, float p_180183_1_, float p_180183_2_) {
return func_180181_b(floor_float(p_180183_0_ * 255.0F), floor_float(p_180183_1_ * 255.0F), floor_float(p_180183_2_ * 255.0F));
}
public static int func_180181_b(int p_180181_0_, int p_180181_1_, int p_180181_2_) {
int i = (p_180181_0_ << 8) + p_180181_1_;
i = (i << 8) + p_180181_2_;
return i;
}
public static int func_180188_d(int p_180188_0_, int p_180188_1_) {
int i = (p_180188_0_ & 16711680) >> 16;
int j = (p_180188_1_ & 16711680) >> 16;
int k = (p_180188_0_ & 65280) >> 8;
int l = (p_180188_1_ & 65280) >> 8;
int i1 = (p_180188_0_ & 255) >> 0;
int j1 = (p_180188_1_ & 255) >> 0;
int k1 = (int) ((float) i * (float) j / 255.0F);
int l1 = (int) ((float) k * (float) l / 255.0F);
int i2 = (int) ((float) i1 * (float) j1 / 255.0F);
return p_180188_0_ & -16777216 | k1 << 16 | l1 << 8 | i2;
}
public static double func_181162_h(double p_181162_0_) {
return p_181162_0_ - Math.floor(p_181162_0_);
}
public static long getCoordinateRandom(int x, int y, int z) {
long i = (long) (x * 3129871) ^ (long) z * 116129781L ^ (long) y;
i = i * i * 42317861L + i * 11L;
return i;
}
public static UUID getRandomUuid(Random rand) {
long i = rand.nextLong() & -61441L | 16384L;
long j = rand.nextLong() & 4611686018427387903L | Long.MIN_VALUE;
return new UUID(i, j);
}
public static double func_181160_c(double p_181160_0_, double p_181160_2_, double p_181160_4_) {
return (p_181160_0_ - p_181160_2_) / (p_181160_4_ - p_181160_2_);
}
public static double func_181159_b(double p_181159_0_, double p_181159_2_) {
double d0 = p_181159_2_ * p_181159_2_ + p_181159_0_ * p_181159_0_;
if (Double.isNaN(d0)) {
return Double.NaN;
} else {
boolean flag = p_181159_0_ < 0.0D;
if (flag) {
p_181159_0_ = -p_181159_0_;
}
boolean flag1 = p_181159_2_ < 0.0D;
if (flag1) {
p_181159_2_ = -p_181159_2_;
}
boolean flag2 = p_181159_0_ > p_181159_2_;
if (flag2) {
double d1 = p_181159_2_;
p_181159_2_ = p_181159_0_;
p_181159_0_ = d1;
}
double d9 = func_181161_i(d0);
p_181159_2_ = p_181159_2_ * d9;
p_181159_0_ = p_181159_0_ * d9;
double d2 = field_181163_d + p_181159_0_;
int i = (int) Double.doubleToRawLongBits(d2);
double d3 = field_181164_e[i];
double d4 = field_181165_f[i];
double d5 = d2 - field_181163_d;
double d6 = p_181159_0_ * d4 - p_181159_2_ * d5;
double d7 = (6.0D + d6 * d6) * d6 * 0.16666666666666666D;
double d8 = d3 + d7;
if (flag2) {
d8 = (Math.PI / 2D) - d8;
}
if (flag1) {
d8 = Math.PI - d8;
}
if (flag) {
d8 = -d8;
}
return d8;
}
}
public static double func_181161_i(double p_181161_0_) {
double d0 = 0.5D * p_181161_0_;
long i = Double.doubleToRawLongBits(p_181161_0_);
i = 6910469410427058090L - (i >> 1);
p_181161_0_ = Double.longBitsToDouble(i);
p_181161_0_ = p_181161_0_ * (1.5D - d0 * p_181161_0_ * p_181161_0_);
return p_181161_0_;
}
public static int func_181758_c(float p_181758_0_, float p_181758_1_, float p_181758_2_) {
int i = (int) (p_181758_0_ * 6.0F) % 6;
float f = p_181758_0_ * 6.0F - (float) i;
float f1 = p_181758_2_ * (1.0F - p_181758_1_);
float f2 = p_181758_2_ * (1.0F - f * p_181758_1_);
float f3 = p_181758_2_ * (1.0F - (1.0F - f) * p_181758_1_);
float f4;
float f5;
float f6;
switch (i) {
case 0:
f4 = p_181758_2_;
f5 = f3;
f6 = f1;
break;
case 1:
f4 = f2;
f5 = p_181758_2_;
f6 = f1;
break;
case 2:
f4 = f1;
f5 = p_181758_2_;
f6 = f3;
break;
case 3:
f4 = f1;
f5 = f2;
f6 = p_181758_2_;
break;
case 4:
f4 = f3;
f5 = f1;
f6 = p_181758_2_;
break;
case 5:
f4 = p_181758_2_;
f5 = f1;
f6 = f2;
break;
default:
throw new RuntimeException("Something went wrong when converting from HSV to RGB. Input was " + p_181758_0_ + ", " + p_181758_1_ + ", " + p_181758_2_);
}
int j = clamp_int((int) (f4 * 255.0F), 0, 255);
int k = clamp_int((int) (f5 * 255.0F), 0, 255);
int l = clamp_int((int) (f6 * 255.0F), 0, 255);
return j << 16 | k << 8 | l;
}
}
@@ -0,0 +1,860 @@
package dev.brighten.ac.utils;
import lombok.val;
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;
public class MathUtils {
public static double offset(Vector from, Vector to) {
from.setY(0);
to.setY(0);
return to.subtract(from).length();
}
public static boolean playerMoved(Location from, Location to) {
return playerMoved(from.toVector(), to.toVector());
}
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;
}
//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.getRotations(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 = getMedian(values.subList(0, values.size() / 2)),
q3 = getMedian(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 = getMedian(values.subList(0, values.size() / 2)),
q3 = getMedian(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 = getMedian(values.subList(0, values.size() / 2)),
q3 = getMedian(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) {
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 getMedian(Iterable<? extends Number> iterable) {
List<Double> data = new ArrayList<>();
for (Number number : iterable) {
data.add(number.doubleValue());
}
return getMedian(data);
}
//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);
}
public static double getDistanceToBox(Vector vec, BoundingBox box) {
return vec.distance(getCenterOfBox(box));
}
public static Vector getCenterOfBox(BoundingBox box) {
return box.getMinimum().midpoint(box.getMaximum());
}
//Returns -1 if fails.
public static <T extends Number> T tryParse(String string) {
try {
return (T)(Number)Double.parseDouble(string);
} catch(NumberFormatException e) {
}
return (T)(Number)(-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 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(double yaw, double pitch) {
Vector vector = new Vector();
vector.setY(-Math.sin(Math.toRadians(pitch)));
double xz = Math.cos(Math.toRadians(pitch));
vector.setX(-xz * Math.sin(Math.toRadians(yaw)));
vector.setZ(xz * Math.cos(Math.toRadians(yaw)));
return vector;
}
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 int getDistanceToGround(Player p) {
Location loc = p.getLocation().clone();
double y = loc.getBlockY();
int distance = 0;
for (double i = y; i >= 0.0; i -= 1.0) {
loc.setY(i);
if (BlockUtils.getBlock(loc).getType().isSolid() || BlockUtils.getBlock(loc).isLiquid()) break;
++distance;
}
return distance;
}
public static double trim(int degree, double d) {
String format = "#.#";
for (int i = 1; i < degree; ++i) {
format = String.valueOf(format) + "#";
}
DecimalFormat twoDForm = new DecimalFormat(format);
return Double.parseDouble(twoDForm.format(d).replaceAll(",", "."));
}
public static float trimFloat(int degree, float d) {
String format = "#.#";
for (int i = 1; i < degree; ++i) {
format = String.valueOf(format) + "#";
}
DecimalFormat twoDForm = new DecimalFormat(format);
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 (T) 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[] getRotations(Location one, Location two) {
double diffX = two.getX() - one.getX();
double diffZ = two.getZ() - one.getZ();
double diffY = two.getY() + 2.0 - 0.4 - (one.getY() + 2.0);
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[] getRotations(LivingEntity origin, LivingEntity point) {
Location two = point.getLocation(), one = origin.getLocation();
double diffX = two.getX() - one.getX();
double diffZ = two.getZ() - one.getZ();
double diffY = two.getY() + 2.0 - 0.4 - (one.getY() + 2.0);
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 boolean isLookingTowardsEntity(Location from, Location to, LivingEntity entity) {
float[] rotFrom = getRotations(from, entity.getLocation()), rotTo = getRotations(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.getRotations(player.getLocation(), entity.getLocation())[0]));
double pitchOffset = Math.abs(Math.abs(player.getEyeLocation().getPitch()) - Math.abs(MathUtils.getRotations(player.getLocation(), entity.getLocation())[1]));
return new double[]{yawOffset, pitchOffset};
}
public static double[] getOffsetFromLocation(Location one, Location two) {
double yaw = MathUtils.getRotations(one, two)[0];
double pitch = MathUtils.getRotations(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,517 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.reflections.impl.CraftReflection;
import dev.brighten.ac.utils.reflections.impl.MinecraftReflection;
import dev.brighten.ac.utils.reflections.types.WrappedClass;
import dev.brighten.ac.utils.reflections.types.WrappedField;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.*;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.Vector;
import java.io.*;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
public class MiscUtils {
public static Material[] array = Arrays.stream(Material.values())
.filter(mat -> mat.name().contains("LEGACY"))
.toArray(Material[]::new);
public static Map<EntityType, Vector> entityDimensions = new HashMap<>();;
public static boolean containsIgnoreCase(String toCheck, String contains) {
return toCheck.toLowerCase().contains(contains.toLowerCase());
}
public static <T> List<T> combineLists(List<T> one, List<T> two) {
List<T> newList = new ArrayList<>();
newList.addAll(one);
newList.addAll(two);
return newList;
}
public static boolean endsWith(double value, String string) {
return String.valueOf(value).endsWith(string);
}
public static void sendMessage(CommandSender player, String message, Object... objects) {
String toSend = String.format(Color.translate(message), objects);
if(player instanceof Player) {
((Player)player).spigot().sendMessage(TextComponent.fromLegacyText(toSend));
} else player.sendMessage(toSend);
}
private static final WrappedField ticksField;
static {
switch (ProtocolVersion.getGameVersion()) {
case V1_19: {
ticksField = MinecraftReflection.minecraftServer
.getFieldByName("S");
break;
}
case V1_18_2:
case V1_18:
case V1_17_1:
case V1_17: {
ticksField = MinecraftReflection.minecraftServer.getFieldByName("V");
break;
}
default: {
ticksField = MinecraftReflection.minecraftServer.getFieldByName("ticks");
break;
}
}
}
private static Object minecraftServer = null;
//TODO Make this use the new abstraction system.
public static int currentTick() {
if(minecraftServer == null) minecraftServer = CraftReflection.getMinecraftServer();
return ticksField.get(minecraftServer);
}
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet());
list.sort(Map.Entry.comparingByValue());
return list.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> b, LinkedHashMap::new));
}
public static LongStream listToStream(Collection<Long> collection) {
LongStream.Builder longBuilder = LongStream.builder();
collection.forEach(longBuilder::add);
return longBuilder.build();
}
/** Nik's method **/
public static <E> E randomElement(final Collection<? extends E> collection) {
if (collection.size() == 0) return null;
int index = new Random().nextInt(collection.size());
if (collection instanceof List) {
return ((List<? extends E>) collection).get(index);
} else {
Iterator<? extends E> iter = collection.iterator();
for (int i = 0; i < index; i++) iter.next();
return iter.next();
}
}
public static String timeStampToDate(long timeStamp) {
SimpleDateFormat format = new SimpleDateFormat("MM/dd/YYYY (hh:mm)");
format.setTimeZone(TimeZone.getTimeZone("America/New_York"));
Date date = new Date(timeStamp);
return format.format(date);
}
public static void copy(InputStream in, File file) {
try {
OutputStream out = new FileOutputStream(file);
int lenght;
byte[] buf = new byte[1024];
while ((lenght = in.read(buf)) > 0)
{
out.write(buf, 0, lenght);
}
out.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static int getOridinal(Material material) {
int i = 0;
for (Material mat : array) {
if(mat.getId() == material.getId()) {
return i;
}
i++;
}
return -1;
}
public static BaseComponent[] toComponentArray(TextComponent message) {
return TextComponent.fromLegacyText(message.toLegacyText());
}
public static String injectColor(String string, String color) {
String[] split = string.split("");
return Arrays.stream(split).map(s -> color + s).collect(Collectors.joining());
}
public static Material getById(int id) {
return Arrays.stream(Material.values()).filter(mat -> mat.getId() == id).findFirst()
.orElse(Material.getMaterial("AIR"));
}
public static String line(String color) {
return color + Color.Strikethrough + "-----------------------------------------------------";
}
public static String line() {
return Color.Strikethrough + "-----------------------------------------------------";
}
public static String lineNoStrike(String color) {
return color + "-----------------------------------------------------";
}
public static long copy(InputStream from, OutputStream to) throws IOException {
if(from == null || to == null) return 0;
byte[] buf = new byte[4096];
long total = 0L;
int r ;
while((r = from.read(buf)) != -1) {
to.write(buf, 0, r);
total += r;
}
return total;
}
private static WrappedClass materialClass = new WrappedClass(Material.class);
public static Material match(String material) {
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_13)) {
return materialClass
.getMethod("matchMaterial", String.class, boolean.class)
.invoke(null, material, material.contains("LEGACY_"));
} return Material.getMaterial(material.replace("LEGACY_", ""));
}
public static <T> List<T> combine(List<T> one, List<T> two) {
if(one != null)
one.addAll(two);
else return two;
return one;
}
public static void printToConsole(String string, Object... objects) {
Bukkit.getConsoleSender().sendMessage(Color.translate(String.format(string, objects)));
}
public static void printToConsole(String string) {
Bukkit.getConsoleSender().sendMessage(Color.translate(string));
}
public static String trimEnd(String string) {
if(string.length() <= 1) {
return string;
}
return string.substring(0, string.length() - 1);
}
public static String[] splitIntoLine(String input, int maxCharInLine) {
StringTokenizer tok = new StringTokenizer(input, " ");
StringBuilder output = new StringBuilder(input.length());
int lineLen = 0;
while (tok.hasMoreTokens()) {
String word = tok.nextToken();
while (word.length() > maxCharInLine) {
output.append(word.substring(0, maxCharInLine - lineLen) + "\n");
word = word.substring(maxCharInLine - lineLen);
lineLen = 0;
}
if (lineLen + word.length() > maxCharInLine) {
output.append("\n");
lineLen = 0;
}
output.append("&f" + word + " ");
lineLen += word.length() + 1;
}
// output.split();
// return output.toString();
return output.toString().split("\n");
}
public static <T> T getResult(Supplier<T> consumer) {
return consumer.get();
}
public static String lineNoStrike() {
return "-----------------------------------------------------";
}
public static String unloadPlugin(String pl) {
PluginManager pm = Bukkit.getServer().getPluginManager();
SimplePluginManager spm = (SimplePluginManager)pm;
SimpleCommandMap cmdMap = null;
List plugins = null;
Map names = null;
Map commands = null;
Map listeners = null;
boolean reloadlisteners = true;
if(spm != null) {
try {
Field tp = spm.getClass().getDeclaredField("plugins");
tp.setAccessible(true);
plugins = (List)tp.get(spm);
Field arr$ = spm.getClass().getDeclaredField("lookupNames");
arr$.setAccessible(true);
names = (Map)arr$.get(spm);
Field len$;
try {
len$ = spm.getClass().getDeclaredField("listeners");
len$.setAccessible(true);
listeners = (Map)len$.get(spm);
} catch (Exception var19) {
reloadlisteners = false;
}
len$ = spm.getClass().getDeclaredField("commandMap");
len$.setAccessible(true);
cmdMap = (SimpleCommandMap)len$.get(spm);
Field i$ = cmdMap.getClass().getDeclaredField("knownCommands");
i$.setAccessible(true);
commands = (Map)i$.get(cmdMap);
} catch (IllegalAccessException | NoSuchFieldException var20) {
return "Failed to unload plugin!";
}
}
String var21 = "";
Plugin[] var22 = Bukkit.getServer().getPluginManager().getPlugins();
int var23 = var22.length;
for(int var24 = 0; var24 < var23; ++var24) {
Plugin p = var22[var24];
if(p.getDescription().getName().equalsIgnoreCase(pl)) {
pm.disablePlugin(p);
var21 = var21 + p.getName() + " ";
if(plugins != null && plugins.contains(p)) {
plugins.remove(p);
}
if(names != null && names.containsKey(pl)) {
names.remove(pl);
}
Iterator it;
if(listeners != null && reloadlisteners) {
it = listeners.values().iterator();
while(it.hasNext()) {
SortedSet entry = (SortedSet)it.next();
Iterator c = entry.iterator();
while(c.hasNext()) {
RegisteredListener value = (RegisteredListener)c.next();
if(value.getPlugin() == p) {
c.remove();
}
}
}
}
if(cmdMap != null) {
it = commands.entrySet().iterator();
while(it.hasNext()) {
Map.Entry var25 = (Map.Entry) it.next();
if(var25.getValue() instanceof PluginCommand) {
PluginCommand var26 = (PluginCommand)var25.getValue();
if(var26.getPlugin() == p) {
var26.unregister(cmdMap);
it.remove();
}
}
}
}
}
}
return var21 + "has been unloaded and disabled!";
}
//Stolen from Luke
public static boolean contains(Object[] array, Object obj) {
for (Object object : array) if (object != null && object.equals(obj)) return true;
return false;
}
public static <T> T parseObjectFromString(String s, Class<T> clazz) throws Exception {
return clazz.getConstructor(new Class[] {String.class}).newInstance(s);
}
public static BoundingBox getEntityBoundingBox(LivingEntity entity) {
if (entityDimensions.containsKey(entity.getType())) {
Vector entityVector = entityDimensions.get(entity.getType());
float minX = (float) Math.min(-entityVector.getX() + entity.getLocation().getX(), entityVector.getX() + entity.getLocation().getX());
float minY = (float) Math.min(entity.getLocation().getY(), entityVector.getY() + entity.getLocation().getY());
float minZ = (float) Math.min(-entityVector.getZ() + entity.getLocation().getZ(), entityVector.getZ() + entity.getLocation().getZ());
float maxX = (float) Math.max(-entityVector.getX() + entity.getLocation().getX(), entityVector.getX() + entity.getLocation().getX());
float maxY = (float) Math.max(entity.getLocation().getY(), entityVector.getY() + entity.getLocation().getY());
float maxZ = (float) Math.max(-entityVector.getZ() + entity.getLocation().getZ(), entityVector.getZ() + entity.getLocation().getZ());
return new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
}
return ReflectionsUtil.toBoundingBox(ReflectionsUtil.getBoundingBox(entity));
}
/* MAKE SURE TO ONLY RUN THIS METHOD IN onLoad() AND NO WHERE ELSE */
public static void registerCommand(String name, JavaPlugin plugin) {
plugin.getDescription().getCommands().put(name, new HashMap<>());
}
public static ItemStack createItem(Material material, int amount, String name, String... lore) {
ItemStack thing = new ItemStack(material, amount);
ItemMeta thingm = thing.getItemMeta();
thingm.setDisplayName(Color.translate(name));
ArrayList<String> loreList = new ArrayList<>();
for (String string : lore) {
loreList.add(Color.translate(string));
}
thingm.setLore(loreList);
thing.setItemMeta(thingm);
return thing;
}
public static boolean arraysSimilar(String[] one, String[] two) {
if(one.length != two.length) return false;
for (int i = 0; i < one.length; i++) {
String a1 = one[i], a2 = two[i];
if(!a1.equalsIgnoreCase(a2)) {
return false;
}
}
return true;
}
public static List<File> getAtlasDependingPlugins() {
List<File> plugins = new ArrayList<>();
final File pluginDir = new File("plugins");
if (!pluginDir.isDirectory()) {
return plugins;
}
for (final File f : pluginDir.listFiles()) {
try {
if (f.getName().endsWith(".jar")) {
final PluginDescriptionFile pdf = Anticheat.INSTANCE.getPluginLoader().getPluginDescription(f);
if (pdf.getDepend().contains("Atlas")) {
plugins.add(f);
}
}
}
catch (InvalidDescriptionException e2) {
//Empty catch block.
}
}
return plugins;
}
public static void loadPlugin(final String pl) {
Plugin targetPlugin = null;
String msg = "";
final File pluginDir = new File("plugins");
if (!pluginDir.isDirectory()) {
return;
}
File pluginFile = new File(pluginDir, pl + ".jar");
if (!pluginFile.isFile()) {
for (final File f : pluginDir.listFiles()) {
try {
if (f.getName().endsWith(".jar")) {
final PluginDescriptionFile pdf = Anticheat.INSTANCE.getPluginLoader().getPluginDescription(f);
if (pdf.getName().equalsIgnoreCase(pl)) {
pluginFile = f;
msg = "(via search) ";
break;
}
}
}
catch (InvalidDescriptionException e2) {
return;
}
}
}
try {
Anticheat.INSTANCE.getServer().getPluginManager().loadPlugin(pluginFile);
targetPlugin = getPlugin(pl);
Anticheat.INSTANCE.getServer().getPluginManager().enablePlugin(targetPlugin);
}
catch (UnknownDependencyException | InvalidPluginException | InvalidDescriptionException e3) {
e3.printStackTrace();
}
}
private static Plugin getPlugin(final String p) {
for (final Plugin pl : Anticheat.INSTANCE.getServer().getPluginManager().getPlugins()) {
if (pl.getDescription().getName().equalsIgnoreCase(p)) {
return pl;
}
}
return null;
}
public static <T> T getArgOrNull(T[] array, int index) {
if(array.length > index) {
return array[index];
}
return null;
}
static {
entityDimensions.put(EntityType.WOLF, new Vector(0.31, 0.8, 0.31));
entityDimensions.put(EntityType.SHEEP, new Vector(0.45, 1.3, 0.45));
entityDimensions.put(EntityType.COW, new Vector(0.45, 1.3, 0.45));
entityDimensions.put(EntityType.PIG, new Vector(0.45, 0.9, 0.45));
entityDimensions.put(EntityType.MUSHROOM_COW, new Vector(0.45, 1.3, 0.45));
entityDimensions.put(EntityType.WITCH, new Vector(0.31, 1.95, 0.31));
entityDimensions.put(EntityType.BLAZE, new Vector(0.31, 1.8, 0.31));
entityDimensions.put(EntityType.PLAYER, new Vector(0.3, 1.8, 0.3));
entityDimensions.put(EntityType.VILLAGER, new Vector(0.31, 1.8, 0.31));
entityDimensions.put(EntityType.CREEPER, new Vector(0.31, 1.8, 0.31));
entityDimensions.put(EntityType.GIANT, new Vector(1.8, 10.8, 1.8));
entityDimensions.put(EntityType.SKELETON, new Vector(0.31, 1.8, 0.31));
entityDimensions.put(EntityType.ZOMBIE, new Vector(0.31, 1.8, 0.31));
entityDimensions.put(EntityType.SNOWMAN, new Vector(0.35, 1.9, 0.35));
entityDimensions.put(EntityType.HORSE, new Vector(0.7, 1.6, 0.7));
entityDimensions.put(EntityType.ENDER_DRAGON, new Vector(1.5, 1.5, 1.5));
entityDimensions.put(EntityType.ENDERMAN, new Vector(0.31, 2.9, 0.31));
entityDimensions.put(EntityType.CHICKEN, new Vector(0.2, 0.7, 0.2));
entityDimensions.put(EntityType.OCELOT, new Vector(0.31, 0.7, 0.31));
entityDimensions.put(EntityType.SPIDER, new Vector(0.7, 0.9, 0.7));
entityDimensions.put(EntityType.WITHER, new Vector(0.45, 3.5, 0.45));
entityDimensions.put(EntityType.IRON_GOLEM, new Vector(0.7, 2.9, 0.7));
entityDimensions.put(EntityType.GHAST, new Vector(2, 4, 2));
}
}
@@ -0,0 +1,113 @@
package dev.brighten.ac.utils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class Pastebin {
static String pasteURL = "https://funkemunky.cc/pastebin/make";
public Pastebin() {
}
static String checkResponse(String response) {
if (response.substring(0, 15).equals("Bad API request")) {
return response.substring(17);
}
return "";
}
static public String makePaste(String body, String name, Privacy privacy)
throws UnsupportedEncodingException {
String content = URLEncoder.encode(body, "UTF-8");
String title = URLEncoder.encode(name + " report", "UTF-8");
String data = "body=" + content + "&name=" + title + "&privacy=" + privacy.name();
String response = Pastebin.page(Pastebin.pasteURL, data);
if(response == null) return "";
String check = Pastebin.checkResponse(response);
if (!check.equals("")) {
return check;
}
return response;
}
static public String makePaste(String body, String name, Privacy privacy, String expire)
throws UnsupportedEncodingException {
String content = URLEncoder.encode(body, "UTF-8");
String title = URLEncoder.encode(name + " report", "UTF-8");
String data = "body=" + content + "&name=" + title + "&privacy=" + privacy.name() + "&expire=" + expire;
String response = Pastebin.page(Pastebin.pasteURL, data);
String check = Pastebin.checkResponse(response);
if (!check.equals("")) {
return check;
}
return response;
}
public static String page(String uri, String urlParameters) {
URL url;
HttpURLConnection connection = null;
try {
// Create connection
url = new URL(uri);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length",
"" + Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
// Send request
DataOutputStream wr = new DataOutputStream(
connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
// Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while ((line = rd.readLine()) != null) {
response.append(line);
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
public static enum Privacy {
PUBLIC(0), UNLISTED(1), PRIVATE(2);
private int privacy;
Privacy(int privacy) {
this.privacy = privacy;
}
public int getPrivacy() {
return privacy;
}
}
}
@@ -0,0 +1,106 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.packet.ProtocolVersion;
import lombok.val;
import org.bukkit.Location;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
public class PlayerUtils {
private static Enchantment DEPTH;
public static int getDepthStriderLevel(Player player) {
if(DEPTH == null) return 0;
val boots = player.getInventory().getBoots();
if(boots == null) return 0;
return boots.getEnchantmentLevel(DEPTH);
}
public static boolean hasBlocksAround(Location loc) {
Location one = loc.clone().subtract(1, 0, 1), two = loc.clone().add(1, 1, 1);
int minX = Math.min(one.getBlockX(), two.getBlockX()), minY = Math.min(one.getBlockY(), two.getBlockY()), minZ = Math.min(one.getBlockZ(), two.getBlockZ());
int maxX = Math.max(one.getBlockX(), two.getBlockX()), maxY = Math.max(one.getBlockY(), two.getBlockY()), maxZ = Math.max(one.getBlockZ(), two.getBlockZ());
for (int x = minX; x < maxX; x++) {
for (int y = minY; y < maxY; y++) {
for (int z = minZ; z < maxZ; z++) {
Location blockLoc = new Location(loc.getWorld(), x, y, z);
if (BlockUtils.isSolid(BlockUtils.getBlock(blockLoc))) {
return true;
}
}
}
}
return false;
}
public static boolean facingOpposite(Entity one, Entity two) {
return one.getLocation().getDirection().distance(two.getLocation().getDirection()) < 0.5;
}
public static boolean isGliding(Player p) {
if (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_9)) return false;
boolean isGliding = false;
try {
isGliding = (boolean) p.getClass().getMethod("isGliding", new Class[0]).invoke(p, new Object[0]);
} catch (Exception e) {
e.printStackTrace();
}
return isGliding;
}
public static double getAccurateDistance(LivingEntity attacked, LivingEntity entity) {
Location origin = attacked.getEyeLocation(), point;
if (entity.getLocation().getY() > attacked.getLocation().getBlockY()) {
point = entity.getLocation();
} else {
point = entity.getEyeLocation();
}
return origin.distance(point);
}
public static double getAccurateDistance(Location origin, Location point) {
return origin.distance(point) * Math.cos(origin.getPitch());
}
public static int getPotionEffectLevel(Player player, PotionEffectType pet) {
for (PotionEffect pe : player.getActivePotionEffects()) {
if (!pe.getType().getName().equals(pet.getName())) continue;
return pe.getAmplifier() + 1;
}
return 0;
}
public static float getJumpHeight(Player player) {
float baseHeight = 0.42f;
if(player.hasPotionEffect(PotionEffectType.JUMP)) {
baseHeight+= PlayerUtils.getPotionEffectLevel(player, PotionEffectType.JUMP) * 0.1f;
}
return baseHeight;
}
static {
try {
if(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_8)) {
DEPTH = Enchantment.getByName("DEPTH_STRIDER");
}
} catch(Exception e) {
DEPTH = null;
}
}
}
@@ -0,0 +1,14 @@
package dev.brighten.ac.utils;
import lombok.Getter;
@Getter
public enum Priority {
LOWEST(1), LOW(2), NORMAL(3), HIGH(4), HIGHEST(5);
int priority;
Priority(int priority) {
this.priority = priority;
}
}
@@ -0,0 +1,595 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.reflections.Reflections;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Step;
import org.bukkit.material.WoodenStep;
import org.bukkit.util.Vector;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
public class ReflectionsUtil {
public static Class<?> blockPosition = null;
private static String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
public static Class<?> EntityPlayer = getNMSClass("EntityPlayer");
public static Class<?> Entity = getNMSClass("Entity");
public static Class<?> CraftPlayer = getCBClass("entity.CraftPlayer");
public static Class<?> CraftEntity = getCBClass("entity.CraftEntity");
public static Class<?> CraftWorld = getCBClass("CraftWorld");
private static Class<?> craftServer = getCBClass("CraftServer");
public static Class<?> World = getNMSClass("World");
public static Class<?> worldServer = getNMSClass("WorldServer");
public static Class<?> playerConnection = getNMSClass("PlayerConnection");
public static Class<?> networkManager = getNMSClass("NetworkManager");
public static Class<?> minecraftServer = getNMSClass("MinecraftServer"), nmsItemStack = getNMSClass("ItemStack");
public static Class<?> packet = getNMSClass("Packet");
public static Class<?> iBlockData = null;
public static Class<?> iBlockAccess = null;
private static Class<?> vanillaBlock = getNMSClass("Block");
private static Method getCubes = getMethod(World, "a", getNMSClass("AxisAlignedBB"));
private static Method getCubes1_12 = getMethod(World, "getCubes", getNMSClass("Entity"), getNMSClass("AxisAlignedBB"));
public static Object getEntityPlayer(Player player) {
return getMethodValue(getMethod(CraftPlayer, "getHandle"), player);
}
public static Object getEntity(org.bukkit.entity.Entity entity) {
return getMethodValue(getMethod(CraftEntity, "getHandle"), entity);
}
public static Object getExpandedBoundingBox(Object box, double x, double y, double z) {
return getMethodValue(getMethod(box.getClass(), "grow", double.class, double.class, double.class), box, x, y, z);
}
public static Object modifyBoundingBox(Object box, double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
double newminX = (double) getFieldValue(getFieldByName(box.getClass(), "a"), box) - minX;
double newminY = (double) getFieldValue(getFieldByName(box.getClass(), "b"), box) - minY;
double newminZ = (double) getFieldValue(getFieldByName(box.getClass(), "c"), box) - minZ;
double newmaxX = (double) getFieldValue(getFieldByName(box.getClass(), "d"), box) + maxX;
double newmaxY = (double) getFieldValue(getFieldByName(box.getClass(), "e"), box) + maxY;
double newmaxZ = (double) getFieldValue(getFieldByName(box.getClass(), "f"), box) + maxZ;
return newInstance(getNMSClass("AxisAlignedBB"), newminX, newminY, newminZ, newmaxX, newmaxY, newmaxZ);
}
private static Vector getBoxMin(Object box) {
if (hasField(box.getClass(), "a")) {
double x = (double) getFieldValue(getFieldByName(box.getClass(), "a"), box);
double y = (double) getFieldValue(getFieldByName(box.getClass(), "b"), box);
double z = (double) getFieldValue(getFieldByName(box.getClass(), "c"), box);
return new Vector(x, y, z);
} else {
double x = (double) getFieldValue(getFieldByName(box.getClass(), "minX"), box);
double y = (double) getFieldValue(getFieldByName(box.getClass(), "minY"), box);
double z = (double) getFieldValue(getFieldByName(box.getClass(), "minZ"), box);
return new Vector(x, y, z);
}
}
public static Object getMinecraftServer() {
return getMethodValue(getMethod(craftServer, "getServer"), Bukkit.getServer());
}
private static Vector getBoxMax(Object box) {
if (hasField(box.getClass(), "d")) {
double x = (double) getFieldValue(getFieldByName(box.getClass(), "d"), box);
double y = (double) getFieldValue(getFieldByName(box.getClass(), "e"), box);
double z = (double) getFieldValue(getFieldByName(box.getClass(), "f"), box);
return new Vector(x, y, z);
} else {
double x = (double) getFieldValue(getFieldByName(box.getClass(), "maxX"), box);
double y = (double) getFieldValue(getFieldByName(box.getClass(), "maxY"), box);
double z = (double) getFieldValue(getFieldByName(box.getClass(), "maxZ"), box);
return new Vector(x, y, z);
}
}
public static BoundingBox toBoundingBox(Object aaBB) {
Vector min = getBoxMin(aaBB);
Vector max = getBoxMax(aaBB);
return new BoundingBox((float) min.getX(), (float) min.getY(), (float) min.getZ(), (float) max.getX(), (float) max.getY(), (float) max.getZ());
}
public static float getBlockDurability(Block block) {
Object vanillaBlock = getVanillaBlock(block);
return (float) getFieldValue(getFieldByName(getNMSClass("Block"), "strength"), vanillaBlock);
}
public static boolean canDestroyBlock(Player player, Block block) {
Object inventory = getVanillaInventory(player);
return (boolean) getMethodValue(getMethod(getNMSClass("PlayerInventory"), "b", getNMSClass("Block")), inventory, ProtocolVersion.getGameVersion().isAbove(ProtocolVersion.V1_8_9) ? getBlockData(block) : getVanillaBlock(block));
}
public static Object getVanillaInventory(Player player) {
return getMethodValue(getMethod(getCBClass("inventory.CraftInventoryPlayer"), "getInventory"), player.getInventory());
}
private static Field frictionFactorField = getFieldByName(vanillaBlock, "frictionFactor");
public static float getFriction(Block block) {
Object blockNMS = getVanillaBlock(block);
return (float) getFieldValue(frictionFactorField, blockNMS);
}
public static Object getBlockPosition(Location location) {
if (ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_8)) {
return newInstance(blockPosition, location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
return null;
}
public static List<org.bukkit.entity.Entity> getEntitiesInWorld(org.bukkit.World world) {
Object worldHandle = getWorldHandle(world);
List<org.bukkit.entity.Entity> toReturn = new ArrayList<>();
List<Object> entityList = new ArrayList<>((List<Object>) getFieldValue(getFieldByName(getNMSClass("World"), "entityList"), worldHandle));
Class<?> entity = getNMSClass("Entity");
entityList.forEach(object -> {
Object bEntity = getMethodValue(getMethod(entity, "getBukkitEntity"), object);
if(bEntity != null) {
toReturn.add((org.bukkit.entity.Entity) bEntity);
}
});
return toReturn;
}
public static BoundingBox getBlockBoundingBox(Block block) {
try {
if (!isBukkitVerison("1_7")) {
Object bPos = blockPosition.getConstructor(int.class, int.class, int.class).newInstance(block.getLocation().getBlockX(), block.getLocation().getBlockY(), block.getLocation().getBlockZ());
Object world = getWorldHandle(block.getWorld());
Object data = getMethodValue(getMethod(world.getClass(), "getType", blockPosition), world, bPos);
Object blockNMS = getMethodValue(getMethod(getNMSClass("IBlockData"), "getBlock"), data);
if (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_13)) {
if (!isNewVersion()) {
if (getMethodValueNoST(getMethodNoST(blockNMS.getClass(), "a", World, blockPosition, iBlockData), blockNMS, world, bPos, data) != null
&& !BlockUtils.isSlab(block)) {
BoundingBox box = toBoundingBox(getMethodValue(getMethod(blockNMS.getClass(), "a", World, blockPosition, iBlockData), blockNMS, world, bPos, data));
if (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_13)) {
if (block.getType().toString().contains("STEP") && !block.getType().toString().contains("WOOD")) {
Step slab = (Step) block.getType().getNewData(block.getData());
box.minY = block.getY();
box.maxY = block.getY();
if (slab.isInverted()) {
box = box.add(0, 0.5f, 0, 0, 1f, 0);
} else {
box = box.add(0, 0f, 0, 0, 0.5f, 0);
}
} else if (block.getType().toString().contains("STEP")) {
WoodenStep slab = (WoodenStep) block.getType().getNewData(block.getData());
box.minY = block.getY();
box.maxY = block.getY();
if (slab.isInverted()) {
box = box.add(0, 0.5f, 0, 0, 1f, 0);
} else {
box = box.add(0, 0f, 0, 0, 0.5f, 0);
}
}
}
return box;
} else if (getMethodValueNoST(getMethodNoST(vanillaBlock, "a", World, blockPosition, iBlockData), blockNMS, world, bPos, data) != null) {
BoundingBox box = toBoundingBox(getMethodValue(getMethod(vanillaBlock, "a", World, blockPosition, iBlockData), blockNMS, world, bPos, data));
if (ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_13)) {
if (block.getType().toString().contains("STEP") && !block.getType().toString().contains("WOOD")) {
Step slab = (Step) block.getType().getNewData(block.getData());
box.minY = block.getY();
box.maxY = block.getY();
if (slab.isInverted()) {
box = box.add(0, 0.5f, 0, 0, 1f, 0);
} else {
box = box.add(0, 0f, 0, 0, 0.5f, 0);
}
} else if (block.getType().toString().contains("STEP")) {
WoodenStep slab = (WoodenStep) block.getType().getNewData(block.getData());
box.minY = block.getY();
box.maxY = block.getY();
if (slab.isInverted()) {
box = box.add(0, 0.5f, 0, 0, 1f, 0);
} else {
box = box.add(0, 0f, 0, 0, 0.5f, 0);
}
}
}
return box;
} else {
return new BoundingBox(block.getX(), block.getY(), block.getZ(), block.getX(), block.getY(), block.getZ());
}
} else {
if (getMethodValueNoST(getMethodNoST(blockNMS.getClass(), "a", iBlockData, getNMSClass("IBlockAccess"), blockPosition), blockNMS, data, world, bPos) != null) {
return toBoundingBox(getMethodValue(getMethod(blockNMS.getClass(), "a", iBlockData, getNMSClass("IBlockAccess"), blockPosition), blockNMS, data, world, bPos)).add(block.getX(), block.getY(), block.getZ(), block.getX(), block.getY(), block.getZ());
} else if (getMethodValueNoST(getMethodNoST(vanillaBlock, "a", iBlockData, getNMSClass("IBlockAccess"), blockPosition), blockNMS, data, world, bPos) != null) {
return toBoundingBox(getMethodValue(getMethod(vanillaBlock, "a", iBlockData, getNMSClass("IBlockAccess"), blockPosition), blockNMS, data, world, bPos)).add(block.getX(), block.getY(), block.getZ(), block.getX(), block.getY(), block.getZ());
} else {
return new BoundingBox(block.getX(), block.getY(), block.getZ(), block.getX(), block.getY(), block.getZ());
}
}
} else {
Object voxelShape = getMethodValue(getMethod(vanillaBlock, "a", iBlockData, getNMSClass("IBlockAccess"), blockPosition), blockNMS, data, world, bPos);
Object axisAlignedBB = getMethodValue(getMethod(getNMSClass("VoxelShape"), "a"), voxelShape);
return toBoundingBox(axisAlignedBB);
}
} else {
Object blockNMS = getVanillaBlock(block);
Object world = getWorldHandle(block.getWorld());
if (getMethodValueNoST(getMethodNoST(vanillaBlock, "a", getNMSClass("World"), int.class, int.class, int.class), blockNMS, world, block.getLocation().getBlockX(), block.getLocation().getBlockY(), block.getLocation().getBlockZ()) != null) {
return toBoundingBox(getMethodValue(getMethod(vanillaBlock, "a", getNMSClass("World"), int.class, int.class, int.class), blockNMS, world, block.getLocation().getBlockX(), block.getLocation().getBlockY(), block.getLocation().getBlockZ()));
} else {
//Bukkit.broadcastMessage(block.getType().name());
return new BoundingBox(block.getX(), block.getY(), block.getZ(), block.getX(), block.getY(), block.getZ());
}
}
} catch (Exception e) {
Bukkit.getLogger().log(Level.SEVERE, "Error occured with block: " + block.getType().toString());
e.printStackTrace();
}
return null;
}
public static double getTPS(Server server) {
Object handle = getMethodValue(getMethod(getCBClass("CraftServer"), "getHandle"), server);
return (int) getFieldValue(getFieldByName(getNMSClass("MinecraftServer"), "TPS"), handle);
}
public static float getBlockHardness(final Material material) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
if (!material.isBlock())
return 0;
final int blockId = material.getId();
final Object nmsBlock = getNMSClass("Block").getMethod("getById", Integer.TYPE).invoke(null, blockId);
try {
final Field field = nmsBlock.getClass().getDeclaredField("strength");
field.setAccessible(true);
return (float) field.get(nmsBlock);
} catch (final NoSuchFieldException e) {
return 0.0F;
}
}
public static float getDestroySpeed(Block block, Player player) {
if (ProtocolVersion.getGameVersion().isAbove(ProtocolVersion.V1_8_9)) {
Object item = getVanillaItem(player.getItemInHand());
return (float) getMethodValue(getMethod(getNMSClass("Item"), "getDestroySpeed", nmsItemStack, getNMSClass("IBlockData")), item, getVanillaItemStack(player.getItemInHand()), getBlockData(block));
} else {
Object item = getVanillaItem(player.getInventory().getItemInHand());
return (float) getMethodValue(getMethod(getNMSClass("Item"), "getDestroySpeed", nmsItemStack, getNMSClass("Block")), item, getVanillaItemStack(player.getInventory().getItemInHand()), getVanillaBlock(block));
}
}
private static Method getItemMethod = getMethod(nmsItemStack, "getItem");
public static Object getVanillaItem(ItemStack itemStack) {
return getMethodValue(getMethod(nmsItemStack, "getItem"), getVanillaItemStack(itemStack));
}
public static Object getVanillaItemStack(ItemStack itemStack) {
return getMethodValue(getMethod(getCBClass("inventory.CraftItemStack"), "asNMSCopy", getClass("org.bukkit.inventory.ItemStack")), itemStack, itemStack);
}
private static Method getBlockMethod = null,
getTypeMethod = null;
public static Object getVanillaBlock(Block block) {
if (!isBukkitVerison("1_7")) {
if(getBlockMethod == null) getBlockMethod = getMethod(iBlockData, "getBlock");
Object getType = getBlockData(block);
return getMethodValue(getBlockMethod, getType);
} else {
if(getTypeMethod == null) getTypeMethod = getMethod(worldServer, "getType", int.class, int.class, int.class);
Object world = getWorldHandle(block.getWorld());
return getMethodValue(getTypeMethod, world, block.getLocation().getBlockX(), block.getLocation().getBlockY(), block.getLocation().getBlockZ());
}
}
private static Constructor blockPosConstructor = null;
private static Method getTypeMethod2 = null;
public static Object getBlockData(Block block) {
try {
if (!isBukkitVerison("1_7")) {
if(blockPosConstructor == null) blockPosConstructor = blockPosition.getConstructor(int.class, int.class, int.class);
Object bPos = blockPosConstructor.newInstance(block.getX(), block.getY(), block.getZ());
Object world = getWorldHandle(block.getWorld());
if(getTypeMethod2 == null) getTypeMethod2 = getMethod(worldServer, "getType", blockPosition);
return getMethodValue(getTypeMethod2, world, bPos);
} else {
Object world = getWorldHandle(block.getWorld());
if(getTypeMethod2 == null) getTypeMethod2 = getMethod(worldServer, "getType", int.class, int.class, int.class);
return getMethodValue(getTypeMethod2, world, block.getX(), block.getY(), block.getZ());
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object getBelowBox(Player player, double below) {
Object box = getBoundingBox(player);
double minX = (double) getFieldValue(getFieldByName(box.getClass(), "a"), box);
double minY = (double) getFieldValue(getFieldByName(box.getClass(), "b"), box) - below;
double minZ = (double) getFieldValue(getFieldByName(box.getClass(), "c"), box);
double maxX = (double) getFieldValue(getFieldByName(box.getClass(), "d"), box);
double maxY = (double) getFieldValue(getFieldByName(box.getClass(), "e"), box);
double maxZ = (double) getFieldValue(getFieldByName(box.getClass(), "f"), box);
try {
return getNMSClass("AxisAlignedBB").getConstructor(double.class, double.class, double.class, double.class, double.class, double.class).newInstance(minX, minY, minZ, maxX, maxY, maxZ);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object getBoundingBox(Player player) {
return getBoundingBox((org.bukkit.entity.Entity) player);
}
public static Object getBoundingBox(org.bukkit.entity.Entity entity) {
return isBukkitVerison("1_7") ? getFieldValue(getFieldByName(Entity, "boundingBox"), getEntity(entity)) : getMethodValue(getMethod(Entity, "getBoundingBox"), getEntity(entity));
}
public static boolean isBukkitVerison(String version) {
return ProtocolVersion.getGameVersion().getServerVersion().contains(version);
}
public static File getPluginFolder() {
Object console = getMethodValue(getMethod(getCBClass("CraftServer"), "console"), Anticheat.INSTANCE.getServer());
Object options = getFieldValue(getFieldByName(getNMSClass("MinecraftServer"), "options"), console);
return (File) getMethodValue(getMethod(getNMSClass("OptionSet"), "valueOf", String.class), options, "plugins");
}
public static boolean isNewVersion() {
return isBukkitVerison("1_9") || isBukkitVerison("1_1");
}
public static Class<?> getCBClass(String string) {
return getClass("org.bukkit.craftbukkit." + version + "." + string);
}
public static Object newAxisAlignedBB(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
try {
return isBukkitVerison("1_7") ? getMethodValue(getMethod(getNMSClass("AxisAlignedBB"), "a", double.class, double.class, double.class, double.class, double.class, double.class), null, minX, minY, minZ, maxX, maxY, maxZ) : getNMSClass("AxisAlignedBB").getConstructor(double.class, double.class, double.class, double.class, double.class, double.class).newInstance(minX, minY, minZ, maxX, maxY, maxZ);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Object newVoxelShape(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
try {
return getNMSClass("AxisAlignedBB").getConstructor(double.class, double.class, double.class, double.class, double.class, double.class).newInstance(minX, minY, minZ, maxX, maxY, maxZ);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static double getMotionY(Player player) {
double motionY = 0;
try {
motionY = (double) ReflectionsUtil.getEntityPlayer(player).getClass().getField("motY").get(ReflectionsUtil.getEntityPlayer(player));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return motionY;
}
public static Object newAxisAlignedBB(Location from, Location to) {
double minX = Math.min(from.getX(), to.getX());
double minY = Math.min(from.getY(), to.getY());
double minZ = Math.min(from.getZ(), to.getZ());
double maxX = Math.max(from.getX(), to.getX());
double maxY = Math.max(from.getY(), to.getY());
double maxZ = Math.max(from.getZ(), to.getZ());
try {
return getNMSClass("AxisAlignedBB").getConstructor(double.class, double.class, double.class, double.class, double.class, double.class).newInstance(minX, minY, minZ, maxX, maxY, maxZ);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Class<?> getClass(String string) {
try {
return Class.forName(string);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
@SuppressWarnings("unchecked")
public static Enum<?> getEnum(Class<?> clazz, String enumName) {
return Enum.valueOf((Class<Enum>) clazz, enumName);
}
public static Field getFieldByName(Class<?> clazz, String fieldName) {
try {
Field field = clazz.getDeclaredField(fieldName) != null ? clazz.getDeclaredField(fieldName) : clazz.getSuperclass().getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Object setFieldValue(Object object, Field field, Object value) {
try {
field.set(object, value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return field.getDeclaringClass();
}
public static boolean inBlock(Player player, Object axisAlignedBB) {
return getCollidingBlocks(player, axisAlignedBB).size() > 0;
}
/**
* Method removed in 1.12 and later versions in NMS
**/
public static Collection<?> getCollidingBlocks(Player player, Object axisAlignedBB) {
Object world = getWorldHandle(player.getWorld());
return (Collection<?>) (isNewVersion()
? getMethodValue(getCubes1_12, world, null, axisAlignedBB)
: getMethodValue(getCubes, world, axisAlignedBB));
}
private static Method craftWorldHandle = getMethod(CraftWorld, "getHandle");
public static Object getWorldHandle(org.bukkit.World world) {
return getMethodValue(craftWorldHandle, world);
}
public static Field getFirstFieldByType(Class<?> clazz, Class<?> type) {
try {
for (Field field : clazz.getDeclaredFields()) {
if (field.getType().equals(type)) {
field.setAccessible(true);
return field;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... args) {
try {
Method method = clazz.getMethod(methodName, args);
method.setAccessible(true);
return method;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static Method getMethodNoST(Class<?> clazz, String methodName, Class<?>... args) {
try {
Method method = clazz.getMethod(methodName, args);
method.setAccessible(true);
return method;
} catch (Exception e) {
}
return null;
}
public static boolean hasMethod(Class clazz, Method method) {
return Arrays.stream(clazz.getMethods()).anyMatch(methodLoop -> methodLoop.getName().equals(method.getName()));
}
public static boolean hasMethod(Class clazz, String methodName) {
return Arrays.stream(clazz.getMethods()).anyMatch(methodLoop -> methodLoop.getName().equals(methodName));
}
public static Object getMethodValue(Method method, Object object, Object... args) {
try {
return method.invoke(object, args);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean hasField(Class<?> object, String fieldName) {
return Arrays.stream(object.getFields()).anyMatch(field -> field.getName().equalsIgnoreCase(fieldName));
}
public static Object getMethodValueNoST(Method method, Object object, Object... args) {
try {
return method.invoke(object, args);
} catch (Exception e) {
return null;
}
}
public static Object getFieldValue(Field field, Object object) {
try {
field.setAccessible(true);
return field.get(object);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Object getFieldValueNoST(Field field, Object object) {
try {
field.setAccessible(true);
return field.get(object);
} catch (Exception e) {
return null;
}
}
public static Field getFieldByNameNoST(Class<?> clazz, String fieldName) {
try {
Field field = clazz.getDeclaredField(fieldName) != null ? clazz.getDeclaredField(fieldName) : clazz.getSuperclass().getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (Exception e) {
return null;
}
}
public static Object newInstance(Class<?> objectClass, Object... args) {
try {
return objectClass.getConstructor(args.getClass()).newInstance(args);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static Class<?> getNMSClass(String string) {
return Reflections.getNMSClass(string).getParent();
}
static {
if (ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_8)) {
iBlockData = getNMSClass("IBlockData");
blockPosition = getNMSClass("BlockPosition");
iBlockAccess = getNMSClass("IBlockAccess");
}
}
}
@@ -0,0 +1,86 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.Anticheat;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/*
The whole purpose of this class is just to save disk space and make development more efficient
with the use of lambdas and with less verbose conventions. This does not affect performance.
*/
public class RunUtils {
public static BukkitTask taskTimer(Runnable runnable, Plugin plugin, long delay, long interval) {
return Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, interval);
}
public static BukkitTask taskTimer(Runnable runnable, long delay, long interval) {
return taskTimer(runnable, Anticheat.INSTANCE, delay, interval);
}
public static BukkitTask taskTimerAsync(Runnable runnable, Plugin plugin, long delay, long interval) {
return Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, interval);
}
public static BukkitTask taskTimerAsync(Runnable runnable, long delay, long interval) {
return taskTimerAsync(runnable, Anticheat.INSTANCE, delay, interval);
}
public static BukkitTask task(Runnable runnable, Plugin plugin) {
return Bukkit.getScheduler().runTask(plugin, runnable);
}
public static BukkitTask task(Runnable runnable) {
return task(runnable, Anticheat.INSTANCE);
}
public static BukkitTask taskAsync(Runnable runnable, Plugin plugin) {
return Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable);
}
public static BukkitTask taskAsync(Runnable runnable) {
return taskAsync(runnable, Anticheat.INSTANCE);
}
public static BukkitTask taskLater(Runnable runnable, Plugin plugin, long delay) {
return Bukkit.getScheduler().runTaskLater(plugin, runnable, delay);
}
public static BukkitTask taskLater(Runnable runnable, long delay) {
return taskLater(runnable, Anticheat.INSTANCE, delay);
}
public static BukkitTask taskLaterAsync(Runnable runnable, Plugin plugin, long delay) {
return Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay);
}
public static BukkitTask taskLaterAsync(Runnable runnable, long delay) {
return taskLaterAsync(runnable, Anticheat.INSTANCE, delay);
}
public static <T> Future<?> callLater(Future<T> runnable, long delay, Consumer<T> onComplete) {
return Anticheat.INSTANCE.getScheduler().schedule(() -> {
try {
onComplete.accept(runnable.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}, delay, TimeUnit.MILLISECONDS);
}
public static <T> Future<?> call(Future<T> runnable, Consumer<T> onComplete) {
return Anticheat.INSTANCE.getScheduler().submit(() -> {
try {
onComplete.accept(runnable.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
});
}
}
@@ -0,0 +1,39 @@
package dev.brighten.ac.utils;
import lombok.AllArgsConstructor;
import org.bukkit.entity.Player;
import java.util.function.BiConsumer;
import java.util.function.Function;
@AllArgsConstructor
public class Setting<T> {
public final String name;
private T value;
public final T[] options;
private final Function<Player, T> getValue;
public final BiConsumer<Player, T> onValueChange;
public Setting(String name, Function<Player, T> getValue, BiConsumer<Player, T> onValueChange, T... options) {
this.name = name;
this.getValue = getValue;
this.onValueChange = onValueChange;
this.options = options;
}
public Setting(String name, BiConsumer<Player, T> onValueChange, T... options) {
this.name = name;
this.value = options[0];
this.onValueChange = onValueChange;
this.getValue = (pl) -> this.value;
this.options = options;
}
public void setValue(Player player, Object value) {
onValueChange.accept(player, (T) value);
}
public T getValue(Player player) {
return getValue.apply(player);
}
}
@@ -0,0 +1,99 @@
package dev.brighten.ac.utils;
import java.util.Iterator;
public class Step {
public static GenericStepper<Float> step(float start, float incr, float end) {
Link<Float> first = new Link<>();
Link<Float> cur = first;
Link<Float> last = first;
first.value = start;
while (start < end) {
last = cur;
cur = new Link<>();
cur.value = start+=incr;
last.next = cur;
}
cur = new Link<>();
cur.value =end;
last.next = cur;
return new GenericStepper<>(first);
}
public static GenericStepper<Double> step(double start, double incr, double end) {
Link<Double> first = new Link<>();
Link<Double> cur = first;
Link<Double> last = first;
first.value = start;
while (start < end) {
last = cur;
cur = new Link<>();
start+=incr;
cur.value = start;
last.next = cur;
}
cur = new Link<>();
cur.value = end;
last.next = cur;
return new GenericStepper<>(first);
}
public static class GenericStepper<T> implements Iterator<T>, Iterable<T> {
private Link<T> first;
private Link<T> link;
public GenericStepper(Link<T> link) {
this.link = link;
this.first = link;
}
@Override
public boolean hasNext() {
return link!=null;
}
@Override
public T next() {
T v = link.value;
link = link.next;
return v;
}
public boolean first() {
return link == first || link == first.next;
}
public boolean last() {
return link==null;
}
public int count_() {
int i =0;
Link<T> t = first;
while (t!=null) {
i++;
t = t.next;
}
return i;
}
public void reset() {
this.link = first;
}
@Override
public Iterator<T> iterator() {
reset();
return this;
}
}
private static class Link<T> {
private T value;
private Link<T> next;
}
}
@@ -0,0 +1,36 @@
package dev.brighten.ac.utils;
import dev.brighten.ac.Anticheat;
public class TickTimer {
private int ticks = Anticheat.INSTANCE.getCurrentTicks(), defaultPassed;
public TickTimer(int defaultPassed) {
this.defaultPassed = defaultPassed;
}
public void reset() {
ticks = Anticheat.INSTANCE.getCurrentTicks();
}
public boolean hasPassed() {
return Anticheat.INSTANCE.getCurrentTicks() - ticks > defaultPassed;
}
public boolean hasPassed(int amount) {
return Anticheat.INSTANCE.getCurrentTicks() - ticks > amount;
}
public boolean hasNotPassed() {
return Anticheat.INSTANCE.getCurrentTicks() - ticks <= defaultPassed;
}
public boolean hasNotPassed(int amount) {
return Anticheat.INSTANCE.getCurrentTicks() - ticks <= amount;
}
public int getPassed() {
return Anticheat.INSTANCE.getCurrentTicks() - ticks;
}
}
@@ -0,0 +1,14 @@
package dev.brighten.ac.utils;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Tuple<A, B> {
public A one;
public B two;
public Tuple(A one, B two) {
this.one = one;
this.two = two;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,508 @@
package dev.brighten.ac.utils.config;
import java.util.*;
public final class Configuration
{
private static final char SEPARATOR = '.';
public final Map<String, Object> self;
final Map<String, List<String>> comments;
private final Configuration defaults;
public Configuration()
{
this( null );
}
public Configuration(Configuration defaults)
{
this( new LinkedHashMap<String, Object>(), defaults );
}
Configuration(Map<?, ?> map, Configuration defaults)
{
this.self = new LinkedHashMap<>();
this.defaults = defaults;
comments = new HashMap<>();
if(map != null)
for ( Map.Entry<?, ?> entry : map.entrySet() )
{
String key = ( entry.getKey() == null ) ? "null" : entry.getKey().toString();
if ( entry.getValue() instanceof Map )
{
this.self.put( key, new Configuration( (Map) entry.getValue(), ( defaults == null ) ? null : defaults.getSection( key ) ) );
} else
{
this.self.put( key, entry.getValue() );
}
}
}
public void loadFromString(String contents) {
List<String> list = new ArrayList<>();
Collections.addAll(list, contents.split("\n"));
int currentLayer = 0;
String currentPath = "";
int lineNumber = 0;
for(Iterator<String> iterator = list.iterator(); iterator.hasNext(); lineNumber++) {
String line = iterator.next();
String trimmed = line.trim();
if(trimmed.startsWith("#") || trimmed.isEmpty()) {
addCommentLine(currentPath, line);
continue;
}
if(!line.isEmpty()) {
if(line.contains(":")) {
int layerFromLine = getLayerFromLine(line, lineNumber);
if(layerFromLine < currentLayer) {
currentPath = regressPathBy(currentLayer - layerFromLine, currentPath);
}
String key = getKeyFromLine(line);
if(currentLayer == 0) {
currentPath = key;
}
else {
currentPath += "." + key;
}
}
}
}
}
private void addCommentLine(String currentPath, String line) {
List<String> list = comments.get(currentPath);
if(list == null) {
list = new ArrayList<>();
}
list.add(line);
comments.put(currentPath, list);
}
String getKeyFromLine(String line) {
String key = null;
for(int i = 0; i < line.length(); i++) {
if(line.charAt(i) == ':') {
key = line.substring(0, i);
break;
}
}
return key == null ? null : key.trim();
}
String regressPathBy(int i, String currentPath) {
if(i <= 0) {
return currentPath;
}
String[] split = currentPath.split("\\.");
String rebuild = "";
for(int j = 0; j < split.length - i; j++) {
rebuild += split[j];
if(j <= (split.length - j)) {
rebuild += ".";
}
}
return rebuild;
}
int getLayerFromLine(String line, int lineNumber) {
double d = 0;
for(int i = 0; i < line.length(); i++) {
if(line.charAt(i) == ' ') {
d += 0.5;
}
else {
break;
}
}
return (int) d;
}
private Configuration getSectionFor(String path)
{
int index = path.indexOf( SEPARATOR );
if ( index == -1 )
{
return this;
}
String root = path.substring( 0, index );
Object section = self.get( root );
if ( section == null )
{
section = new Configuration( ( defaults == null ) ? null : defaults.getSection( root ) );
self.put( root, section );
}
return (Configuration) section;
}
private String getChild(String path)
{
int index = path.indexOf( SEPARATOR );
return ( index == -1 ) ? path : path.substring( index + 1 );
}
/*------------------------------------------------------------------------*/
@SuppressWarnings("unchecked")
public <T> T get(String path, T def)
{
Configuration section = getSectionFor( path );
Object val;
if ( section == this )
{
val = self.get( path );
} else
{
val = section.get( getChild( path ), def );
}
if ( val == null && def instanceof Configuration )
{
self.put( path, def );
}
return ( val != null ) ? (T) val : def;
}
public boolean contains(String path)
{
return get( path, null ) != null;
}
public Object get(String path)
{
return get( path, getDefault( path ) );
}
public Object getDefault(String path)
{
return ( defaults == null ) ? null : defaults.get( path );
}
public void set(String path, Object value)
{
if ( value instanceof Map )
{
value = new Configuration( (Map) value, ( defaults == null ) ? null : defaults.getSection( path ) );
}
Configuration section = getSectionFor( path );
if ( section == this )
{
if ( value == null )
{
self.remove( path );
} else
{
self.put( path, value );
}
} else
{
section.set( getChild( path ), value );
}
}
/*------------------------------------------------------------------------*/
public Configuration getSection(String path)
{
Object def = getDefault( path );
return (Configuration) get( path, ( def instanceof Configuration ) ? def : new Configuration( ( defaults == null ) ? null : defaults.getSection( path ) ) );
}
/**
* Gets keys, not deep by default.
*
* @return top level keys for this section
*/
public Collection<String> getKeys()
{
return new LinkedHashSet<>( self.keySet() );
}
/*------------------------------------------------------------------------*/
public byte getByte(String path)
{
Object def = getDefault( path );
return getByte( path, ( def instanceof Number ) ? ( (Number) def ).byteValue() : 0 );
}
public byte getByte(String path, byte def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).byteValue() : def;
}
public List<Byte> getByteList(String path)
{
List<?> list = getList( path );
List<Byte> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).byteValue() );
}
}
return result;
}
public short getShort(String path)
{
Object def = getDefault( path );
return getShort( path, ( def instanceof Number ) ? ( (Number) def ).shortValue() : 0 );
}
public short getShort(String path, short def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).shortValue() : def;
}
public List<Short> getShortList(String path)
{
List<?> list = getList( path );
List<Short> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).shortValue() );
}
}
return result;
}
public int getInt(String path)
{
Object def = getDefault( path );
return getInt( path, ( def instanceof Number ) ? ( (Number) def ).intValue() : 0 );
}
public int getInt(String path, int def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).intValue() : def;
}
public List<Integer> getIntList(String path)
{
List<?> list = getList( path );
List<Integer> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).intValue() );
}
}
return result;
}
public long getLong(String path)
{
Object def = getDefault( path );
return getLong( path, ( def instanceof Number ) ? ( (Number) def ).longValue() : 0 );
}
public long getLong(String path, long def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).longValue() : def;
}
public List<Long> getLongList(String path)
{
List<?> list = getList( path );
List<Long> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).longValue() );
}
}
return result;
}
public float getFloat(String path)
{
Object def = getDefault( path );
return getFloat( path, ( def instanceof Number ) ? ( (Number) def ).floatValue() : 0 );
}
public float getFloat(String path, float def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).floatValue() : def;
}
public List<Float> getFloatList(String path)
{
List<?> list = getList( path );
List<Float> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).floatValue() );
}
}
return result;
}
public double getDouble(String path)
{
Object def = getDefault( path );
return getDouble( path, ( def instanceof Number ) ? ( (Number) def ).doubleValue() : 0 );
}
public double getDouble(String path, double def)
{
Object val = get( path, def );
return ( val instanceof Number ) ? ( (Number) val ).doubleValue() : def;
}
public List<Double> getDoubleList(String path)
{
List<?> list = getList( path );
List<Double> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Number )
{
result.add( ( (Number) object ).doubleValue() );
}
}
return result;
}
public boolean getBoolean(String path)
{
Object def = getDefault( path );
return getBoolean( path, ( def instanceof Boolean ) ? (Boolean) def : false );
}
public boolean getBoolean(String path, boolean def)
{
Object val = get( path, def );
return ( val instanceof Boolean ) ? (Boolean) val : def;
}
public List<Boolean> getBooleanList(String path)
{
List<?> list = getList( path );
List<Boolean> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Boolean )
{
result.add( (Boolean) object );
}
}
return result;
}
public char getChar(String path)
{
Object def = getDefault( path );
return getChar( path, ( def instanceof Character ) ? (Character) def : '\u0000' );
}
public char getChar(String path, char def)
{
Object val = get( path, def );
return ( val instanceof Character ) ? (Character) val : def;
}
public List<Character> getCharList(String path)
{
List<?> list = getList( path );
List<Character> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof Character )
{
result.add( (Character) object );
}
}
return result;
}
public String getString(String path)
{
Object def = getDefault( path );
return getString( path, ( def instanceof String ) ? (String) def : "" );
}
public String getString(String path, String def)
{
Object val = get( path, def );
return ( val instanceof String ) ? (String) val : def;
}
public List<String> getStringList(String path)
{
List<?> list = getList( path );
List<String> result = new ArrayList<>();
for ( Object object : list )
{
if ( object instanceof String )
{
result.add( (String) object );
}
}
return result;
}
/*------------------------------------------------------------------------*/
public List<?> getList(String path)
{
Object def = getDefault( path );
return getList( path, ( def instanceof List<?> ) ? (List<?>) def : Collections.EMPTY_LIST );
}
public List<?> getList(String path, List<?> def)
{
Object val = get( path, def );
return ( val instanceof List<?> ) ? (List<?>) val : def;
}
}
@@ -0,0 +1,58 @@
package dev.brighten.ac.utils.config;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public abstract class ConfigurationProvider
{
public static final Map<Class<? extends ConfigurationProvider>, ConfigurationProvider> providers = new HashMap<>();
static
{
try
{
providers.put( YamlConfiguration.class, new YamlConfiguration() );
} catch ( NoClassDefFoundError ex )
{
ex.printStackTrace();
// Ignore, no SnakeYAML
}
try
{
providers.put( JsonConfiguration.class, new JsonConfiguration() );
} catch ( NoClassDefFoundError ex )
{
ex.printStackTrace();
// Ignore, no Gson
}
}
public static ConfigurationProvider getProvider(Class<? extends ConfigurationProvider> provider)
{
return providers.get( provider );
}
/*------------------------------------------------------------------------*/
public abstract void save(Configuration config, File file) throws IOException;
public abstract void save(Configuration config, Writer writer);
public abstract Configuration load(File file) throws IOException;
public abstract Configuration load(File file, Configuration defaults) throws IOException;
public abstract Configuration load(Reader reader);
public abstract Configuration load(Reader reader, Configuration defaults);
public abstract Configuration load(InputStream is);
public abstract Configuration load(InputStream is, Configuration defaults);
public abstract Configuration load(String string);
public abstract Configuration load(String string, Configuration defaults);
}
@@ -0,0 +1,103 @@
package dev.brighten.ac.utils.config;
import com.google.common.base.Charsets;
import com.google.gson.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.io.*;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PACKAGE)
public class JsonConfiguration extends ConfigurationProvider
{
private final Gson json = new GsonBuilder().serializeNulls().setPrettyPrinting().registerTypeAdapter( Configuration.class, new JsonSerializer<Configuration>()
{
@Override
public JsonElement serialize(Configuration src, Type typeOfSrc, JsonSerializationContext context)
{
return context.serialize( ( (Configuration) src ).self );
}
} ).create();
@Override
public void save(Configuration config, File file) throws IOException
{
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) )
{
save( config, writer );
}
}
@Override
public void save(Configuration config, Writer writer)
{
json.toJson( config.self, writer );
}
@Override
public Configuration load(File file) throws IOException
{
return load( file, null );
}
@Override
public Configuration load(File file, Configuration defaults) throws IOException
{
try ( FileInputStream is = new FileInputStream( file ) )
{
return load( is, defaults );
}
}
@Override
public Configuration load(Reader reader)
{
return load( reader, null );
}
@Override
@SuppressWarnings("unchecked")
public Configuration load(Reader reader, Configuration defaults)
{
Map<String, Object> map = json.fromJson( reader, LinkedHashMap.class );
if ( map == null )
{
map = new LinkedHashMap<>();
}
return new Configuration( map, defaults );
}
@Override
public Configuration load(InputStream is)
{
return load( is, null );
}
@Override
public Configuration load(InputStream is, Configuration defaults)
{
return load( new InputStreamReader( is, Charsets.UTF_8 ), defaults );
}
@Override
public Configuration load(String string)
{
return load( string, null );
}
@Override
@SuppressWarnings("unchecked")
public Configuration load(String string, Configuration defaults)
{
Map<String, Object> map = json.fromJson( string, LinkedHashMap.class );
if ( map == null )
{
map = new LinkedHashMap<>();
}
return new Configuration( map, defaults );
}
}
@@ -0,0 +1,190 @@
package dev.brighten.ac.utils.config;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.representer.Represent;
import org.yaml.snakeyaml.representer.Representer;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
@NoArgsConstructor(access = AccessLevel.PACKAGE)
public class YamlConfiguration extends ConfigurationProvider
{
private final ThreadLocal<Yaml> yaml = new ThreadLocal<Yaml>()
{
@Override
protected Yaml initialValue()
{
Representer representer = new Representer()
{
{
representers.put( Configuration.class, data -> represent( ( (Configuration) data ).self ));
representers.put(ConfigurationSerializable.class, new Represent() {
@Override
public Node representData(Object data) {
ConfigurationSerializable serializable = (ConfigurationSerializable)data;
Map<String, Object> values = new LinkedHashMap();
values.put("==", ConfigurationSerialization.getAlias(serializable.getClass()));
values.putAll(serializable.serialize());
return represent(values);
}
});
}
};
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK );
representer.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
return new Yaml( new Constructor(), representer, options );
}
};
@Override
public void save(Configuration config, File file) throws IOException
{
try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file ), StandardCharsets.UTF_8 ) )
{
save( config, writer );
}
}
@Override
public void save(Configuration config, Writer writer)
{
String contents = this.yaml.get().dump(config.self);
List<String> list = new ArrayList<>();
Collections.addAll(list, contents.split("\n"));
int currentLayer = 0;
StringBuilder currentPath = new StringBuilder();
StringBuilder sb = new StringBuilder();
int lineNumber = 0;
for(Iterator<String> iterator = list.iterator(); iterator.hasNext(); lineNumber++) {
String line = iterator.next();
sb.append(line);
sb.append('\n');
if (!line.isEmpty()) {
if (line.contains(":")) {
int layerFromLine = config.getLayerFromLine(line, lineNumber);
if (layerFromLine < currentLayer) {
currentPath = new StringBuilder(config.regressPathBy(currentLayer - layerFromLine, currentPath.toString()));
}
String key = config.getKeyFromLine(line);
if (currentLayer == 0) {
currentPath = new StringBuilder(key);
} else {
currentPath.append("." + key);
}
String path = currentPath.toString();
if (config.comments.containsKey(path)) {
config.comments.get(path).forEach(string -> {
sb.append(string);
sb.append('\n');
});
}
}
}
}
try {
writer.write(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public Configuration load(File file) throws IOException
{
return load( file, null );
}
@Override
public Configuration load(File file, Configuration defaults) throws IOException
{
try ( FileInputStream is = new FileInputStream( file ) )
{
return load( is, defaults );
}
}
@Override
public Configuration load(Reader reader)
{
return load( reader, null );
}
@SneakyThrows
@Override
public Configuration load(Reader reader, Configuration defaults)
{
BufferedReader input = reader instanceof BufferedReader ? (BufferedReader)reader : new BufferedReader(reader);
StringBuilder builder = new StringBuilder();
String line;
try {
while((line = input.readLine()) != null) {
builder.append(line);
builder.append('\n');
}
} finally {
input.close();
}
return load(builder.toString(), defaults);
}
@Override
public Configuration load(InputStream is)
{
return this.load(new InputStreamReader(is, Charset.defaultCharset()));
}
@Override
public Configuration load(InputStream is, Configuration defaults)
{
return this.load(new InputStreamReader(is, Charset.defaultCharset()), defaults);
}
@Override
public Configuration load(String string)
{
return load( string, null );
}
@Override
@SuppressWarnings("unchecked")
public Configuration load(String contents, Configuration defaults)
{
Map<String, Object> map;
map = this.yaml.get().loadAs(contents, LinkedHashMap.class);
Configuration config = new Configuration( map, defaults );
config.loadFromString(contents);
return config;
}
}
@@ -0,0 +1,40 @@
package dev.brighten.ac.utils.handlers;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public interface PlayerSizeHandler {
PlayerSizeHandler instance = getInstance();
double height(Player player);
double width(Player player);
boolean isGliding(Player player);
default SimpleCollisionBox bounds(Player player) {
Location l = player.getLocation();
return bounds(player,l.getX(),l.getY(),l.getZ());
}
default SimpleCollisionBox bounds(Player player, double x, double y, double z) {
double width = width(player);
return new SimpleCollisionBox().offset(x,y,z).expand(width,0,width).expandMax(0,height(player),0);
}
static PlayerSizeHandler getInstance() {
if (instance!=null)
return instance;
try {
return ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_12)
? new PlayerSizeHandlerModern()
: new PlayerSizeHandlerLegacy();
} catch(Exception e) {
return new PlayerSizeHandlerLegacy();
}
}
}
@@ -0,0 +1,32 @@
package dev.brighten.ac.utils.handlers;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class PlayerSizeHandlerLegacy implements PlayerSizeHandler {
@Override
public double height(Player player) {
return 1.8;
}
@Override
public double width(Player player) {
return 0.6;
}
@Override
public boolean isGliding(Player player) {
return false;
}
public SimpleCollisionBox bounds(Player player) {
Location l = player.getLocation();
return new SimpleCollisionBox().offset(l.getX(), l.getY(), l.getZ()).expand(.3,0,.3).expandMax(0,1.8,0);
}
public SimpleCollisionBox bounds(Player player, double x, double y, double z) {
return new SimpleCollisionBox().offset(x,y,z).expand(.3,0,.3).expandMax(0,1.8,0);
}
}
@@ -0,0 +1,58 @@
package dev.brighten.ac.utils.handlers;
import dev.brighten.ac.utils.reflections.types.WrappedClass;
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import lombok.SneakyThrows;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public class PlayerSizeHandlerModern implements PlayerSizeHandler {
private final WrappedMethod width;
private final WrappedMethod height;
private final WrappedMethod gliding;
private static WrappedClass entityClass = new WrappedClass(Entity.class);
public PlayerSizeHandlerModern() {
width = entityClass.getMethod("getWidth");
height = entityClass.getMethod("getHeight");
gliding = entityClass.getMethod("isGliding");
}
@Override
@SneakyThrows
public double height(Player player) {
return (double) height.invoke(player);
}
@Override
@SneakyThrows
public double width(Player player) {
return (double) width.invoke(player);
}
@Override
@SneakyThrows
public boolean isGliding(Player player) {
return (boolean) gliding.invoke(player);
}
@SneakyThrows
public SimpleCollisionBox bounds(Player player) {
Location l = player.getLocation();
double width = (double) this.width.invoke(player)/2;
double height = this.height.invoke(player);
return new SimpleCollisionBox().offset(l.getX(), l.getY(), l.getZ()).expand(width,0,width).expandMax(0,height,0);
}
@Override
@SneakyThrows
public SimpleCollisionBox bounds(Player player, double x, double y, double z) {
double width = (double) this.width.invoke(player)/2;
double height = this.height.invoke(player);
return new SimpleCollisionBox().offset(x,y,z).expand(width,0,width).expandMax(0,height,0);
}
}
@@ -0,0 +1,41 @@
package dev.brighten.ac.utils.math;
import java.util.HashSet;
import java.util.Set;
public class Average {
private final Set<Double> values;
private final int limit;
public Average(int limit) {
this.limit = limit;
values = new HashSet<>();
}
public void addValue(double value) {
if (value != 0) values.add(value);
}
public void clearValues() {
values.clear();
}
public boolean isAtLimit() {
return values.size() >= limit;
}
public double getAverage(boolean clear) {
double output = 0;
int amount = 0;
for (double value : values) {
output = output + value;
amount++;
}
if (isAtLimit()) clearValues();
return (output / amount);
}
}
@@ -0,0 +1,28 @@
package dev.brighten.ac.utils.math;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.bukkit.util.Vector;
@AllArgsConstructor
@NoArgsConstructor
public class IntVector {
@Getter
@Setter
private int x, y, z;
public IntVector clone() {
return new IntVector(x, y, z);
}
public Vector toBukkitVector() {
return new Vector(x, y, z);
}
@Override
public String toString() {
return String.format("IntVector[%s, %s, %s]", x, y, z);
}
}
@@ -0,0 +1,26 @@
package dev.brighten.ac.utils.math;
public class MCSmooth {
private float x = 0, y = 0, z = 0;
public float smooth(float toSmooth, float increment) {
x += toSmooth;
toSmooth = (x - y) * increment;
z += (toSmooth - z) * 0.5f;
if (toSmooth > 0f && toSmooth > z || toSmooth < 0f && toSmooth < z) {
toSmooth = z;
}
y += toSmooth;
return toSmooth;
}
public void reset() {
x = 0;
y = 0;
z = 0;
}
}
@@ -0,0 +1,146 @@
package dev.brighten.ac.utils.math;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Effect;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
public class RayTrace {
//origin = start position
//direction = direction in which the raytrace will go
Vector origin, direction;
public RayTrace(Vector origin, Vector direction) {
this.origin = origin;
this.direction = direction;
}
//general intersection detection
public static boolean intersects(Vector position, Vector min, Vector max) {
if (position.getX() < min.getX() || position.getX() > max.getX()) {
return false;
} else if (position.getY() < min.getY() || position.getY() > max.getY()) {
return false;
} else if (position.getZ() < min.getZ() || position.getZ() > max.getZ()) {
return false;
}
return true;
}
//get a point on the raytrace at X blocks away
public Vector getPostion(double blocksAway) {
return origin.clone().add(direction.clone().multiply(blocksAway));
}
//checks if a position is on contained within the position
public boolean isOnLine(Vector position) {
double t = (position.getX() - origin.getX()) / direction.getX();
;
if (position.getBlockY() == origin.getY() + (t * direction.getY()) && position.getBlockZ() == origin.getZ() + (t * direction.getZ())) {
return true;
}
return false;
}
//get all postions on a raytrace
public List<Vector> traverse(double blocksAway, double accuracy) {
List<Vector> positions = new ArrayList<>();
for (double d = 0; d <= blocksAway; d += accuracy) {
positions.add(getPostion(d));
}
return positions;
}
public List<Vector> traverse(double skip, double blocksAway, double accuracy) {
List<Vector> positions = new ArrayList<>();
for (double d = skip; d <= blocksAway; d += accuracy) {
positions.add(getPostion(d));
}
return positions;
}
public List<Block> getBlocks(World world, double blocksAway, double accuracy) {
List<Block> blocks = new ArrayList<>();
traverse(blocksAway, accuracy).stream().filter(vector -> vector.toLocation(world).getBlock().getType().isSolid()).forEach(vector -> blocks.add(vector.toLocation(world).getBlock()));
return blocks;
}
//intersection detection for current raytrace with return
public Vector positionOfIntersection(Vector min, Vector max, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
if (intersects(position, min, max)) {
return position;
}
}
return null;
}
//intersection detection for current raytrace
public boolean intersects(Vector min, Vector max, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
if (intersects(position, min, max)) {
return true;
}
}
return false;
}
//bounding blockbox instead of vector
public Vector positionOfIntersection(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) {
return position;
}
}
return null;
}
public Vector positionOfIntersection(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) {
List<Vector> positions = traverse(skip, blocksAway, accuracy);
for (Vector position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) {
return position;
}
}
return null;
}
//bounding blockbox instead of vector
public boolean intersects(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) {
return true;
}
}
return false;
}
public boolean intersects(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) {
return true;
}
}
return false;
}
//debug / effects
public void highlight(World world, double blocksAway, double accuracy) {
for (Vector position : traverse(blocksAway, accuracy)) {
world.playEffect(position.toLocation(world), (ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_13) ? Effect.SMOKE : Effect.valueOf("COLOURED_DUST")), 0);
}
}
}
@@ -0,0 +1,53 @@
package dev.brighten.ac.utils.math;
public class RollingAverage {
private final int size;
private double[] samples;
private long[] times;
private long time;
private double total;
private int index = 0;
public RollingAverage(int size) {
this.size = size;
this.time = (long) size * 1000000000L;
this.total = (double) (20000000000L * (long) size);
this.samples = new double[size];
this.times = new long[size];
for (int i = 0; i < size; ++i) {
this.samples[i] = 20.0D;
this.times[i] = 1000000000L;
}
}
public void add(double x, long t) {
this.time -= this.times[this.index];
this.total -= this.samples[this.index] * (double) this.times[this.index];
this.samples[this.index] = x;
this.times[this.index] = t;
this.time += t;
this.total += x * (double) t;
if (++this.index == this.size) {
this.index = 0;
}
}
public void clearValues() {
this.time = (long) size * 1000000000L;
this.total = (double) (20000000000L * (long) size);
this.samples = new double[size];
this.times = new long[size];
for (int i = 0; i < size; ++i) {
this.samples[i] = 20.0D;
this.times[i] = 1000000000L;
}
}
public double getAverage() {
return this.total / (double) this.time;
}
}
@@ -0,0 +1,44 @@
package dev.brighten.ac.utils.math;
import lombok.Getter;
import java.util.Arrays;
public class RollingAverageDouble {
private final int size;
private double[] array;
private int index;
@Getter
private double average;
public RollingAverageDouble(int size, double initial) {
this.size = size;
array = new double[size];
average = initial;
initial /= size;
Arrays.fill(array, initial);
}
public void add(double value) {
value /= size;
average -= array[index];
average += value;
array[index] = value;
index = (index + 1) % size;
if(Double.isNaN(average)) {
average = 0;
array = new double[size];
index = 0;
}
//System.out.println(Arrays.stream(array).mapToObj(d -> String.format("%.2f", d)).collect(Collectors.joining(",")));
}
public void clearValues() {
average = 0;
Arrays.fill(array, 0);
}
}
@@ -0,0 +1,32 @@
package dev.brighten.ac.utils.math;
import lombok.Getter;
import java.util.Arrays;
public class RollingAverageLong {
private final int size;
private final double[] array;
private int index;
@Getter
private long average;
public RollingAverageLong(int size, long initial) {
this.size = size;
array = new double[size];
average = initial;
initial /= size;
Arrays.fill(array, initial);
}
public void add(long value) {
value /= size;
average -= array[index];
average += value;
array[index] = value;
index = (index + 1) % size;
}
}
@@ -0,0 +1,36 @@
package dev.brighten.ac.utils.math;
import lombok.Getter;
@Getter
public class SimpleAverage {
private double total;
private int count;
private final int size;
private final double initial;
public SimpleAverage(int size, double initial) {
this.size = size;
this.initial = initial;
}
public void add(double value) {
total+= value;
if(++count > size) {
total-= getAverage();
count--;
}
}
public double getAverage() {
if(count == 0) return initial;
return total / count;
}
public void clear() {
count = 0;
total = 0;
}
}
@@ -0,0 +1,35 @@
package dev.brighten.ac.utils.math.cond;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@RequiredArgsConstructor
public class MaxDouble {
@Setter
private double value;
private final double max;
public double add(double amount) {
return value = Math.min(max, value + amount);
}
public double add() {
return add(1);
}
public double subtract(double amount) {
return value = Math.max(0, value - amount);
}
public double subtract() {
return subtract(1);
}
public double value() {
return value;
}
public String toString() {
return String.valueOf(value);
}
}
@@ -0,0 +1,35 @@
package dev.brighten.ac.utils.math.cond;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@RequiredArgsConstructor
public class MaxFloat {
@Setter
private float value;
private final float max;
public float add(float amount) {
return value = Math.min(max, value + amount);
}
public float add() {
return add(1);
}
public float subtract(float amount) {
return value = Math.max(0, value - amount);
}
public float subtract() {
return subtract(1);
}
public float value() {
return value;
}
public String toString() {
return String.valueOf(value);
}
}
@@ -0,0 +1,35 @@
package dev.brighten.ac.utils.math.cond;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@RequiredArgsConstructor
public class MaxInteger {
@Setter
private int value;
private final int max;
public int add(int amount) {
return value = Math.min(max, value + amount);
}
public int add() {
return add(1);
}
public int subtract(int amount) {
return value = Math.max(0, value - amount);
}
public int subtract() {
return subtract(1);
}
public int value() {
return value;
}
public String toString() {
return String.valueOf(value);
}
}
@@ -0,0 +1,35 @@
package dev.brighten.ac.utils.math.cond;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@RequiredArgsConstructor
public class MaxLong {
@Setter
private long value;
private final long max;
public long add(long amount) {
return value = Math.min(max, value + amount);
}
public long add() {
return add(1);
}
public long subtract(long amount) {
return value = Math.max(0, value - amount);
}
public long subtract() {
return subtract(1);
}
public long value() {
return value;
}
public String toString() {
return String.valueOf(value);
}
}
@@ -0,0 +1,145 @@
package dev.brighten.ac.utils.menu;
import dev.brighten.ac.utils.menu.button.Button;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.bukkit.entity.Player;
import java.util.Optional;
import java.util.function.BiConsumer;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 3/28/2018
*/
public interface Menu extends Iterable<Button> {
/**
* Returns the Dimensions of the menu (R, C)
*
* @return The menu's row and column count
*/
MenuDimension getMenuDimension();
/**
* Allows for a 'parent' menu
* (e.g. You have a GUI based punishment history system
* and the main menu shows: Bans, Mutes, and Warnings.
* When you choose the option you open a new GUI that lists the information,
* then on close it re-opens the list menu)
*
* @return the {@link Optional< Menu >}
*/
Optional<Menu> getParent();
/**
* Add a {@link Button} to the menu with no specified index
*
* @param button The button to be added
*/
void addItem(Button button);
/**
* Sets an {@link Button} in the menu with a specified index
*
* @param index The location of the button to be added
* @param button The button to be added
*/
void setItem(int index, Button button);
/**
* Fills the entire menu with the specified {@link Button}
* This is backed by {@link #fillRange(int, int, Button)}
*
* @param button The button to use for the procedure
*/
void fill(Button button);
/**
* Fills the menu from a index to the ending index with a {@link Button}
*
* @param startingIndex The index to start the procedure
* @param endingIndex The index at which the procedure terminates
* @param button The button to be used in the procedure
*/
void fillRange(int startingIndex, int endingIndex, Button button);
/**
* Gets the first empty slot in the inventory
*
* @return the first empty slot or else -1
*/
int getFirstEmptySlot();
/**
* Checks to see if the index is within the bounds of the {@link MenuDimension}
*
* @param index The index to check with
* @throws IndexOutOfBoundsException If the index is out of bounds this is thrown
*/
public void checkBounds(int index) throws IndexOutOfBoundsException;
/**
* Gets the {@link Button} at the specified index
*
* @param index Location to get the button from
* @return A {@link Optional} that may or may not contain the requested button
*/
Optional<Button> getButtonByIndex(int index);
/**
* Method used to construct the inventory in conjunction with {@link BukkitInventoryHolder}
*
* @param initial Is the first build of the menu which needs Bukkit inventory stuff done.
*/
void buildInventory(boolean initial);
/**
* Open's the menu for the specified {@link Player}
*
* @param player The player to open the menu for
*/
void showMenu(Player player);
/**
* Closes the menu for the specified {@link Player}
* Note: This method should call the {@link CloseHandler} if it is present
*
* @param player The player to close the menu for
*/
void close(Player player);
/**
* Setter method for the {@link CloseHandler}
*
* @param handler The handler to set with
*/
void setCloseHandler(CloseHandler handler);
/**
* Calls the {@link CloseHandler}
* Note: Should only be called from the {@link #close(Player)} method
*
* @param player The player to provide to the backing {@link BiConsumer}
*/
void handleClose(Player player);
/**
* A blank interface that extends {@link BiConsumer} for our usage.
*/
interface CloseHandler extends BiConsumer<Player, Menu> {
}
@Getter
@EqualsAndHashCode
@AllArgsConstructor
class MenuDimension {
private final int rows, columns;
public int getSize() {
return rows * columns;
}
}
}
@@ -0,0 +1,136 @@
package dev.brighten.ac.utils.menu;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.Color;
import dev.brighten.ac.utils.Init;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.menu.button.Button;
import dev.brighten.ac.utils.menu.button.ClickAction;
import dev.brighten.ac.utils.menu.button.UpdatingButton;
import dev.brighten.ac.utils.menu.type.BukkitInventoryHolder;
import dev.brighten.ac.utils.menu.type.impl.ChestMenu;
import dev.brighten.ac.utils.menu.type.impl.ValueMenu;
import dev.brighten.ac.utils.reflections.types.WrappedClass;
import dev.brighten.ac.utils.reflections.types.WrappedMethod;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 2/21/2018
*/
@Init
public class MenuListener implements Listener {
public static Map<AnvilInventory, ValueMenu> anvils = new HashMap<>();
@EventHandler(priority = EventPriority.LOW)
private void onInventoryClick(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player)) return;
final InventoryView inventoryView = event.getView();
final Inventory inventory = inventoryView.getTopInventory();
if (inventory.getHolder() instanceof BukkitInventoryHolder && ((Player) event.getWhoClicked()).isOnline()) {
Menu menu = ((BukkitInventoryHolder) inventory.getHolder()).getMenu();
event.setCancelled(true);
if (menu != null) {
final ItemStack stack = event.getCurrentItem();
if ((stack == null || stack.getType() == XMaterial.AIR.parseMaterial()))
return;
int slot = event.getSlot();
if (slot >= 0 && slot <= menu.getMenuDimension().getSize()) {
Optional<Button> buttonOptional = menu.getButtonByIndex(slot);
buttonOptional.ifPresent(button -> {
if (button.getConsumer() == null) { // Allows for Buttons to not have an action.
return;
}
button.getConsumer().accept((Player) event.getWhoClicked(),
new ClickAction.InformationPair(button, event.getClick(), menu));
if (!button.isMoveable()) {
event.setResult(Event.Result.DENY);
event.setCancelled(true);
}
});
}
}
}
if(!event.getAction().equals(InventoryAction.NOTHING)
&& inventory instanceof AnvilInventory
&& anvils.containsKey(inventory)) {
event.setResult(Event.Result.DENY);
event.setCancelled(true);
}
}
@EventHandler(ignoreCancelled = true)
private void onInventoryClose(InventoryCloseEvent event) {
if (!(event.getPlayer() instanceof Player)) return;
final InventoryView inventoryView = event.getView();
final Inventory inventory = inventoryView.getTopInventory();
if (inventory.getHolder() instanceof BukkitInventoryHolder) {
Menu menu = ((BukkitInventoryHolder) inventory.getHolder()).getMenu();
if (menu != null) {
menu.handleClose((Player) event.getPlayer());
if(menu instanceof ChestMenu) {
ChestMenu cmenu = (ChestMenu) menu;
for (int i = 0; i < cmenu.contents.length; i++) {
Button button = cmenu.contents[i];
if(button instanceof UpdatingButton) {
((UpdatingButton)button).cancelUpdate();
}
}
}
menu.getParent().ifPresent(buttons -> new BukkitRunnable() {
public void run() {
if (event.getPlayer().getOpenInventory() == null
|| (!(event.getPlayer().getOpenInventory().getTopInventory().getHolder()
instanceof BukkitInventoryHolder))) {
buttons.showMenu((Player) event.getPlayer());
this.cancel();
}
}
}.runTaskTimer(Anticheat.INSTANCE, 2L, 0L));
}
}
if(inventory instanceof AnvilInventory && anvils.containsKey(inventory)) {
AnvilInventory anvil = (AnvilInventory) inventory;
WrappedMethod method = new WrappedClass(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_11)
? AnvilInventory.class : Inventory.class)
.getMethod(ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_11)
? "getRenameText" : "getName");
anvils.get(anvil).consumer.accept(event.getPlayer(), Color.translate(method.invoke(anvil)));
anvils.remove(anvil);
}
}
}
@@ -0,0 +1,31 @@
package dev.brighten.ac.utils.menu.button;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.bukkit.inventory.ItemStack;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 2/21/2018
*/
@Getter
public class Button {
@Setter
private boolean moveable;
@Setter
private ItemStack stack;
@Setter
private ClickAction consumer;
public Button(boolean moveable, @NonNull ItemStack stack, ClickAction consumer) {
this.moveable = moveable;
this.stack = stack;
this.consumer = consumer;
}
public Button(boolean moveable, ItemStack stack) {
this(moveable, stack, null);
}
}
@@ -0,0 +1,34 @@
package dev.brighten.ac.utils.menu.button;
import dev.brighten.ac.utils.menu.Menu;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 3/2/2018
*/
@FunctionalInterface
public interface ClickAction {
/**
* Preforms an operation on the given argument(s)
*
* @param player The {@link Player} that has acted
* @param buttonClickTypeInformationPair The {@link InformationPair} that contains the {@link Button} clicked, the {@link Menu}, and the {@link ClickType}
*/
void accept(Player player, InformationPair buttonClickTypeInformationPair);
@Getter
@Setter
@AllArgsConstructor
class InformationPair {
private Button button;
private ClickType clickType;
private Menu menu;
}
}
@@ -0,0 +1,62 @@
package dev.brighten.ac.utils.menu.button;
import dev.brighten.ac.utils.RunUtils;
import dev.brighten.ac.utils.menu.Menu;
import dev.brighten.ac.utils.menu.type.impl.ChestMenu;
import lombok.Setter;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import java.util.function.Supplier;
public class UpdatingButton extends Button {
private final Supplier<ItemStack> update;
private BukkitTask updateTask;
private final int tick;
@Setter
private Menu menu;
@Setter
private int index;
public UpdatingButton(boolean moveable, ClickAction consumer,
Supplier<ItemStack> update, int tick) {
super(moveable, update.get(), consumer);
this.update = update;
this.tick = tick;
}
public UpdatingButton(boolean moveable, Supplier<ItemStack> update, int tick) {
super(moveable, update.get());
this.update = update;
this.tick = tick;
}
public void startUpdate() {
if(updateTask != null) return;
updateTask = RunUtils.taskTimer(() -> {
if(menu == null) {
updateTask.cancel();
updateTask = null;
return;
}
setStack(update.get());
menu.setItem(index, this);
if(menu instanceof ChestMenu) {
((ChestMenu)menu).getHolder().getInventory().setItem(index, getStack());
}
}, tick, tick);
}
public void cancelUpdate() {
if(updateTask != null) {
updateTask.cancel();
updateTask = null;
}
}
}
@@ -0,0 +1,17 @@
package dev.brighten.ac.utils.menu.mask;
import dev.brighten.ac.utils.menu.Menu;
import dev.brighten.ac.utils.menu.button.Button;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 5/17/2018
*/
public interface Mask {
Mask setButton(char key, Button button);
Mask setMaskPattern(String... maskPattern);
void applyTo(Menu menu);
}
@@ -0,0 +1,63 @@
package dev.brighten.ac.utils.menu.mask;
import dev.brighten.ac.utils.menu.Menu;
import dev.brighten.ac.utils.menu.button.Button;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 5/17/2018
* <p>
* Note: The use of a blank space ( ) or underscore (_) will remove the item.
*/
public class Mask2D implements Mask {
private final Map<Character, Button> maskButtonKey;
private String maskPattern;
public Mask2D() {
this.maskButtonKey = new HashMap<>();
}
@Override
public Mask setButton(char key, Button button) {
maskButtonKey.put(key, button);
return this;
}
@Override
public Mask setMaskPattern(String... maskPattern) {
String concatPattern = String.join("", maskPattern);
for (char c : concatPattern.toCharArray()) {
if (Character.isWhitespace(c)) {
continue;
}
if (!maskButtonKey.containsKey(c)) {
throw new IllegalArgumentException(String.format("%s is a unrecognized mapping for the Mask.", c));
}
}
this.maskPattern = concatPattern.replace("\n", "");
return this;
}
@Override
public void applyTo(Menu menu) {
if (maskButtonKey.isEmpty()) {
throw new IllegalArgumentException("The maskButtonKey map is empty!");
}
if (maskPattern == null) {
throw new IllegalArgumentException("The maskPattern is null!");
}
if (maskPattern.length() > menu.getMenuDimension().getSize()) {
throw new IllegalArgumentException(String.format("The maskPattern length: %d is longer than the menu dimension: %d", maskPattern.length(), menu.getMenuDimension().getSize()));
}
IntStream.range(0, maskPattern.length()).forEach(i -> {
char ch = maskPattern.charAt(i);
menu.setItem(i, ch == ' ' || ch == '_' ? null : maskButtonKey.get(ch));
});
}
}
@@ -0,0 +1,31 @@
package dev.brighten.ac.utils.menu.preset;
import dev.brighten.ac.utils.ItemBuilder;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.menu.button.Button;
import dev.brighten.ac.utils.menu.preset.button.FillerButton;
import dev.brighten.ac.utils.menu.type.impl.ChestMenu;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import java.util.function.BiConsumer;
public class ConfirmationMenu extends ChestMenu {
public ConfirmationMenu(String message, BiConsumer<Player, Boolean> function) {
super(message, 1);
fill(new FillerButton());
setItem(2, new Button(false, new ItemBuilder(XMaterial.LIME_DYE.parseMaterial()).durability(10)
.name(ChatColor.GREEN + "Accept").build(), ((player, buttonClickTypeInformationPair) -> {
function.accept(player, true);
setCloseHandler(null);
close(player);
})));
setItem(6, new Button(false, new ItemBuilder(XMaterial.RED_DYE.parseMaterial())
.durability(1).name(ChatColor.RED + "Deny").build(), (((player, buttonClickTypeInformationPair) -> {
function.accept(player, false);
close(player);
}))));
setCloseHandler((player, buttons) -> function.accept(player, false));
}
}
@@ -0,0 +1,15 @@
package dev.brighten.ac.utils.menu.preset;
import dev.brighten.ac.utils.MathHelper;
import dev.brighten.ac.utils.menu.preset.button.SettingButton;
import dev.brighten.ac.utils.menu.type.impl.ChestMenu;
public class SettingsMenu extends ChestMenu {
public SettingsMenu(String title, SettingButton... buttons) {
super(title, MathHelper.ceiling_float_int(buttons.length / 9f));
for (int i = 0; i < buttons.length; i++) {
setItem(i, buttons[i]);
}
}
}
@@ -0,0 +1,13 @@
package dev.brighten.ac.utils.menu.preset.button;
import dev.brighten.ac.utils.ItemBuilder;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.menu.button.Button;
public class FillerButton extends Button {
public FillerButton() {
super(false, new ItemBuilder(XMaterial.GRAY_STAINED_GLASS_PANE.parseMaterial()).name(" ")
.durability(15).build());
}
}
@@ -0,0 +1,64 @@
package dev.brighten.ac.utils.menu.preset.button;
import dev.brighten.ac.utils.Color;
import dev.brighten.ac.utils.ItemBuilder;
import dev.brighten.ac.utils.Setting;
import dev.brighten.ac.utils.menu.button.Button;
import lombok.val;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.concurrent.atomic.AtomicInteger;
public class SettingButton extends Button {
private Setting<?> setting;
private AtomicInteger current;
public SettingButton(Player player, String name, String description, Setting<?> setting) {
super(false, new ItemBuilder(Material.BOOK)
.amount(1).name(Color.Gold + name)
.lore(description, "&7Current State: &6" +
(setting.getValue(player) instanceof Enum
? ((Enum)setting.getValue(player)).name() : setting.getValue(player)))
.build());
this.setting = setting;
Object currentVal = setting.getValue(player);
current = new AtomicInteger(0);
for (int i = 0; i < setting.options.length; i++) {
if(setting.options[i].equals(currentVal)) {
current = new AtomicInteger(i);
break;
}
}
setConsumer((pl, info) -> {
if(info.getClickType().isLeftClick()) {
if(current.incrementAndGet() > setting.options.length - 1) {
current.set(0);
}
int i = current.get();
String stringVal = setting.options[i] instanceof Enum
? ((Enum)setting.options[i]).name() : String.valueOf(setting.options[i]);
val stack = new ItemBuilder(Material.BOOK)
.amount(1).name(Color.Gold + name)
.lore(description, "&7Current State: &6" + stringVal)
.build();
pl.sendMessage(Color.Green + "Option set to " + stringVal);
info.getButton().getStack().setItemMeta(stack.getItemMeta());
info.getMenu().buildInventory(false);
SettingButton.this.setting.setValue(pl, setting.options[i]);
}
});
}
}
@@ -0,0 +1,37 @@
package dev.brighten.ac.utils.menu.type;
import dev.brighten.ac.utils.menu.Menu;
import lombok.NonNull;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 3/28/2018
*/
public class BukkitInventoryHolder implements InventoryHolder {
private Menu menu;
private Inventory inventory;
public BukkitInventoryHolder(Menu menu) {
this.menu = menu;
}
public Menu getMenu() {
return menu;
}
public void setMenu(@NonNull Menu menu) {
this.menu = menu;
}
@Override
public Inventory getInventory() {
return inventory;
}
public void setInventory(@NonNull Inventory inventory) {
this.inventory = inventory;
}
}
@@ -0,0 +1,14 @@
package dev.brighten.ac.utils.menu.type.impl;
import org.bukkit.entity.Player;
public class BookMenu {
public BookMenu(String... contents) {
}
public void openBook(Player player) {
}
}
@@ -0,0 +1,158 @@
package dev.brighten.ac.utils.menu.type.impl;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.menu.Menu;
import dev.brighten.ac.utils.menu.button.Button;
import dev.brighten.ac.utils.menu.button.UpdatingButton;
import dev.brighten.ac.utils.menu.type.BukkitInventoryHolder;
import dev.brighten.ac.utils.menu.util.ArrayIterator;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.Iterator;
import java.util.Optional;
import java.util.stream.IntStream;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 3/28/2018
*/
public class ChestMenu implements Menu {
@Getter
@Setter
String title;
final MenuDimension dimension;
@Setter
private Menu parent;
@Getter
BukkitInventoryHolder holder;
public Button[] contents;
private CloseHandler closeHandler;
public ChestMenu(@NonNull String title, int size) {
this.title = title.length() > 32 ? title.substring(0, 32) : title;
if (size <= 0 || size > 6) {
throw new IndexOutOfBoundsException("A menu can only have between 1 & 6 for a size (rows)");
}
this.dimension = new MenuDimension(size, 9);
this.contents = new Button[size * 9];
}
@Override
public MenuDimension getMenuDimension() {
return dimension;
}
@Override
public void addItem(Button button) {
setItem(getFirstEmptySlot(), button);
}
@Override
public void setItem(int index, Button button) {
checkBounds(index);
contents[index] = button;
if(button instanceof UpdatingButton) {
((UpdatingButton)button).setMenu(this);
((UpdatingButton)button).setIndex(index);
}
}
@Override
public void fill(Button button) {
fillRange(0, dimension.getSize(), button);
}
@Override
public void fillRange(int startingIndex, int endingIndex, Button button) {
IntStream.range(startingIndex, endingIndex)
.filter(i -> contents[i] == null || contents[i].getStack().getType()
.equals(XMaterial.AIR.parseMaterial()))
.forEach(i -> setItem(i, button));
}
@Override
public int getFirstEmptySlot() {
for (int i = 0; i < contents.length; i++) {
Button button = contents[i];
if (button == null) {
return i;
}
}
return -1; // Will throw when #checkBounds is called.
}
@Override
public void checkBounds(int index) throws IndexOutOfBoundsException {
if (index < 0 || index > (dimension.getSize())) {
throw new IndexOutOfBoundsException(String.format("setItem(); %s is out of bounds!", index));
}
}
@Override
public Optional<Button> getButtonByIndex(int index) {
return Optional.ofNullable(contents[index]);
}
@Override
public void buildInventory(boolean initial) {
if (initial) {
this.holder = new BukkitInventoryHolder(this);
holder.setInventory(Bukkit.createInventory(holder, dimension.getSize(), title));
}
holder.getInventory().clear();
IntStream.range(0, contents.length).forEach(i -> {
Button button = contents[i];
if (button != null) {
holder.getInventory().setItem(i, button.getStack());
if(button instanceof UpdatingButton) {
((UpdatingButton)button).startUpdate();
}
}
});
}
@Override
public void showMenu(Player player) {
if (holder == null) {
buildInventory(true);
} else {
buildInventory(false);
}
player.openInventory(holder.getInventory());
}
@Override
public void close(Player player) {
player.closeInventory();
handleClose(player);
}
@Override
public void setCloseHandler(CloseHandler handler) {
this.closeHandler = handler;
}
@Override
public void handleClose(Player player) {
if (closeHandler != null) {
closeHandler.accept(player, this);
}
}
@Override
public Optional<Menu> getParent() {
return Optional.ofNullable(parent);
}
@Override
public Iterator<Button> iterator() {
return new ArrayIterator<>(contents);
}
}
@@ -0,0 +1,164 @@
package dev.brighten.ac.utils.menu.type.impl;
import dev.brighten.ac.utils.ItemBuilder;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.menu.Menu;
import dev.brighten.ac.utils.menu.button.Button;
import dev.brighten.ac.utils.menu.type.BukkitInventoryHolder;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.val;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
public class PagedMenu implements Menu {
@Getter
@Setter
String title;
final MenuDimension dimension;
@Setter
private Menu parent;
@Getter
@Setter
private int currentPage = 1;
@Getter
BukkitInventoryHolder holder;
public List<Button> contents;
private CloseHandler closeHandler;
public PagedMenu(@NonNull String title, int size) {
this.title = title.length() > 32 ? title.substring(0, 32) : title;
if (size <= 0 || size > 6) {
throw new IndexOutOfBoundsException("A menu can only have between 1 & 6 for a size (rows)");
}
this.dimension = new MenuDimension(size, 9);
this.contents = new ArrayList<>();
}
@Override
public MenuDimension getMenuDimension() {
return dimension;
}
@Override
public void addItem(Button button) {
contents.add(button);
}
@Override
public void setItem(int index, Button button) {
contents.set(index, button);
}
@Override
public void fill(Button button) {
fillRange(0, dimension.getSize(), button);
}
@Override
public void fillRange(int startingIndex, int endingIndex, Button button) {
IntStream.range(startingIndex, endingIndex)
.filter(i -> contents.get(i) == null || contents.get(i).getStack().getType()
.equals(XMaterial.AIR.parseMaterial()))
.forEach(i -> setItem(i, button));
}
@Override
public int getFirstEmptySlot() {
return contents.size();
}
@Override
public void checkBounds(int index) {
}
@Override
public Optional<Button> getButtonByIndex(int index) {
if(index >= contents.size() - 1) return Optional.empty();
return Optional.ofNullable(contents.get(index));
}
@Override
public void buildInventory(boolean initial) {
if (initial) {
this.holder = new BukkitInventoryHolder(this);
holder.setInventory(Bukkit.createInventory(holder, dimension.getSize(), title));
}
holder.getInventory().clear();
int size = (dimension.getRows() - 1) * dimension.getColumns();
if(currentPage > 1) {
val previous = new ItemBuilder(Material.BOOK).amount(currentPage - 1).name("&ePrevious Page").build();
setItem(dimension.getSize() * currentPage - 6, new Button(false, previous,
(player, info) -> {
currentPage--;
buildInventory(false);
}));
holder.getInventory().setItem(dimension.getSize() - 6, previous);
}
val next = new ItemBuilder(Material.BOOK).amount(currentPage + 1).name("&eNext Page").build();
setItem(dimension.getSize() * currentPage - 4, new Button(false, next, (player, info) -> {
currentPage++;
buildInventory(false);
}));
holder.getInventory().setItem(dimension.getSize() - 4, next);
AtomicInteger index = new AtomicInteger(0);
IntStream.range(Math.min(contents.size(), size * (currentPage - 1)),
Math.min(contents.size(), size * currentPage))
.forEach(i -> {
Button button = contents.get(i);
if (button != null) {
holder.getInventory().setItem(index.getAndIncrement(), button.getStack());
}
});
}
@Override
public void showMenu(Player player) {
if (holder == null) {
buildInventory(true);
} else {
buildInventory(false);
}
player.openInventory(holder.getInventory());
}
@Override
public void close(Player player) {
player.closeInventory();
handleClose(player);
}
@Override
public void setCloseHandler(CloseHandler handler) {
this.closeHandler = handler;
}
@Override
public void handleClose(Player player) {
if (closeHandler != null) {
closeHandler.accept(player, this);
}
}
@Override
public Optional<Menu> getParent() {
return Optional.ofNullable(parent);
}
@Override
public Iterator<Button> iterator() {
return contents.iterator();
}
}
@@ -0,0 +1,37 @@
package dev.brighten.ac.utils.menu.type.impl;
import dev.brighten.ac.utils.ItemBuilder;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.menu.MenuListener;
import dev.brighten.ac.utils.menu.button.Button;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.AnvilInventory;
import java.util.function.BiConsumer;
public class ValueMenu<T> extends ChestMenu {
public BiConsumer<Player, T> consumer;
public ValueMenu(BiConsumer<Player, T> consumer) {
super("&7Value Menu", 1);
Button valButton = new Button(false,
new ItemBuilder(XMaterial.BOOK.parseMaterial()).name("&eEnter Value").amount(1).build(),
(player, info) -> {
AnvilInventory anvil = (AnvilInventory) Bukkit.createInventory(null, InventoryType.ANVIL, "Enter Value");
anvil.setItem(0, new ItemBuilder(XMaterial.WHITE_STAINED_GLASS_PANE.parseMaterial()).amount(1)
.name(" ").build());
player.openInventory(anvil);
MenuListener.anvils.put(anvil, this);
});
this.consumer = consumer;
setItem(4, valButton);
}
}
@@ -0,0 +1,30 @@
package dev.brighten.ac.utils.menu.util;
import java.util.Iterator;
/**
* @author Missionary (missionarymc@gmail.com)
* @since 3/28/2018
* <p>
* This class allows us to fulfill requests for {@link Menu}'s
* Iterable need since default Java arrays do not have a built-in iterator implementation
*/
public class ArrayIterator<T> implements Iterator<T> {
private final T[] elementArray;
private int currentIndex;
public ArrayIterator(T[] elementArray) {
this.elementArray = elementArray;
}
@Override
public boolean hasNext() {
return elementArray.length > currentIndex;
}
@Override
public T next() {
return elementArray[currentIndex++];
}
}
@@ -0,0 +1,97 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package dev.brighten.ac.utils.msg;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.*;
import net.md_5.bungee.api.chat.ComponentBuilder.FormatRetention;
import net.md_5.bungee.api.chat.HoverEvent.Action;
public class ChatBuilder {
private ComponentBuilder componentBuilder;
public ChatBuilder(String text, Object... objects) {
this.componentBuilder = new ComponentBuilder(String.format(text, objects));
}
public ChatBuilder text(String text, Object... objects) {
this.componentBuilder.append(String.format(text, objects), FormatRetention.ALL);
return this;
}
public ChatBuilder color(String color) {
String[] colors = color.split("§");
String[] var3 = colors;
int var4 = colors.length;
for(int var5 = 0; var5 < var4; ++var5) {
String s = var3[var5];
if (s.length() >= 1) {
switch(s.toCharArray()[0]) {
case 'k':
this.componentBuilder.obfuscated(true);
break;
case 'l':
this.componentBuilder.bold(true);
break;
case 'm':
this.componentBuilder.strikethrough(true);
break;
case 'n':
this.componentBuilder.underlined(true);
break;
case 'o':
this.componentBuilder.italic(true);
break;
case 'p':
case 'q':
default:
this.componentBuilder.color(ChatColor.getByChar(s.toCharArray()[0]));
break;
case 'r':
this.componentBuilder.reset();
}
}
}
return this;
}
public ChatBuilder event(Action action, BaseComponent... message) {
this.componentBuilder.event(new HoverEvent(action, message));
return this;
}
public ChatBuilder event(Action action, TextComponent component) {
return this.event(action, TextComponent.fromLegacyText(TextComponent.toLegacyText(new BaseComponent[]{component})));
}
public ChatBuilder event(Action action, String string) {
return this.event(action, TextComponent.fromLegacyText(string));
}
public ChatBuilder event(ClickEvent.Action action, String value) {
this.componentBuilder.event(new ClickEvent(action, value));
return this;
}
public ChatBuilder reset() {
this.componentBuilder.reset();
return this;
}
public BaseComponent[] build() {
return this.componentBuilder.create();
}
public static ChatBuilder create() {
return new ChatBuilder("", new Object[0]);
}
public static ChatBuilder create(String text, Object... objects) {
return new ChatBuilder(text, objects);
}
}
@@ -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 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,82 @@
package dev.brighten.ac.utils.objects;
import dev.brighten.ac.utils.MiscUtils;
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 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, MiscUtils.getArgOrNull(args, 0));
} else if(triFunc != null) {
return (T) triFunc.apply(instance, MiscUtils.getArgOrNull(args, 0),
MiscUtils.getArgOrNull(args, 1));
} else if(quadFunc != null) {
return (T) quadFunc.apply(instance, MiscUtils.getArgOrNull(args, 0),
MiscUtils.getArgOrNull(args, 1), MiscUtils.getArgOrNull(args, 2));
}
}
try {
return (T) method.invoke(instance, args);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
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;
}
}
@@ -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 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();
}
}
@@ -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 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;
}
}
@@ -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 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;
}
}
@@ -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 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 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;
}
}

Some files were not shown because too many files have changed in this diff Show More