From a7c317789010c382b5561670b7786d403b4191b9 Mon Sep 17 00:00:00 2001 From: KosmX Date: Sat, 15 Jul 2023 18:14:32 +0200 Subject: [PATCH 1/7] Add ClothConfig (autoconfig) and modmenu config screen --- build.gradle | 10 +++++++ gradle.properties | 4 +++ .../slotswap/config/ModMenuEntry.java | 12 +++++++++ .../slotswap/config/SwapConfig.java | 26 +++++++++++++++++++ src/main/resources/fabric.mod.json | 3 +++ 5 files changed, 55 insertions(+) create mode 100644 src/main/java/com/turtlearmymc/slotswap/config/ModMenuEntry.java create mode 100644 src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java diff --git a/build.gradle b/build.gradle index 8d0e21a..9eb173f 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,8 @@ archivesBaseName = project.archives_base_name version = project.mod_version + "+mc" + project.minecraft_version repositories { + maven { url "https://maven.shedaniel.me/" } + maven { url "https://maven.terraformersmc.com/releases/" } } dependencies { @@ -18,6 +20,14 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + + modApi("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config}") { + exclude(group: "net.fabricmc.fabric-api") + } + + modApi "com.terraformersmc:modmenu:${project.modmenu}" + } processResources { diff --git a/gradle.properties b/gradle.properties index 330117c..8bf36e3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,3 +12,7 @@ loader_version = 0.14.21 # Dependencies fabric_version = 0.85.0+1.20.1 + +# These can be easily found here https://linkie.shedaniel.dev/dependencies +cloth_config = 11.1.106 +modmenu = 7.1.0 diff --git a/src/main/java/com/turtlearmymc/slotswap/config/ModMenuEntry.java b/src/main/java/com/turtlearmymc/slotswap/config/ModMenuEntry.java new file mode 100644 index 0000000..04b1b2b --- /dev/null +++ b/src/main/java/com/turtlearmymc/slotswap/config/ModMenuEntry.java @@ -0,0 +1,12 @@ +package com.turtlearmymc.slotswap.config; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; +import me.shedaniel.autoconfig.AutoConfig; + +public class ModMenuEntry implements ModMenuApi { + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return parent -> AutoConfig.getConfigScreen(SwapConfig.class, parent).get(); + } +} diff --git a/src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java b/src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java new file mode 100644 index 0000000..871c34a --- /dev/null +++ b/src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java @@ -0,0 +1,26 @@ +package com.turtlearmymc.slotswap.config; + +import me.shedaniel.autoconfig.ConfigData; +import me.shedaniel.autoconfig.annotation.Config; + +@Config(name = "slotswap") +public class SwapConfig implements ConfigData { + + public SwapMode swapMode = SwapMode.COMPATIBLE; + + public enum SwapMode { + /** + * Swap items using vanilla pick-item packet, likely safe to use everywhere but having issues + */ + COMPATIBLE, + + /** + * Use PlayerHandler swap packet, precisely swaps the items, may trigger anti-cheat + */ + SWAP, + /** + * Use same method as SWAP, but instead of swapping items, it cyclic-shift the column, it shouldn't shuffle items in inventory. + */ + SHIFT, + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ab8858c..4c78087 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -20,6 +20,9 @@ "entrypoints": { "client": [ "com.turtlearmymc.slotswap.SwapManager" + ], + "modmenu": [ + "com.turtlearmymc.slotswap.config.ModMenuEntry" ] }, "mixins": [ From 417255187b25ff321f4309db8beae2f2540ea6fc Mon Sep 17 00:00:00 2001 From: KosmX Date: Sat, 15 Jul 2023 18:15:11 +0200 Subject: [PATCH 2/7] Implement swap modes --- .../turtlearmymc/slotswap/SwapManager.java | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/turtlearmymc/slotswap/SwapManager.java b/src/main/java/com/turtlearmymc/slotswap/SwapManager.java index 6740262..221c67e 100644 --- a/src/main/java/com/turtlearmymc/slotswap/SwapManager.java +++ b/src/main/java/com/turtlearmymc/slotswap/SwapManager.java @@ -1,11 +1,16 @@ package com.turtlearmymc.slotswap; +import com.turtlearmymc.slotswap.config.SwapConfig; +import me.shedaniel.autoconfig.AutoConfig; +import me.shedaniel.autoconfig.serializer.JanksonConfigSerializer; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.slot.SlotActionType; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; @@ -16,6 +21,7 @@ public class SwapManager implements ClientModInitializer { public static final int ROW_COUNT = PlayerInventory.MAIN_SIZE / PlayerInventory.getHotbarSize(); private static int currentRow; private static boolean active; + public static SwapConfig CONFIG; private static @Nullable KeyBinding selectSlotKey = null; @@ -54,6 +60,10 @@ public static int getCurrentRow() { return active ? currentRow : 0; } + private static ClientPlayerInteractionManager getInteractionManager() { + return MinecraftClient.getInstance().interactionManager; + } + public static void scroll(PlayerInventory inv, int rowDelta) { tryStartSwap(); final int col = inv.selectedSlot; @@ -69,16 +79,60 @@ public static void scroll(PlayerInventory inv, int rowDelta) { } } + private static void swapSlots(PlayerInventory inv, int slotA, int slotB) { + + // clickSlot has a weird indexing: + // first slot arg is slot index, what is kinda random + // https://videa.hu/videok/film-animacio/laputa-az-egi-palota-124-perc-1986-KZZvhnBm2KnCxTNx?start=1920.560579 + + // second item is normal slot index + + final int slotAIndex = slotA < 9 ? slotA + PlayerInventory.MAIN_SIZE : slotA; + getInteractionManager().clickSlot(0, slotAIndex, slotB, SlotActionType.SWAP, MinecraftClient.getInstance().player); + } + + public static void tryDoSwap(PlayerInventory inv) { if (!active) return; active = false; if (currentRow == 0) return; // Hotbar selected - final int slot = rowColToSlot(currentRow, inv.selectedSlot); - MinecraftClient.getInstance().interactionManager.pickFromInventory(slot); + switch (CONFIG.swapMode) { + case COMPATIBLE -> { + final int slot = rowColToSlot(currentRow, inv.selectedSlot); + getInteractionManager().pickFromInventory(slot); + } + case SWAP -> { + final int slotA = rowColToSlot(currentRow, inv.selectedSlot); + final int slotB = rowColToSlot(0, inv.selectedSlot); + swapSlots(inv, slotA, slotB); + } + case SHIFT -> { + final int column = inv.selectedSlot; + final int distance = currentRow; + + for (int cycleStart = 0, nMoved = 0; nMoved != ROW_COUNT; cycleStart++) { + int i = cycleStart; + int displaced = i; + do { + i += distance; + if (i >= ROW_COUNT) + i -= ROW_COUNT; + swapSlots(inv, rowColToSlot(displaced, column), rowColToSlot(i, column)); + displaced = i; + nMoved++; + } while ((i + distance) % ROW_COUNT != cycleStart); + nMoved++; + } + } + } } @Override public void onInitializeClient() { + + AutoConfig.register(SwapConfig.class, JanksonConfigSerializer::new); + CONFIG = AutoConfig.getConfigHolder(SwapConfig.class).get(); + selectSlotKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( "key.slotswap.swap", InputUtil.Type.KEYSYM, From a75e2076210b91699bbc0234d78277217a2b6ee8 Mon Sep 17 00:00:00 2001 From: KosmX Date: Sat, 15 Jul 2023 18:29:14 +0200 Subject: [PATCH 3/7] Add translations and description --- src/main/resources/assets/slotswap/lang/en_US.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/resources/assets/slotswap/lang/en_US.json b/src/main/resources/assets/slotswap/lang/en_US.json index 9a730ea..141229e 100644 --- a/src/main/resources/assets/slotswap/lang/en_US.json +++ b/src/main/resources/assets/slotswap/lang/en_US.json @@ -1,3 +1,5 @@ { - "key.slotswap.swap": "Slot swap" + "key.slotswap.swap": "Slot swap", + "text.autoconfig.slotswap.option.swapMode": "Swap mode", + "text.autoconfig.slotswap.option.swapMode.@Tooltip": "COMPATIBLE: Item swap with item pick packet, it may swap items randomly but is unlikely to trigger anti-cheat\nSWAP: Simply swap the item with the selected\nSHIFT: Shift the whole column up/down when swapping items" } \ No newline at end of file From c2198ad8a564d55a2173afdf59cd745eb9990ac3 Mon Sep 17 00:00:00 2001 From: KosmX Date: Sat, 15 Jul 2023 18:29:25 +0200 Subject: [PATCH 4/7] Make the config entry user-friendly --- src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java b/src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java index 871c34a..92c8830 100644 --- a/src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java +++ b/src/main/java/com/turtlearmymc/slotswap/config/SwapConfig.java @@ -2,10 +2,13 @@ import me.shedaniel.autoconfig.ConfigData; import me.shedaniel.autoconfig.annotation.Config; +import me.shedaniel.autoconfig.annotation.ConfigEntry; @Config(name = "slotswap") public class SwapConfig implements ConfigData { + @ConfigEntry.Gui.Tooltip + @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) public SwapMode swapMode = SwapMode.COMPATIBLE; public enum SwapMode { From f11d6de438e6c8b3b6b306cabfa2c6e69032a541 Mon Sep 17 00:00:00 2001 From: KosmX Date: Sat, 15 Jul 2023 20:03:33 +0200 Subject: [PATCH 5/7] Compatibility with autohud --- build.gradle | 14 ++++++++++ gradle.properties | 2 ++ .../turtlearmymc/slotswap/SwapManager.java | 6 ++++ .../slotswap/compat/AutoHudCompatibility.java | 11 ++++++++ .../slotswap/compat/LoadCompat.java | 28 +++++++++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 src/main/java/com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java create mode 100644 src/main/java/com/turtlearmymc/slotswap/compat/LoadCompat.java diff --git a/build.gradle b/build.gradle index 9eb173f..0417fc9 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,18 @@ version = project.mod_version + "+mc" + project.minecraft_version repositories { maven { url "https://maven.shedaniel.me/" } maven { url "https://maven.terraformersmc.com/releases/" } + + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" + } + } } dependencies { @@ -28,6 +40,8 @@ dependencies { modApi "com.terraformersmc:modmenu:${project.modmenu}" + // only in classpath + modCompileOnly "maven.modrinth:autohud:${project.autohud_version}" } processResources { diff --git a/gradle.properties b/gradle.properties index 8bf36e3..ca13336 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,3 +16,5 @@ fabric_version = 0.85.0+1.20.1 # These can be easily found here https://linkie.shedaniel.dev/dependencies cloth_config = 11.1.106 modmenu = 7.1.0 + +autohud_version = 6.1+1.20 diff --git a/src/main/java/com/turtlearmymc/slotswap/SwapManager.java b/src/main/java/com/turtlearmymc/slotswap/SwapManager.java index 221c67e..b393dea 100644 --- a/src/main/java/com/turtlearmymc/slotswap/SwapManager.java +++ b/src/main/java/com/turtlearmymc/slotswap/SwapManager.java @@ -1,5 +1,6 @@ package com.turtlearmymc.slotswap; +import com.turtlearmymc.slotswap.compat.LoadCompat; import com.turtlearmymc.slotswap.config.SwapConfig; import me.shedaniel.autoconfig.AutoConfig; import me.shedaniel.autoconfig.serializer.JanksonConfigSerializer; @@ -25,6 +26,8 @@ public class SwapManager implements ClientModInitializer { private static @Nullable KeyBinding selectSlotKey = null; + private static LoadCompat.Action compatibilityAction; + public static boolean isSelectKeyDown() { if (selectSlotKey != null) { return selectSlotKey.isPressed(); @@ -50,6 +53,7 @@ public static void tryStartSwap() { active = true; currentRow = 0; } + compatibilityAction.invoke(); } public static void cancel() { @@ -133,6 +137,8 @@ public void onInitializeClient() { AutoConfig.register(SwapConfig.class, JanksonConfigSerializer::new); CONFIG = AutoConfig.getConfigHolder(SwapConfig.class).get(); + compatibilityAction = LoadCompat.getActivationAction(); + selectSlotKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( "key.slotswap.swap", InputUtil.Type.KEYSYM, diff --git a/src/main/java/com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java b/src/main/java/com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java new file mode 100644 index 0000000..bf37d19 --- /dev/null +++ b/src/main/java/com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java @@ -0,0 +1,11 @@ +package com.turtlearmymc.slotswap.compat; + +import mod.crend.autohud.component.Component; + +public class AutoHudCompatibility implements LoadCompat.Action { + + @Override + public void invoke() { + Component.Hotbar.revealCombined(); + } +} diff --git a/src/main/java/com/turtlearmymc/slotswap/compat/LoadCompat.java b/src/main/java/com/turtlearmymc/slotswap/compat/LoadCompat.java new file mode 100644 index 0000000..3f7139f --- /dev/null +++ b/src/main/java/com/turtlearmymc/slotswap/compat/LoadCompat.java @@ -0,0 +1,28 @@ +package com.turtlearmymc.slotswap.compat; + +import net.fabricmc.loader.api.FabricLoader; +import org.jetbrains.annotations.NotNull; + +public class LoadCompat { + + + @NotNull + public static Action getActivationAction() { + + return getAutoHudAction(); + } + + private static Action getAutoHudAction() { + if (FabricLoader.getInstance().isModLoaded("autohud")) { + return new AutoHudCompatibility(); + } else { + return () -> {}; + } + } + + + @FunctionalInterface + public interface Action { + void invoke(); + } +} From bd3b5fbcdcbce3f030bb06061a2d0c8119215c51 Mon Sep 17 00:00:00 2001 From: KosmX Date: Sat, 15 Jul 2023 20:04:59 +0200 Subject: [PATCH 6/7] oops --- .../resources/assets/slotswap/lang/{en_US.json => en_us.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/assets/slotswap/lang/{en_US.json => en_us.json} (100%) diff --git a/src/main/resources/assets/slotswap/lang/en_US.json b/src/main/resources/assets/slotswap/lang/en_us.json similarity index 100% rename from src/main/resources/assets/slotswap/lang/en_US.json rename to src/main/resources/assets/slotswap/lang/en_us.json From 77d7ae067089aba7a7d9c9b6ca042ef8dd1c4e23 Mon Sep 17 00:00:00 2001 From: KosmX Date: Sat, 15 Jul 2023 20:10:47 +0200 Subject: [PATCH 7/7] small tweak --- .../com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java b/src/main/java/com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java index bf37d19..f8cf6ec 100644 --- a/src/main/java/com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java +++ b/src/main/java/com/turtlearmymc/slotswap/compat/AutoHudCompatibility.java @@ -6,6 +6,6 @@ public class AutoHudCompatibility implements LoadCompat.Action { @Override public void invoke() { - Component.Hotbar.revealCombined(); + Component.Hotbar.reveal(); } }