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

v5.8.0 Update
- Config screen animations
- Require dragging the favorites further before initializing the dragging phase
- Require specific fabric modules to run instead of the whole API
- Mark getPreviousContainerScreen as nullable
- New config settings for setting entry list boundaries
- Update fabric loader, auto config and cloth config versions

Signed-off-by: shedaniel <daniel@shedaniel.me>

shedaniel 4 жил өмнө
parent
commit
33de3995b6
26 өөрчлөгдсөн 439 нэмэгдсэн , 41 устгасан
  1. 9 4
      RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/AutoTransferHandler.java
  2. 6 0
      RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/ConfigObject.java
  3. 2 0
      RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/REIHelper.java
  4. 2 0
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultRecipeBookHandler.java
  5. 1 0
      RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingCategory.java
  6. 2 5
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java
  7. 1 5
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java
  8. 19 0
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsState.java
  9. 3 1
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java
  10. 243 0
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/DelegateScreen.java
  11. 73 0
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/TransformingScreen.java
  12. 1 1
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringAddRuleScreen.java
  13. 1 1
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRuleOptionsScreen.java
  14. 1 1
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRulesScreen.java
  15. 1 1
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java
  16. 7 0
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java
  17. 11 2
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java
  18. 13 4
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java
  19. 18 0
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java
  20. 1 1
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/RecipeHelperImpl.java
  21. 2 5
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ScreenHelper.java
  22. 2 0
      RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java
  23. 6 1
      RoughlyEnoughItems-runtime/src/main/resources/roughlyenoughitems-runtime.accessWidener
  24. 6 3
      build.gradle
  25. 6 6
      gradle.properties
  26. 2 0
      src/main/resources/assets/roughlyenoughitems/lang/en_us.json

+ 9 - 4
RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/AutoTransferHandler.java

@@ -32,6 +32,7 @@ import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
 import net.minecraft.world.inventory.AbstractContainerMenu;
 import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.function.Supplier;
 
