--- a/net/minecraft/network/PacketEncoder.java
+++ b/net/minecraft/network/PacketEncoder.java
@@ -17,10 +17,12 @@
         this.protocolInfo = state;
     }
 
+    static final ThreadLocal<java.util.Locale> ADVENTURE_LOCALE = ThreadLocal.withInitial(() -> null); // Paper - adventure; set player's locale
     protected void encode(ChannelHandlerContext channelHandlerContext, Packet<T> packet, ByteBuf byteBuf) throws Exception {
         PacketType<? extends Packet<? super T>> packetType = packet.type();
 
         try {
+            ADVENTURE_LOCALE.set(channelHandlerContext.channel().attr(io.papermc.paper.adventure.PaperAdventure.LOCALE_ATTRIBUTE).get()); // Paper - adventure; set player's locale
             this.protocolInfo.codec().encode(byteBuf, packet);
             int i = byteBuf.readableBytes();
             if (LOGGER.isDebugEnabled()) {
@@ -31,14 +33,40 @@
 
             JvmProfiler.INSTANCE.onPacketSent(this.protocolInfo.id(), packetType, channelHandlerContext.channel().remoteAddress(), i);
         } catch (Throwable var9) {
-            LOGGER.error("Error sending packet {}", packetType, var9);
+            LOGGER.error("Error sending packet {} (skippable? {})", packetType, packet.isSkippable(), var9);
             if (packet.isSkippable()) {
                 throw new SkipPacketException(var9);
             }
 
             throw var9;
         } finally {
+            // Paper start - Handle large packets disconnecting client
+            int packetLength = byteBuf.readableBytes();
+            if (packetLength > MAX_PACKET_SIZE || (packetLength > MAX_FINAL_PACKET_SIZE && packet.hasLargePacketFallback())) {
+                throw new PacketTooLargeException(packet, packetLength);
+            }
+            // Paper end - Handle large packets disconnecting client
             ProtocolSwapHandler.handleOutboundTerminalPacket(channelHandlerContext, packet);
         }
     }
+
+    // Paper start
+    // packet size is encoded into 3-byte varint
+    private static final int MAX_FINAL_PACKET_SIZE = (1 << 21) - 1;
+    // Vanilla Max size for the encoder (before compression)
+    private static final int MAX_PACKET_SIZE = 8388608;
+
+    public static class PacketTooLargeException extends RuntimeException {
+        private final Packet<?> packet;
+
+        PacketTooLargeException(Packet<?> packet, int packetLength) {
+            super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE);
+            this.packet = packet;
+        }
+
+        public Packet<?> getPacket() {
+            return this.packet;
+        }
+    }
+    // Paper end
 }
