Architectury build system & huge code cleanup

This commit is contained in:
Martin Prokoph
2024-07-17 14:26:17 +02:00
parent 9e3b2ae060
commit 27221b62cd
146 changed files with 1529 additions and 855 deletions

View File

@@ -0,0 +1,28 @@
/*
* Copyright © 2022 Motschen <motschen@midnightdust.eu>
*
* This file is part of midnightcontrols.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.compat;
import me.juancarloscp52.bedrockify.client.BedrockifyClient;
import me.juancarloscp52.bedrockify.client.BedrockifyClientSettings;
/**
* Represents HQM compatibility handler.
*
* @author Motschen
* @version 1.7.0
* @since 1.7.0
*/
public class BedrockifyCompat implements CompatHandler {
@Override
public void handle() {
BedrockifyClient.getInstance().settings.disableFlyingMomentum = false;
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of midnightcontrols.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.screen.slot.Slot;
import net.minecraft.util.hit.BlockHitResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a compatibility handler for a mod.
*
* @author LambdAurora
* @version 1.7.0
* @since 1.1.0
*/
public interface CompatHandler {
/**
* Handles compatibility of a mod.
*/
default void handle() {
handle(MidnightControlsClient.get());
}
/**
* Handles compatibility of a mod.
*
* @param mod this mod instance
*/
@Deprecated
default void handle(@NotNull MidnightControlsClient mod) {}
/**
* Handles custom camera updates
*
* @param client the Minecraft client instance
*/
default void handleCamera(@NotNull MinecraftClient client, double targetYaw, double targetPitch) {};
/**
* Handles custom tab behavior
*
* @param forward whether the direction is forward or backward
*/
default boolean handleTabs(Screen screen, boolean forward) {
return false;
};
/**
* Returns whether the mouse is required on the specified screen.
*
* @param screen the screen
* @return true if the mouse is required on the specified screen, else false
*/
default boolean requireMouseOnScreen(Screen screen) {
return false;
}
/**
* Returns a slot at the specified location if possible.
*
* @param screen the screen
* @param mouseX the mouse X-coordinate
* @param mouseY the mouse Y-coordinate
* @return a slot if present, else null
* @since 1.5.0
*/
default @Nullable CompatHandler.SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
return null;
}
/**
* Returns whether the current slot is a creative slot or not.
*
* @param screen the screen
* @param slot the slot to check
* @return true if the slot is a creative slot, else false
*/
default boolean isCreativeSlot(@NotNull HandledScreen screen, @NotNull Slot slot) {
return false;
}
/**
* Returns a custom translation key to make custom attack action strings on the HUD.
*
* @param client the client instance
* @param placeResult the last place block result
* @return null if untouched, else a translation key
*/
default String getAttackActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
return null;
}
/**
* Returns a custom translation key to make custom use action strings on the HUD.
*
* @param client the client instance
* @param placeResult the last place block result
* @return null if untouched, else a translation key
*/
default String getUseActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
return null;
}
/**
* Handles the menu back button.
*
* @param client the client instance
* @param screen the screen
* @return true if the handle was fired and succeed, else false
*/
default boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
return false;
}
record SlotPos(int x, int y) {
public static final SlotPos INVALID_SLOT = new SlotPos(-1, -1);
}
}

View File

