1
0
forked from Clones/Controlify

compound binds, complete vanilla compat, better vmouse screen handling, controller uuid, beta notice screen, configurable movement keys, vmouse shift key, icon, optimize controller save/load

This commit is contained in:
isXander
2023-02-05 14:55:20 +00:00
parent 9c7972c971
commit 6c5108469c
62 changed files with 831 additions and 137 deletions

View File

@ -1,12 +1,17 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.SliderComponentProcessor;
import net.minecraft.client.InputType;
import net.minecraft.client.gui.components.AbstractSliderButton;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
/**
* Mixin to insert a custom {@link ComponentProcessor} into slider to support left/right movement without navigating to next component.
@ -22,6 +27,13 @@ public class AbstractSliderButtonMixin implements ComponentProcessorProvider {
val -> this.canChangeValue = val
);
@ModifyExpressionValue(method = "setFocused", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getLastInputType()Lnet/minecraft/client/InputType;"))
private InputType shouldChangeValue(InputType type) {
if (Controlify.instance().currentInputMode() == InputMode.CONTROLLER)
return InputType.NONE; // none doesn't pass condition
return type;
}
@Override
public ComponentProcessor componentProcessor() {
return controlify$processor;

View File

@ -0,0 +1,16 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla;
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
import net.minecraft.world.item.CreativeModeTab;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(CreativeModeInventoryScreen.class)
public interface CreativeModeInventoryScreenAccessor {
@Accessor
CreativeModeTab getSelectedTab();
@Invoker
void invokeSelectTab(CreativeModeTab tab);
}

View File

@ -0,0 +1,19 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.CreativeModeInventoryScreenProcessor;
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(CreativeModeInventoryScreen.class)
public class CreativeModeInventoryScreenMixin implements ScreenProcessorProvider {
@Unique private final CreativeModeInventoryScreenProcessor controlify$screenProcessor
= new CreativeModeInventoryScreenProcessor((CreativeModeInventoryScreen) (Object) this);
@Override
public ScreenProcessor<?> screenProcessor() {
return controlify$screenProcessor;
}
}

View File

@ -0,0 +1,12 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(JoinMultiplayerScreen.class)
public interface JoinMultiplayerScreenAccessor {
@Accessor
Button getSelectButton();
}

View File

@ -0,0 +1,23 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.JoinMultiplayerScreenProcessor;
import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen;
import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@Mixin(JoinMultiplayerScreen.class)
public class JoinMultiplayerScreenMixin implements ScreenProcessorProvider {
@Shadow protected ServerSelectionList serverSelectionList;
@Unique private final JoinMultiplayerScreenProcessor controlify$processor
= new JoinMultiplayerScreenProcessor((JoinMultiplayerScreen) (Object) this, serverSelectionList);
@Override
public ScreenProcessor<?> screenProcessor() {
return controlify$processor;
}
}

View File

@ -0,0 +1,26 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.LanguageSelectionListComponentProcessor;
import net.minecraft.client.gui.screens.LanguageSelectScreen;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@Mixin(LanguageSelectScreen.LanguageSelectionList.Entry.class)
public class LanguageSelectionListEntryMixin implements ComponentProcessorProvider {
@Shadow @Final String code;
@Unique private LanguageSelectionListComponentProcessor controlify$componentProcessor = null;
@Override
public ComponentProcessor componentProcessor() {
// lazily create the component processor so `code` is defined
if (controlify$componentProcessor == null)
controlify$componentProcessor = new LanguageSelectionListComponentProcessor(code);
return controlify$componentProcessor;
}
}

View File

@ -0,0 +1,12 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla;
import net.minecraft.client.gui.screens.OptionsSubScreen;
import net.minecraft.client.gui.screens.Screen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(OptionsSubScreen.class)
public interface OptionsSubScreenAccessor {
@Accessor
Screen getLastScreen();
}

View File

@ -0,0 +1,21 @@
package dev.isxander.controlify.mixins.compat.screen.vanilla;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.vanilla.ServerSelectionListEntryComponentProcessor;
import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(ServerSelectionList.Entry.class)
public class ServerSelectionListEntryMixin implements ComponentProcessorProvider {
@Unique private final ServerSelectionListEntryComponentProcessor controlify$componentProcessor
= new ServerSelectionListEntryComponentProcessor();
@Override
public ComponentProcessor componentProcessor() {
return ((ServerSelectionList.Entry) (Object) this) instanceof ServerSelectionList.LANHeader
? ComponentProcessor.EMPTY
: controlify$componentProcessor;
}
}

View File

@ -1,14 +1,21 @@
package dev.isxander.controlify.mixins.core;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.gui.screen.BetaNoticeScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.main.GameConfig;
import org.jetbrains.annotations.Nullable;
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(Minecraft.class)
public class MinecraftMixin {
public abstract class MinecraftMixin {
@Shadow public abstract void setScreen(@Nullable Screen screen);
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyboardHandler;setup(J)V", shift = At.Shift.AFTER))
private void onInputInitialized(CallbackInfo ci) {
Controlify.instance().onInitializeInput();
@ -18,4 +25,10 @@ public class MinecraftMixin {
private void doPlayerLook(boolean tick, CallbackInfo ci) {
Controlify.instance().inGameInputHandler().processPlayerLook();
}
@Inject(method = "<init>", at = @At("TAIL"))
private void showBetaScreen(GameConfig args, CallbackInfo ci) {
if (Controlify.instance().config().isFirstLaunch())
setScreen(new BetaNoticeScreen());
}
}

View File

@ -0,0 +1,21 @@
package dev.isxander.controlify.mixins.feature.virtualmouse;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.mojang.blaze3d.platform.InputConstants;
import dev.isxander.controlify.Controlify;
import org.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(InputConstants.class)
public class InputConstantsMixin {
// must modify isKeyDown here because Screen.hasShiftDown has some instances that ask for this directly.
@ModifyReturnValue(method = "isKeyDown", at = @At("RETURN"))
private static boolean modifyIsKeyDown(boolean keyDown, long window, int key) {
if (key == GLFW.GLFW_KEY_LEFT_SHIFT) {
return keyDown || Controlify.instance().currentController().bindings().VMOUSE_SHIFT.held();
}
return keyDown;
}
}