diff --git a/src/main/java/net/momirealms/customfishing/CustomFishing.java b/src/main/java/net/momirealms/customfishing/CustomFishing.java index bacf36ac..7bc9af61 100644 --- a/src/main/java/net/momirealms/customfishing/CustomFishing.java +++ b/src/main/java/net/momirealms/customfishing/CustomFishing.java @@ -14,6 +14,24 @@ public final class CustomFishing extends JavaPlugin { public static JavaPlugin instance; public static BukkitAudiences adventure; + @Override + public void onLoad(){ + +// Paper原生的adventure似乎存在冲突导致1.18.1以下版本无法使用,所以方法废弃 +// LibraryLoader.load("net.kyori","adventure-api","4.11.0","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-platform-api","4.1.1","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-platform-bukkit","4.1.1","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-platform-facet","4.1.1","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-text-serializer-gson","4.11.0","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-text-serializer-plain","4.11.0","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-text-serializer-gson-legacy-impl","4.11.0","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-text-serializer-legacy","4.11.0","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-nbt","4.11.0","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-key","4.11.0","https://oss.sonatype.org/content/groups/public"); +// LibraryLoader.load("net.kyori","adventure-text-minimessage","4.11.0","https://oss.sonatype.org/content/groups/public"); + + } + @Override public void onEnable() { instance = this; @@ -28,7 +46,6 @@ public final class CustomFishing extends JavaPlugin { @Override public void onDisable() { - AdventureManager.consoleMessage("[CustomFishing] 插件已卸载! 作者:小默米 QQ:3266959688"); if(adventure != null) { adventure.close(); adventure = null; diff --git a/src/main/java/net/momirealms/customfishing/helper/LibraryLoader.java b/src/main/java/net/momirealms/customfishing/helper/LibraryLoader.java new file mode 100644 index 00000000..d35ab114 --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/helper/LibraryLoader.java @@ -0,0 +1,196 @@ +/* + * This file is part of helper, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 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 net.momirealms.customfishing.helper; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; + +import net.momirealms.customfishing.CustomFishing; +import org.apache.commons.lang.StringUtils; + +import java.io.File; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.util.Objects; + +/** + * Resolves {@link MavenLibrary} annotations for a class, and loads the dependency + * into the classloader. + */ +@NonnullByDefault +public final class LibraryLoader { + + @SuppressWarnings("Guava") + private static final Supplier URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) CustomFishing.instance.getClass().getClassLoader())); + + /** + * Resolves all {@link MavenLibrary} annotations on the given object. + * + * @param object the object to load libraries for. + */ + public static void loadAll(Object object) { + loadAll(object.getClass()); + } + + /** + * Resolves all {@link MavenLibrary} annotations on the given class. + * + * @param clazz the class to load libraries for. + */ + public static void loadAll(Class clazz) { + MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class); + if (libs == null) { + return; + } + + for (MavenLibrary lib : libs) { + load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url()); + } + } + + public static void load(String groupId, String artifactId, String version, String repoUrl) { + load(new Dependency(groupId, artifactId, version, repoUrl)); + } + + public static void load(Dependency d) { + //Log.info(String.format("Loading dependency %s:%s:%s from %s", d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getRepoUrl())); + String name = d.getArtifactId() + "-" + d.getVersion(); + + File saveLocation = new File(getLibFolder(d), name + ".jar"); + if (!saveLocation.exists()) { + + try { + Log.info("Dependency '" + name + "' is not already in the libraries folder. Attempting to download..."); + URL url = d.getUrl(); + + try (InputStream is = url.openStream()) { + Files.copy(is, saveLocation.toPath()); + Log.info("Dependency '" + name + "' successfully downloaded."); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (!saveLocation.exists()) { + throw new RuntimeException("Unable to download dependency: " + d.toString()); + } + + try { + URL_INJECTOR.get().addURL(saveLocation.toURI().toURL()); + } catch (Exception e) { + throw new RuntimeException("Unable to load dependency: " + saveLocation.toString(), e); + } + } + + private static File getLibFolder(Dependency dependency) { + File pluginDataFolder = CustomFishing.instance.getDataFolder(); + File serverDir = pluginDataFolder.getParentFile().getParentFile(); + + File helperDir = new File(serverDir, "libraries"); + String[] split = StringUtils.split(dependency.getGroupId(), "."); + File jarDir = new File(helperDir, split[0] + File.separator + split[1] + File.separator + dependency.artifactId + File.separator + dependency.version ); + jarDir.mkdirs(); + return jarDir; + } + + @NonnullByDefault + public static final class Dependency { + private final String groupId; + private final String artifactId; + private final String version; + private final String repoUrl; + + public Dependency(String groupId, String artifactId, String version, String repoUrl) { + this.groupId = Objects.requireNonNull(groupId, "groupId"); + this.artifactId = Objects.requireNonNull(artifactId, "artifactId"); + this.version = Objects.requireNonNull(version, "version"); + this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl"); + } + + public String getGroupId() { + return this.groupId; + } + + public String getArtifactId() { + return this.artifactId; + } + + public String getVersion() { + return this.version; + } + + public String getRepoUrl() { + return this.repoUrl; + } + + public URL getUrl() throws MalformedURLException { + String repo = this.repoUrl; + if (!repo.endsWith("/")) { + repo += "/"; + } + repo += "%s/%s/%s/%s-%s.jar"; + + String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version); + return new URL(url); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Dependency)) return false; + final Dependency other = (Dependency) o; + return this.getGroupId().equals(other.getGroupId()) && + this.getArtifactId().equals(other.getArtifactId()) && + this.getVersion().equals(other.getVersion()) && + this.getRepoUrl().equals(other.getRepoUrl()); + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.getGroupId().hashCode(); + result = result * PRIME + this.getArtifactId().hashCode(); + result = result * PRIME + this.getVersion().hashCode(); + result = result * PRIME + this.getRepoUrl().hashCode(); + return result; + } + + @Override + public String toString() { + return "LibraryLoader.Dependency(" + + "groupId=" + this.getGroupId() + ", " + + "artifactId=" + this.getArtifactId() + ", " + + "version=" + this.getVersion() + ", " + + "repoUrl=" + this.getRepoUrl() + ")"; + } + } +} diff --git a/src/main/java/net/momirealms/customfishing/helper/Log.java b/src/main/java/net/momirealms/customfishing/helper/Log.java new file mode 100644 index 00000000..175afaeb --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/helper/Log.java @@ -0,0 +1,64 @@ +/* + * This file is part of helper, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 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 net.momirealms.customfishing.helper; + +import net.momirealms.customfishing.CustomFishing; +import org.bukkit.Bukkit; + +import java.util.logging.Level; + +import javax.annotation.Nonnull; + +/** + * Utility for quickly accessing a logger instance without using {@link Bukkit#getLogger()} + */ +public final class Log { + + public static void info(@Nonnull String s) { + CustomFishing.instance.getLogger().info(s); + } + + public static void warn(@Nonnull String s) { + CustomFishing.instance.getLogger().warning(s); + } + + public static void severe(@Nonnull String s) { + CustomFishing.instance.getLogger().severe(s); + } + + public static void warn(@Nonnull String s, Throwable t) { + CustomFishing.instance.getLogger().log(Level.WARNING, s, t); + } + + public static void severe(@Nonnull String s, Throwable t) { + CustomFishing.instance.getLogger().log(Level.SEVERE, s, t); + } + + private Log() { + throw new UnsupportedOperationException("This class cannot be instantiated"); + } + +} diff --git a/src/main/java/net/momirealms/customfishing/helper/MavenLibraries.java b/src/main/java/net/momirealms/customfishing/helper/MavenLibraries.java new file mode 100644 index 00000000..0a89bf49 --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/helper/MavenLibraries.java @@ -0,0 +1,47 @@ +/* + * This file is part of helper, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 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 net.momirealms.customfishing.helper; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.annotation.Nonnull; + +/** + * Annotation to indicate the required libraries for a class. + */ +@Documented +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface MavenLibraries { + + @Nonnull + MavenLibrary[] value() default {}; + +} diff --git a/src/main/java/net/momirealms/customfishing/helper/MavenLibrary.java b/src/main/java/net/momirealms/customfishing/helper/MavenLibrary.java new file mode 100644 index 00000000..de197ae9 --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/helper/MavenLibrary.java @@ -0,0 +1,78 @@ +/* + * This file is part of helper, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 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 net.momirealms.customfishing.helper; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.annotation.Nonnull; + +/** + * Annotation to indicate a required library for a class. + */ +@Documented +@Repeatable(MavenLibraries.class) +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface MavenLibrary { + + /** + * The group id of the library + * + * @return the group id of the library + */ + @Nonnull + String groupId(); + + /** + * The artifact id of the library + * + * @return the artifact id of the library + */ + @Nonnull + String artifactId(); + + /** + * The version of the library + * + * @return the version of the library + */ + @Nonnull + String version(); + + /** + * The repo where the library can be obtained from + * + * @return the repo where the library can be obtained from + */ + @Nonnull + Repository repo() default @Repository(url = "https://repo1.maven.org/maven2"); + +} diff --git a/src/main/java/net/momirealms/customfishing/helper/NonnullByDefault.java b/src/main/java/net/momirealms/customfishing/helper/NonnullByDefault.java new file mode 100644 index 00000000..1c63b4b9 --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/helper/NonnullByDefault.java @@ -0,0 +1,46 @@ +/* + * This file is part of helper, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 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 net.momirealms.customfishing.helper; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.annotation.Nonnull; +import javax.annotation.meta.TypeQualifierDefault; + +@Nonnull +@Documented +@TypeQualifierDefault({ + ElementType.FIELD, + ElementType.METHOD, + ElementType.PARAMETER +}) +@Retention(RetentionPolicy.RUNTIME) +public @interface NonnullByDefault { + +} diff --git a/src/main/java/net/momirealms/customfishing/helper/Repository.java b/src/main/java/net/momirealms/customfishing/helper/Repository.java new file mode 100644 index 00000000..1764e119 --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/helper/Repository.java @@ -0,0 +1,52 @@ +/* + * This file is part of helper, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 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 net.momirealms.customfishing.helper; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.annotation.Nonnull; + +/** + * Represents a maven repository. + */ +@Documented +@Target(ElementType.LOCAL_VARIABLE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Repository { + + /** + * Gets the base url of the repository. + * + * @return the base url of the repository + */ + @Nonnull + String url(); + +} diff --git a/src/main/java/net/momirealms/customfishing/helper/URLClassLoaderAccess.java b/src/main/java/net/momirealms/customfishing/helper/URLClassLoaderAccess.java new file mode 100644 index 00000000..8ddf8f42 --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/helper/URLClassLoaderAccess.java @@ -0,0 +1,139 @@ +/* + * This file is part of helper, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 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 net.momirealms.customfishing.helper; + +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Collection; + +import javax.annotation.Nonnull; + +/** + * Provides access to {@link URLClassLoader}#addURL. + */ +public abstract class URLClassLoaderAccess { + + /** + * Creates a {@link URLClassLoaderAccess} for the given class loader. + * + * @param classLoader the class loader + * @return the access object + */ + static URLClassLoaderAccess create(URLClassLoader classLoader) { + if (Unsafe.isSupported()) { + return new Unsafe(classLoader); + } else { + return Noop.INSTANCE; + } + } + + private final URLClassLoader classLoader; + + protected URLClassLoaderAccess(URLClassLoader classLoader) { + this.classLoader = classLoader; + } + + + /** + * Adds the given URL to the class loader. + * + * @param url the URL to add + */ + public abstract void addURL(@Nonnull URL url); + + /** + * Accesses using sun.misc.Unsafe, supported on Java 9+. + * + * @author Vaishnav Anil (https://github.com/slimjar/slimjar) + */ + private static class Unsafe extends URLClassLoaderAccess { + private static final sun.misc.Unsafe UNSAFE; + + static { + sun.misc.Unsafe unsafe; + try { + Field unsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); + unsafeField.setAccessible(true); + unsafe = (sun.misc.Unsafe) unsafeField.get(null); + } catch (Throwable t) { + unsafe = null; + } + UNSAFE = unsafe; + } + + private static boolean isSupported() { + return UNSAFE != null; + } + + private final Collection unopenedURLs; + private final Collection pathURLs; + + @SuppressWarnings("unchecked") + Unsafe(URLClassLoader classLoader) { + super(classLoader); + + Collection unopenedURLs; + Collection pathURLs; + try { + Object ucp = fetchField(URLClassLoader.class, classLoader, "ucp"); + unopenedURLs = (Collection) fetchField(ucp.getClass(), ucp, "unopenedUrls"); + pathURLs = (Collection) fetchField(ucp.getClass(), ucp, "path"); + } catch (Throwable e) { + unopenedURLs = null; + pathURLs = null; + } + this.unopenedURLs = unopenedURLs; + this.pathURLs = pathURLs; + } + + private static Object fetchField(final Class clazz, final Object object, final String name) throws NoSuchFieldException { + Field field = clazz.getDeclaredField(name); + long offset = UNSAFE.objectFieldOffset(field); + return UNSAFE.getObject(object, offset); + } + + @Override + public void addURL(@Nonnull URL url) { + this.unopenedURLs.add(url); + this.pathURLs.add(url); + } + } + + private static class Noop extends URLClassLoaderAccess { + private static final Noop INSTANCE = new Noop(); + + private Noop() { + super(null); + } + + @Override + public void addURL(@Nonnull URL url) { + throw new UnsupportedOperationException(); + } + } + +} diff --git a/src/main/java/net/momirealms/customfishing/listener/PlayerListener.java b/src/main/java/net/momirealms/customfishing/listener/PlayerListener.java index 5bf07fc9..56ed660d 100644 --- a/src/main/java/net/momirealms/customfishing/listener/PlayerListener.java +++ b/src/main/java/net/momirealms/customfishing/listener/PlayerListener.java @@ -22,6 +22,7 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.potion.PotionEffect; @@ -381,7 +382,9 @@ public class PlayerListener implements Listener { public void onInteract(PlayerInteractEvent event){ if (!event.hasItem()) return; if (!(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)) return; - NBTItem nbtItem = new NBTItem(event.getItem()); + ItemStack itemStack = event.getItem(); + if (itemStack.getType() == Material.AIR) return; + NBTItem nbtItem = new NBTItem(itemStack); if (nbtItem.getCompound("CustomFishing") == null) return; if (nbtItem.getCompound("CustomFishing").getString("type").equals("util") || nbtItem.getCompound("CustomFishing").getString("id").equals("fishfinder")){ Player player = event.getPlayer(); diff --git a/src/main/java/net/momirealms/customfishing/utils/LootInstance.java b/src/main/java/net/momirealms/customfishing/utils/LootInstance.java index 4c62c237..65bb11b3 100644 --- a/src/main/java/net/momirealms/customfishing/utils/LootInstance.java +++ b/src/main/java/net/momirealms/customfishing/utils/LootInstance.java @@ -12,6 +12,7 @@ import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.inventory.meta.ItemMeta; import java.util.*; @@ -114,14 +115,25 @@ public class LootInstance { ItemStack itemStack = new ItemStack(Material.valueOf(this.material.toUpperCase())); ItemMeta itemMeta = itemStack.getItemMeta(); if (enchantment != null){ - enchantment.forEach(enchantment1 -> { - itemMeta.addEnchant(Enchantment.getByKey(enchantment1.getKey()),enchantment1.getLevel(),true); - }); + if (itemStack.getType() == Material.ENCHANTED_BOOK){ + EnchantmentStorageMeta meta = (EnchantmentStorageMeta)itemMeta; + enchantment.forEach(enchantment1 -> { + meta.addStoredEnchant(Enchantment.getByKey(enchantment1.getKey()),enchantment1.getLevel(),true); + }); + if (itemFlags != null){ + itemFlags.forEach(meta::addItemFlags); + } + itemStack.setItemMeta(meta); + }else { + enchantment.forEach(enchantment1 -> { + itemMeta.addEnchant(Enchantment.getByKey(enchantment1.getKey()),enchantment1.getLevel(),true); + }); + if (itemFlags != null){ + itemFlags.forEach(itemMeta::addItemFlags); + } + itemStack.setItemMeta(itemMeta); + } } - if (itemFlags != null){ - itemFlags.forEach(itemMeta::addItemFlags); - } - itemStack.setItemMeta(itemMeta); NBTItem nbtItem = new NBTItem(itemStack); //设置Name和Lore diff --git a/src/main/resources/loots.yml b/src/main/resources/loots.yml index 61584c69..5a5bc3b4 100644 --- a/src/main/resources/loots.yml +++ b/src/main/resources/loots.yml @@ -62,7 +62,7 @@ items: #附魔 enchantments: - minecraft:sharpness/1 - - minecraft:flames/1 + - minecraft:flame/1 item_flags: - HIDE_ENCHANTS