1
0
forked from Clones/Controlify

button guide hud

This commit is contained in:
isXander
2023-02-09 23:08:28 +00:00
parent ab801e37b4
commit 773aebe04e
60 changed files with 566 additions and 154 deletions

View File

@ -1,12 +1,13 @@
package dev.isxander.controlify; package dev.isxander.controlify;
import com.mojang.logging.LogUtils; import com.mojang.logging.LogUtils;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.config.ControlifyConfig; import dev.isxander.controlify.config.ControlifyConfig;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerState; import dev.isxander.controlify.controller.ControllerState;
import dev.isxander.controlify.controller.hid.ControllerHIDService; import dev.isxander.controlify.controller.hid.ControllerHIDService;
import dev.isxander.controlify.event.ControlifyEvents; import dev.isxander.controlify.event.ControlifyEvents;
import dev.isxander.controlify.ingame.guide.InGameButtonGuide;
import dev.isxander.controlify.ingame.InGameInputHandler; import dev.isxander.controlify.ingame.InGameInputHandler;
import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor; import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor;
import dev.isxander.controlify.virtualmouse.VirtualMouseHandler; import dev.isxander.controlify.virtualmouse.VirtualMouseHandler;
@ -23,6 +24,7 @@ public class Controlify {
private Controller currentController; private Controller currentController;
private InGameInputHandler inGameInputHandler; private InGameInputHandler inGameInputHandler;
public InGameButtonGuide inGameButtonGuide;
private VirtualMouseHandler virtualMouseHandler; private VirtualMouseHandler virtualMouseHandler;
private InputMode currentInputMode; private InputMode currentInputMode;
private ControllerHIDService controllerHIDService; private ControllerHIDService controllerHIDService;
@ -131,12 +133,19 @@ public class Controlify {
this.currentController = controller; this.currentController = controller;
this.inGameInputHandler = new InGameInputHandler(this.currentController != null ? controller : Controller.DUMMY); this.inGameInputHandler = new InGameInputHandler(this.currentController != null ? controller : Controller.DUMMY);
if (Minecraft.getInstance().player != null) {
this.inGameButtonGuide = new InGameButtonGuide(this.currentController != null ? controller : Controller.DUMMY, Minecraft.getInstance().player);
}
} }
public InGameInputHandler inGameInputHandler() { public InGameInputHandler inGameInputHandler() {
return inGameInputHandler; return inGameInputHandler;
} }
public InGameButtonGuide inGameButtonGuide() {
return inGameButtonGuide;
}
public VirtualMouseHandler virtualMouseHandler() { public VirtualMouseHandler virtualMouseHandler() {
return virtualMouseHandler; return virtualMouseHandler;
} }
@ -155,6 +164,12 @@ public class Controlify {
if (minecraft.screen != null) { if (minecraft.screen != null) {
ScreenProcessorProvider.provide(minecraft.screen).onInputModeChanged(currentInputMode); ScreenProcessorProvider.provide(minecraft.screen).onInputModeChanged(currentInputMode);
} }
if (Minecraft.getInstance().player != null) {
if (currentInputMode == InputMode.KEYBOARD_MOUSE)
this.inGameButtonGuide = null;
else
this.inGameButtonGuide = new InGameButtonGuide(this.currentController != null ? currentController : Controller.DUMMY, Minecraft.getInstance().player);
}
ControlifyEvents.INPUT_MODE_CHANGED.invoker().onInputModeChanged(currentInputMode); ControlifyEvents.INPUT_MODE_CHANGED.invoker().onInputModeChanged(currentInputMode);
} }

View File

