|
| 1 | +package com.ishland.c2me.notickvd.mixin.smooth_sending_rate; |
| 2 | + |
| 3 | +import com.ishland.c2me.notickvd.common.smooth_sending_rate.ExponentialMovingAverage; |
| 4 | +import com.llamalad7.mixinextras.injector.ModifyReturnValue; |
| 5 | +import it.unimi.dsi.fastutil.longs.LongSet; |
| 6 | +import net.minecraft.server.network.ChunkDataSender; |
| 7 | +import net.minecraft.server.network.ServerPlayerEntity; |
| 8 | +import net.minecraft.text.Text; |
| 9 | +import net.minecraft.world.chunk.WorldChunk; |
| 10 | +import org.objectweb.asm.Opcodes; |
| 11 | +import org.spongepowered.asm.mixin.Final; |
| 12 | +import org.spongepowered.asm.mixin.Mixin; |
| 13 | +import org.spongepowered.asm.mixin.Shadow; |
| 14 | +import org.spongepowered.asm.mixin.Unique; |
| 15 | +import org.spongepowered.asm.mixin.injection.At; |
| 16 | +import org.spongepowered.asm.mixin.injection.Inject; |
| 17 | +import org.spongepowered.asm.mixin.injection.Redirect; |
| 18 | +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; |
| 19 | + |
| 20 | +import java.util.List; |
| 21 | + |
| 22 | +@Mixin(ChunkDataSender.class) |
| 23 | +public class MixinChunkDataSender { |
| 24 | + |
| 25 | + @Shadow |
| 26 | + @Final |
| 27 | + private LongSet chunks; |
| 28 | + |
| 29 | + @Shadow |
| 30 | + private float pending; |
| 31 | + @Shadow |
| 32 | + @Final |
| 33 | + private boolean local; |
| 34 | + @Shadow |
| 35 | + private float desiredBatchSize; |
| 36 | + @Unique |
| 37 | + private ExponentialMovingAverage c2me$ema; |
| 38 | + @Unique |
| 39 | + private ExponentialMovingAverage c2me$emaActual; |
| 40 | + @Unique |
| 41 | + private int c2me$lastTickSent = 0; |
| 42 | + |
| 43 | + @Inject(method = "<init>", at = @At(value = "RETURN")) |
| 44 | + private void onInit(boolean local, CallbackInfo ci) { |
| 45 | + this.c2me$ema = new ExponentialMovingAverage(1.0 / 20.0, 10.0, 4.0); |
| 46 | + this.c2me$emaActual = new ExponentialMovingAverage(1.0 / 20.0, 0.1, 0.1); |
| 47 | + } |
| 48 | + |
| 49 | + @Inject(method = "sendChunkBatches", at = @At(value = "HEAD")) |
| 50 | + private void onTick(ServerPlayerEntity player, CallbackInfo ci) { |
| 51 | + this.c2me$ema.onTick(this.chunks.size()); |
| 52 | + this.c2me$emaActual.onTick(this.c2me$lastTickSent); |
| 53 | +// player.sendMessage(Text.of(String.format("Current target sending rate: %.1f cps, %.1f cps, actual: %.1f cps", this.c2me$getTargetSendingRate() * 20.0, this.desiredBatchSize * 20.0, this.c2me$emaActual.getCurrent() * 20.0)), true); |
| 54 | + this.c2me$lastTickSent = 0; |
| 55 | + } |
| 56 | + |
| 57 | + @Redirect(method = "sendChunkBatches", at = @At(value = "FIELD", target = "Lnet/minecraft/server/network/ChunkDataSender;desiredBatchSize:F", opcode = Opcodes.GETFIELD), require = 2) |
| 58 | + private float redirectDesiredBatchSize(ChunkDataSender instance) { |
| 59 | + assert instance == (Object) this; |
| 60 | + return this.local ? (float) this.c2me$getTargetSendingRate() : Math.min(this.desiredBatchSize, (float) this.c2me$getTargetSendingRate()); |
| 61 | + } |
| 62 | + |
| 63 | + @Redirect(method = "makeBatch", at = @At(value = "FIELD", target = "Lnet/minecraft/server/network/ChunkDataSender;local:Z", opcode = Opcodes.GETFIELD)) |
| 64 | + private boolean applyClampingToLocal(ChunkDataSender instance) { |
| 65 | + return false; |
| 66 | + } |
| 67 | + |
| 68 | + @ModifyReturnValue(method = "makeBatch", at = @At("RETURN")) |
| 69 | + private List<WorldChunk> onBatch(List<WorldChunk> original) { |
| 70 | + this.c2me$lastTickSent = original.size(); |
| 71 | + return original; |
| 72 | + } |
| 73 | + |
| 74 | + @Unique |
| 75 | + private double c2me$getTargetSendingRate() { |
| 76 | + return (this.c2me$ema.getCurrent()) / 10.0F; |
| 77 | + } |
| 78 | + |
| 79 | +} |
0 commit comments