@@ -0,0 +1,46 @@
package eu.midnightdust.midnightcontrols.client.compat;
import dev.emi.emi.api.EmiApi;
import dev.emi.emi.config.EmiConfig;
import dev.emi.emi.screen.EmiScreenManager;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
public class EMICompat implements CompatHandler {
public static boolean handleEmiPages(boolean direction) {
if (isEMIEnabled() && MidnightControlsClient.input.actionGuiCooldown == 0 && EmiScreenManager.getSearchPanel() != null && EmiScreenManager.getSearchPanel().pageLeft != null && EmiScreenManager.getSearchPanel().pageRight != null) {
if (direction) EmiScreenManager.getSearchPanel().pageRight.onPress();
else EmiScreenManager.getSearchPanel().pageLeft.onPress();
MidnightControlsClient.input.actionGuiCooldown = 5;
return true;
}
return false;
}
@Override
public void handle() {
ButtonCategory category = new ButtonCategory(Identifier.of("midnightcontrols","category.emi"));
InputManager.registerCategory(category);
new ButtonBinding.Builder("emi_page_left")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
.category(category)
.action((client,action,value,buttonState)->handleEmiPages(false)).cooldown()
.filter(((client, buttonBinding) -> EmiApi.getHandledScreen() != null))
.register();
new ButtonBinding.Builder("emi_page_right")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
.category(category)
.action((client,action,value,buttonState)->handleEmiPages(true)).cooldown()
.filter(((client, buttonBinding) -> EmiApi.getHandledScreen() != null))
.register();
}
public static boolean isEMIEnabled() {
return EmiConfig.enabled;
}
public static boolean isSearchBarCentered() {
return EmiConfig.centerSearchBar;
}
}

View File