@ -36,7 +36,8 @@ public enum Bind implements IBind {
RIGHT_STICK_FORWARD((state, controller) -> -Math.min(0, state.axes().rightStickY()), "right_stick_up"), RIGHT_STICK_FORWARD((state, controller) -> -Math.min(0, state.axes().rightStickY()), "right_stick_up"),
RIGHT_STICK_BACKWARD((state, controller) -> Math.max(0, state.axes().rightStickY()), "right_stick_down"), RIGHT_STICK_BACKWARD((state, controller) -> Math.max(0, state.axes().rightStickY()), "right_stick_down"),
RIGHT_STICK_LEFT((state, controller) -> -Math.min(0, state.axes().rightStickX()), "right_stick_left"), RIGHT_STICK_LEFT((state, controller) -> -Math.min(0, state.axes().rightStickX()), "right_stick_left"),
RIGHT_STICK_RIGHT((state, controller) -> Math.max(0, state.axes().rightStickX()), "right_stick_right"); RIGHT_STICK_RIGHT((state, controller) -> Math.max(0, state.axes().rightStickX()), "right_stick_right"),
NONE((state, controller) -> 0f, "none");
private final BiFunction<ControllerState, Controller, Float> state; private final BiFunction<ControllerState, Controller, Float> state;
private final String identifier; private final String identifier;
@ -57,11 +58,14 @@ public enum Bind implements IBind {
@Override @Override
public void draw(PoseStack matrices, int x, int centerY, Controller controller) { public void draw(PoseStack matrices, int x, int centerY, Controller controller) {
if (this != NONE)
ButtonRenderer.drawButton(this, controller, matrices, x, centerY); ButtonRenderer.drawButton(this, controller, matrices, x, centerY);
} }
@Override @Override
public ButtonRenderer.DrawSize drawSize() { public ButtonRenderer.DrawSize drawSize() {
if (this == NONE) return new ButtonRenderer.DrawSize(0, 0);
return new ButtonRenderer.DrawSize(22, 22); return new ButtonRenderer.DrawSize(22, 22);
} }

View File

@ -18,6 +18,7 @@ public class CompoundBind implements IBind {
CompoundBind(Bind... binds) { CompoundBind(Bind... binds) {
this.binds = new LinkedHashSet<>(Arrays.asList(binds)); this.binds = new LinkedHashSet<>(Arrays.asList(binds));
if (this.binds.contains(Bind.NONE)) throw new IllegalArgumentException("Cannot have NONE in a compound bind!");
} }
public Set<Bind> binds() { public Set<Bind> binds() {

View File

@ -27,7 +27,9 @@ public class ControllerBindings {
GUI_PRESS, GUI_BACK, GUI_PRESS, GUI_BACK,
GUI_NEXT_TAB, GUI_PREV_TAB, GUI_NEXT_TAB, GUI_PREV_TAB,
VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_MCLICK, VMOUSE_SCROLL_UP, VMOUSE_SCROLL_DOWN, VMOUSE_ESCAPE, VMOUSE_SHIFT, VMOUSE_TOGGLE, VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_MCLICK, VMOUSE_SCROLL_UP, VMOUSE_SCROLL_DOWN, VMOUSE_ESCAPE, VMOUSE_SHIFT, VMOUSE_TOGGLE,
PICK_BLOCK; PICK_BLOCK,
TOGGLE_HUD_VISIBILITY,
SHOW_PLAYER_LIST;
private final Map<ResourceLocation, ControllerBinding> registry = new LinkedHashMap<>(); private final Map<ResourceLocation, ControllerBinding> registry = new LinkedHashMap<>();
@ -57,6 +59,9 @@ public class ControllerBindings {
register(GUI_BACK = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "gui_back"))); register(GUI_BACK = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "gui_back")));
register(GUI_NEXT_TAB = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "gui_next_tab"))); register(GUI_NEXT_TAB = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "gui_next_tab")));
register(GUI_PREV_TAB = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "gui_prev_tab"))); register(GUI_PREV_TAB = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "gui_prev_tab")));
register(PICK_BLOCK = new ControllerBinding(controller, Bind.DPAD_LEFT, new ResourceLocation("controlify", "pick_block"), options.keyPickItem, () -> false));
register(TOGGLE_HUD_VISIBILITY = new ControllerBinding(controller, Bind.NONE, new ResourceLocation("controlify", "toggle_hud_visibility")));
register(SHOW_PLAYER_LIST = new ControllerBinding(controller, Bind.DPAD_RIGHT, new ResourceLocation("controlify", "show_player_list"), options.keyPlayerList, () -> false));
register(VMOUSE_LCLICK = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "vmouse_lclick"))); register(VMOUSE_LCLICK = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "vmouse_lclick")));
register(VMOUSE_RCLICK = new ControllerBinding(controller, Bind.X_BUTTON, new ResourceLocation("controlify", "vmouse_rclick"))); register(VMOUSE_RCLICK = new ControllerBinding(controller, Bind.X_BUTTON, new ResourceLocation("controlify", "vmouse_rclick")));
register(VMOUSE_MCLICK = new ControllerBinding(controller, Bind.Y_BUTTON, new ResourceLocation("controlify", "vmouse_mclick"))); register(VMOUSE_MCLICK = new ControllerBinding(controller, Bind.Y_BUTTON, new ResourceLocation("controlify", "vmouse_mclick")));
@ -65,7 +70,6 @@ public class ControllerBindings {
register(VMOUSE_ESCAPE = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "vmouse_escape"))); register(VMOUSE_ESCAPE = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "vmouse_escape")));
register(VMOUSE_SHIFT = new ControllerBinding(controller, Bind.LEFT_STICK_PRESS, new ResourceLocation("controlify", "vmouse_shift"))); register(VMOUSE_SHIFT = new ControllerBinding(controller, Bind.LEFT_STICK_PRESS, new ResourceLocation("controlify", "vmouse_shift")));
register(VMOUSE_TOGGLE = new ControllerBinding(controller, Bind.BACK, new ResourceLocation("controlify", "vmouse_toggle"))); register(VMOUSE_TOGGLE = new ControllerBinding(controller, Bind.BACK, new ResourceLocation("controlify", "vmouse_toggle")));
register(PICK_BLOCK = new ControllerBinding(controller, Bind.DPAD_LEFT, new ResourceLocation("controlify", "pick_block"), options.keyPickItem, () -> false));
ControlifyEvents.CONTROLLER_BIND_REGISTRY.invoker().onRegisterControllerBinds(this, controller); ControlifyEvents.CONTROLLER_BIND_REGISTRY.invoker().onRegisterControllerBinds(this, controller);

View File

