diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ConnectionMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ConnectionMixin.java index 64b8bbefb01..8e128e50fe9 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ConnectionMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ConnectionMixin.java @@ -30,9 +30,13 @@ import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundBundlePacket; +import net.minecraft.network.protocol.game.ServerboundClientTickEndPacket; +import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.server.network.EventLoopGroupHolder; import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -82,6 +86,26 @@ private void onSendPacketTail(Packet packet, @Nullable ChannelFutureListener MeteorClient.EVENT_BUS.post(new PacketEvent.Sent(packet, (Connection) (Object) this)); } + @Unique + private boolean sentPositionThisTick; + + @Inject(method = "doSendPacket(Lnet/minecraft/network/protocol/Packet;Lio/netty/channel/ChannelFutureListener;Z)V", at = @At("HEAD")) + private void onDoSendPacket(Packet packet, @Nullable ChannelFutureListener listener, boolean flush, CallbackInfo ci) { + if (packet instanceof ServerboundClientTickEndPacket) { + sentPositionThisTick = false; + return; + } + + if (!(packet instanceof ServerboundMovePlayerPacket move) || !move.hasPosition()) return; + + if (sentPositionThisTick) sendPacket(ServerboundClientTickEndPacket.INSTANCE, null, false); + + sentPositionThisTick = true; + } + + @Shadow + private void sendPacket(Packet packet, @Nullable ChannelFutureListener listener, boolean flush) {} + @Inject(method = "exceptionCaught", at = @At("HEAD"), cancellable = true) private void exceptionCaught(ChannelHandlerContext ctx, Throwable cause, CallbackInfo ci) { AntiPacketKick apk = Modules.get().get(AntiPacketKick.class); diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/TitleScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/TitleScreenMixin.java index cd9c564b464..a7f2af4c3dc 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/TitleScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/TitleScreenMixin.java @@ -27,12 +27,12 @@ public TitleScreenMixin(Component title) { @Inject(method = "extractRenderState", at = @At("TAIL")) private void onExtractRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float a, CallbackInfo ci) { - if (Config.get().titleScreenCredits.get()) TitleScreenCredits.render(graphics); + if (Config.get() != null && Config.get().titleScreenCredits.get()) TitleScreenCredits.render(graphics); } @Inject(method = "mouseClicked", at = @At("HEAD"), cancellable = true) private void onMouseClicked(MouseButtonEvent event, boolean doubleClick, CallbackInfoReturnable cir) { - if (Config.get().titleScreenCredits.get() && event.button() == InputConstants.MOUSE_BUTTON_LEFT) { + if (Config.get() != null && Config.get().titleScreenCredits.get() && event.button() == InputConstants.MOUSE_BUTTON_LEFT) { if (TitleScreenCredits.onClicked(event.x(), event.y())) cir.setReturnValue(true); } } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/sodium/SodiumDefaultFluidRendererMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/sodium/SodiumDefaultFluidRendererMixin.java index 674bde9913d..35f81a7cd70 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/sodium/SodiumDefaultFluidRendererMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/sodium/SodiumDefaultFluidRendererMixin.java @@ -6,7 +6,6 @@ package meteordevelopment.meteorclient.mixin.sodium; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.llamalad7.mixinextras.sugar.Local; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.systems.modules.render.Xray; import net.caffeinemc.mods.sodium.client.model.color.ColorProvider; @@ -67,16 +66,23 @@ private void onRender(LevelSlice level, BlockState blockState, FluidState fluidS } @ModifyReturnValue(method = "isFullBlockFluidSideVisible", at = @At("RETURN")) - private boolean onIsFullBlockFluidSideVisible(boolean original, BlockGetter view, BlockPos selfPos, Direction facing, FluidState fluid, @Local(name = "otherState") BlockState otherState) { + private boolean onIsFullBlockFluidSideVisible(boolean original, BlockGetter view, BlockPos selfPos, Direction facing, FluidState fluid) { if (original || !forceXrayFluidSides || facing.getAxis().isVertical()) return original; + // Sodium 0.9.2 for 26.3 no longer exposes the neighbor state as a local variable here, + // so we query it from the BlockGetter ourselves. Semantics are identical. + BlockState otherState = view.getBlockState(selfPos.relative(facing)); if (!xray.isBlocked(otherState.getBlock(), null)) return false; return !otherState.getFluidState().getType().isSame(fluid.getType()); } - @ModifyReturnValue(method = "isFluidSideExposed(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/Direction;F)Z", at = @At("RETURN")) - private boolean onIsFluidSideExposed(boolean original, BlockState ownBlockState, BlockState neighborBlockState, Direction facing, float height) { + // In Sodium 0.9.2 (MC 26.3) the old 4-param isFluidSideExposed(BlockState, BlockState, Direction, float) + // is inlined into its 5-param entrypoint, so we can no longer inject on it. Target the public entrypoint instead + // and re-derive the neighbor state from BlockAndTintGetter + pos. + @ModifyReturnValue(method = "isFluidSideExposed(Lnet/minecraft/client/renderer/block/BlockAndTintGetter;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;F)Z", at = @At("RETURN")) + private boolean onIsFluidSideExposed(boolean original, BlockAndTintGetter level, BlockState ownBlockState, BlockPos pos, Direction facing, float height) { if (original || !forceXrayFluidSides || facing.getAxis().isVertical()) return original; + BlockState neighborBlockState = level.getBlockState(pos.relative(facing)); if (!xray.isBlocked(neighborBlockState.getBlock(), null)) return false; return !neighborBlockState.getFluidState().getType().isSame(ownBlockState.getFluidState().getType());