mirror of
https://github.com/TeamMidnightDust/MidnightControls.git
synced 2025-12-16 08:35:10 +01:00
MidnightControls 0.1.0 (Beta)
Changes from LambdaControls: - Support for Steam Deck and Dualsense - Support for L4, L5, R4, R5 buttons - Updated Libraries - New Logo and Name - Lots of Bugfixes - MidnightConfig backend
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @param mod this mod instance
|
||||
*/
|
||||
void handle(@NotNull MidnightControlsClient mod);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen;
|
||||
import io.github.kosmx.emotes.main.network.ClientEmotePlay;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
/**
|
||||
* Represents a compatibility handler for Emotecraft.
|
||||
*
|
||||
* @author Motschen
|
||||
* @version 1.4.3
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class EmotecraftCompat implements CompatHandler {
|
||||
@Override
|
||||
public void handle(@NotNull MidnightControlsClient mod) {
|
||||
new ButtonBinding.Builder("key.emotecraft.fastchoose")
|
||||
.buttons(16)
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.action((client, button, value, action) -> {
|
||||
client.setScreen(new FastChosseScreen(null));
|
||||
return true;
|
||||
})
|
||||
.register();
|
||||
new ButtonBinding.Builder("key.emotecraft.stop")
|
||||
.buttons(17)
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.action((client, button, value, action) -> {
|
||||
ClientEmotePlay.clientStopLocalEmote();
|
||||
return true;
|
||||
})
|
||||
.register();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.gui.screen.Screen;
|
||||
import org.aperlambda.lambdacommon.utils.LambdaReflection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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(@NotNull MidnightControlsClient mod) {
|
||||
this.guiBaseClass = LambdaReflection.getClass(GUI_BASE_CLASS_PATH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireMouseOnScreen(Screen screen) {
|
||||
return this.guiBaseClass.map(clazz -> clazz.isInstance(screen)).orElse(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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 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;
|
||||
|
||||
/**
|
||||
* Represents a compatibility handler.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.5.0
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class MidnightControlsCompat {
|
||||
private static final List<CompatHandler> HANDLERS = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Initializes compatibility with other mods if needed.
|
||||
*
|
||||
* @param mod the mod instance
|
||||
*/
|
||||
public static void init(@NotNull MidnightControlsClient mod) {
|
||||
if (FabricLoader.getInstance().isModLoaded("okzoomer")) {
|
||||
mod.log("Adding okzoomer compatibility...");
|
||||
HANDLERS.add(new OkZoomerCompat());
|
||||
}
|
||||
/*if (isReiPresent()) {
|
||||
mod.log("Adding REI compatiblity...");
|
||||
HANDLERS.add(new ReiCompat());
|
||||
}*/
|
||||
if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) {
|
||||
mod.log("Adding HQM compatibility...");
|
||||
HANDLERS.add(new HQMCompat());
|
||||
}
|
||||
if (FabricLoader.getInstance().isModLoaded("emotecraft")) {
|
||||
mod.log("Adding Emotecraft compatibility...");
|
||||
HANDLERS.add(new EmotecraftCompat());
|
||||
}
|
||||
HANDLERS.forEach(handler -> handler.handle(mod));
|
||||
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 HANDLERS.stream().anyMatch(handler -> handler.requireMouseOnScreen(screen));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Roughly Enough Items is present.
|
||||
*
|
||||
* @return true if Roughly Enough Items is present, else false
|
||||
*/
|
||||
public static boolean isReiPresent() {
|
||||
return FabricLoader.getInstance().isModLoaded("roughlyenoughitems");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 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
|
||||
* @version 1.5.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class MidnightControlsMixinPlugin implements IMixinConfigPlugin {
|
||||
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>();
|
||||
|
||||
public MidnightControlsMixinPlugin() {
|
||||
this.putConditionalMixin("EntryListWidgetAccessor", MidnightControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("EntryWidgetAccessor", MidnightControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("RecipeViewingScreenAccessor", MidnightControlsCompat.isReiPresent());
|
||||
this.putConditionalMixin("VillagerRecipeViewingScreenAccessor", MidnightControlsCompat.isReiPresent());
|
||||
}
|
||||
|
||||
private void putConditionalMixin(@NotNull String path, boolean condition) {
|
||||
this.conditionalMixins.put("me.lambdaurora.midnightcontrols.client.compat.mixin." + path, condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
return this.conditionalMixins.getOrDefault(mixinClassName, Boolean.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) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import io.github.ennuil.okzoomer.keybinds.ZoomKeybinds;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
/**
|
||||
* Represents a compatibility handler for OkZoomer.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.4.3
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class OkZoomerCompat implements CompatHandler {
|
||||
@Override
|
||||
public void handle(@NotNull MidnightControlsClient mod) {
|
||||
new ButtonBinding.Builder("zoom")
|
||||
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(ZoomKeybinds.zoomKey)
|
||||
.register();
|
||||
|
||||
if (ZoomKeybinds.areExtraKeybindsEnabled()) {
|
||||
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(ZoomKeybinds.increaseZoomKey)
|
||||
.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(ZoomKeybinds.decreaseZoomKey)
|
||||
.register();
|
||||
new ButtonBinding.Builder("zoom_reset")
|
||||
.onlyInGame()
|
||||
.cooldown(true)
|
||||
.category(ButtonBinding.MISC_CATEGORY)
|
||||
.linkKeybind(ZoomKeybinds.resetZoomKey)
|
||||
.register();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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.ButtonState;
|
||||
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.InputHandlers;
|
||||
import eu.midnightdust.midnightcontrols.client.controller.PressAction;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
/**
|
||||
* Represents a compatibility handler for REI.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.7.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class ReiCompat implements CompatHandler {
|
||||
//private static EntryListWidget ENTRY_LIST_WIDGET;
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull MidnightControlsClient mod) {
|
||||
ButtonBinding.builder(new Identifier("rei", "category_back"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleTab(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "category_next"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleTab(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
ButtonBinding.builder(new Identifier("rei", "page_back"))
|
||||
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, false))
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handlePage(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "page_next"))
|
||||
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, true))
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handlePage(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
ButtonBinding.builder(new Identifier("rei", "recipe_back"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleRecipe(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
ButtonBinding.builder(new Identifier("rei", "recipe_next"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
|
||||
.filter((client, binding) -> isViewingScreen(client.currentScreen))
|
||||
.action(handleRecipe(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
// For some reasons this is broken.
|
||||
ButtonBinding.builder(new Identifier("rei", "show_usage"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handleShowRecipeUsage(true))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
|
||||
ButtonBinding.builder(new Identifier("rei", "show_recipe"))
|
||||
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
|
||||
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
|
||||
.action(handleShowRecipeUsage(false))
|
||||
.cooldown(true)
|
||||
.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireMouseOnScreen(Screen screen) {
|
||||
return isViewingScreen(screen) /*|| screen instanceof PreRecipeViewingScreen*/;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SlotPos getSlotAt(@NotNull Screen screen, int mouseX, int mouseY) {
|
||||
/*var overlay = ScreenHelper.getOptionalOverlay();
|
||||
if (overlay.isPresent() && overlay.get().isInside(mouseX, mouseY)) {
|
||||
var widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return null;
|
||||
|
||||
var slot = this.getSlotAt(widget, mouseX, mouseY, false);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
} else if (isViewingScreen(screen)) {
|
||||
for (var element : screen.children()) {
|
||||
var slot = this.getSlotAt(element, mouseX, mouseY, true);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
}
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
|
||||
/*private @Nullable SlotPos getSlotAt(@NotNull Element element, int mouseX, int mouseY, boolean allowEmpty) {
|
||||
if (element instanceof EntryWidget entry) {
|
||||
if (entry.containsMouse(mouseX, mouseY)) {
|
||||
if (!allowEmpty && entry.entries().isEmpty())
|
||||
return INVALID_SLOT;
|
||||
return new SlotPos(entry.getBounds().getX() + 1, entry.getBounds().getY() + 1);
|
||||
}
|
||||
} else if (element instanceof EntryListWidget) {
|
||||
List<EntryListEntryWidget> entries = ((EntryListWidgetAccessor) element).getEntries();
|
||||
for (EntryListEntryWidget entry : entries) {
|
||||
var slot = this.getSlotAt(entry, mouseX, mouseY, allowEmpty);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
}
|
||||
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds widgetWithBounds) {
|
||||
for (var child : widgetWithBounds.children()) {
|
||||
var slot = this.getSlotAt(child, mouseX, mouseY, allowEmpty);
|
||||
if (slot != null && slot != INVALID_SLOT)
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
|
||||
private static boolean isViewingScreen(Screen screen) {
|
||||
return true;
|
||||
//return screen instanceof DefaultDisplayViewingScreen || screen instanceof CompositeDisplayViewingScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMenuBack(@NotNull MinecraftClient client, @NotNull Screen screen) {
|
||||
if (!isViewingScreen(screen))
|
||||
return false;
|
||||
|
||||
/*MinecraftClient.getInstance().openScreen(REIRuntimeImpl.getInstance().getPreviousContainerScreen());
|
||||
ScreenHelper.getLastOverlay().init();*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/*private static EntryListWidget getEntryListWidget() {
|
||||
if (ENTRY_LIST_WIDGET == null) {
|
||||
ENTRY_LIST_WIDGET = LambdaReflection.getFirstFieldOfType(ContainerScreenOverlay.class, EntryListWidget.class)
|
||||
.map(field -> (EntryListWidget) LambdaReflection.getFieldValue(null, field))
|
||||
.orElse(null);
|
||||
}
|
||||
return ENTRY_LIST_WIDGET;
|
||||
}
|
||||
|
||||
private static @Nullable EntryStack getCurrentStack(@NotNull MinecraftClient client) {
|
||||
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
|
||||
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
|
||||
|
||||
if (isViewingScreen(client.currentScreen)) {
|
||||
for (var element : client.currentScreen.children()) {
|
||||
var stack = getCurrentStack(element, x, y);
|
||||
if (stack != null)
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
var overlay = ScreenHelper.getOptionalOverlay();
|
||||
if (!overlay.isPresent())
|
||||
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
||||
var widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
||||
|
||||
return getCurrentStack(widget, x, y);
|
||||
}
|
||||
|
||||
private static @Nullable EntryStack getCurrentStack(@NotNull Element element, double mouseX, double mouseY) {
|
||||
if (element instanceof EntryWidget entry) {
|
||||
if (entry.containsMouse(mouseX, mouseY))
|
||||
return ((EntryWidgetAccessor) entry).midnightcontrols_getCurrentEntry();
|
||||
} else if (element instanceof EntryListWidget) {
|
||||
var entries = ((EntryListWidgetAccessor) element).getEntries();
|
||||
for (EntryListEntryWidget entry : entries) {
|
||||
if (entry.containsMouse(mouseX, mouseY)) {
|
||||
return ((EntryWidgetAccessor) entry).midnightcontrols_getCurrentEntry();
|
||||
}
|
||||
}
|
||||
} else if (!(element instanceof ButtonWidget) && element instanceof WidgetWithBounds widgetWithBounds) {
|
||||
for (var child : widgetWithBounds.children()) {
|
||||
var stack = getCurrentStack(child, mouseX, mouseY);
|
||||
if (stack != null)
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
|
||||
private static PressAction handleShowRecipeUsage(boolean usage) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action.isUnpressed())
|
||||
return false;
|
||||
|
||||
/*EntryStack stack = RecipeHelper.getInstance().getScreenFocusedStack(client.currentScreen);
|
||||
if (stack == null) {
|
||||
stack = getCurrentStack(client);
|
||||
}
|
||||
|
||||
if (stack != null && !stack.isEmpty()) {
|
||||
stack = stack.copy();
|
||||
if (usage) {
|
||||
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addUsagesFor(stack).setInputNotice(stack).fillPreferredOpenedCategory());
|
||||
} else {
|
||||
return ClientHelper.getInstance().openView(ClientHelper.ViewSearchBuilder.builder().addRecipesFor(stack).setOutputNotice(stack).fillPreferredOpenedCategory());
|
||||
}
|
||||
}*/
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static PressAction handlePage(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action == ButtonState.RELEASE)
|
||||
return false;
|
||||
|
||||
/*Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
|
||||
if (!overlay.isPresent())
|
||||
return false;
|
||||
|
||||
var widget = getEntryListWidget();
|
||||
if (widget == null)
|
||||
return false;
|
||||
|
||||
if (next)
|
||||
widget.nextPage();
|
||||
else
|
||||
widget.previousPage();
|
||||
widget.updateEntriesPosition();*/
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the handler for category tabs buttons.
|
||||
*
|
||||
* @param next True if the action is to switch to the next tab.
|
||||
* @return The handler.
|
||||
*/
|
||||
private static PressAction handleTab(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action != ButtonState.RELEASE)
|
||||
return false;
|
||||
|
||||
/*if (client.currentScreen instanceof DefaultDisplayViewingScreen) {
|
||||
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
|
||||
if (next)
|
||||
screen.getCategoryNext().onClick();
|
||||
else
|
||||
screen.getCategoryBack().onClick();
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof CompositeDisplayViewingScreen) {
|
||||
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
|
||||
List<RecipeCategory<?>> categories = screen.getCategories();
|
||||
int currentTab = screen.getSelectedCategoryIndex();
|
||||
screen.setSelectedCategoryIndex(getNextIndex(currentTab, categories.size(), next));
|
||||
screen.setSelectedRecipeIndex(0);
|
||||
screen.midnightcontrols_init();
|
||||
return true;
|
||||
}*/
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static PressAction handleRecipe(boolean next) {
|
||||
return (client, button, value, action) -> {
|
||||
if (action.isUnpressed())
|
||||
return false;
|
||||
|
||||
/*if (client.currentScreen instanceof RecipeViewingScreenAccessor screen) {
|
||||
if (next)
|
||||
screen.getRecipeNext().onClick();
|
||||
else
|
||||
screen.getRecipeBack().onClick();
|
||||
return true;
|
||||
} else if (client.currentScreen instanceof VillagerRecipeViewingScreenAccessor screen) {
|
||||
List<RecipeCategory<?>> categories = screen.getCategories();
|
||||
int currentTab = screen.getSelectedCategoryIndex();
|
||||
List<RecipeDisplay> recipes = screen.getCategoryMap().get(categories.get(currentTab));
|
||||
|
||||
if (recipes.size() == 0)
|
||||
return true;
|
||||
|
||||
int currentRecipe = screen.getSelectedRecipeIndex();
|
||||
int nextRecipe = getNextIndex(currentRecipe, recipes.size(), next);
|
||||
|
||||
if (nextRecipe == 0) {
|
||||
screen.getScrolling().scrollTo(0.0, true);
|
||||
} else if (nextRecipe == recipes.size() - 1) {
|
||||
screen.getScrolling().scrollTo(screen.getScrolling().getMaxScroll(), true);
|
||||
} else {
|
||||
double scrollAmount = screen.getScrolling().getMaxScroll() / (float) recipes.size();
|
||||
screen.getScrolling().offset(next ? scrollAmount : -scrollAmount, true);
|
||||
}
|
||||
|
||||
screen.setSelectedRecipeIndex(nextRecipe);
|
||||
screen.midnightcontrols_init();
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static int getNextIndex(int currentIndex, int size, boolean next) {
|
||||
int nextIndex = currentIndex + (next ? 1 : -1);
|
||||
if (nextIndex < 0)
|
||||
nextIndex = size - 1;
|
||||
else if (nextIndex >= size)
|
||||
nextIndex = 0;
|
||||
return nextIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.mixin;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's EntryListWidget.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.5.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
//@Mixin(value = EntryListWidget.class, remap = false)
|
||||
public interface EntryListWidgetAccessor {
|
||||
/*@Accessor(value = "entries")
|
||||
List<EntryListEntryWidget> getEntries();*/
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.mixin;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's EntryWidget.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.5.0
|
||||
* @since 1.5.0
|
||||
*/
|
||||
//@Mixin(value = EntryWidget.class, remap = false)
|
||||
public interface EntryWidgetAccessor {
|
||||
/*@Invoker("getCurrentEntry")
|
||||
EntryStack midnightcontrols_getCurrentEntry();*/
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.mixin;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's RecipeViewingScreen.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.7.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
//@Mixin(value = DefaultDisplayViewingScreen.class, remap = false)
|
||||
public interface RecipeViewingScreenAccessor {
|
||||
/*@Accessor("categoryBack")
|
||||
Button getCategoryBack();
|
||||
|
||||
@Accessor("categoryNext")
|
||||
Button getCategoryNext();
|
||||
|
||||
@Accessor("recipeBack")
|
||||
Button getRecipeBack();
|
||||
|
||||
@Accessor("recipeNext")
|
||||
Button getRecipeNext();*/
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.mixin;
|
||||
|
||||
/**
|
||||
* Represents an accessor to REI's VillagerRecipeViewingScreen.
|
||||
*
|
||||
* @author LambdAurora
|
||||
* @version 1.7.0
|
||||
* @since 1.2.0
|
||||
*/
|
||||
//@Mixin(CompositeDisplayViewingScreen.class)
|
||||
public interface VillagerRecipeViewingScreenAccessor {
|
||||
/*@Accessor(value = "categoryMap", remap = false)
|
||||
Map<DisplayCategory<?>, List<Display>> getCategoryMap();
|
||||
|
||||
@Accessor(value = "categories", remap = false)
|
||||
List<DisplayCategory<?>> getCategories();
|
||||
|
||||
@Accessor(value = "selectedCategoryIndex", remap = false)
|
||||
int getSelectedCategoryIndex();
|
||||
|
||||
@Accessor(value = "selectedCategoryIndex", remap = false)
|
||||
void setSelectedCategoryIndex(int selectedCategoryIndex);
|
||||
|
||||
@Accessor(value = "selectedRecipeIndex", remap = false)
|
||||
int getSelectedRecipeIndex();
|
||||
|
||||
@Accessor(value = "selectedRecipeIndex", remap = false)
|
||||
void setSelectedRecipeIndex(int selectedRecipeIndex);
|
||||
|
||||
@Accessor(value = "scrolling", remap = false)
|
||||
ScrollingContainer getScrolling();
|
||||
|
||||
@Invoker("init")
|
||||
void midnightcontrols_init();*/
|
||||
}
|
||||
Reference in New Issue
Block a user