@ -3,11 +3,9 @@ package dev.isxander.controlify.config.gui;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.bindings.Bind; import dev.isxander.controlify.bindings.Bind;
import dev.isxander.controlify.bindings.IBind; import dev.isxander.controlify.bindings.IBind;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.event.ControlifyEvents;
import dev.isxander.controlify.gui.ButtonRenderer;
import dev.isxander.yacl.api.Controller; import dev.isxander.yacl.api.Controller;
import dev.isxander.yacl.api.Option; import dev.isxander.yacl.api.Option;
import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.api.utils.Dimension;
@ -18,7 +16,6 @@ import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.util.HashSet;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
@ -113,9 +110,18 @@ public class BindButtonController implements Controller<IBind> {
} else { } else {
for (var bind : Bind.values()) { for (var bind : Bind.values()) {
if (bind.held(controller.state(), controller) && !bind.held(controller.prevState(), controller)) { if (bind.held(controller.state(), controller) && !bind.held(controller.prevState(), controller)) {
if (bind == Bind.GUIDE) { // FIXME: guide cannot be used as reserve because Windows hooks into xbox button to open game bar, maybe START?
if (pressedBinds.isEmpty()) {
awaitingControllerInput = false;
control.option().requestSet(IBind.create(Bind.NONE));
pressedBinds.clear();
return true;
}
} else {
pressedBinds.add(bind); pressedBinds.add(bind);
} }
} }
}
control.controller.consumeButtonState(); control.controller.consumeButtonState();
} }

View File

@ -96,6 +96,12 @@ public class YACLHelper {
.binding(def.toggleSneak, () -> config.toggleSneak, v -> config.toggleSneak = v) .binding(def.toggleSneak, () -> config.toggleSneak, v -> config.toggleSneak = v)
.controller(opt -> new BooleanController(opt, v -> Component.translatable("controlify.gui.format.hold_toggle." + (v ? "toggle" : "hold")), false)) .controller(opt -> new BooleanController(opt, v -> Component.translatable("controlify.gui.format.hold_toggle." + (v ? "toggle" : "hold")), false))
.build()) .build())
.option(Option.createBuilder(boolean.class)
.name(Component.translatable("controlify.gui.show_guide"))
.tooltip(Component.translatable("controlify.gui.show_guide.tooltip"))
.binding(def.showGuide, () -> config.showGuide, v -> config.showGuide = v)
.controller(TickBoxController::new)
.build())
.option(Option.createBuilder(float.class) .option(Option.createBuilder(float.class)
.name(Component.translatable("controlify.gui.vmouse_sensitivity")) .name(Component.translatable("controlify.gui.vmouse_sensitivity"))
.tooltip(Component.translatable("controlify.gui.vmouse_sensitivity.tooltip")) .tooltip(Component.translatable("controlify.gui.vmouse_sensitivity.tooltip"))

View File

@ -182,5 +182,7 @@ public final class Controller {
public boolean toggleSneak = true; public boolean toggleSneak = true;
public String customName = null; public String customName = null;
public boolean showGuide = true;
} }
} }

View File

