diff --git a/src/main/scala/io/izzel/taboolib/common/listener/ListenerCommand.java b/src/main/scala/io/izzel/taboolib/common/listener/ListenerCommand.java index 5bb1524..b23c147 100644 --- a/src/main/scala/io/izzel/taboolib/common/listener/ListenerCommand.java +++ b/src/main/scala/io/izzel/taboolib/common/listener/ListenerCommand.java @@ -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 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 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 action1 = loc -> Effects.create(Particle.FLAME, loc).count(1).player(player).play(); + Consumer 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 list, int index, int def) { + return list.size() > index ? NumberConversions.toInt(list.get(index)) : def; + } + + private static double orDob(List list, int index, double def) { + return list.size() > index ? NumberConversions.toDouble(list.get(index)) : def; + } } diff --git a/src/main/scala/io/izzel/taboolib/module/nms/NMSImpl.java b/src/main/scala/io/izzel/taboolib/module/nms/NMSImpl.java index 1b563a5..2ab21b0 100644 --- a/src/main/scala/io/izzel/taboolib/module/nms/NMSImpl.java +++ b/src/main/scala/io/izzel/taboolib/module/nms/NMSImpl.java @@ -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 diff --git a/src/main/scala/io/izzel/taboolib/util/item/Items.java b/src/main/scala/io/izzel/taboolib/util/item/Items.java index f222c3c..f32a98b 100644 --- a/src/main/scala/io/izzel/taboolib/util/item/Items.java +++ b/src/main/scala/io/izzel/taboolib/util/item/Items.java @@ -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(); } diff --git a/src/main/scala/io/izzel/taboolib/util/lite/Effects.java b/src/main/scala/io/izzel/taboolib/util/lite/Effects.java index ad2a1fa..05bb257 100644 --- a/src/main/scala/io/izzel/taboolib/util/lite/Effects.java +++ b/src/main/scala/io/izzel/taboolib/util/lite/Effects.java @@ -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 + *

+ * 部分代码来自 + * CryptoMorin 的 XSeries 项目 */ public class Effects { @@ -36,10 +41,26 @@ public class Effects { private List 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 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 action) { + public static void buildPolygon(Location center, double radius, double interval, Consumer 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 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 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 orbit, Consumer 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 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 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 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 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 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 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 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 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 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 action1, Consumer 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 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 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 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 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 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 action) { + List previousPoints = null; + for (int i = 0; i < cubes + 1; i++) { + List 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; diff --git a/src/main/scala/io/izzel/taboolib/util/lite/Materials.java b/src/main/scala/io/izzel/taboolib/util/lite/Materials.java index 6def722..6fbda01 100644 --- a/src/main/scala/io/izzel/taboolib/util/lite/Materials.java +++ b/src/main/scala/io/izzel/taboolib/util/lite/Materials.java @@ -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/ - */ /** * Materials - Data Values/Pre-flattening
* Supports 1.8-1.15
* 1.13 and above as priority. + *

+ * This class is mainly designed to support ItemStacks. + * If you want to use it on blocks you'll have to + * use XBlock + *

+ * 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. *

- * 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 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 PARSED_CACHE = CacheBuilder.newBuilder() + private static final Cache> 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: *

*

- * {@link #isVersionOrHigher(MinecraftVersion V1_13)} + * {@link #supports(int) 13}} *
* * @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: *

*

- * {@link #getVersion()} == {@link MinecraftVersion#V1_8} + * {@link #getVersion()} == 1.8 *
* * @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 { *

* Examples *

-     *     INK_SACK:1 -> RED_DYE
-     *     WOOL, 14  -> RED_WOOL
+     *     {@code INK_SACK:1 -> RED_DYE}
+     *     {@code WOOL, 14  -> RED_WOOL}
      * 
* * @see #matchDefinedMaterials(String, byte) @@ -1332,7 +1335,6 @@ public enum Materials { */ @Nonnull public static Optional matchMaterials(@Nonnull String name, byte data) { - Validate.notEmpty(name, "Cannot match a material with null or empty material name"); Optional oldMatch = matchMaterialsWithData(name); if (oldMatch.isPresent()) return oldMatch; @@ -1348,8 +1350,8 @@ public enum Materials { *

* Examples *

-     *     INK_SACK:1 -> RED_DYE
-     *     WOOL, 14  -> RED_WOOL
+     *     {@code INK_SACK:1 -> RED_DYE}
+     *     {@code WOOL, 14  -> RED_WOOL}
      * 
* * @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 getNewMaterialsIfDuplicated(@Nonnull String name) { - Validate.notEmpty(name, "Cannot get new duplicated material for null or empty material name"); name = format(name); for (Map.Entry 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 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 { *
* {@code CONTAINS} Examples: *
-     *     "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}
      * 
*

* {@code REGEX} Examples *

-     *     "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}
      * 
*

* 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 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 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 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; } } diff --git a/src/main/scala/io/izzel/taboolib/util/lite/Numbers.java b/src/main/scala/io/izzel/taboolib/util/lite/Numbers.java index a9409fd..dd7f962 100644 --- a/src/main/scala/io/izzel/taboolib/util/lite/Numbers.java +++ b/src/main/scala/io/izzel/taboolib/util/lite/Numbers.java @@ -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) { diff --git a/src/main/scala/io/izzel/taboolib/util/lite/Particles.java b/src/main/scala/io/izzel/taboolib/util/lite/Particles.java index 3baebad..cee1f0e 100644 --- a/src/main/scala/io/izzel/taboolib/util/lite/Particles.java +++ b/src/main/scala/io/izzel/taboolib/util/lite/Particles.java @@ -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 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;