mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
prevent illegal chars in anvil
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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<NetWorkUser, NMSPacketEvent, Object> 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<NetWorkUser, NMSPacketEvent, Object> 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<Integer> codepointsInUse() {
|
||||
return Collections.unmodifiableCollection(this.idToCodepoint.keySet());
|
||||
}
|
||||
|
||||
public BitmapImage getImageByCodepoint(int codepoint) {
|
||||
return this.idToCodepoint.get(codepoint);
|
||||
}
|
||||
|
||||
@@ -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<Font> fontsInUse();
|
||||
|
||||
Optional<BitmapImage> bitmapImageByCodepoint(Key font, int codepoint);
|
||||
|
||||
@@ -18,6 +18,7 @@ public class ImageManagerImpl implements ImageManager {
|
||||
private final HashMap<Key, Font> fonts = new HashMap<>();
|
||||
// namespace:id image
|
||||
private final HashMap<Key, BitmapImage> images = new HashMap<>();
|
||||
private final Set<Integer> 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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user