diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 267906d..99f8f7c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -17,9 +17,8 @@ updates: - gradle-plugins - maven-central ignore: - - dependency-name: me.melontini:dark-matter* + - dependency-name: dev.zenfyr:pulsar - dependency-name: io.wispforest:owo-lib - - dependency-name: me.melontini:handy-tests directory: / schedule: interval: weekly \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e4879df..36f0e9d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,12 +7,3 @@ jobs: uses: constellation-mc/actions/.github/workflows/gradle-build.yml@main with: java: 17 - gradle_tasks: spotbugs - reviewdog: | - cat ./build/reports/spotbugs/main/spotbugs.sarif | reviewdog -name="spotbugs" -f=sarif -reporter=github-check -level=warning - - run_tests: - uses: constellation-mc/actions/.github/workflows/mc-tests.yml@main - with: - java: 17 - client_task: runTestClient \ No newline at end of file diff --git a/LICENSE b/LICENSE index 5073f53..3ed4ec7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2023 melontini +Copyright (c) 2026 zenfyr Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/build.gradle b/build.gradle index 1fbdbf6..a18a805 100644 --- a/build.gradle +++ b/build.gradle @@ -13,8 +13,11 @@ def local = !System.getenv().containsKey("GITHUB_RUN_NUMBER") version = "${project.mod_version}-${project.minecraft_version}-${local ? 'SNAPSHOT' : "build.${System.getenv("GITHUB_RUN_NUMBER")}"}" group = project.maven_group +base { + archivesName = project.archives_base_name +} + apply from: "https://raw.githubusercontent.com/constellation-mc/artifacts/main/artifacts.groovy" -constellationRepo(project, "dark-matter") repositories { // Add repositories to retrieve artifacts from in here. @@ -35,6 +38,7 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation libs.fabric.loader + modImplementation libs.fabric.api } spotless { @@ -54,7 +58,8 @@ processResources { def map = [ "version" : project.version, "minecraft_version": project.minecraft_version, - "loader_version" : libs.fabric.loader.get().version + "loader_version" : libs.fabric.loader.get().version, + "fabric_version" : libs.fabric.api.get().version ] inputs.properties(map) filteringCharset "UTF-8" @@ -86,8 +91,15 @@ java { jar { from("LICENSE") { - rename { "${it}_${project.archivesBaseName}" } + rename { "${it}_${project.archives_base_name}" } + } +} + +sourcesJar { + exclude { + sourceSets.main.allSource.contains it.file } + from delombok } // configure the maven publication @@ -103,7 +115,7 @@ publishing { repositories { maven { name = "GitHubPackages" - url = "https://maven.pkg.github.com/constellation-mc/recipe_book_is_pain" + url = "https://maven.pkg.github.com/constellation-mc/rbip" credentials { username = System.getenv("GITHUB_ACTOR") password = System.getenv("GITHUB_TOKEN") @@ -140,7 +152,7 @@ publishMods { embeds("dark-matter") } github { - repository = "constellation-mc/recipe_book_is_pain" + repository = "constellation-mc/rbip" accessToken = providers.environmentVariable("GITHUB_TOKEN") commitish = providers.environmentVariable("GITHUB_SHA").getOrElse("${project.minecraft_version}-fabric") diff --git a/gradle.properties b/gradle.properties index f1c1cbd..4f91be7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,5 +6,5 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.10 # Mod Properties mod_version=0.11.2 -maven_group=me.melontini +maven_group=dev.zenfyr archives_base_name=rbip diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b57e169..83bfdbf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,6 @@ [libraries] fabric-loader = { group = "net.fabricmc", name = "fabric-loader", version = "0.19.2" } +fabric-api = { group = "net.fabricmc.fabric-api", name = "fabric-api", version = "0.92.8+1.20.1" } [plugins] fabric-loom = { id = "fabric-loom", version = "1.16.1" } diff --git a/spotbugs.xml b/spotbugs.xml deleted file mode 100644 index edc2a76..0000000 --- a/spotbugs.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/java/dev/zenfyr/rbip/RecipeBookIsPain.java b/src/main/java/dev/zenfyr/rbip/RecipeBookIsPain.java new file mode 100644 index 0000000..27d3cbd --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/RecipeBookIsPain.java @@ -0,0 +1,33 @@ +package dev.zenfyr.rbip; + +import dev.zenfyr.rbip.compat.OwOCompat; +import dev.zenfyr.rbip.compat.PulsarCompat; +import java.lang.invoke.MethodHandles; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.fabricmc.loader.api.FabricLoader; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Environment(EnvType.CLIENT) +public class RecipeBookIsPain implements ClientModInitializer { + + public static final Logger LOGGER = LogManager.getLogger("RBIP"); + + public static final boolean isOwOLoaded = FabricLoader.getInstance().isModLoaded("owo"); + public static final boolean isPulsarLoaded = FabricLoader.getInstance().isModLoaded("pulsar"); + + @Override + public void onInitializeClient() { + var lookup = MethodHandles.lookup(); + + if (isOwOLoaded) { + OwOCompat.init(lookup); + } + + if (isPulsarLoaded) { + PulsarCompat.init(lookup); + } + } +} diff --git a/src/main/java/dev/zenfyr/rbip/RecipeBookPageButton.java b/src/main/java/dev/zenfyr/rbip/RecipeBookPageButton.java new file mode 100644 index 0000000..d52b245 --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/RecipeBookPageButton.java @@ -0,0 +1,70 @@ +package dev.zenfyr.rbip; + +import com.mojang.blaze3d.systems.RenderSystem; +import dev.zenfyr.rbip.access.PaginatedRecipeBookWidget; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +public class RecipeBookPageButton extends ButtonWidget { + + private static final Identifier TEXTURE = + new Identifier("rbip", "textures/gui/recipe_book_buttons.png"); + + private final boolean next; + private final RecipeBookWidget widget; + + public RecipeBookPageButton(int x, int y, RecipeBookWidget widget, boolean next) { + super( + x, + y, + 14, + 13, + next ? Text.literal(">") : Text.literal("<"), + button -> {}, + DEFAULT_NARRATION_SUPPLIER); + this.widget = widget; + this.next = next; + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + this.hovered = mouseX >= this.getX() + && mouseY >= this.getY() + && mouseX < this.getX() + this.width + && mouseY < this.getY() + this.height; + + if (this.visible) { + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + RenderSystem.setShaderTexture(0, TEXTURE); + int u = this.active && this.isHovered() ? 28 : 0; + int v = this.active ? 0 : 13; + + RenderSystem.enableDepthTest(); + this.drawTexture( + context, + TEXTURE, + this.getX(), + this.getY(), + u + (next ? 14 : 0), + v, + 0, + this.width, + this.height, + 256, + 256); + if (this.hovered && MinecraftClient.getInstance().currentScreen != null) { + context.drawTooltip( + MinecraftClient.getInstance().textRenderer, + Text.literal(((PaginatedRecipeBookWidget) widget).rbip$getPage() + 1 + "/" + + ((PaginatedRecipeBookWidget) widget).rbip$getPageCount()), + mouseX, + mouseY); + } + } + } +} diff --git a/src/main/java/dev/zenfyr/rbip/access/ClientRecipeBookDuck.java b/src/main/java/dev/zenfyr/rbip/access/ClientRecipeBookDuck.java new file mode 100644 index 0000000..cf4a7b8 --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/access/ClientRecipeBookDuck.java @@ -0,0 +1,10 @@ +package dev.zenfyr.rbip.access; + +import java.util.List; +import net.minecraft.client.gui.screen.recipebook.RecipeResultCollection; +import net.minecraft.item.ItemGroup; + +public interface ClientRecipeBookDuck { + + List rbip$getResultsForGroup(ItemGroup group); +} diff --git a/src/main/java/dev/zenfyr/rbip/access/PaginatedRecipeBookWidget.java b/src/main/java/dev/zenfyr/rbip/access/PaginatedRecipeBookWidget.java new file mode 100644 index 0000000..9e396d7 --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/access/PaginatedRecipeBookWidget.java @@ -0,0 +1,36 @@ +package dev.zenfyr.rbip.access; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public interface PaginatedRecipeBookWidget { + + default void rbip$updatePages() { + throw new IllegalStateException("Interface not implemented"); + } + + default void rbip$updatePageSwitchButtons() { + throw new IllegalStateException("Interface not implemented"); + } + + default int rbip$getPage() { + throw new IllegalStateException("Interface not implemented"); + } + + default void rbip$setPage(int page) { + throw new IllegalStateException("Interface not implemented"); + } + + default void rbip$incrementPage() { + this.rbip$setPage(this.rbip$getPage() + 1); + } + + default void rbip$decrementPage() { + this.rbip$setPage(this.rbip$getPage() - 1); + } + + default int rbip$getPageCount() { + throw new IllegalStateException("Interface not implemented"); + } +} diff --git a/src/main/java/dev/zenfyr/rbip/access/PaginatedRecipeGroupButtonWidget.java b/src/main/java/dev/zenfyr/rbip/access/PaginatedRecipeGroupButtonWidget.java new file mode 100644 index 0000000..ed967e6 --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/access/PaginatedRecipeGroupButtonWidget.java @@ -0,0 +1,16 @@ +package dev.zenfyr.rbip.access; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public interface PaginatedRecipeGroupButtonWidget { + + default int rbip$getPage() { + throw new IllegalStateException("Interface not implemented"); + } + + default void rbip$setPage(int page) { + throw new IllegalStateException("Interface not implemented"); + } +} diff --git a/src/main/java/dev/zenfyr/rbip/access/RecipeGroupButtonWidgetDuck.java b/src/main/java/dev/zenfyr/rbip/access/RecipeGroupButtonWidgetDuck.java new file mode 100644 index 0000000..15e21fe --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/access/RecipeGroupButtonWidgetDuck.java @@ -0,0 +1,10 @@ +package dev.zenfyr.rbip.access; + +import net.minecraft.item.ItemGroup; + +public interface RecipeGroupButtonWidgetDuck { + + void rbip$setRealItemGroup(ItemGroup group); + + ItemGroup rbip$getRealItemGroup(); +} diff --git a/src/main/java/dev/zenfyr/rbip/compat/OwOCompat.java b/src/main/java/dev/zenfyr/rbip/compat/OwOCompat.java new file mode 100644 index 0000000..5afeaa6 --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/compat/OwOCompat.java @@ -0,0 +1,65 @@ +package dev.zenfyr.rbip.compat; + +import dev.zenfyr.rbip.RecipeBookIsPain; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import lombok.SneakyThrows; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget; +import net.minecraft.item.ItemGroup; + +public class OwOCompat { + + private static Class groupClass; + private static MethodHandle iconHandle; + private static MethodHandle renderHandle; + + @SneakyThrows + public static boolean render( + DrawContext context, int i, RecipeGroupButtonWidget widget, ItemGroup group) { + if (groupClass == null || iconHandle == null || renderHandle == null) return false; + if (!groupClass.isInstance(group)) return false; + + MinecraftClient client = MinecraftClient.getInstance(); + double e = client.mouse.getX() + * client.getWindow().getScaledWidth() + / client.getWindow().getWidth(); + double f = client.mouse.getY() + * client.getWindow().getScaledHeight() + / client.getWindow().getHeight(); + var icon = iconHandle.invoke(group); + renderHandle.invoke( + icon, + context, + widget.getX() + 9 + i, + widget.getY() + 5, + (int) e, + (int) f, + client.getTickDelta()); + return true; + } + + public static void init(MethodHandles.Lookup lookup) { + try { + groupClass = Class.forName("io.wispforest.owo.itemgroup.OwoItemGroup"); + var iconClass = Class.forName("io.wispforest.owo.itemgroup.Icon"); + + iconHandle = lookup.findVirtual(groupClass, "icon", MethodType.methodType(iconClass)); + renderHandle = lookup.findVirtual( + iconClass, + "render", + MethodType.methodType( + void.class, + DrawContext.class, + int.class, + int.class, + int.class, + int.class, + float.class)); + } catch (Exception e) { + RecipeBookIsPain.LOGGER.error("Failed to prepare OwO compat.", e); + } + } +} diff --git a/src/main/java/dev/zenfyr/rbip/compat/PulsarCompat.java b/src/main/java/dev/zenfyr/rbip/compat/PulsarCompat.java new file mode 100644 index 0000000..bcbad01 --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/compat/PulsarCompat.java @@ -0,0 +1,57 @@ +package dev.zenfyr.rbip.compat; + +import dev.zenfyr.rbip.RecipeBookIsPain; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Optional; +import lombok.SneakyThrows; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget; +import net.minecraft.item.ItemGroup; + +public class PulsarCompat { + + private static MethodHandle getIconAnimation; + private static MethodHandle animateIcon; + + @SneakyThrows + public static boolean render( + DrawContext context, int i, RecipeGroupButtonWidget widget, ItemGroup group) { + if (getIconAnimation == null || animateIcon == null) return false; + Optional opt = (Optional) getIconAnimation.invoke(group); + if (opt.isEmpty()) return false; + + animateIcon.invoke( + opt.get(), + group, + context, + widget.getX() + 9 + i, + widget.getY() + 5, + widget.isToggled(), + false); + return true; + } + + public static void init(MethodHandles.Lookup lookup) { + try { + var iconClass = Class.forName("dev.zenfyr.pulsar.creativetab.CreativeModeTabAnimaton"); + + getIconAnimation = lookup.findStatic( + iconClass, "getIconAnimation", MethodType.methodType(Optional.class, ItemGroup.class)); + animateIcon = lookup.findVirtual( + iconClass, + "animateIcon", + MethodType.methodType( + void.class, + ItemGroup.class, + DrawContext.class, + int.class, + int.class, + boolean.class, + boolean.class)); + } catch (Exception e) { + RecipeBookIsPain.LOGGER.error("Failed to prepare Pulsar compat.", e); + } + } +} diff --git a/src/main/java/dev/zenfyr/rbip/mixin/ClientRecipeBookMixin.java b/src/main/java/dev/zenfyr/rbip/mixin/ClientRecipeBookMixin.java new file mode 100644 index 0000000..f952ed8 --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/mixin/ClientRecipeBookMixin.java @@ -0,0 +1,81 @@ +package dev.zenfyr.rbip.mixin; + +import com.google.common.collect.*; +import dev.zenfyr.rbip.access.ClientRecipeBookDuck; +import java.util.*; +import net.minecraft.client.gui.screen.recipebook.RecipeResultCollection; +import net.minecraft.client.recipebook.ClientRecipeBook; +import net.minecraft.client.recipebook.RecipeBookGroup; +import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemGroups; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.RecipeType; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.Registries; +import net.minecraft.resource.featuretoggle.FeatureFlags; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +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; + +@Mixin(value = ClientRecipeBook.class, priority = 999) +public class ClientRecipeBookMixin implements ClientRecipeBookDuck { + + @Shadow + private List orderedResults; + + @Unique private final Map> rbip$groupedRecipes = new HashMap<>(); + + @Inject(at = @At("TAIL"), method = "reload") + private void rbip$reload( + Iterable> recipes, DynamicRegistryManager manager, CallbackInfo ci) { + ItemGroups.updateDisplayContext(FeatureFlags.FEATURE_MANAGER.getFeatureSet(), false, manager); + + Map groups = new HashMap<>(); + Registries.ITEM_GROUP.stream() + .filter(itemGroup -> !itemGroup.isSpecial()) + .forEach(itemGroup -> { + for (ItemStack stack : itemGroup.getSearchTabStacks()) { + if (groups.containsKey(stack.getItem())) continue; + groups.put(stack.getItem(), itemGroup); + } + }); + + Map> map2 = new HashMap<>(); + + this.orderedResults.forEach(collection -> { + for (Recipe recipe : collection.getAllRecipes()) { + if (!RecipeType.CRAFTING.equals(recipe.getType())) return; + if (recipe.isIgnoredInRecipeBook() || recipe.isEmpty()) return; + + ItemStack output = recipe.getOutput(manager); + if (output.isEmpty()) continue; + + ItemGroup itemGroup = groups.getOrDefault(output.getItem(), ItemGroups.getDefaultTab()); + map2.computeIfAbsent(itemGroup, g -> new ArrayList<>()).add(collection); + return; + } + }); + + this.rbip$groupedRecipes.clear(); + this.rbip$groupedRecipes.putAll(map2); + } + + @Inject(at = @At("HEAD"), method = "getGroupForRecipe", cancellable = true) + private static void rbip$getGroupForRecipe( + Recipe recipe, CallbackInfoReturnable cir) { + if (RecipeType.CRAFTING.equals(recipe.getType())) { + cir.setReturnValue(RecipeBookGroup.CRAFTING_MISC); + } + } + + @Override + public List rbip$getResultsForGroup(ItemGroup group) { + return this.rbip$groupedRecipes.getOrDefault(group, List.of()); + } +} diff --git a/src/main/java/dev/zenfyr/rbip/mixin/RecipeBookWidgetMixin.java b/src/main/java/dev/zenfyr/rbip/mixin/RecipeBookWidgetMixin.java new file mode 100644 index 0000000..2ca604f --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/mixin/RecipeBookWidgetMixin.java @@ -0,0 +1,346 @@ +package dev.zenfyr.rbip.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalIntRef; +import dev.zenfyr.rbip.RecipeBookPageButton; +import dev.zenfyr.rbip.access.ClientRecipeBookDuck; +import dev.zenfyr.rbip.access.PaginatedRecipeBookWidget; +import dev.zenfyr.rbip.access.PaginatedRecipeGroupButtonWidget; +import dev.zenfyr.rbip.access.RecipeGroupButtonWidgetDuck; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; +import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget; +import net.minecraft.client.gui.screen.recipebook.RecipeResultCollection; +import net.minecraft.client.recipebook.ClientRecipeBook; +import net.minecraft.client.recipebook.RecipeBookGroup; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemGroups; +import net.minecraft.recipe.book.RecipeBookCategory; +import net.minecraft.registry.Registries; +import net.minecraft.screen.AbstractRecipeScreenHandler; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = RecipeBookWidget.class, priority = 1001) +public abstract class RecipeBookWidgetMixin implements PaginatedRecipeBookWidget { + @Shadow + protected MinecraftClient client; + + @Shadow + @Final + private List tabButtons; + + @Shadow + protected AbstractRecipeScreenHandler craftingScreenHandler; + + @Shadow + private int parentWidth; + + @Shadow + private int parentHeight; + + @Shadow + private int leftOffset; + + @Shadow + public abstract boolean isOpen(); + + @Shadow + @Final + public static int field_32408; + + @Shadow + @Final + public static int field_32409; + + @Shadow + @Nullable private RecipeGroupButtonWidget currentTab; + + @Shadow + private ClientRecipeBook recipeBook; + + @Unique private int rbip$page = 0; + + @Unique private int rbip$pages; + + @Unique private RecipeBookPageButton rbip$nextPageButton; + + @Unique private RecipeBookPageButton rbip$prevPageButton; + + @Inject( + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/client/gui/screen/recipebook/RecipeGroupButtonWidget;setToggled(Z)V", + shift = At.Shift.BEFORE), + method = "reset") + private void dark_matter$reset(CallbackInfo ci) { + int a = (this.parentWidth - rbip$horizontalOffset()) / 2 - this.leftOffset; + int s = (this.parentHeight - rbip$verticalOffset()) / 2; + this.rbip$nextPageButton = + new RecipeBookPageButton(a + 18, s - 13, (RecipeBookWidget) (Object) this, true); + this.rbip$prevPageButton = + new RecipeBookPageButton(a + 3, s - 13, (RecipeBookWidget) (Object) this, false); + } + + @Inject( + at = + @At( + value = "INVOKE", + target = "Lnet/minecraft/client/util/math/MatrixStack;pop()V", + shift = At.Shift.BEFORE), + method = "render") + private void dark_matter$render( + DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + this.rbip$prevPageButton.render(context, mouseX, mouseY, delta); + this.rbip$nextPageButton.render(context, mouseX, mouseY, delta); + } + + @Inject(at = @At("HEAD"), method = "mouseClicked", cancellable = true) + private void dark_matter$mouseClicked( + double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { + if (this.client.player != null) + if (this.isOpen() && !this.client.player.isSpectator()) { + if (this.rbip$nextPageButton.mouseClicked(mouseX, mouseY, button)) { + this.rbip$incrementPage(); + cir.setReturnValue(true); + } else if (this.rbip$prevPageButton.mouseClicked(mouseX, mouseY, button)) { + this.rbip$decrementPage(); + cir.setReturnValue(true); + } + } + } + + @Inject(at = @At("TAIL"), method = "refreshResults") + private void dark_matter$refreshResults(boolean resetCurrentPage, CallbackInfo ci) { + if (resetCurrentPage && this.currentTab != null) { + if (this.rbip$getPage() + != ((PaginatedRecipeGroupButtonWidget) this.currentTab).rbip$getPage()) { + this.rbip$setPage( + Math.max(((PaginatedRecipeGroupButtonWidget) this.currentTab).rbip$getPage(), 0)); + } + } + } + + @ModifyExpressionValue( + at = + @At( + value = "FIELD", + target = + "Lnet/minecraft/client/recipebook/RecipeBookGroup;CRAFTING_SEARCH:Lnet/minecraft/client/recipebook/RecipeBookGroup;"), + method = "refreshTabButtons", + require = 0) + private RecipeBookGroup dark_matter$refresh$correctGroup( + RecipeBookGroup group, @Local RecipeGroupButtonWidget widget) { + return RecipeBookGroup.SEARCH_MAP.containsKey(widget.getCategory()) + ? widget.getCategory() + : group; + } + + @ModifyArg( + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/client/gui/screen/recipebook/RecipeGroupButtonWidget;setPosition(II)V"), + method = "refreshTabButtons", + index = 1) + private int dark_matter$refresh$setPos( + int y, + @Local RecipeGroupButtonWidget widget, + @Local(ordinal = 1) int j, + @Share("index") LocalIntRef index) { + int pos = j + widget.getHeight() * index.get(); + index.set(index.get() + 1); + return pos; + } + + @Inject( + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/client/gui/screen/recipebook/RecipeGroupButtonWidget;setPosition(II)V", + shift = At.Shift.AFTER), + method = "refreshTabButtons") + private void dark_matter$refresh$setPos( + CallbackInfo ci, + @Local RecipeGroupButtonWidget widget, + @Share("index") LocalIntRef index, + @Share("wc") LocalIntRef wc) { + ((PaginatedRecipeGroupButtonWidget) widget).rbip$setPage((int) Math.floor(wc.get() / 6f)); + if (index.get() == 6) index.set(0); + wc.set(wc.get() + 1); + } + + @Inject(at = @At("TAIL"), method = "refreshTabButtons") + private void dark_matter$refresh$tail(CallbackInfo ci, @Share("wc") LocalIntRef wc) { + this.rbip$pages = (int) Math.ceil(wc.get() / 6f); + this.rbip$updatePages(); + this.rbip$updatePageSwitchButtons(); + } + + @Unique private static int rbip$horizontalOffset() { + return field_32408; + } + + @Unique private static int rbip$verticalOffset() { + return field_32409; + } + + @Unique @Override + public void rbip$updatePages() { + for (RecipeGroupButtonWidget widget : this.tabButtons) { + widget.visible = ((PaginatedRecipeGroupButtonWidget) widget).rbip$getPage() == this.rbip$page; + } + } + + @Unique @Override + public void rbip$updatePageSwitchButtons() { + if (this.rbip$nextPageButton != null) { + this.rbip$nextPageButton.visible = this.rbip$getPageCount() > 1; + this.rbip$nextPageButton.active = this.rbip$getPage() < (this.rbip$getPageCount() - 1); + } + if (this.rbip$prevPageButton != null) { + this.rbip$prevPageButton.visible = this.rbip$getPageCount() > 1; + this.rbip$prevPageButton.active = this.rbip$getPage() > 0; + } + } + + @Unique @Override + public int rbip$getPage() { + return this.rbip$page; + } + + @Unique @Override + public void rbip$setPage(int page) { + if (page < 0) page = 0; + if (page > rbip$pages - 1) page = rbip$pages - 1; + + this.rbip$page = page; + rbip$updatePages(); + rbip$updatePageSwitchButtons(); + } + + @Unique @Override + public int rbip$getPageCount() { + return this.rbip$pages; + } + + // + // The Hacky part is here! + // + + @Inject( + at = @At(value = "INVOKE", target = "Ljava/util/List;clear()V", shift = At.Shift.AFTER), + method = "reset") + private void init(CallbackInfo ci) { + if (this.craftingScreenHandler.getCategory() != RecipeBookCategory.CRAFTING) return; + + var search = RecipeBookGroup.getGroups(this.craftingScreenHandler.getCategory()).stream() + .filter(RecipeBookGroup.SEARCH_MAP::containsKey) + .findFirst(); + search.ifPresent( + recipeBookGroup -> this.tabButtons.add(new RecipeGroupButtonWidget(recipeBookGroup))); + + Registries.ITEM_GROUP.stream() + .filter(itemGroup -> !itemGroup.isSpecial()) + .forEach(itemGroup -> { + var widget = new RecipeGroupButtonWidget(RecipeBookGroup.CRAFTING_MISC); + ((RecipeGroupButtonWidgetDuck) widget).rbip$setRealItemGroup(itemGroup); + this.tabButtons.add(widget); + }); + } + + @WrapOperation( + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/client/recipebook/RecipeBookGroup;equals(Ljava/lang/Object;)Z"), + method = "method_2582") + private boolean checkTabInEquals( + RecipeBookGroup instance, + Object o, + Operation original, + @Local(argsOnly = true) RecipeGroupButtonWidget widget) { + if (((RecipeGroupButtonWidgetDuck) widget).rbip$getRealItemGroup() != null + && this.currentTab != null) { + return Objects.equals( + ((RecipeGroupButtonWidgetDuck) widget).rbip$getRealItemGroup(), + ((RecipeGroupButtonWidgetDuck) this.currentTab).rbip$getRealItemGroup()); + } + return original.call(instance, o); + } + + @ModifyExpressionValue( + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/client/recipebook/RecipeBookGroup;getGroups(Lnet/minecraft/recipe/book/RecipeBookCategory;)Ljava/util/List;"), + method = "reset") + private List skipRealButtons(List original) { + return this.craftingScreenHandler.getCategory() == RecipeBookCategory.CRAFTING + ? List.of() + : original; + } + + @ModifyExpressionValue( + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/client/recipebook/ClientRecipeBook;getResultsForGroup(Lnet/minecraft/client/recipebook/RecipeBookGroup;)Ljava/util/List;"), + method = "refreshResults") + private List refreshResults(List original) { + var real = ((RecipeGroupButtonWidgetDuck) this.currentTab).rbip$getRealItemGroup(); + if (real != null) { + return ((ClientRecipeBookDuck) this.recipeBook).rbip$getResultsForGroup(real); + } + return original; + } + + @Inject( + at = + @At( + value = "INVOKE", + target = "Lnet/minecraft/client/util/math/MatrixStack;pop()V", + shift = At.Shift.BEFORE), + method = "render") + private void rbip$renderTooltip( + DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (client.currentScreen == null) return; + if (this.craftingScreenHandler.getCategory() != RecipeBookCategory.CRAFTING) return; + + this.tabButtons.stream() + .filter(widget -> widget.visible && widget.isHovered()) + .forEach(widget -> { + if (RecipeBookGroup.SEARCH_MAP.containsKey(widget.getCategory())) { + context.drawTooltip( + client.textRenderer, ItemGroups.getSearchGroup().getDisplayName(), mouseX, mouseY); + } else { + Optional.ofNullable(((RecipeGroupButtonWidgetDuck) widget).rbip$getRealItemGroup()) + .map(ItemGroup::getDisplayName) + .ifPresent(text -> context.drawTooltip(client.textRenderer, text, mouseX, mouseY)); + } + }); + } +} diff --git a/src/main/java/dev/zenfyr/rbip/mixin/RecipeGroupButtonMixin.java b/src/main/java/dev/zenfyr/rbip/mixin/RecipeGroupButtonMixin.java new file mode 100644 index 0000000..c752306 --- /dev/null +++ b/src/main/java/dev/zenfyr/rbip/mixin/RecipeGroupButtonMixin.java @@ -0,0 +1,113 @@ +package dev.zenfyr.rbip.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import dev.zenfyr.rbip.RecipeBookIsPain; +import dev.zenfyr.rbip.access.ClientRecipeBookDuck; +import dev.zenfyr.rbip.access.PaginatedRecipeGroupButtonWidget; +import dev.zenfyr.rbip.access.RecipeGroupButtonWidgetDuck; +import dev.zenfyr.rbip.compat.OwOCompat; +import dev.zenfyr.rbip.compat.PulsarCompat; +import java.util.List; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget; +import net.minecraft.client.gui.screen.recipebook.RecipeResultCollection; +import net.minecraft.client.gui.widget.ToggleButtonWidget; +import net.minecraft.client.recipebook.ClientRecipeBook; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(RecipeGroupButtonWidget.class) +public abstract class RecipeGroupButtonMixin extends ToggleButtonWidget + implements RecipeGroupButtonWidgetDuck, PaginatedRecipeGroupButtonWidget { + + public RecipeGroupButtonMixin(int x, int y, int width, int height, boolean toggled) { + super(x, y, width, height, toggled); + } + + @Unique private int rbip$page = -1; + + @Unique private ItemGroup rbip$realGroup; + + @Override + public int rbip$getPage() { + return rbip$page; + } + + @Override + public void rbip$setPage(int page) { + this.rbip$page = page; + } + + @Override + public void rbip$setRealItemGroup(ItemGroup group) { + this.rbip$realGroup = group; + } + + @Override + public ItemGroup rbip$getRealItemGroup() { + return this.rbip$realGroup; + } + + @ModifyExpressionValue( + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/client/recipebook/ClientRecipeBook;getResultsForGroup(Lnet/minecraft/client/recipebook/RecipeBookGroup;)Ljava/util/List;"), + method = "checkForNewRecipes") + private List checkForNewRecipes( + List original, @Local ClientRecipeBook recipeBook) { + if (this.rbip$realGroup != null) { + return ((ClientRecipeBookDuck) recipeBook).rbip$getResultsForGroup(this.rbip$realGroup); + } + return original; + } + + @ModifyExpressionValue( + at = + @At( + value = "INVOKE", + target = + "Lnet/minecraft/client/recipebook/ClientRecipeBook;getResultsForGroup(Lnet/minecraft/client/recipebook/RecipeBookGroup;)Ljava/util/List;"), + method = "hasKnownRecipes") + private List hasKnownRecipes( + List original, @Local(argsOnly = true) ClientRecipeBook recipeBook) { + if (this.rbip$realGroup != null) { + return ((ClientRecipeBookDuck) recipeBook).rbip$getResultsForGroup(this.rbip$realGroup); + } + return original; + } + + @Inject(at = @At("HEAD"), method = "renderIcons", cancellable = true) + private void rbip$render(DrawContext context, ItemRenderer itemRenderer, CallbackInfo ci) { + if (this.rbip$realGroup == null) return; + + int i = this.toggled ? -2 : 0; + + if (RecipeBookIsPain.isOwOLoaded) { + if (OwOCompat.render(context, i, (RecipeGroupButtonWidget) (Object) this, rbip$realGroup)) { + ci.cancel(); + return; + } + } + + if (RecipeBookIsPain.isPulsarLoaded) { + if (PulsarCompat.render( + context, i, (RecipeGroupButtonWidget) (Object) this, rbip$realGroup)) { + ci.cancel(); + return; + } + } + + ItemStack icon = this.rbip$realGroup.getIcon(); + if (!icon.isEmpty()) context.drawItemWithoutEntity(icon, this.getX() + 9 + i, this.getY() + 5); + ci.cancel(); + } +} diff --git a/src/main/java/me/melontini/recipebookispain/RecipeBookIsPain.java b/src/main/java/me/melontini/recipebookispain/RecipeBookIsPain.java deleted file mode 100644 index 742cf30..0000000 --- a/src/main/java/me/melontini/recipebookispain/RecipeBookIsPain.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.melontini.recipebookispain; - -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import io.wispforest.owo.itemgroup.OwoItemGroup; -import me.melontini.dark_matter.api.item_group.ItemGroupAnimaton; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget; -import net.minecraft.client.recipebook.RecipeBookGroup; -import net.minecraft.item.ItemGroup; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.ArrayList; -import java.util.List; - -@Environment(EnvType.CLIENT) -public class RecipeBookIsPain { - - public static final Logger LOGGER = LogManager.getLogger("RBIP"); - public static final boolean isOwOLoaded = FabricLoader.getInstance().isModLoaded("owo"); - public static final boolean isDarkMatterContentLoaded = FabricLoader.getInstance().isModLoaded("dark-matter-content"); - - public static final List CRAFTING_SEARCH_LIST = new ArrayList<>(); - public static final List CRAFTING_LIST = new ArrayList<>(); - public static final BiMap RECIPE_BOOK_GROUP_TO_ITEM_GROUP = HashBiMap.create(); - - public static ItemGroup toItemGroup(RecipeBookGroup recipeBookGroup) { - return RECIPE_BOOK_GROUP_TO_ITEM_GROUP.get(recipeBookGroup); - } - - public static RecipeBookGroup toRecipeBookGroup(ItemGroup itemGroup) { - return RECIPE_BOOK_GROUP_TO_ITEM_GROUP.inverse().get(itemGroup); - } - - public static boolean rbip$renderOwo(DrawContext context, int i, RecipeGroupButtonWidget widget, ItemGroup group) { - if (group instanceof OwoItemGroup owoItemGroup) { - MinecraftClient client = MinecraftClient.getInstance(); - double e = client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth(); - double f = client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight(); - owoItemGroup.icon().render(context, widget.getX() + 9 + i, widget.getY() + 5, (int) e, (int) f, client.getTickDelta()); - return true; - } - return false; - } - - public static boolean renderDarkMatter(DrawContext context, int i, RecipeGroupButtonWidget widget, ItemGroup group) { - return ItemGroupAnimaton.getIconAnimation(group).map(animation -> { - animation.animateIcon(group, context, widget.getX() + 9 + i, widget.getY() + 5, widget.isToggled(), false); - return true; - }).orElse(false); - } -} diff --git a/src/main/java/me/melontini/recipebookispain/access/ItemAccess.java b/src/main/java/me/melontini/recipebookispain/access/ItemAccess.java deleted file mode 100644 index 452928d..0000000 --- a/src/main/java/me/melontini/recipebookispain/access/ItemAccess.java +++ /dev/null @@ -1,10 +0,0 @@ -package me.melontini.recipebookispain.access; - -import net.minecraft.item.ItemGroup; - -import java.util.Optional; - -public interface ItemAccess { - Optional rbip$getPossibleGroup(); - void rbip$setPossibleGroup(ItemGroup group); -} diff --git a/src/main/java/me/melontini/recipebookispain/mixin/ItemMixin.java b/src/main/java/me/melontini/recipebookispain/mixin/ItemMixin.java deleted file mode 100644 index 0a27b05..0000000 --- a/src/main/java/me/melontini/recipebookispain/mixin/ItemMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package me.melontini.recipebookispain.mixin; - -import me.melontini.recipebookispain.access.ItemAccess; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -import java.util.Optional; - -@Mixin(Item.class) -public class ItemMixin implements ItemAccess { - @Unique - public ItemGroup rbip$possibleGroup; - - @Override - public Optional rbip$getPossibleGroup() { - return Optional.ofNullable(rbip$possibleGroup); - } - - @Override - public void rbip$setPossibleGroup(ItemGroup group) { - rbip$possibleGroup = group; - } -} diff --git a/src/main/java/me/melontini/recipebookispain/mixin/groups/ClientRecipeBookMixin.java b/src/main/java/me/melontini/recipebookispain/mixin/groups/ClientRecipeBookMixin.java deleted file mode 100644 index 60c6e76..0000000 --- a/src/main/java/me/melontini/recipebookispain/mixin/groups/ClientRecipeBookMixin.java +++ /dev/null @@ -1,77 +0,0 @@ -package me.melontini.recipebookispain.mixin.groups; - -import com.llamalad7.mixinextras.sugar.Local; -import me.melontini.dark_matter.api.recipe_book.RecipeBookHelper; -import me.melontini.recipebookispain.RecipeBookIsPain; -import me.melontini.recipebookispain.access.ItemAccess; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.recipebook.ClientRecipeBook; -import net.minecraft.client.recipebook.RecipeBookGroup; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemGroups; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeType; -import net.minecraft.registry.DynamicRegistryManager; -import net.minecraft.registry.Registries; -import net.minecraft.resource.featuretoggle.FeatureFlags; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -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; - -import static me.melontini.recipebookispain.RecipeBookIsPain.*; - -@Mixin(value = ClientRecipeBook.class, priority = 999) -public class ClientRecipeBookMixin { - - @Unique - private static boolean rbip$firstReload = true; - - @Inject(at = @At("HEAD"), method = "reload") - private void rbip$reload(CallbackInfo ci, @Local(argsOnly = true) DynamicRegistryManager manager) { - if (!rbip$firstReload) return; - ItemGroups.updateDisplayContext(FeatureFlags.FEATURE_MANAGER.getFeatureSet(), false, manager); - - ItemGroups.getGroups().stream().filter(itemGroup -> itemGroup.getType() != ItemGroup.Type.INVENTORY && itemGroup.getType() != ItemGroup.Type.HOTBAR && itemGroup.getType() != ItemGroup.Type.SEARCH) - .forEach(group -> group.getSearchTabStacks().stream().filter(stack -> ((ItemAccess) stack.getItem()).rbip$getPossibleGroup().isEmpty()) - .forEach(stack -> ((ItemAccess) stack.getItem()).rbip$setPossibleGroup(group))); - - ItemGroups.getGroups().stream().filter(itemGroup -> itemGroup.getType() != ItemGroup.Type.HOTBAR && itemGroup.getType() != ItemGroup.Type.INVENTORY && itemGroup.getType() != ItemGroup.Type.SEARCH) - .forEach(itemGroup -> { - try { - RecipeBookGroup recipeBookGroup = RecipeBookHelper.createGroup(new Identifier("rbip", "crafting_" + ItemGroups.getGroups().indexOf(itemGroup)), itemGroup.getIcon()); - RECIPE_BOOK_GROUP_TO_ITEM_GROUP.put(recipeBookGroup, itemGroup); - - CRAFTING_LIST.add(recipeBookGroup); - CRAFTING_SEARCH_LIST.add(recipeBookGroup); - } catch (Exception e) { - RecipeBookIsPain.LOGGER.error("Error while processing %s item group".formatted(itemGroup.getDisplayName()), e); - } - }); - CRAFTING_LIST.add(0, RecipeBookGroup.CRAFTING_SEARCH); - CRAFTING_LIST.add(RecipeBookGroup.CRAFTING_MISC); - CRAFTING_SEARCH_LIST.add(RecipeBookGroup.CRAFTING_MISC); - - RecipeBookGroup.SEARCH_MAP.replace(RecipeBookGroup.CRAFTING_SEARCH, CRAFTING_SEARCH_LIST); - LOGGER.info("[RBIP] recipe book init complete"); - rbip$firstReload = false; - } - - @Inject(at = @At("HEAD"), method = "getGroupForRecipe", cancellable = true) - private static void rbip$getGroupForRecipe(Recipe recipe, CallbackInfoReturnable cir) { - if (RecipeType.CRAFTING.equals(recipe.getType())) { - var nh = MinecraftClient.getInstance().getNetworkHandler(); - if (nh == null) return; - - ItemStack itemStack = recipe.getOutput(nh.getRegistryManager()); - ((ItemAccess) itemStack.getItem()).rbip$getPossibleGroup() - .filter(group -> group.getType() != ItemGroup.Type.INVENTORY && group.getType() != ItemGroup.Type.HOTBAR && group.getType() != ItemGroup.Type.SEARCH) - .map(RecipeBookIsPain::toRecipeBookGroup) - .ifPresentOrElse(cir::setReturnValue, () -> cir.setReturnValue(toRecipeBookGroup(Registries.ITEM_GROUP.get(ItemGroups.BUILDING_BLOCKS)))); - } - } -} diff --git a/src/main/java/me/melontini/recipebookispain/mixin/groups/RecipeBookGroupMixin.java b/src/main/java/me/melontini/recipebookispain/mixin/groups/RecipeBookGroupMixin.java deleted file mode 100644 index 7f507d9..0000000 --- a/src/main/java/me/melontini/recipebookispain/mixin/groups/RecipeBookGroupMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.melontini.recipebookispain.mixin.groups; - -import net.minecraft.client.recipebook.RecipeBookGroup; -import net.minecraft.recipe.book.RecipeBookCategory; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.List; - -import static me.melontini.recipebookispain.RecipeBookIsPain.CRAFTING_LIST; - -@Mixin(RecipeBookGroup.class) -@Unique -public class RecipeBookGroupMixin { - - @Inject(at = @At("HEAD"), method = "getGroups", cancellable = true) - private static void rbip$getGroups(RecipeBookCategory category, CallbackInfoReturnable> cir) { - if (category == RecipeBookCategory.CRAFTING) cir.setReturnValue(CRAFTING_LIST); - } -} diff --git a/src/main/java/me/melontini/recipebookispain/mixin/widget/RecipeBookTooltipMixin.java b/src/main/java/me/melontini/recipebookispain/mixin/widget/RecipeBookTooltipMixin.java deleted file mode 100644 index cada9b9..0000000 --- a/src/main/java/me/melontini/recipebookispain/mixin/widget/RecipeBookTooltipMixin.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.melontini.recipebookispain.mixin.widget; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; -import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget; -import net.minecraft.client.recipebook.RecipeBookGroup; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemGroups; -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; -import java.util.Optional; - -import static me.melontini.recipebookispain.RecipeBookIsPain.toItemGroup; - -@Mixin(value = RecipeBookWidget.class, priority = 1001) -public class RecipeBookTooltipMixin { - @Shadow protected MinecraftClient client; - @Shadow @Final private List tabButtons; - - @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;pop()V", shift = At.Shift.BEFORE), method = "render") - private void rbip$renderTooltip(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - if (client.currentScreen != null) { - this.tabButtons.stream().filter(widget -> widget.visible && widget.isHovered()).forEach(widget -> { - if (RecipeBookGroup.SEARCH_MAP.containsKey(widget.getCategory())) { - context.drawTooltip(client.textRenderer, ItemGroups.getSearchGroup().getDisplayName(), mouseX, mouseY); - } else { - Optional.ofNullable(toItemGroup(widget.getCategory())) - .map(ItemGroup::getDisplayName) - .ifPresent(text -> context.drawTooltip(client.textRenderer, text, mouseX, mouseY)); - } - }); - } - } -} diff --git a/src/main/java/me/melontini/recipebookispain/mixin/widget/RecipeGroupButtonMixin.java b/src/main/java/me/melontini/recipebookispain/mixin/widget/RecipeGroupButtonMixin.java deleted file mode 100644 index 8f14f6a..0000000 --- a/src/main/java/me/melontini/recipebookispain/mixin/widget/RecipeGroupButtonMixin.java +++ /dev/null @@ -1,44 +0,0 @@ -package me.melontini.recipebookispain.mixin.widget; - -import me.melontini.recipebookispain.RecipeBookIsPain; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget; -import net.minecraft.client.gui.widget.ToggleButtonWidget; -import net.minecraft.client.recipebook.RecipeBookGroup; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.item.ItemGroup; -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; - -@Mixin(RecipeGroupButtonWidget.class) -public abstract class RecipeGroupButtonMixin extends ToggleButtonWidget { - @Shadow @Final private RecipeBookGroup category; - - public RecipeGroupButtonMixin(int x, int y, int width, int height, boolean toggled) { - super(x, y, width, height, toggled); - } - - @Inject(at = @At("HEAD"), method = "renderIcons", cancellable = true) - private void rbip$render(DrawContext context, ItemRenderer itemRenderer, CallbackInfo ci) { - ItemGroup group = RecipeBookIsPain.toItemGroup(this.category); - if (group == null) return; - - int i = this.toggled ? -2 : 0; - - if (RecipeBookIsPain.isOwOLoaded) { - if (RecipeBookIsPain.rbip$renderOwo(context, i, (RecipeGroupButtonWidget) (Object) this, group)) { - ci.cancel(); - return; - } - } - if (RecipeBookIsPain.isDarkMatterContentLoaded) { - if (RecipeBookIsPain.renderDarkMatter(context, i, (RecipeGroupButtonWidget) (Object) this, group)) { - ci.cancel(); - } - } - } -} diff --git a/src/main/resources/assets/recipe-book-is-pain/icon.png b/src/main/resources/assets/rbip/icon.png similarity index 100% rename from src/main/resources/assets/recipe-book-is-pain/icon.png rename to src/main/resources/assets/rbip/icon.png diff --git a/src/main/resources/assets/rbip/textures/gui/recipe_book_buttons.png b/src/main/resources/assets/rbip/textures/gui/recipe_book_buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..e0cb319a1377d6b361642029a33cd87b91d38a50 GIT binary patch literal 789 zcmeAS@N?(olHy`uVBq!ia0y~yU}OMc4mJh`hM1xiX$%ZZcRXDjLn`9l-f--??I6H< zVdqr;N2O+#PTLf3HZ*PGPSu)f ze!sfpPB^nq)tRn>r@OxNzi&7sHRJbRJJaj0zdqLfed_La`TfhDU4EXw{vIQhqLUw z8EVeO@N6yPs-`)+c|L6}51mkK9?h^bn86^O*I)F}QH>LenIb~ULp#JlX81qnlZa^E z%=)!#cj~fvdJRvvuiCA}NgU&WpC*oH4W8#MV<_6b8)QNj zo7H@IQ3tzz>jy5g7RdRAGPo~hcu+HIfm|;W!$<%Y-Q^3W35#ClX)^_R*VEO{Wt~$( F697!P{mcLW literal 0 HcmV?d00001 diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 3c10583..3054031 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,27 +1,30 @@ { "schemaVersion": 1, - "id": "recipe-book-is-pain", + "id": "rbip", "version": "${version}", "name": "Recipe Book Is Pain", "description": "Makes the recipe book use a little more enums", "authors": [ - "melontini" + "zenfyr" ], "contact": { - "sources": "https://github.com/constellation-mc/recipe_book_is_pain", - "issues": "https://github.com/constellation-mc/recipe_book_is_pain/issues" + "sources": "https://github.com/constellation-mc/rbip", + "issues": "https://github.com/constellation-mc/rbip/issues" }, "license": "MIT", - "icon": "assets/recipe-book-is-pain/icon.png", + "icon": "assets/rbip/icon.png", "environment": "client", "entrypoints": { + "client": [ + "dev.zenfyr.rbip.RecipeBookIsPain" + ] }, "mixins": [ - "recipe-book-is-pain.mixins.json" + "rbip.mixins.json" ], "depends": { "fabricloader": ">=${loader_version}", - "minecraft": ">=${minecraft_version}", - "dark-matter-base": "*" + "minecraft": "${minecraft_version}", + "fabric": ">=${fabric_version}" } } diff --git a/src/main/resources/rbip.mixins.json b/src/main/resources/rbip.mixins.json new file mode 100644 index 0000000..2cd166c --- /dev/null +++ b/src/main/resources/rbip.mixins.json @@ -0,0 +1,16 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "dev.zenfyr.rbip.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + ], + "client": [ + "ClientRecipeBookMixin", + "RecipeBookWidgetMixin", + "RecipeGroupButtonMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/recipe-book-is-pain.mixins.json b/src/main/resources/recipe-book-is-pain.mixins.json deleted file mode 100644 index 57563d1..0000000 --- a/src/main/resources/recipe-book-is-pain.mixins.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "required": true, - "minVersion": "0.8", - "package": "me.melontini.recipebookispain.mixin", - "compatibilityLevel": "JAVA_17", - "mixins": [ - ], - "client": [ - "ItemMixin", - "groups.ClientRecipeBookMixin", - "groups.RecipeBookGroupMixin", - "widget.RecipeBookTooltipMixin", - "widget.RecipeGroupButtonMixin" - ], - "injectors": { - "defaultRequire": 1 - } -}