diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java index b851b1b463c..ac4c9840d9a 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java @@ -628,6 +628,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig newValue -> config.uiAndVisuals.smoothAOTE.predictive = newValue) .controller(ConfigUtils.createBooleanController()) .build()) + .option(Option.createBuilder() + .name(Component.translatable("skyblocker.config.uiAndVisuals.smoothAOTE.thirdPerson")) + .description(Component.translatable("skyblocker.config.uiAndVisuals.smoothAOTE.thirdPerson.@Tooltip")) + .binding(defaults.uiAndVisuals.smoothAOTE.thirdPerson, + () -> config.uiAndVisuals.smoothAOTE.thirdPerson, + newValue -> config.uiAndVisuals.smoothAOTE.thirdPerson = newValue) + .controller(ConfigUtils.createBooleanController()) + .build()) .option(Option.createBuilder() .name(Component.translatable("skyblocker.config.uiAndVisuals.smoothAOTE.enableWeirdTransmission")) .description(Component.translatable("skyblocker.config.uiAndVisuals.smoothAOTE.enableWeirdTransmission.@Tooltip")) diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index f188d4179a5..eb2ef13040c 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -358,6 +358,8 @@ public static class TeleportOverlay { public static class SmoothAOTE { public boolean predictive = false; + public boolean thirdPerson = true; + public boolean enableWeirdTransmission = false; public boolean enableInstantTransmission = false; diff --git a/src/main/java/de/hysky/skyblocker/mixins/CameraMixin.java b/src/main/java/de/hysky/skyblocker/mixins/CameraMixin.java index 27232b814cd..f1b8bd3440b 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/CameraMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/CameraMixin.java @@ -20,7 +20,7 @@ public class CameraMixin { return pos; } } else { - Vec3 pos = ResponsiveSmoothAOTE.getInterpolatedPos(); + Vec3 pos = ResponsiveSmoothAOTE.getInterpolatedPos(original); if (pos != null) { return pos; } diff --git a/src/main/java/de/hysky/skyblocker/mixins/EntityRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixins/EntityRendererMixin.java index 2624cf260fd..ae66b3a6c52 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/EntityRendererMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/EntityRendererMixin.java @@ -8,13 +8,17 @@ import de.hysky.skyblocker.skyblock.entity.MobBoundingBoxes; import de.hysky.skyblocker.skyblock.entity.MobGlow; import de.hysky.skyblocker.skyblock.slayers.SlayerManager; +import de.hysky.skyblocker.skyblock.teleport.PredictiveSmoothAOTE; +import de.hysky.skyblocker.skyblock.teleport.ResponsiveSmoothAOTE; import de.hysky.skyblocker.utils.Boxes; import de.hysky.skyblocker.utils.ColorUtils; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.state.EntityRenderState; import net.minecraft.network.chat.Component; import net.minecraft.util.ARGB; import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -57,6 +61,28 @@ public class EntityRendererMixin { } } + // This is meant to be separate from the previous injection for organizational purposes. + @Inject(method = "extractRenderState", at = @At(value = "TAIL")) + private void skyblocker$movePlayerRenderPos(CallbackInfo ci, @Local(name = "entity") Entity entity, @Local(name = "state") EntityRenderState state, @Local(name = "partialTicks") float partialTicks) { + Minecraft client = Minecraft.getInstance(); + + if (entity == client.player && !client.options.getCameraType().isFirstPerson()) { + Vec3 pos; + if (SkyblockerConfigManager.get().uiAndVisuals.smoothAOTE.predictive) { + pos = PredictiveSmoothAOTE.getInterpolatedPlayerPos(); + + } else { + pos = ResponsiveSmoothAOTE.getInterpolatedPlayerPos(partialTicks); + } + if (pos != null) + { + state.x = pos.x; + state.y = pos.y; + state.z = pos.z; + } + } + } + @ModifyReturnValue(method = "getNameTag", at = @At("RETURN")) private @Nullable Component skyblocker$applyCustomName(@Nullable Component original, T entity) { Component customName = entity.skyblocker$getCustomName(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/teleport/PredictiveSmoothAOTE.java b/src/main/java/de/hysky/skyblocker/skyblock/teleport/PredictiveSmoothAOTE.java index cc937a7b1cb..25bb0d72d53 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/teleport/PredictiveSmoothAOTE.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/teleport/PredictiveSmoothAOTE.java @@ -12,6 +12,7 @@ import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Location; import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.render.RenderHelper; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.event.player.UseItemCallback; @@ -43,6 +44,8 @@ import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; +import org.jspecify.annotations.Nullable; + import java.util.List; public class PredictiveSmoothAOTE { @@ -52,8 +55,11 @@ public class PredictiveSmoothAOTE { private static final long MAX_TELEPORT_TIME = 2500; //2.5 seconds private static long startTime; + @Nullable private static Vec3 startPos; + @Nullable private static Vec3 cameraStartPos; + @Nullable private static Vec3 teleportVector; private static long lastPing; private static long currentTeleportPing; @@ -177,8 +183,8 @@ private static void calculateTeleportUse(InteractionHand hand) { return; } - // make sure the camera is not in 3rd person - if (CLIENT.options.getCameraType() != CameraType.FIRST_PERSON) { + // make sure the camera is not in 3rd person if disabled + if (CLIENT.options.getCameraType() != CameraType.FIRST_PERSON && !SkyblockerConfigManager.get().uiAndVisuals.smoothAOTE.thirdPerson) { return; } @@ -211,7 +217,7 @@ private static void calculateTeleportUse(InteractionHand hand) { if (teleportsAhead == 0 || startPos == null || teleportVector == null) { //start of teleport sequence startPos = CLIENT.player.position().add(0, Utils.getEyeHeight(CLIENT.player), 0); // the eye poss should not be affected by crouching - cameraStartPos = CLIENT.player.getEyePosition(); + cameraStartPos = RenderHelper.getCamera().position(); lastTeleportTime = System.currentTimeMillis(); // update the ping used for the teleport currentTeleportPing = lastPing; @@ -479,6 +485,11 @@ protected static Vec3 raycast(int distance, Vec3 direction, Vec3 startPos, boole } //return full distance if no collision found + //Hypixel has started moving this a block down so do that if it's not solid + if (!isBlockFloor(BlockPos.containing(startPos.add(direction.scale(distance)).subtract(0, 1, 0)))) { + return direction.scale(distance).subtract(0, 1, 0); + } + return direction.scale(distance); } @@ -528,7 +539,7 @@ private static Boolean isBlockFloor(BlockPos blockPos) { * * @return the camera position for the interpolated pos */ - + @Nullable public static Vec3 getInterpolatedPos() { if (CLIENT.player == null || teleportVector == null || startPos == null || teleportDisabled) { return null; @@ -556,6 +567,19 @@ public static Vec3 getInterpolatedPos() { return cameraStartPos.add(teleportVector.scale(percentage)); } + /** + * Get the difference between the camara and the actual player position. Then adds this to interpolated camara position + * @return Interpolated player position + */ + @Nullable + public static Vec3 getInterpolatedPlayerPos() { + if (startPos == null || CLIENT.player == null || cameraStartPos == null) return null; + Vec3 diff = startPos.subtract(0, Utils.getEyeHeight(CLIENT.player), 0).subtract(cameraStartPos); + Vec3 camara = getInterpolatedPos(); + if (camara == null) return null; + return camara.add(diff); + } + public static void updatePing(long ping) { lastPing = ping; } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/teleport/ResponsiveSmoothAOTE.java b/src/main/java/de/hysky/skyblocker/skyblock/teleport/ResponsiveSmoothAOTE.java index 0253bb76224..468ed922538 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/teleport/ResponsiveSmoothAOTE.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/teleport/ResponsiveSmoothAOTE.java @@ -2,19 +2,26 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.ItemUtils; +import de.hysky.skyblocker.utils.render.RenderHelper; +import net.minecraft.client.CameraType; import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; +import javax.annotation.Nullable; + import static de.hysky.skyblocker.skyblock.teleport.PredictiveSmoothAOTE.getItemDistance; public class ResponsiveSmoothAOTE { private static final Minecraft CLIENT = Minecraft.getInstance(); private static long startTime; + @Nullable private static Vec3 lastPosition; private static double lastProgress; + @Nullable + private static Vec3 cameraStartPos; public static void playerGoingToTeleport() { if (CLIENT.player == null || SkyblockerConfigManager.get().uiAndVisuals.smoothAOTE.maximumAddedLag == 0) return; @@ -26,15 +33,21 @@ public static void playerGoingToTeleport() { if (distance == -1) { return; } + // make sure the camera is not in 3rd person if disabled + if (CLIENT.options.getCameraType() != CameraType.FIRST_PERSON && !SkyblockerConfigManager.get().uiAndVisuals.smoothAOTE.thirdPerson) { + return; + } - Vec3 currentIntermediatePosition = getInterpolatedPos(); - lastPosition = currentIntermediatePosition == null ? CLIENT.player.getEyePosition() : currentIntermediatePosition; + Vec3 currentIntermediatePosition = getInterpolatedPos(RenderHelper.getCamera().position()); + lastPosition = currentIntermediatePosition == null ? RenderHelper.getCamera().position() : currentIntermediatePosition; lastProgress = 0; startTime = System.currentTimeMillis(); } - public static Vec3 getInterpolatedPos() { + @Nullable + public static Vec3 getInterpolatedPos(Vec3 original) { if (lastPosition == null || CLIENT.player == null) return null; + cameraStartPos = original; double progress = (double) (System.currentTimeMillis() - startTime) / SkyblockerConfigManager.get().uiAndVisuals.smoothAOTE.maximumAddedLag; //end if finished if (progress >= 1) { @@ -43,7 +56,7 @@ public static Vec3 getInterpolatedPos() { return null; } //find vector between last position and current pos - Vec3 teleportVector = CLIENT.player.getEyePosition().subtract(lastPosition); + Vec3 teleportVector = original.subtract(lastPosition); double progressDiff = progress - lastProgress; double relativeProgress = progressDiff / (1 - lastProgress); @@ -53,6 +66,14 @@ public static Vec3 getInterpolatedPos() { lastPosition = lastPosition.add(teleportVector.scale(relativeProgress)); lastProgress = progress; return lastPosition; + } + @Nullable + public static Vec3 getInterpolatedPlayerPos(float partialTicks) { + if (CLIENT.player == null || cameraStartPos == null) return null; + Vec3 diff = CLIENT.player.getPosition(partialTicks).subtract(cameraStartPos); + Vec3 camara = getInterpolatedPos(cameraStartPos); + if (camara == null) return null; + return camara.add(diff); } } diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index ed9d1ac0194..6a3935436b9 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -1376,6 +1376,8 @@ "skyblocker.config.uiAndVisuals.smoothAOTE.maximumAddedLag.@Tooltip": "Predictive:\nHow long the animation is allowed to get behind the game in milliseconds. (If set to 0, smoothing will not have any lag, but stuttering will likely occur. Increase this value if you're experiencing flashing.)\n\nPredictive disabled:\nduration of animation", "skyblocker.config.uiAndVisuals.smoothAOTE.predictive": "Predictive Algorithm", "skyblocker.config.uiAndVisuals.smoothAOTE.predictive.@Tooltip": "Predict where the teleport will end. This will mean there can be no added lag however it is sometimes wrong and can glitch out.", + "skyblocker.config.uiAndVisuals.smoothAOTE.thirdPerson": "Enable 3rd Person", + "skyblocker.config.uiAndVisuals.smoothAOTE.thirdPerson.@Tooltip": "Enables teleport smoothing when in 3rd person modes.", "skyblocker.config.uiAndVisuals.swingOnAbilities": "Swing On Abilities", "skyblocker.config.uiAndVisuals.swingOnAbilities.@Tooltip": "Swings your hand whenever you use an item with a right-click ability.",