mirror of
https://github.com/funkemunky/KauriV3.git
synced 2026-06-14 19:30:37 +00:00
Project files
This commit is contained in:
@@ -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 cφ = COS_TAB[ind]; // cos(φ)
|
||||
|
||||
// sin(φ) == ind / 256.0
|
||||
// Note that sφ is truncated, hence not identical to y.
|
||||
double sφ = yp - FRAC_BIAS;
|
||||
double sd = y * cφ - x * sφ; // sin(θ-φ) ≡ sinθ cosφ - cosθ sinφ
|
||||
|
||||
// asin(sd) ≅ sd + ⅙sd³ (from first 2 terms of Maclaurin series)
|
||||
double d = (6.0 + sd * sd) * sd * ONE_SIXTH;
|
||||
double θ = φ + d;
|
||||
|
||||
// Translate back to correct octant
|
||||
if (steep) { θ = Math.PI * 0.5 - θ; }
|
||||
if (negX) { θ = Math.PI - θ; }
|
||||
if (negY) { θ = -θ; }
|
||||
|
||||
return θ;
|
||||
}
|
||||
|
||||
private static final double ONE_SIXTH = 1.0 / 6.0;
|
||||
private static final int FRAC_EXP = 8; // LUT precision == 2 ** -8 == 1/256
|
||||
private static final int LUT_SIZE = (1 << FRAC_EXP) + 1;
|
||||
private static final double FRAC_BIAS =
|
||||
Double.longBitsToDouble((0x433L - FRAC_EXP) << 52);
|
||||
private static final double[] ASIN_TAB = new double[LUT_SIZE];
|
||||
private static final double[] COS_TAB = new double[LUT_SIZE];
|
||||
|
||||
static
|
||||
{
|
||||
/* Populate trig tables */
|
||||
for (int ind = 0; ind < LUT_SIZE; ++ ind)
|
||||
{
|
||||
double v = ind / (double) (1 << FRAC_EXP);
|
||||
double asinv = Math.asin(v);
|
||||
COS_TAB[ind] = Math.cos(asinv);
|
||||
ASIN_TAB[ind] = asinv;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,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
Reference in New Issue
Block a user