diff --git a/src/main/java/net/momirealms/customnameplates/ConfigManager.java b/src/main/java/net/momirealms/customnameplates/ConfigManager.java index 98c6231..772db06 100644 --- a/src/main/java/net/momirealms/customnameplates/ConfigManager.java +++ b/src/main/java/net/momirealms/customnameplates/ConfigManager.java @@ -36,6 +36,8 @@ public class ConfigManager { public static String lang; public static Long preview; public static boolean thin_font; + public static boolean hidePrefix; + public static boolean hideSuffix; public static void ReloadConfig(){ CustomNameplates.instance.saveDefaultConfig(); @@ -57,6 +59,8 @@ public class ConfigManager { key = Key.key(fontName); preview = config.getLong("config.preview-duration"); thin_font = config.getBoolean("config.use-thin-font",false); + hidePrefix = config.getBoolean("config.hide-prefix-when-equipped",false); + hideSuffix = config.getBoolean("config.hide-suffix-when-equipped",false); } } //消息文件 @@ -107,6 +111,7 @@ public class ConfigManager { public static String tableName; public static boolean enable_pool; public static boolean use_mysql; + public static boolean async; public static int maximum_pool_size; public static int minimum_idle; public static int maximum_lifetime; @@ -116,6 +121,7 @@ public class ConfigManager { YamlConfiguration databaseConfig = getConfig("database.yml"); String storage_mode = databaseConfig.getString("settings.storage-mode"); + async = !databaseConfig.getBoolean("settings.disable-async", true); //使用SQLite if(storage_mode.equals("SQLite")){ enable_pool = false; diff --git a/src/main/java/net/momirealms/customnameplates/CustomNameplates.java b/src/main/java/net/momirealms/customnameplates/CustomNameplates.java index 080ce78..9997071 100644 --- a/src/main/java/net/momirealms/customnameplates/CustomNameplates.java +++ b/src/main/java/net/momirealms/customnameplates/CustomNameplates.java @@ -6,6 +6,7 @@ import net.momirealms.customnameplates.commands.Execute; import net.momirealms.customnameplates.commands.TabComplete; import net.momirealms.customnameplates.data.DataManager; import net.momirealms.customnameplates.data.SqlHandler; +import net.momirealms.customnameplates.helper.LibraryLoader; import net.momirealms.customnameplates.hook.HookManager; import net.momirealms.customnameplates.listener.PlayerListener; import net.momirealms.customnameplates.listener.PacketsListener; @@ -35,8 +36,16 @@ public final class CustomNameplates extends JavaPlugin { public ScoreBoardManager getScoreBoardManager() { return this.scoreBoardManager; } @Override - public void onEnable() { + public void onLoad(){ + instance = this; + LibraryLoader.load("commons-io","commons-io","2.11.0","https://repo.maven.apache.org/maven2/"); + LibraryLoader.load("com.zaxxer","HikariCP","5.0.1","https://repo.maven.apache.org/maven2/"); + } + + @Override + public void onEnable() { + adventure = BukkitAudiences.create(this); AdventureManager.consoleMessage("[CustomNameplates] Running on " + Bukkit.getVersion()); //重载插件 @@ -62,7 +71,7 @@ public final class CustomNameplates extends JavaPlugin { return; } //启动完成 - AdventureManager.consoleMessage("[CustomNameplates] 插件已启用! 作者: 小默米 QQ:3266959688"); + AdventureManager.consoleMessage("[CustomNameplates] Plugin Enabled!"); } @Override @@ -71,8 +80,6 @@ public final class CustomNameplates extends JavaPlugin { SqlHandler.close(); //清除缓存实体 Execute.pCache.forEach(Entity::remove); - //卸载完成 - AdventureManager.consoleMessage("[CustomNameplates] 插件已卸载! 作者: 小默米 QQ:3266959688"); //关闭adventure if(adventure != null) { adventure.close(); diff --git a/src/main/java/net/momirealms/customnameplates/commands/Execute.java b/src/main/java/net/momirealms/customnameplates/commands/Execute.java index af84373..5b6d860 100644 --- a/src/main/java/net/momirealms/customnameplates/commands/Execute.java +++ b/src/main/java/net/momirealms/customnameplates/commands/Execute.java @@ -5,7 +5,6 @@ import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedDataWatcher; -import com.sun.source.tree.BreakTree; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; @@ -15,6 +14,7 @@ import net.momirealms.customnameplates.AdventureManager; import net.momirealms.customnameplates.CustomNameplates; import net.momirealms.customnameplates.data.DataManager; import net.momirealms.customnameplates.font.FontCache; +import net.momirealms.customnameplates.hook.ParsePapi; import net.momirealms.customnameplates.nameplates.NameplateUtil; import net.momirealms.customnameplates.scoreboard.NameplatesTeam; import org.apache.commons.lang.StringUtils; @@ -239,8 +239,8 @@ public class Execute implements CommandExecutor { String playerPrefix; String playerSuffix; if (plugin.getHookManager().hasPlaceholderAPI()) { - playerPrefix = this.plugin.getHookManager().parsePlaceholders(player, ConfigManager.MainConfig.player_prefix); - playerSuffix = this.plugin.getHookManager().parsePlaceholders(player, ConfigManager.MainConfig.player_suffix); + playerPrefix = ParsePapi.parsePlaceholders(player, ConfigManager.MainConfig.player_prefix); + playerSuffix = ParsePapi.parsePlaceholders(player, ConfigManager.MainConfig.player_suffix); }else { playerPrefix = ConfigManager.MainConfig.player_prefix; playerSuffix = ConfigManager.MainConfig.player_suffix; diff --git a/src/main/java/net/momirealms/customnameplates/data/DataManager.java b/src/main/java/net/momirealms/customnameplates/data/DataManager.java index 48ba34f..725dd91 100644 --- a/src/main/java/net/momirealms/customnameplates/data/DataManager.java +++ b/src/main/java/net/momirealms/customnameplates/data/DataManager.java @@ -2,6 +2,8 @@ package net.momirealms.customnameplates.data; import net.momirealms.customnameplates.AdventureManager; import net.momirealms.customnameplates.ConfigManager; +import net.momirealms.customnameplates.CustomNameplates; +import org.bukkit.Bukkit; import java.util.HashMap; import java.util.Map; @@ -30,19 +32,24 @@ public class DataManager { if (!cache.containsKey(uuid)) { return; } - SqlHandler.save(cache.get(uuid), uuid); cache.remove(uuid); } public void savePlayer(UUID uuid) { - SqlHandler.save(cache.get(uuid), uuid); + if (ConfigManager.DatabaseConfig.async){ + Bukkit.getScheduler().runTaskAsynchronously(CustomNameplates.instance, () -> { + SqlHandler.save(cache.get(uuid), uuid); + }); + }else { + SqlHandler.save(cache.get(uuid), uuid); + } } public static boolean create() { if(ConfigManager.DatabaseConfig.use_mysql){ - AdventureManager.consoleMessage("[CustomNameplates] 存储模式 - MYSQL"); + AdventureManager.consoleMessage("[CustomNameplates] Storage Mode - MYSQL"); }else { - AdventureManager.consoleMessage("[CustomNameplates] 存储模式 - SQLite"); + AdventureManager.consoleMessage("[CustomNameplates] Storage Mode - SQLite"); } if (SqlHandler.connect()) { if (ConfigManager.DatabaseConfig.use_mysql) { diff --git a/src/main/java/net/momirealms/customnameplates/font/FontChar.java b/src/main/java/net/momirealms/customnameplates/font/FontChar.java index 584bfb6..2b93266 100644 --- a/src/main/java/net/momirealms/customnameplates/font/FontChar.java +++ b/src/main/java/net/momirealms/customnameplates/font/FontChar.java @@ -26,11 +26,6 @@ public record FontChar(char left, char middle, char right) { return this.getLeft() == fontInfo.getLeft() && this.getMiddle() == fontInfo.getMiddle() && this.getRight() == fontInfo.getRight(); } - /* - 如果对象的equals方法被重写,那么对象的HashCode方法也尽量重写 - 比如:有个A类重写了equals方法,但是没有重写hashCode方法,看输出结果,对象a1和对象a2使用equals方法相等, - 所以,我们在重写了equals方法后,尽量也重写了hashcode方法,通过一定的算法,使他们在equals相等时,也会有相同的hashcode值。 - */ @Override public int hashCode() { return ((59 + this.getLeft()) * 59 + this.getMiddle()) * 59 + this.getRight(); diff --git a/src/main/java/net/momirealms/customnameplates/helper/LibraryLoader.java b/src/main/java/net/momirealms/customnameplates/helper/LibraryLoader.java new file mode 100644 index 0000000..b8df644 --- /dev/null +++ b/src/main/java/net/momirealms/customnameplates/helper/LibraryLoader.java @@ -0,0 +1,201 @@ +/* + * 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.customnameplates.helper; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; + +import net.momirealms.customnameplates.CustomNameplates; +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) CustomNameplates.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 = CustomNameplates.instance.getDataFolder(); + File serverDir = pluginDataFolder.getParentFile().getParentFile(); + + File helperDir = new File(serverDir, "libraries"); + String[] split = StringUtils.split(dependency.getGroupId(), "."); + File jarDir; + if (split.length > 1){ + jarDir = new File(helperDir, split[0] + File.separator + split[1] + File.separator + dependency.artifactId + File.separator + dependency.version ); + }else { + jarDir = new File(helperDir, dependency.getGroupId() + 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/customnameplates/helper/Log.java b/src/main/java/net/momirealms/customnameplates/helper/Log.java new file mode 100644 index 0000000..f7338cf --- /dev/null +++ b/src/main/java/net/momirealms/customnameplates/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.customnameplates.helper; + +import net.momirealms.customnameplates.CustomNameplates; +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) { + CustomNameplates.instance.getLogger().info(s); + } + + public static void warn(@Nonnull String s) { + CustomNameplates.instance.getLogger().warning(s); + } + + public static void severe(@Nonnull String s) { + CustomNameplates.instance.getLogger().severe(s); + } + + public static void warn(@Nonnull String s, Throwable t) { + CustomNameplates.instance.getLogger().log(Level.WARNING, s, t); + } + + public static void severe(@Nonnull String s, Throwable t) { + CustomNameplates.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/customnameplates/helper/MavenLibraries.java b/src/main/java/net/momirealms/customnameplates/helper/MavenLibraries.java new file mode 100644 index 0000000..4654110 --- /dev/null +++ b/src/main/java/net/momirealms/customnameplates/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.customnameplates.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/customnameplates/helper/MavenLibrary.java b/src/main/java/net/momirealms/customnameplates/helper/MavenLibrary.java new file mode 100644 index 0000000..80e29ea --- /dev/null +++ b/src/main/java/net/momirealms/customnameplates/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.customnameplates.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/customnameplates/helper/NonnullByDefault.java b/src/main/java/net/momirealms/customnameplates/helper/NonnullByDefault.java new file mode 100644 index 0000000..a6475a3 --- /dev/null +++ b/src/main/java/net/momirealms/customnameplates/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.customnameplates.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/customnameplates/helper/Repository.java b/src/main/java/net/momirealms/customnameplates/helper/Repository.java new file mode 100644 index 0000000..444d7be --- /dev/null +++ b/src/main/java/net/momirealms/customnameplates/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.customnameplates.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/customnameplates/helper/URLClassLoaderAccess.java b/src/main/java/net/momirealms/customnameplates/helper/URLClassLoaderAccess.java new file mode 100644 index 0000000..1c617d4 --- /dev/null +++ b/src/main/java/net/momirealms/customnameplates/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.customnameplates.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/customnameplates/hook/HookManager.java b/src/main/java/net/momirealms/customnameplates/hook/HookManager.java index 8623fd9..31def5b 100644 --- a/src/main/java/net/momirealms/customnameplates/hook/HookManager.java +++ b/src/main/java/net/momirealms/customnameplates/hook/HookManager.java @@ -1,12 +1,8 @@ package net.momirealms.customnameplates.hook; -import me.clip.placeholderapi.PlaceholderAPI; import net.momirealms.customnameplates.AdventureManager; import net.momirealms.customnameplates.ConfigManager; import net.momirealms.customnameplates.CustomNameplates; -import org.apache.commons.lang.StringUtils; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; public class HookManager { @@ -33,7 +29,7 @@ public class HookManager { return; } if(CustomNameplates.instance.getServer().getPluginManager().getPlugin("PlaceholderAPI") != null){ - AdventureManager.consoleMessage("[CustomNameplates] 已启用 PlaceholderAPI 变量解析!"); + AdventureManager.consoleMessage("[CustomNameplates] PlaceholderAPI Hooked!"); this.placeholderAPI = true; } } @@ -46,12 +42,12 @@ public class HookManager { this.itemsAdder = true; } } - /* - 解析prefix与suffix - */ - public String parsePlaceholders(Player player, String papi) { - String s = StringUtils.replace(StringUtils.replace(papi, "%player_name%", player.getName()), "%player_displayname%", player.getDisplayName()); - s = PlaceholderAPI.setPlaceholders(player, s); - return ChatColor.translateAlternateColorCodes('&', s); - } +// /* +// 解析prefix与suffix +// */ +// public String parsePlaceholders(Player player, String papi) { +// String s = StringUtils.replace(StringUtils.replace(papi, "%player_name%", player.getName()), "%player_displayname%", player.getDisplayName()); +// s = PlaceholderAPI.setPlaceholders(player, s); +// return ChatColor.translateAlternateColorCodes('&', s); +// } } \ No newline at end of file diff --git a/src/main/java/net/momirealms/customnameplates/hook/ParsePapi.java b/src/main/java/net/momirealms/customnameplates/hook/ParsePapi.java new file mode 100644 index 0000000..5560092 --- /dev/null +++ b/src/main/java/net/momirealms/customnameplates/hook/ParsePapi.java @@ -0,0 +1,15 @@ +package net.momirealms.customnameplates.hook; + +import me.clip.placeholderapi.PlaceholderAPI; +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +public class ParsePapi { + + public static String parsePlaceholders(Player player, String papi) { + String s = StringUtils.replace(StringUtils.replace(papi, "%player_name%", player.getName()), "%player_displayname%", player.getDisplayName()); + s = PlaceholderAPI.setPlaceholders(player, s); + return ChatColor.translateAlternateColorCodes('&', s); + } +} diff --git a/src/main/java/net/momirealms/customnameplates/listener/PacketsListener.java b/src/main/java/net/momirealms/customnameplates/listener/PacketsListener.java index 8414f4e..2a20f7f 100644 --- a/src/main/java/net/momirealms/customnameplates/listener/PacketsListener.java +++ b/src/main/java/net/momirealms/customnameplates/listener/PacketsListener.java @@ -48,8 +48,12 @@ public class PacketsListener extends PacketAdapter { return; } //在新建队伍名字的时候其实就是以玩家名命名,所以获得的teamName=playerName - internalStructure.getChatComponents().write(1, WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(team.getPrefix()))); - internalStructure.getChatComponents().write(2, WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(team.getSuffix()))); + if (team.getPrefix() != null){ + internalStructure.getChatComponents().write(1, WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(team.getPrefix()))); + } + if (team.getSuffix() != null){ + internalStructure.getChatComponents().write(2, WrappedChatComponent.fromJson(GsonComponentSerializer.gson().serialize(team.getSuffix()))); + } internalStructure.getEnumModifier(ChatColor.class, MinecraftReflection.getMinecraftClass("EnumChatFormat")).write(0,team.getColor()); } } diff --git a/src/main/java/net/momirealms/customnameplates/listener/PlayerListener.java b/src/main/java/net/momirealms/customnameplates/listener/PlayerListener.java index d833ebb..ad279e1 100644 --- a/src/main/java/net/momirealms/customnameplates/listener/PlayerListener.java +++ b/src/main/java/net/momirealms/customnameplates/listener/PlayerListener.java @@ -1,5 +1,6 @@ package net.momirealms.customnameplates.listener; +import net.momirealms.customnameplates.ConfigManager; import net.momirealms.customnameplates.CustomNameplates; import net.momirealms.customnameplates.data.DataManager; import org.bukkit.Bukkit; diff --git a/src/main/java/net/momirealms/customnameplates/resource/ResourceManager.java b/src/main/java/net/momirealms/customnameplates/resource/ResourceManager.java index ebf0724..d7b7773 100644 --- a/src/main/java/net/momirealms/customnameplates/resource/ResourceManager.java +++ b/src/main/java/net/momirealms/customnameplates/resource/ResourceManager.java @@ -39,7 +39,7 @@ public class ResourceManager { File g_file = new File(CustomNameplates.instance.getDataFolder() + File.separator + "generated"); //如果资源文件夹不存在则创建 if (!r_file.exists()) { - AdventureManager.consoleMessage("[CustomNameplates] Failed to detect resources folder! Generating default resources..."); + AdventureManager.consoleMessage("[CustomNameplates] Failed to detect resources folder! Generating default resources..."); if (!r_file.mkdir()) { AdventureManager.consoleMessage("[CustomNameplates] Error! Failed to create resources folder..."); return; @@ -111,11 +111,11 @@ public class ResourceManager { return; } //资源包生成成功提示 - AdventureManager.consoleMessage("[CustomNameplates] 资源包已成功生成! 已载入 " + (this.caches.size() -1) + " 个铭牌!"); + AdventureManager.consoleMessage("[CustomNameplates] ResourcePack has been generated! " + (this.caches.size() -1) + " nameplates loaded!"); if (this.plugin.getHookManager().hasItemsAdder()){ try{ FileUtils.copyDirectory(g_file, new File(Bukkit.getPluginManager().getPlugin("ItemsAdder").getDataFolder() + File.separator + "data"+ File.separator + "resource_pack" + File.separator + "assets") ); - AdventureManager.consoleMessage("[CustomNameplates] 检测到 ItemsAdder 已自动转移生成的资源包!"); + AdventureManager.consoleMessage("[CustomNameplates] Detected ItemsAdder! Automatically sent rp to ItemsAdder folder!"); }catch (IOException e){ e.printStackTrace(); AdventureManager.consoleMessage("[CustomNameplates] Error! Failed to copy files to ItemsAdder..."); diff --git a/src/main/java/net/momirealms/customnameplates/scoreboard/NameplatesTeam.java b/src/main/java/net/momirealms/customnameplates/scoreboard/NameplatesTeam.java index 4adc202..4b1170f 100644 --- a/src/main/java/net/momirealms/customnameplates/scoreboard/NameplatesTeam.java +++ b/src/main/java/net/momirealms/customnameplates/scoreboard/NameplatesTeam.java @@ -3,11 +3,12 @@ package net.momirealms.customnameplates.scoreboard; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.momirealms.customnameplates.ConfigManager; import net.momirealms.customnameplates.CustomNameplates; import net.momirealms.customnameplates.data.DataManager; +import net.momirealms.customnameplates.data.PlayerData; import net.momirealms.customnameplates.font.FontCache; +import net.momirealms.customnameplates.hook.ParsePapi; import net.momirealms.customnameplates.nameplates.NameplateUtil; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -53,12 +54,22 @@ public class NameplatesTeam { } public void updateNameplates() { - //获取玩家的铭牌,没有数据则创建数据,没有铭牌则设置为空铭牌 - String nameplate = (this.plugin.getDataManager().getOrCreate(this.player.getUniqueId())).getEquippedNameplate(); + Optional playerData = Optional.ofNullable(this.plugin.getDataManager().getOrCreate(this.player.getUniqueId())); + String nameplate; + if (playerData.isPresent()){ + nameplate = playerData.get().getEquippedNameplate(); + }else { + nameplate = "none"; + } //如果是空铭牌直接飞机票送走 if (nameplate.equals("none")) { - this.prefix = Component.text(""); - this.suffix = Component.text(""); + if (plugin.getHookManager().hasPlaceholderAPI()) { + this.prefix = Component.text(ParsePapi.parsePlaceholders(this.player, ConfigManager.MainConfig.player_prefix)); + this.suffix = Component.text(ParsePapi.parsePlaceholders(this.player, ConfigManager.MainConfig.player_suffix)); + }else { + this.prefix = Component.text(ConfigManager.MainConfig.player_prefix); + this.suffix = Component.text(ConfigManager.MainConfig.player_suffix); + } this.color = ChatColor.WHITE; this.team.setPrefix(""); return; @@ -79,11 +90,27 @@ public class NameplatesTeam { String playerSuffix; //有Papi才解析 if (plugin.getHookManager().hasPlaceholderAPI()) { - playerPrefix = this.plugin.getHookManager().parsePlaceholders(this.player, ConfigManager.MainConfig.player_prefix); - playerSuffix = this.plugin.getHookManager().parsePlaceholders(this.player, ConfigManager.MainConfig.player_suffix); + if (!ConfigManager.MainConfig.hidePrefix){ + playerPrefix = ParsePapi.parsePlaceholders(this.player, ConfigManager.MainConfig.player_prefix); + }else { + playerPrefix = ""; + } + if (!ConfigManager.MainConfig.hideSuffix){ + playerSuffix = ParsePapi.parsePlaceholders(this.player, ConfigManager.MainConfig.player_suffix); + }else { + playerSuffix = ""; + } }else { - playerPrefix = ConfigManager.MainConfig.player_prefix; - playerSuffix = ConfigManager.MainConfig.player_suffix; + if (!ConfigManager.MainConfig.hidePrefix){ + playerPrefix = ConfigManager.MainConfig.player_prefix; + }else { + playerPrefix = ""; + } + if (!ConfigManager.MainConfig.hideSuffix){ + playerSuffix = ConfigManager.MainConfig.player_suffix; + }else { + playerSuffix = ""; + } } //最终prefix: 偏移 + 铭牌左 + 偏移 + 铭牌中 + 偏移 + 铭牌右 + 偏移 + 前缀 //最终suffix: 偏移 + 后缀 diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 876e062..507cbc3 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,7 +1,7 @@ config: # Language # en/cn - lang: cn + lang: en # Your namespace namespace: "nameplates" @@ -38,6 +38,10 @@ config: prefix: '' suffix: '' + # should prefix/suffix be hidden when player is equipping a nameplate + hide-prefix-when-equipped: false + hide-suffix-when-equipped: false + # Thin-font support use-thin-font: false diff --git a/src/main/resources/database.yml b/src/main/resources/database.yml index 2102040..1197e54 100644 --- a/src/main/resources/database.yml +++ b/src/main/resources/database.yml @@ -4,6 +4,7 @@ settings: # Restart is a must when you change database configuration. storage-mode: SQLite use-pool: false + disable-async: false # MySQL settings MySQL: diff --git a/src/main/resources/messages/messages_en.yml b/src/main/resources/messages/messages_en.yml index 98c37af..db78048 100644 --- a/src/main/resources/messages/messages_en.yml +++ b/src/main/resources/messages/messages_en.yml @@ -10,7 +10,7 @@ messages: preview: 'Now previewing your nameplate (go to third person to view)!' not-exist: 'This nameplate does not exist!' not-online: 'Player {Player} is not online!' - no-console: 'This command can be only sent by player!' + no-console: 'This command can be only executed by player!' not-available: 'This nameplate is currently not available!' available: 'Available nameplates: {Nameplates}.' cooldown: 'Previewing is still Ongoing!' \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 41e96e2..d94bbef 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,9 +5,9 @@ api-version: 1.16 authors: [ XiaoMoMi ] depend: - ProtocolLib - - PlaceholderAPI softdepend: - ItemsAdder + - PlaceholderAPI commands: customnameplates: usage: /customnameplates help