diff options
Diffstat (limited to 'api')
6 files changed, 205 insertions, 28 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntry.java b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntry.java index 336a80088..856cea841 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntry.java @@ -23,6 +23,8 @@ package me.shedaniel.rei.api.client.favorites; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.Lifecycle; import me.shedaniel.rei.api.client.gui.Renderer; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.impl.ClientInternals; @@ -44,16 +46,29 @@ public abstract class FavoriteEntry { private final UUID uuid = UUID.randomUUID(); public static FavoriteEntry delegate(Supplier<FavoriteEntry> supplier, @Nullable Supplier<CompoundTag> toJson) { + return delegateResult(() -> DataResult.success(supplier.get(), Lifecycle.stable()), toJson); + } + + public static FavoriteEntry delegateResult(Supplier<DataResult<FavoriteEntry>> supplier, @Nullable Supplier<CompoundTag> toJson) { return ClientInternals.delegateFavoriteEntry(supplier, toJson); } @Nullable public static FavoriteEntry read(CompoundTag object) { + return readResult(object).result().orElse(null); + } + + public static DataResult<FavoriteEntry> readResult(CompoundTag object) { return ClientInternals.favoriteEntryFromJson(object); } + public static FavoriteEntry readDelegated(CompoundTag object) { + CompoundTag copy = object.copy(); + return delegateResult(() -> readResult(object), () -> copy); + } + public static FavoriteEntry fromEntryStack(EntryStack<?> stack) { - return delegate(() -> FavoriteEntryType.registry().get(FavoriteEntryType.ENTRY_STACK).fromArgs(stack), null); + return delegateResult(() -> FavoriteEntryType.registry().get(FavoriteEntryType.ENTRY_STACK).fromArgsResult(stack), null); } public static boolean isEntryInvalid(@Nullable FavoriteEntry entry) { @@ -89,9 +104,14 @@ public abstract class FavoriteEntry { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof FavoriteEntry that)) return false; - FavoriteEntry unwrapped = getUnwrapped(); - FavoriteEntry thatUnwrapped = that.getUnwrapped(); - return unwrapped == thatUnwrapped || unwrapped.isSame(thatUnwrapped); + try { + FavoriteEntry unwrapped = getUnwrapped(); + FavoriteEntry thatUnwrapped = that.getUnwrapped(); + return unwrapped == thatUnwrapped || unwrapped.isSame(thatUnwrapped); + } catch (Throwable throwable) { + throwable.printStackTrace(); + return false; + } } @Override diff --git a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java index fd05c2bbd..7c60253b9 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java @@ -23,6 +23,8 @@ package me.shedaniel.rei.api.client.favorites; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.Lifecycle; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.plugins.PluginManager; @@ -48,9 +50,25 @@ public interface FavoriteEntryType<T extends FavoriteEntry> { return PluginManager.getClientInstance().get(FavoriteEntryType.Registry.class); } - T read(CompoundTag object); + @ApiStatus.ScheduledForRemoval + @Deprecated + default T read(CompoundTag object) { + throw new UnsupportedOperationException("Implementation of FavoriteEntryType must override #read or #readResult"); + } + + default DataResult<T> readResult(CompoundTag object) { + return DataResult.success(read(object), Lifecycle.stable()); + } - T fromArgs(Object... args); + @ApiStatus.ScheduledForRemoval + @Deprecated + default T fromArgs(Object... args) { + throw new UnsupportedOperationException("Implementation of FavoriteEntryType must override #fromArgs or #fromArgsResult"); + } + + default DataResult<T> fromArgsResult(Object... args) { + return DataResult.success(fromArgs(args), Lifecycle.stable()); + } CompoundTag save(T entry, CompoundTag tag); 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 a3eeebdbf..ae973be16 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 @@ -23,10 +23,16 @@ package me.shedaniel.rei.api.client.gui.drag; +import me.shedaniel.math.Rectangle; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import org.jetbrains.annotations.ApiStatus; import java.util.Optional; import java.util.function.Supplier; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; /** * A visitor for accepting {@link DraggableStack} to the screen. @@ -45,19 +51,60 @@ public interface DraggableStackVisitor<T extends Screen> extends Comparable<Drag } @Override - public Optional<Acceptor> visitDraggedStack(DraggingContext<T> context, DraggableStack stack) { + public boolean acceptDraggedStack(DraggingContext<T> context, DraggableStack stack) { for (DraggableStackVisitor<T> visitor : visitors.get()) { if (visitor.isHandingScreen(context.getScreen())) { - Optional<Acceptor> acceptor = visitor.visitDraggedStack(context, stack); - if (acceptor.isPresent()) return acceptor; + boolean visited = visitor.acceptDraggedStack(context, stack); + if (visited) return true; } } - return Optional.empty(); + return false; + } + + @Override + public Stream<BoundsProvider> getDraggableAcceptingBounds(DraggingContext<T> context, DraggableStack stack) { + return StreamSupport.stream(visitors.get().spliterator(), false) + .filter(visitor -> visitor.isHandingScreen(context.getScreen())) + .flatMap(visitor -> visitor.getDraggableAcceptingBounds(context, stack)); } }; } - Optional<Acceptor> visitDraggedStack(DraggingContext<T> context, DraggableStack stack); + @Deprecated(forRemoval = true) + @ApiStatus.ScheduledForRemoval + default Optional<Acceptor> visitDraggedStack(DraggingContext<T> context, DraggableStack stack) { + return Optional.empty(); + } + + /** + * Accepts a dragged stack, 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 stack on the overlay + * @param stack the stack being dragged + * @return whether the stack is accepted by the visitor + */ + default boolean acceptDraggedStack(DraggingContext<T> context, DraggableStack stack) { + Optional<Acceptor> acceptor = visitDraggedStack(context, stack); + if (acceptor.isPresent()) { + acceptor.get().accept(stack); + return true; + } else { + return false; + } + } + + /** + * 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. + * + * @param context the context of the current dragged stack on the overlay + * @param stack the stack being dragged + * @return the accepting bounds for the dragging stack in a stream + */ + default Stream<BoundsProvider> getDraggableAcceptingBounds(DraggingContext<T> context, DraggableStack stack) { + return Stream.empty(); + } <R extends Screen> boolean isHandingScreen(R screen); @@ -83,4 +130,44 @@ public interface DraggableStackVisitor<T extends Screen> extends Comparable<Drag interface Acceptor { void accept(DraggableStack stack); } + + @FunctionalInterface + interface BoundsProvider { + static VoxelShape fromRectangle(Rectangle bounds) { + return Shapes.box(bounds.x, bounds.y, 0, bounds.getMaxX(), bounds.getMaxY(), 0.1); + } + + static BoundsProvider ofRectangle(Rectangle bounds) { + return ofShape(fromRectangle(bounds)); + } + + static BoundsProvider ofRectangles(Iterable<Rectangle> bounds) { + VoxelShape shape = StreamSupport.stream(bounds.spliterator(), false) + .map(BoundsProvider::fromRectangle) + .reduce(Shapes.empty(), Shapes::or); + return ofShape(shape); + } + + static BoundsProvider ofShape(VoxelShape shape) { + return () -> shape; + } + + static BoundsProvider ofShapes(Iterable<VoxelShape> shapes) { + VoxelShape shape = StreamSupport.stream(shapes.spliterator(), false) + .reduce(Shapes.empty(), Shapes::or); + return ofShape(shape); + } + + static BoundsProvider empty() { + return Shapes::empty; + } + + static BoundsProvider concat(Iterable<BoundsProvider> providers) { + return () -> StreamSupport.stream(providers.spliterator(), false) + .map(BoundsProvider::bounds) + .reduce(Shapes.empty(), Shapes::or); + } + + 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 e1cd311d4..7bb813d4d 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 @@ -24,37 +24,79 @@ package me.shedaniel.rei.api.client.gui.drag; import net.minecraft.client.gui.screens.Screen; +import org.jetbrains.annotations.ApiStatus; import java.util.Optional; 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 DraggableStack}. */ -@FunctionalInterface public interface DraggableStackVisitorWidget { static DraggableStackVisitorWidget from(Function<DraggingContext<Screen>, Iterable<DraggableStackVisitorWidget>> providers) { - return (context, stack) -> { - for (DraggableStackVisitorWidget visitor : providers.apply(context)) { - Optional<DraggableStackVisitor.Acceptor> acceptor = visitor.visitDraggedStack(context, stack); - if (acceptor.isPresent()) return acceptor; + return new DraggableStackVisitorWidget() { + @Override + public boolean acceptDraggedStack(DraggingContext<Screen> context, DraggableStack stack) { + return StreamSupport.stream(providers.apply(context).spliterator(), false) + .anyMatch(visitor -> visitor.acceptDraggedStack(context, stack)); + } + + @Override + public Stream<DraggableStackVisitor.BoundsProvider> getDraggableAcceptingBounds(DraggingContext<Screen> context, DraggableStack stack) { + return StreamSupport.stream(providers.apply(context).spliterator(), false) + .flatMap(visitor -> visitor.getDraggableAcceptingBounds(context, stack)); } - return Optional.empty(); }; } - Optional<DraggableStackVisitor.Acceptor> visitDraggedStack(DraggingContext<Screen> context, DraggableStack stack); + @ApiStatus.ScheduledForRemoval + @Deprecated(forRemoval = true) + default Optional<DraggableStackVisitor.Acceptor> visitDraggedStack(DraggingContext<Screen> context, DraggableStack stack) { + return Optional.empty(); + } + + /** + * Accepts a dragged stack, implementations of this function should check if the {@code context} is within + * boundaries of the widget. + * + * @param context the context of the current dragged stack on the overlay + * @param stack the stack being dragged + * @return whether the stack is accepted by the widget + */ + default boolean acceptDraggedStack(DraggingContext<Screen> context, DraggableStack stack) { + Optional<DraggableStackVisitor.Acceptor> acceptor = visitDraggedStack(context, stack); + if (acceptor.isPresent()) { + acceptor.get().accept(stack); + return true; + } else { + return false; + } + } + + /** + * 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. + * + * @param context the context of the current dragged stack on the overlay + * @param stack the stack being dragged + * @return the accepting bounds for the dragging stack in a stream + */ + default Stream<DraggableStackVisitor.BoundsProvider> getDraggableAcceptingBounds(DraggingContext<Screen> context, DraggableStack stack) { + return Stream.empty(); + } static DraggableStackVisitor<Screen> toVisitor(DraggableStackVisitorWidget widget) { return toVisitor(widget, 0.0); } static DraggableStackVisitor<Screen> toVisitor(DraggableStackVisitorWidget widget, double priority) { - return new DraggableStackVisitor<Screen>() { + return new DraggableStackVisitor<>() { @Override - public Optional<Acceptor> visitDraggedStack(DraggingContext<Screen> context, DraggableStack stack) { - return widget.visitDraggedStack(context, stack); + public boolean acceptDraggedStack(DraggingContext<Screen> context, DraggableStack stack) { + return widget.acceptDraggedStack(context, stack); } @Override @@ -63,6 +105,11 @@ public interface DraggableStackVisitorWidget { } @Override + public Stream<BoundsProvider> getDraggableAcceptingBounds(DraggingContext<Screen> context, DraggableStack stack) { + return widget.getDraggableAcceptingBounds(context, stack); + } + + @Override public double getPriority() { return priority; } diff --git a/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryStack.java b/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryStack.java index 9ac571bdb..76ff50f98 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryStack.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryStack.java @@ -77,15 +77,19 @@ public interface EntryStack<T> extends TextRepresentable, Renderer { @Nullable default CompoundTag save() { - EntrySerializer<T> serializer = getDefinition().getSerializer(); - if (serializer != null && serializer.supportSaving()) { - CompoundTag tag = serializer.save(this, getValue()); + if (supportSaving()) { + CompoundTag tag = getDefinition().getSerializer().save(this, getValue()); tag.putString("type", getType().getId().toString()); return tag; } throw new UnsupportedOperationException(getType().getId() + " does not support serialization!"); } + default boolean supportSaving() { + EntrySerializer<T> serializer = getDefinition().getSerializer(); + return serializer != null && serializer.supportSaving(); + } + @Nullable @Environment(EnvType.CLIENT) Tooltip getTooltip(Point mouse, boolean appendModName); diff --git a/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java b/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java index daccb744d..d9cb5eaa8 100644 --- a/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java +++ b/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java @@ -23,6 +23,7 @@ package me.shedaniel.rei.impl; +import com.mojang.serialization.DataResult; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.ClientHelper; @@ -60,8 +61,8 @@ public final class ClientInternals { private static Supplier<ViewSearchBuilder> viewSearchBuilder = ClientInternals::throwNotSetup; private static Supplier<PluginManager<REIClientPlugin>> clientPluginManager = ClientInternals::throwNotSetup; private static Supplier<EntryRenderer<?>> emptyEntryRenderer = ClientInternals::throwNotSetup; - private static BiFunction<Supplier<FavoriteEntry>, Supplier<CompoundTag>, FavoriteEntry> delegateFavoriteEntry = (supplier, toJson) -> throwNotSetup(); - private static Function<CompoundTag, FavoriteEntry> favoriteEntryFromJson = (object) -> throwNotSetup(); + private static BiFunction<Supplier<DataResult<FavoriteEntry>>, Supplier<CompoundTag>, FavoriteEntry> delegateFavoriteEntry = (supplier, toJson) -> throwNotSetup(); + private static Function<CompoundTag, DataResult<FavoriteEntry>> favoriteEntryFromJson = (object) -> throwNotSetup(); private static Function<Boolean, ClickArea.Result> clickAreaHandlerResult = (result) -> throwNotSetup(); private static BiConsumer<List<ClientTooltipComponent>, TooltipComponent> clientTooltipComponentProvider = (tooltip, result) -> throwNotSetup(); private static BiFunction<@Nullable Point, Collection<Tooltip.Entry>, Tooltip> tooltipProvider = (point, texts) -> throwNotSetup(); @@ -130,11 +131,11 @@ public final class ClientInternals { return tooltipEntryProvider.apply(component); } - public static FavoriteEntry delegateFavoriteEntry(Supplier<FavoriteEntry> supplier, Supplier<CompoundTag> toJoin) { + public static FavoriteEntry delegateFavoriteEntry(Supplier<DataResult<FavoriteEntry>> supplier, Supplier<CompoundTag> toJoin) { return delegateFavoriteEntry.apply(supplier, toJoin); } - public static FavoriteEntry favoriteEntryFromJson(CompoundTag tag) { + public static DataResult<FavoriteEntry> favoriteEntryFromJson(CompoundTag tag) { return favoriteEntryFromJson.apply(tag); } |