@ -3,6 +3,7 @@ package dev.isxander.controlify.event;
import dev.isxander.controlify.InputMode; import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.bindings.ControllerBindings; import dev.isxander.controlify.bindings.ControllerBindings;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.ingame.guide.ButtonGuideRegistry;
import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory; import net.fabricmc.fabric.api.event.EventFactory;
@ -25,6 +26,12 @@ public class ControlifyEvents {
} }
}); });
public static final Event<ButtonGuideRegistryEvent> BUTTON_GUIDE_REGISTRY = EventFactory.createArrayBacked(ButtonGuideRegistryEvent.class, callbacks -> registry -> {
for (ButtonGuideRegistryEvent callback : callbacks) {
callback.onRegisterButtonGuide(registry);
}
});
public static final Event<VirtualMouseToggled> VIRTUAL_MOUSE_TOGGLED = EventFactory.createArrayBacked(VirtualMouseToggled.class, callbacks -> enabled -> { public static final Event<VirtualMouseToggled> VIRTUAL_MOUSE_TOGGLED = EventFactory.createArrayBacked(VirtualMouseToggled.class, callbacks -> enabled -> {
for (VirtualMouseToggled callback : callbacks) { for (VirtualMouseToggled callback : callbacks) {
callback.onVirtualMouseToggled(enabled); callback.onVirtualMouseToggled(enabled);
@ -46,6 +53,11 @@ public class ControlifyEvents {
void onRegisterControllerBinds(ControllerBindings bindings, Controller controller); void onRegisterControllerBinds(ControllerBindings bindings, Controller controller);
} }
@FunctionalInterface
public interface ButtonGuideRegistryEvent {
void onRegisterButtonGuide(ButtonGuideRegistry registry);
}
@FunctionalInterface @FunctionalInterface
public interface VirtualMouseToggled { public interface VirtualMouseToggled {
void onVirtualMouseToggled(boolean enabled); void onVirtualMouseToggled(boolean enabled);

View File

@ -9,6 +9,8 @@ public class ControllerPlayerMovement extends Input {
private final Controller controller; private final Controller controller;
private final LocalPlayer player; private final LocalPlayer player;
private boolean shiftToggled = false;
public ControllerPlayerMovement(Controller controller, LocalPlayer player) { public ControllerPlayerMovement(Controller controller, LocalPlayer player) {
this.controller = controller; this.controller = controller;
this.player = player; this.player = player;
@ -16,7 +18,7 @@ public class ControllerPlayerMovement extends Input {
@Override @Override
public void tick(boolean slowDown, float f) { public void tick(boolean slowDown, float f) {
if (Minecraft.getInstance().screen != null) { if (Minecraft.getInstance().screen != null || player == null) {
this.up = false; this.up = false;
this.down = false; this.down = false;
this.left = false; this.left = false;
@ -46,12 +48,10 @@ public class ControllerPlayerMovement extends Input {
this.jumping = bindings.JUMP.held(); 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(); this.shiftKeyDown = bindings.SNEAK.held();
} else { } else {
if (bindings.SNEAK.justPressed()) { this.shiftKeyDown = Minecraft.getInstance().options.keyShift.isDown();
this.shiftKeyDown = !this.shiftKeyDown;
}
} }
} }
} }

View File

@ -12,8 +12,6 @@ public class InGameInputHandler {
private final Controller controller; private final Controller controller;
private final Minecraft minecraft; private final Minecraft minecraft;
private final Input controllerInput, keyboardInput;
private double accumulatedDX, accumulatedDY; private double accumulatedDX, accumulatedDY;
private double deltaTime; private double deltaTime;
@ -21,14 +19,11 @@ public class InGameInputHandler {
this.controller = controller; this.controller = controller;
this.minecraft = Minecraft.getInstance(); this.minecraft = Minecraft.getInstance();
this.controllerInput = new ControllerPlayerMovement(controller, minecraft.player);
this.keyboardInput = new KeyboardInput(minecraft.options);
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> { ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> {
if (minecraft.player != null) { if (minecraft.player != null) {
minecraft.player.input = mode == InputMode.CONTROLLER minecraft.player.input = mode == InputMode.CONTROLLER
? this.controllerInput ? new ControllerPlayerMovement(controller, minecraft.player)
: this.keyboardInput; : new KeyboardInput(minecraft.options);
} }
}); });
} }
@ -53,13 +48,16 @@ public class InGameInputHandler {
minecraft.player.getInventory().swapPaint(1); minecraft.player.getInventory().swapPaint(1);
} }
} }
if (controller.bindings().TOGGLE_HUD_VISIBILITY.justPressed()) {
minecraft.options.hideGui = !minecraft.options.hideGui;
}
} }
protected void handlePlayerLookInput() { protected void handlePlayerLookInput() {
var axes = controller.state().axes(); var axes = controller.state().axes();
if (minecraft.mouseHandler.isMouseGrabbed() && minecraft.isWindowActive()) { if (minecraft.mouseHandler.isMouseGrabbed() && minecraft.isWindowActive()) {
accumulatedDX += axes.rightStickX(); accumulatedDX += axes.rightStickX() * Math.abs(axes.rightStickX());
accumulatedDY += axes.rightStickY(); accumulatedDY += axes.rightStickY() * Math.abs(axes.rightStickY());
} }
processPlayerLook(); processPlayerLook();

View File

@ -0,0 +1,5 @@
package dev.isxander.controlify.ingame.guide;
public enum ActionLocation {
LEFT, RIGHT
}

View File

@ -0,0 +1,9 @@
package dev.isxander.controlify.ingame.guide;
public enum ActionPriority {
LOWEST,
LOW,
NORMAL,
HIGH,
HIGHEST
}

View File

@ -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);
}

View File

@ -0,0 +1,5 @@
package dev.isxander.controlify.ingame.guide;
public interface ButtonGuideRegistry {
void registerGuideAction(ButtonActionSupplier supplier);
}

View File

@ -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());
}
}

View File

@ -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;
}
}
}

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.AbstractButtonComponentProcessor; import dev.isxander.controlify.screenop.compat.vanilla.AbstractButtonComponentProcessor;
import net.minecraft.client.gui.components.AbstractButton; import net.minecraft.client.gui.components.AbstractButton;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;

View File

@ -1,6 +1,6 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.component.CustomFocus; import dev.isxander.controlify.screenop.component.CustomFocus;
import net.minecraft.client.gui.components.events.AbstractContainerEventHandler; import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;

View File

@ -1,11 +1,11 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode; import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.SliderComponentProcessor; import dev.isxander.controlify.screenop.compat.vanilla.SliderComponentProcessor;
import net.minecraft.client.InputType; import net.minecraft.client.InputType;
import net.minecraft.client.gui.components.AbstractSliderButton; import net.minecraft.client.gui.components.AbstractSliderButton;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,6 +1,6 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.component.CustomFocus; import dev.isxander.controlify.screenop.component.CustomFocus;
import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.CreativeModeInventoryScreenProcessor; import dev.isxander.controlify.screenop.compat.vanilla.CreativeModeInventoryScreenProcessor;
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.JoinMultiplayerScreenProcessor; import dev.isxander.controlify.screenop.compat.vanilla.JoinMultiplayerScreenProcessor;
import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen;
import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList; import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.LanguageSelectionListComponentProcessor; import dev.isxander.controlify.screenop.compat.vanilla.LanguageSelectionListComponentProcessor;
import net.minecraft.client.gui.screens.LanguageSelectScreen; import net.minecraft.client.gui.screens.LanguageSelectScreen;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import net.minecraft.client.gui.screens.OptionsSubScreen; import net.minecraft.client.gui.screens.OptionsSubScreen;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import net.minecraft.client.gui.ComponentPath; import net.minecraft.client.gui.ComponentPath;
import net.minecraft.client.gui.navigation.FocusNavigationEvent; import net.minecraft.client.gui.navigation.FocusNavigationEvent;

View File

