update 5.29
This commit is contained in:
		@@ -20,9 +20,11 @@ import io.izzel.taboolib.module.tellraw.TellrawJson;
 | 
			
		||||
import io.izzel.taboolib.util.Files;
 | 
			
		||||
import io.izzel.taboolib.util.book.BookFormatter;
 | 
			
		||||
import io.izzel.taboolib.util.item.Items;
 | 
			
		||||
import io.izzel.taboolib.util.lite.Effects;
 | 
			
		||||
import io.izzel.taboolib.util.lite.Signs;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.Location;
 | 
			
		||||
import org.bukkit.Particle;
 | 
			
		||||
import org.bukkit.configuration.file.FileConfiguration;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.bukkit.entity.Skeleton;
 | 
			
		||||
@@ -31,10 +33,13 @@ import org.bukkit.event.EventPriority;
 | 
			
		||||
import org.bukkit.event.Listener;
 | 
			
		||||
import org.bukkit.event.server.ServerCommandEvent;
 | 
			
		||||
import org.bukkit.inventory.meta.BookMeta;
 | 
			
		||||
import org.bukkit.util.NumberConversions;
 | 
			
		||||
import org.bukkit.util.Vector;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -51,7 +56,7 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
 | 
			
		||||
        abstract public String[] name();
 | 
			
		||||
 | 
			
		||||
        abstract public void run(Player player);
 | 
			
		||||
        abstract public void run(Player player, String[] args);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    List<Module> testUtil = Lists.newArrayList(
 | 
			
		||||
@@ -62,7 +67,7 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run(Player player) {
 | 
			
		||||
                public void run(Player player, String[] args) {
 | 
			
		||||
                    TellrawJson.create()
 | 
			
		||||
                            .append("§8[§fTabooLib§8] §7TellrawJson: §f[")
 | 
			
		||||
                            .append(Items.getName(player.getItemInHand())).hoverItem(player.getItemInHand())
 | 
			
		||||
@@ -77,7 +82,7 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run(Player player) {
 | 
			
		||||
                public void run(Player player, String[] args) {
 | 
			
		||||
                    Signs.fakeSign(player, lines -> player.sendMessage("§8[§fTabooLib§8] §7FakeSign: §f" + Arrays.toString(lines)));
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
@@ -88,7 +93,7 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run(Player player) {
 | 
			
		||||
                public void run(Player player, String[] args) {
 | 
			
		||||
                    player.sendMessage("§8[§fTabooLib§8] §7Hologram.");
 | 
			
		||||
                    Location location = player.getEyeLocation().add(player.getLocation().getDirection());
 | 
			
		||||
                    Hologram hologram = THologram.create(location, "TabooLib", player)
 | 
			
		||||
@@ -119,7 +124,7 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run(Player player) {
 | 
			
		||||
                public void run(Player player, String[] args) {
 | 
			
		||||
                    BookFormatter.writtenBook()
 | 
			
		||||
                            .generation(BookMeta.Generation.COPY_OF_COPY)
 | 
			
		||||
                            .addPage(TellrawJson.create()
 | 
			
		||||
@@ -135,7 +140,7 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run(Player player) {
 | 
			
		||||
                public void run(Player player, String[] args) {
 | 
			
		||||
                    player.sendMessage("§8[§fTabooLib§8] §7Lighting. §a(+)");
 | 
			
		||||
                    TLight.create(player.getLocation().getBlock(), Type.BLOCK, 15);
 | 
			
		||||
                    TabooLib.getPlugin().runTask(() -> {
 | 
			
		||||
@@ -155,7 +160,7 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run(Player player) {
 | 
			
		||||
                public void run(Player player, String[] args) {
 | 
			
		||||
                    player.sendMessage("§8[§fTabooLib§8] §7SimpleAI.");
 | 
			
		||||
                    Skeleton skeleton = player.getWorld().spawn(player.getLocation(), Skeleton.class, c -> {
 | 
			
		||||
                        c.setCustomName("Fearless Skeleton");
 | 
			
		||||
@@ -179,7 +184,7 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run(Player player) {
 | 
			
		||||
                public void run(Player player, String[] args) {
 | 
			
		||||
                    TellrawJson.create().append("§8[§fTabooLib§8] §7LocalPlayer: ").append("§c[...]").hoverText(LocalPlayer.get(player).saveToString()).send(player);
 | 
			
		||||
                    long time = System.currentTimeMillis();
 | 
			
		||||
                    FileConfiguration conf = LocalPlayer.get0(player);
 | 
			
		||||
@@ -188,6 +193,135 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                    LocalPlayer.set0(player, conf);
 | 
			
		||||
                    player.sendMessage("§8[§fTabooLib§8] §7set: " + (System.currentTimeMillis() - time) + "ms");
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            new Module() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public String[] name() {
 | 
			
		||||
                    return new String[] {"effects", "effect"};
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run(Player player, String[] args) {
 | 
			
		||||
                    if (args.length < 2) {
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7Effects:");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f LINE-[interval]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f POLYGON-[radius]-[interval]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f CIRCLE-[radius]-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f CONE-[height]-[radius]-[rate]-[circle rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f ATOM-[orbits]-[radius]-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f ELLIPSE-[radius]-[other radius]-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f INFINITY-[radius]-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f CRESCENT-[radius]-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f WARE_FUNCTION-[extend]-[height range]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f CYLINDER-[height]-[radius]-[rate]-[interval]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f SPHERE-[radius]-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f SPHERE_SPIKE-[radius]-[rate]-[chance]-[min]-[max]-[interval]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f RING-[rate]-[tube rate]-[radius]-[tube radius]");
 | 
			
		||||
                        TellrawJson.create().append("§8[§fTabooLib§8] §7-§f LIGHTING-").append("§c[...]").hoverText("[rate]-[direction]-[entries]-[branches]-[radius]-[offset]-[offset rate]-[length]-[length rate]-[branch]-[branch rate]").send(player);
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f DNA-[radius]-[rate]-[extension]-[height]-[hydrogen bond dist]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f RECTANGLE-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f CAGE-[rate]-[bar rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f CUBE-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f CUBE_FILLED-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f CUBE_STRUCTURED-[rate]");
 | 
			
		||||
                        player.sendMessage("§8[§fTabooLib§8] §7-§f HYPERCUBE-[rate]-[size rate]-[cubes]");
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    List<String> a = Lists.newArrayList(args[1].toUpperCase().split("-"));
 | 
			
		||||
                    Location locA = player.getEyeLocation();
 | 
			
		||||
                    Location locB = player.getEyeLocation().add(player.getLocation().getDirection().multiply(10)).add(Vector.getRandom().multiply(5));
 | 
			
		||||
                    Consumer<Location> action1 = loc -> Effects.create(Particle.FLAME, loc).count(1).player(player).play();
 | 
			
		||||
                    Consumer<Location> action2 = loc -> Effects.create(Particle.VILLAGER_HAPPY, loc).count(1).player(player).play();
 | 
			
		||||
                    switch (a.get(0)) {
 | 
			
		||||
                        case "LINE": {
 | 
			
		||||
                            Effects.buildLine(locA, locB, action1, orDob(a, 1, 0.1));
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "POLYGON": {
 | 
			
		||||
                            Effects.buildPolygon(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "CIRCLE": {
 | 
			
		||||
                            Effects.buildCircle(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "CONE": {
 | 
			
		||||
                            Effects.buildCone(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), orDob(a, 3, 10D), orDob(a, 4, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "ATOM": {
 | 
			
		||||
                            Effects.buildAtom(locA, orInt(a, 1, 10), orDob(a, 2, 10D), orDob(a, 3, 10D), action1, action2);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "ELLIPSE": {
 | 
			
		||||
                            Effects.buildEllipse(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), orDob(a, 3, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "INFINITY": {
 | 
			
		||||
                            Effects.buildInfinity(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "CRESCENT": {
 | 
			
		||||
                            Effects.buildCrescent(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "WARE_FUNCTION": {
 | 
			
		||||
                            Effects.buildWaveFunction(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), orDob(a, 3, 10D), orDob(a, 4, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "CYLINDER": {
 | 
			
		||||
                            Effects.buildCylinder(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), orDob(a, 3, 10D), orDob(a, 4, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "SPHERE": {
 | 
			
		||||
                            Effects.buildSphere(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "SPHERE_SPIKE": {
 | 
			
		||||
                            Effects.buildSphereSpike(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), orInt(a, 3, 10), orDob(a, 4, 10D), orDob(a, 5, 10D), orDob(a, 6, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "RING": {
 | 
			
		||||
                            Effects.buildRing(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), orDob(a, 3, 10D), orDob(a, 4, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "LIGHTING": {
 | 
			
		||||
                            Effects.buildLightning(locA, locA.getDirection(), orInt(a, 1, 10), orInt(a, 2, 10), orDob(a, 3, 10), orDob(a, 4, 10D), orDob(a, 5, 10D), orDob(a, 6, 10D), orDob(a, 7, 10D), orDob(a, 8, 10D), orDob(a, 9, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "DNA": {
 | 
			
		||||
                            Effects.buildDNA(locA, orDob(a, 1, 10D), orDob(a, 2, 10D), orDob(a, 3, 10D), orInt(a, 4, 10), orInt(a, 5, 10), action1, action2);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "RECTANGLE": {
 | 
			
		||||
                            Effects.buildRectangle(locA, locB, orDob(a, 1, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "CAGE": {
 | 
			
		||||
                            Effects.buildCage(locA, locB, orDob(a, 1, 10D), orDob(a, 2, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "CUBE": {
 | 
			
		||||
                            Effects.buildCube(locA, locB, orDob(a, 1, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "CUBE_FILLED": {
 | 
			
		||||
                            Effects.buildCubeFilled(locA, locB, orDob(a, 1, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "CUBE_STRUCTURED": {
 | 
			
		||||
                            Effects.buildCubeStructured(locA, locB, orDob(a, 1, 10D), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        case "HYPERCUBE": {
 | 
			
		||||
                            Effects.buildHypercube(locA, locB, orDob(a, 1, 10D), orDob(a, 2, 10D), orInt(a, 3, 10), action1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                        default:
 | 
			
		||||
                            player.sendMessage("§8[§fTabooLib§8] §7No Effect.");
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -213,11 +347,12 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
                        for (Module module : testUtil) {
 | 
			
		||||
                            for (String name : module.name()) {
 | 
			
		||||
                                if (name.equalsIgnoreCase(args[0])) {
 | 
			
		||||
                                    module.run((Player) sender);
 | 
			
		||||
                                    module.run((Player) sender, args);
 | 
			
		||||
                                    return;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        sender.sendMessage("§8[§fTabooLib§8] §7Test: §f" + testUtil.stream().map(i -> i.name()[0]).collect(Collectors.joining(", ")));
 | 
			
		||||
                    }
 | 
			
		||||
                }).build();
 | 
			
		||||
    }
 | 
			
		||||
@@ -251,4 +386,12 @@ public class ListenerCommand implements Listener {
 | 
			
		||||
            Bukkit.shutdown();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static int orInt(List<String> list, int index, int def) {
 | 
			
		||||
        return list.size() > index ? NumberConversions.toInt(list.get(index)) : def;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static double orDob(List<String> list, int index, double def) {
 | 
			
		||||
        return list.size() > index ? NumberConversions.toDouble(list.get(index)) : def;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@ import java.util.function.Consumer;
 | 
			
		||||
public class NMSImpl extends NMS {
 | 
			
		||||
 | 
			
		||||
    private Field entityTypesField;
 | 
			
		||||
    private final boolean is11300 = Version.isAfter(Version.v1_13);
 | 
			
		||||
    private final boolean is11400 = Version.isAfter(Version.v1_14);
 | 
			
		||||
    private final boolean is11500 = Version.isAfter(Version.v1_15);
 | 
			
		||||
 | 
			
		||||
@@ -116,7 +117,11 @@ public class NMSImpl extends NMS {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Object toPacketPlayOutWorldParticles(Particle var1, boolean var2, float var3, float var4, float var5, float var6, float var7, float var8, float var9, int var10, Object var11) {
 | 
			
		||||
        return new net.minecraft.server.v1_12_R1.PacketPlayOutWorldParticles(CraftParticle.toNMS(var1), var2, var3, var4, var5, var6, var7, var8, var9, var10, CraftParticle.toData(var1, var11));
 | 
			
		||||
        if (is11300) {
 | 
			
		||||
            return new net.minecraft.server.v1_13_R2.PacketPlayOutWorldParticles(org.bukkit.craftbukkit.v1_13_R2.CraftParticle.toNMS(var1, var11), var2, var3, var4, var5, var6, var7, var8, var9, var10);
 | 
			
		||||
        } else {
 | 
			
		||||
            return new net.minecraft.server.v1_12_R1.PacketPlayOutWorldParticles(CraftParticle.toNMS(var1), var2, var3, var4, var5, var6, var7, var8, var9, var10, CraftParticle.toData(var1, var11));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package io.izzel.taboolib.util.item;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Enums;
 | 
			
		||||
import com.google.common.collect.ImmutableMap;
 | 
			
		||||
import com.google.gson.*;
 | 
			
		||||
import io.izzel.taboolib.Version;
 | 
			
		||||
@@ -75,7 +76,7 @@ public class Items {
 | 
			
		||||
    public static Material asMaterial(String args) {
 | 
			
		||||
        try {
 | 
			
		||||
            Material material = Material.getMaterial(args.toUpperCase());
 | 
			
		||||
            return material != null ? material : Material.getMaterial(Integer.parseInt(args));
 | 
			
		||||
            return material != null ? material : Material.getMaterial(NumberConversions.toInt(args));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            return Material.STONE;
 | 
			
		||||
        }
 | 
			
		||||
@@ -84,24 +85,16 @@ public class Items {
 | 
			
		||||
    public static Color asColor(String color) {
 | 
			
		||||
        try {
 | 
			
		||||
            String[] v = color.split("-");
 | 
			
		||||
            return Color.fromBGR(Integer.parseInt(v[0]), Integer.parseInt(v[1]), Integer.parseInt(v[2]));
 | 
			
		||||
            return Color.fromRGB(NumberConversions.toInt(v[0]), NumberConversions.toInt(v[1]), NumberConversions.toInt(v[2]));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            return Color.fromBGR(0, 0, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ItemFlag asItemFlag(String flag) {
 | 
			
		||||
        try {
 | 
			
		||||
            return ItemFlag.valueOf(flag);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            return null;
 | 
			
		||||
            return Color.fromRGB(0, 0, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Enchantment asEnchantment(String enchant) {
 | 
			
		||||
        try {
 | 
			
		||||
            Enchantment enchantment = Enchantment.getByName(enchant);
 | 
			
		||||
            return enchantment != null ? enchantment : Enchantment.getById(Integer.parseInt(enchant));
 | 
			
		||||
            return enchantment != null ? enchantment : Enchantment.getById(NumberConversions.toInt(enchant));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
@@ -110,12 +103,16 @@ public class Items {
 | 
			
		||||
    public static PotionEffectType asPotionEffectType(String potion) {
 | 
			
		||||
        try {
 | 
			
		||||
            PotionEffectType type = PotionEffectType.getByName(potion);
 | 
			
		||||
            return type != null ? type : PotionEffectType.getById(Integer.parseInt(potion));
 | 
			
		||||
            return type != null ? type : PotionEffectType.getById(NumberConversions.toInt(potion));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ItemFlag asItemFlag(String flag) {
 | 
			
		||||
        return Enums.getIfPresent(ItemFlag.class, flag).orNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String asAttribute(String name) {
 | 
			
		||||
        return Attribute.parse(name).getMinecraftKey();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,29 +1,34 @@
 | 
			
		||||
package io.izzel.taboolib.util.lite;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Enums;
 | 
			
		||||
import com.google.common.base.Preconditions;
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import io.izzel.taboolib.TabooLib;
 | 
			
		||||
import io.izzel.taboolib.util.ArrayUtil;
 | 
			
		||||
import io.izzel.taboolib.util.Reflection;
 | 
			
		||||
import io.izzel.taboolib.util.TMap;
 | 
			
		||||
import io.izzel.taboolib.util.item.Items;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.Color;
 | 
			
		||||
import org.bukkit.Location;
 | 
			
		||||
import org.bukkit.Particle;
 | 
			
		||||
import org.bukkit.block.data.BlockData;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.bukkit.inventory.ItemStack;
 | 
			
		||||
import org.bukkit.material.MaterialData;
 | 
			
		||||
import org.bukkit.util.NumberConversions;
 | 
			
		||||
import org.bukkit.util.Vector;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.concurrent.ThreadLocalRandom;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author sky
 | 
			
		||||
 * @Since 2019-10-06 1:02
 | 
			
		||||
 * <p>
 | 
			
		||||
 * 部分代码来自
 | 
			
		||||
 * CryptoMorin 的 XSeries 项目
 | 
			
		||||
 */
 | 
			
		||||
public class Effects {
 | 
			
		||||
 | 
			
		||||
@@ -36,10 +41,26 @@ public class Effects {
 | 
			
		||||
    private List<Player> player = Lists.newArrayList();
 | 
			
		||||
    private Object data;
 | 
			
		||||
 | 
			
		||||
    public static Particle parseParticle(String in) {
 | 
			
		||||
        return Enums.getIfPresent(Particle.class, in).or(Particle.FLAME);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Effects create(Particle particle, Location center) {
 | 
			
		||||
        return new Effects(particle, center);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Effects create(Particle particle, Location center, double offsetX, double offsetY, double offsetZ) {
 | 
			
		||||
        return new Effects(particle, center).offset(new double[] {offsetX, offsetY, offsetZ});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Effects create(Particle particle, Location center, double offsetX, double offsetY, double offsetZ, double speed) {
 | 
			
		||||
        return new Effects(particle, center).offset(new double[] {offsetX, offsetY, offsetZ}).speed(speed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Effects create(Particle particle, Location center, double offsetX, double offsetY, double offsetZ, double speed, int count) {
 | 
			
		||||
        return new Effects(particle, center).offset(new double[] {offsetX, offsetY, offsetZ}).speed(speed).count(count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Effects parse(String in) {
 | 
			
		||||
        TMap map = TMap.parse(in);
 | 
			
		||||
        Effects effects = Effects.create(parseParticle(map.getName()), null);
 | 
			
		||||
@@ -80,14 +101,6 @@ public class Effects {
 | 
			
		||||
        return effects;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Particle parseParticle(String in) {
 | 
			
		||||
        try {
 | 
			
		||||
            return Particle.valueOf(in.toUpperCase());
 | 
			
		||||
        } catch (Throwable ignored) {
 | 
			
		||||
        }
 | 
			
		||||
        return Particle.FLAME;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildLine(Location locA, Location locB, Consumer<Location> action) {
 | 
			
		||||
        buildLine(locA, locB, action, 0.25);
 | 
			
		||||
    }
 | 
			
		||||
@@ -101,15 +114,367 @@ public class Effects {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildPolygon(Location center, double range, double interval, Consumer<Location> action) {
 | 
			
		||||
    public static void buildPolygon(Location center, double radius, double interval, Consumer<Location> action) {
 | 
			
		||||
        for (double i = 0; i < 360; i += interval) {
 | 
			
		||||
            double radians = Math.toRadians(i);
 | 
			
		||||
            double cos = Math.cos(radians) * range;
 | 
			
		||||
            double sin = Math.sin(radians) * range;
 | 
			
		||||
            double cos = Math.cos(radians) * radius;
 | 
			
		||||
            double sin = Math.sin(radians) * radius;
 | 
			
		||||
            action.accept(center.clone().add(cos, 0, sin));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildCircle(Location center, double radius, double rate, Consumer<Location> action) {
 | 
			
		||||
        double pii = Math.PI * 2;
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        for (double theta = 0; theta <= pii; theta += rateDiv) {
 | 
			
		||||
            double x = radius * Math.cos(theta);
 | 
			
		||||
            double z = radius * Math.sin(theta);
 | 
			
		||||
            action.accept(center.clone().add(x, 0, z));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public static void buildCone(Location center, double height, double radius, double rate, double circleRate, Consumer<Location> action) {
 | 
			
		||||
        double radiusDiv = radius / (height / rate);
 | 
			
		||||
        for (double i = 0; i < height; i += rate) {
 | 
			
		||||
            radius -= radiusDiv;
 | 
			
		||||
            buildCircle(center.clone().add(0, i, 0), Math.max(radius, 0), circleRate - i, action);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildAtom(Location center, int orbits, double radius, double rate, Consumer<Location> orbit, Consumer<Location> nucleus) {
 | 
			
		||||
        double dist = Math.PI / orbits;
 | 
			
		||||
        for (double angle = 0; orbits > 0; angle += dist) {
 | 
			
		||||
            buildCircle(center, radius, rate, orbit);
 | 
			
		||||
            orbits--;
 | 
			
		||||
        }
 | 
			
		||||
        buildSphere(center, radius / 3, rate / 2, nucleus);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildEllipse(Location center, double radius, double otherRadius, double rate, Consumer<Location> action) {
 | 
			
		||||
        double pii = Math.PI * 2;
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        for (double theta = 0; theta <= pii; theta += rateDiv) {
 | 
			
		||||
            double x = radius * Math.cos(theta);
 | 
			
		||||
            double y = otherRadius * Math.sin(theta);
 | 
			
		||||
            action.accept(center.clone().add(x, y, 0));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildInfinity(Location center, double radius, double rate, Consumer<Location> action) {
 | 
			
		||||
        double pii = Math.PI * 2;
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        for (double i = 0; i < pii; i += rateDiv) {
 | 
			
		||||
            double x = Math.sin(i);
 | 
			
		||||
            double smooth = Math.pow(x, 2) + 1;
 | 
			
		||||
            double curve = radius * Math.cos(i);
 | 
			
		||||
            double z = curve / smooth;
 | 
			
		||||
            double y = (curve * x) / smooth;
 | 
			
		||||
            buildCircle(center.clone().add(x, y, z), 1, rate, action);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildCrescent(Location center, double radius, double rate, Consumer<Location> action) {
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        for (double theta = Math.toRadians(45); theta <= Math.toRadians(325); theta += rateDiv) {
 | 
			
		||||
            double x = Math.cos(theta);
 | 
			
		||||
            double z = Math.sin(theta);
 | 
			
		||||
            action.accept(center.clone().add(radius * x, 0, radius * z));
 | 
			
		||||
            double smallerRadius = radius / 1.3;
 | 
			
		||||
            action.accept(center.clone().add(smallerRadius * x + 0.8, 0, smallerRadius * z));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildWaveFunction(Location center, double extend, double heightRange, double size, double rate, Consumer<Location> action) {
 | 
			
		||||
        double pii = Math.PI * 2;
 | 
			
		||||
        double height = heightRange / 2;
 | 
			
		||||
        boolean increase = true;
 | 
			
		||||
        double increaseRandomizer = Numbers.getRandomDouble(heightRange / 2, heightRange);
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        size *= pii;
 | 
			
		||||
        for (double x = 0; x <= size; x += rateDiv) {
 | 
			
		||||
            double xx = extend * x;
 | 
			
		||||
            double y1 = Math.sin(x);
 | 
			
		||||
            if (y1 == 1) {
 | 
			
		||||
                increase = !increase;
 | 
			
		||||
                if (increase) {
 | 
			
		||||
                    increaseRandomizer = Numbers.getRandomDouble(heightRange / 2, heightRange);
 | 
			
		||||
                } else {
 | 
			
		||||
                    increaseRandomizer = Numbers.getRandomDouble(-heightRange, -heightRange / 2);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            height += increaseRandomizer;
 | 
			
		||||
            for (double z = 0; z <= size; z += rateDiv) {
 | 
			
		||||
                double y2 = Math.cos(z);
 | 
			
		||||
                double yy = height * y1 * y2;
 | 
			
		||||
                double zz = extend * z;
 | 
			
		||||
                action.accept(center.clone().add(xx, yy, zz));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildCylinder(Location center, double height, double radius, double rate, double interval, Consumer<Location> action) {
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        for (double theta = 0; theta <= Math.PI; theta += rateDiv) {
 | 
			
		||||
            double x = radius * Math.cos(theta);
 | 
			
		||||
            double z = radius * Math.sin(theta);
 | 
			
		||||
            action.accept(center.clone().add(x, 0, z));
 | 
			
		||||
            action.accept(center.clone().add(-x, 0, -z));
 | 
			
		||||
            action.accept(center.clone().add(x, height, z));
 | 
			
		||||
            action.accept(center.clone().add(-x, height, -z));
 | 
			
		||||
            Location point1 = center.clone().add(x, 0, z);
 | 
			
		||||
            Location point2 = center.clone().add(-x, 0, -z);
 | 
			
		||||
            buildLine(point1, point2, action, interval);
 | 
			
		||||
            Location point21 = center.clone().add(x, height, z);
 | 
			
		||||
            Location point22 = center.clone().add(-x, height, -z);
 | 
			
		||||
            buildLine(point21, point22, action, interval);
 | 
			
		||||
            buildLine(point1, point21, action, interval);
 | 
			
		||||
            buildLine(point2, point22, action, interval);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildSphere(Location center, double radius, double rate, Consumer<Location> action) {
 | 
			
		||||
        double pii = Math.PI * 2;
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        for (double phi = 0; phi <= Math.PI; phi += rateDiv) {
 | 
			
		||||
            double y1 = radius * Math.cos(phi);
 | 
			
		||||
            double y2 = radius * Math.sin(phi);
 | 
			
		||||
            for (double theta = 0; theta <= pii; theta += rateDiv) {
 | 
			
		||||
                double x = Math.cos(theta) * y2;
 | 
			
		||||
                double z = Math.sin(theta) * y2;
 | 
			
		||||
                action.accept(center.clone().add(x, y1, z));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildSphereSpike(Location center, double radius, double rate, int chance, double minRandomDistance, double maxRandomDistance, double interval, Consumer<Location> action) {
 | 
			
		||||
        double pii = Math.PI * 2;
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        for (double phi = 0; phi <= Math.PI; phi += rateDiv) {
 | 
			
		||||
            double y = radius * Math.cos(phi);
 | 
			
		||||
            double sinPhi = radius * Math.sin(phi);
 | 
			
		||||
            for (double theta = 0; theta <= pii; theta += rateDiv) {
 | 
			
		||||
                double x = Math.cos(theta) * sinPhi;
 | 
			
		||||
                double z = Math.sin(theta) * sinPhi;
 | 
			
		||||
                if (chance == 0 || Numbers.getRandomInteger(0, chance) == 1) {
 | 
			
		||||
                    Location start = center.clone().add(x, y, z);
 | 
			
		||||
                    Vector endV = start.clone().subtract(center).toVector().multiply(Numbers.getRandomDouble(minRandomDistance, maxRandomDistance));
 | 
			
		||||
                    Location end = start.clone().add(endV);
 | 
			
		||||
                    buildLine(start, end, action, interval);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildRing(Location center, double rate, double tubeRate, double radius, double tubeRadius, Consumer<Location> action) {
 | 
			
		||||
        double pii = Math.PI * 2;
 | 
			
		||||
        double rateDiv = Math.PI / rate;
 | 
			
		||||
        double tubeDiv = Math.PI / tubeRadius;
 | 
			
		||||
        for (double theta = 0; theta <= pii; theta += rateDiv) {
 | 
			
		||||
            double cos = Math.cos(theta);
 | 
			
		||||
            double sin = Math.sin(theta);
 | 
			
		||||
            for (double phi = 0; phi <= pii; phi += tubeDiv) {
 | 
			
		||||
                double finalRadius = radius + (tubeRadius * Math.cos(phi));
 | 
			
		||||
                double x = finalRadius * cos;
 | 
			
		||||
                double y = finalRadius * sin;
 | 
			
		||||
                double z = tubeRadius * Math.sin(phi);
 | 
			
		||||
                action.accept(center.clone().add(x, y, z));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildLightning(Location start, Vector direction, int entries, int branches, double radius, double offset, double offsetRate, double length, double lengthRate, double branch, double branchRate, Consumer<Location> action) {
 | 
			
		||||
        ThreadLocalRandom random = ThreadLocalRandom.current();
 | 
			
		||||
        if (entries <= 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        boolean inRange = true;
 | 
			
		||||
        while (random.nextDouble() < branch || inRange) {
 | 
			
		||||
            Vector randomizer = new Vector(random.nextDouble(-radius, radius), random.nextDouble(-radius, radius), random.nextDouble(-radius, radius)).normalize().multiply((random.nextDouble(-radius, radius)) * offset);
 | 
			
		||||
            Vector endVector = start.clone().toVector().add(direction.clone().multiply(length)).add(randomizer);
 | 
			
		||||
            Location end = endVector.toLocation(start.getWorld());
 | 
			
		||||
            if (end.distance(start) <= length) {
 | 
			
		||||
                inRange = true;
 | 
			
		||||
                continue;
 | 
			
		||||
            } else {
 | 
			
		||||
                inRange = false;
 | 
			
		||||
            }
 | 
			
		||||
            int rate = (int) (start.distance(end) / 0.1); // distance * (distance / 10)
 | 
			
		||||
            Vector rateDir = endVector.clone().subtract(start.toVector()).normalize().multiply(0.1);
 | 
			
		||||
            for (int i = 0; i < rate; i++) {
 | 
			
		||||
                Location loc = start.clone().add(rateDir.clone().multiply(i));
 | 
			
		||||
                action.accept(loc);
 | 
			
		||||
            }
 | 
			
		||||
            buildLightning(end.clone(), direction, entries - 1, branches - 1, radius, offset * offsetRate, offsetRate, length * lengthRate, lengthRate, branch * branchRate, branchRate, action);
 | 
			
		||||
            if (branches <= 0) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildDNA(Location start, double radius, double rate, double extension, int height, int hydrogenBondDist, Consumer<Location> action1, Consumer<Location> action2) {
 | 
			
		||||
        int nucleotideDist = 0;
 | 
			
		||||
        for (double y = 0; y <= height; y += rate) {
 | 
			
		||||
            nucleotideDist++;
 | 
			
		||||
            double x = radius * Math.cos(extension * y);
 | 
			
		||||
            double z = radius * Math.sin(extension * y);
 | 
			
		||||
            Location nucleotide1 = start.clone().add(x, y, z);
 | 
			
		||||
            action1.accept(start.clone().add(x, y, z));
 | 
			
		||||
            Location nucleotide2 = start.clone().subtract(x, -y, z);
 | 
			
		||||
            action1.accept(start.clone().add(-x, y, -z));
 | 
			
		||||
            if (nucleotideDist >= hydrogenBondDist) {
 | 
			
		||||
                nucleotideDist = 0;
 | 
			
		||||
                buildLine(nucleotide1, nucleotide2, action2, rate * 2);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildRectangle(Location start, Location end, double rate, Consumer<Location> action) {
 | 
			
		||||
        double maxX = Math.max(start.getX(), end.getX());
 | 
			
		||||
        double minX = Math.min(start.getX(), end.getX());
 | 
			
		||||
        double maxY = Math.max(start.getY(), end.getY());
 | 
			
		||||
        double minY = Math.min(start.getY(), end.getY());
 | 
			
		||||
        for (double x = minX; x <= maxX; x += rate) {
 | 
			
		||||
            for (double y = minY; y <= maxY; y += rate) {
 | 
			
		||||
                action.accept(start.clone().add(x - minX, y - minY, 0));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildCage(Location start, Location end, double rate, double barRate, Consumer<Location> action) {
 | 
			
		||||
        double maxX = Math.max(start.getX(), end.getX());
 | 
			
		||||
        double minX = Math.min(start.getX(), end.getX());
 | 
			
		||||
        double maxZ = Math.max(start.getZ(), end.getZ());
 | 
			
		||||
        double minZ = Math.min(start.getZ(), end.getZ());
 | 
			
		||||
        double barChance = 0;
 | 
			
		||||
        for (double x = minX; x <= maxX; x += rate) {
 | 
			
		||||
            for (double z = minZ; z <= maxZ; z += rate) {
 | 
			
		||||
                Location barStart = start.clone().add(x - minX, 0, z - minZ);
 | 
			
		||||
                Location barEnd = start.clone().add(x - minX, 3, z - minZ);
 | 
			
		||||
                if ((x == minX || x + rate > maxX) || (z == minZ || z + rate > maxZ)) {
 | 
			
		||||
                    barChance++;
 | 
			
		||||
                    if (barChance >= barRate) {
 | 
			
		||||
                        barChance = 0;
 | 
			
		||||
                        buildLine(barStart, barEnd, action, rate);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildCube(Location start, Location end, double rate, Consumer<Location> action) {
 | 
			
		||||
        double maxX = Math.max(start.getX(), end.getX());
 | 
			
		||||
        double minX = Math.min(start.getX(), end.getX());
 | 
			
		||||
        double maxY = Math.max(start.getY(), end.getY());
 | 
			
		||||
        double minY = Math.min(start.getY(), end.getY());
 | 
			
		||||
        double maxZ = Math.max(start.getZ(), end.getZ());
 | 
			
		||||
        double minZ = Math.min(start.getZ(), end.getZ());
 | 
			
		||||
        for (double x = minX; x <= maxX; x += rate) {
 | 
			
		||||
            for (double y = minY; y <= maxY; y += rate) {
 | 
			
		||||
                for (double z = minZ; z <= maxZ; z += rate) {
 | 
			
		||||
                    if ((y == minY || y + rate > maxY) || (x == minX || x + rate > maxX) || (z == minZ || z + rate > maxZ)) {
 | 
			
		||||
                        action.accept(start.clone().add(x - minX, y - minY, z - minZ));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildCubeFilled(Location start, Location end, double rate, Consumer<Location> action) {
 | 
			
		||||
        double maxX = Math.max(start.getX(), end.getX());
 | 
			
		||||
        double minX = Math.min(start.getX(), end.getX());
 | 
			
		||||
        double maxY = Math.max(start.getY(), end.getY());
 | 
			
		||||
        double minY = Math.min(start.getY(), end.getY());
 | 
			
		||||
        double maxZ = Math.max(start.getZ(), end.getZ());
 | 
			
		||||
        double minZ = Math.min(start.getZ(), end.getZ());
 | 
			
		||||
        for (double x = minX; x <= maxX; x += rate) {
 | 
			
		||||
            for (double y = minY; y <= maxY; y += rate) {
 | 
			
		||||
                for (double z = minZ; z <= maxZ; z += rate) {
 | 
			
		||||
                    action.accept(start.clone().add(x - minX, y - minY, z - minZ));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildCubeStructured(Location start, Location end, double rate, Consumer<Location> action) {
 | 
			
		||||
        double maxX = Math.max(start.getX(), end.getX());
 | 
			
		||||
        double minX = Math.min(start.getX(), end.getX());
 | 
			
		||||
        double maxY = Math.max(start.getY(), end.getY());
 | 
			
		||||
        double minY = Math.min(start.getY(), end.getY());
 | 
			
		||||
        double maxZ = Math.max(start.getZ(), end.getZ());
 | 
			
		||||
        double minZ = Math.min(start.getZ(), end.getZ());
 | 
			
		||||
        for (double x = minX; x <= maxX; x += rate) {
 | 
			
		||||
            for (double y = minY; y <= maxY; y += rate) {
 | 
			
		||||
                for (double z = minZ; z <= maxZ; z += rate) {
 | 
			
		||||
                    int components = 0;
 | 
			
		||||
                    if (x == minX || x + rate > maxX) {
 | 
			
		||||
                        components++;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (y == minY || y + rate > maxY) {
 | 
			
		||||
                        components++;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (z == minZ || z + rate > maxZ) {
 | 
			
		||||
                        components++;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (components >= 2) {
 | 
			
		||||
                        action.accept(start.clone().add(x - minX, y - minY, z - minZ));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void buildHypercube(Location startOrigin, Location endOrigin, double rate, double sizeRate, int cubes, Consumer<Location> action) {
 | 
			
		||||
        List<Location> previousPoints = null;
 | 
			
		||||
        for (int i = 0; i < cubes + 1; i++) {
 | 
			
		||||
            List<Location> points = new ArrayList<>();
 | 
			
		||||
            Location start = startOrigin.clone().subtract(i * sizeRate, i * sizeRate, i * sizeRate);
 | 
			
		||||
            Location end = endOrigin.clone().add(i * sizeRate, i * sizeRate, i * sizeRate);
 | 
			
		||||
            double maxX = Math.max(start.getX(), end.getX());
 | 
			
		||||
            double minX = Math.min(start.getX(), end.getX());
 | 
			
		||||
            double maxY = Math.max(start.getY(), end.getY());
 | 
			
		||||
            double minY = Math.min(start.getY(), end.getY());
 | 
			
		||||
            double maxZ = Math.max(start.getZ(), end.getZ());
 | 
			
		||||
            double minZ = Math.min(start.getZ(), end.getZ());
 | 
			
		||||
            points.add(new Location(start.getWorld(), maxX, maxY, maxZ));
 | 
			
		||||
            points.add(new Location(start.getWorld(), minX, minY, minZ));
 | 
			
		||||
            points.add(new Location(start.getWorld(), maxX, minY, maxZ));
 | 
			
		||||
            points.add(new Location(start.getWorld(), minX, maxY, minZ));
 | 
			
		||||
            points.add(new Location(start.getWorld(), minX, minY, maxZ));
 | 
			
		||||
            points.add(new Location(start.getWorld(), maxX, minY, minZ));
 | 
			
		||||
            points.add(new Location(start.getWorld(), maxX, maxY, minZ));
 | 
			
		||||
            points.add(new Location(start.getWorld(), minX, maxY, maxZ));
 | 
			
		||||
            if (previousPoints != null) {
 | 
			
		||||
                for (int p = 0; p < 8; p++) {
 | 
			
		||||
                    Location current = points.get(p);
 | 
			
		||||
                    Location previous = previousPoints.get(p);
 | 
			
		||||
                    buildLine(previous, current, action, rate);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            previousPoints = points;
 | 
			
		||||
            for (double x = minX; x <= maxX; x += rate) {
 | 
			
		||||
                for (double y = minY; y <= maxY; y += rate) {
 | 
			
		||||
                    for (double z = minZ; z <= maxZ; z += rate) {
 | 
			
		||||
                        int components = 0;
 | 
			
		||||
                        if (x == minX || x + rate > maxX) {
 | 
			
		||||
                            components++;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (y == minY || y + rate > maxY) {
 | 
			
		||||
                            components++;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (z == minZ || z + rate > maxZ) {
 | 
			
		||||
                            components++;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (components >= 2) {
 | 
			
		||||
                            action.accept(start.clone().add(x - minX, y - minY, z - minZ));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    Effects() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -130,6 +495,10 @@ public class Effects {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void playAsync() {
 | 
			
		||||
        Bukkit.getScheduler().runTaskAsynchronously(TabooLib.getPlugin(), this::play);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Effects particle(Particle particle) {
 | 
			
		||||
        this.particle = particle;
 | 
			
		||||
        return this;
 | 
			
		||||
@@ -180,11 +549,21 @@ public class Effects {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Effects data(BlockData data) {
 | 
			
		||||
        this.data = data;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Effects data(ColorData data) {
 | 
			
		||||
        this.data = data;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Effects data0(Object data) {
 | 
			
		||||
        this.data = data;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class ColorData {
 | 
			
		||||
 | 
			
		||||
        private final Color color;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
package io.izzel.taboolib.util.lite;/*
 | 
			
		||||
/*
 | 
			
		||||
 * The MIT License (MIT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2018 Hex_27
 | 
			
		||||
@@ -20,6 +20,7 @@ package io.izzel.taboolib.util.lite;/*
 | 
			
		||||
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 | 
			
		||||
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
package io.izzel.taboolib.util.lite;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Enums;
 | 
			
		||||
import com.google.common.cache.Cache;
 | 
			
		||||
@@ -27,9 +28,8 @@ import com.google.common.cache.CacheBuilder;
 | 
			
		||||
import com.google.common.collect.ImmutableMap;
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import com.google.common.collect.Maps;
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.apache.commons.lang3.Validate;
 | 
			
		||||
import org.apache.commons.lang3.text.WordUtils;
 | 
			
		||||
import org.apache.commons.lang.StringUtils;
 | 
			
		||||
import org.apache.commons.lang.WordUtils;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
import org.bukkit.inventory.ItemStack;
 | 
			
		||||
@@ -39,33 +39,30 @@ import javax.annotation.Nullable;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * References
 | 
			
		||||
 *
 | 
			
		||||
 * * * GitHub: https://github.com/CryptoMorin/XSeries/blob/master/Materials.java
 | 
			
		||||
 * * XSeries: https://www.spigotmc.org/threads/378136/
 | 
			
		||||
 * Pre-flattening: https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening
 | 
			
		||||
 * Materials: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
 | 
			
		||||
 * Materials (1.8): https://helpch.at/docs/1.8/org/bukkit/Material.html
 | 
			
		||||
 * Material IDs: https://minecraft-ids.grahamedgecombe.com/
 | 
			
		||||
 * Material Source Code: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse/src/main/java/org/bukkit/Material.java
 | 
			
		||||
 * Materials v1: https://www.spigotmc.org/threads/329630/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * <b>Materials</b> - Data Values/Pre-flattening<br>
 | 
			
		||||
 * Supports 1.8-1.15<br>
 | 
			
		||||
 * 1.13 and above as priority.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * This class is mainly designed to support ItemStacks.
 | 
			
		||||
 * If you want to use it on blocks you'll have to
 | 
			
		||||
 * use <a href="https://github.com/CryptoMorin/XSeries/blob/master/XBlock.java">XBlock</a>
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Pre-flattening: https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening
 | 
			
		||||
 * Materials: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
 | 
			
		||||
 * Materials (1.12): https://helpch.at/docs/1.12.2/index.html?org/bukkit/Material.html
 | 
			
		||||
 * Material IDs: https://minecraft-ids.grahamedgecombe.com/
 | 
			
		||||
 * Material Source Code: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse/src/main/java/org/bukkit/Material.java
 | 
			
		||||
 * Materials v1: https://www.spigotmc.org/threads/329630/
 | 
			
		||||
 *
 | 
			
		||||
 * @author Crypto Morin
 | 
			
		||||
 * @version 3.2.0
 | 
			
		||||
 * @version 4.0.0
 | 
			
		||||
 * @see Material
 | 
			
		||||
 * @see ItemStack
 | 
			
		||||
 */
 | 
			
		||||
public enum Materials {
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    ACACIA_BOAT("BOAT_ACACIA"),
 | 
			
		||||
    ACACIA_BUTTON("WOOD_BUTTON"),
 | 
			
		||||
    ACACIA_DOOR("ACACIA_DOOR_ITEM"),
 | 
			
		||||
@@ -103,15 +100,19 @@ public enum Materials {
 | 
			
		||||
    ATTACHED_PUMPKIN_STEM(7, "PUMPKIN_STEM"),
 | 
			
		||||
    AZURE_BLUET(3, "RED_ROSE"),
 | 
			
		||||
    BAKED_POTATO,
 | 
			
		||||
    BAMBOO("1.14", "SUGAR_CANE"),
 | 
			
		||||
    BAMBOO("1.14", "SUGAR_CANE", ""),
 | 
			
		||||
    BAMBOO_SAPLING("1.14"),
 | 
			
		||||
    BARREL("1.14", "CHEST"),
 | 
			
		||||
    BARREL("1.14", "CHEST", ""),
 | 
			
		||||
    BARRIER,
 | 
			
		||||
    BAT_SPAWN_EGG(65, "MONSTER_EGG"),
 | 
			
		||||
    BEACON,
 | 
			
		||||
    BEDROCK,
 | 
			
		||||
    BEEF("RAW_BEEF"),
 | 
			
		||||
    BEEHIVE("1.15"),
 | 
			
		||||
    /**
 | 
			
		||||
     * Beetroot is a known material in pre-1.13
 | 
			
		||||
     * Use XBlock when comparing block types.
 | 
			
		||||
     */
 | 
			
		||||
    BEETROOT("BEETROOT_BLOCK"),
 | 
			
		||||
    BEETROOTS("BEETROOT"),
 | 
			
		||||
    BEETROOT_SEEDS,
 | 
			
		||||
@@ -148,7 +149,7 @@ public enum Materials {
 | 
			
		||||
    BLACK_TERRACOTTA(15, "HARD_CLAY", "STAINED_CLAY"),
 | 
			
		||||
    BLACK_WALL_BANNER("WALL_BANNER"),
 | 
			
		||||
    BLACK_WOOL(15, "WOOL"),
 | 
			
		||||
    BLAST_FURNACE("1.14", "FURNACE"),
 | 
			
		||||
    BLAST_FURNACE("1.14", "FURNACE", ""),
 | 
			
		||||
    BLAZE_POWDER,
 | 
			
		||||
    BLAZE_ROD,
 | 
			
		||||
    BLAZE_SPAWN_EGG(61, "MONSTER_EGG"),
 | 
			
		||||
@@ -159,7 +160,7 @@ public enum Materials {
 | 
			
		||||
    BLUE_CONCRETE_POWDER(11, "CONCRETE_POWDER"),
 | 
			
		||||
    BLUE_DYE(4, "INK_SACK", "LAPIS_LAZULI"),
 | 
			
		||||
    BLUE_GLAZED_TERRACOTTA(11, "1.12", "HARD_CLAY", "STAINED_CLAY", "BLUE_TERRACOTTA"),
 | 
			
		||||
    BLUE_ICE("1.13", "PACKED_ICE"),
 | 
			
		||||
    BLUE_ICE("1.13", "PACKED_ICE", ""),
 | 
			
		||||
    BLUE_ORCHID(1, "RED_ROSE"),
 | 
			
		||||
    BLUE_SHULKER_BOX,
 | 
			
		||||
    BLUE_STAINED_GLASS(11, "STAINED_GLASS"),
 | 
			
		||||
@@ -212,8 +213,8 @@ public enum Materials {
 | 
			
		||||
    CARROT("CARROT_ITEM"),
 | 
			
		||||
    CARROTS("CARROT"),
 | 
			
		||||
    CARROT_ON_A_STICK("CARROT_STICK"),
 | 
			
		||||
    CARTOGRAPHY_TABLE("1.14", "CRAFTING_TABLE"),
 | 
			
		||||
    CARVED_PUMPKIN(1, "1.13", "PUMPKIN"),
 | 
			
		||||
    CARTOGRAPHY_TABLE("1.14", "CRAFTING_TABLE", ""),
 | 
			
		||||
    CARVED_PUMPKIN(1, "1.13", "PUMPKIN", ""),
 | 
			
		||||
    CAT_SPAWN_EGG,
 | 
			
		||||
    CAULDRON("CAULDRON_ITEM"),
 | 
			
		||||
    /**
 | 
			
		||||
@@ -238,9 +239,9 @@ public enum Materials {
 | 
			
		||||
    CHISELED_RED_SANDSTONE(1, "RED_SANDSTONE"),
 | 
			
		||||
    CHISELED_SANDSTONE(1, "SANDSTONE"),
 | 
			
		||||
    CHISELED_STONE_BRICKS(3, "SMOOTH_BRICK"),
 | 
			
		||||
    CHORUS_FLOWER,
 | 
			
		||||
    CHORUS_FRUIT,
 | 
			
		||||
    CHORUS_PLANT,
 | 
			
		||||
    CHORUS_FLOWER("1.9"),
 | 
			
		||||
    CHORUS_FRUIT("1.9"),
 | 
			
		||||
    CHORUS_PLANT("1.9"),
 | 
			
		||||
    CLAY,
 | 
			
		||||
    CLAY_BALL,
 | 
			
		||||
    CLOCK("WATCH"),
 | 
			
		||||
@@ -256,13 +257,13 @@ public enum Materials {
 | 
			
		||||
    COCOA("1.15"),
 | 
			
		||||
    COCOA_BEANS(3, "INK_SACK", "COCOA"),
 | 
			
		||||
    COD("RAW_FISH"),
 | 
			
		||||
    COD_BUCKET("1.13", "BUCKET", "WATER_BUCKET"),
 | 
			
		||||
    COD_SPAWN_EGG("1.13", "MONSTER_EGG"),
 | 
			
		||||
    COD_BUCKET("1.13", "BUCKET", "WATER_BUCKET", ""),
 | 
			
		||||
    COD_SPAWN_EGG("1.13", "MONSTER_EGG", ""),
 | 
			
		||||
    COMMAND_BLOCK("COMMAND"),
 | 
			
		||||
    COMMAND_BLOCK_MINECART("COMMAND_MINECART"),
 | 
			
		||||
    COMPARATOR("REDSTONE_COMPARATOR", "REDSTONE_COMPARATOR_ON", "REDSTONE_COMPARATOR_OFF"),
 | 
			
		||||
    COMPASS,
 | 
			
		||||
    COMPOSTER("1.14", "CAULDRON"),
 | 
			
		||||
    COMPOSTER("1.14", "CAULDRON", ""),
 | 
			
		||||
    CONDUIT("1.13", "BEACON"),
 | 
			
		||||
    COOKED_BEEF,
 | 
			
		||||
    COOKED_CHICKEN,
 | 
			
		||||
@@ -272,7 +273,7 @@ public enum Materials {
 | 
			
		||||
    COOKED_RABBIT,
 | 
			
		||||
    COOKED_SALMON(1, "COOKED_FISH"),
 | 
			
		||||
    COOKIE,
 | 
			
		||||
    CORNFLOWER(4, "1.14", "BLUE_DYE"),
 | 
			
		||||
    CORNFLOWER(4, "1.14", "BLUE_DYE", ""),
 | 
			
		||||
    COW_SPAWN_EGG(92, "MONSTER_EGG"),
 | 
			
		||||
    CRACKED_STONE_BRICKS(2, "SMOOTH_BRICK"),
 | 
			
		||||
    CRAFTING_TABLE("WORKBENCH"),
 | 
			
		||||
@@ -341,7 +342,7 @@ public enum Materials {
 | 
			
		||||
    DEAD_TUBE_CORAL_BLOCK("1.13"),
 | 
			
		||||
    DEAD_TUBE_CORAL_FAN("1.13"),
 | 
			
		||||
    DEAD_TUBE_CORAL_WALL_FAN("1.13"),
 | 
			
		||||
    DEBUG_STICK("1.13", "STICK"),
 | 
			
		||||
    DEBUG_STICK("1.13", "STICK", ""),
 | 
			
		||||
    DETECTOR_RAIL,
 | 
			
		||||
    DIAMOND,
 | 
			
		||||
    DIAMOND_AXE,
 | 
			
		||||
@@ -362,16 +363,16 @@ public enum Materials {
 | 
			
		||||
    DIORITE_WALL,
 | 
			
		||||
    DIRT,
 | 
			
		||||
    DISPENSER,
 | 
			
		||||
    DOLPHIN_SPAWN_EGG("1.13", "MONSTER_EGG"),
 | 
			
		||||
    DOLPHIN_SPAWN_EGG("1.13", "MONSTER_EGG", ""),
 | 
			
		||||
    DONKEY_SPAWN_EGG(32, "MONSTER_EGG"),
 | 
			
		||||
    DRAGON_BREATH("DRAGONS_BREATH"),
 | 
			
		||||
    DRAGON_EGG,
 | 
			
		||||
    DRAGON_HEAD(5, "SKULL", "SKULL_ITEM"),
 | 
			
		||||
    DRAGON_HEAD(5, "1.9", "SKULL", "SKULL_ITEM"),
 | 
			
		||||
    DRAGON_WALL_HEAD(5, "SKULL", "SKULL_ITEM"),
 | 
			
		||||
    DRIED_KELP("1.13"),
 | 
			
		||||
    DRIED_KELP_BLOCK("1.13"),
 | 
			
		||||
    DROPPER,
 | 
			
		||||
    DROWNED_SPAWN_EGG("1.13", "MONSTER_EGG"),
 | 
			
		||||
    DROWNED_SPAWN_EGG("1.13", "MONSTER_EGG", ""),
 | 
			
		||||
    EGG,
 | 
			
		||||
    ELDER_GUARDIAN_SPAWN_EGG(4, "MONSTER_EGG"),
 | 
			
		||||
    ELYTRA,
 | 
			
		||||
@@ -387,10 +388,10 @@ public enum Materials {
 | 
			
		||||
    ENDER_EYE("EYE_OF_ENDER"),
 | 
			
		||||
    ENDER_PEARL,
 | 
			
		||||
    END_CRYSTAL,
 | 
			
		||||
    END_GATEWAY,
 | 
			
		||||
    END_GATEWAY("1.9"),
 | 
			
		||||
    END_PORTAL("ENDER_PORTAL"),
 | 
			
		||||
    END_PORTAL_FRAME("ENDER_PORTAL_FRAME"),
 | 
			
		||||
    END_ROD,
 | 
			
		||||
    END_ROD("1.9", "BLAZE_ROD", ""),
 | 
			
		||||
    END_STONE("ENDER_STONE"),
 | 
			
		||||
    END_STONE_BRICKS("END_BRICKS"),
 | 
			
		||||
    END_STONE_BRICK_SLAB(4, "STEP"),
 | 
			
		||||
@@ -412,13 +413,16 @@ public enum Materials {
 | 
			
		||||
    FIRE_CORAL_FAN("1.13"),
 | 
			
		||||
    FIRE_CORAL_WALL_FAN,
 | 
			
		||||
    FISHING_ROD,
 | 
			
		||||
    FLETCHING_TABLE("1.14", "CRAFTING_TABLE"),
 | 
			
		||||
    FLETCHING_TABLE("1.14", "CRAFTING_TABLE", ""),
 | 
			
		||||
    FLINT,
 | 
			
		||||
    FLINT_AND_STEEL,
 | 
			
		||||
    FLOWER_BANNER_PATTERN,
 | 
			
		||||
    FLOWER_POT("FLOWER_POT_ITEM"), // TODO Fix exceptional material
 | 
			
		||||
    FLOWER_POT("FLOWER_POT_ITEM"),
 | 
			
		||||
    FOX_SPAWN_EGG("1.14"),
 | 
			
		||||
    FROSTED_ICE,
 | 
			
		||||
    /**
 | 
			
		||||
     * This special material cannot be obtained as an item.
 | 
			
		||||
     */
 | 
			
		||||
    FROSTED_ICE("1.9", "PACKED_ICE", ""),
 | 
			
		||||
    FURNACE("BURNING_FURNACE"),
 | 
			
		||||
    FURNACE_MINECART("POWERED_MINECART"),
 | 
			
		||||
    GHAST_SPAWN_EGG(56, "MONSTER_EGG"),
 | 
			
		||||
@@ -480,7 +484,7 @@ public enum Materials {
 | 
			
		||||
    GREEN_TERRACOTTA(13, "HARD_CLAY", "STAINED_CLAY"),
 | 
			
		||||
    GREEN_WALL_BANNER(2, "WALL_BANNER"),
 | 
			
		||||
    GREEN_WOOL(13, "WOOL"),
 | 
			
		||||
    GRINDSTONE("1.14", "ANVIL"),
 | 
			
		||||
    GRINDSTONE("1.14", "ANVIL", ""),
 | 
			
		||||
    GUARDIAN_SPAWN_EGG(68, "MONSTER_EGG"),
 | 
			
		||||
    GUNPOWDER("SULPHUR"),
 | 
			
		||||
    HAY_BLOCK,
 | 
			
		||||
@@ -488,8 +492,8 @@ public enum Materials {
 | 
			
		||||
    HEAVY_WEIGHTED_PRESSURE_PLATE("IRON_PLATE"),
 | 
			
		||||
    HONEYCOMB("1.15"),
 | 
			
		||||
    HONEYCOMB_BLOCK("1.15"),
 | 
			
		||||
    HONEY_BLOCK("1.15", "SLIME_BLOCK"),
 | 
			
		||||
    HONEY_BOTTLE("1.15", "GLASS_BOTTLE"),
 | 
			
		||||
    HONEY_BLOCK("1.15", "SLIME_BLOCK", ""),
 | 
			
		||||
    HONEY_BOTTLE("1.15", "GLASS_BOTTLE", ""),
 | 
			
		||||
    HOPPER,
 | 
			
		||||
    HOPPER_MINECART,
 | 
			
		||||
    HORN_CORAL("1.13"),
 | 
			
		||||
@@ -525,7 +529,7 @@ public enum Materials {
 | 
			
		||||
    IRON_TRAPDOOR,
 | 
			
		||||
    ITEM_FRAME,
 | 
			
		||||
    JACK_O_LANTERN,
 | 
			
		||||
    JIGSAW("1.14", "COMMAND_BLOCK", "STRUCTURE_BLOCK"),
 | 
			
		||||
    JIGSAW("1.14", "COMMAND_BLOCK", "STRUCTURE_BLOCK", ""),
 | 
			
		||||
    JUKEBOX,
 | 
			
		||||
    JUNGLE_BOAT("BOAT_JUNGLE"),
 | 
			
		||||
    JUNGLE_BUTTON("WOOD_BUTTON"),
 | 
			
		||||
@@ -547,7 +551,7 @@ public enum Materials {
 | 
			
		||||
    KELP_PLANT("1.13"),
 | 
			
		||||
    KNOWLEDGE_BOOK("1.12", "BOOK"),
 | 
			
		||||
    LADDER,
 | 
			
		||||
    LANTERN("1.14", "SEA_LANTERN"),
 | 
			
		||||
    LANTERN("1.14", "SEA_LANTERN", ""),
 | 
			
		||||
    LAPIS_BLOCK,
 | 
			
		||||
    LAPIS_LAZULI(4, "INK_SACK"),
 | 
			
		||||
    LAPIS_ORE,
 | 
			
		||||
@@ -559,9 +563,9 @@ public enum Materials {
 | 
			
		||||
    LEATHER_BOOTS,
 | 
			
		||||
    LEATHER_CHESTPLATE,
 | 
			
		||||
    LEATHER_HELMET,
 | 
			
		||||
    LEATHER_HORSE_ARMOR("1.14", "IRON_HORSE_ARMOR"),
 | 
			
		||||
    LEATHER_HORSE_ARMOR("1.14", "IRON_HORSE_ARMOR", ""),
 | 
			
		||||
    LEATHER_LEGGINGS,
 | 
			
		||||
    LECTERN("1.14", "BOOKSHELF"),
 | 
			
		||||
    LECTERN("1.14", "BOOKSHELF", ""),
 | 
			
		||||
    LEVER,
 | 
			
		||||
    LIGHT_BLUE_BANNER(3, "BANNER", "STANDING_BANNER"),
 | 
			
		||||
    LIGHT_BLUE_BED(3, "BED", "BED_BLOCK"),
 | 
			
		||||
@@ -582,7 +586,11 @@ public enum Materials {
 | 
			
		||||
    LIGHT_GRAY_CONCRETE(8, "CONCRETE"),
 | 
			
		||||
    LIGHT_GRAY_CONCRETE_POWDER(8, "CONCRETE_POWDER"),
 | 
			
		||||
    LIGHT_GRAY_DYE(7, "INK_SACK"),
 | 
			
		||||
    LIGHT_GRAY_GLAZED_TERRACOTTA(8, "1.12", "HARD_CLAY", "STAINED_CLAY", "LIGHT_GRAY_TERRACOTTA", "SILVER_GLAZED_TERRACOTTA/1.13"),
 | 
			
		||||
    /**
 | 
			
		||||
     * Renamed to SILVER_GLAZED_TERRACOTTA in 1.13
 | 
			
		||||
     * Renamed to LIGHT_GRAY_GLAZED_TERRACOTTA in 1.14
 | 
			
		||||
     */
 | 
			
		||||
    LIGHT_GRAY_GLAZED_TERRACOTTA(8, "1.12", "HARD_CLAY", "STAINED_CLAY", "LIGHT_GRAY_TERRACOTTA", "SILVER_GLAZED_TERRACOTTA"),
 | 
			
		||||
    LIGHT_GRAY_SHULKER_BOX("SILVER_SHULKER_BOX"),
 | 
			
		||||
    LIGHT_GRAY_STAINED_GLASS(8, "STAINED_GLASS"),
 | 
			
		||||
    LIGHT_GRAY_STAINED_GLASS_PANE(8, "THIN_GLASS", "STAINED_GLASS_PANE"),
 | 
			
		||||
@@ -591,7 +599,7 @@ public enum Materials {
 | 
			
		||||
    LIGHT_GRAY_WOOL(8, "WOOL"),
 | 
			
		||||
    LIGHT_WEIGHTED_PRESSURE_PLATE("GOLD_PLATE"),
 | 
			
		||||
    LILAC(1, "DOUBLE_PLANT"),
 | 
			
		||||
    LILY_OF_THE_VALLEY(15, "1.14", "WHITE_DYE"),
 | 
			
		||||
    LILY_OF_THE_VALLEY(15, "1.14", "WHITE_DYE", ""),
 | 
			
		||||
    LILY_PAD("WATER_LILY"),
 | 
			
		||||
    LIME_BANNER(10, "BANNER", "STANDING_BANNER"),
 | 
			
		||||
    LIME_BED(5, "BED", "BED_BLOCK"),
 | 
			
		||||
@@ -622,7 +630,7 @@ public enum Materials {
 | 
			
		||||
    MAGENTA_TERRACOTTA(2, "HARD_CLAY", "STAINED_CLAY"),
 | 
			
		||||
    MAGENTA_WALL_BANNER(13, "WALL_BANNER"),
 | 
			
		||||
    MAGENTA_WOOL(2, "WOOL"),
 | 
			
		||||
    MAGMA_BLOCK("MAGMA"),
 | 
			
		||||
    MAGMA_BLOCK("1.10", "MAGMA"),
 | 
			
		||||
    MAGMA_CREAM,
 | 
			
		||||
    MAGMA_CUBE_SPAWN_EGG(62, "MONSTER_EGG"),
 | 
			
		||||
    MAP("EMPTY_MAP"),
 | 
			
		||||
@@ -672,8 +680,13 @@ public enum Materials {
 | 
			
		||||
    NETHER_PORTAL("PORTAL"),
 | 
			
		||||
    NETHER_QUARTZ_ORE("QUARTZ_ORE"),
 | 
			
		||||
    NETHER_STAR,
 | 
			
		||||
    NETHER_WART("NETHER_STALK"),
 | 
			
		||||
    NETHER_WART_BLOCK("NETHER_WARTS"),
 | 
			
		||||
    /**
 | 
			
		||||
     * Just like mentioned in https://minecraft.gamepedia.com/Nether_Wart
 | 
			
		||||
     * Nether wart is also known as nether stalk in the code.
 | 
			
		||||
     * NETHER_STALK is the planted state of nether warts.
 | 
			
		||||
     */
 | 
			
		||||
    NETHER_WART("NETHER_WARTS", "NETHER_STALK"),
 | 
			
		||||
    NETHER_WART_BLOCK,
 | 
			
		||||
    NOTE_BLOCK,
 | 
			
		||||
    OAK_BOAT("BOAT"),
 | 
			
		||||
    OAK_BUTTON("WOOD_BUTTON"),
 | 
			
		||||
@@ -717,7 +730,7 @@ public enum Materials {
 | 
			
		||||
    PEONY(5, "DOUBLE_PLANT"),
 | 
			
		||||
    PETRIFIED_OAK_SLAB("WOOD_STEP"),
 | 
			
		||||
    PHANTOM_MEMBRANE("1.13"),
 | 
			
		||||
    PHANTOM_SPAWN_EGG("1.13", "MONSTER_EGG"),
 | 
			
		||||
    PHANTOM_SPAWN_EGG("1.13", "MONSTER_EGG", ""),
 | 
			
		||||
    PIG_SPAWN_EGG(90, "MONSTER_EGG"),
 | 
			
		||||
    PILLAGER_SPAWN_EGG("1.14"),
 | 
			
		||||
    PINK_BANNER(9, "BANNER", "STANDING_BANNER"),
 | 
			
		||||
@@ -792,8 +805,8 @@ public enum Materials {
 | 
			
		||||
    PRISMARINE_STAIRS("1.13"),
 | 
			
		||||
    PRISMARINE_WALL,
 | 
			
		||||
    PUFFERFISH(3, "RAW_FISH"),
 | 
			
		||||
    PUFFERFISH_BUCKET("1.13", "BUCKET", "WATER_BUCKET"),
 | 
			
		||||
    PUFFERFISH_SPAWN_EGG("1.13", "MONSTER_EGG"),
 | 
			
		||||
    PUFFERFISH_BUCKET("1.13", "BUCKET", "WATER_BUCKET", ""),
 | 
			
		||||
    PUFFERFISH_SPAWN_EGG("1.13", "MONSTER_EGG", ""),
 | 
			
		||||
    PUMPKIN,
 | 
			
		||||
    PUMPKIN_PIE,
 | 
			
		||||
    PUMPKIN_SEEDS,
 | 
			
		||||
@@ -865,16 +878,16 @@ public enum Materials {
 | 
			
		||||
    ROTTEN_FLESH,
 | 
			
		||||
    SADDLE,
 | 
			
		||||
    SALMON(1, "RAW_FISH"),
 | 
			
		||||
    SALMON_BUCKET("1.13", "BUCKET", "WATER_BUCKET"),
 | 
			
		||||
    SALMON_SPAWN_EGG("1.13", "MONSTER_EGG"),
 | 
			
		||||
    SALMON_BUCKET("1.13", "BUCKET", "WATER_BUCKET", ""),
 | 
			
		||||
    SALMON_SPAWN_EGG("1.13", "MONSTER_EGG", ""),
 | 
			
		||||
    SAND,
 | 
			
		||||
    SANDSTONE,
 | 
			
		||||
    SANDSTONE_SLAB(1, "STEP", "STONE_SLAB", "DOUBLE_STEP"),
 | 
			
		||||
    SANDSTONE_STAIRS,
 | 
			
		||||
    SANDSTONE_WALL,
 | 
			
		||||
    SCAFFOLDING("1.14", "SLIME_BLOCK"),
 | 
			
		||||
    SCAFFOLDING("1.14", "SLIME_BLOCK", ""),
 | 
			
		||||
    SCUTE("1.13"),
 | 
			
		||||
    SEAGRASS("1.13", "GRASS"),
 | 
			
		||||
    SEAGRASS("1.13", "GRASS", ""),
 | 
			
		||||
    SEA_LANTERN,
 | 
			
		||||
    SEA_PICKLE("1.13"),
 | 
			
		||||
    SHEARS,
 | 
			
		||||
@@ -893,8 +906,8 @@ public enum Materials {
 | 
			
		||||
    SLIME_BLOCK,
 | 
			
		||||
    SLIME_SPAWN_EGG(55, "MONSTER_EGG"),
 | 
			
		||||
    SMITHING_TABLE,
 | 
			
		||||
    SMOKER("1.14", "FURNACE"),
 | 
			
		||||
    SMOOTH_QUARTZ("1.13"),
 | 
			
		||||
    SMOKER("1.14", "FURNACE", ""),
 | 
			
		||||
    SMOOTH_QUARTZ("1.13", "QUARTZ", ""),
 | 
			
		||||
    SMOOTH_QUARTZ_SLAB(7, "STEP"),
 | 
			
		||||
    SMOOTH_QUARTZ_STAIRS,
 | 
			
		||||
    SMOOTH_RED_SANDSTONE(2, "RED_SANDSTONE"),
 | 
			
		||||
@@ -910,7 +923,7 @@ public enum Materials {
 | 
			
		||||
    SNOW_BLOCK,
 | 
			
		||||
    SOUL_SAND,
 | 
			
		||||
    SPAWNER("MOB_SPAWNER"),
 | 
			
		||||
    SPECTRAL_ARROW("1.9", "ARROW"),
 | 
			
		||||
    SPECTRAL_ARROW("1.9", "ARROW", ""),
 | 
			
		||||
    SPIDER_EYE,
 | 
			
		||||
    SPIDER_SPAWN_EGG(52, "MONSTER_EGG"),
 | 
			
		||||
    SPLASH_POTION,
 | 
			
		||||
@@ -966,24 +979,28 @@ public enum Materials {
 | 
			
		||||
    STRUCTURE_BLOCK,
 | 
			
		||||
    /**
 | 
			
		||||
     * Originally developers used barrier blocks for its purpose.
 | 
			
		||||
     * 1.10 will be parsed as 1.9 version.
 | 
			
		||||
     * So technically this isn't really considered as a suggested material.
 | 
			
		||||
     */
 | 
			
		||||
    STRUCTURE_VOID("1.10", "BARRIER"),
 | 
			
		||||
    STRUCTURE_VOID("1.10", "", "BARRIER"),
 | 
			
		||||
    SUGAR,
 | 
			
		||||
    /**
 | 
			
		||||
     * Sugar Cane is a known material in pre-1.13
 | 
			
		||||
     * Use XBlock when comparing block types.
 | 
			
		||||
     */
 | 
			
		||||
    SUGAR_CANE("SUGAR_CANE_BLOCK"),
 | 
			
		||||
    SUNFLOWER("DOUBLE_PLANT"),
 | 
			
		||||
    SUSPICIOUS_STEW("1.14", "MUSHROOM_STEW"),
 | 
			
		||||
    SUSPICIOUS_STEW("1.14", "MUSHROOM_STEW", ""),
 | 
			
		||||
    SWEET_BERRIES("1.14"),
 | 
			
		||||
    SWEET_BERRY_BUSH("1.14", "GRASS"),
 | 
			
		||||
    SWEET_BERRY_BUSH("1.14", "GRASS", ""),
 | 
			
		||||
    TALL_GRASS(2, "DOUBLE_PLANT"),
 | 
			
		||||
    TALL_SEAGRASS(2, "1.13", "TALL_GRASS"),
 | 
			
		||||
    TALL_SEAGRASS(2, "1.13", "TALL_GRASS", ""),
 | 
			
		||||
    TERRACOTTA("HARD_CLAY"),
 | 
			
		||||
    TIPPED_ARROW("1.9", "ARROW"),
 | 
			
		||||
    TIPPED_ARROW("1.9", "ARROW", ""),
 | 
			
		||||
    TNT,
 | 
			
		||||
    TNT_MINECART("EXPLOSIVE_MINECART"),
 | 
			
		||||
    TORCH,
 | 
			
		||||
    TOTEM_OF_UNDYING("TOTEM"),
 | 
			
		||||
    TRADER_LLAMA_SPAWN_EGG(103, "1.14", "MONSTER_EGG"),
 | 
			
		||||
    TRADER_LLAMA_SPAWN_EGG(103, "1.14", "MONSTER_EGG", ""),
 | 
			
		||||
    TRAPPED_CHEST,
 | 
			
		||||
    TRIDENT("1.13"),
 | 
			
		||||
    TRIPWIRE,
 | 
			
		||||
@@ -995,9 +1012,9 @@ public enum Materials {
 | 
			
		||||
    TUBE_CORAL_BLOCK("1.13"),
 | 
			
		||||
    TUBE_CORAL_FAN("1.13"),
 | 
			
		||||
    TUBE_CORAL_WALL_FAN,
 | 
			
		||||
    TURTLE_EGG("1.13", "EGG"),
 | 
			
		||||
    TURTLE_HELMET("1.13", "IRON_HELMET"),
 | 
			
		||||
    TURTLE_SPAWN_EGG("1.13", "CHICKEN_SPAWN_EGG"),
 | 
			
		||||
    TURTLE_EGG("1.13", "EGG", ""),
 | 
			
		||||
    TURTLE_HELMET("1.13", "IRON_HELMET", ""),
 | 
			
		||||
    TURTLE_SPAWN_EGG("1.13", "CHICKEN_SPAWN_EGG", ""),
 | 
			
		||||
    VEX_SPAWN_EGG(35, "MONSTER_EGG"),
 | 
			
		||||
    VILLAGER_SPAWN_EGG(120, "MONSTER_EGG"),
 | 
			
		||||
    VINDICATOR_SPAWN_EGG(36, "MONSTER_EGG"),
 | 
			
		||||
@@ -1009,7 +1026,7 @@ public enum Materials {
 | 
			
		||||
     */
 | 
			
		||||
    VOID_AIR("AIR"),
 | 
			
		||||
    WALL_TORCH("TORCH"),
 | 
			
		||||
    WANDERING_TRADER_SPAWN_EGG("1.14", "VILLAGER_SPAWN_EGG"),
 | 
			
		||||
    WANDERING_TRADER_SPAWN_EGG("1.14", "VILLAGER_SPAWN_EGG", ""),
 | 
			
		||||
    /**
 | 
			
		||||
     * This is used for blocks only.
 | 
			
		||||
     * In 1.13- WATER will turn into STATIONARY_WATER after it finished spreading.
 | 
			
		||||
@@ -1020,6 +1037,10 @@ public enum Materials {
 | 
			
		||||
    WATER("STATIONARY_WATER"),
 | 
			
		||||
    WATER_BUCKET,
 | 
			
		||||
    WET_SPONGE(1, "SPONGE"),
 | 
			
		||||
    /**
 | 
			
		||||
     * Wheat is a known material in pre-1.13
 | 
			
		||||
     * Use XBlock when comparing block types.
 | 
			
		||||
     */
 | 
			
		||||
    WHEAT("CROPS"),
 | 
			
		||||
    WHEAT_SEEDS("SEEDS"),
 | 
			
		||||
    WHITE_BANNER(15, "BANNER", "STANDING_BANNER"),
 | 
			
		||||
@@ -1037,7 +1058,7 @@ public enum Materials {
 | 
			
		||||
    WHITE_WALL_BANNER(15, "WALL_BANNER"),
 | 
			
		||||
    WHITE_WOOL("WOOL"),
 | 
			
		||||
    WITCH_SPAWN_EGG(66, "MONSTER_EGG"),
 | 
			
		||||
    WITHER_ROSE("1.14", "BLACK_DYE"),
 | 
			
		||||
    WITHER_ROSE("1.14", "BLACK_DYE", ""),
 | 
			
		||||
    WITHER_SKELETON_SKULL(1, "SKULL", "SKULL_ITEM"),
 | 
			
		||||
    WITHER_SKELETON_SPAWN_EGG(5, "MONSTER_EGG"),
 | 
			
		||||
    WITHER_SKELETON_WALL_SKULL(1, "SKULL", "SKULL_ITEM"),
 | 
			
		||||
@@ -1115,19 +1136,20 @@ public enum Materials {
 | 
			
		||||
            .put(NETHER_BRICK, NETHER_BRICKS)
 | 
			
		||||
            .build()
 | 
			
		||||
    );
 | 
			
		||||
    /**
 | 
			
		||||
    /*
 | 
			
		||||
     * A set of all the legacy names without duplicates.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * REMOVE THIS IF YOU DON'T NEED IT.
 | 
			
		||||
     * It'll help to free up a lot of memory.
 | 
			
		||||
     * It'll help to free up a lot of memory if it's not used.
 | 
			
		||||
     * Add it back if you need it.
 | 
			
		||||
     *
 | 
			
		||||
     * @see #containsLegacy(String)
 | 
			
		||||
     * @since 2.2.0
 | 
			
		||||
     */
 | 
			
		||||
     *
 | 
			
		||||
    private static final ImmutableSet<String> LEGACY_VALUES = VALUES.stream().map(Materials::getLegacy)
 | 
			
		||||
            .flatMap(Arrays::stream)
 | 
			
		||||
            .filter(m -> m.charAt(1) == '.')
 | 
			
		||||
            .collect(Collectors.collectingAndThen(Collectors.toSet(), ImmutableSet::copyOf));
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Guava (Google Core Libraries for Java)'s cache for performance and timed caches.
 | 
			
		||||
@@ -1145,7 +1167,7 @@ public enum Materials {
 | 
			
		||||
     *
 | 
			
		||||
     * @since 3.0.0
 | 
			
		||||
     */
 | 
			
		||||
    private static final Cache<Materials, Material> PARSED_CACHE = CacheBuilder.newBuilder()
 | 
			
		||||
    private static final Cache<Materials, Optional<Material>> PARSED_CACHE = CacheBuilder.newBuilder()
 | 
			
		||||
            .softValues()
 | 
			
		||||
            .expireAfterAccess(10, TimeUnit.MINUTES)
 | 
			
		||||
            .concurrencyLevel(Runtime.getRuntime().availableProcessors())
 | 
			
		||||
@@ -1159,19 +1181,18 @@ public enum Materials {
 | 
			
		||||
     */
 | 
			
		||||
    private static final Pattern FORMAT_PATTERN = Pattern.compile("\\W+");
 | 
			
		||||
    /**
 | 
			
		||||
     * The current version of the server in the a form of a major {@link MinecraftVersion} version.
 | 
			
		||||
     * The current version of the server in the a form of a major version.
 | 
			
		||||
     *
 | 
			
		||||
     * @since 1.0.0
 | 
			
		||||
     */
 | 
			
		||||
    private static final MinecraftVersion VERSION = valueOfVersion(Bukkit.getVersion());
 | 
			
		||||
    private static final int VERSION = Integer.parseInt(getMajorVersion(Bukkit.getVersion()).substring(2));
 | 
			
		||||
    /**
 | 
			
		||||
     * Cached result if the server version is after the flattening ({@link MinecraftVersion#V1_13}) update.
 | 
			
		||||
     * Cached result if the server version is after the v1.13 flattening update.
 | 
			
		||||
     * Please don't mistake this with flat-chested people. It happened.
 | 
			
		||||
     *
 | 
			
		||||
     * @since 3.0.0
 | 
			
		||||
     */
 | 
			
		||||
    private static final boolean ISFLAT = isVersionOrHigher(MinecraftVersion.V1_13);
 | 
			
		||||
 | 
			
		||||
    private static final boolean ISFLAT = supports(13);
 | 
			
		||||
    /**
 | 
			
		||||
     * The data value of this material https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening
 | 
			
		||||
     *
 | 
			
		||||
@@ -1199,16 +1220,16 @@ public enum Materials {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if the version is {@link MinecraftVersion#V1_13} (Aquatic Update) or higher.
 | 
			
		||||
     * Checks if the version is 1.13 Aquatic Update or higher.
 | 
			
		||||
     * An invocation of this method yields the cached result from the expression:
 | 
			
		||||
     * <p>
 | 
			
		||||
     * <blockquote>
 | 
			
		||||
     * {@link #isVersionOrHigher(MinecraftVersion V1_13)}
 | 
			
		||||
     * {@link #supports(int) 13}}
 | 
			
		||||
     * </blockquote>
 | 
			
		||||
     *
 | 
			
		||||
     * @return true if 1.13 or higher.
 | 
			
		||||
     * @see #getVersion()
 | 
			
		||||
     * @see #isVersionOrHigher(MinecraftVersion)
 | 
			
		||||
     * @see #supports(int)
 | 
			
		||||
     * @since 1.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isNewVersion() {
 | 
			
		||||
@@ -1224,24 +1245,23 @@ public enum Materials {
 | 
			
		||||
     * An invocation of this method yields exactly the same result as the expression:
 | 
			
		||||
     * <p>
 | 
			
		||||
     * <blockquote>
 | 
			
		||||
     * {@link #getVersion()} == {@link MinecraftVersion#V1_8}
 | 
			
		||||
     * {@link #getVersion()} == 1.8
 | 
			
		||||
     * </blockquote>
 | 
			
		||||
     *
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isOneEight() {
 | 
			
		||||
        return VERSION == MinecraftVersion.V1_8;
 | 
			
		||||
        return !supports(9);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The current version of the server.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the current server version or {@link MinecraftVersion#UNKNOWN} if unknown or below 1.8.
 | 
			
		||||
     * @return the current server version or 0.0 if unknown.
 | 
			
		||||
     * @see #isNewVersion()
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static MinecraftVersion getVersion() {
 | 
			
		||||
    public static double getVersion() {
 | 
			
		||||
        return VERSION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1278,11 +1298,9 @@ public enum Materials {
 | 
			
		||||
     *
 | 
			
		||||
     * @param name name of the material.
 | 
			
		||||
     * @return true if Materials enum has this material.
 | 
			
		||||
     * @see #containsLegacy(String)
 | 
			
		||||
     * @since 1.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean contains(@Nonnull String name) {
 | 
			
		||||
        Validate.notEmpty(name, "Cannot check for null or empty material name");
 | 
			
		||||
        name = format(name);
 | 
			
		||||
 | 
			
		||||
        for (Materials materials : VALUES)
 | 
			
		||||
@@ -1290,21 +1308,6 @@ public enum Materials {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if the given material matches any of the available legacy names.
 | 
			
		||||
     * Changed names between the {@code 1.9} and {@code 1.12} versions are not supported (there are only a few anyway).
 | 
			
		||||
     *
 | 
			
		||||
     * @param name the material name.
 | 
			
		||||
     * @return true if it's a legacy name.
 | 
			
		||||
     * @see #contains(String)
 | 
			
		||||
     * @see #anyMatchLegacy(String)
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean containsLegacy(@Nonnull String name) {
 | 
			
		||||
        Validate.notEmpty(name, "Cannot check legacy names for null or empty material name");
 | 
			
		||||
        return LEGACY_VALUES.contains(format(name));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Parses the given material name as an Materials with unspecified data value.
 | 
			
		||||
     *
 | 
			
		||||
@@ -1322,8 +1325,8 @@ public enum Materials {
 | 
			
		||||
     * <p>
 | 
			
		||||
     * <b>Examples</b>
 | 
			
		||||
     * <pre>
 | 
			
		||||
     *     INK_SACK:1 -> RED_DYE
 | 
			
		||||
     *     WOOL, 14  -> RED_WOOL
 | 
			
		||||
     *     {@code INK_SACK:1 -> RED_DYE}
 | 
			
		||||
     *     {@code WOOL, 14  -> RED_WOOL}
 | 
			
		||||
     * </pre>
 | 
			
		||||
     *
 | 
			
		||||
     * @see #matchDefinedMaterials(String, byte)
 | 
			
		||||
@@ -1332,7 +1335,6 @@ public enum Materials {
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static Optional<Materials> matchMaterials(@Nonnull String name, byte data) {
 | 
			
		||||
        Validate.notEmpty(name, "Cannot match a material with null or empty material name");
 | 
			
		||||
        Optional<Materials> oldMatch = matchMaterialsWithData(name);
 | 
			
		||||
        if (oldMatch.isPresent()) return oldMatch;
 | 
			
		||||
 | 
			
		||||
@@ -1348,8 +1350,8 @@ public enum Materials {
 | 
			
		||||
     * <p>
 | 
			
		||||
     * <b>Examples</b>
 | 
			
		||||
     * <p><pre>
 | 
			
		||||
     *     INK_SACK:1 -> RED_DYE
 | 
			
		||||
     *     WOOL, 14  -> RED_WOOL
 | 
			
		||||
     *     {@code INK_SACK:1 -> RED_DYE}
 | 
			
		||||
     *     {@code WOOL, 14  -> RED_WOOL}
 | 
			
		||||
     * </pre>
 | 
			
		||||
     *
 | 
			
		||||
     * @param name the material string that consists of the material name, data and separator character.
 | 
			
		||||
@@ -1452,7 +1454,6 @@ public enum Materials {
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isDuplicated(@Nonnull String name) {
 | 
			
		||||
        Validate.notEmpty(name, "Cannot check duplication for null or empty material name");
 | 
			
		||||
        name = format(name);
 | 
			
		||||
 | 
			
		||||
        // Don't use matchMaterials() since this method is being called from matchMaterials() itself and will cause a StackOverflowError.
 | 
			
		||||
@@ -1507,7 +1508,6 @@ public enum Materials {
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static Optional<Materials> getNewMaterialsIfDuplicated(@Nonnull String name) {
 | 
			
		||||
        Validate.notEmpty(name, "Cannot get new duplicated material for null or empty material name");
 | 
			
		||||
        name = format(name);
 | 
			
		||||
 | 
			
		||||
        for (Map.Entry<Materials, Materials> duplicated : DUPLICATED.entrySet())
 | 
			
		||||
@@ -1525,7 +1525,6 @@ public enum Materials {
 | 
			
		||||
     */
 | 
			
		||||
    @Nullable
 | 
			
		||||
    public static Materials getMaterialsIfDuplicated(@Nonnull String name) {
 | 
			
		||||
        Validate.notEmpty(name, "Cannot get duplicated material for null or empty material name");
 | 
			
		||||
        name = format(name);
 | 
			
		||||
 | 
			
		||||
        for (Map.Entry<Materials, Materials> duplicated : DUPLICATED.entrySet())
 | 
			
		||||
@@ -1549,29 +1548,15 @@ public enum Materials {
 | 
			
		||||
                name.trim().replace('-', '_').replace(' ', '_')).replaceAll("").toUpperCase(Locale.ENGLISH);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Parses the material name if the legacy name has a version attached to it.
 | 
			
		||||
     *
 | 
			
		||||
     * @param name the material name to parse.
 | 
			
		||||
     * @return the material name with the version removed.
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    private static String parseLegacyMaterialName(String name) {
 | 
			
		||||
        int index = name.indexOf('/');
 | 
			
		||||
        return index == -1 ? name : name.substring(0, index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if the specified version is the same version or higher than the current server version.
 | 
			
		||||
     *
 | 
			
		||||
     * @param version the version to be checked.
 | 
			
		||||
     * @param version the major version to be checked. "1." is ignored. E.g. 1.12 = 12 | 1.9 = 9
 | 
			
		||||
     * @return true of the version is equal or higher than the current version.
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isVersionOrHigher(@Nonnull MinecraftVersion version) {
 | 
			
		||||
        Objects.requireNonNull(version, "Cannot compare to a null version");
 | 
			
		||||
        return VERSION.ordinal() >= version.ordinal();
 | 
			
		||||
    public static boolean supports(int version) {
 | 
			
		||||
        return VERSION >= version;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -1611,45 +1596,28 @@ public enum Materials {
 | 
			
		||||
     * Gets the exact major version (..., 1.9, 1.10, ..., 1.14)
 | 
			
		||||
     *
 | 
			
		||||
     * @param version Supports {@link Bukkit#getVersion()}, {@link Bukkit#getBukkitVersion()} and normal formats such as "1.14"
 | 
			
		||||
     * @return the exact major version, or {@link MinecraftVersion#UNKNOWN} if unknown or unsupported.
 | 
			
		||||
     * @return the exact major version.
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static String getMajorVersion(@Nonnull String version) {
 | 
			
		||||
        Validate.notEmpty(version, "Cannot get exact major minecraft version for null or empty version");
 | 
			
		||||
 | 
			
		||||
        // getBukkitVersion()
 | 
			
		||||
        if (version.contains("-R") || version.endsWith("SNAPSHOT")) version = version.substring(0, version.indexOf('-'));
 | 
			
		||||
 | 
			
		||||
        // getVersion()
 | 
			
		||||
        int index = version.indexOf("MC:");
 | 
			
		||||
        if (index != -1) version = version.substring(index + 4, version.length() - 1);
 | 
			
		||||
        int index = version.lastIndexOf("MC:");
 | 
			
		||||
        if (index != -1) {
 | 
			
		||||
            version = version.substring(index + 4, version.length() - 1);
 | 
			
		||||
        } else if (version.endsWith("SNAPSHOT")) {
 | 
			
		||||
            // getBukkitVersion()
 | 
			
		||||
            index = version.indexOf('-');
 | 
			
		||||
            version = version.substring(0, index);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 1.13.2, 1.14.4, etc...
 | 
			
		||||
        int lastDot = version.lastIndexOf('.');
 | 
			
		||||
        if (version.indexOf('.') != lastDot) version = version.substring(0, lastDot);
 | 
			
		||||
 | 
			
		||||
        return version;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Parses the string arugment to a version.
 | 
			
		||||
     * Supports {@link Bukkit#getVersion()}, {@link Bukkit#getBukkitVersion()} and normal formats such as "1.14"
 | 
			
		||||
     *
 | 
			
		||||
     * @param version the server version.
 | 
			
		||||
     * @return the Minecraft version represented by the string.
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public static MinecraftVersion valueOfVersion(@Nonnull String version) {
 | 
			
		||||
        Validate.notEmpty(version, "Cannot get minecraft version for null or empty version");
 | 
			
		||||
 | 
			
		||||
        version = getMajorVersion(version);
 | 
			
		||||
        if (version.equals("1.10") || version.equals("1.11") || version.equals("1.12")) return MinecraftVersion.V1_9;
 | 
			
		||||
 | 
			
		||||
        version = 'V' + version.replace('.', '_');
 | 
			
		||||
        return Enums.getIfPresent(MinecraftVersion.class, version).or(MinecraftVersion.UNKNOWN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if the material can be damaged by using it.
 | 
			
		||||
     * Names going through this method are not formatted.
 | 
			
		||||
@@ -1680,14 +1648,14 @@ public enum Materials {
 | 
			
		||||
     * <br>
 | 
			
		||||
     * <b>{@code CONTAINS} Examples:</b>
 | 
			
		||||
     * <pre>
 | 
			
		||||
     *     "CONTAINS:CHEST" -> CHEST, ENDERCHEST, TRAPPED_CHEST -> true
 | 
			
		||||
     *     "cOnTaINS:dYe" -> GREEN_DYE, YELLOW_DYE, BLUE_DYE, INK_SACK -> true
 | 
			
		||||
     *     {@code "CONTAINS:CHEST" -> CHEST, ENDERCHEST, TRAPPED_CHEST -> true}
 | 
			
		||||
     *     {@code "cOnTaINS:dYe" -> GREEN_DYE, YELLOW_DYE, BLUE_DYE, INK_SACK -> true}
 | 
			
		||||
     * </pre>
 | 
			
		||||
     * <p>
 | 
			
		||||
     * <b>{@code REGEX} Examples</b>
 | 
			
		||||
     * <pre>
 | 
			
		||||
     *     "REGEX:^.+_.+_.+$" -> Every Material with 3 underlines or more: SHULKER_SPAWN_EGG, SILVERFISH_SPAWN_EGG, SKELETON_HORSE_SPAWN_EGG
 | 
			
		||||
     *     "REGEX:^.{1,3}$" -> Material names that have 3 letters only: BED, MAP, AIR
 | 
			
		||||
     *     {@code "REGEX:^.+_.+_.+$" -> Every Material with 3 underlines or more: SHULKER_SPAWN_EGG, SILVERFISH_SPAWN_EGG, SKELETON_HORSE_SPAWN_EGG}
 | 
			
		||||
     *     {@code "REGEX:^.{1,3}$" -> Material names that have 3 letters only: BED, MAP, AIR}
 | 
			
		||||
     * </pre>
 | 
			
		||||
     * <p>
 | 
			
		||||
     * The reason that there are tags for {@code CONTAINS} and {@code REGEX}
 | 
			
		||||
@@ -1734,19 +1702,17 @@ public enum Materials {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the version which this material was added in.
 | 
			
		||||
     * If the material was added before {@link MinecraftVersion#V1_13} then
 | 
			
		||||
     * it'll return {@link MinecraftVersion#UNKNOWN}
 | 
			
		||||
     * If the material doesn't have a version it'll return 0;
 | 
			
		||||
     *
 | 
			
		||||
     * @return the Minecraft version which tihs material was added in.
 | 
			
		||||
     * @since 3.0.0
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public MinecraftVersion getMaterialVersion() {
 | 
			
		||||
        if (this.legacy.length == 0) return MinecraftVersion.UNKNOWN;
 | 
			
		||||
    public int getMaterialVersion() {
 | 
			
		||||
        if (this.legacy.length == 0) return 0;
 | 
			
		||||
        String version = this.legacy[0];
 | 
			
		||||
        if (version.charAt(1) != '.') return MinecraftVersion.UNKNOWN;
 | 
			
		||||
        if (version.charAt(1) != '.') return 0;
 | 
			
		||||
 | 
			
		||||
        return MinecraftVersion.valueOf('V' + version.replace('.', '_'));
 | 
			
		||||
        return Integer.parseInt(version.substring(2));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -1790,16 +1756,13 @@ public enum Materials {
 | 
			
		||||
     *
 | 
			
		||||
     * @param name the name to check
 | 
			
		||||
     * @return true if it's one of the legacy names.
 | 
			
		||||
     * @see #containsLegacy(String)
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    private boolean anyMatchLegacy(@Nonnull String name) {
 | 
			
		||||
        // If it's a new material, everything after this is a suggestion.
 | 
			
		||||
        // At least until now except one or two materials.
 | 
			
		||||
        if (this.isNew()) return false;
 | 
			
		||||
 | 
			
		||||
        for (String legacy : this.legacy)
 | 
			
		||||
            if (parseLegacyMaterialName(legacy).equals(name)) return true;
 | 
			
		||||
        for (String legacy : this.legacy) {
 | 
			
		||||
            if (legacy.isEmpty()) break; // Left-side suggestion list
 | 
			
		||||
            if (name.equals(legacy)) return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1825,7 +1788,7 @@ public enum Materials {
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressWarnings("deprecation")
 | 
			
		||||
    public int getId() {
 | 
			
		||||
        if (this.isNew()) return -1;
 | 
			
		||||
        if (this.data != 0 || (this.legacy.length != 0 && Integer.parseInt(this.legacy[0].substring(2)) >= 13)) return -1;
 | 
			
		||||
        Material material = this.parseMaterial();
 | 
			
		||||
        return material == null ? -1 : material.getId();
 | 
			
		||||
    }
 | 
			
		||||
@@ -1884,7 +1847,7 @@ public enum Materials {
 | 
			
		||||
    /**
 | 
			
		||||
     * Get a list of materials names that was previously used by older versions.
 | 
			
		||||
     * If the material was added in a new version {@link #isNewVersion()},
 | 
			
		||||
     * then the first element will indicate which version the material was added in {@link MinecraftVersion}.
 | 
			
		||||
     * then the first element will indicate which version the material was added in.
 | 
			
		||||
     *
 | 
			
		||||
     * @return a list of legacy material names and the first element as the version the material was added in if new.
 | 
			
		||||
     * @since 1.0.0
 | 
			
		||||
@@ -1912,7 +1875,7 @@ public enum Materials {
 | 
			
		||||
     * Parses an item from this Materials.
 | 
			
		||||
     * Uses data values on older versions.
 | 
			
		||||
     *
 | 
			
		||||
     * @param suggest if true {@link #parseMaterial(boolean true)} will be used.
 | 
			
		||||
     * @param suggest if true {@link #parseMaterial(boolean)} true will be used.
 | 
			
		||||
     * @return an ItemStack with the same material (and data value if in older versions.)
 | 
			
		||||
     * @see #setType(ItemStack)
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
@@ -1945,10 +1908,12 @@ public enum Materials {
 | 
			
		||||
     * @see #matchMaterials(String, byte)
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    @SuppressWarnings("OptionalAssignedToNull")
 | 
			
		||||
    @Nullable
 | 
			
		||||
    public Material parseMaterial(boolean suggest) {
 | 
			
		||||
        Material mat = PARSED_CACHE.getIfPresent(this);
 | 
			
		||||
        if (mat != null) return mat;
 | 
			
		||||
        Optional<Material> cache = PARSED_CACHE.getIfPresent(this);
 | 
			
		||||
        if (cache != null) return cache.orElse(null);
 | 
			
		||||
        Material mat;
 | 
			
		||||
 | 
			
		||||
        if (!ISFLAT && this.isDuplicated()) mat = requestOldMaterial(suggest);
 | 
			
		||||
        else {
 | 
			
		||||
@@ -1956,7 +1921,7 @@ public enum Materials {
 | 
			
		||||
            if (mat == null) mat = requestOldMaterial(suggest);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mat != null) PARSED_CACHE.put(this, mat);
 | 
			
		||||
        if (mat != null) PARSED_CACHE.put(this, Optional.ofNullable(mat));
 | 
			
		||||
        return mat;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1971,27 +1936,22 @@ public enum Materials {
 | 
			
		||||
     */
 | 
			
		||||
    @Nullable
 | 
			
		||||
    private Material requestOldMaterial(boolean suggest) {
 | 
			
		||||
        boolean noMaterialParse = this.isNew() && !suggest;
 | 
			
		||||
        Material material;
 | 
			
		||||
 | 
			
		||||
        for (int i = this.legacy.length - 1; i >= 0; i--) {
 | 
			
		||||
            String legacy = this.legacy[i];
 | 
			
		||||
 | 
			
		||||
            // Slash means it's just another name for the material in another version.
 | 
			
		||||
            int index = legacy.indexOf('/');
 | 
			
		||||
            if (index != -1) {
 | 
			
		||||
                legacy = legacy.substring(0, index);
 | 
			
		||||
                material = Material.getMaterial(legacy);
 | 
			
		||||
            // Check if we've reached the end and the last string is our
 | 
			
		||||
            // material version.
 | 
			
		||||
            if (i == 0 && legacy.charAt(1) == '.') return null;
 | 
			
		||||
 | 
			
		||||
                if (material != null) return material;
 | 
			
		||||
                else continue;
 | 
			
		||||
            // According to the suggestion list format, all the other names continuing
 | 
			
		||||
            // from here are considered as a "suggestion"
 | 
			
		||||
            // The empty string is an indicator for suggestion list on the left side.
 | 
			
		||||
            if (legacy.isEmpty()) {
 | 
			
		||||
                if (suggest) continue;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // According to the suggestion format list, all the other names continuing
 | 
			
		||||
            // from here are considered as a "suggestion" if there's no slash anymore.
 | 
			
		||||
            // But continue if it's not even a new material.
 | 
			
		||||
            if (noMaterialParse) return null;
 | 
			
		||||
            material = Material.getMaterial(legacy);
 | 
			
		||||
            Material material = Material.getMaterial(legacy);
 | 
			
		||||
            if (material != null) return material;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
@@ -2008,7 +1968,7 @@ public enum Materials {
 | 
			
		||||
    public boolean isSimilar(@Nonnull ItemStack item) {
 | 
			
		||||
        Objects.requireNonNull(item, "Cannot compare with null ItemStack");
 | 
			
		||||
        if (item.getType() != this.parseMaterial()) return false;
 | 
			
		||||
        return (ISFLAT || this.isDamageable()) || item.getDurability() == this.data;
 | 
			
		||||
        return ISFLAT || this.isDamageable() || item.getDurability() == this.data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -2021,7 +1981,13 @@ public enum Materials {
 | 
			
		||||
     */
 | 
			
		||||
    @Nonnull
 | 
			
		||||
    public List<String> getSuggestions() {
 | 
			
		||||
        return this.isNew() ? Arrays.stream(this.legacy).skip(1).collect(Collectors.toList()) : new ArrayList<>();
 | 
			
		||||
        if (this.legacy.length == 0 || this.legacy[0].charAt(1) != '.') return new ArrayList<>();
 | 
			
		||||
        List<String> suggestions = new ArrayList<>();
 | 
			
		||||
        for (String legacy : this.legacy) {
 | 
			
		||||
            if (legacy.isEmpty()) break;
 | 
			
		||||
            suggestions.add(legacy);
 | 
			
		||||
        }
 | 
			
		||||
        return suggestions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -2032,92 +1998,25 @@ public enum Materials {
 | 
			
		||||
     * if you're going to parse and use the material later.
 | 
			
		||||
     *
 | 
			
		||||
     * @return true if the material exists in {@link Material} list.
 | 
			
		||||
     * @see #isNew()
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isSupported() {
 | 
			
		||||
        MinecraftVersion version = this.getMaterialVersion();
 | 
			
		||||
        if (version != MinecraftVersion.UNKNOWN) return isVersionOrHigher(version);
 | 
			
		||||
        int version = this.getMaterialVersion();
 | 
			
		||||
        if (version != 0) return supports(version);
 | 
			
		||||
 | 
			
		||||
        Material material = Material.getMaterial(this.name());
 | 
			
		||||
        if (material == null) {
 | 
			
		||||
            for (int i = this.legacy.length - 1; i != -1; i--) {
 | 
			
		||||
                String legacy = this.legacy[i];
 | 
			
		||||
                if (StringUtils.contains(legacy, '/')) continue;
 | 
			
		||||
 | 
			
		||||
                material = Material.getMaterial(legacy);
 | 
			
		||||
                if (material != null) break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return material != null;
 | 
			
		||||
        if (material != null) return true;
 | 
			
		||||
        return requestOldMaterial(false) != null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if the material is newly added after the 1.13 Aquatic Update ({@link MinecraftVersion#V1_13}).
 | 
			
		||||
     * Checks if the material is newly added after the 1.13 Aquatic Update.
 | 
			
		||||
     *
 | 
			
		||||
     * @return true if the material was newly added, otherwise false.
 | 
			
		||||
     * @see #getMaterialVersion()
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isNew() {
 | 
			
		||||
        return this.legacy.length != 0 && this.legacy[0].charAt(1) == '.';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Only major Minecraft versions related to most changes.
 | 
			
		||||
     * The enum's order should not be changed.
 | 
			
		||||
     *
 | 
			
		||||
     * @since 2.0.0
 | 
			
		||||
     */
 | 
			
		||||
    public enum MinecraftVersion {
 | 
			
		||||
        /**
 | 
			
		||||
         * 1.7 or below.
 | 
			
		||||
         * Using {@link #getMaterialVersion()} it means 1.12 or below.
 | 
			
		||||
         * https://minecraft.gamepedia.com/Java_Edition_1.7
 | 
			
		||||
         *
 | 
			
		||||
         * @since 2.0.0
 | 
			
		||||
         */
 | 
			
		||||
        UNKNOWN,
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Bountiful Update
 | 
			
		||||
         * https://minecraft.gamepedia.com/Java_Edition_1.18
 | 
			
		||||
         *
 | 
			
		||||
         * @since 2.0.0
 | 
			
		||||
         */
 | 
			
		||||
        V1_8,
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Combat Update (Pitiful Update? 90% of the reason why that this class is a thing)
 | 
			
		||||
         * https://minecraft.gamepedia.com/Java_Edition_1.9
 | 
			
		||||
         *
 | 
			
		||||
         * @since 2.0.0
 | 
			
		||||
         */
 | 
			
		||||
        V1_9,
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Aquatic Update
 | 
			
		||||
         * Includes 1.10, 1.11 and 1.12
 | 
			
		||||
         * https://minecraft.gamepedia.com/Java_Edition_1.13
 | 
			
		||||
         *
 | 
			
		||||
         * @since 2.0.0
 | 
			
		||||
         */
 | 
			
		||||
        V1_13,
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Village Pillage Update
 | 
			
		||||
         * https://minecraft.gamepedia.com/Java_Edition_1.14
 | 
			
		||||
         *
 | 
			
		||||
         * @since 2.0.0
 | 
			
		||||
         */
 | 
			
		||||
        V1_14,
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Buzzy Bees Update
 | 
			
		||||
         * https://minecraft.gamepedia.com/Java_Edition_1.15
 | 
			
		||||
         *
 | 
			
		||||
         * @since 3.0.0
 | 
			
		||||
         */
 | 
			
		||||
        V1_15
 | 
			
		||||
    public boolean isFromNewSystem() {
 | 
			
		||||
        return this.legacy.length != 0 && Integer.parseInt(this.legacy[0].substring(2)) > 13;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,10 @@
 | 
			
		||||
package io.izzel.taboolib.util.lite;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.util.NumberConversions;
 | 
			
		||||
 | 
			
		||||
import java.text.DecimalFormat;
 | 
			
		||||
import java.util.Random;
 | 
			
		||||
import java.util.concurrent.ThreadLocalRandom;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @Author 坏黑
 | 
			
		||||
@@ -9,19 +12,42 @@ import java.util.Random;
 | 
			
		||||
 */
 | 
			
		||||
public class Numbers {
 | 
			
		||||
 | 
			
		||||
    private static Random random = new Random();
 | 
			
		||||
    private static DecimalFormat doubleFormat = new DecimalFormat("#.##");
 | 
			
		||||
    private static final DecimalFormat doubleFormat = new DecimalFormat("#.##");
 | 
			
		||||
 | 
			
		||||
    public static int toInt(Object in) {
 | 
			
		||||
        return NumberConversions.toInt(in);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static long toLong(Object in) {
 | 
			
		||||
        return NumberConversions.toLong(in);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static short toShort(Object in) {
 | 
			
		||||
        return NumberConversions.toShort(in);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static float toFloat(Object in) {
 | 
			
		||||
        return NumberConversions.toFloat(in);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double toDouble(Object in) {
 | 
			
		||||
        return NumberConversions.toDouble(in);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static byte toByte(Object in) {
 | 
			
		||||
        return NumberConversions.toByte(in);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Random getRandom() {
 | 
			
		||||
        return random;
 | 
			
		||||
        return ThreadLocalRandom.current();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean random(double v) {
 | 
			
		||||
        return random.nextDouble() <= v;
 | 
			
		||||
        return ThreadLocalRandom.current().nextDouble() <= v;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int random(int v) {
 | 
			
		||||
        return random.nextInt(v);
 | 
			
		||||
        return ThreadLocalRandom.current().nextInt(v);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Double format(Double num) {
 | 
			
		||||
@@ -29,15 +55,11 @@ public class Numbers {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int getRandomInteger(Number num1, Number num2) {
 | 
			
		||||
        int min = Math.min(num1.intValue(), num2.intValue());
 | 
			
		||||
        int max = Math.max(num1.intValue(), num2.intValue());
 | 
			
		||||
        return (int) (random.nextDouble() * (max - min) + min);
 | 
			
		||||
        return ThreadLocalRandom.current().nextInt(num1.intValue(), num2.intValue() + 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getRandomDouble(Number num1, Number num2) {
 | 
			
		||||
        double min = Math.min(num1.doubleValue(), num2.doubleValue());
 | 
			
		||||
        double max = Math.max(num1.doubleValue(), num2.doubleValue());
 | 
			
		||||
        return random.nextDouble() * (max - min) + min;
 | 
			
		||||
        return ThreadLocalRandom.current().nextDouble(num1.doubleValue(), num2.doubleValue());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Boolean getBoolean(String str) {
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@ import java.util.Random;
 | 
			
		||||
 * @author DarkBlade12
 | 
			
		||||
 * @version 1.8
 | 
			
		||||
 */
 | 
			
		||||
@Deprecated
 | 
			
		||||
public enum Particles {
 | 
			
		||||
 | 
			
		||||
    BARRIER,
 | 
			
		||||
@@ -105,10 +106,11 @@ public enum Particles {
 | 
			
		||||
    WATER_WAKE,
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    private static int mcVersion = NumberConversions.toInt(Version.getBukkitVersion().split("_")[1]);
 | 
			
		||||
    private static final int mcVersion = NumberConversions.toInt(Version.getBukkitVersion().split("_")[1]);
 | 
			
		||||
    private org.bukkit.Particle bukkitParticle;
 | 
			
		||||
    private final List<ParticleProperty> properties;
 | 
			
		||||
    private int min, max;
 | 
			
		||||
    private final int min;
 | 
			
		||||
    private final int max;
 | 
			
		||||
 | 
			
		||||
    Particles(ParticleProperty... properties) {
 | 
			
		||||
        this(0, 0, properties);
 | 
			
		||||
@@ -597,13 +599,13 @@ public enum Particles {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class Particle {
 | 
			
		||||
        private static Random random = new Random();
 | 
			
		||||
        private static final Random random = new Random();
 | 
			
		||||
 | 
			
		||||
        private Particles effect;
 | 
			
		||||
        private ParticleShape shape;
 | 
			
		||||
        private OrdinaryColor color;
 | 
			
		||||
        private final Particles effect;
 | 
			
		||||
        private final ParticleShape shape;
 | 
			
		||||
        private final OrdinaryColor color;
 | 
			
		||||
 | 
			
		||||
        private byte typeCode;
 | 
			
		||||
        private final byte typeCode;
 | 
			
		||||
 | 
			
		||||
        public Particle(Particles effect, ParticleShape shape, OrdinaryColor color) {
 | 
			
		||||
            this.effect = effect;
 | 
			
		||||
@@ -742,7 +744,7 @@ public enum Particles {
 | 
			
		||||
        private float offsetZ;
 | 
			
		||||
        private final float speed;
 | 
			
		||||
        private int amount;
 | 
			
		||||
        private int size = 1;
 | 
			
		||||
        private final int size = 1;
 | 
			
		||||
        private final boolean longDistance;
 | 
			
		||||
        private Object data;
 | 
			
		||||
        private Object packet;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user