From 63075ad1bbfc492d49a07ff05f1f554937371a6f Mon Sep 17 00:00:00 2001 From: XiaoMoMi <70987828+Xiao-MoMi@users.noreply.github.com> Date: Fri, 11 Oct 2024 02:53:43 +0800 Subject: [PATCH] 3.0.1 --- .../customnameplates/api/Platform.java | 11 ++ .../api/network/PacketSender.java | 4 - .../placeholder/PlaceholderManagerImpl.java | 8 + .../bukkit/BukkitNetworkManager.java | 44 ++--- .../bukkit/BukkitPlatform.java | 8 + .../requirement/builtin/BiomeRequirement.java | 10 +- .../builtin/NotBiomeRequirement.java | 10 +- .../bukkit/util/BiomeUtils.java | 38 +++++ .../bukkit/util/Reflections.java | 154 +++++++++++++++++- .../common/util/ReflectionUtils.java | 17 +- gradle.properties | 2 +- 11 files changed, 252 insertions(+), 54 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/BiomeUtils.java diff --git a/api/src/main/java/net/momirealms/customnameplates/api/Platform.java b/api/src/main/java/net/momirealms/customnameplates/api/Platform.java index 9bc976c..78c3bce 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/Platform.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/Platform.java @@ -222,4 +222,15 @@ public interface Platform { * @return the remove entity packet object */ Object removeEntityPacket(int... entityID); + + /** + * Gets the biome based on location + * + * @param world world + * @param x x + * @param y y + * @param z z + * @return the biome key + */ + String getBiome(String world, int x, int y, int z); } diff --git a/api/src/main/java/net/momirealms/customnameplates/api/network/PacketSender.java b/api/src/main/java/net/momirealms/customnameplates/api/network/PacketSender.java index 07eb217..6c81528 100644 --- a/api/src/main/java/net/momirealms/customnameplates/api/network/PacketSender.java +++ b/api/src/main/java/net/momirealms/customnameplates/api/network/PacketSender.java @@ -35,8 +35,6 @@ public interface PacketSender { */ void sendPacket(@NotNull CNPlayer player, Object packet); - void sendPacket(@NotNull CNPlayer player, Object packet, boolean immediately); - /** * Sends a list of packets to the specified player. * @@ -44,6 +42,4 @@ public interface PacketSender { * @param packet the list of packets to be sent */ void sendPacket(@NotNull CNPlayer player, List packet); - - void sendPacket(@NotNull CNPlayer player, List packet, boolean immediately); } diff --git a/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java b/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java index 13f4762..9faaeee 100644 --- a/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java +++ b/backend/src/main/java/net/momirealms/customnameplates/backend/placeholder/PlaceholderManagerImpl.java @@ -165,6 +165,14 @@ public class PlaceholderManagerImpl implements PlaceholderManager { this.registerPlayerPlaceholder("%player_x%", (player -> String.valueOf((int) Math.floor(player.position().x())))); this.registerPlayerPlaceholder("%player_y%", (player -> String.valueOf((int) Math.floor(player.position().y())))); this.registerPlayerPlaceholder("%player_z%", (player -> String.valueOf((int) Math.floor(player.position().z())))); + this.registerPlayerPlaceholder("%np_biome%", (player -> { + Vector3 vector3 = player.position(); + return plugin.getPlatform().getBiome(player.world(), (int) Math.floor(vector3.x()), (int) Math.floor(vector3.y()), (int) Math.floor(vector3.z())); + })); + this.registerRelationalPlaceholder("%rel_np_biome%", (p1,p2) -> { + Vector3 vector3 = p1.position(); + return plugin.getPlatform().getBiome(p1.world(), (int) Math.floor(vector3.x()), (int) Math.floor(vector3.y()), (int) Math.floor(vector3.z())); + }); this.registerPlayerPlaceholder("%player_world%", (CNPlayer::world)); this.registerPlayerPlaceholder("%player_remaining_air%", (player -> String.valueOf(player.remainingAir()))); for (int i = -256; i <= 256; i++) { diff --git a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitNetworkManager.java index 460076a..0878913 100644 --- a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitNetworkManager.java @@ -24,24 +24,24 @@ import net.momirealms.customnameplates.api.network.PacketEvent; import net.momirealms.customnameplates.api.network.PacketSender; import net.momirealms.customnameplates.api.network.PipelineInjector; import net.momirealms.customnameplates.bukkit.util.Reflections; -import net.momirealms.customnameplates.common.util.TriConsumer; import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.function.BiConsumer; public class BukkitNetworkManager implements PacketSender, PipelineInjector { - private final TriConsumer, Boolean> packetsConsumer; + private final BiConsumer> packetsConsumer; private final CustomNameplates plugin; public BukkitNetworkManager(CustomNameplates plugin) { this.plugin = plugin; - this.packetsConsumer = ((player, objects, immediate) -> { + this.packetsConsumer = ((player, objects) -> { try { Object bundle = Reflections.constructor$ClientboundBundlePacket.newInstance(objects); - sendPacket(player, bundle, immediate); + sendPacket(player, bundle); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -50,41 +50,19 @@ public class BukkitNetworkManager implements PacketSender, PipelineInjector { @Override public void sendPacket(@NotNull CNPlayer player, Object packet) { - sendPacket(player, packet, false); - } - - @Override - public void sendPacket(@NotNull CNPlayer player, final Object packet, final boolean immediately) { - if (!player.isOnline()) return; - if (immediately) { - try { - Reflections.method$SendPacketImmediately.invoke( - Reflections.field$NetworkManager.get(Reflections.field$PlayerConnection.get( - Reflections.method$CraftPlayer$getHandle.invoke(player.player()))), packet, null, true); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } else { - try { - Reflections.method$SendPacket.invoke( - Reflections.field$PlayerConnection.get( - Reflections.method$CraftPlayer$getHandle.invoke(player.player())), packet); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } + try { + Reflections.method$SendPacket.invoke( + Reflections.field$PlayerConnection.get( + Reflections.method$CraftPlayer$getHandle.invoke(player.player())), packet); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); } } @Override public void sendPacket(@NotNull CNPlayer player, final List packet) { if (!player.isOnline()) return; - sendPacket(player, packet, false); - } - - @Override - public void sendPacket(@NotNull CNPlayer player, final List packet, boolean immediately) { - if (!player.isOnline()) return; - packetsConsumer.accept(player, packet, immediately); + packetsConsumer.accept(player, packet); } @Override diff --git a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitPlatform.java b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitPlatform.java index e043cdc..873e1c2 100644 --- a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitPlatform.java +++ b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/BukkitPlatform.java @@ -33,10 +33,12 @@ import net.momirealms.customnameplates.api.placeholder.Placeholder; import net.momirealms.customnameplates.api.util.Alignment; import net.momirealms.customnameplates.api.util.Vector3; import net.momirealms.customnameplates.backend.feature.actionbar.ActionBarManagerImpl; +import net.momirealms.customnameplates.bukkit.util.BiomeUtils; import net.momirealms.customnameplates.bukkit.util.EntityData; import net.momirealms.customnameplates.bukkit.util.Reflections; import net.momirealms.customnameplates.common.util.TriConsumer; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -495,6 +497,12 @@ public class BukkitPlatform implements Platform { } } + @Override + public String getBiome(String world, int x, int y, int z) { + Location location = new Location(Bukkit.getWorld(world), x, y, z); + return BiomeUtils.getBiome(location); + } + @Override public Object vec3(double x, double y, double z) { try { diff --git a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/requirement/builtin/BiomeRequirement.java b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/requirement/builtin/BiomeRequirement.java index 6619984..ad909af 100644 --- a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/requirement/builtin/BiomeRequirement.java +++ b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/requirement/builtin/BiomeRequirement.java @@ -18,8 +18,11 @@ package net.momirealms.customnameplates.bukkit.requirement.builtin; import net.momirealms.customnameplates.api.CNPlayer; +import net.momirealms.customnameplates.api.util.Vector3; import net.momirealms.customnameplates.backend.requirement.AbstractRequirement; -import org.bukkit.entity.Player; +import net.momirealms.customnameplates.bukkit.util.BiomeUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; import java.util.HashSet; import java.util.List; @@ -37,8 +40,9 @@ public class BiomeRequirement extends AbstractRequirement { @Override public boolean isSatisfied(CNPlayer p1, CNPlayer p2) { - String currentBiome = ((Player) p1.player()).getLocation().getBlock().getBiome().toString(); - return biomes.contains(currentBiome); + Vector3 vector3 = p1.position(); + Location location = new Location(Bukkit.getWorld(p1.world()), vector3.x(), vector3.y(), vector3.z()); + return biomes.contains(BiomeUtils.getBiome(location)); } @Override diff --git a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/requirement/builtin/NotBiomeRequirement.java b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/requirement/builtin/NotBiomeRequirement.java index 545370b..b45033e 100644 --- a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/requirement/builtin/NotBiomeRequirement.java +++ b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/requirement/builtin/NotBiomeRequirement.java @@ -18,8 +18,11 @@ package net.momirealms.customnameplates.bukkit.requirement.builtin; import net.momirealms.customnameplates.api.CNPlayer; +import net.momirealms.customnameplates.api.util.Vector3; import net.momirealms.customnameplates.backend.requirement.AbstractRequirement; -import org.bukkit.entity.Player; +import net.momirealms.customnameplates.bukkit.util.BiomeUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; import java.util.HashSet; import java.util.List; @@ -37,8 +40,9 @@ public class NotBiomeRequirement extends AbstractRequirement { @Override public boolean isSatisfied(CNPlayer p1, CNPlayer p2) { - String currentBiome = ((Player) p1.player()).getLocation().getBlock().getBiome().toString(); - return !biomes.contains(currentBiome); + Vector3 vector3 = p1.position(); + Location location = new Location(Bukkit.getWorld(p1.world()), vector3.x(), vector3.y(), vector3.z()); + return !biomes.contains(BiomeUtils.getBiome(location)); } @Override diff --git a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/BiomeUtils.java b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/BiomeUtils.java new file mode 100644 index 0000000..e4b1696 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/BiomeUtils.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) <2024> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customnameplates.bukkit.util; + +import org.bukkit.Location; + +public class BiomeUtils { + + public static String getBiome(Location loc) { + try { + Object serverLevel = Reflections.field$CraftWorld$ServerLevel.get(loc.getWorld()); + Object holder$Biome = Reflections.method$ServerLevel$getNoiseBiome.invoke(serverLevel, loc.getBlockX() >> 2, loc.getBlockY() >> 2, loc.getBlockZ() >> 2); + Object biome = Reflections.method$Holder$value.invoke(holder$Biome); + Object resourceLocation = Reflections.method$Registry$getKey.invoke(Reflections.instance$BiomeRegistry, biome); + if (resourceLocation != null) { + return resourceLocation.toString(); + } + return "void"; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/Reflections.java index 41d0790..fa4058b 100644 --- a/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/customnameplates/bukkit/util/Reflections.java @@ -22,10 +22,11 @@ import net.momirealms.customnameplates.api.helper.VersionHelper; import net.momirealms.customnameplates.common.util.ReflectionUtils; import sun.misc.Unsafe; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.*; +import java.lang.reflect.*; +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.UUID; import static java.util.Objects.requireNonNull; @@ -377,11 +378,6 @@ public class Reflections { ReflectionUtils.getMethods(clazz$PlayerConnection, void.class, clazz$Packet).get(0) ); - public static final Method method$SendPacketImmediately = requireNonNull( - Optional.ofNullable(ReflectionUtils.getMethod(clazz$NetworkManager, void.class, clazz$Packet, clazz$PacketSendListener, boolean.class)) - .orElse(ReflectionUtils.getMethod(clazz$NetworkManager, void.class, clazz$Packet, clazz$PacketSendListener, Boolean.class)) - ); - public static final Field field$NetworkManager = requireNonNull( VersionHelper.isVersionNewerThan1_20_2() ? ReflectionUtils.getDeclaredField(clazz$PlayerConnection.getSuperclass(), clazz$NetworkManager, 0) : @@ -852,4 +848,144 @@ public class Reflections { clazz$GameType, new String[] { "getId", "a" } ) ); + + public static final Class clazz$Biome = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.level.biome.Biome"), + BukkitReflectionUtils.assembleMCClass("world.level.biome.BiomeBase") + ) + ); + + public static final Class clazz$CraftWorld = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleCBClass("CraftWorld") + ) + ); + + public static final Class clazz$ServerLevel = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("server.level.ServerLevel"), + BukkitReflectionUtils.assembleMCClass("server.level.WorldServer") + ) + ); + + public static final Field field$CraftWorld$ServerLevel = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$CraftWorld, clazz$ServerLevel, 0 + ) + ); + + public static final Method method$ServerLevel$getNoiseBiome = requireNonNull( + ReflectionUtils.getMethod( + clazz$ServerLevel, clazz$Holder, int.class, int.class, int.class + ) + ); + + public static final Class clazz$ResourceLocation = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("resources.ResourceLocation"), + BukkitReflectionUtils.assembleMCClass("resources.MinecraftKey") + ) + ); + + public static final Class clazz$ResourceKey = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("resources.ResourceKey") + ) + ); + + public static final Class clazz$MinecraftServer = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("server.MinecraftServer") + ) + ); + + public static final Method method$MinecraftServer$getServer = requireNonNull( + ReflectionUtils.getMethod(clazz$MinecraftServer, new String[] { "getServer" }) + ); + + public static final Class clazz$LayeredRegistryAccess = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("core.LayeredRegistryAccess") + ) + ); + + public static final Field field$MinecraftServer$registries = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$MinecraftServer, clazz$LayeredRegistryAccess, 0 + ) + ); + + public static final Class clazz$RegistryAccess$Frozen = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("core.RegistryAccess$Frozen"), + BukkitReflectionUtils.assembleMCClass("core.IRegistryCustom$Dimension") + ) + ); + + public static final Class clazz$RegistryAccess = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("core.RegistryAccess"), + BukkitReflectionUtils.assembleMCClass("core.IRegistryCustom") + ) + ); + + public static final Field field$LayeredRegistryAccess$composite = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$LayeredRegistryAccess, clazz$RegistryAccess$Frozen, 0 + ) + ); + + public static final Class clazz$Registry = requireNonNull( + requireNonNull(ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("core.WritableRegistry"), + BukkitReflectionUtils.assembleMCClass("core.IRegistryWritable") + )).getInterfaces()[0] + ); + + public static final Method method$RegistryAccess$registryOrThrow = requireNonNull( + ReflectionUtils.getMethod( + clazz$RegistryAccess, clazz$Registry, clazz$ResourceKey + ) + ); + + public static final Class clazz$Registries = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("core.registries.Registries") + ) + ); + + public static final Method method$Registry$getKey = requireNonNull( + ReflectionUtils.getMethod(clazz$Registry, clazz$ResourceLocation, Object.class) + ); + + public static final Object instance$BiomeRegistry; + + static { + Field[] fields = clazz$Registries.getDeclaredFields(); + try { + Object field$Registries$Biome = null; + for (Field field : fields) { + Type fieldType = field.getGenericType(); + if (fieldType instanceof ParameterizedType paramType) { + if (paramType.getRawType() == clazz$ResourceKey) { + Type[] actualTypeArguments = paramType.getActualTypeArguments(); + if (actualTypeArguments.length == 1 && actualTypeArguments[0] instanceof ParameterizedType registryType) { + if (registryType.getActualTypeArguments()[0] == clazz$Biome) { + field$Registries$Biome = field.get(null); + break; + } + } + } + } + } + requireNonNull(field$Registries$Biome); + Object server = method$MinecraftServer$getServer.invoke(null); + Object registries = field$MinecraftServer$registries.get(server); + Object compositeAccess = field$LayeredRegistryAccess$composite.get(registries); + instance$BiomeRegistry = method$RegistryAccess$registryOrThrow.invoke(compositeAccess, field$Registries$Biome); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } } diff --git a/common/src/main/java/net/momirealms/customnameplates/common/util/ReflectionUtils.java b/common/src/main/java/net/momirealms/customnameplates/common/util/ReflectionUtils.java index ef1b2e9..8d8a448 100644 --- a/common/src/main/java/net/momirealms/customnameplates/common/util/ReflectionUtils.java +++ b/common/src/main/java/net/momirealms/customnameplates/common/util/ReflectionUtils.java @@ -200,6 +200,20 @@ public class ReflectionUtils { return null; } + @Nullable + public static Method getMethod(final Class clazz, Class returnType, int index) { + int i = 0; + for (Method method : clazz.getMethods()) { + if (returnType.isAssignableFrom(method.getReturnType())) { + if (i == index) { + return setAccessible(method); + } + i++; + } + } + return null; + } + @Nullable public static Method getStaticMethod(final Class clazz, Class returnType, final Class... parameterTypes) { outer: @@ -216,7 +230,8 @@ public class ReflectionUtils { continue outer; } } - if (returnType.isAssignableFrom(method.getReturnType())) return method; + if (returnType.isAssignableFrom(method.getReturnType())) + return setAccessible(method); } return null; } diff --git a/gradle.properties b/gradle.properties index f17d2a8..6dc0005 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=3.0.0 +project_version=3.0.1 config_version=29 project_group=net.momirealms