@ -1,7 +1,7 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen; import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.SelectWorldScreenProcessor; import dev.isxander.controlify.screenop.compat.vanilla.SelectWorldScreenProcessor;
import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen; import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.ServerSelectionListEntryComponentProcessor; import dev.isxander.controlify.screenop.compat.vanilla.ServerSelectionListEntryComponentProcessor;
import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList; import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla; package dev.isxander.controlify.mixins.compat.screenop.vanilla;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.WorldListEntryComponentProcessor; import dev.isxander.controlify.screenop.compat.vanilla.WorldListEntryComponentProcessor;
import net.minecraft.client.gui.screens.worldselection.WorldSelectionList; import net.minecraft.client.gui.screens.worldselection.WorldSelectionList;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.yacl; package dev.isxander.controlify.mixins.compat.screenop.yacl;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.yacl.CyclingControllerElementComponentProcessor; import dev.isxander.controlify.screenop.compat.yacl.CyclingControllerElementComponentProcessor;
import dev.isxander.yacl.gui.controllers.cycling.CyclingControllerElement; import dev.isxander.yacl.gui.controllers.cycling.CyclingControllerElement;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.yacl; package dev.isxander.controlify.mixins.compat.screenop.yacl;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.yacl.SliderControllerElementComponentProcessor; import dev.isxander.controlify.screenop.compat.yacl.SliderControllerElementComponentProcessor;
import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement; import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.mixins.compat.screen.yacl; package dev.isxander.controlify.mixins.compat.screenop.yacl;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.compatibility.yacl.YACLScreenProcessor; import dev.isxander.controlify.screenop.compat.yacl.YACLScreenProcessor;
import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.gui.YACLScreen;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;

View File

@ -1,11 +1,14 @@
package dev.isxander.controlify.mixins.core; package dev.isxander.controlify.mixins.core;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode; import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.ingame.ControllerPlayerMovement; import dev.isxander.controlify.ingame.ControllerPlayerMovement;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.protocol.game.ClientboundLoginPacket; import net.minecraft.network.protocol.game.ClientboundLoginPacket;
import net.minecraft.network.protocol.game.ClientboundRespawnPacket;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -22,8 +25,17 @@ public class ClientPacketListenerMixin {
@Shadow @Final private Minecraft minecraft; @Shadow @Final private Minecraft minecraft;
@Inject(method = "handleLogin", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/LocalPlayer;input:Lnet/minecraft/client/player/Input;", opcode = Opcodes.ASTORE, shift = At.Shift.AFTER)) @Inject(method = "handleLogin", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/LocalPlayer;input:Lnet/minecraft/client/player/Input;", opcode = Opcodes.ASTORE, shift = At.Shift.AFTER))
private void useControllerInput(ClientboundLoginPacket packet, CallbackInfo ci) { private void overrideNewPlayerInput(ClientboundLoginPacket packet, CallbackInfo ci) {
if (Controlify.instance().currentInputMode() == InputMode.CONTROLLER && minecraft.player != null) overrideInput(minecraft.player);
minecraft.player.input = new ControllerPlayerMovement(Controlify.instance().currentController(), minecraft.player); }
@Inject(method = "handleRespawn", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/LocalPlayer;input:Lnet/minecraft/client/player/Input;", opcode = Opcodes.ASTORE, shift = At.Shift.AFTER))
private void overrideRespawnInput(ClientboundRespawnPacket packet, CallbackInfo ci, @Local(ordinal = 1) LocalPlayer newPlayer) {
overrideInput(newPlayer);
}
private void overrideInput(LocalPlayer player) {
if (Controlify.instance().currentInputMode() == InputMode.CONTROLLER && player != null)
player.input = new ControllerPlayerMovement(Controlify.instance().currentController(), player);
} }
} }

View File

@ -0,0 +1,36 @@
package dev.isxander.controlify.mixins.feature.guide;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.ingame.guide.InGameButtonGuide;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
import net.minecraft.network.protocol.game.ClientboundRespawnPacket;
import org.objectweb.asm.Opcodes;
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;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientPacketListener.class)
public class ClientPacketListenerMixin {
@Shadow @Final private Minecraft minecraft;
@Inject(method = "handleLogin", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/LocalPlayer;input:Lnet/minecraft/client/player/Input;", opcode = Opcodes.ASTORE, shift = At.Shift.AFTER))
private void buttonGuideLogin(ClientboundLoginPacket packet, CallbackInfo ci) {
initButtonGuide();
}
@Inject(method = "handleRespawn", at = @At("RETURN"))
private void buttonGuideRespawn(ClientboundRespawnPacket packet, CallbackInfo ci) {
initButtonGuide();
}
private void initButtonGuide() {
if (Controlify.instance().currentInputMode() == InputMode.CONTROLLER && minecraft.player != null)
Controlify.instance().inGameButtonGuide = new InGameButtonGuide(Controlify.instance().currentController(), minecraft.player);
}
}

View File

@ -0,0 +1,36 @@
package dev.isxander.controlify.mixins.feature.guide;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.Controlify;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
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;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Gui.class)
public class GuiMixin {
@Shadow private int screenWidth;
@Shadow private int screenHeight;
@Shadow @Final private Minecraft minecraft;
@Inject(method = "render", at = @At(value = "CONSTANT", args = "stringValue=chat"))
private void renderButtonGuide(PoseStack matrices, float tickDelta, CallbackInfo ci) {
if (Controlify.instance().inGameButtonGuide() != null) {
minecraft.getProfiler().push("controlify_button_guide");
Controlify.instance().inGameButtonGuide().renderHud(matrices, tickDelta, screenWidth, screenHeight);
minecraft.getProfiler().pop();
}
}
@Inject(method = "tick()V", at = @At("RETURN"))
private void tickButtonGuide(CallbackInfo ci) {
if (Controlify.instance().inGameButtonGuide() != null) {
Controlify.instance().inGameButtonGuide().tick();
}
}
}

