Эх сурвалжийг харах

Fix endless recursion with item and fluid

Signed-off-by: shedaniel <daniel@shedaniel.me>
shedaniel 5 жил өмнө
parent
commit
d17036320d

+ 1 - 1
gradle.properties

@@ -1,4 +1,4 @@
-mod_version=4.1.13-unstable
+mod_version=4.1.14-unstable
 supported_version=20w16a
 minecraft_version=20w16a
 yarn_version=20w16a+build.1

+ 4 - 4
src/main/java/me/shedaniel/rei/gui/FailedToLoadScreen.java → src/main/java/me/shedaniel/rei/gui/WarningAndErrorScreen.java

@@ -43,13 +43,13 @@ import java.net.URI;
 import java.net.URISyntaxException;
 
 @ApiStatus.Internal
-public class FailedToLoadScreen extends Screen {
-    public static final Lazy<FailedToLoadScreen> INSTANCE = new Lazy<>(FailedToLoadScreen::new);
+public class WarningAndErrorScreen extends Screen {
+    public static final Lazy<WarningAndErrorScreen> INSTANCE = new Lazy<>(WarningAndErrorScreen::new);
     private AbstractButtonWidget buttonExit;
     private StringEntryListWidget listWidget;
     private Screen parent;
     
-    private FailedToLoadScreen() {
+    private WarningAndErrorScreen() {
         super(NarratorManager.EMPTY);
     }
     
@@ -260,7 +260,7 @@ public class FailedToLoadScreen extends Screen {
         public void render(int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
             contains = mouseX >= x && mouseX <= x + entryWidth && mouseY >= y && mouseY <= y + entryHeight;
             if (contains) {
-                FailedToLoadScreen.this.renderTooltip("Click to open link.", mouseX, mouseY);
+                WarningAndErrorScreen.this.renderTooltip("Click to open link.", mouseX, mouseY);
                 MinecraftClient.getInstance().textRenderer.drawWithShadow("§n" + text, x + 5, y, 0xff1fc3ff);
             } else {
                 MinecraftClient.getInstance().textRenderer.drawWithShadow(text, x + 5, y, 0xff1fc3ff);

+ 18 - 10
src/main/java/me/shedaniel/rei/impl/FluidEntryStack.java

@@ -52,12 +52,12 @@ import java.util.*;
 @ApiStatus.Internal
 public class FluidEntryStack extends AbstractEntryStack {
     private static final Map<Fluid, Pair<Sprite, Integer>> FLUID_SPRITE_CACHE = new HashMap<>();
-    private static final double EMPTY_AMOUNT = -1319182373;
+    private static final double IGNORE_AMOUNT = -1319182373;
     private Fluid fluid;
     private double amount;
     
     public FluidEntryStack(Fluid fluid) {
-        this(fluid, EMPTY_AMOUNT);
+        this(fluid, IGNORE_AMOUNT);
     }
     
     public FluidEntryStack(Fluid fluid, int amount) {
@@ -103,7 +103,7 @@ public class FluidEntryStack extends AbstractEntryStack {
     
     @Override
     public void setFloatingAmount(double amount) {
-        this.amount = amount <= 0 ? EMPTY_AMOUNT : amount;
+        this.amount = amount == IGNORE_AMOUNT ? IGNORE_AMOUNT :  Math.max(amount, 0);
         if (isEmpty()) {
             fluid = Fluids.EMPTY;
         }
@@ -111,7 +111,7 @@ public class FluidEntryStack extends AbstractEntryStack {
     
     @Override
     public boolean isEmpty() {
-        return (amount != EMPTY_AMOUNT && amount <= 0) || fluid == Fluids.EMPTY;
+        return (amount != IGNORE_AMOUNT && amount <= 0) || fluid == Fluids.EMPTY;
     }
     
     @Override
@@ -130,30 +130,38 @@ public class FluidEntryStack extends AbstractEntryStack {
     
     @Override
     public boolean equalsIgnoreTagsAndAmount(EntryStack stack) {
+        if (stack.getType() == Type.ITEM)
+            return equalsIgnoreTagsAndAmount(EntryStack.copyItemToFluid(stack));
         if (stack.getType() != Type.FLUID)
-            return EntryStack.copyFluidToItem(this).equalsIgnoreTagsAndAmount(stack);
+            return false;
         return fluid == stack.getFluid();
     }
     
     @Override
     public boolean equalsIgnoreTags(EntryStack stack) {
+        if (stack.getType() == Type.ITEM)
+            return equalsIgnoreTags(EntryStack.copyItemToFluid(stack));
         if (stack.getType() != Type.FLUID)
-            return EntryStack.copyFluidToItem(this).equalsIgnoreTags(stack);
-        return fluid == stack.getFluid() && amount == stack.getAmount();
+            return false;
+        return fluid == stack.getFluid() && (amount == IGNORE_AMOUNT || stack.getAmount() == IGNORE_AMOUNT || amount == stack.getAmount());
     }
     
     @Override
     public boolean equalsIgnoreAmount(EntryStack stack) {
+        if (stack.getType() == Type.ITEM)
+            return equalsIgnoreAmount(EntryStack.copyItemToFluid(stack));
         if (stack.getType() != Type.FLUID)
-            return EntryStack.copyFluidToItem(this).equalsIgnoreAmount(stack);
+            return false;
         return fluid == stack.getFluid();
     }
     
     @Override
     public boolean equalsAll(EntryStack stack) {
+        if (stack.getType() == Type.ITEM)
+            return equalsAll(EntryStack.copyItemToFluid(stack));
         if (stack.getType() != Type.FLUID)
-            return EntryStack.copyFluidToItem(this).equalsAll(stack);
-        return fluid == stack.getFluid() && amount == stack.getAmount();
+            return false;
+        return fluid == stack.getFluid() && (amount == IGNORE_AMOUNT || stack.getAmount() == IGNORE_AMOUNT || amount == stack.getAmount());
     }
     
     @Override

+ 39 - 7
src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java

@@ -111,26 +111,56 @@ public class ItemEntryStack extends AbstractEntryStack implements OptimalEntrySt
         return itemStack;
     }
     
+    /**
+     * type:
+     * 0: ignore tags and amount
+     * 1: ignore tags
+     * 2: ignore amount
+     * 3: all
+     */
+    private Boolean compareIfFluid(EntryStack stack, int type) {
+        EntryStack fluid = EntryStack.copyItemToFluid(this);
+        if (fluid.isEmpty()) return null;
+        if (stack.getType() == Type.ITEM)
+            stack = EntryStack.copyItemToFluid(stack);
+        if (stack.isEmpty()) return null;
+        switch (type) {
+            case 0:
+                return fluid.equalsIgnoreTagsAndAmount(stack);
+            case 1:
+                return fluid.equalsIgnoreTags(stack);
+            case 2:
+                return fluid.equalsIgnoreAmount(stack);
+            case 3:
+                return fluid.equalsAll(stack);
+        }
+        return null;
+    }
+    
     @Override
     public boolean equalsIgnoreTagsAndAmount(EntryStack stack) {
+        Boolean ifFluid = compareIfFluid(stack, 0);
+        if (ifFluid != null) return ifFluid;
         if (stack.getType() != Type.ITEM)
-            return EntryStack.copyItemToFluid(this).equalsIgnoreTagsAndAmount(stack);
-        return itemStack.getItem() == stack.getItem();
+            return false;
+        return itemStack.getItem() == stack.getItem() || (stack.getType() != Type.ITEM ? stack : EntryStack.copyItemToFluid(stack)).equalsIgnoreTagsAndAmount(EntryStack.copyItemToFluid(this));
     }
     
     @Override
     public boolean equalsAll(EntryStack stack) {
+        Boolean ifFluid = compareIfFluid(stack, 3);
+        if (ifFluid != null) return ifFluid;
         if (stack.getType() != Type.ITEM)
-            return EntryStack.copyItemToFluid(this).equalsAll(stack);
-        if (itemStack.getItem() != stack.getItem() || getAmount() != stack.getAmount())
             return false;
-        return ItemStack.areTagsEqual(itemStack, stack.getItemStack());
+        return itemStack.getItem() == stack.getItem() && getAmount() != stack.getAmount() && ItemStack.areTagsEqual(itemStack, stack.getItemStack());
     }
     
     @Override
     public boolean equalsIgnoreAmount(EntryStack stack) {
+        Boolean ifFluid = compareIfFluid(stack, 2);
+        if (ifFluid != null) return ifFluid;
         if (stack.getType() != Type.ITEM)
-            return EntryStack.copyItemToFluid(this).equalsIgnoreAmount(stack);
+            return false;
         if (itemStack.getItem() != stack.getItem())
             return false;
         ItemStack otherStack = stack.getItemStack();
@@ -183,8 +213,10 @@ public class ItemEntryStack extends AbstractEntryStack implements OptimalEntrySt
     
     @Override
     public boolean equalsIgnoreTags(EntryStack stack) {
+        Boolean ifFluid = compareIfFluid(stack, 1);
+        if (ifFluid != null) return ifFluid;
         if (stack.getType() != Type.ITEM)
-            return EntryStack.copyItemToFluid(this).equalsIgnoreTags(stack);
+            return false;
         if (itemStack.getItem() != stack.getItem())
             return false;
         return getAmount() == stack.getAmount();

+ 10 - 5
src/main/java/me/shedaniel/rei/impl/ScreenHelper.java

@@ -34,9 +34,9 @@ import me.shedaniel.rei.api.ConfigObject;
 import me.shedaniel.rei.api.REIHelper;
 import me.shedaniel.rei.api.widgets.Tooltip;
 import me.shedaniel.rei.gui.ContainerScreenOverlay;
-import me.shedaniel.rei.gui.FailedToLoadScreen;
 import me.shedaniel.rei.gui.OverlaySearchField;
 import me.shedaniel.rei.gui.RecipeScreen;
+import me.shedaniel.rei.gui.WarningAndErrorScreen;
 import me.shedaniel.rei.gui.widget.TextFieldWidget;
 import net.fabricmc.api.ClientModInitializer;
 import net.fabricmc.fabric.api.event.client.ClientTickCallback;
@@ -204,10 +204,15 @@ public class ScreenHelper implements ClientModInitializer, REIHelper {
     @Override
     public void onInitializeClient() {
         ClothClientHooks.SCREEN_INIT_PRE.register((client, screen, screenHooks) -> {
-            if ((!RoughlyEnoughItemsState.getErrors().isEmpty() || !RoughlyEnoughItemsState.getWarnings().isEmpty()) && !(screen instanceof FailedToLoadScreen)) {
-                FailedToLoadScreen failedToLoadScreen = FailedToLoadScreen.INSTANCE.get();
-                failedToLoadScreen.setParent(screen);
-                client.openScreen(failedToLoadScreen);
+            if ((!RoughlyEnoughItemsState.getErrors().isEmpty() || !RoughlyEnoughItemsState.getWarnings().isEmpty()) && !(screen instanceof WarningAndErrorScreen)) {
+                WarningAndErrorScreen warningAndErrorScreen = WarningAndErrorScreen.INSTANCE.get();
+                warningAndErrorScreen.setParent(screen);
+                try {
+                    if (client.currentScreen != null) client.currentScreen.removed();
+                } catch (Throwable ignored) {
+                }
+                client.currentScreen = null;
+                client.openScreen(warningAndErrorScreen);
             } else if (lastHandledScreen != screen && screen instanceof HandledScreen)
                 lastHandledScreen = (HandledScreen<?>) screen;
             return ActionResult.PASS;