mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-20 07:29:17 +00:00
feat(network): 实现阻止玩家在游戏内直接使用自定义默认字体
This commit is contained in:
@@ -127,6 +127,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener {
|
||||
registerNMSPacketConsumer(PacketConsumers.SOUND, Reflections.clazz$ClientboundSoundPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.CHAT, Reflections.clazz$ServerboundChatPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, Reflections.clazz$ServerboundRenameItemPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, Reflections.clazz$ServerboundSignUpdatePacket);
|
||||
registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.LEVEL_PARTICLE, this.packetIds.clientboundLevelParticlesPacket());
|
||||
@@ -267,6 +268,20 @@ public class BukkitNetworkManager implements NetworkManager, Listener {
|
||||
this.packetsConsumer.accept(player.serverPlayer(), packet);
|
||||
}
|
||||
|
||||
public void receivePacket(@NotNull NetWorkUser player, Object packet) {
|
||||
Channel channel = player.nettyChannel();
|
||||
List<String> handlerNames = channel.pipeline().names();
|
||||
if (handlerNames.contains("decompress")) {
|
||||
channel.pipeline().context("decompress").fireChannelRead(packet);
|
||||
} else {
|
||||
if (handlerNames.contains("decrypt")) {
|
||||
channel.pipeline().context("decrypt").fireChannelRead(packet);
|
||||
} else {
|
||||
channel.pipeline().context("splitter").fireChannelRead(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void injectServerChannel(Channel serverChannel) {
|
||||
ChannelPipeline pipeline = serverChannel.pipeline();
|
||||
ChannelHandler connectionHandler = pipeline.get(CONNECTION_HANDLER_NAME);
|
||||
|
||||
@@ -3,6 +3,8 @@ package net.momirealms.craftengine.bukkit.plugin.network;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent;
|
||||
import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent;
|
||||
@@ -33,9 +35,8 @@ 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.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class PacketConsumers {
|
||||
@@ -670,17 +671,19 @@ public class PacketConsumers {
|
||||
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) {
|
||||
}
|
||||
String str = replaceIllegalString(message, manager);
|
||||
if (message.equals(str)) return;
|
||||
event.setCancelled(true);
|
||||
Object newPacket = Reflections.constructor$ServerboundChatPacket.newInstance(
|
||||
str,
|
||||
Reflections.field$ServerboundChatPacket$timeStamp.get(packet),
|
||||
Reflections.field$ServerboundChatPacket$salt.get(packet),
|
||||
Reflections.field$ServerboundChatPacket$signature.get(packet),
|
||||
Reflections.field$ServerboundChatPacket$lastSeenMessages.get(packet)
|
||||
);
|
||||
user.receivePacket(newPacket);
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundChatPacket", e);
|
||||
@@ -694,25 +697,49 @@ public class PacketConsumers {
|
||||
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);
|
||||
String str = replaceIllegalString(message, manager);
|
||||
Reflections.field$ServerboundRenameItemPacket$name.set(packet, str);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundRenameItemPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
// we handle it on packet level to prevent it from being captured by plugins
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SIGN_UPDATE = (user, event, packet) -> {
|
||||
try {
|
||||
String[] lines = (String[]) Reflections.field$ServerboundSignUpdatePacket$lines.get(packet);
|
||||
ImageManager manager = CraftEngine.instance().imageManager();
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
if (line != null && !line.isEmpty()) {
|
||||
if (!manager.isDefaultFontInUse()) return;
|
||||
try {
|
||||
String str = replaceIllegalString(line, manager);
|
||||
if (line.equals(str)) continue;
|
||||
lines[i] = str;
|
||||
} catch (Exception ignore){}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundSignUpdatePacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
private static String replaceIllegalString(String string, ImageManager manager) {
|
||||
char[] chars = string.toCharArray();
|
||||
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] = '*';
|
||||
}
|
||||
}
|
||||
return new String(newCodepoints, 0, newCodepoints.length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +231,11 @@ public class BukkitServerPlayer extends Player {
|
||||
this.plugin.networkManager().sendPacket(this, packet, immediately);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receivePacket(Object packet) {
|
||||
this.plugin.networkManager().receivePacket(this, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionState decoderState() {
|
||||
return decoderState;
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Location;
|
||||
@@ -26,6 +27,7 @@ import sun.misc.Unsafe;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.lang.reflect.*;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -134,9 +136,9 @@ public class Reflections {
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ClientboundSystemChatPacket = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
clazz$ClientboundSystemChatPacket, clazz$Component, boolean.class
|
||||
)
|
||||
VersionHelper.isVersionNewerThan1_20_4()
|
||||
? ReflectionUtils.getConstructor(clazz$ClientboundSystemChatPacket, clazz$Component, boolean.class)
|
||||
: ReflectionUtils.getConstructor(clazz$ClientboundSystemChatPacket, Component.class, String.class, boolean.class)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundSystemChatPacket$overlay = requireNonNull(
|
||||
@@ -189,6 +191,11 @@ public class Reflections {
|
||||
clazz$ClientboundSystemChatPacket, clazz$Component, 0
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundSystemChatPacket$adventure$content =
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundSystemChatPacket, Component.class, 0
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundSystemChatPacket$text =
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundSystemChatPacket, String.class, 0
|
||||
@@ -5115,6 +5122,19 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$MessageSignature = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.chat.MessageSignature")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$LastSeenMessages$Update = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.chat.LastSeenMessages$Update"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.chat.LastSeenMessages$b")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundChatPacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatPacket"),
|
||||
@@ -5122,12 +5142,42 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ServerboundChatPacket = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
clazz$ServerboundChatPacket, String.class, Instant.class, long.class, clazz$MessageSignature, clazz$LastSeenMessages$Update
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$message = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, String.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$timeStamp = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, Instant.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$salt = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, long.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$signature = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, clazz$MessageSignature, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$lastSeenMessages = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, clazz$LastSeenMessages$Update, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundRenameItemPacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundRenameItemPacket"),
|
||||
@@ -5140,4 +5190,17 @@ public class Reflections {
|
||||
clazz$ServerboundRenameItemPacket, String.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundSignUpdatePacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundSignUpdatePacket"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayInUpdateSign")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundSignUpdatePacket$lines = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundSignUpdatePacket, String[].class, 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ public interface NetWorkUser {
|
||||
|
||||
void sendPacket(Object packet, boolean immediately);
|
||||
|
||||
void receivePacket(Object packet);
|
||||
|
||||
@ApiStatus.Internal
|
||||
ConnectionState decoderState();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user