View File

@ -1,13 +1,12 @@
package dev.isxander.controlify.compatibility.screen; package dev.isxander.controlify.screenop;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode; import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.screenop.component.CustomFocus;
import dev.isxander.controlify.compatibility.screen.component.CustomFocus;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.event.ControlifyEvents; import dev.isxander.controlify.event.ControlifyEvents;
import dev.isxander.controlify.mixins.compat.screen.vanilla.ScreenAccessor; import dev.isxander.controlify.mixins.compat.screenop.vanilla.ScreenAccessor;
import net.minecraft.client.gui.ComponentPath; import net.minecraft.client.gui.ComponentPath;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.navigation.FocusNavigationEvent; import net.minecraft.client.gui.navigation.FocusNavigationEvent;
@ -134,8 +133,10 @@ public class ScreenProcessor<T extends Screen> {
if (screen.getFocused() == null && Controlify.instance().currentInputMode() == InputMode.CONTROLLER && !Controlify.instance().virtualMouseHandler().isVirtualMouseEnabled()) { if (screen.getFocused() == null && Controlify.instance().currentInputMode() == InputMode.CONTROLLER && !Controlify.instance().virtualMouseHandler().isVirtualMouseEnabled()) {
var accessor = (ScreenAccessor) screen; var accessor = (ScreenAccessor) screen;
ComponentPath path = screen.nextFocusPath(accessor.invokeCreateArrowEvent(ScreenDirection.DOWN)); ComponentPath path = screen.nextFocusPath(accessor.invokeCreateArrowEvent(ScreenDirection.DOWN));
if (path != null) if (path != null) {
accessor.invokeChangeFocus(path); accessor.invokeChangeFocus(path);
lastMoved = 0;
}
} }
} }

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.compatibility.screen; package dev.isxander.controlify.screenop;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;

View File

@ -1,7 +1,7 @@
package dev.isxander.controlify.compatibility.vanilla; package dev.isxander.controlify.screenop.compat.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.AbstractButton; import net.minecraft.client.gui.components.AbstractButton;

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.compatibility.vanilla; package dev.isxander.controlify.screenop.compat.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.mixins.compat.screen.vanilla.CreativeModeInventoryScreenAccessor; import dev.isxander.controlify.mixins.compat.screenop.vanilla.CreativeModeInventoryScreenAccessor;
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
import net.minecraft.world.item.CreativeModeTabs; import net.minecraft.world.item.CreativeModeTabs;

View File

@ -1,6 +1,6 @@
package dev.isxander.controlify.compatibility.vanilla; package dev.isxander.controlify.screenop.compat.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen;

View File