@@ -0,0 +1,34 @@
package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import io.github.kosmx.emotes.arch.gui.EmoteMenuImpl;
import io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
public class EmotecraftCompat {
private static final MinecraftClient client = MinecraftClient.getInstance();
public static void openEmotecraftScreen(Screen parent) {
client.setScreen(new EmoteMenuImpl(parent));
}
public static boolean isEmotecraftScreen(Screen screen) {
return screen instanceof FastChosseScreen;
}
public static void handleEmoteSelector(int index) {
if (client.currentScreen instanceof FastChosseScreen) {
int x = client.getWindow().getWidth() / 2;
int y = client.getWindow().getHeight() / 2;
if (index == 0) InputManager.queueMousePosition(x-200, y-200);
if (index == 1) InputManager.queueMousePosition(x, y-200);
if (index == 2) InputManager.queueMousePosition(x+200, y-200);
if (index == 3) InputManager.queueMousePosition(x-200, y);
if (index == 4) InputManager.queueMousePosition(x+200, y);
if (index == 5) InputManager.queueMousePosition(x-200, y+200);
if (index == 6) InputManager.queueMousePosition(x, y+200);
if (index == 7) InputManager.queueMousePosition(x+200, y+200);
InputManager.INPUT_MANAGER.updateMousePosition(client);
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of midnightcontrols.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.compat;
import net.minecraft.client.gui.screen.Screen;
import org.aperlambda.lambdacommon.utils.LambdaReflection;
import java.util.Optional;
/**
* Represents HQM compatibility handler.
* <p>
* This is bad.
*
* @author LambdAurora
* @version 1.3.2
* @since 1.3.2
*/
public class HQMCompat implements CompatHandler {
public static final String GUI_BASE_CLASS_PATH = "hardcorequesting.client.interfaces.GuiBase";
private Optional<Class<?>> guiBaseClass;
@Override
public void handle() {
this.guiBaseClass = LambdaReflection.getClass(GUI_BASE_CLASS_PATH);
}
@Override
public boolean requireMouseOnScreen(Screen screen) {
return this.guiBaseClass.map(clazz -> clazz.isInstance(screen)).orElse(false);
}
}

View File

@@ -0,0 +1,44 @@
package eu.midnightdust.midnightcontrols.client.compat;
import com.kqp.inventorytabs.tabs.TabManager;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
public class InventoryTabsCompat implements CompatHandler {
private static InventoryTabsCompat INSTANCE;
@Override
public void handle() {
INSTANCE = this;
}
@Override
public boolean handleTabs(Screen screen, boolean next) {
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
TabManager tabManager = TabManager.getInstance();
int tabIndex = tabManager.tabs.indexOf(tabManager.currentTab);
if (next) {
if (tabIndex < tabManager.tabs.size() - 1) tabManager.onTabClick(tabManager.tabs.get(tabIndex + 1));
else tabManager.onTabClick(tabManager.tabs.get(0));
} else {
if (tabIndex > 0) tabManager.onTabClick(tabManager.tabs.get(tabIndex - 1));
else tabManager.onTabClick(tabManager.tabs.get(tabManager.tabs.size() - 1));
}
return true;
}
return false;
}
public static boolean handleInventoryTabs(Screen screen, boolean next) {
return INSTANCE.handleTabs(screen, next);
}
public static void handleInventoryPage(Screen screen, boolean next) {
if (screen instanceof HandledScreen<?> && !(screen instanceof CreativeInventoryScreen)) {
TabManager tabManager = TabManager.getInstance();
if (next) {
if (tabManager.canGoForwardAPage()) tabManager.setCurrentPage(tabManager.currentPage + 1);
} else {
if (tabManager.canGoBackAPage()) tabManager.setCurrentPage(tabManager.currentPage - 1);
}
}
}
}

View File

@@ -0,0 +1,25 @@
package eu.midnightdust.midnightcontrols.client.compat;
import io.github.cottonmc.cotton.gui.impl.client.CottonScreenImpl;
import io.github.cottonmc.cotton.gui.widget.WButton;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.sound.PositionedSoundInstance;
import net.minecraft.sound.SoundEvents;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("UnstableApiUsage")
public class LibGuiCompat {
public static boolean handlePress(@NotNull Screen screen) {
if (screen instanceof CottonScreenImpl cottonScreen) {
if (cottonScreen.getDescription() != null && cottonScreen.getDescription().getFocus() != null) {
if (cottonScreen.getDescription().getFocus() instanceof WButton button && button.getOnClick() != null) {
button.getOnClick().run();
MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
return true;
}
}
}
return false;
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of midnightcontrols.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.hit.BlockHitResult;
import org.aperlambda.lambdacommon.utils.LambdaReflection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import static eu.midnightdust.midnightcontrols.MidnightControls.log;
/**
* Represents a compatibility handler.
*
* @author LambdAurora, Motschen
* @version 1.10.0
* @since 1.1.0
*/
public class MidnightControlsCompat {
private static final List<CompatHandler> HANDLERS = new ArrayList<>();
/**
* Initializes compatibility with other mods if needed.
*/
public static void init() {
// "okzoomer" is the mod ID used by Fabric-compatible versions of Ok Zoomer. (5.0.0-beta.6 and below.)
// "ok_zoomer" is the mod ID used by Quilt-exclusive versions of Ok Zoomer. (5.0.0-beta.7 and above.)
if (FabricLoader.getInstance().isModLoaded("okzoomer") || FabricLoader.getInstance().isModLoaded("ok_zoomer")) {
log("Adding Ok Zoomer compatibility...");
registerCompatHandler(new OkZoomerCompat());
}
if (isEMIPresent()) {
log("Adding EMI compatibility...");
registerCompatHandler(new EMICompat());
}
if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
log("Adding HQM compatibility...");
registerCompatHandler(new HQMCompat());
}
if (FabricLoader.getInstance().isModLoaded("bedrockify")) {
log("Adding Bedrockify compatibility...");
registerCompatHandler(new BedrockifyCompat());
}
if (PlatformFunctions.isModLoaded("yet-another-config-lib")) {
log("Adding YACL compatibility...");
registerCompatHandler(new YACLCompat());
}
if (PlatformFunctions.isModLoaded("sodium")) {
log("Adding Sodium compatibility...");
registerCompatHandler(new SodiumCompat());
}
if (PlatformFunctions.isModLoaded("inventorytabs")) {
log("Adding Inventory Tabs compatibility...");
registerCompatHandler(new InventoryTabsCompat());
}
HANDLERS.forEach(CompatHandler::handle);
InputManager.loadButtonBindings();
}
/**
* Registers a new compatibility handler.
*
* @param handler the compatibility handler to register
*/
public static void registerCompatHandler(@NotNull CompatHandler handler) {
HANDLERS.add(handler);
}
/**
* Streams through compatibility handlers.
*
* @return a stream of compatibility handlers
*/
public static Stream<CompatHandler> streamCompatHandlers() {
return HANDLERS.stream();
}
/**
* Returns whether the mouse is required on the specified screen.
*
* @param screen the screen
* @return true if the mouse is requried on the specified screen, else false
*/
public static boolean requireMouseOnScreen(Screen screen) {
return streamCompatHandlers().anyMatch(handler -> handler.requireMouseOnScreen(screen));
}
/**
* Handles custom tabs for modded screens
*
* @param screen the screen
* @return true if the handle was fired and succeed, else false
*/
public static boolean handleTabs(Screen screen, boolean forward) {
return streamCompatHandlers().anyMatch(handler -> handler.handleTabs(screen, forward));
}
/**
* Returns a slot at the specified location if possible.
*
* @param screen the screen
* @param mouseX the mouse X-coordinate
* @param mouseY the mouse Y-coordinate
* @return a slot if present, else null
*/
public static @Nullable CompatHandler.SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
for (var handler : HANDLERS) {
var slot = handler.getSlotAt(screen, mouseX, mouseY);
if (slot != null)
return slot;
}
return null;
}
/**
* Returns a custom translation key to make custom attack action strings on the HUD.
*
* @param client the client instance
* @param placeResult the last place block result
* @return null if untouched, else a translation key
*/
public static String getAttackActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
for (CompatHandler handler : HANDLERS) {
String action = handler.getAttackActionAt(client, placeResult);
if (action != null) {
return action;
}
}
return null;
}
/**
* Returns a custom translation key to make custom use action strings on the HUD.
*
* @param client the client instance
* @param placeResult the last place block result
* @return null if untouched, else a translation key
*/
public static String getUseActionAt(@NotNull MinecraftClient client, @Nullable BlockHitResult placeResult) {
for (CompatHandler handler : HANDLERS) {
String action = handler.getUseActionAt(client, placeResult);
if (action != null) {
return action;
}
}
return null;
}
/**
* Handles the menu back button.
*
* @param client the client instance
* @param screen the screen
* @return true if the handle was fired and succeed, else false
*/
public static boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
for (CompatHandler handler : HANDLERS) {
if (handler.handleMenuBack(client, screen))
return true;
}
return false;
}
/**
* Handles the camera movement.
*
* @param client the client instance
* @param targetYaw the target yaw
* @param targetPitch the target pitch
*/
public static void handleCamera(@NotNull MinecraftClient client, double targetYaw, double targetPitch) {
MidnightControlsCompat.HANDLERS.forEach(handler -> handler.handleCamera(client, targetYaw, targetPitch));
}
/**
* Returns whether EMI is present.
*
* @return true if EMI is present, else false
*/
public static boolean isEMIPresent() {
return PlatformFunctions.isModLoaded("emi");
}
/**
* Returns whether InventoryTabs is present.
*
* @return true if InventoryTabs is present, else false
*/
public static boolean isInventoryTabsPresent() {
return PlatformFunctions.isModLoaded("inventorytabs");
}
/**
* Returns whether Emotecraft is present.
*
* @return true if Emotecraft is present, else false
*/
public static boolean isEmotecraftPresent() {
return FabricLoader.getInstance().isModLoaded("emotecraft");
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of midnightcontrols.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.lib.util.PlatformFunctions;
import net.fabricmc.loader.api.FabricLoader;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
/**
* This plugin is only present for the conditional mixins.
*
* @author LambdAurora & Motschen
* @version 1.6.0
* @since 1.2.0
*/
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
private String mixinPackage;
@Override
public void onLoad(String mixinPackage) {
this.mixinPackage = mixinPackage + ".";
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
final String mixinName = mixinClassName.substring(this.mixinPackage.length());
final String packageName = mixinName.substring(0, mixinName.lastIndexOf('.'));
if (packageName.startsWith("sodium") && !PlatformFunctions.isModLoaded("sodium"))
return false;
return true;
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
@Override
public List<String> getMixins() {
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright © 2021-2022 Karen/あけみ <karen@akemi.ai>, LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of MidnightControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.MidnightControls;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import net.minecraft.client.option.KeyBinding;
import org.jetbrains.annotations.NotNull;
import org.aperlambda.lambdacommon.utils.LambdaReflection;
import org.lwjgl.glfw.GLFW;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Represents a compatibility handler for Ok Zoomer.
*
* @author Karen/あけみ, LambdAurora
* @version 1.4.3
* @since 1.1.0
*/
public class OkZoomerCompat implements CompatHandler {
private boolean didAllReflectionCallsSucceed = false;
private KeyBinding okZoomerZoomKey;
private KeyBinding okZoomerIncreaseZoomKey;
private KeyBinding okZoomerDecreaseZoomKey;
private KeyBinding okZoomerResetZoomKey;
private Method okZoomerAreExtraKeyBindsEnabledMethod;
public OkZoomerCompat() {
// These strings represent the names of the classes, fields, and methods we use from the Ok Zoomer API
String okZoomerZoomKeybindsClassString;
String okZoomerZoomKeyFieldString;
String okZoomerIncreaseZoomKeyFieldString;
String okZoomerDecreaseZoomKeyFieldString;
String okZoomerResetZoomKeyFieldString;
String okZoomerAreExtraKeyBindsEnabledMethodNameString;
// These variables represent the actual objects that we reflect to
Class<?> okZoomerZoomKeybindsClass;
Field okZoomerZoomKeyField;
Field okZoomerIncreaseZoomKeyField;
Field okZoomerDecreaseZoomKeyField;
Field okZoomerResetZoomKeyField;
// First, we need to determine which version of the Ok Zoomer API we're dealing with here.
if (LambdaReflection.doesClassExist("io.github.ennuil.okzoomer.keybinds.ZoomKeybinds")) {
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.3+1.17.1/src/main/java/io/github/ennuil/okzoomer/keybinds/ZoomKeybinds.java
MidnightControls.log("Ok Zoomer version 5.0.0-beta.3 or below detected!");
okZoomerZoomKeybindsClassString = "io.github.ennuil.okzoomer.keybinds.ZoomKeybinds";
okZoomerZoomKeyFieldString = "zoomKey";
okZoomerIncreaseZoomKeyFieldString = "increaseZoomKey";
okZoomerDecreaseZoomKeyFieldString = "decreaseZoomKey";
okZoomerResetZoomKeyFieldString = "resetZoomKey";
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeybindsEnabled";
} else if (LambdaReflection.doesClassExist("io.github.ennuil.okzoomer.key_binds.ZoomKeyBinds")) {
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.6+1.18.2/src/main/java/io/github/ennuil/okzoomer/key_binds/ZoomKeyBinds.java
MidnightControls.log("Ok Zoomer version 5.0.0-beta.6, 5.0.0-beta.5, or 5.0.0-beta.4 detected!");
okZoomerZoomKeybindsClassString = "io.github.ennuil.okzoomer.key_binds.ZoomKeyBinds";
okZoomerZoomKeyFieldString = "ZOOM_KEY";
okZoomerIncreaseZoomKeyFieldString = "INCREASE_ZOOM_KEY";
okZoomerDecreaseZoomKeyFieldString = "DECREASE_ZOOM_KEY";
okZoomerResetZoomKeyFieldString = "RESET_ZOOM_KEY";
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeyBindsEnabled";
} else if (LambdaReflection.doesClassExist("io.github.ennuil.ok_zoomer.key_binds.ZoomKeyBinds")) {
// https://github.com/EnnuiL/OkZoomer/blob/5.0.0-beta.7+1.18.2/src/main/java/io/github/ennuil/ok_zoomer/key_binds/ZoomKeyBinds.java
MidnightControls.log("Ok Zoomer version 5.0.0-beta.7 (Quilt) or above detected!");
okZoomerZoomKeybindsClassString = "io.github.ennuil.ok_zoomer.key_binds.ZoomKeyBinds";
okZoomerZoomKeyFieldString = "ZOOM_KEY";
okZoomerIncreaseZoomKeyFieldString = "INCREASE_ZOOM_KEY";
okZoomerDecreaseZoomKeyFieldString = "DECREASE_ZOOM_KEY";
okZoomerResetZoomKeyFieldString = "RESET_ZOOM_KEY";
okZoomerAreExtraKeyBindsEnabledMethodNameString = "areExtraKeyBindsEnabled";
} else {
// If all of the above checks fail, then the version of the Ok Zoomer API that the user is trying to use is too new.
MidnightControls.warn("The version of Ok Zoomer that you are currently using is too new, and is not yet supported by MidnightControls!");
return;
}
// Reflect to the ZoomKeyBinds (>= 5.0.0-beta.4) / ZoomKeybinds (<= 5.0.0-beta.3) class.
try {
okZoomerZoomKeybindsClass = Class.forName(okZoomerZoomKeybindsClassString);
} catch (ClassNotFoundException exception) {
// This theoretically should never happen.
MidnightControls.warn("MidnightControls failed to reflect to the Ok Zoomer keybinds class!");
exception.printStackTrace();
return;
}
// Reflect to all of the keybind fields.
try {
okZoomerZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerZoomKeyFieldString);
okZoomerIncreaseZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerIncreaseZoomKeyFieldString);
okZoomerDecreaseZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerDecreaseZoomKeyFieldString);
okZoomerResetZoomKeyField = okZoomerZoomKeybindsClass.getField(okZoomerResetZoomKeyFieldString);
} catch (NoSuchFieldException exception) {
MidnightControls.warn("MidnightControls failed to reflect to the Ok Zoomer keybind fields!");
exception.printStackTrace();
return;
}
// Initialise KeyBinding objects
try {
okZoomerZoomKey = (KeyBinding) okZoomerZoomKeyField.get(null);
okZoomerIncreaseZoomKey = (KeyBinding) okZoomerIncreaseZoomKeyField.get(null);
okZoomerDecreaseZoomKey = (KeyBinding) okZoomerDecreaseZoomKeyField.get(null);
okZoomerResetZoomKey = (KeyBinding) okZoomerResetZoomKeyField.get(null);
} catch (IllegalAccessException exception) {
MidnightControls.warn("MidnightControls failed to reflect to the Ok Zoomer keybind objects!");
exception.printStackTrace();
return;
}
// Reflect to the areExtraKeyBindsEnabled (>= 5.0.0-beta.4) / areExtraKeybindsEnabled (<= 5.0.0-beta.3) method.
// TODO: Consider replacing this entirely with getExtraKeyBind (>= 5.0.0-beta.4) / getExtraKeybind (<= 5.0.0-beta.3) in the future.
try {
okZoomerAreExtraKeyBindsEnabledMethod = okZoomerZoomKeybindsClass.getDeclaredMethod(okZoomerAreExtraKeyBindsEnabledMethodNameString);
} catch (NoSuchMethodException exception) {
MidnightControls.warn("MidnightControls failed to reflect to an Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
exception.printStackTrace();
return;
}
didAllReflectionCallsSucceed = true;
}
@Override
public void handle() {
if (didAllReflectionCallsSucceed) {
new ButtonBinding.Builder("zoom")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
.onlyInGame()
.cooldown(true)
.category(ButtonBinding.MISC_CATEGORY)
.linkKeybind(okZoomerZoomKey)
.register();
boolean okZoomerAreExtraKeyBindsEnabled = false;
try {
okZoomerAreExtraKeyBindsEnabled = (boolean) okZoomerAreExtraKeyBindsEnabledMethod.invoke(null);
} catch (IllegalAccessException exception) {
MidnightControls.warn("MidnightControls encountered an IllegalAccessException while attempting to invoke a reflected Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
exception.printStackTrace();
} catch (InvocationTargetException exception) {
MidnightControls.warn("MidnightControls encountered an InvocationTargetException while attempting to invoke a reflected Ok Zoomer method (areExtraKeyBindsEnabled / areExtraKeybindsEnabled)!");
exception.printStackTrace();
}
if (okZoomerAreExtraKeyBindsEnabled) {
new ButtonBinding.Builder("zoom_in")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
.onlyInGame()
.cooldown(true)
.category(ButtonBinding.MISC_CATEGORY)
.linkKeybind(okZoomerIncreaseZoomKey)
.register();
new ButtonBinding.Builder("zoom_out")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
.onlyInGame()
.cooldown(true)
.category(ButtonBinding.MISC_CATEGORY)
.linkKeybind(okZoomerDecreaseZoomKey)
.register();
new ButtonBinding.Builder("zoom_reset")
.onlyInGame()
.cooldown(true)
.category(ButtonBinding.MISC_CATEGORY)
.linkKeybind(okZoomerResetZoomKey)
.register();
}
}
}
}

View File

@@ -0,0 +1,20 @@
package eu.midnightdust.midnightcontrols.client.compat;
import eu.midnightdust.midnightcontrols.client.compat.mixin.sodium.SodiumOptionsGUIAccessor;
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
import net.minecraft.client.gui.screen.Screen;
public class SodiumCompat implements CompatHandler {
@Override
public boolean handleTabs(Screen screen, boolean direction) {
if (screen instanceof SodiumOptionsGUI optionsGUI) {
SodiumOptionsGUIAccessor accessor = (SodiumOptionsGUIAccessor) optionsGUI;
final int max = accessor.getPages().size()-1;
int i = accessor.getPages().indexOf(accessor.getCurrentPage());
i = (direction ? ((max > i) ? ++i : 0) : (i > 0 ? --i : max));
optionsGUI.setPage(accessor.getPages().get(i));
return true;
}
return false;
}
}

View File

@@ -0,0 +1,57 @@
package eu.midnightdust.midnightcontrols.client.compat;
import dev.isxander.yacl.gui.AbstractWidget;
import dev.isxander.yacl.gui.OptionListWidget;
import dev.isxander.yacl.gui.YACLScreen;
import dev.isxander.yacl.gui.controllers.ControllerWidget;
import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.Screen;
import org.lwjgl.glfw.GLFW;
public class YACLCompat implements CompatHandler {
public static boolean handleAButton(Screen screen, Element element) {
if (element instanceof AbstractWidget abstractWidget) {
// imitate enter key press
return abstractWidget.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0);
}
return false;
}
public static boolean handleLeftRight(Screen screen, boolean direction) {
if (screen instanceof YACLScreen yaclScreen) {
SliderControllerElement focusedSlider = yaclScreen.optionList.children().stream()
.filter(OptionListWidget.OptionEntry.class::isInstance)
.map(entry -> ((OptionListWidget.OptionEntry) entry).widget)
.filter(ControllerWidget.class::isInstance)
.map(ControllerWidget.class::cast)
.filter(SliderControllerElement.class::isInstance)
.map(SliderControllerElement.class::cast)
.filter(ControllerWidget::isHovered)
.findFirst()
.orElse(null);
if (focusedSlider == null)
return false;
focusedSlider.incrementValue(direction ? 1 : -1);
return true;
}
return false;
}
@Override
public boolean handleTabs(Screen screen, boolean direction) {
if (screen instanceof YACLScreen yaclScreen) {
int categoryIdx = yaclScreen.getCurrentCategoryIdx();
if (direction) categoryIdx++; else categoryIdx--;
if (categoryIdx < 0) categoryIdx = yaclScreen.config.categories().size() - 1;
if (categoryIdx >= yaclScreen.config.categories().size()) categoryIdx = 0;
yaclScreen.changeCategory(categoryIdx);
return true;
}
return false;
}
}

View File

@@ -0,0 +1,19 @@
package eu.midnightdust.midnightcontrols.client.compat.mixin.sodium;
import me.jellysquid.mods.sodium.client.gui.SodiumOptionsGUI;
import me.jellysquid.mods.sodium.client.gui.options.OptionPage;
import me.jellysquid.mods.sodium.client.gui.options.control.ControlElement;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(value = SodiumOptionsGUI.class, remap = false)
public interface SodiumOptionsGUIAccessor {
@Accessor
List<ControlElement<?>> getControls();
@Accessor
List<OptionPage> getPages();
@Accessor
OptionPage getCurrentPage();
}