Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: astei/krypton
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.1.9
Choose a base ref
...
head repository: astei/krypton
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Mar 9, 2022

  1. Better mixin name

    astei committed Mar 9, 2022
    Copy the full SHA
    bfd6d9f View commit details
  2. Unschooled?

    astei committed Mar 9, 2022
    Copy the full SHA
    4d6054e View commit details
  3. Krypton 0.1.10-SNAPSHOT

    astei committed Mar 9, 2022
    Copy the full SHA
    e5dbc48 View commit details
  4. Resync splitter from Velocity

    astei committed Mar 9, 2022
    Copy the full SHA
    fff5cca View commit details
  5. Copy the full SHA
    c41bced View commit details

Commits on Mar 19, 2022

  1. Fix #67

    Since this mixin is now present in Lithium (which most users of Krypton run as well), there's no need for us to retain this historic optimization.
    astei committed Mar 19, 2022
    Copy the full SHA
    c6482d6 View commit details

Commits on Apr 17, 2022

  1. Update Krypton for 22w15a

    astei committed Apr 17, 2022
    Copy the full SHA
    422a430 View commit details

Commits on May 13, 2022

  1. Fix #69

    This PR changes chunk sending order, now preferring to send the chunks nearest to the player whenever possible.
    astei committed May 13, 2022
    Copy the full SHA
    d24cb7e View commit details

Commits on May 14, 2022

  1. fix #70 - send chunks in a spiral

    astei committed May 14, 2022
    Copy the full SHA
    3b66408 View commit details

