diff --git a/build.gradle.kts b/build.gradle.kts index 18ed652..0823cc1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,11 +1,11 @@ plugins { id("java") - id("io.github.goooler.shadow") version "8.1.7" + id("com.gradleup.shadow") version "8.3.2" id("xyz.jpenilla.run-paper") version "2.3.0" } group = "xyz.ineanto" -version = "1.1.8" +version = "1.2.0" java { sourceCompatibility = JavaVersion.VERSION_21 @@ -38,14 +38,13 @@ repositories { } dependencies { - // Nicko - compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT") - compileOnly("com.github.dmulloy2:ProtocolLib:master-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT") + compileOnly("com.github.dmulloy2:ProtocolLib:-SNAPSHOT") compileOnly("me.clip:placeholderapi:2.11.5") compileOnly("net.kyori:adventure-api:4.17.0") - implementation("xyz.xenondevs.invui:invui:1.35") - implementation("net.wesjd:anvilgui:1.10.1-SNAPSHOT") + implementation("xyz.xenondevs.invui:invui:1.36") + implementation("net.wesjd:anvilgui:1.10.2-SNAPSHOT") implementation("com.github.jsixface:yamlconfig:1.2") implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2") implementation("com.fasterxml.jackson.core:jackson-core:2.15.2") @@ -115,14 +114,6 @@ tasks { } } - jar { - enabled = false - } - - test { - useJUnitPlatform() - } - runServer { dependsOn(shadowJar) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f31fb9b..1edb788 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Dec 11 00:36:17 CET 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/xyz/ineanto/nicko/Nicko.java b/src/main/java/xyz/ineanto/nicko/Nicko.java index a0621bb..40c6fb5 100644 --- a/src/main/java/xyz/ineanto/nicko/Nicko.java +++ b/src/main/java/xyz/ineanto/nicko/Nicko.java @@ -1,5 +1,6 @@ package xyz.ineanto.nicko; +import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.utility.MinecraftVersion; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; @@ -10,6 +11,7 @@ import xyz.ineanto.nicko.appearance.random.RandomNameFetcher; import xyz.ineanto.nicko.command.NickoCommand; import xyz.ineanto.nicko.config.Configuration; import xyz.ineanto.nicko.config.ConfigurationManager; +import xyz.ineanto.nicko.debug.RespawnPacketListener; import xyz.ineanto.nicko.event.PlayerJoinListener; import xyz.ineanto.nicko.event.PlayerQuitListener; import xyz.ineanto.nicko.language.CustomLanguage; @@ -132,6 +134,8 @@ public class Nicko extends JavaPlugin { getServer().getPluginManager().registerEvents(new PlayerJoinListener(), this); getServer().getPluginManager().registerEvents(new PlayerQuitListener(), this); metrics = new Metrics(this, 20483); + + ProtocolLibrary.getProtocolManager().addPacketListener(new RespawnPacketListener()); } getLogger().info("Nicko has been enabled."); diff --git a/src/main/java/xyz/ineanto/nicko/appearance/AppearanceManager.java b/src/main/java/xyz/ineanto/nicko/appearance/AppearanceManager.java index eaa1dc9..effd2f0 100644 --- a/src/main/java/xyz/ineanto/nicko/appearance/AppearanceManager.java +++ b/src/main/java/xyz/ineanto/nicko/appearance/AppearanceManager.java @@ -1,6 +1,5 @@ package xyz.ineanto.nicko.appearance; -import com.comphenix.protocol.utility.MinecraftVersion; import com.comphenix.protocol.wrappers.*; import com.google.common.collect.Multimap; import it.unimi.dsi.fastutil.ints.IntList; @@ -160,27 +159,19 @@ public class AppearanceManager { player.setFoodLevel(foodLevel); } - @SuppressWarnings("deprecation") private void updateTabList(WrappedGameProfile gameProfile, String displayName) { final WrapperPlayerServerPlayerInfo add = new WrapperPlayerServerPlayerInfo(); - if (MinecraftVersion.FEATURE_PREVIEW_UPDATE.atOrAbove()) { - final WrapperPlayerServerPlayerInfoRemove remove = new WrapperPlayerServerPlayerInfoRemove(); - final EnumSet actions = EnumSet.of( - EnumWrappers.PlayerInfoAction.ADD_PLAYER, - EnumWrappers.PlayerInfoAction.INITIALIZE_CHAT, - EnumWrappers.PlayerInfoAction.UPDATE_LISTED, - EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME, - EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE, - EnumWrappers.PlayerInfoAction.UPDATE_LATENCY); - remove.setUUIDs(List.of(player.getUniqueId())); - remove.broadcastPacket(); - add.setActions(actions); - } else { - final WrapperPlayerServerPlayerInfo remove = new WrapperPlayerServerPlayerInfo(); - remove.setActions(EnumSet.of(EnumWrappers.PlayerInfoAction.REMOVE_PLAYER)); - add.setActions(EnumSet.of(EnumWrappers.PlayerInfoAction.ADD_PLAYER)); - remove.broadcastPacket(); - } + final WrapperPlayerServerPlayerInfoRemove remove = new WrapperPlayerServerPlayerInfoRemove(); + final EnumSet actions = EnumSet.of( + EnumWrappers.PlayerInfoAction.ADD_PLAYER, + EnumWrappers.PlayerInfoAction.INITIALIZE_CHAT, + EnumWrappers.PlayerInfoAction.UPDATE_LISTED, + EnumWrappers.PlayerInfoAction.UPDATE_DISPLAY_NAME, + EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE, + EnumWrappers.PlayerInfoAction.UPDATE_LATENCY); + remove.setUUIDs(List.of(player.getUniqueId())); + remove.broadcastPacket(); + add.setActions(actions); add.setData(List.of(new PlayerInfoData( player.getUniqueId(), diff --git a/src/main/java/xyz/ineanto/nicko/config/Configuration.java b/src/main/java/xyz/ineanto/nicko/config/Configuration.java index b706f2f..d112559 100644 --- a/src/main/java/xyz/ineanto/nicko/config/Configuration.java +++ b/src/main/java/xyz/ineanto/nicko/config/Configuration.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import xyz.ineanto.nicko.version.Version; public class Configuration { - public static final Version VERSION = new Version(1, 0, 9); + public static final Version VERSION = new Version(1, 2, 0); public static final Configuration DEFAULT = new Configuration(VERSION.toString(), DefaultDataSources.SQL_EMPTY, DefaultDataSources.REDIS_EMPTY, diff --git a/src/main/java/xyz/ineanto/nicko/debug/RespawnPacketListener.java b/src/main/java/xyz/ineanto/nicko/debug/RespawnPacketListener.java new file mode 100644 index 0000000..fa37b6b --- /dev/null +++ b/src/main/java/xyz/ineanto/nicko/debug/RespawnPacketListener.java @@ -0,0 +1,86 @@ +package xyz.ineanto.nicko.debug; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.ListeningWhitelist; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.events.PacketListener; +import com.comphenix.protocol.utility.MinecraftReflection; +import com.comphenix.protocol.wrappers.MinecraftKey; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.plugin.Plugin; +import xyz.ineanto.nicko.Nicko; + +import java.util.Arrays; +import java.util.Optional; + +public class RespawnPacketListener implements PacketListener { + @Override + public void onPacketSending(PacketEvent event) { + try { + final Optional world = getWorld(event); + if (world.isEmpty()) { + Bukkit.broadcast(Component.text("did not find the world the player was in")); + return; + } + + Bukkit.broadcast(Component.text("found " + world.get().getName() + "!")); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + @Override + public void onPacketReceiving(PacketEvent event) { + + } + + @Override + public ListeningWhitelist getSendingWhitelist() { + return ListeningWhitelist.newBuilder().types(PacketType.Play.Server.RESPAWN).build(); + } + + @Override + public ListeningWhitelist getReceivingWhitelist() { + return ListeningWhitelist.EMPTY_WHITELIST; + } + + @Override + public Plugin getPlugin() { + return Nicko.getInstance(); + } + + private boolean keysEquals(MinecraftKey wrappedKey, NamespacedKey bukkitKey) { + // compare bukkit minecraft key and NMS wrapped minecraft key + return wrappedKey.getPrefix().equals(bukkitKey.getNamespace()) && wrappedKey.getKey().equals(bukkitKey.getKey()); + } + + public Optional getWorld(PacketEvent event) throws Throwable { + final Class commonPlayerInfoClazz = MinecraftReflection.getMinecraftClass("network.protocol.game.CommonPlayerSpawnInfo"); + // access CommonPlayerSpawnInfo, first field of that type in the Respawn / Login packets + final Object packetHandle = event.getPacket().getHandle(); + final Object commonSpawnData = packetHandle.getClass().getRecordComponents()[0].getAccessor().invoke(packetHandle); + + Arrays.stream(commonSpawnData.getClass().getRecordComponents()).forEach(component -> { + component.getAccessor().setAccessible(true); + System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=-"); + System.out.println(component.getName()); + System.out.println(component.getType().getSimpleName()); + System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=-"); + component.getAccessor().setAccessible(false); + } + ); + + // get the key of the level the player is joining. Second field in the object. First of type ResourceKey + /**MinecraftKey key = MinecraftKey.fromHandle(Accessors.getFieldAccessor(commonSpawnData.getClass(), MinecraftReflection.getResourceKey(), true) + .get(commonSpawnData)); // wrap to ProtocolLib handle + for (World world : Bukkit.getWorlds()) { + if (keysEquals(key, world.getKey())) { + return Optional.of(world); + } + }*/ + return Optional.empty(); + } +} diff --git a/src/main/java/xyz/ineanto/nicko/gui/items/admin/ManageCacheItem.java b/src/main/java/xyz/ineanto/nicko/gui/items/admin/ManageCacheItem.java index ac9d4a4..a14baa5 100644 --- a/src/main/java/xyz/ineanto/nicko/gui/items/admin/ManageCacheItem.java +++ b/src/main/java/xyz/ineanto/nicko/gui/items/admin/ManageCacheItem.java @@ -5,18 +5,12 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.jetbrains.annotations.NotNull; -import xyz.ineanto.nicko.Nicko; import xyz.ineanto.nicko.gui.CacheManagementGUI; -import xyz.ineanto.nicko.gui.items.ItemDefaults; -import xyz.ineanto.nicko.language.PlayerLanguage; import xyz.ineanto.nicko.language.LanguageKey; +import xyz.ineanto.nicko.language.PlayerLanguage; import xyz.xenondevs.invui.item.builder.ItemBuilder; -import xyz.xenondevs.invui.item.builder.SkullBuilder; import xyz.xenondevs.invui.item.impl.AsyncItem; import xyz.xenondevs.invui.item.impl.SuppliedItem; -import xyz.xenondevs.invui.util.MojangApiUtils; - -import java.io.IOException; public class ManageCacheItem extends AsyncItem { public ManageCacheItem(PlayerLanguage playerLanguage) { @@ -25,13 +19,8 @@ public class ManageCacheItem extends AsyncItem { return playerLanguage.translateItem(builder, LanguageKey.GUI.LOADING); }, (click -> true)).getItemProvider(), () -> { - try { - final SkullBuilder builder = new SkullBuilder("Notch"); - return playerLanguage.translateItem(builder, LanguageKey.GUI.Admin.MANAGE_CACHE); - } catch (MojangApiUtils.MojangApiException | IOException e) { - Nicko.getInstance().getLogger().warning("Unable to get Head texture for Notch! (GUI/ManageCache)"); - return ItemDefaults.getErrorSkullItem(playerLanguage, LanguageKey.GUI.Admin.MANAGE_CACHE); - } + final ItemBuilder builder = new ItemBuilder(Material.PLAYER_HEAD); + return playerLanguage.translateItem(builder, LanguageKey.GUI.Admin.MANAGE_CACHE); }); } diff --git a/src/main/java/xyz/ineanto/nicko/gui/items/appearance/ChangeBothItem.java b/src/main/java/xyz/ineanto/nicko/gui/items/appearance/ChangeBothItem.java index 2e19cf2..a076ab1 100644 --- a/src/main/java/xyz/ineanto/nicko/gui/items/appearance/ChangeBothItem.java +++ b/src/main/java/xyz/ineanto/nicko/gui/items/appearance/ChangeBothItem.java @@ -18,7 +18,7 @@ public class ChangeBothItem { public SuppliedItem get() { return new SuppliedItem(() -> { - final ItemBuilder builder = new ItemBuilder(Material.TOTEM_OF_UNDYING); + final ItemBuilder builder = new ItemBuilder(Material.ARMOR_STAND); return playerLanguage.translateItem(builder, LanguageKey.GUI.Home.CHANGE_BOTH); }, click -> { final ClickType clickType = click.getClickType(); diff --git a/src/main/java/xyz/ineanto/nicko/gui/items/appearance/ChangeSkinItem.java b/src/main/java/xyz/ineanto/nicko/gui/items/appearance/ChangeSkinItem.java index 6c78cc8..24927b3 100644 --- a/src/main/java/xyz/ineanto/nicko/gui/items/appearance/ChangeSkinItem.java +++ b/src/main/java/xyz/ineanto/nicko/gui/items/appearance/ChangeSkinItem.java @@ -1,36 +1,25 @@ package xyz.ineanto.nicko.gui.items.appearance; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; -import xyz.ineanto.nicko.Nicko; import xyz.ineanto.nicko.anvil.AnvilManager; -import xyz.ineanto.nicko.gui.items.ItemDefaults; -import xyz.ineanto.nicko.language.PlayerLanguage; import xyz.ineanto.nicko.language.LanguageKey; -import xyz.xenondevs.invui.item.builder.SkullBuilder; +import xyz.ineanto.nicko.language.PlayerLanguage; +import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.impl.SuppliedItem; -import xyz.xenondevs.invui.util.MojangApiUtils; - -import java.io.IOException; public class ChangeSkinItem { private final PlayerLanguage playerLanguage; - private final Player player; public ChangeSkinItem(Player player) { this.playerLanguage = new PlayerLanguage(player); - this.player = player; } public SuppliedItem get() { return new SuppliedItem(() -> { - try { - final SkullBuilder builder = new SkullBuilder(player.getName()); - return playerLanguage.translateItem(builder, LanguageKey.GUI.Home.CHANGE_SKIN); - } catch (MojangApiUtils.MojangApiException | IOException e) { - Nicko.getInstance().getLogger().warning("Unable to get Head texture for specified player (" + player.getName() + ")! (GUI/Home)"); - return ItemDefaults.getErrorSkullItem(playerLanguage, LanguageKey.GUI.Home.CHANGE_SKIN); - } + final ItemBuilder builder = new ItemBuilder(Material.PLAYER_HEAD); + return playerLanguage.translateItem(builder, LanguageKey.GUI.Home.CHANGE_SKIN); }, click -> { final ClickType clickType = click.getClickType(); if (clickType.isLeftClick() || clickType.isRightClick()) { diff --git a/src/main/java/xyz/ineanto/nicko/gui/items/home/AdminAccessItem.java b/src/main/java/xyz/ineanto/nicko/gui/items/home/AdminAccessItem.java index 478431d..107db6f 100644 --- a/src/main/java/xyz/ineanto/nicko/gui/items/home/AdminAccessItem.java +++ b/src/main/java/xyz/ineanto/nicko/gui/items/home/AdminAccessItem.java @@ -18,7 +18,7 @@ public class AdminAccessItem { public SuppliedItem get() { return new SuppliedItem(() -> { - final ItemBuilder builder = new ItemBuilder(Material.COMMAND_BLOCK_MINECART); + final ItemBuilder builder = new ItemBuilder(Material.SCAFFOLDING); return playerLanguage.translateItem(builder, LanguageKey.GUI.Home.ADMIN); }, click -> { final ClickType clickType = click.getClickType(); diff --git a/src/main/java/xyz/ineanto/nicko/gui/items/home/RandomSkinItem.java b/src/main/java/xyz/ineanto/nicko/gui/items/home/RandomSkinItem.java index 9ddd6af..0306017 100644 --- a/src/main/java/xyz/ineanto/nicko/gui/items/home/RandomSkinItem.java +++ b/src/main/java/xyz/ineanto/nicko/gui/items/home/RandomSkinItem.java @@ -1,14 +1,15 @@ package xyz.ineanto.nicko.gui.items.home; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import xyz.ineanto.nicko.Nicko; import xyz.ineanto.nicko.appearance.ActionResult; import xyz.ineanto.nicko.appearance.AppearanceManager; -import xyz.ineanto.nicko.language.PlayerLanguage; import xyz.ineanto.nicko.language.LanguageKey; +import xyz.ineanto.nicko.language.PlayerLanguage; import xyz.ineanto.nicko.profile.NickoProfile; -import xyz.xenondevs.invui.item.builder.SkullBuilder; +import xyz.xenondevs.invui.item.builder.ItemBuilder; import xyz.xenondevs.invui.item.impl.SuppliedItem; import java.util.Optional; @@ -24,8 +25,7 @@ public class RandomSkinItem { public SuppliedItem get() { return new SuppliedItem(() -> { - final SkullBuilder.HeadTexture texture = new SkullBuilder.HeadTexture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzgzMTEzOGMyMDYxMWQzMDJjNDIzZmEzMjM3MWE3NDNkMTc0MzdhMTg5NzNjMzUxOTczNDQ3MGE3YWJiNCJ9fX0="); - final SkullBuilder builder = new SkullBuilder(texture); + final ItemBuilder builder = new ItemBuilder(Material.SPAWNER); return playerLanguage.translateItem(builder, LanguageKey.GUI.Home.RANDOM_SKIN); }, (event) -> { final Player player = event.getPlayer(); diff --git a/src/main/java/xyz/ineanto/nicko/language/Language.java b/src/main/java/xyz/ineanto/nicko/language/Language.java index a13b78d..049039c 100644 --- a/src/main/java/xyz/ineanto/nicko/language/Language.java +++ b/src/main/java/xyz/ineanto/nicko/language/Language.java @@ -9,7 +9,7 @@ public enum Language implements Serializable { FRENCH("fr", "Français"), CUSTOM("cm", "Server Custom"); - public static final Version VERSION = new Version(1, 1, 4); + public static final Version VERSION = new Version(1, 2, 0); private final String code; private transient final String name; diff --git a/src/main/java/xyz/ineanto/nicko/wrapper/WrapperPlayServerRespawn.java b/src/main/java/xyz/ineanto/nicko/wrapper/WrapperPlayServerRespawn.java index 6fd7b95..707258c 100644 --- a/src/main/java/xyz/ineanto/nicko/wrapper/WrapperPlayServerRespawn.java +++ b/src/main/java/xyz/ineanto/nicko/wrapper/WrapperPlayServerRespawn.java @@ -13,6 +13,8 @@ import com.google.common.hash.Hashing; import org.bukkit.GameMode; import org.bukkit.World; +import java.lang.reflect.Field; + /** * PacketPlayServerRespawn Wrapper class (1.20.X to 1.21.X) *

@@ -53,11 +55,11 @@ public class WrapperPlayServerRespawn extends AbstractPacket { } else { // 1.20.5 to 1.21.1 - // why is life so hard? final Class commonPlayerInfoClazz = MinecraftReflection.getMinecraftClass("network.protocol.game.CommonPlayerSpawnInfo"); try { - final Object commonSpawnData = Accessors.getFieldAccessor(TYPE.getPacketClass(), commonPlayerInfoClazz, true).getField() - .get(this); + final Field commonSpawnDataField = Accessors.getFieldAccessor(TYPE.getPacketClass(), commonPlayerInfoClazz, true).getField(); + commonSpawnDataField.setAccessible(true); + final MinecraftKey key = MinecraftKey.fromHandle( Accessors.getFieldAccessor( commonPlayerInfoClazz, @@ -71,7 +73,7 @@ public class WrapperPlayServerRespawn extends AbstractPacket { MinecraftReflection.getResourceKey(), true ) - .set(commonSpawnData, key); + .set(commonSpawnDataField.get(this), key); } catch (IllegalAccessException e) { throw new RuntimeException(e); } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 5f56371..0ed717d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,11 +1,7 @@ # Nicko ${version} - Config: # Specifies the configuration version, don't change. -version: "1.0.9" - -# -# Language -# +version: "1.2.0" # Nicko will copy the English locale as "lang.yml" # and will use the translations in that file when "Server Custom" @@ -13,10 +9,6 @@ version: "1.0.9" # Accepted values: false (Disabled), true (Enabled) customLocale: false -# -# Storage -# - sql: # Indicates wherever the data will be stored locally # inside a .json file or in an SQL database. @@ -39,8 +31,6 @@ sql: # Accepted values: any string password: "password" -# This configuration section manages Redis (enabled BungeeCord support). -# It is used to transfer data between multiple servers. redis: # Indicates wherever the data will be stored through # Redis to transfer whenever a player switches server. diff --git a/src/main/resources/en.yml b/src/main/resources/en.yml index 91704f4..14248b6 100644 --- a/src/main/resources/en.yml +++ b/src/main/resources/en.yml @@ -1,7 +1,7 @@ # Nicko ${version} - Language File: # Specifies the configuration version, don't change. -version: "1.1.4" +version: "1.2.0" prefix: "NICKO" whoosh: "WHOOSH!" diff --git a/src/main/resources/fr.yml b/src/main/resources/fr.yml index 9f9419f..a17c532 100644 --- a/src/main/resources/fr.yml +++ b/src/main/resources/fr.yml @@ -1,7 +1,7 @@ # Nicko ${version} - Fichier de langue: # Précise la version de la configuration, ne pas changer. -version: "1.1.4" +version: "1.2.0" prefix: "NICKO" whoosh: "WHOOSH!"