From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: AlphaKR93 Date: Mon, 29 Apr 2024 14:49:37 +0900 Subject: [PATCH] Implement FreedomChat ocelotpotpie/FreedomChat Copyright (C) 2022-2024 ocelotpotpie, Licensed under GNU GPL v3.0 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 (at your option) 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 . diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java index 14d15dd0d4973957871f5c06042fcaa4ea8b7a8a..2a45bebb2b83efd4ffcecad6c0a979198ab985c7 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -134,6 +134,7 @@ public abstract class PlayerList { private static final int SEND_PLAYER_INFO_INTERVAL = 600; private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); private static final org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[] EMPTY_FLAG = new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]; // Plazma - Reduce allocations + private static final ru.bk.oharass.freedomchat.FreedomChat FREEDOM_HANDLER = new ru.bk.oharass.freedomchat.FreedomChat(); // Plazma - Implement FreedomChat private final MinecraftServer server; public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety private final Map playersByUUID = Maps.newHashMap(); @@ -287,6 +288,8 @@ public abstract class PlayerList { // PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[]{entityplayer.getName().getString(), s1, entityplayer.getId(), entityplayer.getX(), entityplayer.getY(), entityplayer.getZ()}); LevelData worlddata = worldserver1.getLevelData(); + connection.channel.pipeline().addAfter("packet_handler", "freedom_handler", FREEDOM_HANDLER); // Plazma - Implement FreedomChat + player.loadGameTypes(nbttagcompound); ServerGamePacketListenerImpl playerconnection = new ServerGamePacketListenerImpl(this.server, connection, player, clientData); GameRules gamerules = worldserver1.getGameRules(); diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhase.java index 48826eb0a960f7af6dd2ef184a8aed744a1d8f83..c6df4262d660a1043705c3a4041f959490fae79e 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhase.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/EnderDragonPhase.java @@ -5,7 +5,7 @@ import java.util.Arrays; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; public class EnderDragonPhase { - private static EnderDragonPhase[] phases = new EnderDragonPhase[0]; + private static EnderDragonPhase[] phases = new EnderDragonPhase[0]; // Plazma - Reduce allocations (mark) public static final EnderDragonPhase HOLDING_PATTERN = create(DragonHoldingPatternPhase.class, "HoldingPattern"); public static final EnderDragonPhase STRAFE_PLAYER = create(DragonStrafePlayerPhase.class, "StrafePlayer"); public static final EnderDragonPhase LANDING_APPROACH = create(DragonLandingApproachPhase.class, "LandingApproach"); diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapedRecipePattern.java b/src/main/java/net/minecraft/world/item/crafting/ShapedRecipePattern.java index d8fe760bb74c8ea0d6fb8321d2c8a49d838c5362..6e910d74bac39735020d553cf31eb65b750163e0 100644 --- a/src/main/java/net/minecraft/world/item/crafting/ShapedRecipePattern.java +++ b/src/main/java/net/minecraft/world/item/crafting/ShapedRecipePattern.java @@ -85,7 +85,7 @@ public record ShapedRecipePattern(int width, int height, NonNullList } if (pattern.size() == l) { - return new String[0]; + return org.plazmamc.plazma.constants.Empty.STRING; // Plazma - Reduce allocations } else { String[] strings = new String[pattern.size() - l - k]; diff --git a/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java b/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java index 4f3ed01e12ccb8a6f1a5c4f605451bb36370a236..98f26e3de66a881163e84295e9156c7f362bf7cb 100644 --- a/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java +++ b/src/main/java/org/plazmamc/plazma/configurations/GlobalConfiguration.java @@ -29,6 +29,16 @@ public class GlobalConfiguration extends ConfigurationPart { public boolean checkSpectatorMovedToQuickly = !OPTIMIZE; + public FreedomChat freedomChat; + public class FreedomChat extends ConfigurationPart { + + public boolean enabled = false; + public boolean rewriteChat = true; + public boolean claimSecureChatEnforced = true; + public boolean noChatReports = true; + + } + } @Setting("world-generation") diff --git a/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java b/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java new file mode 100644 index 0000000000000000000000000000000000000000..67f21c23e80881f52e7b92f22c6cbbe3a0bd55b5 --- /dev/null +++ b/src/main/java/ru/bk/oharass/freedomchat/FreedomChat.java @@ -0,0 +1,96 @@ +package ru.bk.oharass.freedomchat; + +import com.google.gson.JsonObject; +import com.mojang.logging.LogUtils; +import com.mojang.serialization.JsonOps; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.EncoderException; +import io.netty.handler.codec.MessageToByteEncoder; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.minecraft.network.Connection; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.ChatType; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundPlayerChatPacket; +import net.minecraft.network.protocol.game.ClientboundServerDataPacket; +import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; +import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; +import net.minecraft.network.protocol.status.ServerStatus; +import org.slf4j.Logger; + +import java.util.Optional; + +import static org.plazmamc.plazma.configurations.GlobalConfiguration.get; +import static net.minecraft.server.MinecraftServer.getServer; + +@ChannelHandler.Sharable +public class FreedomChat extends MessageToByteEncoder> { + + private static final Logger LOGGER = LogUtils.getLogger(); + + @Override + public boolean acceptOutboundMessage(final Object msg) { + return get().player.freedomChat.rewriteChat && msg instanceof ClientboundPlayerChatPacket + || get().player.freedomChat.claimSecureChatEnforced && msg instanceof ClientboundServerDataPacket + || get().player.freedomChat.noChatReports && msg instanceof ClientboundStatusResponsePacket; + } + + @Override + protected void encode(final ChannelHandlerContext context, final Packet packet, final ByteBuf byteBuf) throws Exception { + final FriendlyByteBuf buf = new FriendlyByteBuf(byteBuf); + + // TODO: JDK 21 - Change to pattern matching + if (packet instanceof ClientboundPlayerChatPacket chat) + encodeChat(context, chat, buf); + else if (packet instanceof ClientboundServerDataPacket data) + encodeData(context, data, buf); + else if (packet instanceof ClientboundStatusResponsePacket query) + encodeQuery(context, query, buf); + } + + private static void encodeChat( + final ChannelHandlerContext context, final ClientboundPlayerChatPacket packet, final FriendlyByteBuf byteBuf + ) { + final Optional bound = packet.chatType().resolve(getServer().registryAccess()); + if (bound.isEmpty()) { + LOGGER.warn("Failed to resolve chat type: {}", packet.chatType().chatType(), new Throwable()); + return; + } + + final ClientboundSystemChatPacket after = new ClientboundSystemChatPacket( bound.orElseThrow().decorate( + Optional.ofNullable( packet.unsignedContent() ).orElse( Component.literal(packet.body().content()) ) + ), false ); + write(context, after, byteBuf); + after.write(byteBuf); + } + + private static void encodeData( + final ChannelHandlerContext context, final ClientboundServerDataPacket packet, final FriendlyByteBuf byteBuf + ) { + write(context, packet, byteBuf); + byteBuf.writeComponent(packet.getMotd()); + byteBuf.writeOptional(packet.getIconBytes(), FriendlyByteBuf::writeByteArray); + byteBuf.writeBoolean(true); + } + + private static void encodeQuery( + final ChannelHandlerContext context, final ClientboundStatusResponsePacket packet, final FriendlyByteBuf byteBuf + ) { + final JsonObject status = ServerStatus.CODEC.encodeStart(JsonOps.INSTANCE, packet.status()).get().left() + .orElseThrow(() -> new EncoderException("Failed to encode server status query response")).getAsJsonObject(); + + status.addProperty("preventsChatReports", true); + write(context, packet, byteBuf); + byteBuf.writeUtf(GsonComponentSerializer.gson().serializer().toJson(status)); + } + + private static void write( + final ChannelHandlerContext context, final Packet packet, final FriendlyByteBuf byteBuf + ) { + byteBuf.writeVarInt(context.channel().attr(Connection.ATTRIBUTE_CLIENTBOUND_PROTOCOL).get().packetId(packet)); + } + +}