From 6d092d7599d27748abd8dc50b0c87e7fdba689cd Mon Sep 17 00:00:00 2001 From: shedaniel Date: Thu, 28 Apr 2022 14:03:31 +0800 Subject: REI 8.2 - Display History - Draggable Component - Multi Select Filtering Screen - Better Craftable Filter - Fix #850 - Fix #845 - Fix #832 - Fix #731 - Fix #839 - Fix #804 - Fix EvilCraft --- .../client/gui/drag/DraggableBoundsProvider.java | 70 ++++ .../rei/api/client/gui/drag/DraggableStack.java | 49 ++- .../client/gui/drag/DraggableStackProvider.java | 15 +- .../gui/drag/DraggableStackProviderWidget.java | 11 +- .../api/client/gui/drag/DraggableStackVisitor.java | 49 ++- .../gui/drag/DraggableStackVisitorWidget.java | 20 +- .../rei/api/client/gui/drag/DraggingContext.java | 69 +++- .../gui/drag/component/DraggableComponent.java | 83 +++++ .../drag/component/DraggableComponentProvider.java | 84 +++++ .../DraggableComponentProviderWidget.java | 74 +++++ .../drag/component/DraggableComponentVisitor.java | 115 +++++++ .../component/DraggableComponentVisitorWidget.java | 110 +++++++ .../gui/widgets/DelegateWidgetWithBounds.java | 15 + .../rei/api/client/gui/widgets/Widgets.java | 3 +- .../client/registry/category/CategoryRegistry.java | 2 + .../api/client/registry/screen/ScreenRegistry.java | 32 ++ .../rei/api/common/util/CollectionUtils.java | 9 + .../rei/plugin/client/DefaultClientPlugin.java | 15 +- .../categories/DefaultCompostingCategory.java | 13 +- forge/build.gradle | 8 +- gradle.properties | 4 +- .../rei/impl/client/config/ConfigObjectImpl.java | 6 +- .../client/config/entries/FilteringScreen.java | 95 +++--- .../rei/impl/client/gui/RecipeDisplayExporter.java | 23 +- .../rei/impl/client/gui/ScreenOverlayImpl.java | 14 +- .../client/gui/dragging/CurrentDraggingStack.java | 99 ++++-- .../gui/screen/AbstractDisplayViewingScreen.java | 7 +- .../gui/screen/DefaultDisplayViewingScreen.java | 87 +++-- .../client/gui/widget/AutoCraftingEvaluator.java | 7 + .../client/gui/widget/DisplayCompositeWidget.java | 170 ++++++++++ .../rei/impl/client/gui/widget/EntryWidget.java | 10 +- .../impl/client/gui/widget/InternalWidgets.java | 61 ++-- .../rei/impl/client/gui/widget/MergedWidget.java | 45 +++ .../client/gui/widget/basewidgets/ArrowWidget.java | 4 +- .../gui/widget/basewidgets/BurningFireWidget.java | 4 +- .../client/gui/widget/basewidgets/PanelWidget.java | 4 +- .../gui/widget/entrylist/EntryListWidget.java | 22 +- .../gui/widget/favorites/FavoritesListWidget.java | 66 +++- .../gui/widget/favorites/history/DisplayEntry.java | 152 +++++++++ .../favorites/history/DisplayHistoryWidget.java | 365 +++++++++++++++++++++ .../panel/FadingFavoritesPanelButton.java | 2 +- .../gui/widget/favorites/panel/FavoritesPanel.java | 2 +- .../panel/rows/FavoritesPanelEntriesRow.java | 2 +- .../gui/widget/favorites/trash/TrashWidget.java | 41 ++- .../gui/widget/region/EntryStacksRegionWidget.java | 7 +- .../client/gui/widget/region/RegionListener.java | 5 + .../gui/widget/region/RegionRenderingDebugger.java | 3 + .../registry/category/CategoryRegistryImpl.java | 7 +- .../client/registry/screen/ScreenRegistryImpl.java | 58 +++- .../shedaniel/rei/impl/client/view/ViewsImpl.java | 11 + .../impl/common/entry/type/EntryRegistryImpl.java | 5 +- .../rei/impl/common/util/RectangleUtils.java | 52 +++ .../plugin/client/entry/ItemEntryDefinition.java | 17 +- .../client/runtime/DefaultClientRuntimePlugin.java | 12 +- .../assets/roughlyenoughitems/lang/cs_cz.json | 2 +- .../assets/roughlyenoughitems/lang/de_de.json | 2 +- .../assets/roughlyenoughitems/lang/en_ud.json | 2 +- .../assets/roughlyenoughitems/lang/en_us.json | 6 +- .../assets/roughlyenoughitems/lang/es_es.json | 2 +- .../assets/roughlyenoughitems/lang/et_ee.json | 2 +- .../assets/roughlyenoughitems/lang/fr_fr.json | 2 +- .../assets/roughlyenoughitems/lang/it_it.json | 2 +- .../assets/roughlyenoughitems/lang/ja_jp.json | 2 +- .../assets/roughlyenoughitems/lang/ko_kr.json | 2 +- .../assets/roughlyenoughitems/lang/lol_us.json | 2 +- .../assets/roughlyenoughitems/lang/pl_pl.json | 2 +- .../assets/roughlyenoughitems/lang/pt_br.json | 2 +- .../assets/roughlyenoughitems/lang/pt_pt.json | 2 +- .../assets/roughlyenoughitems/lang/ru_ru.json | 2 +- .../assets/roughlyenoughitems/lang/tr_tr.json | 2 +- .../assets/roughlyenoughitems/lang/uk_ua.json | 2 +- .../assets/roughlyenoughitems/lang/zh_cn.json | 2 +- .../assets/roughlyenoughitems/lang/zh_tw.json | 2 +- 73 files changed, 2066 insertions(+), 291 deletions(-) create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableBoundsProvider.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponent.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProvider.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProviderWidget.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentVisitor.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentVisitorWidget.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayCompositeWidget.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/history/DisplayEntry.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/history/DisplayHistoryWidget.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/impl/common/util/RectangleUtils.java diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableBoundsProvider.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableBoundsProvider.java new file mode 100644 index 000000000..c6d1a35cf --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableBoundsProvider.java @@ -0,0 +1,70 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag; + +import me.shedaniel.math.Rectangle; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import java.util.stream.StreamSupport; + +@FunctionalInterface +public interface DraggableBoundsProvider { + static VoxelShape fromRectangle(Rectangle bounds) { + return Shapes.box(bounds.x, bounds.y, 0, bounds.getMaxX(), bounds.getMaxY(), 0.1); + } + + static DraggableBoundsProvider ofRectangle(Rectangle bounds) { + return ofShape(fromRectangle(bounds)); + } + + static DraggableBoundsProvider ofRectangles(Iterable bounds) { + VoxelShape shape = StreamSupport.stream(bounds.spliterator(), false) + .map(DraggableBoundsProvider::fromRectangle) + .reduce(Shapes.empty(), Shapes::or); + return ofShape(shape); + } + + static DraggableBoundsProvider ofShape(VoxelShape shape) { + return () -> shape; + } + + static DraggableBoundsProvider ofShapes(Iterable shapes) { + VoxelShape shape = StreamSupport.stream(shapes.spliterator(), false) + .reduce(Shapes.empty(), Shapes::or); + return ofShape(shape); + } + + static DraggableBoundsProvider empty() { + return Shapes::empty; + } + + static DraggableBoundsProvider concat(Iterable providers) { + return () -> StreamSupport.stream(providers.spliterator(), false) + .map(DraggableBoundsProvider::bounds) + .reduce(Shapes.empty(), Shapes::or); + } + + VoxelShape bounds(); +} diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java index dc3311055..713347743 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java @@ -24,17 +24,64 @@ package me.shedaniel.rei.api.client.gui.drag; import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; import me.shedaniel.rei.api.common.entry.EntryStack; -public interface DraggableStack { +public interface DraggableStack extends DraggableComponent> { + static DraggableStack from(DraggableComponent> component) { + return component instanceof DraggableStack ? (DraggableStack) component : new DraggableStack() { + @Override + public EntryStack getStack() { + return component.get(); + } + + @Override + public void drag() { + component.drag(); + } + + @Override + public void release(DraggedAcceptorResult result) { + component.release(result); + } + + @Override + public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + component.render(matrices, bounds, mouseX, mouseY, delta); + } + + @Override + public void render(PoseStack matrices, Point position, int mouseX, int mouseY, float delta) { + component.render(matrices, position, mouseX, mouseY, delta); + } + }; + } + EntryStack getStack(); + @Override + default EntryStack get() { + return getStack(); + } + void drag(); + @Override + default int getWidth() { + return 18; + } + + @Override + default int getHeight() { + return 18; + } + default void release(DraggedAcceptorResult result) { } + @Override default void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { getStack().render(matrices, bounds, mouseX, mouseY, delta); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProvider.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProvider.java index 57569b405..e11805d0a 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProvider.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProvider.java @@ -23,6 +23,9 @@ package me.shedaniel.rei.api.client.gui.drag; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProvider; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; @@ -31,7 +34,7 @@ import java.util.function.Supplier; /** * A provider for supplying {@link DraggableStack} to the screen. */ -public interface DraggableStackProvider extends Comparable> { +public interface DraggableStackProvider extends DraggableComponentProvider> { static DraggableStackProvider from(Supplier>> providers) { return new DraggableStackProvider() { @Override @@ -61,8 +64,16 @@ public interface DraggableStackProvider extends Comparable context, double mouseX, double mouseY); + @Override + @Nullable + default DraggableComponent> getHovered(DraggingContext context, double mouseX, double mouseY) { + return getHoveredStack(context, mouseX, mouseY); + } + + @Override boolean isHandingScreen(R screen); + @Override default DraggingContext getContext() { return DraggingContext.getInstance().cast(); } @@ -72,11 +83,11 @@ public interface DraggableStackProvider extends Comparable o) { return Double.compare(getPriority(), o.getPriority()); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProviderWidget.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProviderWidget.java index 29d375118..d0ae7227c 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProviderWidget.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProviderWidget.java @@ -23,6 +23,9 @@ package me.shedaniel.rei.api.client.gui.drag; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProviderWidget; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; @@ -33,7 +36,7 @@ import java.util.function.Function; * {@link DraggableStack}. */ @FunctionalInterface -public interface DraggableStackProviderWidget { +public interface DraggableStackProviderWidget extends DraggableComponentProviderWidget> { static DraggableStackProviderWidget from(Function, Iterable> providers) { return (context, mouseX, mouseY) -> { for (DraggableStackProviderWidget provider : providers.apply(context)) { @@ -47,6 +50,12 @@ public interface DraggableStackProviderWidget { @Nullable DraggableStack getHoveredStack(DraggingContext context, double mouseX, double mouseY); + @Override + @Nullable + default DraggableComponent> getHovered(DraggingContext context, double mouseX, double mouseY) { + return getHoveredStack(context, mouseX, mouseY); + } + static DraggableStackProvider toProvider(DraggableStackProviderWidget widget) { return toProvider(widget, 0D); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java index 8b8f9c220..dfbf5d69b 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java @@ -24,11 +24,16 @@ package me.shedaniel.rei.api.client.gui.drag; import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitor; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.minecraft.client.gui.screens.Screen; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; +import java.util.List; import java.util.Objects; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -36,7 +41,7 @@ import java.util.stream.StreamSupport; /** * A visitor for accepting {@link DraggableStack} to the screen. */ -public interface DraggableStackVisitor extends Comparable> { +public interface DraggableStackVisitor extends DraggableComponentVisitor { static DraggableStackVisitor from(Supplier>> visitors) { return new DraggableStackVisitor() { @Override @@ -81,6 +86,13 @@ public interface DraggableStackVisitor extends Comparable context, DraggableComponent component) { + return component.>getIf() + .map(comp -> acceptDraggedStack(context, DraggableStack.from(comp))) + .orElse(DraggedAcceptorResult.PASS); + } + /** * Returns the accepting bounds for the dragging stack, this should only be called once on drag. * The bounds are used to overlay to indicate to the users that the area is accepting entries. @@ -93,8 +105,18 @@ public interface DraggableStackVisitor extends Comparable getDraggableAcceptingBounds(DraggingContext context, DraggableComponent component) { + return component.>getIf() + .map(comp -> getDraggableAcceptingBounds(context, DraggableStack.from(comp))) + .orElse(Stream.empty()) + .map(Function.identity()); + } + + @Override boolean isHandingScreen(R screen); + @Override default DraggingContext getContext() { return DraggingContext.getInstance().cast(); } @@ -104,11 +126,11 @@ public interface DraggableStackVisitor extends Comparable o) { return Double.compare(getPriority(), o.getPriority()); } @@ -119,30 +141,25 @@ public interface DraggableStackVisitor extends Comparable bounds) { - VoxelShape shape = StreamSupport.stream(bounds.spliterator(), false) - .map(BoundsProvider::fromRectangle) - .reduce(Shapes.empty(), Shapes::or); - return ofShape(shape); + return DraggableBoundsProvider.ofRectangles(bounds)::bounds; } static BoundsProvider ofShape(VoxelShape shape) { - return () -> shape; + return DraggableBoundsProvider.ofShape(shape)::bounds; } static BoundsProvider ofShapes(Iterable shapes) { - VoxelShape shape = StreamSupport.stream(shapes.spliterator(), false) - .reduce(Shapes.empty(), Shapes::or); - return ofShape(shape); + return DraggableBoundsProvider.ofShapes(shapes)::bounds; } static BoundsProvider empty() { @@ -150,11 +167,11 @@ public interface DraggableStackVisitor extends Comparable providers) { - return () -> StreamSupport.stream(providers.spliterator(), false) - .map(BoundsProvider::bounds) - .reduce(Shapes.empty(), Shapes::or); + return DraggableBoundsProvider.concat((List) + (List) providers)::bounds; } + @Override VoxelShape bounds(); } } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java index 9181b82d2..34d49f53a 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java @@ -23,6 +23,9 @@ package me.shedaniel.rei.api.client.gui.drag; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitorWidget; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.minecraft.client.gui.screens.Screen; import java.util.function.Function; @@ -33,7 +36,7 @@ import java.util.stream.StreamSupport; * An interface to be implemented on {@link me.shedaniel.rei.api.client.gui.widgets.Widget} to accept * incoming {@link DraggableStack}. */ -public interface DraggableStackVisitorWidget { +public interface DraggableStackVisitorWidget extends DraggableComponentVisitorWidget { static DraggableStackVisitorWidget from(Function, Iterable> providers) { return new DraggableStackVisitorWidget() { @Override @@ -65,6 +68,13 @@ public interface DraggableStackVisitorWidget { return DraggedAcceptorResult.PASS; } + @Override + default DraggedAcceptorResult acceptDragged(DraggingContext context, DraggableComponent component) { + return component.>getIf() + .map(comp -> acceptDraggedStack(context, DraggableStack.from(comp))) + .orElse(DraggedAcceptorResult.PASS); + } + /** * Returns the accepting bounds for the dragging stack, this should only be called once on drag. * The bounds are used to overlay to indicate to the users that the widget is accepting entries. @@ -77,6 +87,14 @@ public interface DraggableStackVisitorWidget { return Stream.empty(); } + @Override + default Stream getDraggableAcceptingBounds(DraggingContext context, DraggableComponent component) { + return component.>getIf() + .map(comp -> getDraggableAcceptingBounds(context, DraggableStack.from(comp))) + .orElse(Stream.empty()) + .map(Function.identity()); + } + static DraggableStackVisitor toVisitor(DraggableStackVisitorWidget widget) { return toVisitor(widget, 0.0); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java index 30e6549c3..ea96128c7 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java @@ -23,9 +23,12 @@ package me.shedaniel.rei.api.client.gui.drag; +import com.google.common.base.MoreObjects; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; +import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.api.client.REIRuntime; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; @@ -54,6 +57,15 @@ public interface DraggingContext { return getCurrentStack() != null; } + /** + * Returns whether a draggable component is present. + * + * @return whether a draggable component is present + */ + default boolean isDraggingComponent() { + return getDragged() != null; + } + S getScreen(); /** @@ -64,6 +76,14 @@ public interface DraggingContext { @Nullable DraggableStack getCurrentStack(); + /** + * Returns the current dragged component, may be null. + * + * @return the current dragged component, may be null + */ + @Nullable + DraggableComponent getDragged(); + /** * Returns the current position of the dragged stack, this is usually the position of the mouse pointer, * but you should use this regardless to account for future changes. @@ -73,6 +93,15 @@ public interface DraggingContext { @Nullable Point getCurrentPosition(); + /** + * Returns the current bounds of the dragged stack, this is usually on the mouse pointer, + * but you should use this regardless to account for future changes. + * + * @return the current bounds of the dragged stack + */ + @Nullable + Rectangle getCurrentBounds(); + /** * Renders the draggable stack back to the position {@code position}. * This may be used to animate an unaccepted draggable stack returning to its initial position. @@ -81,7 +110,9 @@ public interface DraggingContext { * @param initialPosition the initial position of the stack * @param position the position supplier of the destination */ - void renderBackToPosition(DraggableStack stack, Point initialPosition, Supplier position); + default void renderBackToPosition(DraggableStack stack, Point initialPosition, Supplier position) { + renderBack(stack, initialPosition, position); + } /** * Renders the draggable stack back to the bounds {@code bounds}. @@ -91,12 +122,40 @@ public interface DraggingContext { * @param initialPosition the initial bounds of the stack * @param bounds the boundary supplier of the destination */ - void renderBackToPosition(DraggableStack stack, Rectangle initialPosition, Supplier bounds); + default void renderBackToPosition(DraggableStack stack, Rectangle initialPosition, Supplier bounds) { + renderBack(stack, initialPosition, bounds); + } default void renderToVoid(DraggableStack stack) { - Point currentPosition = getCurrentPosition(); - Rectangle targetBounds = new Rectangle(currentPosition.x, currentPosition.y, 1, 1); - renderBackToPosition(stack, new Rectangle(currentPosition.x - 8, currentPosition.y - 8, 16, 16), () -> targetBounds); + this.renderToVoid((DraggableComponent) stack); + } + + /** + * Renders the draggable component back to the position {@code position}. + * This may be used to animate an unaccepted draggable component returning to its initial position. + * + * @param component the component to use for render + * @param initialPosition the initial position of the component + * @param position the position supplier of the destination + */ + void renderBack(DraggableComponent component, Point initialPosition, Supplier position); + + /** + * Renders the draggable component back to the bounds {@code bounds}. + * This may be used to animate an unaccepted draggable component returning to its initial position. + * + * @param component the component to use for render + * @param initialPosition the initial bounds of the component + * @param bounds the boundary supplier of the destination + */ + void renderBack(DraggableComponent component, Rectangle initialPosition, Supplier bounds); + + default void renderToVoid(DraggableComponent component) { + Rectangle currentBounds = MoreObjects.firstNonNull(getCurrentBounds(), component.getOriginBounds(PointHelper.ofMouse())); + Rectangle targetBounds = new Rectangle(currentBounds.getCenterX(), currentBounds.getCenterY(), 1, 1); + int width = component.getWidth(); + int height = component.getHeight(); + renderBack(component, currentBounds, () -> targetBounds); } default DraggingContext cast() { diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponent.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponent.java new file mode 100644 index 000000000..e1153a408 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponent.java @@ -0,0 +1,83 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag.component; + +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; + +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public interface DraggableComponent extends Supplier { + default Optional> getIf(A... typeHack) { + if (typeHack.length != 0) throw new IllegalStateException("array must be empty!"); + if (typeHack.getClass().getComponentType().isInstance(get())) { + return Optional.of((DraggableComponent) this); + } else { + return Optional.empty(); + } + } + + default boolean ifMatches(Consumer consumer, A... typeHack) { + Optional> optional = getIf(typeHack); + optional.ifPresent(comp -> consumer.accept(comp.get())); + return optional.isPresent(); + } + + default boolean ifMatches(Predicate consumer, A... typeHack) { + Optional> optional = getIf(typeHack); + return optional.map(comp -> consumer.test(comp.get())).orElse(false); + } + + int getWidth(); + + int getHeight(); + + /** + * Returns the bounds of the component. This is the bounds that the origin of the component is at. + * + * @param mouse the mouse position + * @return the bounds of the component + */ + default Rectangle getOriginBounds(Point mouse) { + return new Rectangle(mouse.x - getWidth() / 2, mouse.y - getHeight() / 2, getWidth(), getHeight()); + } + + default void drag() { + } + + default void release(DraggedAcceptorResult result) { + } + + default void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + } + + default void render(PoseStack matrices, Point position, int mouseX, int mouseY, float delta) { + render(matrices, new Rectangle(position.x - getWidth() / 2, position.y - getHeight() / 2, getWidth(), getHeight()), mouseX, mouseY, delta); + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProvider.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProvider.java new file mode 100644 index 000000000..b52728b53 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProvider.java @@ -0,0 +1,84 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag.component; + +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import net.minecraft.client.gui.screens.Screen; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +/** + * A provider for supplying {@link DraggableComponent} to the screen. + */ +public interface DraggableComponentProvider extends Comparable> { + static DraggableComponentProvider from(Supplier>> providers) { + return new DraggableComponentProvider() { + @Override + public boolean isHandingScreen(R screen) { + for (DraggableComponentProvider provider : providers.get()) { + if (provider.isHandingScreen(screen)) { + return true; + } + } + return false; + } + + @Override + @Nullable + public DraggableComponent getHovered(DraggingContext context, double mouseX, double mouseY) { + for (DraggableComponentProvider provider : providers.get()) { + if (provider.isHandingScreen(context.getScreen())) { + DraggableComponent component = provider.getHovered(context, mouseX, mouseY); + if (component != null) return component; + } + } + return null; + } + }; + } + + @Nullable + DraggableComponent getHovered(DraggingContext context, double mouseX, double mouseY); + + boolean isHandingScreen(R screen); + + default DraggingContext getContext() { + return DraggingContext.getInstance().cast(); + } + + /** + * Gets the priority of the handler, the higher the priority, the earlier this is called. + * + * @return the priority + */ + default double getPriority() { + return 0f; + } + + @Override + default int compareTo(DraggableComponentProvider o) { + return Double.compare(getPriority(), o.getPriority()); + } +} \ No newline at end of file diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProviderWidget.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProviderWidget.java new file mode 100644 index 000000000..98826e6d2 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProviderWidget.java @@ -0,0 +1,74 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag.component; + +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import net.minecraft.client.gui.screens.Screen; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; + +/** + * An interface to be implemented on {@link me.shedaniel.rei.api.client.gui.widgets.Widget} to provide + * {@link DraggableComponent}. + */ +@FunctionalInterface +public interface DraggableComponentProviderWidget { + static DraggableComponentProviderWidget from(Function, Iterable>> providers) { + return (context, mouseX, mouseY) -> { + for (DraggableComponentProviderWidget provider : providers.apply(context)) { + DraggableComponent component = provider.getHovered(context, mouseX, mouseY); + if (component != null) return component; + } + return null; + }; + } + + @Nullable + DraggableComponent getHovered(DraggingContext context, double mouseX, double mouseY); + + static DraggableComponentProvider toProvider(DraggableComponentProviderWidget widget) { + return toProvider(widget, 0D); + } + + static DraggableComponentProvider toProvider(DraggableComponentProviderWidget widget, double priority) { + return new DraggableComponentProvider() { + @Override + @Nullable + public DraggableComponent getHovered(DraggingContext context, double mouseX, double mouseY) { + return widget.getHovered(context, mouseX, mouseY); + } + + @Override + public boolean isHandingScreen(R screen) { + return true; + } + + @Override + public double getPriority() { + return priority; + } + }; + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentVisitor.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentVisitor.java new file mode 100644 index 000000000..d19214a4d --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentVisitor.java @@ -0,0 +1,115 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag.component; + +import me.shedaniel.rei.api.client.gui.drag.DraggableBoundsProvider; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import net.minecraft.client.gui.screens.Screen; + +import java.util.Objects; +import java.util.function.Supplier; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * A visitor for accepting {@link DraggableComponent} to the screen. + */ +public interface DraggableComponentVisitor extends Comparable> { + static DraggableComponentVisitor from(Supplier>> visitors) { + return new DraggableComponentVisitor() { + @Override + public boolean isHandingScreen(R screen) { + for (DraggableComponentVisitor visitor : visitors.get()) { + if (visitor.isHandingScreen(screen)) { + return true; + } + } + return false; + } + + @Override + public DraggedAcceptorResult acceptDragged(DraggingContext context, DraggableComponent component) { + for (DraggableComponentVisitor visitor : visitors.get()) { + if (visitor.isHandingScreen(context.getScreen())) { + DraggedAcceptorResult result = Objects.requireNonNull(visitor.acceptDragged(context, component)); + if (result != DraggedAcceptorResult.PASS) return result; + } + } + return DraggedAcceptorResult.PASS; + } + + @Override + public Stream getDraggableAcceptingBounds(DraggingContext context, DraggableComponent component) { + return StreamSupport.stream(visitors.get().spliterator(), false) + .filter(visitor -> visitor.isHandingScreen(context.getScreen())) + .flatMap(visitor -> visitor.getDraggableAcceptingBounds(context, component)); + } + }; + } + + /** + * Accepts a dragged component, implementations of this function should check if the {@code context} is within + * boundaries of the accepting boundaries. + * + * @param context the context of the current dragged component on the overlay + * @param component the component being dragged + * @return the result of the visitor + */ + default DraggedAcceptorResult acceptDragged(DraggingContext context, DraggableComponent component) { + return DraggedAcceptorResult.PASS; + } + + /** + * Returns the accepting bounds for the dragging component, this should only be called once on drag. + * The bounds are used to overlay to indicate to the users that the area is accepting entries. + * + * @param context the context of the current dragged component on the overlay + * @param component the component being dragged + * @return the accepting bounds for the dragging component in a stream + */ + default Stream getDraggableAcceptingBounds(DraggingContext context, DraggableComponent component) { + return Stream.empty(); + } + + boolean isHandingScreen(R screen); + + default DraggingContext getContext() { + return DraggingContext.getInstance().cast(); + } + + /** + * Gets the priority of the handler, the higher the priority, the earlier this is called. + * + * @return the priority + */ + default double getPriority() { + return 0.0; + } + + @Override + default int compareTo(DraggableComponentVisitor o) { + return Double.compare(getPriority(), o.getPriority()); + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentVisitorWidget.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentVisitorWidget.java new file mode 100644 index 000000000..10b02c1b0 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentVisitorWidget.java @@ -0,0 +1,110 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag.component; + +import me.shedaniel.rei.api.client.gui.drag.DraggableBoundsProvider; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import net.minecraft.client.gui.screens.Screen; + +import java.util.function.Function; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * An interface to be implemented on {@link me.shedaniel.rei.api.client.gui.widgets.Widget} to accept + * incoming {@link DraggableComponent}. + */ +public interface DraggableComponentVisitorWidget { + static DraggableComponentVisitorWidget from(Function, Iterable> providers) { + return new DraggableComponentVisitorWidget() { + @Override + public DraggedAcceptorResult acceptDragged(DraggingContext context, DraggableComponent component) { + return StreamSupport.stream(providers.apply(context).spliterator(), false) + .map(visitor -> visitor.acceptDragged(context, component)) + .filter(result -> result != DraggedAcceptorResult.PASS) + .findFirst() + .orElse(DraggedAcceptorResult.PASS); + } + + @Override + public Stream getDraggableAcceptingBounds(DraggingContext context, DraggableComponent component) { + return StreamSupport.stream(providers.apply(context).spliterator(), false) + .flatMap(visitor -> visitor.getDraggableAcceptingBounds(context, component)); + } + }; + } + + /** + * Accepts a dragged component, implementations of this function should check if the {@code context} is within + * boundaries of the widget. + * + * @param context the context of the current dragged component on the overlay + * @param component the component being dragged + * @return the result of the visitor + */ + default DraggedAcceptorResult acceptDragged(DraggingContext context, DraggableComponent component) { + return DraggedAcceptorResult.PASS; + } + + /** + * Returns the accepting bounds for the dragging component, this should only be called once on drag. + * The bounds are used to overlay to indicate to the users that the widget is accepting entries. + * + * @param context the context of the current dragged component on the overlay + * @param component the component being dragged + * @return the accepting bounds for the dragging component in a stream + */ + default Stream getDraggableAcceptingBounds(DraggingContext context, DraggableComponent component) { + return Stream.empty(); + } + + static DraggableComponentVisitor toVisitor(DraggableComponentVisitorWidget widget) { + return toVisitor(widget, 0.0); + } + + static DraggableComponentVisitor toVisitor(DraggableComponentVisitorWidget widget, double priority) { + return new DraggableComponentVisitor<>() { + @Override + public DraggedAcceptorResult acceptDragged(DraggingContext context, DraggableComponent component) { + return widget.acceptDragged(context, component); + } + + @Override + public boolean isHandingScreen(R screen) { + return true; + } + + @Override + public Stream getDraggableAcceptingBounds(DraggingContext context, DraggableComponent component) { + return widget.getDraggableAcceptingBounds(context, component); + } + + @Override + public double getPriority() { + return priority; + } + }; + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/DelegateWidgetWithBounds.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/DelegateWidgetWithBounds.java index cf2a9e025..593a62588 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/DelegateWidgetWithBounds.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/DelegateWidgetWithBounds.java @@ -23,6 +23,7 @@ package me.shedaniel.rei.api.client.gui.widgets; +import com.mojang.blaze3d.vertex.PoseStack; import me.shedaniel.math.Rectangle; import java.util.function.Supplier; @@ -39,4 +40,18 @@ public class DelegateWidgetWithBounds extends DelegateWidget { public Rectangle getBounds() { return bounds.get(); } + + @Override + public boolean containsMouse(double mouseX, double mouseY) { + return getBounds().contains(mouseX, mouseY); + } + + @Deprecated + @Override + public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + Rectangle clone = getBounds().clone(); + getBounds().setBounds(bounds); + render(matrices, mouseX, mouseY, delta); + getBounds().setBounds(clone); + } } \ No newline at end of file diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Widgets.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Widgets.java index 9dbeb363c..191d276d2 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Widgets.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Widgets.java @@ -306,6 +306,7 @@ public final class Widgets { public static Iterable walk(Iterable listeners, Predicate predicate) { return () -> new AbstractIterator() { Stack> stack; + Set visited = new HashSet<>(); { stack = new Stack<>(); @@ -323,7 +324,7 @@ public final class Widgets { GuiEventListener listener = peek.next(); if (!peek.hasNext()) stack.pop(); - if (predicate.test(listener)) { + if (predicate.test(listener) && visited.add((T) listener)) { return (T) listener; } if (listener instanceof ContainerEventHandler handler) { diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/category/CategoryRegistry.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/category/CategoryRegistry.java index 017282dca..7d7052756 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/registry/category/CategoryRegistry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/category/CategoryRegistry.java @@ -158,6 +158,7 @@ public interface CategoryRegistry extends Reloadable, Iterable< configure(category, config -> config.addWorkstations(stations)); } + @Deprecated(forRemoval = true) default void removePlusButton(CategoryIdentifier category) { configure(category, CategoryConfiguration::removePlusButton); } @@ -186,6 +187,7 @@ public interface CategoryRegistry extends Reloadable, Iterable< /** * Removes the plus button. */ + @Deprecated(forRemoval = true) default void removePlusButton() { setPlusButtonArea(bounds -> null); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/screen/ScreenRegistry.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/screen/ScreenRegistry.java index 7e8722928..e6423d4e3 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/registry/screen/ScreenRegistry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/screen/ScreenRegistry.java @@ -30,6 +30,10 @@ import me.shedaniel.rei.api.client.gui.drag.DraggableStackProvider; import me.shedaniel.rei.api.client.gui.drag.DraggableStackProviderWidget; import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitor; import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitorWidget; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProvider; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProviderWidget; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitor; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitorWidget; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.view.ViewSearchBuilder; import me.shedaniel.rei.api.common.category.CategoryIdentifier; @@ -113,10 +117,38 @@ public interface ScreenRegistry extends Reloadable { registerDraggableStackProvider(DraggableStackProviderWidget.toProvider(provider, priority)); } + void registerDraggableComponentVisitor(DraggableComponentVisitor visitor); + + void registerDraggableComponentProvider(DraggableComponentProvider provider); + + default void registerDraggableComponentVisitor(DraggableComponentVisitorWidget visitor) { + registerDraggableComponentVisitor(DraggableComponentVisitorWidget.toVisitor(visitor)); + } + + default void registerDraggableComponentProvider(DraggableComponentProviderWidget provider) { + registerDraggableComponentProvider(DraggableComponentProviderWidget.toProvider(provider)); + } + + default void registerDraggableComponentVisitor(double priority, DraggableComponentVisitorWidget visitor) { + registerDraggableComponentVisitor(DraggableComponentVisitorWidget.toVisitor(visitor, priority)); + } + + default void registerDraggableComponentProvider(double priority, DraggableComponentProviderWidget provider) { + registerDraggableComponentProvider(DraggableComponentProviderWidget.toProvider(provider, priority)); + } + + @ApiStatus.ScheduledForRemoval + @Deprecated(forRemoval = true) Iterable> getDraggableProviders(); + @ApiStatus.ScheduledForRemoval + @Deprecated(forRemoval = true) Iterable> getDraggableVisitors(); + Iterable> getDraggableComponentProviders(); + + Iterable> getDraggableComponentVisitors(); + /** * Returns the main center screen bounds returned, provided by deciders. * diff --git a/api/src/main/java/me/shedaniel/rei/api/common/util/CollectionUtils.java b/api/src/main/java/me/shedaniel/rei/api/common/util/CollectionUtils.java index 7d00c76ec..a478ee693 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/util/CollectionUtils.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/util/CollectionUtils.java @@ -82,6 +82,15 @@ public class CollectionUtils { return null; } + public static boolean allMatch(Iterable list, Predicate predicate) { + for (T t : list) { + if (!predicate.test(t)) { + return false; + } + } + return true; + } + public static boolean anyMatch(Iterable list, Predicate predicate) { return findFirstOrNull(list, predicate) != null; } diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java index 0b9b7a7ac..ec6c8edaa 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/DefaultClientPlugin.java @@ -166,19 +166,6 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin new DefaultInformationCategory() ); - registry.removePlusButton(FUEL); - registry.removePlusButton(COMPOSTING); - registry.removePlusButton(BEACON_BASE); - registry.removePlusButton(BEACON_PAYMENT); - registry.removePlusButton(INFO); - registry.removePlusButton(STRIPPING); - registry.removePlusButton(TILLING); - registry.removePlusButton(PATHING); - registry.removePlusButton(WAXING); - registry.removePlusButton(WAX_SCRAPING); - registry.removePlusButton(OXIDIZING); - registry.removePlusButton(OXIDATION_SCRAPING); - registry.addWorkstations(CRAFTING, EntryStacks.of(Items.CRAFTING_TABLE)); registry.addWorkstations(SMELTING, EntryStacks.of(Items.FURNACE)); registry.addWorkstations(SMOKING, EntryStacks.of(Items.SMOKER)); @@ -273,7 +260,7 @@ public class DefaultClientPlugin implements REIClientPlugin, BuiltinClientPlugin ComposterBlock.bootStrap(); } int page = 0; - Iterator>> iterator = Iterators.partition(ComposterBlock.COMPOSTABLES.object2FloatEntrySet().stream().sorted(Map.Entry.comparingByValue()).iterator(), 48); + Iterator>> iterator = Iterators.partition(ComposterBlock.COMPOSTABLES.object2FloatEntrySet().stream().sorted(Map.Entry.comparingByValue()).iterator(), 35); while (iterator.hasNext()) { List> entries = iterator.next(); registry.add(DefaultCompostingDisplay.of(entries, Collections.singletonList(EntryIngredients.of(new ItemStack(Items.BONE_MEAL))), page++)); diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/DefaultCompostingCategory.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/DefaultCompostingCategory.java index 5b8302ca0..aa402a34d 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/DefaultCompostingCategory.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/DefaultCompostingCategory.java @@ -92,9 +92,10 @@ public class DefaultCompostingCategory implements DisplayCategory widgets = Lists.newArrayList(); Point startingPoint = new Point(bounds.x + bounds.width - 55, bounds.y + 110); List stacks = new ArrayList<>(display.getInputEntries()); + widgets.add(Widgets.createRecipeBase(bounds)); int i = 0; - for (int y = 0; y < 6; y++) - for (int x = 0; x < 8; x++) { + for (int y = 0; y < 5; y++) + for (int x = 0; x < 7; x++) { EntryIngredient entryStack = stacks.size() > i ? stacks.get(i) : EntryIngredient.empty(); if (!entryStack.isEmpty()) { ComposterBlock.COMPOSTABLES.object2FloatEntrySet().stream().filter(entry -> entry.getKey() != null && Objects.equals(entry.getKey().asItem(), entryStack.get(0).getValue())).findAny().map(Map.Entry::getValue).ifPresent(chance -> { @@ -103,12 +104,12 @@ public class DefaultCompostingCategory implements DisplayCategory