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
- }
-}