@ -1,9 +1,9 @@
package dev.isxander.controlify.compatibility.vanilla; package dev.isxander.controlify.screenop.compat.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.mixins.compat.screen.vanilla.OptionsSubScreenAccessor; import dev.isxander.controlify.mixins.compat.screenop.vanilla.OptionsSubScreenAccessor;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
public class LanguageSelectionListComponentProcessor implements ComponentProcessor { public class LanguageSelectionListComponentProcessor implements ComponentProcessor {

View File

@ -1,8 +1,8 @@
package dev.isxander.controlify.compatibility.vanilla; package dev.isxander.controlify.screenop.compat.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.mixins.compat.screen.vanilla.SelectWorldScreenAccessor; import dev.isxander.controlify.mixins.compat.screenop.vanilla.SelectWorldScreenAccessor;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen; import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen;

View File

@ -1,9 +1,9 @@
package dev.isxander.controlify.compatibility.vanilla; package dev.isxander.controlify.screenop.compat.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.mixins.compat.screen.vanilla.JoinMultiplayerScreenAccessor; import dev.isxander.controlify.mixins.compat.screenop.vanilla.JoinMultiplayerScreenAccessor;
public class ServerSelectionListEntryComponentProcessor implements ComponentProcessor { public class ServerSelectionListEntryComponentProcessor implements ComponentProcessor {
@Override @Override

View File

@ -1,7 +1,7 @@
package dev.isxander.controlify.compatibility.vanilla; package dev.isxander.controlify.screenop.compat.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import net.minecraft.client.gui.components.AbstractSliderButton; import net.minecraft.client.gui.components.AbstractSliderButton;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;

View File

@ -1,9 +1,9 @@
package dev.isxander.controlify.compatibility.vanilla; package dev.isxander.controlify.screenop.compat.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.mixins.compat.screen.vanilla.SelectWorldScreenAccessor; import dev.isxander.controlify.mixins.compat.screenop.vanilla.SelectWorldScreenAccessor;
import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen; import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen;
public class WorldListEntryComponentProcessor implements ComponentProcessor { public class WorldListEntryComponentProcessor implements ComponentProcessor {

View File

@ -1,7 +1,7 @@
package dev.isxander.controlify.compatibility.yacl; package dev.isxander.controlify.screenop.compat.yacl;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.yacl.gui.controllers.cycling.CyclingControllerElement; import dev.isxander.yacl.gui.controllers.cycling.CyclingControllerElement;

View File

@ -1,7 +1,7 @@
package dev.isxander.controlify.compatibility.yacl; package dev.isxander.controlify.screenop.compat.yacl;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.screenop.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement; import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement;

View File

@ -1,6 +1,6 @@
package dev.isxander.controlify.compatibility.yacl; package dev.isxander.controlify.screenop.compat.yacl;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.gui.YACLScreen;

View File

@ -1,6 +1,6 @@
package dev.isxander.controlify.compatibility.screen.component; package dev.isxander.controlify.screenop.component;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
public interface ComponentProcessor { public interface ComponentProcessor {

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.compatibility.screen.component; package dev.isxander.controlify.screenop.component;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;

View File

@ -1,4 +1,4 @@
package dev.isxander.controlify.compatibility.screen.component; package dev.isxander.controlify.screenop.component;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;

View File

@ -4,7 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode; import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.event.ControlifyEvents; import dev.isxander.controlify.event.ControlifyEvents;
import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor; import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor;

View File

@ -16,6 +16,8 @@
"controlify.gui.toggle_sneak.tooltip": "How the state of the sneak button behaves.", "controlify.gui.toggle_sneak.tooltip": "How the state of the sneak button behaves.",
"controlify.gui.toggle_sprint": "Sprint", "controlify.gui.toggle_sprint": "Sprint",
"controlify.gui.toggle_sprint.tooltip": "How the state of the sprint button behaves.", "controlify.gui.toggle_sprint.tooltip": "How the state of the sprint button behaves.",
"controlify.gui.show_guide": "Show Button Guide",
"controlify.gui.show_guide.tooltip": "Show a HUD in-game displaying actions you can do with controller buttons.",
"controlify.gui.vmouse_sensitivity": "Virtual Mouse Sensitivity", "controlify.gui.vmouse_sensitivity": "Virtual Mouse Sensitivity",
"controlify.gui.vmouse_sensitivity.tooltip": "How fast the virtual mouse moves.", "controlify.gui.vmouse_sensitivity.tooltip": "How fast the virtual mouse moves.",
"controlify.gui.controller_theme": "Controller Theme", "controlify.gui.controller_theme": "Controller Theme",
@ -25,7 +27,7 @@
"controlify.gui.group.advanced": "Advanced", "controlify.gui.group.advanced": "Advanced",
"controlify.gui.group.advanced.tooltip": "Settings you probably shouldn't touch!.", "controlify.gui.group.advanced.tooltip": "Settings you probably shouldn't touch!.",
"controlify.gui.screen_repeat_navi_delay": "Screen Repeat Navigation Delay", "controlify.gui.screen_repeat_navi_delay": "Screen Repeat Navigation Delay",
"controlify.gui.screen_repeat_navi_delay.tooltip": "How the delay is for navigation to start repeating if you hold the stick.", "controlify.gui.screen_repeat_navi_delay.tooltip": "How fast a screen navigation action repeats.",
"controlify.gui.left_stick_deadzone": "Left Stick Deadzone", "controlify.gui.left_stick_deadzone": "Left Stick Deadzone",
"controlify.gui.left_stick_deadzone.tooltip": "How far the left joystick needs to be pushed before registering input.", "controlify.gui.left_stick_deadzone.tooltip": "How far the left joystick needs to be pushed before registering input.",
"controlify.gui.right_stick_deadzone": "Right Stick Deadzone", "controlify.gui.right_stick_deadzone": "Right Stick Deadzone",
@ -80,6 +82,9 @@
"controlify.binding.controlify.gui_next_tab": "GUI Next Tab", "controlify.binding.controlify.gui_next_tab": "GUI Next Tab",
"controlify.binding.controlify.gui_prev_tab": "GUI Previous Tab", "controlify.binding.controlify.gui_prev_tab": "GUI Previous Tab",
"controlify.binding.controlify.drop": "Drop Item", "controlify.binding.controlify.drop": "Drop Item",
"controlify.binding.controlify.pick_block": "Pick Block",
"controlify.binding.controlify.toggle_hud_visibility": "Toggle HUD Visibility",
"controlify.binding.controlify.show_player_list": "Show Player List",
"controlify.binding.controlify.vmouse_lclick": "Virtual Mouse LClick", "controlify.binding.controlify.vmouse_lclick": "Virtual Mouse LClick",
"controlify.binding.controlify.vmouse_rclick": "Virtual Mouse RClick", "controlify.binding.controlify.vmouse_rclick": "Virtual Mouse RClick",
"controlify.binding.controlify.vmouse_mclick": "Virtual Mouse MClick", "controlify.binding.controlify.vmouse_mclick": "Virtual Mouse MClick",
@ -88,7 +93,23 @@
"controlify.binding.controlify.vmouse_escape": "Virtual Mouse Key Escape", "controlify.binding.controlify.vmouse_escape": "Virtual Mouse Key Escape",
"controlify.binding.controlify.vmouse_shift": "Virtual Mouse Key Shift", "controlify.binding.controlify.vmouse_shift": "Virtual Mouse Key Shift",
"controlify.binding.controlify.vmouse_toggle": "Toggle Virtual Mouse", "controlify.binding.controlify.vmouse_toggle": "Toggle Virtual Mouse",
"controlify.binding.controlify.pick_block": "Pick Block",
"controlify.guide.inventory": "Open Inventory",
"controlify.guide.swim_up": "Swim Up",
"controlify.guide.start_elytra": "Open Elytra Wings",
"controlify.guide.fly_up": "Fly Up",
"controlify.guide.fly_down": "Fly Down",
"controlify.guide.start_sneaking": "Start Sneaking",
"controlify.guide.stop_sneaking": "Stop Sneaking",
"controlify.guide.sneak": "Sneak",
"controlify.guide.dismount": "Dismount",
"controlify.guide.swim_down": "Swim Down",
"controlify.guide.drop": "Drop Item",
"controlify.guide.attack": "Attack",
"controlify.guide.break": "Break",
"controlify.guide.use": "Use",
"controlify.guide.interact": "Interact",
"controlify.guide.pick_block": "Pick Block",
"controlify.beta.title": "Controlify Beta Notice", "controlify.beta.title": "Controlify Beta Notice",
"controlify.beta.message": "You are currently using Controlify Beta.\n\nThis mod is a work in progress and will contain many bugs. Please, if you spot a bug in this mod or have a suggestion to make it even better, please create an issue on the %s!\n\nYou can always find the link to the issue tracker in Controlify's settings menu.", "controlify.beta.message": "You are currently using Controlify Beta.\n\nThis mod is a work in progress and will contain many bugs. Please, if you spot a bug in this mod or have a suggestion to make it even better, please create an issue on the %s!\n\nYou can always find the link to the issue tracker in Controlify's settings menu.",

View File

@ -6,31 +6,33 @@
"mixins": [ "mixins": [
], ],
"client": [ "client": [
"compat.screen.vanilla.AbstractButtonMixin", "compat.screenop.vanilla.AbstractButtonMixin",
"compat.screen.vanilla.AbstractContainerEventHandlerMixin", "compat.screenop.vanilla.AbstractContainerEventHandlerMixin",
"compat.screen.vanilla.AbstractSelectionListMixin", "compat.screenop.vanilla.AbstractSelectionListMixin",
"compat.screen.vanilla.AbstractSliderButtonMixin", "compat.screenop.vanilla.AbstractSliderButtonMixin",
"compat.screen.vanilla.ContainerObjectSelectionListEntryMixin", "compat.screenop.vanilla.ContainerObjectSelectionListEntryMixin",
"compat.screen.vanilla.CreativeModeInventoryScreenAccessor", "compat.screenop.vanilla.CreativeModeInventoryScreenAccessor",
"compat.screen.vanilla.CreativeModeInventoryScreenMixin", "compat.screenop.vanilla.CreativeModeInventoryScreenMixin",
"compat.screen.vanilla.JoinMultiplayerScreenAccessor", "compat.screenop.vanilla.JoinMultiplayerScreenAccessor",
"compat.screen.vanilla.JoinMultiplayerScreenMixin", "compat.screenop.vanilla.JoinMultiplayerScreenMixin",
"compat.screen.vanilla.LanguageSelectionListEntryMixin", "compat.screenop.vanilla.LanguageSelectionListEntryMixin",
"compat.screen.vanilla.OptionsSubScreenAccessor", "compat.screenop.vanilla.OptionsSubScreenAccessor",
"compat.screen.vanilla.ScreenAccessor", "compat.screenop.vanilla.ScreenAccessor",
"compat.screen.vanilla.ScreenMixin", "compat.screenop.vanilla.ScreenMixin",
"compat.screen.vanilla.SelectWorldScreenAccessor", "compat.screenop.vanilla.SelectWorldScreenAccessor",
"compat.screen.vanilla.SelectWorldScreenMixin", "compat.screenop.vanilla.SelectWorldScreenMixin",
"compat.screen.vanilla.ServerSelectionListEntryMixin", "compat.screenop.vanilla.ServerSelectionListEntryMixin",
"compat.screen.vanilla.WorldSelectionListEntryMixin", "compat.screenop.vanilla.WorldSelectionListEntryMixin",
"compat.screen.yacl.CyclingControllerElementMixin", "compat.screenop.yacl.CyclingControllerElementMixin",
"compat.screen.yacl.SliderControllerElementMixin", "compat.screenop.yacl.SliderControllerElementMixin",
"compat.screen.yacl.YACLScreenMixin", "compat.screenop.yacl.YACLScreenMixin",
"core.ClientPacketListenerMixin", "core.ClientPacketListenerMixin",
"core.KeyboardHandlerMixin", "core.KeyboardHandlerMixin",
"core.MinecraftMixin", "core.MinecraftMixin",
"core.MouseHandlerMixin", "core.MouseHandlerMixin",
"feature.bind.KeyMappingAccessor", "feature.bind.KeyMappingAccessor",
"feature.guide.ClientPacketListenerMixin",
"feature.guide.GuiMixin",
"feature.settingsbutton.ControlsScreenMixin", "feature.settingsbutton.ControlsScreenMixin",
"feature.virtualmouse.GameRendererMixin", "feature.virtualmouse.GameRendererMixin",
"feature.virtualmouse.InputConstantsMixin", "feature.virtualmouse.InputConstantsMixin",