diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e57227..fa6a3b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,2 @@ ## Change -- update MaFgLib version \ No newline at end of file +- sync with `sakura-ryoko/itemscroller` 1.21-sakura.8 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 52208e0..1232667 100644 --- a/build.gradle +++ b/build.gradle @@ -91,7 +91,7 @@ publisher { setChangelog(file("CHANGELOG.md").getText("UTF-8")) setVersion("${project.version}") setDisplayName("${project.version}") - setGameVersions(libs.versions.minecraft.range.get()) + setGameVersions("1.21", "1.21.1") setLoaders(loom.platform.get().id()) setCurseEnvironment("client") setArtifact(remapJar) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 60f1720..6606f6f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,15 +1,12 @@ [versions] - -minecraft-range="1.21" - # Base properties -minecraft_version="1.21" -yarn_mappings="1.21+build.2" +minecraft_version="1.21.1" +yarn_mappings="1.21.1+build.3" mappings_patch="1.21+build.4" -neoforge="21.0.167" +neoforge="21.1.31" # Mod properties -version="0.1.7" +version="0.1.8" maven-group="org.thinkingstudio.rocknroller" archives-name="RocknRoller" @@ -18,7 +15,7 @@ id-modrinth="hYq29QmW" id-curseforge="916852" # Mod dependencies -mafglib="0.1.21-mc1.21" +mafglib="0.1.22-mc1.21.1" badpackets="neo-0.8.1" # Libraries @@ -26,7 +23,7 @@ jsr305="3.0.2" # Gradle plugin architectury-loom = "1.6-SNAPSHOT" -modpublisher = "2.1.+" +modpublisher = "2.+" [libraries] minecraft = { group = "com.mojang", name = "minecraft", version.ref = "minecraft_version" } diff --git a/src/main/java/fi/dy/masa/itemscroller/config/Configs.java b/src/main/java/fi/dy/masa/itemscroller/config/Configs.java index 3d74403..65b8784 100644 --- a/src/main/java/fi/dy/masa/itemscroller/config/Configs.java +++ b/src/main/java/fi/dy/masa/itemscroller/config/Configs.java @@ -35,6 +35,7 @@ public static class Generic public static final ConfigInteger MASS_CRAFT_INTERVAL = new ConfigInteger("massCraftInterval", 2, 1, 60, "itemscroller.config.generic.comment.massCraftInterval").translatedName("itemscroller.config.generic.name.massCraftInterval"); public static final ConfigInteger MASS_CRAFT_ITERATIONS = new ConfigInteger("massCraftIterations", 36, 1, 256, "itemscroller.config.generic.comment.massCraftIterations").translatedName("itemscroller.config.generic.name.massCraftIterations"); public static final ConfigBoolean MASS_CRAFT_SWAPS = new ConfigBoolean("massCraftSwapsOnly", false, "itemscroller.config.generic.comment.massCraftSwapsOnly").translatedName("itemscroller.config.generic.name.massCraftSwapsOnly"); + public static final ConfigBoolean MASS_CRAFT_RECIPE_BOOK = new ConfigBoolean("massCraftUseRecipeBook", false, "itemscroller.config.generic.comment.massCraftUseRecipeBook").translatedName("itemscroller.config.generic.name.massCraftUseRecipeBook"); public static final ConfigInteger PACKET_RATE_LIMIT = new ConfigInteger("packetRateLimit", 4, 1, 1024, "itemscroller.config.generic.comment.packetRateLimit").translatedName("itemscroller.config.generic.name.packetRateLimit"); public static final ConfigBoolean SCROLL_CRAFT_STORE_RECIPES_TO_FILE = new ConfigBoolean("craftingRecipesSaveToFile", true, "itemscroller.config.generic.comment.craftingRecipesSaveToFile").translatedName("itemscroller.config.generic.name.craftingRecipesSaveToFile"); public static final ConfigBoolean SCROLL_CRAFT_RECIPE_FILE_GLOBAL = new ConfigBoolean("craftingRecipesSaveFileIsGlobal", false, "itemscroller.config.generic.comment.craftingRecipesSaveFileIsGlobal").translatedName("itemscroller.config.generic.name.craftingRecipesSaveFileIsGlobal"); @@ -57,6 +58,7 @@ public static class Generic MASS_CRAFT_INTERVAL, MASS_CRAFT_ITERATIONS, MASS_CRAFT_SWAPS, + MASS_CRAFT_RECIPE_BOOK, MOD_MAIN_TOGGLE, PACKET_RATE_LIMIT, RATE_LIMIT_CLICK_PACKETS, diff --git a/src/main/java/fi/dy/masa/itemscroller/event/KeybindCallbacks.java b/src/main/java/fi/dy/masa/itemscroller/event/KeybindCallbacks.java index 8506a36..8358a97 100644 --- a/src/main/java/fi/dy/masa/itemscroller/event/KeybindCallbacks.java +++ b/src/main/java/fi/dy/masa/itemscroller/event/KeybindCallbacks.java @@ -5,6 +5,8 @@ import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.inventory.RecipeInputInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; import net.minecraft.screen.slot.Slot; import fi.dy.masa.malilib.config.options.ConfigHotkey; import fi.dy.masa.malilib.gui.GuiBase; @@ -30,6 +32,8 @@ public class KeybindCallbacks implements IHotkeyCallback, IClientTickHandler protected int massCraftTicker; + private boolean recipeBookClicks = false; + public static KeybindCallbacks getInstance() { return INSTANCE; @@ -190,6 +194,9 @@ private static void debugPrintInv(RecipeInputInventory inv) @Override public void onClientTick(MinecraftClient mc) { + if (InventoryUtils.dontUpdateRecipeBook > 0) { + --InventoryUtils.dontUpdateRecipeBook; + } if (this.functionalityEnabled() == false || mc.player == null) { return; @@ -223,9 +230,54 @@ public void onClientTick(MinecraftClient mc) } RecipePattern recipe = RecipeStorage.getInstance().getSelectedRecipe(); + int limit = Configs.Generic.MASS_CRAFT_ITERATIONS.getIntegerValue(); - if (Configs.Generic.MASS_CRAFT_SWAPS.getBooleanValue()) + if (Configs.Generic.MASS_CRAFT_RECIPE_BOOK.getBooleanValue() && recipe.lookupVanillaRecipe(mc.world) != null) + { + InventoryUtils.dontUpdateRecipeBook = 2; + for (int i = 0; i < limit; ++i) + { + // todo +// InventoryUtils.tryClearCursor(gui); +// InventoryUtils.setInhibitCraftingOutputUpdate(true); + InventoryUtils.throwAllCraftingResultsToGround(recipe, gui); + + RecipeInputInventory craftingInv = ((IMixinCraftingResultSlot) outputSlot).itemscroller_getCraftingInventory(); + if (!recipe.getVanillaRecipe().matches(craftingInv.createRecipeInput(), mc.world)) + { + CraftingHandler.SlotRange range = CraftingHandler.getCraftingGridSlots(gui, outputSlot); + final int invSlots = gui.getScreenHandler().slots.size(); + final int rangeSlots = range.getSlotCount(); + + for (int j = 0, slotNum = range.getFirst(); j < rangeSlots && slotNum < invSlots; j++, slotNum++) + { + InventoryUtils.shiftClickSlot(gui, slotNum); + + Slot slotTmp = gui.getScreenHandler().getSlot(slotNum); + ItemStack stack = slotTmp.getStack(); + if (!stack.isEmpty()) + { + InventoryUtils.dropStack(gui, slotNum); + } + } + } + + mc.interactionManager.clickRecipe(gui.getScreenHandler().syncId, recipe.getVanillaRecipeEntry(), true); +// InventoryUtils.setInhibitCraftingOutputUpdate(false); +// InventoryUtils.updateCraftingOutputSlot(outputSlot); + + craftingInv = ((IMixinCraftingResultSlot) outputSlot).itemscroller_getCraftingInventory(); + if (recipe.getVanillaRecipe().matches(craftingInv.createRecipeInput(), mc.world)) + { + break; + } + + InventoryUtils.shiftClickSlot(gui, outputSlot.id); + recipeBookClicks = true; + } + } + else if (Configs.Generic.MASS_CRAFT_SWAPS.getBooleanValue()) { for (int i = 0; i < limit; ++i) { @@ -301,4 +353,9 @@ public void onClientTick(MinecraftClient mc) }); } } + + public void onPacket(ScreenHandlerSlotUpdateS2CPacket packet) + { + var mc = MinecraftClient.getInstance(); + } } diff --git a/src/main/java/fi/dy/masa/itemscroller/mixin/MixinClientPlayNetworkHandler.java b/src/main/java/fi/dy/masa/itemscroller/mixin/MixinClientPlayNetworkHandler.java index 81d1cf3..c059be5 100644 --- a/src/main/java/fi/dy/masa/itemscroller/mixin/MixinClientPlayNetworkHandler.java +++ b/src/main/java/fi/dy/masa/itemscroller/mixin/MixinClientPlayNetworkHandler.java @@ -1,7 +1,12 @@ package fi.dy.masa.itemscroller.mixin; +import fi.dy.masa.itemscroller.config.Configs; +import fi.dy.masa.itemscroller.config.Hotkeys; +import fi.dy.masa.itemscroller.event.KeybindCallbacks; import fi.dy.masa.itemscroller.util.InventoryUtils; import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.CraftFailedResponseS2CPacket; +import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.InventoryS2CPacket; import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket; @@ -22,6 +27,26 @@ private void onPong(StatisticsS2CPacket packet, CallbackInfo ci) } } + @Inject(method = "onScreenHandlerSlotUpdate", at = @At("RETURN")) + private void onScreenHandlerSlotUpdate(ScreenHandlerSlotUpdateS2CPacket packet, CallbackInfo ci) + { + KeybindCallbacks.getInstance().onPacket(packet); + } + + @Inject( + method = "onCraftFailedResponse", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/util/thread/ThreadExecutor;)V", + shift = At.Shift.AFTER + ), + cancellable = true + ) + private void onCraftFailedResponse(CraftFailedResponseS2CPacket packet, CallbackInfo ci) + { + // todo + } + @Inject( method = "onInventory", at = @At( @@ -48,7 +73,7 @@ private void onInventory(InventoryS2CPacket packet, CallbackInfo ci) ), cancellable = true ) - private void onScreenHandlerSlotUpdate(ScreenHandlerSlotUpdateS2CPacket packet, CallbackInfo ci) + private void onScreenHandlerSlotUpdateInvokeMainThread(ScreenHandlerSlotUpdateS2CPacket packet, CallbackInfo ci) { if (InventoryUtils.bufferInvUpdates) { diff --git a/src/main/java/fi/dy/masa/itemscroller/mixin/MixinRecipeBookWidget.java b/src/main/java/fi/dy/masa/itemscroller/mixin/MixinRecipeBookWidget.java index d5a98e4..f509e4d 100644 --- a/src/main/java/fi/dy/masa/itemscroller/mixin/MixinRecipeBookWidget.java +++ b/src/main/java/fi/dy/masa/itemscroller/mixin/MixinRecipeBookWidget.java @@ -1,9 +1,51 @@ package fi.dy.masa.itemscroller.mixin; +import fi.dy.masa.itemscroller.util.InventoryUtils; +import net.minecraft.client.gui.screen.recipebook.RecipeBookGhostSlots; import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; +import net.minecraft.recipe.RecipeEntry; +import net.minecraft.screen.slot.Slot; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; @Mixin(RecipeBookWidget.class) public class MixinRecipeBookWidget { + @Shadow @Final protected RecipeBookGhostSlots ghostSlots; + + @Inject(method = "slotClicked", at = @At("HEAD"), cancellable = true) + private void onSlotClicked(Slot slot, CallbackInfo ci) + { + if (InventoryUtils.dontUpdateRecipeBook > 0) + { + ci.cancel(); + } + } + + @Inject(method = "update", at = @At("HEAD"), cancellable = true) + private void onUpdate(CallbackInfo ci) + { + if (InventoryUtils.dontUpdateRecipeBook > 0) + { + ci.cancel(); + } + } + + // Seems to be (intended) bug from Mojang + @Inject( + method = "showGhostRecipe", + at = @At("HEAD"), + cancellable = true + ) + private void onShowGhostRecipe(RecipeEntry recipe, List slots, CallbackInfo ci) { + if (this.ghostSlots.getRecipe() == recipe) { + ci.cancel(); + } + } } diff --git a/src/main/java/fi/dy/masa/itemscroller/recipes/RecipePattern.java b/src/main/java/fi/dy/masa/itemscroller/recipes/RecipePattern.java index 61db62e..085cea3 100644 --- a/src/main/java/fi/dy/masa/itemscroller/recipes/RecipePattern.java +++ b/src/main/java/fi/dy/masa/itemscroller/recipes/RecipePattern.java @@ -55,7 +55,9 @@ public void ensureRecipeSizeAndClearRecipe(int size) this.clearRecipe(); } - private void lookupVanillaRecipe(World world) { + @Nullable + public Recipe lookupVanillaRecipe(World world) { + //Assume all recipes here are of type CraftingRecipe this.vanillaRecipe = null; var mc = MinecraftClient.getInstance(); int recipeSize; @@ -69,7 +71,7 @@ else if (recipe.length == 9) } else { - return; + return null; } for (RecipeEntry match : mc.world.getRecipeManager().getAllMatches(RecipeType.CRAFTING, CraftingRecipeInput.create(recipeSize, recipeSize, Arrays.asList(recipe)), world)) @@ -77,9 +79,10 @@ else if (recipe.length == 9) if (InventoryUtils.areStacksEqual(result, match.value().getResult(world.getRegistryManager()))) { this.vanillaRecipe = match; - return; + return (Recipe) match.value(); } } + return null; } public void storeCraftingRecipe(Slot slot, HandledScreen gui, boolean clearIfEmpty) @@ -152,7 +155,6 @@ public void readFromNBT(@Nonnull NbtCompound nbt, @Nonnull DynamicRegistryManage } this.result = ItemStack.fromNbtOrEmpty(registryManager, nbt.getCompound("Result")); - this.lookupVanillaRecipe(MinecraftClient.getInstance().world); } } @@ -225,7 +227,7 @@ public RecipeEntry getVanillaRecipeEntry() @Nullable public Recipe getVanillaRecipe() { - if (vanillaRecipe == null) + if (recipe == null) { return null; } diff --git a/src/main/java/fi/dy/masa/itemscroller/util/InventoryUtils.java b/src/main/java/fi/dy/masa/itemscroller/util/InventoryUtils.java index eab4952..2aa6854 100644 --- a/src/main/java/fi/dy/masa/itemscroller/util/InventoryUtils.java +++ b/src/main/java/fi/dy/masa/itemscroller/util/InventoryUtils.java @@ -64,6 +64,7 @@ public class InventoryUtils { private static final Set DRAGGED_SLOTS = new HashSet<>(); private static final int SERVER_SYNC_MAGIC = 45510; + public static int dontUpdateRecipeBook; private static WeakReference sourceSlotCandidate = null; private static WeakReference sourceSlot = null; diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index d753fb0..153186f 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -25,14 +25,14 @@ file = "META-INF/accesstransformer.cfg" [[dependencies.rocknroller]] modId = "neoforge" type = "required" -versionRange = "[20.5,)" +versionRange = "[21,)" ordering = "NONE" side = "BOTH" [[dependencies.rocknroller]] modId = "minecraft" type = "required" -versionRange = "[1.20.5,)" +versionRange = "[1.21,)" ordering = "NONE" side = "BOTH"