Commits on May 16, 2022

  1. Fix chunk unload packets not sending & send packets in a more efficie…

    …nt order on player join (#71)
    
    * Chunk packet changes
    
    - Fix krypton not properly sending chunk unload packets
    - Optimize chunk send order for player joins (send chunks in spiral around player)
    
    * Refactor method & fix swapped booleans
    
    - Rename arguments of sendWatchPackets, to indicate their proper function
    - Update chunk unloading to work properly for large teleports (boolean values were swapped)
    
    * Remove logger used for debugging
    
    * Requested changes
    
    Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
    solonovamax authored May 16, 2022
    Copy the full SHA
    8a3179d View commit details

Commits on May 24, 2022

  1. Copy the full SHA
    bd3972e View commit details

Commits on May 28, 2022

  1. Chunk loading order changes (#74)

    * Chunk packet changes
    
    - Fix krypton not properly sending chunk unload packets
    - Optimize chunk send order for player joins (send chunks in spiral around player)
    
    * Refactor method & fix swapped booleans
    
    - Rename arguments of sendWatchPackets, to indicate their proper function
    - Update chunk unloading to work properly for large teleports (boolean values were swapped)
    
    * Remove logger used for debugging
    
    * Requested changes
    
    Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
    
    * Add mixin debug code to build.gradle
    
    Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
    
    * Only send the chunks in the player's render distance to the client
    
    Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
    
    * Fix formatting errors
    
    Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
    
    * Possibly fix nullptr in chunk ticket manager
    
    Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
    solonovamax authored May 28, 2022
    Copy the full SHA
    b23edf8 View commit details
  2. Fix null pointer exception (#75)

    Fix null pointer exception (and the unsupported operation exception that was previously introduced) in ChunkTicketManager
    
    Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
    solonovamax authored May 28, 2022
    Copy the full SHA
    4045984 View commit details
  3. Fix issue with inverted boolean (#76)

    I really did a bruh moment here.
    Renamed the methods to avoid confusion in the future.
    
    Signed-off-by: solonovamax <solonovamax@12oclockpoint.com>
    solonovamax authored May 28, 2022
    Copy the full SHA
    5e2d288 View commit details

Commits on May 30, 2022

  1. comment

    astei committed May 30, 2022
    Copy the full SHA
    918c654 View commit details

Commits on Jun 7, 2022

  1. Merge branch 'master' into dev/mc-1.19

    # Conflicts:
    #	src/main/java/me/steinborn/krypton/mixin/shared/network/flushconsolidation/ThreadedAnvilChunkStorageMixin.java
    astei committed Jun 7, 2022
    Copy the full SHA
    506d73d View commit details
  2. update for 1.19-rc2

    astei committed Jun 7, 2022
    Copy the full SHA
    b2cd4c1 View commit details

Commits on Jun 8, 2022

  1. "formal" 1.19 update

    astei committed Jun 8, 2022
    Copy the full SHA
    b472d2c View commit details
  2. 0.1.10

    astei committed Jun 8, 2022
    Copy the full SHA
    337c4d1 View commit details
  3. Copy the full SHA
    943a27e View commit details

Commits on Jun 23, 2022

  1. Fix

    astei committed Jun 23, 2022
    Copy the full SHA
    8d957c9 View commit details

Commits on Jul 30, 2022

  1. Update to 1.19.1 (#85)

    * Update to 1.19.1
    
    * Remove dead imports
    triphora authored Jul 30, 2022
    Copy the full SHA
    87f253f View commit details
  2. 0.2.1

    astei committed Jul 30, 2022
    Copy the full SHA
    52ed84a View commit details

Commits on Mar 15, 2023

  1. Update to 1.19.4 (#95)

    DrexHD authored Mar 15, 2023
    Copy the full SHA
    a246a12 View commit details

Commits on Mar 16, 2023

  1. 0.2.2

    astei committed Mar 16, 2023
    Copy the full SHA
    ddd5a4c View commit details
  2. Copy the full SHA
    af203ae View commit details

Commits on Apr 19, 2023

  1. Correctly handle negative compression thresholds even though this is …

    …not standardized whatsoever
    astei committed Apr 19, 2023
    Copy the full SHA
    80720b2 View commit details
  2. Add pipeline events

    astei committed Apr 19, 2023
    Copy the full SHA
    5896b60 View commit details
  3. Copy the full SHA
    4ce2286 View commit details
  4. proxy -> server

    astei committed Apr 19, 2023
    Copy the full SHA
    6562a2e View commit details

Commits on Jun 10, 2023

  1. Krypton 0.2.3

    astei committed Jun 10, 2023
    Copy the full SHA
    545721a View commit details

Commits on Sep 11, 2023

  1. Add system property to permit oversized packets.

    This should fix #91, but this is not enabled by default for security reasons. This also does not raise all relevant packet lengths capped by the protocol, although this can be added at a future point in time.
    
    With this system property enabled, Krypton permits packets with 5-byte VarInt prefixes and allows uncompressed packets to be up to 2GiB in size.
    astei committed Sep 11, 2023
    Copy the full SHA
    5fb9eba View commit details

Commits on Sep 13, 2023

  1. Copy the full SHA
    c118928 View commit details

Commits on Sep 23, 2023

  1. Extremely rough initial 1.20.2 version

    I had to axe a bunch of the mixins to get this version working. Of the stuff removed, most is now (mercifully) redundant with Mojang adding batch packets. The only change removed in this commit we can bring back is sending chunks in a spiral.
    astei committed Sep 23, 2023
    Copy the full SHA
    5fd6a75 View commit details
  2. fix

    astei committed Sep 23, 2023
    Copy the full SHA
    b3e3a2e View commit details
  3. Copy the full SHA
    ce63d99 View commit details
  4. Clean up access widener, 0.2.4

    astei committed Sep 23, 2023
    Copy the full SHA
    e6be3e9 View commit details

Commits on Dec 30, 2023

  1. Fix incompatibility with Fabric API 0.9.1 and later.

    Fixes #111.
    
    This isn't the cleanest possible fix, but it does entirely avoid the issue by cloning the contents of plugin messages.
    astei committed Dec 30, 2023
    Copy the full SHA
    da56647 View commit details
  2. Krypton 0.2.5

    astei committed Dec 30, 2023
    Copy the full SHA
    8e74a47 View commit details
  3. Copy the full SHA
    5d5870f View commit details

Commits on Jan 2, 2024

  1. 0.2.6

    astei committed Jan 2, 2024
    Copy the full SHA
    927923b View commit details

Commits on Apr 26, 2024

  1. Initial cut of Minecraft 1.20.5 version

    However, it looks like this keeps crashing in my local environment, and I need to dig deeper here...
    astei committed Apr 26, 2024
    Copy the full SHA
    66dcc36 View commit details

Commits on Apr 30, 2024

  1. 1.20.6

    astei committed Apr 30, 2024
    Copy the full SHA
    82aac06 View commit details
  2. Krypton 0.2.7

    astei committed Apr 30, 2024
    Copy the full SHA
    5a734a3 View commit details

Commits on Jun 22, 2024

  1. Krypton 0.2.8 (#117)

    BenCat07 authored Jun 22, 2024
    Copy the full SHA
    d5c8f54 View commit details
Showing with 262 additions and 765 deletions.
  1. +26 −9 build.gradle
  2. +4 −6 gradle.properties
  3. +1 −1 gradle/wrapper/gradle-wrapper.properties
  4. +0 −25 src/main/java/me/steinborn/krypton/mixin/client/fastchunkentityaccess/ClientWorldMixin.java
  5. +0 −26 src/main/java/me/steinborn/krypton/mixin/server/fastchunkentityaccess/ServerWorldMixin.java
  6. +0 −18 src/main/java/me/steinborn/krypton/mixin/shared/bugfix/CustomPayloadS2CPacketFixMemoryLeakMixin.java
  7. +2 −2 .../java/me/steinborn/krypton/mixin/shared/debugaid/ResourceLeakDetectorDisableConditionalMixin.java
  8. +0 −13 ...n/java/me/steinborn/krypton/mixin/shared/fastchunkentityaccess/EntityTrackingSectionAccessor.java
  9. +0 −48 src/main/java/me/steinborn/krypton/mixin/shared/fastchunkentityaccess/SectionedEntityCacheMixin.java
  10. +0 −73 ...main/java/me/steinborn/krypton/mixin/shared/network/avoidwork/ThreadedAnvilChunkStorageMixin.java
  11. +0 −112 ...main/java/me/steinborn/krypton/mixin/shared/network/flushconsolidation/ClientConnectionMixin.java
  12. +0 −24 ...in/java/me/steinborn/krypton/mixin/shared/network/flushconsolidation/EntityTrackerEntryMixin.java
  13. +0 −162 .../me/steinborn/krypton/mixin/shared/network/flushconsolidation/ThreadedAnvilChunkStorageMixin.java
  14. +34 −0 src/main/java/me/steinborn/krypton/mixin/shared/network/microopt/StringEncodingMixin.java
  15. +0 −23 src/main/java/me/steinborn/krypton/mixin/shared/network/microopt/TacsTrackedEntityMixin.java
  16. +16 −46 .../me/steinborn/krypton/mixin/shared/network/microopt/{PacketByteBufMixin.java → VarIntsMixin.java}
  17. +1 −1 src/main/java/me/steinborn/krypton/mixin/shared/network/pipeline/LegacyQueryHandlerMixin.java
  18. +23 −11 src/main/java/me/steinborn/krypton/mixin/shared/network/pipeline/SplitterHandlerMixin.java
  19. +22 −30 ...in/java/me/steinborn/krypton/mixin/shared/network/pipeline/compression/ClientConnectionMixin.java
  20. +3 −0 ...ain/java/me/steinborn/krypton/mixin/shared/network/pipeline/encryption/ClientConnectionMixin.java
  21. +1 −1 ...me/steinborn/krypton/mixin/shared/network/pipeline/encryption/ServerLoginNetworkHandlerMixin.java
  22. +1 −2 src/main/java/me/steinborn/krypton/mod/client/KryptonClientInitializer.java
  23. +0 −4 src/main/java/me/steinborn/krypton/mod/shared/KryptonMixinPlugin.java
  24. +0 −9 src/main/java/me/steinborn/krypton/mod/shared/WorldEntityByChunkAccess.java
  25. +8 −0 src/main/java/me/steinborn/krypton/mod/shared/misc/KryptonPipelineEvent.java
  26. +17 −4 src/main/java/me/steinborn/krypton/mod/shared/network/VarintByteDecoder.java
  27. +51 −45 src/main/java/me/steinborn/krypton/mod/shared/network/compression/MinecraftCompressDecoder.java
  28. +0 −23 src/main/java/me/steinborn/krypton/mod/shared/network/util/AutoFlushUtil.java
  29. +19 −0 src/main/java/me/steinborn/krypton/mod/shared/network/util/QuietDecoderException.java
  30. +2 −1 src/main/java/me/steinborn/krypton/mod/shared/network/util/VarIntUtil.java
  31. +8 −0 src/main/java/me/steinborn/krypton/mod/shared/network/util/WellKnownExceptions.java
  32. +1 −7 src/main/resources/fabric.mod.json
  33. +2 −9 src/main/resources/krypton.accesswidener
  34. +20 −30 src/main/resources/krypton.mixins.json
35 changes: 26 additions & 9 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
plugins {
id 'fabric-loom' version '0.10-SNAPSHOT'
id 'fabric-loom' version '1.6-SNAPSHOT'
id 'maven-publish'
}

repositories {
maven {
url "https://repo.velocitypowered.com/snapshots/"
url "https://papermc.io/repo/repository/maven-public/"
}
maven { name 'Jitpack'; url 'https://jitpack.io' }
}

sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21

archivesBaseName = project.archives_base_name
version = project.mod_version
@@ -28,10 +28,7 @@ dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation include("com.velocitypowered:velocity-native:1.1.0-SNAPSHOT")

// Include LazyDFU so starting the server and client at the same time doesn't turn my computer into a fighter jet
modRuntime "com.github.astei:lazydfu:${project.lazydfu_version}"
modImplementation include("com.velocitypowered:velocity-native:3.3.0-SNAPSHOT")
}

test {
@@ -73,6 +70,26 @@ publishing {
}
}

afterEvaluate {
tasks.getByName("configureClientLaunch").doFirst {
loom {
runs {
all {
property("fabric.development=true")
property("mixin.hotSwap")
// vmArg("-javaagent:${dependencies.module(group = "net.fabricmc", name = "sponge-mixin")}")
def mixinJarFile = configurations.compileClasspath.files {
it.group == "net.fabricmc" && it.name == "sponge-mixin"
}.find { true }
vmArg("-javaagent:$mixinJarFile")

ideConfigGenerated = true
}
}
}
}
}

loom {
accessWidenerPath = file("src/main/resources/krypton.accesswidener")
}
}
10 changes: 4 additions & 6 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -2,12 +2,10 @@
org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://modmuss50.me/fabric.html
minecraft_version=1.18.2
yarn_mappings=1.18.2+build.1
loader_version=0.13.3
# Runtime
lazydfu_version=0.1.2
minecraft_version=1.21
yarn_mappings=1.21+build.2
loader_version=0.15.11
# Mod Properties
mod_version=0.1.9
mod_version=0.2.8
maven_group=me.steinborn
archives_base_name=krypton
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -10,9 +10,9 @@
public class ResourceLeakDetectorDisableConditionalMixin {
@Redirect(method = "<clinit>", at = @At(value = "INVOKE", target = "Lio/netty/util/ResourceLeakDetector;setLevel(Lio/netty/util/ResourceLeakDetector$Level;)V"))
private static void clinit$resourceLeakDetectorDisableConditional(ResourceLeakDetector.Level level) {
// If io.netty.leakDetection.level is defined, override the client disabling it by default.
// Otherwise, allow it to be disabled.
if (System.getProperty("io.netty.leakDetection.level") == null) {
// Allow the user to override the leak detection level in the Minecraft server with the
// io.netty.leakDetection.level system property.
ResourceLeakDetector.setLevel(level);
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package me.steinborn.krypton.mixin.shared.network.microopt;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.EncoderException;
import net.minecraft.network.encoding.StringEncoding;
import net.minecraft.network.encoding.VarInts;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;

import java.nio.charset.StandardCharsets;

@Mixin(StringEncoding.class)
public class StringEncodingMixin {
/**
* @author Andrew Steinborn
* @reason optimized version
*/
@Overwrite
public static void encode(ByteBuf buf, CharSequence string, int length) {
// Mojang _almost_ gets it right, but stumbles at the finish line...
if (string.length() > length) {
throw new EncoderException("String too big (was " + string.length() + " characters, max " + length + ")");
}
int utf8Bytes = ByteBufUtil.utf8Bytes(string);
int maxBytesPermitted = ByteBufUtil.utf8MaxBytes(length);
if (utf8Bytes > maxBytesPermitted) {
throw new EncoderException("String too big (was " + utf8Bytes + " bytes encoded, max " + maxBytesPermitted + ")");
} else {
VarInts.write(buf, utf8Bytes);
buf.writeCharSequence(string, StandardCharsets.UTF_8);
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,71 +1,41 @@
package me.steinborn.krypton.mixin.shared.network.microopt;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.EncoderException;
import me.steinborn.krypton.mod.shared.network.util.VarIntUtil;
import net.minecraft.network.PacketByteBuf;
import org.spongepowered.asm.mixin.Final;
import net.minecraft.network.encoding.VarInts;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
* Multiple micro-optimizations for packet writing.
*/
@Mixin(PacketByteBuf.class)
public abstract class PacketByteBufMixin extends ByteBuf {

@Shadow @Final private ByteBuf parent;

@Shadow public abstract int writeCharSequence(CharSequence charSequence, Charset charset);

/**
* @author Andrew
* @reason Use optimized VarInt byte size lookup table
*/
@Overwrite
public static int getVarIntLength(int value) {
return VarIntUtil.getVarIntLength(value);
}

@Mixin(VarInts.class)
public class VarIntsMixin {
/**
* @author Andrew
* @reason Use {@link ByteBuf#writeCharSequence(CharSequence, Charset)} instead for improved performance along with
* computing the byte size ahead of time with {@link ByteBufUtil#utf8Bytes(CharSequence)}
* @author Andrew Steinborn
* @reason optimized version
*/
@Overwrite
public PacketByteBuf writeString(String string, int i) {
int utf8Bytes = ByteBufUtil.utf8Bytes(string);
if (utf8Bytes > i) {
throw new EncoderException("String too big (was " + utf8Bytes + " bytes encoded, max " + i + ")");
} else {
this.writeVarInt(utf8Bytes);
this.writeCharSequence(string, StandardCharsets.UTF_8);
return new PacketByteBuf(parent);
}
public static int getSizeInBytes(int v) {
return VarIntUtil.getVarIntLength(v);
}

/**
* @author Andrew
* @reason optimized VarInt writing
* @author Andrew Steinborn
* @reason optimized version
*/
@Overwrite
public PacketByteBuf writeVarInt(int value) {
public static ByteBuf write(ByteBuf buf, int value) {
// Peel the one and two byte count cases explicitly as they are the most common VarInt sizes
// that the proxy will write, to improve inlining.
// that the server will send, to improve inlining.
if ((value & (0xFFFFFFFF << 7)) == 0) {
parent.writeByte(value);
buf.writeByte(value);
} else if ((value & (0xFFFFFFFF << 14)) == 0) {
int w = (value & 0x7F | 0x80) << 8 | (value >>> 7);
parent.writeShort(w);
buf.writeShort(w);
} else {
writeVarIntFull(parent, value);
writeVarIntFull(buf, value);
}
return new PacketByteBuf(parent);

return buf;
}

private static void writeVarIntFull(ByteBuf buf, int value) {
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import net.minecraft.network.LegacyQueryHandler;
import net.minecraft.network.handler.LegacyQueryHandler;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
Original file line number Diff line number Diff line change
@@ -2,14 +2,16 @@

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import me.steinborn.krypton.mod.shared.network.VarintByteDecoder;
import net.minecraft.network.SplitterHandler;
import net.minecraft.network.handler.SplitterHandler;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;

import java.util.List;

import static me.steinborn.krypton.mod.shared.network.util.WellKnownExceptions.BAD_LENGTH_CACHED;
import static me.steinborn.krypton.mod.shared.network.util.WellKnownExceptions.VARINT_BIG_CACHED;

/**
* Overrides the SplitterHandler to use optimized packet splitting from Velocity 1.1.0. In addition this applies a
* security fix to stop "nullping" attacks.
@@ -35,25 +37,35 @@ public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) thro
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.
if (reader.getResult() == VarintByteDecoder.DecodeResult.RUN_OF_ZEROES) {
// Special case where the entire packet is just a run of zeroes. We ignore them all.
in.clear();
}
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
if (reader.getResult() == VarintByteDecoder.DecodeResult.RUN_OF_ZEROES) {
// this will return to the point where the next varint starts
in.readerIndex(varintEnd);
} else if (reader.getResult() == VarintByteDecoder.DecodeResult.SUCCESS) {
int readVarint = reader.getReadVarint();
int bytesRead = reader.getBytesRead();
if (readVarint < 0) {
in.clear();
throw BAD_LENGTH_CACHED;
} else if (readVarint == 0) {
// skip over the empty packet(s) and ignore it
in.readerIndex(varintEnd + 1);
} else {
int minimumRead = reader.varintBytes() + readLen;
int minimumRead = bytesRead + readVarint;
if (in.isReadable(minimumRead)) {
out.add(in.retainedSlice(varintEnd + 1, readLen));
out.add(in.retainedSlice(varintEnd + 1, readVarint));
in.skipBytes(minimumRead);
}
}
} else if (reader.getResult() == VarintByteDecoder.DecodeResult.TOO_BIG) {
throw new DecoderException("Varint too big");
in.clear();
throw VARINT_BIG_CACHED;
}
}
}
Original file line number Diff line number Diff line change
@@ -3,43 +3,34 @@
import com.velocitypowered.natives.compression.VelocityCompressor;
import com.velocitypowered.natives.util.Natives;
import io.netty.channel.Channel;
import me.steinborn.krypton.mod.shared.misc.KryptonPipelineEvent;
import me.steinborn.krypton.mod.shared.network.compression.MinecraftCompressDecoder;
import me.steinborn.krypton.mod.shared.network.compression.MinecraftCompressEncoder;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.handler.PacketDeflater;
import net.minecraft.network.handler.PacketInflater;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

@Mixin(ClientConnection.class)
public class ClientConnectionMixin {
private static Constructor<?> krypton_viaEventConstructor;

static {
krypton_findViaEvent();
}

@Shadow
private Channel channel;

private static void krypton_findViaEvent() {
// ViaFabric compatibility
try {
krypton_viaEventConstructor =
Class.forName("com.viaversion.fabric.common.handler.PipelineReorderEvent").getConstructor();
} catch (ClassNotFoundException | NoSuchMethodException ignored) {
}
}

@Inject(method = "setCompressionThreshold", at = @At("HEAD"), cancellable = true)
public void setCompressionThreshold(int compressionThreshold, boolean validate, CallbackInfo ci) {
if (compressionThreshold == -1) {
this.channel.pipeline().remove("decompress");
this.channel.pipeline().remove("compress");
if (compressionThreshold < 0) {
if (isKryptonOrVanillaDecompressor(this.channel.pipeline().get("decompress"))) {
this.channel.pipeline().remove("decompress");
}
if (isKryptonOrVanillaCompressor(this.channel.pipeline().get("compress"))) {
this.channel.pipeline().remove("compress");
}

this.channel.pipeline().fireUserEventTriggered(KryptonPipelineEvent.COMPRESSION_DISABLED);
} else {
MinecraftCompressDecoder decoder = (MinecraftCompressDecoder) channel.pipeline()
.get("decompress");
@@ -48,6 +39,8 @@ public void setCompressionThreshold(int compressionThreshold, boolean validate,
if (decoder != null && encoder != null) {
decoder.setThreshold(compressionThreshold);
encoder.setThreshold(compressionThreshold);

this.channel.pipeline().fireUserEventTriggered(KryptonPipelineEvent.COMPRESSION_THRESHOLD_UPDATED);
} else {
VelocityCompressor compressor = Natives.compress.get().create(4);

@@ -56,20 +49,19 @@ public void setCompressionThreshold(int compressionThreshold, boolean validate,

channel.pipeline().addBefore("decoder", "decompress", decoder);
channel.pipeline().addBefore("encoder", "compress", encoder);

this.channel.pipeline().fireUserEventTriggered(KryptonPipelineEvent.COMPRESSION_ENABLED);
}
}

this.handleViaCompression();

ci.cancel();
}

private void handleViaCompression() {
if (krypton_viaEventConstructor == null) return;
try {
this.channel.pipeline().fireUserEventTriggered(krypton_viaEventConstructor.newInstance());
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
private static boolean isKryptonOrVanillaDecompressor(Object o) {
return o instanceof PacketInflater || o instanceof MinecraftCompressDecoder;
}

private static boolean isKryptonOrVanillaCompressor(Object o) {
return o instanceof PacketDeflater || o instanceof MinecraftCompressEncoder;
}
}
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import com.velocitypowered.natives.encryption.VelocityCipher;
import com.velocitypowered.natives.util.Natives;
import io.netty.channel.Channel;
import me.steinborn.krypton.mod.shared.misc.KryptonPipelineEvent;
import me.steinborn.krypton.mod.shared.network.ClientConnectionEncryptionExtension;
import me.steinborn.krypton.mod.shared.network.pipeline.MinecraftCipherDecoder;
import me.steinborn.krypton.mod.shared.network.pipeline.MinecraftCipherEncoder;
@@ -27,6 +28,8 @@ public void setupEncryption(SecretKey key) throws GeneralSecurityException {
this.encrypted = true;
this.channel.pipeline().addBefore("splitter", "decrypt", new MinecraftCipherDecoder(decryption));
this.channel.pipeline().addBefore("prepender", "encrypt", new MinecraftCipherEncoder(encryption));

this.channel.pipeline().fireUserEventTriggered(KryptonPipelineEvent.ENCRYPTION_ENABLED);
}
}
}
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@

@Mixin(ServerLoginNetworkHandler.class)
public class ServerLoginNetworkHandlerMixin {
@Shadow @Final public ClientConnection connection;
@Shadow @Final ClientConnection connection;

@Redirect(method = "onKey", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/encryption/NetworkEncryptionUtils;cipherFromKey(ILjava/security/Key;)Ljavax/crypto/Cipher;"))
private Cipher onKey$initializeVelocityCipher(int ignored1, Key secretKey) throws GeneralSecurityException {
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package me.steinborn.krypton.mod.client;

import me.steinborn.krypton.mod.server.KryptonServerInitializer;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@@ -9,7 +8,7 @@

@Environment(EnvType.CLIENT)
public class KryptonClientInitializer implements ClientModInitializer {
private static final Logger LOGGER = LogManager.getLogger(KryptonServerInitializer.class);
private static final Logger LOGGER = LogManager.getLogger(KryptonClientInitializer.class);

@Override
public void onInitializeClient() {
Original file line number Diff line number Diff line change
@@ -20,10 +20,6 @@ public String getRefMapperConfig() {

@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if (mixinClassName.contains("avoidwork.ThreadedAnvilChunkStorageMixin")) {
// This mixin is incompatible with Immersive Portals.
return !FabricLoader.getInstance().isModLoaded("imm_ptl_core");
}
return true;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package me.steinborn.krypton.mod.shared.misc;

public enum KryptonPipelineEvent {
COMPRESSION_ENABLED,
COMPRESSION_THRESHOLD_UPDATED,
COMPRESSION_DISABLED,
ENCRYPTION_ENABLED,
}
Original file line number Diff line number Diff line change
@@ -3,14 +3,26 @@
import io.netty.util.ByteProcessor;

public class VarintByteDecoder implements ByteProcessor {

private static final int MAXIMUM_VARINT_BYTE_SIZE = Boolean.getBoolean("krypton.permit-oversized-packets")
? 5 : 3;

private int readVarint;
private int bytesRead;
private DecodeResult result = DecodeResult.TOO_SHORT;

@Override
public boolean process(byte k) {
if (k == 0 && bytesRead == 0) {
// tentatively say it's invalid, but there's a possibility of redemption
result = DecodeResult.RUN_OF_ZEROES;
return true;
}
if (result == DecodeResult.RUN_OF_ZEROES) {
return false;
}
readVarint |= (k & 0x7F) << bytesRead++ * 7;
if (bytesRead > 3) {
if (bytesRead > MAXIMUM_VARINT_BYTE_SIZE) {
result = DecodeResult.TOO_BIG;
return false;
}
@@ -21,11 +33,11 @@ public boolean process(byte k) {
return true;
}

public int readVarint() {
public int getReadVarint() {
return readVarint;
}

public int varintBytes() {
public int getBytesRead() {
return bytesRead;
}

@@ -42,6 +54,7 @@ public void reset() {
public enum DecodeResult {
SUCCESS,
TOO_SHORT,
TOO_BIG
TOO_BIG,
RUN_OF_ZEROES
}
}
Original file line number Diff line number Diff line change
@@ -3,68 +3,74 @@
import com.velocitypowered.natives.compression.VelocityCompressor;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageDecoder;
import net.minecraft.network.PacketByteBuf;

import java.util.List;

public class MinecraftCompressDecoder extends ByteToMessageDecoder {
import static com.google.common.base.Preconditions.checkState;
import static com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible;
import static com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer;

private static final int UNCOMPRESSED_CAP = 8 * 1024 * 1024; // 8MiB
/**
* Decompresses a Minecraft packet.
*/
public class MinecraftCompressDecoder extends MessageToMessageDecoder<ByteBuf> {

private int threshold;
private final boolean validate;
private final VelocityCompressor compressor;
private static final int VANILLA_MAXIMUM_UNCOMPRESSED_SIZE = 8 * 1024 * 1024; // 8MiB
private static final int HARD_MAXIMUM_UNCOMPRESSED_SIZE = 128 * 1024 * 1024; // 128MiB

public MinecraftCompressDecoder(int threshold, boolean validate, VelocityCompressor compressor) {
this.threshold = threshold;
this.validate = validate;
this.compressor = compressor;
}
private static final int UNCOMPRESSED_CAP =
Boolean.getBoolean("krypton.permit-oversized-packets")
? HARD_MAXIMUM_UNCOMPRESSED_SIZE : VANILLA_MAXIMUM_UNCOMPRESSED_SIZE;

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() != 0) {
PacketByteBuf packetBuf = new PacketByteBuf(in);
int claimedUncompressedSize = packetBuf.readVarInt();
private int threshold;
private final VelocityCompressor compressor;
private final boolean validate;

if (claimedUncompressedSize == 0) {
out.add(packetBuf.readBytes(packetBuf.readableBytes()));
} else {
if (validate) {
if (claimedUncompressedSize < this.threshold) {
throw new DecoderException("Badly compressed packet - size of " + claimedUncompressedSize + " is below server threshold of " + this.threshold);
}
public MinecraftCompressDecoder(int threshold, boolean validate, VelocityCompressor compressor) {
this.threshold = threshold;
this.compressor = compressor;
this.validate = validate;
}

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
PacketByteBuf bb = new PacketByteBuf(in);
int claimedUncompressedSize = bb.readVarInt();
if (claimedUncompressedSize == 0) {
// This message is not compressed.
out.add(in.retain());
return;
}

if (claimedUncompressedSize > UNCOMPRESSED_CAP) {
throw new DecoderException("Badly compressed packet - size of " + claimedUncompressedSize + " is larger than maximum of " + UNCOMPRESSED_CAP);
}
if (validate) {
checkState(claimedUncompressedSize >= threshold, "Uncompressed size %s is less than"
+ " threshold %s", claimedUncompressedSize, threshold);
checkState(claimedUncompressedSize <= UNCOMPRESSED_CAP,
"Uncompressed size %s exceeds hard threshold of %s", claimedUncompressedSize,
UNCOMPRESSED_CAP);
}

ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, in);
ByteBuf uncompressed = com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize);
ByteBuf compatibleIn = ensureCompatible(ctx.alloc(), compressor, in);
ByteBuf uncompressed = preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize);
try {
compressor.inflate(compatibleIn, uncompressed, claimedUncompressedSize);
out.add(uncompressed);
in.clear();
compressor.inflate(compatibleIn, uncompressed, claimedUncompressedSize);
out.add(uncompressed);
} catch (Exception e) {
uncompressed.release();
throw e;
uncompressed.release();
throw e;
} finally {
compatibleIn.release();
compatibleIn.release();
}
}

}
}

public void setThreshold(int threshold) {
this.threshold = threshold;
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
compressor.close();
}

@Override
public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception {
compressor.close();
}
public void setThreshold(int threshold) {
this.threshold = threshold;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package me.steinborn.krypton.mod.shared.network.util;

import io.netty.handler.codec.DecoderException;

/**
* A special-purpose exception thrown when we want to indicate an error decoding but do not want
* to see a large stack trace in logs.
*/
public class QuietDecoderException extends DecoderException {

public QuietDecoderException(String message) {
super(message);
}

@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package me.steinborn.krypton.mod.shared.network.util;

/**
* Maps VarInt byte sizes to a lookup table of 64 entries.
* Maps VarInt byte sizes to a lookup table corresponding to the number of bits in the integer,
* from zero to 32.
*/
public class VarIntUtil {
private static final int[] VARINT_EXACT_BYTE_LENGTHS = new int[33];
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package me.steinborn.krypton.mod.shared.network.util;

public enum WellKnownExceptions {
;

public static final QuietDecoderException BAD_LENGTH_CACHED = new QuietDecoderException("Bad packet length");
public static final QuietDecoderException VARINT_BIG_CACHED = new QuietDecoderException("VarInt too big");
}
8 changes: 1 addition & 7 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
@@ -31,12 +31,6 @@
"accessWidener": "krypton.accesswidener",
"depends": {
"fabricloader": ">=0.11.3",
"minecraft": ">=1.18"
},
"custom": {
"_lithium_mixin_comment": "We disable the player_chunk_tick mixin as Krypton contains a superior version that does flush consolidation.",
"lithium:options": {
"mixin.world.player_chunk_tick": false
}
"minecraft": ">=1.21"
}
}
11 changes: 2 additions & 9 deletions src/main/resources/krypton.accesswidener
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
accessWidener v1 named

accessible class net/minecraft/server/world/ThreadedAnvilChunkStorage$EntityTracker
accessible class net/minecraft/server/world/ThreadedAnvilChunkStorage$TicketManager
accessible method net/minecraft/network/SplitterHandler decode (Lio/netty/channel/ChannelHandlerContext;Lio/netty/buffer/ByteBuf;Ljava/util/List;)V
accessible method net/minecraft/server/world/ThreadedAnvilChunkStorage sendWatchPackets (Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/util/math/ChunkPos;Lorg/apache/commons/lang3/mutable/MutableObject;ZZ)V
accessible field net/minecraft/server/world/ThreadedAnvilChunkStorage$EntityTracker entity Lnet/minecraft/entity/Entity;

# TODO: Reduce abuse
accessible field net/minecraft/client/world/ClientEntityManager cache Lnet/minecraft/world/entity/SectionedEntityCache;
accessible field net/minecraft/server/world/ServerEntityManager cache Lnet/minecraft/world/entity/SectionedEntityCache;
accessible method net/minecraft/network/handler/SplitterHandler decode (Lio/netty/channel/ChannelHandlerContext;Lio/netty/buffer/ByteBuf;Ljava/util/List;)V
accessible field net/minecraft/server/world/ServerChunkLoadingManager$EntityTracker entity Lnet/minecraft/entity/Entity;
50 changes: 20 additions & 30 deletions src/main/resources/krypton.mixins.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
{
"required": true,
"minVersion": "0.8",
"package": "me.steinborn.krypton.mixin",
"compatibilityLevel": "JAVA_16",
"plugin": "me.steinborn.krypton.mod.shared.KryptonMixinPlugin",
"client": [
"client.fastchunkentityaccess.ClientWorldMixin"
],
"mixins": [
"server.fastchunkentityaccess.ServerWorldMixin",
"shared.bugfix.CustomPayloadS2CPacketFixMemoryLeakMixin",
"shared.debugaid.ResourceLeakDetectorDisableConditionalMixin",
"shared.fastchunkentityaccess.EntityTrackingSectionAccessor",
"shared.fastchunkentityaccess.SectionedEntityCacheMixin",
"shared.network.avoidwork.ThreadedAnvilChunkStorageMixin",
"shared.network.flushconsolidation.ClientConnectionMixin",
"shared.network.flushconsolidation.EntityTrackerEntryMixin",
"shared.network.flushconsolidation.ThreadedAnvilChunkStorageMixin",
"shared.network.microopt.EntityTrackerEntryMixin",
"shared.network.microopt.PacketByteBufMixin",
"shared.network.microopt.TacsTrackedEntityMixin",
"shared.network.pipeline.LegacyQueryHandlerMixin",
"shared.network.pipeline.SplitterHandlerMixin",
"shared.network.pipeline.compression.ClientConnectionMixin",
"shared.network.pipeline.encryption.ClientConnectionMixin",
"shared.network.pipeline.encryption.ServerLoginNetworkHandlerMixin"
],
"injectors": {
"defaultRequire": 1
}
"required": true,
"minVersion": "0.8",
"package": "me.steinborn.krypton.mixin",
"compatibilityLevel": "JAVA_16",
"plugin": "me.steinborn.krypton.mod.shared.KryptonMixinPlugin",
"client": [],
"mixins": [
"shared.debugaid.ResourceLeakDetectorDisableConditionalMixin",
"shared.network.microopt.EntityTrackerEntryMixin",
"shared.network.microopt.StringEncodingMixin",
"shared.network.microopt.VarIntsMixin",
"shared.network.pipeline.LegacyQueryHandlerMixin",
"shared.network.pipeline.SplitterHandlerMixin",
"shared.network.pipeline.compression.ClientConnectionMixin",
"shared.network.pipeline.encryption.ClientConnectionMixin",
"shared.network.pipeline.encryption.ServerLoginNetworkHandlerMixin"
],
"injectors": {
"defaultRequire": 1
}
}