diff --git a/Licensing/LICENSE.md b/Licensing/LICENSE.md
index 8293b8409..bc00fd769 100644
--- a/Licensing/LICENSE.md
+++ b/Licensing/LICENSE.md
@@ -1,6 +1,7 @@
The project without the build tools (Everything that is not a .patch file or in the buildSrc folder) are licensed under the MIT license found [here](MIT.md).
-All files in the buildSrc folder are licensed under MIT found [here](../buildSrc/license.txt)
+All files in the buildSrc folder are licensed under MIT found [here](../buildSrc/license.txt).
All patches (.patch files) marked with "lithium" are licensed under LGPL3 found [here](https://github.com/jellysquid3/lithium-fabric/blob/1.16.x/dev/LICENSE.txt).
-All patches (.patch files) marked with "hydrogen" are licensed under LGPL3 found [here](https://github.com/jellysquid3/hydrogen-fabric/blob/1.16.x/LICENSE.txt).
+All patches (.patch files) marked with "hydrogen" are licensed under LGPL3 found [here](https://github.com/jellysquid3/hydrogen-fabric/blob/1.16.x/LICENSE.txt).
+All patches (.patch files) marked with "krypton" are licensed under MIT found [here](https://github.com/astei/krypton/blob/master/LICENSE).
All other patches (.patch files) included in this repo are licensed under the MIT license found [here](MIT.md).
See [EMC](https://github.com/starlis/empirecraft/blob/master/README.md), [Akarin](https://github.com/Akarin-project/Akarin/blob/1.16.3/LICENSE.md), [Purpur](https://github.com/pl3xgaming/Purpur/blob/ver/1.16.5/LICENSE), [AirplaneLite](https://github.com/Technove/AirplaneLite/blob/master/PATCHES-LICENSE), [Origami](https://github.com/Minebench/Origami/blob/1.16/PATCHES-LICENSE), and [Tuinity](https://github.com/Spottedleaf/Tuinity/blob/master/PATCHES-LICENSE) for the license of patches automatically pulled during upstream updates.
diff --git a/PATCHES.md b/PATCHES.md
index 0e3390c7b..55dbb251f 100644
--- a/PATCHES.md
+++ b/PATCHES.md
@@ -242,6 +242,7 @@ This is an overview over all patches that are currently used.
| server | Multi-Threaded Server Ticking Vanilla | Spottedleaf | |
| server | Multi-Threaded ticking CraftBukkit | Spottedleaf | |
| server | Name craft scheduler threads according to the plugin using | Spottedleaf | |
+| server | New Network System | Hugo Planque | Ivan Pekov |
| server | Nuke streams off BlockPosition | Ivan Pekov | |
| server | Nuke streams off SectionPosition | Ivan Pekov | |
| server | Optimise EntityInsentient#checkDespawn | Spottedleaf | |
@@ -291,6 +292,7 @@ This is an overview over all patches that are currently used.
| server | Players should not cram to death | William Blake Galbreath | |
| server | Populator seed controls | Spottedleaf | |
| server | Port hydrogen | JellySquid | |
+| server | Port krypton | Andrew Steinborn | Hugo Planque |
| server | Prevent light queue overfill when no players are online | Spottedleaf | |
| server | Prevent long map entry creation in light engine | Spottedleaf | |
| server | Prevent unload() calls removing tickets for sync loads | Spottedleaf | |
diff --git a/README.md b/README.md
index 025df71cd..2d3ba484b 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ Yatopia combines the code from many [Paper](https://github.com/PaperMC/Paper) fo
* [Purpur](https://github.com/pl3xgaming/Purpur)
* [AirplaneLite](https://github.com/Technove/AirplaneLite)
* [Hydrogen](https://github.com/jellysquid3/hydrogen-fabric)
+* [Krypton](https://github.com/astei/krypton)
## Try it out
diff --git a/patches/server/0066-New-Network-System.patch b/patches/server/0066-New-Network-System.patch
new file mode 100644
index 000000000..0c0613a56
--- /dev/null
+++ b/patches/server/0066-New-Network-System.patch
@@ -0,0 +1,307 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Hugo Planque
+Date: Mon, 18 Jan 2021 11:27:08 +0100
+Subject: [PATCH] New Network System
+
+Co-authored-by: Ivan Pekov
+
+diff --git a/pom.xml b/pom.xml
+index 8af1a91102c5cc4c230f622e6629e46e95f17d44..9b7ed0de1054285dadff6aefc95c7207079504a6 100644
+--- a/pom.xml
++++ b/pom.xml
+@@ -53,9 +53,17 @@
+
+ io.netty
+ netty-all
+- 4.1.50.Final
++ 4.1.58.Final
+
+
++
++
++ io.netty.incubator
++ netty-incubator-transport-native-io_uring
++ 0.0.3.Final
++ linux-x86_64
++
++
+
+ io.papermc
+ minecraft-server
+diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
+index 87cf9cd88d1fb5ae70d19e5618ebfb67d281304a..a1c2bea7c93433434b4e4dfd0bb4b9620657c40d 100644
+--- a/src/main/java/net/minecraft/server/MinecraftServer.java
++++ b/src/main/java/net/minecraft/server/MinecraftServer.java
+@@ -1740,6 +1740,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant a = new LazyInitVar<>(() -> {
+ return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Server IO #%d").setDaemon(true).build());
+ });
+ public static final LazyInitVar b = new LazyInitVar<>(() -> {
+ return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Server IO #%d").setDaemon(true).build());
+ });
++ */
++ // Yatopia end
+ private final MinecraftServer e;
+ public volatile boolean c;
+ private final List listeningChannels = Collections.synchronizedList(Lists.newArrayList());
+@@ -52,15 +57,29 @@ public class ServerConnection {
+ }
+ // Paper end
+
++ // Yatopia start - New network system
++ private final NetworkType networkType;
++ private final EventLoopGroup boss, worker;
++ // Yatopia end
++
+ public ServerConnection(MinecraftServer minecraftserver) {
+ this.e = minecraftserver;
+ this.c = true;
++
++ // Yatopia start - New network system
++ this.networkType = NetworkType.bestType(minecraftserver);
++ this.boss = networkType.createEventLoopGroup(NetworkType.LoopGroupType.BOSS);
++ this.worker = networkType.createEventLoopGroup(NetworkType.LoopGroupType.WORKER);
++ // Yatopia end
+ }
+
+ public void a(@Nullable InetAddress inetaddress, int i) throws IOException {
++ /* // Yatopia start - New network system
+ List list = this.listeningChannels;
++ */
+
+ synchronized (this.listeningChannels) {
++ /*
+ Class oclass;
+ LazyInitVar lazyinitvar;
+
+@@ -73,16 +92,25 @@ public class ServerConnection {
+ lazyinitvar = ServerConnection.a;
+ ServerConnection.LOGGER.info("Using default channel type");
+ }
++ */
++
+
+ // Tuinity start - indicate Velocity natives in use
+ ServerConnection.LOGGER.info("Tuinity: Using " + com.velocitypowered.natives.util.Natives.compress.getLoadedVariant() + " compression from Velocity.");
+ ServerConnection.LOGGER.info("Tuinity: Using " + com.velocitypowered.natives.util.Natives.cipher.getLoadedVariant() + " cipher from Velocity.");
+ // Tuinity end
+
+- this.listeningChannels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer() {
++ ServerConnection.LOGGER.info("Yatopia: Using " + networkType.getName() + " network type.");
++ ServerBootstrap serverBootstrap = new ServerBootstrap();
++
++ if (org.yatopiamc.yatopia.server.YatopiaConfig.tcpFastOpen && networkType == NetworkType.EPOLL) {
++ serverBootstrap.option(EpollChannelOption.TCP_FASTOPEN, 3); // Will improve the connection with some speed
++ }
++ this.listeningChannels.add((((serverBootstrap).channelFactory(networkType.getServerSocketChannelFactory())).childHandler(new ChannelInitializer() {
+ protected void initChannel(Channel channel) throws Exception {
+ try {
+ channel.config().setOption(ChannelOption.TCP_NODELAY, true);
++ channel.config().setOption(ChannelOption.IP_TOS, 0x18); // Change the priority of the packet to immediate
+ } catch (ChannelException channelexception) {
+ ;
+ }
+@@ -97,7 +125,8 @@ public class ServerConnection {
+ channel.pipeline().addLast("packet_handler", (ChannelHandler) object);
+ ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object));
+ }
+- }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit
++ }).group(boss, worker).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit
++ // Yatopia end
+ }
+ }
+
+diff --git a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
+index 35f212c2ac43ebea6ce9c4a333738c7a869ebc18..c4d0dabd408c7a943dafd6ca89b598cb4afb440e 100644
+--- a/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
++++ b/src/main/java/org/yatopiamc/yatopia/server/YatopiaConfig.java
+@@ -303,4 +303,11 @@ public class YatopiaConfig {
+ logPlayerLoginLoc = getBoolean("settings.log-player-login-location", logPlayerLoginLoc);
+ }
+
++ public static boolean ioUringBeta = false;
++ public static boolean tcpFastOpen = false;
++ private static void newNetworkSystem() {
++ ioUringBeta = getBoolean("network.io-uring", ioUringBeta);
++ tcpFastOpen = getBoolean("network.ftcp-fastopen", tcpFastOpen);
++ }
++
+ }
+diff --git a/src/main/java/org/yatopiamc/yatopia/server/network/NettyThreadFactory.java b/src/main/java/org/yatopiamc/yatopia/server/network/NettyThreadFactory.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..3e74e23f3cc44b7547d9f8575b411059e0e65449
+--- /dev/null
++++ b/src/main/java/org/yatopiamc/yatopia/server/network/NettyThreadFactory.java
+@@ -0,0 +1,27 @@
++package org.yatopiamc.yatopia.server.network;
++
++import io.netty.util.concurrent.FastThreadLocalThread;
++import java.util.concurrent.ThreadFactory;
++import java.util.concurrent.atomic.AtomicInteger;
++
++/**
++ * Based off of Velocity's VelocityNettyThreadFactory
++ */
++public class NettyThreadFactory implements ThreadFactory {
++
++ private final AtomicInteger threadNumber = new AtomicInteger();
++ private final String networkTypeName, loopGroupTypeName;
++
++ public NettyThreadFactory(String networkTypeName, String loopGroupTypeName) {
++ this.networkTypeName = networkTypeName;
++ this.loopGroupTypeName = loopGroupTypeName;
++ }
++
++ @Override
++ public Thread newThread(Runnable r) {
++ return new FastThreadLocalThread(
++ r,
++ "Netty " + networkTypeName + " " + loopGroupTypeName + " #" + threadNumber.getAndIncrement()
++ );
++ }
++}
+diff --git a/src/main/java/org/yatopiamc/yatopia/server/network/NetworkType.java b/src/main/java/org/yatopiamc/yatopia/server/network/NetworkType.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..6b9d788dfef2c51111e9f2129a04fce7754c51ba
+--- /dev/null
++++ b/src/main/java/org/yatopiamc/yatopia/server/network/NetworkType.java
+@@ -0,0 +1,110 @@
++package org.yatopiamc.yatopia.server.network;
++
++import io.netty.channel.ChannelFactory;
++import io.netty.channel.EventLoopGroup;
++import io.netty.channel.epoll.Epoll;
++import io.netty.channel.epoll.EpollEventLoopGroup;
++import io.netty.channel.epoll.EpollServerSocketChannel;
++import io.netty.channel.kqueue.KQueue;
++import io.netty.channel.kqueue.KQueueEventLoopGroup;
++import io.netty.channel.kqueue.KQueueServerSocketChannel;
++import io.netty.channel.nio.NioEventLoopGroup;
++import io.netty.channel.socket.ServerSocketChannel;
++import io.netty.channel.socket.nio.NioServerSocketChannel;
++import io.netty.incubator.channel.uring.IOUring;
++import io.netty.incubator.channel.uring.IOUringEventLoopGroup;
++import io.netty.incubator.channel.uring.IOUringServerSocketChannel;
++
++import java.util.concurrent.ThreadFactory;
++import java.util.function.BiFunction;
++
++import net.minecraft.server.MinecraftServer;
++import org.spigotmc.SpigotConfig;
++import org.yatopiamc.yatopia.server.YatopiaConfig;
++
++/**
++ * Based off of Velocity's TransportType
++ */
++public enum NetworkType {
++ NIO("NIO", NioServerSocketChannel::new, (name, type) -> new NioEventLoopGroup(8, createThreadFactory(name, type))),
++
++ EPOLL("Epoll", EpollServerSocketChannel::new, (name, type) -> new EpollEventLoopGroup(8, createThreadFactory(name, type))),
++
++ IOURING("IOUring", IOUringServerSocketChannel::new, (name, type) -> new IOUringEventLoopGroup(8, createThreadFactory(name, type))),
++
++ KQUEUE("KQueue", KQueueServerSocketChannel::new, (name, type) -> new KQueueEventLoopGroup(8, createThreadFactory(name, type)));
++
++ public final String name;
++ public final ChannelFactory extends ServerSocketChannel> serverSocketChannelFactory;
++ public final BiFunction eventLoopGroupFactory;
++
++ NetworkType(final String name,
++ final ChannelFactory extends ServerSocketChannel> serverSocketChannelFactory,
++ final BiFunction eventLoopGroupFactory) {
++ this.name = name;
++ this.serverSocketChannelFactory = serverSocketChannelFactory;
++ this.eventLoopGroupFactory = eventLoopGroupFactory;
++ }
++
++ public String getName() {
++ return name;
++ }
++
++ public ChannelFactory extends ServerSocketChannel> getServerSocketChannelFactory() {
++ return serverSocketChannelFactory;
++ }
++
++ @Override
++ public String toString() {
++ return this.name;
++ }
++
++ public EventLoopGroup createEventLoopGroup(final LoopGroupType type) {
++ return this.eventLoopGroupFactory.apply(this.name, type);
++ }
++
++ private static ThreadFactory createThreadFactory(final String name, final LoopGroupType type) {
++ return new NettyThreadFactory(name, type.toString());
++ }
++
++ public static NetworkType bestType(MinecraftServer minecraftServer) {
++ if (!minecraftServer.isUsingNativeTransport()) {
++ return NIO;
++ }
++ // Actually, there is a decompression problem with zlib from bungeecord that makes
++ // IOUring not available on spigot server with bungeecord
++ // https://github.com/netty/netty-incubator-transport-io_uring/issues/40
++ // Looks like iouring send very small compressed packet and trigger PacketDecompressor
++ if (!SpigotConfig.bungee && YatopiaConfig.ioUringBeta && MinecraftServer.getServer().ax() < 0) {
++ if (IOUring.isAvailable()) {
++ return IOURING;
++ }
++ }
++
++ if (Epoll.isAvailable()) {
++ return EPOLL;
++ }
++
++ if (KQueue.isAvailable()) {
++ return KQUEUE;
++ }
++
++ return NIO;
++ }
++
++ public enum LoopGroupType {
++ BOSS("Boss"),
++ WORKER("Worker");
++
++ private final String name;
++
++ LoopGroupType(final String name) {
++ this.name = name;
++ }
++
++ @Override
++ public String toString() {
++ return this.name;
++ }
++ }
++}
diff --git a/patches/server/0066-Port-hydrogen.patch b/patches/server/0067-Port-hydrogen.patch
similarity index 100%
rename from patches/server/0066-Port-hydrogen.patch
rename to patches/server/0067-Port-hydrogen.patch
diff --git a/patches/server/0068-Port-krypton.patch b/patches/server/0068-Port-krypton.patch
new file mode 100644
index 000000000..3b5de53f8
--- /dev/null
+++ b/patches/server/0068-Port-krypton.patch
@@ -0,0 +1,550 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrew Steinborn
+Date: Thu, 21 Jan 2021 00:40:24 +0100
+Subject: [PATCH] Port krypton
+
+Co-authored-by: Hugo Planque
+
+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/me/steinborn/krypton/mod/shared/network/compression/MinecraftCompressDecoder.java b/src/main/java/me/steinborn/krypton/mod/shared/network/compression/MinecraftCompressDecoder.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..e9a51c71e136be14ebe8a240c4b21205079fc71b
+--- /dev/null
++++ b/src/main/java/me/steinborn/krypton/mod/shared/network/compression/MinecraftCompressDecoder.java
+@@ -0,0 +1,68 @@
++package me.steinborn.krypton.mod.shared.network.compression;
++
++import com.velocitypowered.natives.compression.VelocityCompressor;
++import io.netty.buffer.ByteBuf;
++import io.netty.channel.ChannelHandlerContext;
++import io.netty.handler.codec.CorruptedFrameException;
++import io.netty.handler.codec.MessageToMessageDecoder;
++import net.minecraft.server.PacketDataSerializer;
++
++import java.util.List;
++
++import static com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible;
++import static com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer;
++
++public class MinecraftCompressDecoder extends MessageToMessageDecoder {
++
++ private static final int VANILLA_MAXIMUM_UNCOMPRESSED_SIZE = 2 * 1024 * 1024; // 2MiB
++ private static final int HARD_MAXIMUM_UNCOMPRESSED_SIZE = 16 * 1024 * 1024; // 16MiB
++
++ private static final int UNCOMPRESSED_CAP =
++ Boolean.getBoolean("velocity.increased-compression-cap")
++ ? HARD_MAXIMUM_UNCOMPRESSED_SIZE : VANILLA_MAXIMUM_UNCOMPRESSED_SIZE;
++
++ private final int threshold;
++ private final VelocityCompressor compressor;
++
++ public MinecraftCompressDecoder(int threshold, VelocityCompressor compressor) {
++ this.threshold = threshold;
++ this.compressor = compressor;
++ }
++
++ @Override
++ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List