forked from Clones/Controlify
reach-around
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
package dev.isxander.controlify.config;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import dev.isxander.controlify.reacharound.ReachAroundMode;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
|
||||
import java.util.List;
|
||||
@ -14,4 +15,5 @@ public class GlobalSettings {
|
||||
|
||||
public boolean keyboardMovement = false;
|
||||
public boolean outOfFocusInput = false;
|
||||
public ReachAroundMode reachAround = ReachAroundMode.OFF;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import dev.isxander.controlify.controller.joystick.JoystickController;
|
||||
import dev.isxander.controlify.controller.joystick.SingleJoystickController;
|
||||
import dev.isxander.controlify.controller.joystick.JoystickState;
|
||||
import dev.isxander.controlify.gui.screen.ControllerDeadzoneCalibrationScreen;
|
||||
import dev.isxander.controlify.reacharound.ReachAroundMode;
|
||||
import dev.isxander.yacl.api.*;
|
||||
import dev.isxander.yacl.gui.controllers.ActionController;
|
||||
import dev.isxander.yacl.gui.controllers.BooleanController;
|
||||
@ -53,7 +54,14 @@ public class YACLHelper {
|
||||
.tooltip(Component.translatable("controlify.gui.current_controller.tooltip"))
|
||||
.binding(Controlify.instance().currentController(), () -> Controlify.instance().currentController(), v -> Controlify.instance().setCurrentController(v))
|
||||
.controller(opt -> new CyclingListController<>(opt, Iterables.concat(List.of(Controller.DUMMY), Controller.CONTROLLERS.values().stream().filter(Controller::canBeUsed).toList()), c -> Component.literal(c == Controller.DUMMY ? "Disabled" : c.name())))
|
||||
.instant(true)
|
||||
.build())
|
||||
.option(Option.createBuilder(ReachAroundMode.class)
|
||||
.name(Component.translatable("controlify.gui.reach_around"))
|
||||
.tooltip(Component.translatable("controlify.gui.reach_around.tooltip"))
|
||||
.tooltip(Component.translatable("controlify.gui.reach_around.tooltip.parity").withStyle(ChatFormatting.GRAY))
|
||||
.tooltip(state -> state == ReachAroundMode.EVERYWHERE ? Component.translatable("controlify.gui.reach_around.tooltip.warning").withStyle(ChatFormatting.RED) : Component.empty())
|
||||
.binding(GlobalSettings.DEFAULT.reachAround, () -> globalSettings.reachAround, v -> globalSettings.reachAround = v)
|
||||
.controller(EnumController::new)
|
||||
.build())
|
||||
.option(Option.createBuilder(boolean.class)
|
||||
.name(Component.translatable("controlify.gui.out_of_focus_input"))
|
||||
|
@ -0,0 +1,21 @@
|
||||
package dev.isxander.controlify.mixins.feature.reacharound;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import dev.isxander.controlify.reacharound.ReachAroundHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@Mixin(GameRenderer.class)
|
||||
public class GameRendererMixin {
|
||||
@Shadow @Final Minecraft minecraft;
|
||||
|
||||
@ModifyExpressionValue(method = "pick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;pick(DFZ)Lnet/minecraft/world/phys/HitResult;"))
|
||||
private HitResult modifyPick(HitResult hitResult) {
|
||||
return ReachAroundHandler.getReachAroundHitResult(minecraft.getCameraEntity(), hitResult);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package dev.isxander.controlify.reacharound;
|
||||
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
public class ReachAroundHandler {
|
||||
public static HitResult getReachAroundHitResult(Entity entity, HitResult hitResult) {
|
||||
// if there is already a valid hit, we don't want to override it
|
||||
if (hitResult.getType() != HitResult.Type.MISS)
|
||||
return hitResult;
|
||||
|
||||
if (!canReachAround(entity))
|
||||
return hitResult;
|
||||
|
||||
// LivingEntity#playBlockFallSound - this is the location where the game determines the footstep noise
|
||||
// maybe experiment on different values rather than 0.2f from other areas in the game?
|
||||
int x = Mth.floor(entity.getX());
|
||||
int y = Mth.floor(entity.getY() - 0.2F);
|
||||
int z = Mth.floor(entity.getZ());
|
||||
var floorPos = new BlockPos(x, y, z);
|
||||
|
||||
// this allows all interaction with blocks, such as opening containers, ringing bells, etc.
|
||||
// this is consistent with bedrock edition behaviour, tested
|
||||
return new BlockHitResult(floorPos.getCenter(), entity.getDirection(), floorPos, false);
|
||||
}
|
||||
|
||||
private static boolean canReachAround(Entity cameraEntity) {
|
||||
return // don't want to place blocks while riding an entity
|
||||
cameraEntity.getVehicle() == null
|
||||
// straight ahead = 0deg, up = -90deg, down = 90deg
|
||||
// 45deg and above is half between straight ahead and down, must be lower or equal to this threshold
|
||||
&& cameraEntity.getXRot() >= 45
|
||||
// if the player is not standing on a block, this is inappropriate
|
||||
// this also prevents selecting fluids as a valid position
|
||||
&& cameraEntity.isOnGround()
|
||||
// must respect config option
|
||||
&& Controlify.instance().config().globalSettings().reachAround.canReachAround();
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package dev.isxander.controlify.reacharound;
|
||||
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.yacl.api.NameableEnum;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public enum ReachAroundMode implements NameableEnum {
|
||||
OFF((minecraft, controlify) -> false),
|
||||
SINGLEPLAYER_ONLY((minecraft, controlify) -> minecraft.isSingleplayer()),
|
||||
SINGLEPLAYER_AND_LAN((minecraft, controlify) -> minecraft.isLocalServer()),
|
||||
EVERYWHERE((minecraft, controlify) -> true);
|
||||
|
||||
private final BiFunction<Minecraft, Controlify, Boolean> canReachAround;
|
||||
private final Component displayName;
|
||||
|
||||
ReachAroundMode(BiFunction<Minecraft, Controlify, Boolean> canReachAround) {
|
||||
this.canReachAround = canReachAround;
|
||||
this.displayName = Component.translatable("controlify.reach_around." + this.name().toLowerCase());
|
||||
}
|
||||
|
||||
public boolean canReachAround() {
|
||||
return canReachAround.apply(Minecraft.getInstance(), Controlify.instance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user