forked from Clones/Controlify
button guide hud
This commit is contained in:
@ -9,6 +9,8 @@ public class ControllerPlayerMovement extends Input {
|
||||
private final Controller controller;
|
||||
private final LocalPlayer player;
|
||||
|
||||
private boolean shiftToggled = false;
|
||||
|
||||
public ControllerPlayerMovement(Controller controller, LocalPlayer player) {
|
||||
this.controller = controller;
|
||||
this.player = player;
|
||||
@ -16,7 +18,7 @@ public class ControllerPlayerMovement extends Input {
|
||||
|
||||
@Override
|
||||
public void tick(boolean slowDown, float f) {
|
||||
if (Minecraft.getInstance().screen != null) {
|
||||
if (Minecraft.getInstance().screen != null || player == null) {
|
||||
this.up = false;
|
||||
this.down = false;
|
||||
this.left = false;
|
||||
@ -46,12 +48,10 @@ public class ControllerPlayerMovement extends Input {
|
||||
|
||||
this.jumping = bindings.JUMP.held();
|
||||
|
||||
if (player.getAbilities().flying || !controller.config().toggleSneak) {
|
||||
if (player.getAbilities().flying || player.isInWater() || !controller.config().toggleSneak) {
|
||||
this.shiftKeyDown = bindings.SNEAK.held();
|
||||
} else {
|
||||
if (bindings.SNEAK.justPressed()) {
|
||||
this.shiftKeyDown = !this.shiftKeyDown;
|
||||
}
|
||||
this.shiftKeyDown = Minecraft.getInstance().options.keyShift.isDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,6 @@ public class InGameInputHandler {
|
||||
private final Controller controller;
|
||||
private final Minecraft minecraft;
|
||||
|
||||
private final Input controllerInput, keyboardInput;
|
||||
|
||||
private double accumulatedDX, accumulatedDY;
|
||||
private double deltaTime;
|
||||
|
||||
@ -21,14 +19,11 @@ public class InGameInputHandler {
|
||||
this.controller = controller;
|
||||
this.minecraft = Minecraft.getInstance();
|
||||
|
||||
this.controllerInput = new ControllerPlayerMovement(controller, minecraft.player);
|
||||
this.keyboardInput = new KeyboardInput(minecraft.options);
|
||||
|
||||
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> {
|
||||
if (minecraft.player != null) {
|
||||
minecraft.player.input = mode == InputMode.CONTROLLER
|
||||
? this.controllerInput
|
||||
: this.keyboardInput;
|
||||
? new ControllerPlayerMovement(controller, minecraft.player)
|
||||
: new KeyboardInput(minecraft.options);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -53,13 +48,16 @@ public class InGameInputHandler {
|
||||
minecraft.player.getInventory().swapPaint(1);
|
||||
}
|
||||
}
|
||||
if (controller.bindings().TOGGLE_HUD_VISIBILITY.justPressed()) {
|
||||
minecraft.options.hideGui = !minecraft.options.hideGui;
|
||||
}
|
||||
}
|
||||
|
||||
protected void handlePlayerLookInput() {
|
||||
var axes = controller.state().axes();
|
||||
if (minecraft.mouseHandler.isMouseGrabbed() && minecraft.isWindowActive()) {
|
||||
accumulatedDX += axes.rightStickX();
|
||||
accumulatedDY += axes.rightStickY();
|
||||
accumulatedDX += axes.rightStickX() * Math.abs(axes.rightStickX());
|
||||
accumulatedDY += axes.rightStickY() * Math.abs(axes.rightStickY());
|
||||
}
|
||||
|
||||
processPlayerLook();
|
||||
|
@ -0,0 +1,5 @@
|
||||
package dev.isxander.controlify.ingame.guide;
|
||||
|
||||
public enum ActionLocation {
|
||||
LEFT, RIGHT
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package dev.isxander.controlify.ingame.guide;
|
||||
|
||||
public enum ActionPriority {
|
||||
LOWEST,
|
||||
LOW,
|
||||
NORMAL,
|
||||
HIGH,
|
||||
HIGHEST
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package dev.isxander.controlify.ingame.guide;
|
||||
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ButtonActionSupplier {
|
||||
Optional<GuideAction> supply(Minecraft client, LocalPlayer player, ClientLevel level, HitResult hitResult, Controller controller);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package dev.isxander.controlify.ingame.guide;
|
||||
|
||||
public interface ButtonGuideRegistry {
|
||||
void registerGuideAction(ButtonActionSupplier supplier);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package dev.isxander.controlify.ingame.guide;
|
||||
|
||||
import dev.isxander.controlify.bindings.ControllerBinding;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public record GuideAction(ControllerBinding binding, Component name, ActionLocation location,
|
||||
ActionPriority priority) implements Comparable<GuideAction> {
|
||||
public GuideAction(ControllerBinding binding, Component name, ActionLocation location) {
|
||||
this(binding, name, location, ActionPriority.NORMAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull GuideAction o) {
|
||||
return this.priority().compareTo(o.priority());
|
||||
}
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
package dev.isxander.controlify.ingame.guide;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.event.ControlifyEvents;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.projectile.ProjectileUtil;
|
||||
import net.minecraft.world.item.ElytraItem;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.phys.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class InGameButtonGuide implements ButtonGuideRegistry {
|
||||
private final Controller controller;
|
||||
private final LocalPlayer player;
|
||||
private final Minecraft minecraft = Minecraft.getInstance();
|
||||
|
||||
private final List<ButtonActionSupplier> guidePredicates = new ArrayList<>();
|
||||
|
||||
private final List<GuideAction> leftGuides = new ArrayList<>();
|
||||
private final List<GuideAction> rightGuides = new ArrayList<>();
|
||||
|
||||
public InGameButtonGuide(Controller controller, LocalPlayer localPlayer) {
|
||||
this.controller = controller;
|
||||
this.player = localPlayer;
|
||||
|
||||
registerDefaultActions();
|
||||
ControlifyEvents.BUTTON_GUIDE_REGISTRY.invoker().onRegisterButtonGuide(this);
|
||||
}
|
||||
|
||||
public void renderHud(PoseStack poseStack, float tickDelta, int width, int height) {
|
||||
if (!controller.config().showGuide || minecraft.screen != null)
|
||||
return;
|
||||
|
||||
{
|
||||
var offset = 0;
|
||||
for (var action : leftGuides) {
|
||||
var bind = action.binding().currentBind();
|
||||
|
||||
var drawSize = bind.drawSize();
|
||||
if (offset == 0) offset += drawSize.height() / 2;
|
||||
|
||||
int x = 4;
|
||||
int y = 3 + offset;
|
||||
|
||||
bind.draw(poseStack, x, y, controller);
|
||||
|
||||
int textX = x + drawSize.width() + 2;
|
||||
int textY = y - minecraft.font.lineHeight / 2;
|
||||
GuiComponent.fill(poseStack, textX - 1, textY - 1, textX + minecraft.font.width(action.name()) + 1, textY + minecraft.font.lineHeight + 1, 0x80000000);
|
||||
minecraft.font.draw(poseStack, action.name(), textX, textY, 0xFFFFFF);
|
||||
|
||||
offset += drawSize.height() + 2;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var offset = 0;
|
||||
for (var action : rightGuides) {
|
||||
var bind = action.binding().currentBind();
|
||||
|
||||
var drawSize = bind.drawSize();
|
||||
if (offset == 0) offset += drawSize.height() / 2;
|
||||
|
||||
int x = width - 4 - drawSize.width();
|
||||
int y = 3 + offset;
|
||||
|
||||
bind.draw(poseStack, x, y, controller);
|
||||
|
||||
int textX = x - minecraft.font.width(action.name()) - 2;
|
||||
int textY = y - minecraft.font.lineHeight / 2;
|
||||
GuiComponent.fill(poseStack, textX - 1, textY - 1, textX + minecraft.font.width(action.name()) + 1, textY + minecraft.font.lineHeight + 1, 0x80000000);
|
||||
minecraft.font.draw(poseStack, action.name(), textX, textY, 0xFFFFFF);
|
||||
|
||||
offset += drawSize.height() + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
leftGuides.clear();
|
||||
rightGuides.clear();
|
||||
|
||||
if (!controller.config().showGuide)
|
||||
return;
|
||||
|
||||
for (var actionPredicate : guidePredicates) {
|
||||
var action = actionPredicate.supply(Minecraft.getInstance(), player, minecraft.level, calculateHitResult(), controller);
|
||||
if (action.isPresent()) {
|
||||
if (action.get().location() == ActionLocation.LEFT)
|
||||
leftGuides.add(action.get());
|
||||
else
|
||||
rightGuides.add(action.get());
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(leftGuides);
|
||||
Collections.sort(rightGuides);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGuideAction(ButtonActionSupplier supplier) {
|
||||
guidePredicates.add(supplier);
|
||||
}
|
||||
|
||||
private void registerDefaultActions() {
|
||||
registerGuideAction((client, player, level, hitResult, controller) -> {
|
||||
if (player.getAbilities().flying)
|
||||
return Optional.of(new GuideAction(controller.bindings().JUMP, Component.translatable("controlify.guide.fly_up"), ActionLocation.LEFT));
|
||||
|
||||
if (player.isOnGround())
|
||||
return Optional.of(new GuideAction(controller.bindings().JUMP, Component.translatable("key.jump"), ActionLocation.LEFT));
|
||||
|
||||
if (player.isInWater())
|
||||
return Optional.of(new GuideAction(controller.bindings().JUMP, Component.translatable("controlify.guide.swim_up"), ActionLocation.LEFT));
|
||||
|
||||
if (!player.isOnGround() && !player.isFallFlying() && !player.isInWater() && !player.hasEffect(MobEffects.LEVITATION)) {
|
||||
var chestStack = player.getItemBySlot(EquipmentSlot.CHEST);
|
||||
if (chestStack.is(Items.ELYTRA) && ElytraItem.isFlyEnabled(chestStack))
|
||||
return Optional.of(new GuideAction(controller.bindings().JUMP, Component.translatable("controlify.guide.start_elytra"), ActionLocation.LEFT));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
});
|
||||
registerGuideAction((client, player, level, hitResult, controller) -> {
|
||||
if (player.getVehicle() != null)
|
||||
return Optional.of(new GuideAction(controller.bindings().SNEAK, Component.translatable("controlify.guide.dismount"), ActionLocation.LEFT));
|
||||
if (player.getAbilities().flying)
|
||||
return Optional.of(new GuideAction(controller.bindings().SNEAK, Component.translatable("controlify.guide.fly_down"), ActionLocation.LEFT));
|
||||
if (player.isInWater())
|
||||
return Optional.of(new GuideAction(controller.bindings().SNEAK, Component.translatable("controlify.guide.swim_down"), ActionLocation.LEFT));
|
||||
if (controller.config().toggleSneak) {
|
||||
if (player.input.shiftKeyDown)
|
||||
return Optional.of(new GuideAction(controller.bindings().SNEAK, Component.translatable("controlify.guide.stop_sneaking"), ActionLocation.LEFT));
|
||||
else
|
||||
return Optional.of(new GuideAction(controller.bindings().SNEAK, Component.translatable("controlify.guide.start_sneaking"), ActionLocation.LEFT));
|
||||
} else {
|
||||
if (!player.input.shiftKeyDown)
|
||||
return Optional.of(new GuideAction(controller.bindings().SNEAK, Component.translatable("controlify.guide.sneak"), ActionLocation.LEFT));
|
||||
}
|
||||
return Optional.empty();
|
||||
});
|
||||
registerGuideAction((client, player, level, hitResult, controller) -> {
|
||||
if (client.screen == null)
|
||||
return Optional.of(new GuideAction(controller.bindings().INVENTORY, Component.translatable("controlify.guide.inventory"), ActionLocation.RIGHT));
|
||||
return Optional.empty();
|
||||
});
|
||||
registerGuideAction((client, player, level, hitResult, controller) -> {
|
||||
if (hitResult.getType() == HitResult.Type.ENTITY)
|
||||
return Optional.of(new GuideAction(controller.bindings().ATTACK, Component.translatable("controlify.guide.attack"), ActionLocation.RIGHT));
|
||||
if (hitResult.getType() == HitResult.Type.BLOCK)
|
||||
return Optional.of(new GuideAction(controller.bindings().ATTACK, Component.translatable("controlify.guide.break"), ActionLocation.RIGHT));
|
||||
return Optional.empty();
|
||||
});
|
||||
registerGuideAction((client, player, level, hitResult, controller) -> {
|
||||
if (hitResult.getType() == HitResult.Type.ENTITY)
|
||||
return Optional.of(new GuideAction(controller.bindings().USE, Component.translatable("controlify.guide.interact"), ActionLocation.RIGHT));
|
||||
if (hitResult.getType() == HitResult.Type.BLOCK || player.hasItemInSlot(EquipmentSlot.MAINHAND) || player.hasItemInSlot(EquipmentSlot.OFFHAND))
|
||||
return Optional.of(new GuideAction(controller.bindings().USE, Component.translatable("controlify.guide.use"), ActionLocation.RIGHT));
|
||||
return Optional.empty();
|
||||
});
|
||||
registerGuideAction((client, player, level, hitResult, controller) -> {
|
||||
if (player.hasItemInSlot(EquipmentSlot.MAINHAND) || player.hasItemInSlot(EquipmentSlot.OFFHAND))
|
||||
return Optional.of(new GuideAction(controller.bindings().DROP, Component.translatable("controlify.guide.drop"), ActionLocation.RIGHT));
|
||||
return Optional.empty();
|
||||
});
|
||||
registerGuideAction((client, player, level, hitResult, controller) -> {
|
||||
if (hitResult.getType() == HitResult.Type.BLOCK && player.isCreative())
|
||||
return Optional.of(new GuideAction(controller.bindings().PICK_BLOCK, Component.translatable("controlify.guide.pick_block"), ActionLocation.RIGHT));
|
||||
return Optional.empty();
|
||||
});
|
||||
}
|
||||
|
||||
private HitResult calculateHitResult() {
|
||||
double pickRange = minecraft.gameMode.getPickRange();
|
||||
HitResult pickResult = player.pick(pickRange, 1f, false);
|
||||
|
||||
Vec3 eyePos = player.getEyePosition(1f);
|
||||
|
||||
if (minecraft.gameMode.hasFarPickRange()) {
|
||||
pickRange = 6.0;
|
||||
}
|
||||
double maxPickRange = pickResult.getLocation().distanceToSqr(eyePos);
|
||||
|
||||
Vec3 viewVec = player.getViewVector(1f);
|
||||
Vec3 reachVec = eyePos.add(viewVec.x * pickRange, viewVec.y * pickRange, viewVec.z * pickRange);
|
||||
AABB box = player.getBoundingBox().expandTowards(viewVec.scale(pickRange)).inflate(1d, 1d, 1d);
|
||||
|
||||
EntityHitResult entityHitResult = ProjectileUtil.getEntityHitResult(
|
||||
player, eyePos, reachVec, box, (entity) -> !entity.isSpectator() && entity.isPickable(), maxPickRange
|
||||
);
|
||||
|
||||
if (entityHitResult != null && entityHitResult.getLocation().distanceToSqr(eyePos) < pickResult.getLocation().distanceToSqr(eyePos)) {
|
||||
return entityHitResult;
|
||||
} else {
|
||||
return pickResult;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user