diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java index 3c95a1d9d..c6981358d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java @@ -29,6 +29,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; @@ -157,8 +158,6 @@ public class ItemEventListener implements Listener { } for (ItemBehavior itemBehavior : optionalItemBehaviors.get()) { - - InteractionResult result = itemBehavior.useOnBlock(new UseOnContext(player, hand, hitResult)); if (result == InteractionResult.SUCCESS_AND_CANCEL) { event.setCancelled(true); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index a6bd3107a..67591a0a3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -125,6 +125,8 @@ public class BukkitNetworkManager implements NetworkManager, Listener { registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY, Reflections.clazz$ClientboundMoveEntityPacket$Pos); registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, Reflections.clazz$ServerboundPickItemFromEntityPacket); registerNMSPacketConsumer(PacketConsumers.SOUND, Reflections.clazz$ClientboundSoundPacket); + registerNMSPacketConsumer(PacketConsumers.CHAT, Reflections.clazz$ServerboundChatPacket); + registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, Reflections.clazz$ServerboundRenameItemPacket); registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket()); registerByteBufPacketConsumer(PacketConsumers.LEVEL_PARTICLE, this.packetIds.clientboundLevelParticlesPacket()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index 821b5ce4d..9c4e1ad90 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -14,6 +14,7 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.*; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.font.ImageManager; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.ConfigManager; import net.momirealms.craftengine.core.plugin.network.ConnectionState; @@ -32,9 +33,7 @@ import org.bukkit.util.RayTraceResult; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.function.BiConsumer; public class PacketConsumers { @@ -661,4 +660,57 @@ public class PacketConsumers { CraftEngine.instance().logger().warn("Failed to handle ClientboundSoundPacket", e); } }; + + // we handle it on packet level to prevent it from being captured by plugins (most are chat plugins) + public static final TriConsumer CHAT = (user, event, packet) -> { + try { + String message = (String) Reflections.field$ServerboundChatPacket$message.get(packet); + if (message != null && !message.isEmpty()) { + ImageManager manager = CraftEngine.instance().imageManager(); + if (!manager.isDefaultFontInUse()) return; + char[] chars = message.toCharArray(); + try { + int[] codepoints = CharacterUtils.charsToCodePoints(chars); + for (int codepoint : codepoints) { + if (manager.isIllegalCharacter(codepoint)) { + event.setCancelled(true); + return; + } + } + } catch (Exception ignore) { + } + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ServerboundChatPacket", e); + } + }; + + // we handle it on packet level to prevent it from being captured by plugins + public static final TriConsumer RENAME_ITEM = (user, event, packet) -> { + try { + String message = (String) Reflections.field$ServerboundRenameItemPacket$name.get(packet); + if (message != null && !message.isEmpty()) { + ImageManager manager = CraftEngine.instance().imageManager(); + if (!manager.isDefaultFontInUse()) return; + char[] chars = message.toCharArray(); + try { + int[] codepoints = CharacterUtils.charsToCodePoints(chars); + int[] newCodepoints = new int[codepoints.length]; + for (int i = 0; i < codepoints.length; i++) { + int codepoint = codepoints[i]; + if (!manager.isIllegalCharacter(codepoint)) { + newCodepoints[i] = codepoint; + } else { + newCodepoints[i] = '*'; + } + } + String str = new String(newCodepoints, 0, newCodepoints.length); + Reflections.field$ServerboundRenameItemPacket$name.set(packet, str); + } catch (Exception ignore) { + } + } + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to handle ServerboundRenameItemPacket", e); + } + }; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index e8c696b66..662108a21 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -5114,4 +5114,30 @@ public class Reflections { clazz$HitResult, clazz$Vec3, 0 ) ); + + public static final Class clazz$ServerboundChatPacket = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatPacket"), + BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayInChat") + ) + ); + + public static final Field field$ServerboundChatPacket$message = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ServerboundChatPacket, String.class, 0 + ) + ); + + public static final Class clazz$ServerboundRenameItemPacket = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundRenameItemPacket"), + BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayInItemName") + ) + ); + + public static final Field field$ServerboundRenameItemPacket$name = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$ServerboundRenameItemPacket, String.class, 0 + ) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/Font.java b/core/src/main/java/net/momirealms/craftengine/core/font/Font.java index ffc3f6dd2..eb6ebc802 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/Font.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/Font.java @@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.font; import net.momirealms.craftengine.core.util.Key; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -19,6 +20,10 @@ public class Font { return this.idToCodepoint.containsKey(codepoint); } + public Collection codepointsInUse() { + return Collections.unmodifiableCollection(this.idToCodepoint.keySet()); + } + public BitmapImage getImageByCodepoint(int codepoint) { return this.idToCodepoint.get(codepoint); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/ImageManager.java b/core/src/main/java/net/momirealms/craftengine/core/font/ImageManager.java index c4916334c..ac114d578 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/ImageManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/ImageManager.java @@ -13,11 +13,18 @@ import java.util.function.BiFunction; public interface ImageManager extends Reloadable, ConfigSectionParser { String CONFIG_SECTION_NAME = "images"; + Key DEFAULT_FONT = Key.of("minecraft:default"); default String sectionId() { return CONFIG_SECTION_NAME; } + void delayedLoad(); + + boolean isDefaultFontInUse(); + + boolean isIllegalCharacter(int codepoint); + Collection fontsInUse(); Optional bitmapImageByCodepoint(Key font, int codepoint); diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/ImageManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/font/ImageManagerImpl.java index 4c4436362..ace8f47e0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/ImageManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/ImageManagerImpl.java @@ -18,6 +18,7 @@ public class ImageManagerImpl implements ImageManager { private final HashMap fonts = new HashMap<>(); // namespace:id image private final HashMap images = new HashMap<>(); + private final Set illegalChars = new HashSet<>(); private OffsetFont offsetFont; @@ -36,6 +37,24 @@ public class ImageManagerImpl implements ImageManager { public void unload() { this.fonts.clear(); this.images.clear(); + this.illegalChars.clear(); + } + + @Override + public void delayedLoad() { + Optional.ofNullable(this.fonts.get(DEFAULT_FONT)).ifPresent(font -> { + this.illegalChars.addAll(font.codepointsInUse()); + }); + } + + @Override + public boolean isDefaultFontInUse() { + return !this.illegalChars.isEmpty(); + } + + @Override + public boolean isIllegalCharacter(int codepoint) { + return this.illegalChars.contains(codepoint); } @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index 3e173c3e7..2deedf67f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -106,6 +106,7 @@ public abstract class CraftEngine implements Plugin { this.blockManager.delayedLoad(); this.itemBrowserManager.delayedLoad(); this.soundManager.delayedLoad(); + this.imageManager.delayedLoad(); if (ConfigManager.debug()) { this.debugger = (s) -> logger.info("[Debug] " + s.get()); } else {