diff --git a/.gitignore b/.gitignore index 1d48d5b..5262594 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,13 @@ # # LambdAurora's ignore file # -# v0.12 +# v0.13 # JetBrains .idea/ *.iml +*.ipr +*.iws ## Intellij IDEA out/ ## CLion diff --git a/build.gradle b/build.gradle index 3d49655..960a8f5 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,20 @@ allprojects { classifier = "sources" from sourceSets.main.allSource } + + publishing { + repositories { + mavenLocal() + maven { + name = "GithubPackages" + url = uri("https://maven.pkg.github.com/LambdAurora/LambdaControls") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") + password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") + } + } + } + } } /* diff --git a/core/build.gradle b/core/build.gradle index 92e20eb..18a4eca 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java-library' + id 'maven-publish' } archivesBaseName = project.archives_base_name + "-core" @@ -15,3 +16,17 @@ java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } + +publishing { + publications { + mavenJava(MavenPublication) { + // add all the jars that should be included when publishing to maven + artifact(jar) { + builtBy jar + } + artifact(sourcesJar) { + builtBy sourcesJar + } + } + } +} diff --git a/fabric/build.gradle b/fabric/build.gradle index 54d5aee..c3fe3fb 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -4,6 +4,7 @@ plugins { id 'maven-publish' } +version = "${project.mod_version}+${project.minecraft_version}" archivesBaseName = project.archives_base_name + "-fabric" minecraft { @@ -91,4 +92,20 @@ jar { } } +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + // add all the jars that should be included when publishing to maven + artifact(remapJar) { + builtBy remapJar + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } + } + } +} + build.dependsOn(":core:build") +publish.dependsOn(":core:publish") diff --git a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/LambdaInput.java b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/LambdaInput.java index 8f309d6..c6754a2 100644 --- a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/LambdaInput.java +++ b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/LambdaInput.java @@ -72,24 +72,24 @@ import static org.lwjgl.glfw.GLFW.*; * Represents the LambdaControls' input handler. * * @author LambdAurora - * @version 1.3.0 + * @version 1.3.1 * @since 1.0.0 */ public class LambdaInput { - private static final Map BUTTON_COOLDOWNS = new HashMap<>(); + private static final Map BUTTON_COOLDOWNS = new HashMap<>(); private final LambdaControlsConfig config; // Cooldowns - private int actionGuiCooldown = 0; - private int ignoreNextA = 0; - private double targetYaw = 0.0; - private double targetPitch = 0.0; - private float prevXAxis = 0.F; - private float prevYAxis = 0.F; - private int targetMouseX = 0; - private int targetMouseY = 0; - private float mouseSpeedX = 0.F; - private float mouseSpeedY = 0.F; + private int actionGuiCooldown = 0; + private boolean ignoreNextARelease = false; + private double targetYaw = 0.0; + private double targetPitch = 0.0; + private float prevXAxis = 0.F; + private float prevYAxis = 0.F; + private int targetMouseX = 0; + private int targetMouseY = 0; + private float mouseSpeedX = 0.F; + private float mouseSpeedY = 0.F; public LambdaInput(@NotNull LambdaControlsClient mod) { @@ -156,9 +156,6 @@ public class LambdaInput if (allowInput) InputManager.updateBindings(client); - if (this.ignoreNextA > 0) - this.ignoreNextA--; - if (client.currentScreen instanceof ControllerControlsScreen && InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) { ControllerControlsScreen screen = (ControllerControlsScreen) client.currentScreen; if (screen.focusedBinding != null && !screen.waiting) { @@ -321,31 +318,12 @@ public class LambdaInput } } - if (client.currentScreen instanceof HandledScreen && client.interactionManager != null && client.player != null) { - 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(); - Slot slot = ((HandledScreenAccessor) client.currentScreen).lambdacontrols_getSlotAt(x, y); - SlotActionType slotAction = SlotActionType.PICKUP; - if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && slot != null) { - if (client.currentScreen instanceof CreativeInventoryScreen) { - if (((CreativeInventoryScreenAccessor) client.currentScreen).lambdacontrols_isCreativeInventorySlot(slot)) - slotAction = SlotActionType.CLONE; - } - client.interactionManager.clickSlot(((HandledScreen) client.currentScreen).getScreenHandler().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_1, slotAction, client.player); - client.player.playerScreenHandler.sendContentUpdates(); - this.actionGuiCooldown = 5; - return; - } else if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) { - client.player.closeHandledScreen(); - return; - } else if (button == GLFW.GLFW_GAMEPAD_BUTTON_X && slot != null) { - client.interactionManager.clickSlot(((HandledScreen) client.currentScreen).getScreenHandler().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_2, SlotActionType.PICKUP, client.player); - return; - } else if (button == GLFW.GLFW_GAMEPAD_BUTTON_Y && slot != null) { - client.interactionManager.clickSlot(((HandledScreen) client.currentScreen).getScreenHandler().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_1, SlotActionType.QUICK_MOVE, client.player); - return; - } - } else if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) { + if (this.handleInventory(client, button)) { + this.ignoreNextARelease = true; + return; + } + + if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) { if (client.currentScreen != null) { client.currentScreen.onClose(); return; @@ -353,18 +331,80 @@ public class LambdaInput } } - if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0 && this.ignoreNextA == 0) { - double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); - double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); - if (action == 0) { - client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1); - } else if (action == 1) { - client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1); + if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0) { + if (!this.ignoreNextARelease) { + double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); + double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); + if (action == 0) { + client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1); + } else if (action == 1) { + client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1); + } + this.actionGuiCooldown = 5; + } else { + this.ignoreNextARelease = false; } - this.actionGuiCooldown = 5; } } + /** + * Handles inventory interaction. + * + * @param client The client instance. + * @param button The button pressed. + * @return True if an inventory interaction was done. + */ + private boolean handleInventory(@NotNull MinecraftClient client, int button) + { + if (!(client.currentScreen instanceof HandledScreen)) + return false; + + if (client.interactionManager == null || client.player == null) + return false; + + if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) { + client.player.closeHandledScreen(); + return true; + } + + 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(); + + HandledScreen screen = (HandledScreen) client.currentScreen; + HandledScreenAccessor accessor = (HandledScreenAccessor) screen; + Slot slot = ((HandledScreenAccessor) client.currentScreen).lambdacontrols_getSlotAt(x, y); + + int slotId; + if (slot == null) { + if (client.player.inventory.getCursorStack().isEmpty()) + return false; + slotId = accessor.lambdacontrols_isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1; + } else { + slotId = slot.id; + } + + SlotActionType actionType = SlotActionType.PICKUP; + int clickData = GLFW.GLFW_MOUSE_BUTTON_1; + switch (button) { + case GLFW_GAMEPAD_BUTTON_A: + if (screen instanceof CreativeInventoryScreen) + if (((CreativeInventoryScreenAccessor) screen).lambdacontrols_isCreativeInventorySlot(slot)) + actionType = SlotActionType.CLONE; + break; + case GLFW.GLFW_GAMEPAD_BUTTON_X: + clickData = GLFW_MOUSE_BUTTON_2; + break; + case GLFW.GLFW_GAMEPAD_BUTTON_Y: + actionType = SlotActionType.QUICK_MOVE; + break; + default: + return false; + } + + accessor.lambdacontrols_onMouseClick(slot, slotId, clickData, actionType); + return true; + } + private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) { int asButtonState = value > 0.5F ? 1 : (value < -0.5F ? 2 : 0); diff --git a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/gui/LambdaControlsRenderer.java b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/gui/LambdaControlsRenderer.java index 3749a72..6f73e54 100644 --- a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/gui/LambdaControlsRenderer.java +++ b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/gui/LambdaControlsRenderer.java @@ -24,14 +24,11 @@ import org.aperlambda.lambdacommon.utils.Pair; import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; -import java.util.Comparator; -import java.util.Optional; - /** * Represents the LambdaControls renderer. * * @author LambdAurora - * @version 1.3.0 + * @version 1.3.1 * @since 1.2.0 */ public class LambdaControlsRenderer @@ -240,27 +237,13 @@ public class LambdaControlsRenderer boolean hoverSlot = false; if (client.currentScreen instanceof HandledScreen) { - HandledScreen inventoryScreen = (HandledScreen) client.currentScreen; - HandledScreenAccessor accessor = (HandledScreenAccessor) inventoryScreen; - int guiLeft = accessor.getX(); - int guiTop = accessor.getY(); + HandledScreenAccessor inventoryScreen = (HandledScreenAccessor) client.currentScreen; + int guiLeft = inventoryScreen.getX(); + int guiTop = inventoryScreen.getY(); - // Finds the closest slot in the GUI within 14 pixels. - int finalMouseX = mouseX; - int finalMouseY = mouseY; - Optional> closestSlot = inventoryScreen.getScreenHandler().slots.parallelStream() - .map(slot -> { - int x = guiLeft + slot.x + 8; - int y = guiTop + slot.y + 8; + Slot slot = inventoryScreen.lambdacontrols_getSlotAt(mouseX, mouseY); - // Distance between the slot and the cursor. - double distance = Math.sqrt(Math.pow(x - finalMouseX, 2) + Math.pow(y - finalMouseY, 2)); - return Pair.of(slot, distance); - }).filter(entry -> entry.value <= 9.0) - .min(Comparator.comparingDouble(p -> p.value)); - - if (closestSlot.isPresent()) { - Slot slot = closestSlot.get().key; + if (slot != null) { mouseX = guiLeft + slot.x; mouseY = guiTop + slot.y; hoverSlot = true; diff --git a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/mixin/HandledScreenMixin.java b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/mixin/HandledScreenMixin.java index fd97430..7d47d36 100644 --- a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/mixin/HandledScreenMixin.java +++ b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/mixin/HandledScreenMixin.java @@ -18,14 +18,19 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Arrays; + /** * Represents the mixin for the class ContainerScreen. */ @@ -41,6 +46,12 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor @Invoker("getSlotAt") public abstract Slot lambdacontrols_getSlotAt(double posX, double posY); + @Invoker("isClickOutsideBounds") + public abstract boolean lambdacontrols_isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button); + + @Invoker("onMouseClick") + public abstract void lambdacontrols_onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType); + @Inject(method = "render", at = @At("RETURN")) public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) { diff --git a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/mixin/MouseMixin.java b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/mixin/MouseMixin.java index 61bf4db..cb62662 100644 --- a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/mixin/MouseMixin.java +++ b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/mixin/MouseMixin.java @@ -13,12 +13,16 @@ import me.lambdaurora.lambdacontrols.ControlsMode; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsConfig; import me.lambdaurora.lambdacontrols.client.util.MouseAccessor; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.Mouse; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** * Adds extra access to the mouse. @@ -26,14 +30,31 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Mouse.class) public abstract class MouseMixin implements MouseAccessor { + @Shadow + @Final + private MinecraftClient client; + @Invoker("onCursorPos") public abstract void lambdacontrols_onCursorPos(long window, double x, double y); + @Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true) + private void isCursorLocked(CallbackInfoReturnable ci) + { + if (client.currentScreen == null) { + LambdaControlsConfig config = LambdaControlsClient.get().config; + if (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse()) { + ci.setReturnValue(true); + ci.cancel(); + } + } + } + @Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true) - private void onMouseLocked(CallbackInfo ci) + private void onCursorLocked(CallbackInfo ci) { LambdaControlsConfig config = LambdaControlsClient.get().config; - if (config.getControlsMode() == ControlsMode.TOUCHSCREEN || config.hasVirtualMouse()) + if (config.getControlsMode() == ControlsMode.TOUCHSCREEN + || (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse())) ci.cancel(); } } diff --git a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/ring/KeyBindingRing.java b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/ring/KeyBindingRing.java new file mode 100644 index 0000000..ddc8a3e --- /dev/null +++ b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/ring/KeyBindingRing.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2020 LambdAurora + * + * This file is part of LambdaControls. + * + * Licensed under the MIT license. For more information, + * see the LICENSE file. + */ + +package me.lambdaurora.lambdacontrols.client.ring; + +/** + * Represents a key binding ring. + * + * @author LambdAurora + * @version 1.4.0 + * @since 1.4.0 + */ +public class KeyBindingRing +{ + +} diff --git a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/util/HandledScreenAccessor.java b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/util/HandledScreenAccessor.java index dfb35e1..443a743 100644 --- a/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/util/HandledScreenAccessor.java +++ b/fabric/src/main/java/me/lambdaurora/lambdacontrols/client/util/HandledScreenAccessor.java @@ -10,6 +10,8 @@ package me.lambdaurora.lambdacontrols.client.util; import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import org.jetbrains.annotations.Nullable; /** * Represents an accessor to AbstractContainerScreen. @@ -38,4 +40,16 @@ public interface HandledScreenAccessor * @return The slot at the specified position. */ Slot lambdacontrols_getSlotAt(double pos_x, double pos_y); + + boolean lambdacontrols_isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button); + + /** + * Handles a mouse click on the specified slot. + * + * @param slot The slot instance. + * @param slotId The slot id. + * @param clickData The click data. + * @param actionType The action type. + */ + void lambdacontrols_onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType); } diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 4c433bf..884dda5 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -34,7 +34,7 @@ "fabricloader": ">=0.8.0", "fabric": "*", "minecraft": ">=1.16", - "spruceui": ">=1.5.1" + "spruceui": ">=1.5.2" }, "recommends": { "modmenu": ">=1.12.2", @@ -49,6 +49,10 @@ "optifabric": "*" }, "custom": { - "modmenu:clientsideOnly": true + "modmenu:clientsideOnly": true, + "modupdater": { + "strategy": "curseforge", + "projectID": 354231 + } } } diff --git a/gradle.properties b/gradle.properties index 3db8c04..e7a37ae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,12 +8,12 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.8.8+build.202 # Mod Properties - mod_version = 1.3.0 - maven_group = me.lambdaurora + mod_version = 1.3.1 + maven_group = me.lambdaurora.lambdacontrols archives_base_name = lambdacontrols # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api fabric_version=0.14.0+build.371-1.16 - spruceui_version=1.5.1 + spruceui_version=1.5.2 modmenu_version=1.12.2+build.17