mirror of
https://github.com/TeamMidnightDust/MidnightControls.git
synced 2025-12-13 15:25:08 +01:00
- Added #40 (Modded keybind support) - Added #20 (Touchscreen support) - Improved #13 (Sodium screen controller support) - Attempt to fix #31 & #38 (Jittery input on low FPS) - Fixed #35 (Front placing being broken) - Fixed #32 (Option to disable double tap to sprint) - Fixed #27 (Auto-adapt controller icons) - Fixed #19 (HUD-scaling on big scales) - Fixed #36 (Crash on game load) - Fixed reset option - Fixed scrolling in trading screens - Disable features that might be considered as cheats (install MidnightControlsExtra to enable)
166 lines
6.7 KiB
Java
166 lines
6.7 KiB
Java
/*
|
|
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
|
|
*
|
|
* This file is part of midnightcontrols.
|
|
*
|
|
* Licensed under the MIT license. For more information,
|
|
* see the LICENSE file.
|
|
*/
|
|
|
|
package eu.midnightdust.midnightcontrols.client;
|
|
|
|
import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
|
|
import net.minecraft.block.Block;
|
|
import net.minecraft.block.BlockState;
|
|
import net.minecraft.block.FluidBlock;
|
|
import net.minecraft.block.SlabBlock;
|
|
import net.minecraft.client.MinecraftClient;
|
|
import net.minecraft.item.BlockItem;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.util.hit.BlockHitResult;
|
|
import net.minecraft.util.hit.HitResult;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.math.Direction;
|
|
import net.minecraft.util.math.MathHelper;
|
|
import net.minecraft.util.math.Vec3d;
|
|
import net.minecraft.world.RaycastContext;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
/**
|
|
* Represents the reach-around API of midnightcontrols.
|
|
*
|
|
* @version 1.7.0
|
|
* @since 1.3.2
|
|
*/
|
|
public class MidnightReacharound {
|
|
private BlockHitResult lastReacharoundResult = null;
|
|
private boolean lastReacharoundVertical = false;
|
|
private boolean onSlab = false;
|
|
|
|
public void tick(@NotNull MinecraftClient client) {
|
|
this.lastReacharoundResult = this.tryVerticalReachAround(client);
|
|
if (this.lastReacharoundResult == null) {
|
|
this.lastReacharoundResult = this.tryHorizontalReachAround(client);
|
|
this.lastReacharoundVertical = false;
|
|
} else this.lastReacharoundVertical = true;
|
|
}
|
|
|
|
/**
|
|
* Returns the last reach around result.
|
|
*
|
|
* @return the last reach around result
|
|
*/
|
|
public @Nullable BlockHitResult getLastReacharoundResult() {
|
|
return this.lastReacharoundResult;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the last reach around is vertical.
|
|
*
|
|
* @return {@code true} if the reach around is vertical
|
|
*/
|
|
public boolean isLastReacharoundVertical() {
|
|
return this.lastReacharoundVertical;
|
|
}
|
|
|
|
/**
|
|
* Returns whether reacharound is available or not.
|
|
*
|
|
* @return {@code true} if reacharound is available, else {@code false}
|
|
*/
|
|
public boolean isReacharoundAvailable() {
|
|
return MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable() || MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable();
|
|
}
|
|
|
|
private float getPlayerRange(@NotNull MinecraftClient client) {
|
|
return client.interactionManager != null ? client.interactionManager.getReachDistance() : 0.f;
|
|
}
|
|
|
|
/**
|
|
* Returns a nullable block hit result if vertical reach-around is possible.
|
|
*
|
|
* @param client the client instance
|
|
* @return a block hit result if vertical reach-around is possible, else {@code null}
|
|
*/
|
|
public @Nullable BlockHitResult tryVerticalReachAround(@NotNull MinecraftClient client) {
|
|
if (!MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable())
|
|
return null;
|
|
if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.MISS
|
|
|| !client.player.isOnGround() || client.player.getPitch(0.f) < 80.0F
|
|
|| client.player.isRiding())
|
|
return null;
|
|
|
|
Vec3d pos = client.player.getCameraPosVec(1.0F);
|
|
Vec3d rotationVec = client.player.getRotationVec(1.0F);
|
|
float range = getPlayerRange(client);
|
|
var rayVec = pos.add(rotationVec.x * range, rotationVec.y * range, rotationVec.z * range).add(0, 0.75, 0);
|
|
var result = client.world.raycast(new RaycastContext(pos, rayVec, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player));
|
|
|
|
if (result.getType() == HitResult.Type.BLOCK) {
|
|
BlockPos blockPos = result.getBlockPos().down();
|
|
BlockState state = client.world.getBlockState(blockPos);
|
|
|
|
if (client.player.getBlockPos().getY() - blockPos.getY() > 1 && (client.world.isAir(blockPos) || state.getMaterial().isReplaceable())) {
|
|
return new BlockHitResult(result.getPos(), Direction.DOWN, blockPos, false);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns a nullable block hit result if horizontal reach-around is possible.
|
|
*
|
|
* @param client the client instance
|
|
* @return a block hit result if horizontal reach-around is possible
|
|
*/
|
|
public @Nullable BlockHitResult tryHorizontalReachAround(@NotNull MinecraftClient client) {
|
|
if (!MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable())
|
|
return null;
|
|
|
|
if (client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS
|
|
&& client.player.isOnGround() && client.player.getPitch(0.f) > 35.f) {
|
|
if (client.player.isRiding())
|
|
return null;
|
|
var playerPos = client.player.getBlockPos().down();
|
|
if (client.player.getY() - playerPos.getY() - 1.0 >= 0.25) {
|
|
playerPos = playerPos.up();
|
|
this.onSlab = true;
|
|
} else {
|
|
this.onSlab = false;
|
|
}
|
|
var targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
|
|
var vector = new BlockPos.Mutable(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
|
|
var blockPos = playerPos.add(vector);
|
|
|
|
var direction = client.player.getHorizontalFacing();
|
|
|
|
var state = client.world.getBlockState(blockPos);
|
|
if (!state.isAir())
|
|
return null;
|
|
var adjacentBlockState = client.world.getBlockState(blockPos.offset(direction.getOpposite()));
|
|
if (adjacentBlockState.isAir() || adjacentBlockState.getBlock() instanceof FluidBlock || (vector.getX() == 0 && vector.getZ() == 0)) {
|
|
return null;
|
|
}
|
|
|
|
return new BlockHitResult(new Vec3d(blockPos.getX(),blockPos.getY(),blockPos.getZ()), direction, blockPos, false);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public @NotNull BlockHitResult withSideForReacharound(@NotNull BlockHitResult result, @Nullable ItemStack stack) {
|
|
if (stack == null || stack.isEmpty() || !(stack.getItem() instanceof BlockItem))
|
|
return result;
|
|
return withSideForReacharound(result, Block.getBlockFromItem(stack.getItem()));
|
|
}
|
|
|
|
public @NotNull BlockHitResult withSideForReacharound(@NotNull BlockHitResult result, @NotNull Block block) {
|
|
if (block instanceof SlabBlock) {
|
|
if (this.onSlab) result = result.withSide(Direction.UP);
|
|
else result = result.withSide(Direction.DOWN);
|
|
}
|
|
return result;
|
|
}
|
|
}
|