@@ -182,8 +183,10 @@ public interface AutoTransferHandler {
         
         boolean isActuallyCrafting();
         
+        @Nullable
         AbstractContainerScreen<?> getContainerScreen();
-        
+    
+        @Nullable
         @Deprecated
         @ApiStatus.ScheduledForRemoval
         default AbstractContainerScreen<?> getHandledScreen() {
@@ -191,15 +194,17 @@ public interface AutoTransferHandler {
         }
         
         RecipeDisplay getRecipe();
-        
+    
+        @Nullable
         @Deprecated
         @ApiStatus.ScheduledForRemoval
         default AbstractContainerMenu getScreenHandler() {
             return getContainer();
         }
-        
+    
+        @Nullable
         default AbstractContainerMenu getContainer() {
-            return getHandledScreen().getMenu();
+            return getContainerScreen() == null ? null : getContainerScreen().getMenu();
         }
     }
     

+ 6 - 0
RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/ConfigObject.java

@@ -182,4 +182,10 @@ public interface ConfigObject {
     boolean isInventoryHighlightingAllowed();
     
     boolean shouldResizeDynamically();
+    
+    @ApiStatus.Experimental
+    double getHorizontalEntriesBoundaries();
+    
+    @ApiStatus.Experimental
+    double getVerticalEntriesBoundaries();
 }

+ 2 - 0
RoughlyEnoughItems-api/src/main/java/me/shedaniel/rei/api/REIHelper.java

@@ -51,8 +51,10 @@ public interface REIHelper {
     @ApiStatus.Experimental
     Optional<REIOverlay> getOverlay();
     
+    @Nullable
     AbstractContainerScreen<?> getPreviousContainerScreen();
     
+    @Nullable
     @Deprecated
     default AbstractContainerScreen<?> getPreviousHandledScreen() {
         return getPreviousContainerScreen();

+ 2 - 0
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultRecipeBookHandler.java

@@ -51,6 +51,8 @@ public class DefaultRecipeBookHandler implements AutoTransferHandler {
         if (!(context.getContainer() instanceof RecipeBookMenu))
             return Result.createNotApplicable();
         RecipeBookMenu<?> container = (RecipeBookMenu<?>) context.getContainer();
+        if (container == null)
+            return Result.createNotApplicable();
         if (display instanceof DefaultCraftingDisplay) {
             DefaultCraftingDisplay craftingDisplay = (DefaultCraftingDisplay) display;
             if (craftingDisplay.getOptionalRecipe().isPresent()) {

+ 1 - 0
RoughlyEnoughItems-default-plugin/src/main/java/me/shedaniel/rei/plugin/crafting/DefaultCraftingCategory.java

@@ -96,6 +96,7 @@ public class DefaultCraftingCategory implements TransferRecipeCategory<DefaultCr
     
     @Override
     public void renderRedSlots(PoseStack matrices, List<Widget> widgets, Rectangle bounds, DefaultCraftingDisplay display, IntList redSlots) {
+        if (REIHelper.getInstance().getPreviousContainerScreen() == null) return;
         ContainerInfo<AbstractContainerMenu> info = (ContainerInfo<AbstractContainerMenu>) ContainerInfoHandler.getContainerInfo(getIdentifier(), REIHelper.getInstance().getPreviousContainerScreen().getMenu().getClass());
         if (info == null)
             return;

+ 2 - 5
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java

@@ -383,11 +383,7 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer {
                 RoughlyEnoughItemsCore.LOGGER.error("REI plugin from " + modContainer.getMetadata().getId() + " is not loaded because it is too old!");
         }
         
-        boolean networkingLoaded = FabricLoader.getInstance().isModLoaded("fabric-networking-v0");
-        if (!networkingLoaded) {
-            RoughlyEnoughItemsState.error("Fabric API is not installed!", "https://www.curseforge.com/minecraft/mc-mods/fabric-api/files/all");
-            return;
-        }
+        RoughlyEnoughItemsState.checkRequiredFabricModules();
         Executor.run(() -> () -> {
             ClientSidePacketRegistry.INSTANCE.register(RoughlyEnoughItemsNetwork.CREATE_ITEMS_MESSAGE_PACKET, (packetContext, packetByteBuf) -> {
                 ItemStack stack = packetByteBuf.readItem();
@@ -495,6 +491,7 @@ public class RoughlyEnoughItemsCore implements ClientModInitializer {
     
     private boolean shouldReturn(Screen screen) {
         if (screen == null) return true;
+        if (screen != Minecraft.getInstance().screen) return true;
         return shouldReturn(screen.getClass());
     }
     

+ 1 - 5
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsNetwork.java

@@ -57,11 +57,7 @@ public class RoughlyEnoughItemsNetwork implements ModInitializer {
     
     @Override
     public void onInitialize() {
-        boolean loaded = FabricLoader.getInstance().isModLoaded("fabric-networking-v0");
-        if (!loaded) {
-            RoughlyEnoughItemsState.error("Fabric API is not installed!", "https://www.curseforge.com/minecraft/mc-mods/fabric-api/files/all");
-            return;
-        }
+        RoughlyEnoughItemsState.checkRequiredFabricModules();
         Executor.run(() -> () -> {
             FabricLoader.getInstance().getEntrypoints("rei_containers", Runnable.class).forEach(Runnable::run);
             ServerSidePacketRegistry.INSTANCE.register(DELETE_ITEMS_PACKET, (packetContext, packetByteBuf) -> {

+ 19 - 0
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsState.java

@@ -23,6 +23,7 @@
 
 package me.shedaniel.rei;
 
+import com.google.common.collect.ImmutableSet;
 import net.fabricmc.api.EnvType;
 import net.fabricmc.loader.api.FabricLoader;
 import net.minecraft.util.Tuple;
@@ -56,6 +57,24 @@ public class RoughlyEnoughItemsState {
         }
     }
     
+    public static void checkRequiredFabricModules() {
+        ImmutableSet<String> requiredModules = ImmutableSet.<String>builder()
+                .add("fabric-api-base")
+                .add("fabric-resource-loader-v0")
+                .add("fabric-networking-v0")
+                .add("fabric-lifecycle-events-v1")
+                .add("fabric-lifecycle-events-v1")
+                .add("fabric-rendering-fluids-v1")
+                .build();
+        for (String module : requiredModules) {
+            boolean moduleLoaded = FabricLoader.getInstance().isModLoaded(module);
+            if (!moduleLoaded) {
+                RoughlyEnoughItemsState.error("Fabric API is not installed!", "https://www.curseforge.com/minecraft/mc-mods/fabric-api/files/all");
+                return;
+            }
+        }
+    }
+    
     public static void error(String reason, String link) {
         if (FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER || FabricLoader.getInstance().isDevelopmentEnvironment())
             throw new RuntimeException(reason + " " + link);

+ 3 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java

@@ -401,7 +401,9 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl
                 VillagerRecipeViewingScreen widget = (VillagerRecipeViewingScreen) Minecraft.getInstance().screen;
                 return new Rectangle(widget.bounds.x, 3, widget.bounds.width, 18);
             }
-            return new Rectangle(REIHelper.getInstance().getPreviousContainerScreen().leftPos, 3, REIHelper.getInstance().getPreviousContainerScreen().imageWidth, 18);
+            AbstractContainerScreen<?> containerScreen = REIHelper.getInstance().getPreviousContainerScreen();
+            if (containerScreen != null)
+                return new Rectangle(containerScreen.leftPos, 3, containerScreen.imageWidth, 18);
         }
         return null;
     }

+ 243 - 0
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/DelegateScreen.java

@@ -0,0 +1,243 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.gui;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.components.AbstractWidget;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.Style;
+import net.minecraft.world.item.ItemStack;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.Nullable;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Optional;
+
+@ApiStatus.Internal
+@ApiStatus.Experimental
+public class DelegateScreen extends Screen {
+    protected Screen parent;
+    
+    public DelegateScreen(Screen parent) {
+        super(parent.getTitle());
+        this.parent = parent;
+    }
+    
+    @Override
+    public Component getTitle() {
+        return parent.getTitle();
+    }
+    
+    @Override
+    public String getNarrationMessage() {
+        return parent.getNarrationMessage();
+    }
+    
+    @Override
+    public boolean keyPressed(int i, int j, int k) {
+        return parent.keyPressed(i, j, k);
+    }
+    
+    @Override
+    public boolean shouldCloseOnEsc() {
+        return parent.shouldCloseOnEsc();
+    }
+    
+    @Override
+    public void onClose() {
+        parent.onClose();
+    }
+    
+    @Override
+    public <T extends AbstractWidget> T addButton(T abstractWidget) {
+        return parent.addButton(abstractWidget);
+    }
+    
+    @Override
+    public <T extends GuiEventListener> T addWidget(T guiEventListener) {
+        return parent.addWidget(guiEventListener);
+    }
+    
+    @Override
+    public List<Component> getTooltipFromItem(ItemStack itemStack) {
+        return parent.getTooltipFromItem(itemStack);
+    }
+    
+    @Override
+    public void insertText(String string, boolean bl) {
+        parent.insertText(string, bl);
+    }
+    
+    @Override
+    public boolean handleComponentClicked(@Nullable Style style) {
+        return parent.handleComponentClicked(style);
+    }
+    
+    @Override
+    public void sendMessage(String string) {
+        parent.sendMessage(string);
+    }
+    
+    @Override
+    public void sendMessage(String string, boolean bl) {
+        parent.sendMessage(string, bl);
+    }
+    
+    @Override
+    public List<? extends GuiEventListener> children() {
+        return parent.children();
+    }
+    
+    @Override
+    public void tick() {
+        parent.tick();
+    }
+    
+    @Override
+    public void removed() {
+        parent.removed();
+    }
+    
+    @Override
+    public boolean isPauseScreen() {
+        return parent.isPauseScreen();
+    }
+    
+    @Override
+    public boolean isValidCharacterForName(String string, char c, int i) {
+        return parent.isValidCharacterForName(string, c, i);
+    }
+    
+    @Override
+    public boolean isMouseOver(double d, double e) {
+        return parent.isMouseOver(d, e);
+    }
+    
+    @Override
+    public void onFilesDrop(List<Path> list) {
+        parent.onFilesDrop(list);
+    }
+    
+    @Nullable
+    @Override
+    public GuiEventListener getFocused() {
+        return parent.getFocused();
+    }
+    
+    @Override
+    public void setFocused(@Nullable GuiEventListener guiEventListener) {
+        parent.setFocused(guiEventListener);
+    }
+    
+    @Override
+    public int getBlitOffset() {
+        return parent.getBlitOffset();
+    }
+    
+    @Override
+    public void setBlitOffset(int i) {
+        parent.setBlitOffset(i);
+    }
+    
+    @Override
+    public boolean mouseClicked(double d, double e, int i) {
+        return parent.mouseClicked(d, e, i);
+    }
+    
+    @Override
+    public boolean mouseReleased(double d, double e, int i) {
+        return parent.mouseReleased(d, e, i);
+    }
+    
+    @Override
+    public boolean mouseDragged(double d, double e, int i, double f, double g) {
+        return parent.mouseDragged(d, e, i, f, g);
+    }
+    
+    @Override
+    public boolean mouseScrolled(double d, double e, double f) {
+        return parent.mouseScrolled(d, e, f);
+    }
+    
+    @Override
+    public boolean keyReleased(int i, int j, int k) {
+        return parent.keyReleased(i, j, k);
+    }
+    
+    @Override
+    public boolean charTyped(char c, int i) {
+        return parent.charTyped(c, i);
+    }
+    
+    @Override
+    public void setInitialFocus(@Nullable GuiEventListener guiEventListener) {
+        parent.setInitialFocus(guiEventListener);
+    }
+    
+    @Override
+    public void magicalSpecialHackyFocus(@Nullable GuiEventListener guiEventListener) {
+        parent.magicalSpecialHackyFocus(guiEventListener);
+    }
+    
+    @Override
+    public boolean changeFocus(boolean bl) {
+        return parent.changeFocus(bl);
+    }
+    
+    @Override
+    public void mouseMoved(double d, double e) {
+        parent.mouseMoved(d, e);
+    }
+    
+    @Override
+    public void resize(Minecraft minecraft, int i, int j) {
+        parent.resize(minecraft, i, j);
+    }
+    
+    @Override
+    public void init(Minecraft minecraft, int i, int j) {
+        parent.init(minecraft, i, j);
+    }
+    
+    @Override
+    public void init() {
+        parent.init();
+    }
+    
+    @Override
+    public Optional<GuiEventListener> getChildAt(double d, double e) {
+        return parent.getChildAt(d, e);
+    }
+    
+    @Override
+    public void render(PoseStack poseStack, int i, int j, float f) {
+        parent.render(poseStack, i, j, f);
+    }
+    
+    
+}

+ 73 - 0
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/TransformingScreen.java

@@ -0,0 +1,73 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.gui;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.api.ScissorsScreen;
+import me.shedaniel.math.Rectangle;
+import net.minecraft.client.gui.screens.Screen;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.function.DoubleSupplier;
+
+public class TransformingScreen extends DelegateScreen implements ScissorsScreen {
+    private final DoubleSupplier xTransformer;
+    private final DoubleSupplier yTransformer;
+    private final Screen lastScreen;
+    
+    public TransformingScreen(Screen parent, Screen lastScreen, Runnable init, DoubleSupplier xTransformer, DoubleSupplier yTransformer) {
+        super(parent);
+        this.lastScreen = lastScreen;
+        this.xTransformer = xTransformer;
+        this.yTransformer = yTransformer;
+        init.run();
+    }
+    
+    @Override
+    public void init() {
+        super.init();
+    }
+    
+    @Override
+    public void render(PoseStack poseStack, int i, int j, float f) {
+        if (lastScreen != null) {
+            RenderSystem.pushMatrix();
+            RenderSystem.translated(0, 0, -400);
+            lastScreen.render(poseStack, -1, -1, 0);
+            RenderSystem.popMatrix();
+        }
+        RenderSystem.pushMatrix();
+        RenderSystem.translated(xTransformer.getAsDouble(), yTransformer.getAsDouble(), 0);
+        super.render(poseStack, i, j, f);
+        RenderSystem.popMatrix();
+    }
+    
+    @Override
+    public @Nullable Rectangle handleScissor(@Nullable Rectangle rectangle) {
+        if (rectangle != null)
+            rectangle.translate((int) xTransformer.getAsDouble(), (int) yTransformer.getAsDouble());
+        return rectangle;
+    }
+}

+ 1 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringAddRuleScreen.java

@@ -54,7 +54,7 @@ public class FilteringAddRuleScreen extends Screen {
     }
     
     @Override
-    protected void init() {
+    public void init() {
         super.init();
         {
             Component backText = new TextComponent("↩ ").append(new TranslatableComponent("gui.back"));

+ 1 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRuleOptionsScreen.java

@@ -56,7 +56,7 @@ public abstract class FilteringRuleOptionsScreen<T extends FilteringRule<?>> ext
     }
     
     @Override
-    protected void init() {
+    public void init() {
         super.init();
         if (rulesList != null) save();
         {

+ 1 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringRulesScreen.java

@@ -58,7 +58,7 @@ public class FilteringRulesScreen extends Screen {
     }
     
     @Override
-    protected void init() {
+    public void init() {
         super.init();
         {
             Component backText = new TextComponent("↩ ").append(new TranslatableComponent("gui.back"));

+ 1 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/config/entry/FilteringScreen.java

@@ -172,7 +172,7 @@ public class FilteringScreen extends Screen {
     }
     
     @Override
-    protected void init() {
+    public void init() {
         super.init();
         Rectangle bounds = getBounds();
         updateSearch(this.searchField.getText());

+ 7 - 0
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java

@@ -141,6 +141,13 @@ public class EntryListWidget extends WidgetWithBounds {
     }
     
     private static Rectangle updateInnerBounds(Rectangle bounds) {
+        bounds = bounds.clone();
+        int widthReduction = (int) Math.round(bounds.width * (1 - ConfigObject.getInstance().getHorizontalEntriesBoundaries()));
+        int heightReduction = (int) Math.round(bounds.width * (1 - ConfigObject.getInstance().getVerticalEntriesBoundaries()));
+        bounds.x += widthReduction;
+        bounds.width -= widthReduction;
+        bounds.y += heightReduction / 2;
+        bounds.height -= heightReduction;
         int entrySize = entrySize();
         if (ConfigObject.getInstance().isEntryListWidgetScrolled()) {
             int width = Math.max(Mth.floor((bounds.width - 2 - 6) / (float) entrySize), 1);

+ 11 - 2
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java

@@ -190,8 +190,14 @@ public class FavoritesListWidget extends WidgetWithBounds {
     
     @Override
     public boolean mouseDragged(double mouseX, double mouseY, int int_1, double double_3, double double_4) {
-        if (lastTouchedEntry != null) {
-            lastTouchedEntry.dragged = true;
+        if (lastTouchedEntry != null && !lastTouchedEntry.dragged) {
+            Point startPoint = lastTouchedEntry.startedDraggingPosition;
+            double xDistance = Math.abs(startPoint.x - mouseX);
+            double yDistance = Math.abs(startPoint.y - mouseY);
+            double requiredDistance = entrySize() * .4;
+            if (xDistance * xDistance + yDistance * yDistance > requiredDistance * requiredDistance) {
+                lastTouchedEntry.dragged = true;
+            }
         }
         if (scrolling.mouseDragged(mouseX, mouseY, int_1, double_3, double_4, ConfigObject.getInstance().doesSnapToRows(), entrySize()))
             return true;
@@ -381,6 +387,7 @@ public class FavoritesListWidget extends WidgetWithBounds {
             Entry entry = lastTouchedEntry;
             double x = entry.x.doubleValue();
             double y = entry.y.doubleValue();
+            entry.startedDraggingPosition = null;
             
             boolean contains = currentBounds.contains(PointHelper.ofMouse());
             if (contains || !entry.madeUp) {
@@ -441,6 +448,7 @@ public class FavoritesListWidget extends WidgetWithBounds {
             for (Entry entry : entries.values()) {
                 if (entry.getWidget().containsMouse(mouseX, mouseY)) {
                     lastTouchedEntry = entry;
+                    lastTouchedEntry.startedDraggingPosition = new Point(mouseX, mouseY);
                     break;
                 }
             }
@@ -492,6 +500,7 @@ public class FavoritesListWidget extends WidgetWithBounds {
         private FavoriteEntry entry;
         private final EntryListEntry widget;
         private boolean hidden;
+        private Point startedDraggingPosition;
         private boolean dragged;
         private boolean madeUp;
         private Animator x = new Animator();

+ 13 - 4
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java

@@ -46,6 +46,7 @@ import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
 import me.shedaniel.clothconfig2.api.Modifier;
 import me.shedaniel.clothconfig2.api.ModifierKeyCode;
 import me.shedaniel.clothconfig2.gui.entries.KeyCodeEntry;
+import me.shedaniel.clothconfig2.impl.EasingMethod;
 import me.shedaniel.rei.RoughlyEnoughItemsCore;
 import me.shedaniel.rei.api.ConfigManager;
 import me.shedaniel.rei.api.EntryRegistry;
@@ -53,6 +54,7 @@ import me.shedaniel.rei.api.EntryStack;
 import me.shedaniel.rei.api.REIHelper;
 import me.shedaniel.rei.api.favorites.FavoriteEntry;
 import me.shedaniel.rei.gui.ContainerScreenOverlay;
+import me.shedaniel.rei.gui.TransformingScreen;
 import me.shedaniel.rei.gui.WarningAndErrorScreen;
 import me.shedaniel.rei.gui.config.RecipeScreenType;
 import me.shedaniel.rei.gui.config.entry.FilteringEntry;
@@ -65,6 +67,7 @@ import me.shedaniel.rei.impl.filtering.rules.ManualFilteringRule;
 import net.fabricmc.api.EnvType;
 import net.fabricmc.api.Environment;
 import net.fabricmc.loader.api.FabricLoader;
+import net.minecraft.Util;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.Font;
 import net.minecraft.client.gui.components.Button;
@@ -79,6 +82,7 @@ import net.minecraft.network.chat.TextComponent;
 import net.minecraft.network.chat.TranslatableComponent;
 import net.minecraft.util.Mth;
 import net.minecraft.util.Tuple;
+import org.apache.commons.lang3.mutable.MutableLong;
 import org.jetbrains.annotations.ApiStatus;
 
 import java.lang.reflect.Method;
@@ -158,7 +162,7 @@ public class ConfigManagerImpl implements ConfigManager {
             ConfigObjectImpl.UsePercentage bounds = field.getAnnotation(ConfigObjectImpl.UsePercentage.class);
             return Collections.singletonList(ConfigEntryBuilder.create().startIntSlider(new TranslatableComponent(i13n), Mth.ceil(Utils.getUnsafely(field, config, 0.0) * 100), Mth.ceil(bounds.min() * 100), Mth.ceil(bounds.max() * 100)).setDefaultValue(() -> Mth.ceil((double) Utils.getUnsafely(field, defaults) * 100)).setSaveConsumer((newValue) -> {
                 Utils.setUnsafely(field, config, newValue / 100d);
-            }).setTextGetter(integer -> new TextComponent(String.format("Size: %d%%", integer))).build());
+            }).setTextGetter(integer -> new TextComponent(bounds.prefix() + String.format("%d%%", integer))).build());
         }, (field) -> field.getType() == Double.TYPE || field.getType() == Double.class, ConfigObjectImpl.UsePercentage.class);
         
         guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) ->
@@ -223,7 +227,7 @@ public class ConfigManagerImpl implements ConfigManager {
             provider.setCategoryFunction((baseI13n, categoryName) -> String.format("%s.%s", baseI13n, categoryName));
             provider.setBuildFunction(builder -> {
                 builder.setGlobalized(true);
-                builder.setGlobalizedExpanded(true);
+                builder.setGlobalizedExpanded(false);
                 if (Minecraft.getInstance().getConnection() != null && Minecraft.getInstance().getConnection().getRecipeManager() != null) {
                     builder.getOrCreateCategory(new TranslatableComponent("config.roughlyenoughitems.advanced")).getEntries().add(0, new ReloadPluginsEntry(220));
                 }
@@ -238,7 +242,12 @@ public class ConfigManagerImpl implements ConfigManager {
                         ContainerScreenOverlay.getEntryListWidget().updateSearch(ScreenHelper.getSearchField().getText(), true);
                 }).build();
             });
-            return provider.get();
+            MutableLong current = new MutableLong();
+            return new TransformingScreen(provider.get(),
+                    parent,
+                    () -> current.setValue(Util.getMillis() + (getConfig().isReducedMotion() ? -3000 : 0)),
+                    () -> 0, () -> (1 - EasingMethod.EasingMethodImpl.EXPO.apply(Mth.clamp((Util.getMillis() - current.getValue()) / 750.0, 0, 1)))
+                                   * Minecraft.getInstance().getWindow().getGuiScaledHeight() * 1.3);
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -266,7 +275,7 @@ public class ConfigManagerImpl implements ConfigManager {
         }
         
         @Override
-        protected void init() {
+        public void init() {
             super.init();
             this.addButton(new Button(this.width / 2 - 100, 140, 200, 20, CommonComponents.GUI_CANCEL, button -> this.minecraft.setScreen(parent)));
         }

+ 18 - 0
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigObjectImpl.java

@@ -37,6 +37,7 @@ import me.shedaniel.rei.gui.config.*;
 import me.shedaniel.rei.impl.filtering.FilteringRule;
 import net.fabricmc.api.EnvType;
 import net.fabricmc.api.Environment;
+import net.minecraft.util.Mth;
 import org.jetbrains.annotations.ApiStatus;
 
 import java.lang.annotation.ElementType;
@@ -343,6 +344,18 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
         return advanced.accessibility.resizeDynamically;
     }
     
+    @ApiStatus.Experimental
+    @Override
+    public double getHorizontalEntriesBoundaries() {
+        return Mth.clamp(appearance.horizontalEntriesBoundaries, 0.1,1);
+    }
+    
+    @ApiStatus.Experimental
+    @Override
+    public double getVerticalEntriesBoundaries() {
+        return Mth.clamp(appearance.verticalEntriesBoundaries, 0.1,1);
+    }
+    
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.FIELD})
     @interface DontApplyFieldName {}
@@ -361,6 +374,8 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
         double min();
         
         double max();
+        
+        String prefix() default "Size: ";
     }
     
     public static class Basics {
@@ -405,6 +420,9 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
             @Comment("Declares whether the craftable filter button is enabled.") private boolean enableCraftableOnlyButton = false;
             @Comment("Declares whether the utils buttons are shown.") private boolean showUtilsButtons = false;
         }
+    
+        @UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") private double horizontalEntriesBoundaries = 1.0;
+        @UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") private double verticalEntriesBoundaries = 1.0;
     }
     
     public static class Functionality {

+ 1 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/RecipeHelperImpl.java

@@ -130,7 +130,7 @@ public class RecipeHelperImpl implements RecipeHelper {
     
     @Override
     public List<List<EntryStack>> getWorkingStations(ResourceLocation category) {
-        return categoryWorkingStations.get(category);
+        return categoryWorkingStations.getOrDefault(category, Collections.emptyList());
     }
     
     @Override

+ 2 - 5
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ScreenHelper.java

@@ -172,6 +172,7 @@ public class ScreenHelper implements ClientModInitializer, REIHelper {
      */
     @Deprecated
     @ApiStatus.ScheduledForRemoval
+    @Nullable
     public static AbstractContainerScreen<?> getLastHandledScreen() {
         return previousContainerScreen;
     }
@@ -280,11 +281,7 @@ public class ScreenHelper implements ClientModInitializer, REIHelper {
                 previousContainerScreen = (AbstractContainerScreen<?>) screen;
             return InteractionResult.PASS;
         });
-        boolean loaded = FabricLoader.getInstance().isModLoaded("fabric-events-lifecycle-v0");
-        if (!loaded) {
-            RoughlyEnoughItemsState.error("Fabric API is not installed!", "https://www.curseforge.com/minecraft/mc-mods/fabric-api/files/all");
-            return;
-        }
+        RoughlyEnoughItemsState.checkRequiredFabricModules();
         Executor.run(() -> () -> {
             ClientTickEvents.END_CLIENT_TICK.register(minecraft -> {
                 if (isOverlayVisible() && getSearchField() != null)

+ 2 - 0
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/plugin/autocrafting/DefaultCategoryHandler.java

@@ -61,6 +61,8 @@ public class DefaultCategoryHandler implements AutoTransferHandler {
             return Result.createNotApplicable();
         TransferRecipeDisplay recipe = (TransferRecipeDisplay) context.getRecipe();
         AbstractContainerScreen<?> containerScreen = context.getContainerScreen();
+        if (containerScreen == null)
+            return Result.createNotApplicable();
         AbstractContainerMenu container = context.getContainer();
         ContainerInfo<AbstractContainerMenu> containerInfo = (ContainerInfo<AbstractContainerMenu>) ContainerInfoHandler.getContainerInfo(recipe.getRecipeCategory(), container.getClass());
         if (containerInfo == null)

+ 6 - 1
RoughlyEnoughItems-runtime/src/main/resources/roughlyenoughitems-runtime.accessWidener

@@ -14,4 +14,9 @@ accessible field net/minecraft/world/item/CreativeModeTab langId Ljava/lang/Stri
 accessible field net/minecraft/world/entity/player/Inventory compartments Ljava/util/List;
 accessible class net/minecraft/client/gui/Font$StringRenderOutput
 accessible field net/minecraft/client/gui/Font SHADOW_OFFSET Lcom/mojang/math/Vector3f;
-accessible field net/minecraft/client/StringSplitter widthProvider Lnet/minecraft/client/StringSplitter$WidthProvider;
+accessible field net/minecraft/client/StringSplitter widthProvider Lnet/minecraft/client/StringSplitter$WidthProvider;
+accessible method net/minecraft/client/gui/screens/Screen isValidCharacterForName (Ljava/lang/String;CI)Z
+accessible method net/minecraft/client/gui/screens/Screen insertText (Ljava/lang/String;Z)V
+accessible method net/minecraft/client/gui/screens/Screen addWidget (Lnet/minecraft/client/gui/components/events/GuiEventListener;)Lnet/minecraft/client/gui/components/events/GuiEventListener;
+accessible method net/minecraft/client/gui/screens/Screen addButton (Lnet/minecraft/client/gui/components/AbstractWidget;)Lnet/minecraft/client/gui/components/AbstractWidget;
+accessible method net/minecraft/client/gui/screens/Screen init ()V

+ 6 - 3
build.gradle

@@ -79,9 +79,11 @@ allprojects {
         minecraft("com.mojang:minecraft:${project.minecraft_version}")
         mappings(new MojangMappingsDependency(project, loom))
         modApi("net.fabricmc:fabric-loader:${project.fabricloader_version}")
-        modApi("net.fabricmc.fabric-api:fabric-api:${project.fabric_api}") {
-            exclude(module: "fabric-biomes-v1")
-        }
+        modApi(fabricApi.module("fabric-api-base", project.fabric_api))
+        modApi(fabricApi.module("fabric-resource-loader-v0", project.fabric_api))
+        modApi(fabricApi.module("fabric-networking-v0", project.fabric_api))
+        modApi(fabricApi.module("fabric-lifecycle-events-v1", project.fabric_api))
+        modApi(fabricApi.module("fabric-rendering-fluids-v1", project.fabric_api))
         modApi("me.shedaniel.cloth.api:cloth-client-events-v0:${cloth_client_events_v0_version}") {
             transitive(false)
         }
@@ -285,6 +287,7 @@ curseforge {
             addGameVersion "1.16-Snapshot"
             addGameVersion "1.16.2"
             addGameVersion "1.16.3"
+            addGameVersion "1.16.4"
             addGameVersion "Java 8"
             addGameVersion "Fabric"
             relations {

+ 6 - 6
gradle.properties

@@ -1,13 +1,13 @@
 org.gradle.jvmargs=-Xmx3G
-mod_version=5.7.1
-supported_version=1.16.2/3
-minecraft_version=1.16.3
-fabricloader_version=0.9.1+build.205
+mod_version=5.8.0
+supported_version=1.16.2/3/4
+minecraft_version=1.16.4
+fabricloader_version=0.10.6+build.214
 cloth_client_events_v0_version=1.4.5
-cloth_config_version=4.8.1
+cloth_config_version=4.8.3
 modmenu_version=1.14.6+build.31
 fabric_api=0.17.0+build.393-1.16
-autoconfig1u=3.2.0-unstable
+autoconfig1u=3.3.1
 api_include=me.shedaniel.cloth.api:cloth-client-events-v0,me.shedaniel.cloth:config-2,me.sargunvohra.mcmods:autoconfig1u,net.fabricmc.fabric-api:fabric-api-base
 api_exculde=
 #api_include=me.shedaniel.cloth:cloth-events,me.shedaniel.cloth:config-2,me.sargunvohra.mcmods:autoconfig1u,org.jetbrains:annotations,net.fabricmc.fabric-api:fabric-

+ 2 - 0
src/main/resources/assets/roughlyenoughitems/lang/en_us.json

@@ -208,6 +208,8 @@
   "config.roughlyenoughitems.scrollingEntryListWidget": "Entry List Action:",
   "config.roughlyenoughitems.scrollingEntryListWidget.boolean.true": "Scrolled",
   "config.roughlyenoughitems.scrollingEntryListWidget.boolean.false": "Paginated",
+  "config.roughlyenoughitems.horizontalEntriesBoundaries": "Horizontal Entries Boundaries:",
+  "config.roughlyenoughitems.verticalEntriesBoundaries": "Vertical Entries Boundaries:",
   "config.roughlyenoughitems.filteringScreen": "Customized Filtering",
   "config.roughlyenoughitems.filteringRulesScreen": "Customized Filtering Rules",
   "config.roughlyenoughitems.filteringRulesScreen.new": "Create Filtering Rule",