From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Steinborn <git@steinborn.me>
Date: Thu, 21 Jan 2021 00:40:24 +0100
Subject: [PATCH] Port krypton

Co-authored-by: Hugo Planque <hookwood01@gmail.com>

diff --git a/src/main/java/me/steinborn/krypton/mod/shared/network/VarintByteDecoder.java b/src/main/java/me/steinborn/krypton/mod/shared/network/VarintByteDecoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdf5a3b1f7ec27171f3825f89cfb8d398fb3fd79
--- /dev/null
+++ b/src/main/java/me/steinborn/krypton/mod/shared/network/VarintByteDecoder.java
@@ -0,0 +1,47 @@
+package me.steinborn.krypton.mod.shared.network;
+
+import io.netty.util.ByteProcessor;
+
+public class VarintByteDecoder implements ByteProcessor {
+    private int readVarint;
+    private int bytesRead;
+    private DecodeResult result = DecodeResult.TOO_SHORT;
+
+    @Override
+    public boolean process(byte k) {
+        readVarint |= (k & 0x7F) << bytesRead++ * 7;
+        if (bytesRead > 3) {
+            result = DecodeResult.TOO_BIG;
+            return false;
+        }
+        if ((k & 0x80) != 128) {
+            result = DecodeResult.SUCCESS;
+            return false;
+        }
+        return true;
+    }
+
+    public int readVarint() {
+        return readVarint;
+    }
+
+    public int varintBytes() {
+        return bytesRead;
+    }
+
+    public DecodeResult getResult() {
+        return result;
+    }
+
+    public void reset() {
+        readVarint = 0;
+        bytesRead = 0;
+        result = DecodeResult.TOO_SHORT;
+    }
+
+    public enum DecodeResult {
+        SUCCESS,
+        TOO_SHORT,
+        TOO_BIG
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/server/LegacyPingHandler.java b/src/main/java/net/minecraft/server/LegacyPingHandler.java
index 4a49fe4cc600e2b70963302ddae0c4479849f3f5..3abc3869b8012f060e1997822ffdb321f4884929 100644
--- a/src/main/java/net/minecraft/server/LegacyPingHandler.java
+++ b/src/main/java/net/minecraft/server/LegacyPingHandler.java
@@ -23,6 +23,11 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter {
     }
 
     public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception {
+        // Yatopia start - New network system
+        if (!channelhandlercontext.channel().isActive()) {
+            ((ByteBuf) object).clear();
+            return;
+        } // Yatopia end
         ByteBuf bytebuf = (ByteBuf) object;
 
         // Paper start - Make legacy ping handler more reliable
diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java
index e081905af0abbad0cf9011075a6380ef652924a7..c3240607b23ccaa6743c013251e1e45a67072441 100644
--- a/src/main/java/net/minecraft/server/LoginListener.java
+++ b/src/main/java/net/minecraft/server/LoginListener.java
@@ -8,6 +8,7 @@ import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
+import java.security.GeneralSecurityException; // Yatopia
 import java.security.PrivateKey;
 import java.util.Arrays;
 import java.util.Random;
diff --git a/src/main/java/net/minecraft/server/PacketDataSerializer.java b/src/main/java/net/minecraft/server/PacketDataSerializer.java
index f43193c1090238f2241b878120247d1b3d0d4e57..7dc31ee3211a895993c522a7155a0d8641fd442c 100644
--- a/src/main/java/net/minecraft/server/PacketDataSerializer.java
+++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java
@@ -7,6 +7,7 @@ import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.ByteBufInputStream;
 import io.netty.buffer.ByteBufOutputStream;
+import io.netty.buffer.ByteBufUtil; // Yatopia
 import io.netty.handler.codec.DecoderException;
 import io.netty.handler.codec.EncoderException;
 import io.netty.util.ByteProcessor;
@@ -30,7 +31,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit
 
 public class PacketDataSerializer extends ByteBuf {
 
-    private final ByteBuf a;
+    private final ByteBuf a; private final ByteBuf getParent() { return a; } // Yatopia - OBFHELPER
 
     public PacketDataSerializer(ByteBuf bytebuf) {
         this.a = bytebuf;
@@ -210,6 +211,7 @@ public class PacketDataSerializer extends ByteBuf {
         return new UUID(this.readLong(), this.readLong());
     }
 
+    public PacketDataSerializer writeVarInt(int i){ return d(i); } // Yatopia - OBFHELPER
     public PacketDataSerializer d(int i) {
         while ((i & -128) != 0) {
             this.writeByte(i & 127 | 128);
@@ -358,6 +360,8 @@ public class PacketDataSerializer extends ByteBuf {
     }
 
     public PacketDataSerializer a(String s, int i) {
+        // Yatopia start - New network system
+        /*
         byte[] abyte = s.getBytes(StandardCharsets.UTF_8);
 
         if (abyte.length > i) {
@@ -367,6 +371,16 @@ public class PacketDataSerializer extends ByteBuf {
             this.writeBytes(abyte);
             return this;
         }
+         */
+        int utf8Bytes = ByteBufUtil.utf8Bytes(s);
+        if (utf8Bytes > i) {
+            throw new EncoderException("String too big (was " + utf8Bytes + " bytes encoded, max " + i + ")");
+        } else {
+            this.writeVarInt(utf8Bytes);
+            this.writeCharSequence(s, StandardCharsets.UTF_8);
+            return new PacketDataSerializer(getParent());
+        }
+        // Yatopia end
     }
 
     public MinecraftKey p() {
diff --git a/src/main/java/net/minecraft/server/PacketSplitter.java b/src/main/java/net/minecraft/server/PacketSplitter.java
index 2aaa8770edfd8acc6861c23176e405863858b275..b1e1aa95b5d7a1555428327f2e7fd0eafc679dc1 100644
--- a/src/main/java/net/minecraft/server/PacketSplitter.java
+++ b/src/main/java/net/minecraft/server/PacketSplitter.java
@@ -5,14 +5,20 @@ import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageDecoder;
 import io.netty.handler.codec.CorruptedFrameException;
+// Yatopia start
+import io.netty.handler.codec.DecoderException;
+import me.steinborn.krypton.mod.shared.network.VarintByteDecoder;
+// Yatopia end
 import java.util.List;
 
 public class PacketSplitter extends ByteToMessageDecoder {
 
+    private final VarintByteDecoder reader = new VarintByteDecoder(); // Yatopia
     private final byte[] lenBuf = new byte[3]; // Paper
     public PacketSplitter() {}
 
     protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List<Object> list) throws Exception {
+        /* // Yatopia start - New network system
         // Paper start - if channel is not active just discard the packet
         if (!channelhandlercontext.channel().isActive()) {
             bytebuf.skipBytes(bytebuf.readableBytes());
@@ -53,5 +59,38 @@ public class PacketSplitter extends ByteToMessageDecoder {
         }
 
         throw new CorruptedFrameException("length wider than 21-bit");
+         */
+        if (!channelhandlercontext.channel().isActive()) {
+            bytebuf.clear();
+            return;
+        }
+
+        reader.reset();
+
+        int varintEnd = bytebuf.forEachByte(reader);
+        if (varintEnd == -1) {
+            // We tried to go beyond the end of the buffer. This is probably a good sign that the
+            // buffer was too short to hold a proper varint.
+            return;
+        }
+
+        if (reader.getResult() == VarintByteDecoder.DecodeResult.SUCCESS) {
+            int readLen = reader.readVarint();
+            if (readLen < 0) {
+                throw new DecoderException("Bad packet length");
+            } else if (readLen == 0) {
+                // skip over the empty packet and ignore it
+                bytebuf.readerIndex(varintEnd + 1);
+            } else {
+                int minimumRead = reader.varintBytes() + readLen;
+                if (bytebuf.isReadable(minimumRead)) {
+                    list.add(bytebuf.retainedSlice(varintEnd + 1, readLen));
+                    bytebuf.skipBytes(minimumRead);
+                }
+            }
+        } else if (reader.getResult() == VarintByteDecoder.DecodeResult.TOO_BIG) {
+            throw new DecoderException("Varint too big");
+        }
+        // Yatopia end
     }
 }
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index 756be0886856aabc31e436f82948d3d069f66fef..c1dd04b57e8ffeb343b0efdec36d6fb36c16884f 100644
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
@@ -10,6 +10,7 @@ import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import io.netty.util.ResourceLeakDetector; // Yatopia
 import joptsimple.OptionParser;
 import joptsimple.OptionSet;
 import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper
@@ -289,6 +290,24 @@ public class Main {
                         // Paper End
                     }
                 }
+                // Yatopia start - New network system
+                // By default, Netty allocates 16MiB arenas for the PooledByteBufAllocator. This is too much
+                // memory for Minecraft, which imposes a maximum packet size of 2MiB! We'll use 4MiB as a more
+                // sane default.
+                //
+                // Note: io.netty.allocator.pageSize << io.netty.allocator.maxOrder is the formula used to
+                // compute the chunk size. We lower maxOrder from its default of 11 to 9. (We also use a null
+                // check, so that the user is free to choose another setting if need be.)
+                if (System.getProperty("io.netty.allocator.maxOrder") == null) {
+                    System.setProperty("io.netty.allocator.maxOrder", "9");
+                }
+
+                // Disable the resource leak detector by default as it reduces performance. Allow the user to
+                // override this if desired.
+                if (System.getProperty("io.netty.leakDetection.level") == null) {
+                    ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
+                }
+                // Yatopia end
 
                 // Paper start - Log Java and OS versioning to help with debugging plugin issues
                 java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean();
