9
0
mirror of https://github.com/Xiao-MoMi/Custom-Nameplates.git synced 2026-01-04 15:31:47 +00:00
This commit is contained in:
XiaoMoMi
2024-10-11 02:53:43 +08:00
parent 2c9bdc662a
commit 63075ad1bb
11 changed files with 252 additions and 54 deletions

View File

@@ -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);
}

View File

@@ -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<Object> packet);
void sendPacket(@NotNull CNPlayer player, List<Object> packet, boolean immediately);
}

View File

@@ -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++) {

View File

@@ -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<CNPlayer, List<Object>, Boolean> packetsConsumer;
private final BiConsumer<CNPlayer, List<Object>> 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<Object> packet) {
if (!player.isOnline()) return;
sendPacket(player, packet, false);
}
@Override
public void sendPacket(@NotNull CNPlayer player, final List<Object> packet, boolean immediately) {
if (!player.isOnline()) return;
packetsConsumer.accept(player, packet, immediately);
packetsConsumer.accept(player, packet);
}
@Override

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) <2024> <XiaoMoMi>
*
* 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 <https://www.gnu.org/licenses/>.
*/
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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}

View File

@@ -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