From 64bc9937d6ec04c6d66240a84b4fb345026c0b12 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Tue, 9 Mar 2021 21:30:12 +0800 Subject: Very primitive background rendering for JEI plugins Signed-off-by: shedaniel --- .../main/java/me/shedaniel/rei/api/REIOverlay.java | 3 + .../shedaniel/rei/api/gui/drag/DraggableStack.java | 17 ++ .../rei/api/gui/drag/DraggableStackProvider.java | 21 ++ .../rei/api/gui/drag/DraggableStackVisitor.java | 23 ++ .../rei/api/gui/drag/DraggingContext.java | 25 ++ .../me/shedaniel/rei/api/gui/widgets/Widget.java | 1 + .../rei/api/gui/widgets/WidgetWithBounds.java | 2 - .../shedaniel/rei/api/ingredient/EntryStack.java | 7 +- .../rei/api/ingredient/entry/EntryDefinition.java | 1 - .../api/ingredient/entry/EntryTypeRegistry.java | 8 +- .../rei/api/ingredient/util/EntryIngredients.java | 21 ++ .../rei/api/ingredient/util/EntryStacks.java | 8 +- build.gradle | 9 +- .../rei/fabric/RoughlyEnoughItemsFabric.java | 6 +- .../resources/roughlyenoughitems.accessWidener | 1 - forge/build.gradle | 10 + .../me/shedaniel/rei/forge/PluginDetectorImpl.java | 9 + .../java/me/shedaniel/rei/forge/REIPlugin.java | 11 + .../rei/forge/RoughlyEnoughItemsForge.java | 37 +++ .../main/resources/META-INF/accesstransformer.cfg | 54 ++-- .../me/shedaniel/rei/RoughlyEnoughItemsCore.java | 5 +- .../rei/api/gui/config/entry/FilteringScreen.java | 5 - .../shedaniel/rei/gui/ContainerScreenOverlay.java | 119 +++++---- .../me/shedaniel/rei/gui/CurrentDraggingStack.java | 125 +++++++++ .../shedaniel/rei/gui/credits/CreditsScreen.java | 4 +- .../shedaniel/rei/gui/widget/EntryListWidget.java | 33 ++- .../me/shedaniel/rei/gui/widget/EntryWidget.java | 2 +- .../rei/gui/widget/FavoritesListWidget.java | 289 ++++++++++----------- .../shedaniel/rei/impl/EntryTypeRegistryImpl.java | 11 + .../me/shedaniel/rei/impl/ExclusionZonesImpl.java | 42 ++- .../rei/impl/registry/CategoryRegistryImpl.java | 4 +- settings.gradle | 2 +- 32 files changed, 646 insertions(+), 269 deletions(-) create mode 100644 api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStack.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStackProvider.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStackVisitor.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggingContext.java create mode 100644 forge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java create mode 100644 runtime/src/main/java/me/shedaniel/rei/gui/CurrentDraggingStack.java diff --git a/api/src/main/java/me/shedaniel/rei/api/REIOverlay.java b/api/src/main/java/me/shedaniel/rei/api/REIOverlay.java index 24eaf15bd..c9dc4c16e 100644 --- a/api/src/main/java/me/shedaniel/rei/api/REIOverlay.java +++ b/api/src/main/java/me/shedaniel/rei/api/REIOverlay.java @@ -23,9 +23,12 @@ package me.shedaniel.rei.api; +import me.shedaniel.rei.api.gui.drag.DraggingContext; import org.jetbrains.annotations.ApiStatus; @ApiStatus.Experimental public interface REIOverlay { void queueReloadOverlay(); + + DraggingContext getDraggingContext(); } diff --git a/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStack.java b/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStack.java new file mode 100644 index 000000000..8d38fb4c8 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStack.java @@ -0,0 +1,17 @@ +package me.shedaniel.rei.api.gui.drag; + +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.ingredient.EntryStack; + +public interface DraggableStack { + EntryStack getStack(); + + void drag(); + + void release(boolean accepted); + + default void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + getStack().render(matrices, bounds, mouseX, mouseY, delta); + } +} \ No newline at end of file diff --git a/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStackProvider.java b/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStackProvider.java new file mode 100644 index 000000000..7b799b26a --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStackProvider.java @@ -0,0 +1,21 @@ +package me.shedaniel.rei.api.gui.drag; + +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +@FunctionalInterface +public interface DraggableStackProvider { + static DraggableStackProvider from(Supplier> providers) { + return (context, mouseX, mouseY) -> { + for (DraggableStackProvider provider : providers.get()) { + DraggableStack stack = provider.getHoveredStack(context, mouseX, mouseY); + if (stack != null) return stack; + } + return null; + }; + } + + @Nullable + DraggableStack getHoveredStack(DraggingContext context, double mouseX, double mouseY); +} \ No newline at end of file diff --git a/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStackVisitor.java b/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStackVisitor.java new file mode 100644 index 000000000..e0e64bf9a --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggableStackVisitor.java @@ -0,0 +1,23 @@ +package me.shedaniel.rei.api.gui.drag; + +import java.util.Optional; +import java.util.function.Supplier; + +@FunctionalInterface +public interface DraggableStackVisitor { + static DraggableStackVisitor from(Supplier> visitors) { + return (stack) -> { + for (DraggableStackVisitor visitor : visitors.get()) { + Optional acceptor = visitor.visitDraggedStack(stack); + if (acceptor.isPresent()) return acceptor; + } + return Optional.empty(); + }; + } + + Optional visitDraggedStack(DraggableStack stack); + + interface Acceptor { + void accept(DraggableStack stack); + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggingContext.java b/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggingContext.java new file mode 100644 index 000000000..cd9bc3a32 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/gui/drag/DraggingContext.java @@ -0,0 +1,25 @@ +package me.shedaniel.rei.api.gui.drag; + +import me.shedaniel.math.Point; +import me.shedaniel.rei.api.REIHelper; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public interface DraggingContext { + static DraggingContext getInstance() { + return REIHelper.getInstance().getOverlay().get().getDraggingContext(); + } + + default boolean isDraggingStack() { + return getCurrentStack() != null; + } + + @Nullable + DraggableStack getCurrentStack(); + + @Nullable + Point getCurrentPosition(); + + void registerRenderBackToPosition(DraggableStack stack, Supplier position); +} diff --git a/api/src/main/java/me/shedaniel/rei/api/gui/widgets/Widget.java b/api/src/main/java/me/shedaniel/rei/api/gui/widgets/Widget.java index abe4454ae..ddb4d0d26 100644 --- a/api/src/main/java/me/shedaniel/rei/api/gui/widgets/Widget.java +++ b/api/src/main/java/me/shedaniel/rei/api/gui/widgets/Widget.java @@ -75,6 +75,7 @@ public abstract class Widget extends AbstractContainerEventHandler implements ne } @Override + @Deprecated public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { render(matrices, mouseX, mouseY, delta); } diff --git a/api/src/main/java/me/shedaniel/rei/api/gui/widgets/WidgetWithBounds.java b/api/src/main/java/me/shedaniel/rei/api/gui/widgets/WidgetWithBounds.java index 17b178bb3..b427d8a47 100644 --- a/api/src/main/java/me/shedaniel/rei/api/gui/widgets/WidgetWithBounds.java +++ b/api/src/main/java/me/shedaniel/rei/api/gui/widgets/WidgetWithBounds.java @@ -27,7 +27,6 @@ import me.shedaniel.math.Rectangle; import org.jetbrains.annotations.NotNull; public abstract class WidgetWithBounds extends Widget { - @NotNull public abstract Rectangle getBounds(); @@ -35,5 +34,4 @@ public abstract class WidgetWithBounds extends Widget { public boolean containsMouse(double mouseX, double mouseY) { return getBounds().contains(mouseX, mouseY); } - } diff --git a/api/src/main/java/me/shedaniel/rei/api/ingredient/EntryStack.java b/api/src/main/java/me/shedaniel/rei/api/ingredient/EntryStack.java index 913dded0d..9e62eb9a1 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ingredient/EntryStack.java +++ b/api/src/main/java/me/shedaniel/rei/api/ingredient/EntryStack.java @@ -29,11 +29,11 @@ import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; import me.shedaniel.architectury.utils.Fraction; import me.shedaniel.rei.api.gui.Renderer; -import me.shedaniel.rei.api.util.TextRepresentable; import me.shedaniel.rei.api.ingredient.entry.ComparisonContext; import me.shedaniel.rei.api.ingredient.entry.EntryDefinition; import me.shedaniel.rei.api.ingredient.entry.EntryRenderer; import me.shedaniel.rei.api.ingredient.entry.EntryType; +import me.shedaniel.rei.api.util.TextRepresentable; import me.shedaniel.rei.impl.Internals; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -202,4 +202,9 @@ public interface EntryStack extends TextRepresentable, Renderer { setAmount(getAmount().simplify()); return this; } + + @ApiStatus.NonExtendable + default EntryStack cast() { + return (EntryStack) this; + } } diff --git a/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/EntryDefinition.java b/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/EntryDefinition.java index dcb72f0fe..f2d22668f 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/EntryDefinition.java +++ b/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/EntryDefinition.java @@ -49,7 +49,6 @@ public interface EntryDefinition { boolean isEmpty(EntryStack entry, T value); - @NotNull T copy(EntryStack entry, T value); int hash(EntryStack entry, T value, ComparisonContext context); diff --git a/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/EntryTypeRegistry.java b/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/EntryTypeRegistry.java index 2fd9f0bbb..2397b46a5 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/EntryTypeRegistry.java +++ b/api/src/main/java/me/shedaniel/rei/api/ingredient/entry/EntryTypeRegistry.java @@ -25,11 +25,11 @@ package me.shedaniel.rei.api.ingredient.entry; import me.shedaniel.rei.api.plugins.PluginManager; import me.shedaniel.rei.api.registry.Reloadable; -import me.shedaniel.rei.impl.Internals; import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Set; + public interface EntryTypeRegistry extends Reloadable { static EntryTypeRegistry getInstance() { return PluginManager.getInstance().get(EntryTypeRegistry.class); @@ -75,6 +75,10 @@ public interface EntryTypeRegistry extends Reloadable { @Nullable EntryDefinition get(ResourceLocation id); + Set keySet(); + + Set> values(); + void registerBridge(EntryType original, EntryType destination, EntryTypeBridge bridge); Iterable> getBridgesFor(EntryType original, EntryType destination); diff --git a/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryIngredients.java b/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryIngredients.java index 0407ae215..bbd401247 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryIngredients.java +++ b/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryIngredients.java @@ -24,10 +24,13 @@ package me.shedaniel.rei.api.ingredient.util; import com.google.common.collect.ImmutableList; +import me.shedaniel.architectury.fluid.FluidStack; import me.shedaniel.architectury.utils.Fraction; import me.shedaniel.rei.api.gui.Renderer; import me.shedaniel.rei.api.ingredient.EntryIngredient; import me.shedaniel.rei.api.ingredient.EntryStack; +import me.shedaniel.rei.api.ingredient.entry.EntryDefinition; +import me.shedaniel.rei.api.ingredient.entry.EntryType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.ItemLike; @@ -65,10 +68,28 @@ public final class EntryIngredients { return EntryIngredient.of(EntryStacks.of(fluid, amount)); } + public static EntryIngredient of(FluidStack stack) { + return EntryIngredient.of(EntryStacks.of(stack)); + } + public static EntryIngredient of(Renderer renderer) { return EntryIngredient.of(EntryStacks.of(renderer)); } + public static EntryIngredient of(EntryType type, Collection values) { + return of(type.getDefinition(), values); + } + + public static EntryIngredient of(EntryDefinition definition, Collection values) { + if (values.size() == 0) return EntryIngredient.empty(); + if (values.size() == 1) return EntryIngredient.of(EntryStack.of(definition, values.iterator().next())); + List> result = new ArrayList<>(values.size()); + for (T value : values) { + result.add(EntryStack.of(definition, value)); + } + return EntryIngredient.of(result); + } + public static EntryIngredient ofItems(Collection stacks) { if (stacks.size() == 0) return EntryIngredient.empty(); if (stacks.size() == 1) return EntryIngredient.of(EntryStacks.of(stacks.iterator().next())); diff --git a/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryStacks.java b/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryStacks.java index 18144e5df..30b6af005 100644 --- a/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryStacks.java +++ b/api/src/main/java/me/shedaniel/rei/api/ingredient/util/EntryStacks.java @@ -26,9 +26,9 @@ package me.shedaniel.rei.api.ingredient.util; import com.google.common.collect.ImmutableList; import me.shedaniel.architectury.fluid.FluidStack; import me.shedaniel.architectury.utils.Fraction; +import me.shedaniel.rei.api.gui.Renderer; import me.shedaniel.rei.api.ingredient.EntryStack; import me.shedaniel.rei.api.ingredient.entry.*; -import me.shedaniel.rei.api.gui.Renderer; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; @@ -57,6 +57,10 @@ public final class EntryStacks { return EntryStack.of(VanillaEntryTypes.FLUID, FluidStack.create(fluid, amount)); } + public static EntryStack of(FluidStack stack) { + return EntryStack.of(VanillaEntryTypes.FLUID, stack); + } + public static EntryStack of(ItemStack stack) { return EntryStack.of(VanillaEntryTypes.ITEM, stack); } @@ -67,7 +71,7 @@ public final class EntryStacks { public static EntryStack of(Renderer renderer) { if (renderer instanceof EntryStack) { - return (EntryStack) renderer; + return (EntryStack) renderer; } return EntryStack.of(BuiltinEntryTypes.RENDERING, renderer); diff --git a/build.gradle b/build.gradle index 5c5d0c67c..be2737ac4 100755 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { - id("architectury-plugin") version("3.0.89") - id("forgified-fabric-loom") version("0.6.71") apply false + id("architectury-plugin") version("3.0.97") + id("forgified-fabric-loom") version("0.6-SNAPSHOT") apply false id("org.cadixdev.licenser") version("0.5.0") id("com.matthewprenger.cursegradle") version("1.4.0") id("java") @@ -37,15 +37,10 @@ allprojects { sourceCompatibility = targetCompatibility = 1.8 repositories { - mavenLocal() maven { url "https://maven.shedaniel.me" } maven { url "https://maven.terraformersmc.com/releases" } } - architectury { - transformerVersion = "2.1.9999" - } - license { header rootProject.file("HEADER") include "**/*.java" diff --git a/fabric/src/main/java/me/shedaniel/rei/fabric/RoughlyEnoughItemsFabric.java b/fabric/src/main/java/me/shedaniel/rei/fabric/RoughlyEnoughItemsFabric.java index 7172ec864..11266d68e 100644 --- a/fabric/src/main/java/me/shedaniel/rei/fabric/RoughlyEnoughItemsFabric.java +++ b/fabric/src/main/java/me/shedaniel/rei/fabric/RoughlyEnoughItemsFabric.java @@ -1,16 +1,16 @@ package me.shedaniel.rei.fabric; import me.shedaniel.rei.impl.IssuesDetector; -import net.fabricmc.api.ModInitializer; +import net.fabricmc.api.ClientModInitializer; import net.fabricmc.loader.api.FabricLoader; import org.apache.logging.log4j.Logger; import java.lang.reflect.Field; import java.util.Locale; -public class RoughlyEnoughItemsFabric implements ModInitializer { +public class RoughlyEnoughItemsFabric implements ClientModInitializer { @Override - public void onInitialize() { + public void onInitializeClient() { IssuesDetector.register(() -> { try { FabricLoader instance = FabricLoader.getInstance(); diff --git a/fabric/src/main/resources/roughlyenoughitems.accessWidener b/fabric/src/main/resources/roughlyenoughitems.accessWidener index 4a5503b87..8accdb958 100644 --- a/fabric/src/main/resources/roughlyenoughitems.accessWidener +++ b/fabric/src/main/resources/roughlyenoughitems.accessWidener @@ -30,4 +30,3 @@ accessible method net/minecraft/client/gui/screens/Screen accessible method net/minecraft/client/gui/screens/Screen init ()V accessible method net/minecraft/client/gui/screens/Screen insertText (Ljava/lang/String;Z)V accessible method net/minecraft/client/gui/screens/Screen isValidCharacterForName (Ljava/lang/String;CI)Z -accessible method net/minecraft/tags/TagContainer get (Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/tags/TagCollection; diff --git a/forge/build.gradle b/forge/build.gradle index d81a635c2..ee643b74b 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -12,6 +12,10 @@ processResources { inputs.property "version", project.version } +repositories { + maven { url "https://www.cursemaven.com" } +} + dependencies { forge("net.minecraftforge:forge:${rootProject.minecraft_version}-${rootProject.forge_version}") modApi("me.shedaniel.cloth:cloth-config-forge:${cloth_config_version}") @@ -20,7 +24,13 @@ dependencies { implementation(project(path: ":api")) { transitive = false } implementation(project(path: ":default-plugin")) { transitive = false } implementation(project(path: ":runtime")) { transitive = false } + implementation(project(path: ":jei-compatibility-layer")) { transitive = false } developmentForge(project(path: ":api")) { transitive = false } developmentForge(project(path: ":default-plugin")) { transitive = false } developmentForge(project(path: ":runtime")) { transitive = false } + developmentForge(project(path: ":jei-compatibility-layer")) { transitive = false } + + modRuntime("curse.maven:chiselsbits-231095:3176033") + modRuntime("curse.maven:jumbofurnace-390880:3120970") + modRuntime("curse.maven:cyclic-239286:3221427") } diff --git a/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java b/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java index 044bfd081..4aace1982 100644 --- a/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java +++ b/forge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java @@ -1,11 +1,15 @@ package me.shedaniel.rei.forge; +import me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.gui.plugin.DefaultRuntimePlugin; +import me.shedaniel.rei.jeicompat.JEIPluginDetector; import me.shedaniel.rei.plugin.DefaultPlugin; import me.shedaniel.rei.plugin.DefaultServerContainerPlugin; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import java.util.function.Consumer; + import static me.shedaniel.rei.RoughlyEnoughItemsCore.registerPlugin; public class PluginDetectorImpl { @@ -17,5 +21,10 @@ public class PluginDetectorImpl { public static void detectClientPlugins() { registerPlugin(new DefaultPlugin()); registerPlugin(new DefaultRuntimePlugin()); + RoughlyEnoughItemsForge.scanAnnotation(REIPlugin.class, plugin -> { + registerPlugin(((me.shedaniel.rei.api.plugins.REIPlugin) plugin)); + }); + JEIPluginDetector.detect((aClass, consumer) -> RoughlyEnoughItemsForge.scanAnnotation((Class) aClass, (Consumer) consumer), + RoughlyEnoughItemsCore::registerPlugin); } } diff --git a/forge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java b/forge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java new file mode 100644 index 000000000..a4acbaa46 --- /dev/null +++ b/forge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java @@ -0,0 +1,11 @@ +package me.shedaniel.rei.forge; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface REIPlugin { +} diff --git a/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java b/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java index 9147eb8f2..d96afb6b4 100644 --- a/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java +++ b/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java @@ -1,17 +1,54 @@ package me.shedaniel.rei.forge; +import com.google.common.collect.Lists; import me.shedaniel.architectury.platform.forge.EventBuses; import me.shedaniel.rei.RoughlyEnoughItemsInitializer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.forgespi.language.ModFileScanData; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.ApiStatus; +import org.objectweb.asm.Type; + +import java.util.List; +import java.util.function.Consumer; @Mod("roughlyenoughitems") +@ApiStatus.Internal public class RoughlyEnoughItemsForge { + public static final Logger LOGGER = LogManager.getFormatterLogger("REI"); + public RoughlyEnoughItemsForge() { EventBuses.registerModEventBus("roughlyenoughitems", FMLJavaModLoadingContext.get().getModEventBus()); RoughlyEnoughItemsInitializer.onInitialize(); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> RoughlyEnoughItemsInitializer::onInitializeClient); } + + public static void scanAnnotation(Class clazz, Consumer consumer) { + scanAnnotation(Type.getType(clazz), consumer); + } + + public static void scanAnnotation(Type annotationType, Consumer consumer) { + List instances = Lists.newArrayList(); + for (ModFileScanData data : ModList.get().getAllScanData()) { + for (ModFileScanData.AnnotationData annotation : data.getAnnotations()) { + if (annotationType.equals(annotation.getAnnotationType())) { + try { + T instance = (T) Class.forName(annotation.getMemberName()).getDeclaredConstructor().newInstance(); + instances.add(instance); + } catch (Throwable throwable) { + LOGGER.error("Failed to load plugin: " + annotation.getMemberName(), throwable); + } + } + } + } + + for (T instance : instances) { + consumer.accept(instance); + } + } } diff --git a/forge/src/main/resources/META-INF/accesstransformer.cfg b/forge/src/main/resources/META-INF/accesstransformer.cfg index f4a298c9e..2648dd607 100644 --- a/forge/src/main/resources/META-INF/accesstransformer.cfg +++ b/forge/src/main/resources/META-INF/accesstransformer.cfg @@ -1,23 +1,31 @@ -public net.minecraft.client.gui.recipebook.RecipeBookGui field_191915_z #ghostRecipe -public net.minecraft.client.gui.AbstractGui func_238461_a_(Lnet/minecraft/util/math/vector/Matrix4f;IIIIIFFFF)V #innerBlit -public net.minecraft.client.gui.screen.Screen field_230710_m_ #buttons -public net.minecraft.entity.player.PlayerInventory field_184440_g #compartments -public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147007_t #isQuickCrafting -public net.minecraft.client.gui.widget.button.ImageButton field_191750_o #resourceLocation -public net.minecraft.item.ItemGroup field_78034_o #langId -public net.minecraft.item.crafting.SmithingRecipe field_234837_a_ #base -public net.minecraft.item.crafting.SmithingRecipe field_234838_b_ #addition -public net.minecraft.client.gui.DisplayEffectsScreen field_147045_u #doRenderEffects -public net.minecraft.client.gui.recipebook.RecipeBookGui field_193018_j #tabButtons -public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147006_u #hoveredSlot -public net.minecraft.client.renderer.RenderState field_228520_l_ #SMOOTH_SHADE -public net.minecraft.client.renderer.RenderState field_228528_t_ #LIGHTMAP -public net.minecraft.client.renderer.RenderState field_228515_g_ #TRANSLUCENT_TRANSPARENCY -public net.minecraft.potion.PotionBrewing field_185213_a #POTION_MIXES -public net.minecraft.potion.PotionBrewing field_185214_b #CONTAINER_MIXES -public net.minecraft.potion.PotionBrewing field_185215_c #ALLOWED_CONTAINERS -public net.minecraft.util.text.CharacterManager field_238347_a_ #widthProvider -public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147003_i # leftPos -public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147009_r # topPos -public net.minecraft.client.gui.screen.inventory.ContainerScreen field_146999_f # imageWidth -public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147000_g # imageHeight \ No newline at end of file +public net.minecraft.client.gui.FontRenderer$CharacterRenderer +public net.minecraft.potion.PotionBrewing$MixPredicate +public net.minecraft.client.gui.widget.button.ImageButton field_191750_o +public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147006_u +public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147000_g +public net.minecraft.client.gui.screen.inventory.ContainerScreen field_146999_f +public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147007_t +public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147003_i +public net.minecraft.client.gui.screen.inventory.ContainerScreen field_147009_r +public net.minecraft.client.gui.DisplayEffectsScreen field_147045_u +public net.minecraft.client.gui.recipebook.RecipeBookGui field_191915_z +public net.minecraft.client.gui.recipebook.RecipeBookGui field_193962_q +public net.minecraft.client.gui.recipebook.RecipeBookGui field_193018_j +public net.minecraft.util.text.CharacterManager field_238347_a_ +public net.minecraft.entity.player.PlayerInventory field_184440_g +public net.minecraft.potion.PotionBrewing field_185215_c +public net.minecraft.potion.PotionBrewing field_185214_b +public net.minecraft.potion.PotionBrewing field_185213_a +public net.minecraft.potion.PotionBrewing$MixPredicate field_185198_a +public net.minecraft.potion.PotionBrewing$MixPredicate field_185199_b +public net.minecraft.potion.PotionBrewing$MixPredicate field_185200_c +public net.minecraft.item.BucketItem field_77876_a +public net.minecraft.item.crafting.SmithingRecipe field_234838_b_ +public net.minecraft.item.crafting.SmithingRecipe field_234837_a_ +public net.minecraft.item.ItemGroup field_78034_o +public net.minecraft.client.gui.AbstractGui func_238461_a_(Lnet/minecraft/util/math/vector/Matrix4f;IIIIIFFFF)V +public net.minecraft.client.gui.screen.Screen func_230480_a_(Lnet/minecraft/client/gui/widget/Widget;)Lnet/minecraft/client/gui/widget/Widget; +public net.minecraft.client.gui.screen.Screen func_230481_d_(Lnet/minecraft/client/gui/IGuiEventListener;)Lnet/minecraft/client/gui/IGuiEventListener; +public net.minecraft.client.gui.screen.Screen func_231160_c_()V +public net.minecraft.client.gui.screen.Screen func_231155_a_(Ljava/lang/String;Z)V +public net.minecraft.client.gui.screen.Screen func_231154_a_(Ljava/lang/String;CI)Z \ No newline at end of file diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java index f0cfe81b5..c668dc282 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCore.java @@ -74,6 +74,7 @@ import net.minecraft.client.gui.screens.recipebook.GhostRecipe; import net.minecraft.client.gui.screens.recipebook.RecipeBookComponent; import net.minecraft.client.gui.screens.recipebook.RecipeUpdateListener; import net.minecraft.client.resources.language.I18n; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; import net.minecraft.network.chat.TextComponent; @@ -337,7 +338,7 @@ public class RoughlyEnoughItemsCore { @ApiStatus.Internal public static T registerPlugin(T plugin) { PLUGINS.add(plugin); - RoughlyEnoughItemsCore.LOGGER.debug("Registered plugin %s", plugin.getPluginName()); + RoughlyEnoughItemsCore.LOGGER.info("Registered plugin %s", plugin.getPluginName()); return plugin; } @@ -504,7 +505,7 @@ public class RoughlyEnoughItemsCore { } return InteractionResult.PASS; }); - ClientScreenInputEvent.KEY_RELEASED_PRE.register((minecraftClient, screen, mouseX, mouseY, button) -> { + ClientScreenInputEvent.MOUSE_RELEASED_PRE.register((minecraftClient, screen, mouseX, mouseY, button) -> { isLeftModePressed = false; if (shouldReturn(screen)) return InteractionResult.PASS; diff --git a/runtime/src/main/java/me/shedaniel/rei/api/gui/config/entry/FilteringScreen.java b/runtime/src/main/java/me/shedaniel/rei/api/gui/config/entry/FilteringScreen.java index a54845f60..f5d5464a2 100644 --- a/runtime/src/main/java/me/shedaniel/rei/api/gui/config/entry/FilteringScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/api/gui/config/entry/FilteringScreen.java @@ -482,11 +482,6 @@ public class FilteringScreen extends Screen { } } - @Override - public EntryStack getCurrentEntry() { - return super.getCurrentEntry(); - } - public boolean isSelected() { return getSelection().intersects(getBounds()); } diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java b/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java index a63d38459..e44a56f18 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java @@ -23,25 +23,27 @@ package me.shedaniel.rei.gui; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.math.Matrix4f; import com.mojang.math.Vector4f; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.api.*; +import me.shedaniel.rei.api.gui.drag.DraggableStack; +import me.shedaniel.rei.api.gui.drag.DraggableStackProvider; +import me.shedaniel.rei.api.gui.drag.DraggableStackVisitor; +import me.shedaniel.rei.api.gui.drag.DraggingContext; import me.shedaniel.rei.api.gui.widgets.*; import me.shedaniel.rei.api.ingredient.EntryStack; import me.shedaniel.rei.api.ingredient.util.EntryStacks; import me.shedaniel.rei.api.favorites.FavoriteEntry; import me.shedaniel.rei.api.gui.config.SearchFieldLocation; import me.shedaniel.rei.api.registry.category.CategoryRegistry; -import me.shedaniel.rei.api.registry.display.DisplayRegistry; import me.shedaniel.rei.api.registry.screen.ClickArea; import me.shedaniel.rei.api.registry.screen.DisplayBoundsProvider; import me.shedaniel.rei.api.registry.screen.OverlayDecider; @@ -60,7 +62,6 @@ import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.sounds.SimpleSoundInstance; @@ -75,7 +76,6 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; import net.minecraft.world.level.block.Blocks; -import org.apache.logging.log4j.util.TriConsumer; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -83,7 +83,6 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; -import java.util.stream.Collectors; @ApiStatus.Internal public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverlay { @@ -93,43 +92,11 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl private static final EntryListWidget ENTRY_LIST_WIDGET = new EntryListWidget(); private static FavoritesListWidget favoritesListWidget = null; private final List widgets = Lists.newLinkedList(); - public boolean shouldReInit = false; - private int tooltipWidth; - private int tooltipHeight; - private List tooltipLines; - public final TriConsumer renderTooltipCallback = (matrices, mouse, aFloat) -> { - RenderSystem.disableRescaleNormal(); - RenderSystem.disableDepthTest(); - matrices.pushPose(); - matrices.translate(0, 0, 999); - int x = mouse.x; - int y = mouse.y; - this.fillGradient(matrices, x - 3, y - 4, x + tooltipWidth + 3, y - 3, -267386864, -267386864); - this.fillGradient(matrices, x - 3, y + tooltipHeight + 3, x + tooltipWidth + 3, y + tooltipHeight + 4, -267386864, -267386864); - this.fillGradient(matrices, x - 3, y - 3, x + tooltipWidth + 3, y + tooltipHeight + 3, -267386864, -267386864); - this.fillGradient(matrices, x - 4, y - 3, x - 3, y + tooltipHeight + 3, -267386864, -267386864); - this.fillGradient(matrices, x + tooltipWidth + 3, y - 3, x + tooltipWidth + 4, y + tooltipHeight + 3, -267386864, -267386864); - this.fillGradient(matrices, x - 3, y - 3 + 1, x - 3 + 1, y + tooltipHeight + 3 - 1, 1347420415, 1344798847); - this.fillGradient(matrices, x + tooltipWidth + 2, y - 3 + 1, x + tooltipWidth + 3, y + tooltipHeight + 3 - 1, 1347420415, 1344798847); - this.fillGradient(matrices, x - 3, y - 3, x + tooltipWidth + 3, y - 3 + 1, 1347420415, 1347420415); - this.fillGradient(matrices, x - 3, y + tooltipHeight + 2, x + tooltipWidth + 3, y + tooltipHeight + 3, 1344798847, 1344798847); - int currentY = y; - MultiBufferSource.BufferSource immediate = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); - Matrix4f matrix = matrices.last().pose(); - for (int lineIndex = 0; lineIndex < tooltipLines.size(); lineIndex++) { - font.drawInBatch(tooltipLines.get(lineIndex), x, currentY, -1, true, matrix, immediate, false, 0, 15728880); - currentY += lineIndex == 0 ? 12 : 10; - } - immediate.endBatch(); - matrices.popPose(); - RenderSystem.enableDepthTest(); - RenderSystem.enableRescaleNormal(); - }; + public boolean shouldReload = false; private Rectangle bounds; private Window window; private Button leftButton, rightButton; - @ApiStatus.Experimental - private Rectangle subsetsButtonBounds; + private CurrentDraggingStack draggingStack = new CurrentDraggingStack(); @Nullable private ContainerScreenOverlay.OverlayMenu overlayMenu = null; @@ -208,7 +175,12 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl @Override public void queueReloadOverlay() { - shouldReInit = true; + shouldReload = true; + } + + @Override + public DraggingContext getDraggingContext() { + return draggingStack; } public void init(boolean useless) { @@ -216,7 +188,11 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl } public void init() { - this.shouldReInit = false; + Iterable stackProviders = (Iterable) Iterables.filter(widgets, widget -> widget instanceof DraggableStackProvider); + Iterable stackVisitors = (Iterable) Iterables.filter(widgets, widget -> widget instanceof DraggableStackVisitor); + draggingStack.set(DraggableStackProvider.from(() -> stackProviders), DraggableStackVisitor.from(() -> stackVisitors)); + + this.shouldReload = false; //Update Variables this.children().clear(); this.removeOverlayMenu(); @@ -224,8 +200,9 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl this.bounds = ScreenRegistry.getInstance().getOverlayBounds(ConfigObject.getInstance().getDisplayPanelLocation(), Minecraft.getInstance().screen); widgets.add(ENTRY_LIST_WIDGET); if (ConfigObject.getInstance().isFavoritesEnabled()) { - if (favoritesListWidget == null) + if (favoritesListWidget == null) { favoritesListWidget = new FavoritesListWidget(); + } favoritesListWidget.favoritePanel.resetRows(); widgets.add(favoritesListWidget); } @@ -353,12 +330,12 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl helper.blit(matrices, weatherButton.getBounds().x + 3, weatherButton.getBounds().y + 3, getCurrentWeather().getId() * 14, 14, 14, 14); })); } - subsetsButtonBounds = getSubsetsButtonBounds(); + Rectangle subsetsButtonBounds = getSubsetsButtonBounds(); if (ConfigObject.getInstance().isSubsetsEnabled()) { widgets.add(InternalWidgets.wrapLateRenderable(InternalWidgets.wrapTranslate(Widgets.createButton(subsetsButtonBounds, ClientHelperImpl.getInstance().isAprilFools.get() ? new TranslatableComponent("text.rei.tiny_potato") : new TranslatableComponent("text.rei.subsets")) .onClick(button -> { proceedOpenMenuOrElse(Menu.SUBSETS, () -> { - openMenu(Menu.SUBSETS, Menu.createSubsetsMenuFromRegistry(new Point(this.subsetsButtonBounds.x, this.subsetsButtonBounds.getMaxY())), point -> true); + openMenu(Menu.SUBSETS, Menu.createSubsetsMenuFromRegistry(new Point(subsetsButtonBounds.x, subsetsButtonBounds.getMaxY())), point -> true); }, menu -> { removeOverlayMenu(); }); @@ -397,6 +374,56 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl )); tmp.setZ(600); } + + widgets.add(draggingStack); + + if (Minecraft.getInstance().screen instanceof RecipeViewingScreen) { + widgets.add(new RecipeViewingScreenDraggable()); + } + } + + private static class RecipeViewingScreenDraggable extends Widget implements DraggableStackProvider{ + @Nullable + @Override + public DraggableStack getHoveredStack(DraggingContext context, double mouseX, double mouseY) { + for (Widget widget : ((RecipeViewingScreen) Minecraft.getInstance().screen).getWidgets()) { + if (widget instanceof EntryWidget) { + if (widget.containsMouse(mouseX, mouseY)) { + return new DraggableStack() { + EntryStack stack = ((EntryWidget)widget).getCurrentEntry().copy().rewrap(); + + @Override + public EntryStack getStack() { + return stack; + } + + @Override + public void drag() { + + } + + @Override + public void release(boolean accepted) { + if (!accepted) { + context.registerRenderBackToPosition(this, () -> new Point(((EntryWidget) widget).getBounds().x - 8, ((EntryWidget) widget).getBounds().y - 8)); + } + } + }; + } + } + } + return null; + } + + @Override + public void render(PoseStack poseStack, int i, int j, float f) { + + } + + @Override + public List children() { + return Collections.emptyList(); + } } private Rectangle getSubsetsButtonBounds() { @@ -513,7 +540,7 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl @Override public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { - if (shouldReInit) { + if (shouldReload) { ENTRY_LIST_WIDGET.updateSearch(ScreenHelper.getSearchField().getText(), true); init(); } else { diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/CurrentDraggingStack.java b/runtime/src/main/java/me/shedaniel/rei/gui/CurrentDraggingStack.java new file mode 100644 index 000000000..6f464100e --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/gui/CurrentDraggingStack.java @@ -0,0 +1,125 @@ +package me.shedaniel.rei.gui; + +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.math.impl.PointHelper; +import me.shedaniel.rei.RoughlyEnoughItemsCore; +import me.shedaniel.rei.api.gui.drag.DraggableStack; +import me.shedaniel.rei.api.gui.drag.DraggableStackProvider; +import me.shedaniel.rei.api.gui.drag.DraggableStackVisitor; +import me.shedaniel.rei.api.gui.drag.DraggingContext; +import me.shedaniel.rei.api.gui.widgets.Widget; +import me.shedaniel.rei.gui.widget.LateRenderable; +import net.minecraft.client.gui.components.events.GuiEventListener; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; + +public class CurrentDraggingStack extends Widget implements LateRenderable, DraggingContext { + private DraggableStackProvider provider; + private DraggableStackVisitor visitor; + @Nullable + private DraggableEntry entry; + + public void set(DraggableStackProvider provider, DraggableStackVisitor visitor) { + this.provider = provider; + this.visitor = visitor; + } + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + if (entry != null && entry.dragging) { + if (!RoughlyEnoughItemsCore.isLeftModePressed) { + drop(); + return; + } + matrices.pushPose(); + matrices.translate(0, 0, 600); + entry.stack.render(matrices, new Rectangle(mouseX - 8, mouseY - 8, 16, 16), mouseX, mouseY, delta); + matrices.popPose(); + } + } + + @Override + public List children() { + return Collections.emptyList(); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + drop(); + DraggableStack hoveredStack = provider.getHoveredStack(this, mouseX, mouseY); + if (hoveredStack != null) { + entry = new DraggableEntry(hoveredStack, new Point(mouseX, mouseY)); + return true; + } + return false; + } + + @Override + public boolean mouseReleased(double d, double e, int i) { + return false; + } + + @Override + public boolean mouseDragged(double mouseX1, double mouseY1, int button, double mouseX2, double mouseY2) { + if (entry != null && !entry.dragging) { + Point startPoint = entry.start; + double xDistance = Math.abs(startPoint.x - mouseX1); + double yDistance = Math.abs(startPoint.y - mouseY1); + double requiredDistance = 4; + + if (xDistance * xDistance + yDistance * yDistance > requiredDistance * requiredDistance) { + entry.dragging = true; + entry.stack.drag(); + } + } + + return entry != null; + } + + private boolean drop() { + if (entry != null && entry.dragging) { + Optional acceptor = visitor.visitDraggedStack(entry.stack); + entry.stack.release(acceptor.isPresent()); + acceptor.ifPresent(a -> a.accept(entry.stack)); + entry = null; + return true; + } + + entry = null; + return false; + } + + @Override + @Nullable + public DraggableStack getCurrentStack() { + return entry != null && entry.dragging ? entry.stack : null; + } + + @Override + @Nullable + public Point getCurrentPosition() { + return isDraggingStack() ? PointHelper.ofMouse() : null; + } + + @Override + public void registerRenderBackToPosition(DraggableStack stack, Supplier position) { + + } + + private class DraggableEntry { + private final DraggableStack stack; + private final Point start; + private boolean dragging = false; + + private DraggableEntry(DraggableStack stack, Point start) { + this.stack = stack; + this.start = start; + } + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java b/runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java index 1e676e405..4f3ed051e 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java @@ -25,13 +25,13 @@ package me.shedaniel.rei.gui.credits; import com.google.common.collect.Lists; import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.architectury.platform.Platform; import me.shedaniel.clothconfig2.impl.EasingMethod; import me.shedaniel.rei.api.ConfigObject; import me.shedaniel.rei.api.util.ImmutableLiteralText; import me.shedaniel.rei.gui.TransformingScreen; import me.shedaniel.rei.gui.credits.CreditsEntryListWidget.TextCreditsItem; import me.shedaniel.rei.gui.credits.CreditsEntryListWidget.TranslationCreditsItem; -import net.fabricmc.loader.api.FabricLoader; import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.chat.NarratorChatListener; @@ -100,7 +100,7 @@ public class CreditsScreen extends Screen { ); }).collect(Collectors.toList()); int i = width - 80 - 6; - for (String line : String.format("§lRoughly Enough Items (v%s)\n§7Originally a fork for Almost Enough Items.\n\n§lLanguage Translation\n%s\n\n§lLicense\n§7Roughly Enough Items is licensed under MIT.", FabricLoader.getInstance().getModContainer("roughlyenoughitems").map(mod -> mod.getMetadata().getVersion().getFriendlyString()).orElse("Unknown"), "%translators%").split("\n")) + for (String line : String.format("§lRoughly Enough Items (v%s)\n§7Originally a fork for Almost Enough Items.\n\n§lLanguage Translation\n%s\n\n§lLicense\n§7Roughly Enough Items is licensed under MIT.", Platform.getMod("roughlyenoughitems").getVersion(), "%translators%").split("\n")) if (line.equalsIgnoreCase("%translators%")) { if (exception[0] != null) { entryListWidget.creditsAddEntry(new TextCreditsItem(new ImmutableLiteralText("Failed to get translators: " + exception[0].toString()))); diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java index 4eba1f245..e89023651 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java @@ -44,6 +44,9 @@ import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.api.*; import me.shedaniel.rei.api.gui.config.EntryPanelOrdering; +import me.shedaniel.rei.api.gui.drag.DraggableStack; +import me.shedaniel.rei.api.gui.drag.DraggableStackProvider; +import me.shedaniel.rei.api.gui.drag.DraggingContext; import me.shedaniel.rei.api.gui.widgets.Tooltip; import me.shedaniel.rei.api.gui.widgets.Widget; import me.shedaniel.rei.api.gui.widgets.WidgetWithBounds; @@ -79,6 +82,7 @@ import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableLong; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collections; @@ -92,7 +96,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; @ApiStatus.Internal -public class EntryListWidget extends WidgetWithBounds { +public class EntryListWidget extends WidgetWithBounds implements DraggableStackProvider { static final Comparator> ENTRY_NAME_COMPARER = Comparator.comparing(stack -> stack.asFormatStrippedText().getString()); static final Comparator> ENTRY_GROUP_COMPARER = Comparator.comparingInt(stack -> { if (stack.getType() == VanillaEntryTypes.ITEM) { @@ -180,6 +184,33 @@ public class EntryListWidget extends WidgetWithBounds { return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f)), (int) (bounds.getCenterY() - height * (entrySize / 2f)), width * entrySize, height * entrySize); } + @Override + @Nullable + public DraggableStack getHoveredStack(DraggingContext context, double mouseX, double mouseY) { + for (EntryListEntry entry : entries) { + if (!entry.getCurrentEntry().isEmpty() && entry.containsMouse(mouseX, mouseY)) { + return new DraggableStack() { + EntryStack stack = entry.getCurrentEntry().copy(); + + @Override + public EntryStack getStack() { + return stack; + } + + @Override + public void drag() { + } + + @Override + public void release(boolean accepted) { + context.registerRenderBackToPosition(this, () -> new Point(entry.getBounds().x - 8, entry.getBounds().y - 8)); + } + }; + } + } + return null; + } + @Override public boolean mouseScrolled(double double_1, double double_2, double double_3) { if (bounds.contains(double_1, double_2)) { diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryWidget.java b/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryWidget.java index a98f55b2f..4c15dd4d9 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryWidget.java @@ -244,7 +244,7 @@ public class EntryWidget extends Slot { return this; } - protected EntryStack getCurrentEntry() { + public EntryStack getCurrentEntry() { if (entryStacks.isEmpty()) return EntryStack.empty(); if (entryStacks.size() == 1) diff --git a/runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java b/runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java index 1fa2abd3a..4fb4a62ce 100644 --- a/runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/gui/widget/FavoritesListWidget.java @@ -37,23 +37,33 @@ import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWi import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.math.impl.PointHelper; -import me.shedaniel.rei.RoughlyEnoughItemsCore; -import me.shedaniel.rei.api.*; -import me.shedaniel.rei.api.gui.widgets.Widget; -import me.shedaniel.rei.api.gui.widgets.WidgetWithBounds; -import me.shedaniel.rei.api.ingredient.entry.BatchEntryRenderer; +import me.shedaniel.rei.api.ConfigManager; +import me.shedaniel.rei.api.ConfigObject; +import me.shedaniel.rei.api.REIHelper; +import me.shedaniel.rei.api.REIOverlay; import me.shedaniel.rei.api.favorites.FavoriteEntry; import me.shedaniel.rei.api.favorites.FavoriteEntryType; import me.shedaniel.rei.api.favorites.FavoriteMenuEntry; +import me.shedaniel.rei.api.gui.drag.DraggableStack; +import me.shedaniel.rei.api.gui.drag.DraggableStackProvider; +import me.shedaniel.rei.api.gui.drag.DraggableStackVisitor; +import me.shedaniel.rei.api.gui.drag.DraggingContext; +import me.shedaniel.rei.api.gui.widgets.Tooltip; +import me.shedaniel.rei.api.gui.widgets.Widget; +import me.shedaniel.rei.api.gui.widgets.WidgetWithBounds; +import me.shedaniel.rei.api.ingredient.EntryStack; +import me.shedaniel.rei.api.ingredient.entry.BatchEntryRenderer; import me.shedaniel.rei.api.ingredient.util.EntryStacks; import me.shedaniel.rei.api.registry.screen.ScreenRegistry; +import me.shedaniel.rei.api.util.CollectionUtils; import me.shedaniel.rei.api.util.ImmutableLiteralText; -import me.shedaniel.rei.api.gui.widgets.Tooltip; import me.shedaniel.rei.gui.ContainerScreenOverlay; import me.shedaniel.rei.gui.modules.Menu; import me.shedaniel.rei.gui.modules.MenuEntry; -import me.shedaniel.rei.impl.*; -import me.shedaniel.rei.api.util.CollectionUtils; +import me.shedaniel.rei.impl.Animator; +import me.shedaniel.rei.impl.ConfigManagerImpl; +import me.shedaniel.rei.impl.ConfigObjectImpl; +import me.shedaniel.rei.impl.ScreenHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.events.AbstractContainerEventHandler; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -77,7 +87,7 @@ import java.util.stream.Stream; import static me.shedaniel.rei.gui.widget.EntryListWidget.*; @ApiStatus.Internal -public class FavoritesListWidget extends WidgetWithBounds { +public class FavoritesListWidget extends WidgetWithBounds implements DraggableStackProvider, DraggableStackVisitor { protected final ScrollingContainer scrolling = new ScrollingContainer() { @Override public Rectangle getBounds() { @@ -102,7 +112,6 @@ public class FavoritesListWidget extends WidgetWithBounds { private final Int2ObjectMap removedEntries = new Int2ObjectLinkedOpenHashMap<>(); private List entriesList = Lists.newArrayList(); private List children = Lists.newArrayList(); - private Entry lastTouchedEntry = null; public final AddFavoritePanel favoritePanel = new AddFavoritePanel(this); public final ToggleAddFavoritePanelButton favoritePanelButton = new ToggleAddFavoritePanelButton(this); @@ -142,6 +151,71 @@ public class FavoritesListWidget extends WidgetWithBounds { return fullBounds; } + @Override + @Nullable + public DraggableStack getHoveredStack(DraggingContext context, double mouseX, double mouseY) { + Function apply = entry -> new DraggableStack() { + private FavoriteEntry favoriteEntry = entry.getEntry(); + private EntryStack stack = EntryStacks.of(favoriteEntry.getRenderer(false)).copy(); + + @Override + public EntryStack getStack() { + return stack; + } + + @Override + public void drag() { + entries.remove(entry.hashIgnoreAmount()); + applyNewFavorites(entries.values().stream() + .map(Entry::getEntry) + .collect(Collectors.toList())); + } + + @Override + public void release(boolean accepted) { + if (!accepted) { + drop(entry, this, favoriteEntry); + } + } + }; + if (innerBounds.contains(mouseX, mouseY)) { + for (Entry entry : entries.values()) { + if (entry.getWidget().containsMouse(mouseX, mouseY)) { + return apply.apply(entry); + } + } + } + if (favoritePanel.bounds.contains(mouseX, mouseY)) { + for (AddFavoritePanel.Row row : favoritePanel.rows.get()) { + if (row instanceof AddFavoritePanel.SectionEntriesRow) { + for (AddFavoritePanel.SectionEntriesRow.SectionFavoriteWidget widget : ((AddFavoritePanel.SectionEntriesRow) row).widgets) { + if (widget.containsMouse(mouseX, mouseY)) { + Entry entry = new Entry(widget.entry.copy(), entrySize()); + entry.size.setAs(entrySize() * 100); + return apply.apply(entry); + } + } + } + } + } + return null; + } + + @Override + public Optional visitDraggedStack(DraggableStack stack) { + if (innerBounds.contains(PointHelper.ofMouse())) { + return Optional.of(this::acceptDraggedStack); + } + return Optional.empty(); + } + + private void acceptDraggedStack(DraggableStack stack) { + FavoriteEntry favoriteEntry = FavoriteEntry.fromEntryStack(stack.getStack().copy()); + Entry entry = new Entry(favoriteEntry, entrySize()); + entry.size.setAs(entrySize() * 100); + drop(entry, stack, favoriteEntry); + } + @Override public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { if (fullBounds.isEmpty() || currentBounds.isEmpty()) @@ -149,19 +223,9 @@ public class FavoritesListWidget extends WidgetWithBounds { int entrySize = entrySize(); boolean fastEntryRendering = ConfigObject.getInstance().doesFastEntryRendering(); updateEntriesPosition(entry -> true); - if (lastTouchedEntry != null && lastTouchedEntry.dragged) { - lastTouchedEntry.x.setAs(mouseX - entrySize / 2); - lastTouchedEntry.y.setAs(mouseY - entrySize / 2 + (int) scrolling.scrollAmount); - - if (!RoughlyEnoughItemsCore.isLeftModePressed) - resetDraggedEntry(); - } for (Entry entry : entries.values()) { entry.update(delta); } - if (lastTouchedEntry != null && lastTouchedEntry.madeUp) { - lastTouchedEntry.update(delta); - } ObjectIterator removedEntriesIterator = removedEntries.values().iterator(); while (removedEntriesIterator.hasNext()) { Entry removedEntry = removedEntriesIterator.next(); @@ -176,7 +240,6 @@ public class FavoritesListWidget extends WidgetWithBounds { ScissorsHandler.INSTANCE.scissor(currentBounds); Stream entryStream = this.entriesList.stream() - .filter(entry -> lastTouchedEntry == null || entry != lastTouchedEntry.getWidget()) .filter(entry -> entry.getBounds().getMaxY() >= this.currentBounds.getY() && entry.getBounds().y <= this.currentBounds.getMaxY()); if (fastEntryRendering) { @@ -193,13 +256,6 @@ public class FavoritesListWidget extends WidgetWithBounds { ScissorsHandler.INSTANCE.removeLastScissor(); renderAddFavorite(matrices, mouseX, mouseY, delta); - - if (lastTouchedEntry != null) { - matrices.pushPose(); - matrices.translate(0, 0, 600); - lastTouchedEntry.widget.render(matrices, mouseX, mouseY, delta); - matrices.popPose(); - } } private void renderAddFavorite(PoseStack matrices, int mouseX, int mouseY, float delta) { @@ -209,15 +265,6 @@ 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) { - 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; return super.mouseDragged(mouseX, mouseY, int_1, double_3, double_4); @@ -305,11 +352,10 @@ public class FavoritesListWidget extends WidgetWithBounds { int width = innerBounds.width / entrySize; int currentX = 0; int currentY = 0; - int releaseIndex = lastTouchedEntry != null && lastTouchedEntry.dragged ? getReleaseIndex() : -2; + int releaseIndex = getReleaseIndex(); int slotIndex = 0; for (Entry entry : this.entries.values()) { - if (entry.dragged) continue; while (true) { int xPos = currentX * entrySize + innerBounds.x; int yPos = currentY * entrySize + innerBounds.y; @@ -340,14 +386,15 @@ public class FavoritesListWidget extends WidgetWithBounds { } public int getReleaseIndex() { - if (lastTouchedEntry != null && lastTouchedEntry.dragged && currentBounds.contains(PointHelper.ofMouse())) { + DraggingContext context = DraggingContext.getInstance(); + Point position = context.getCurrentPosition(); + if (context.isDraggingStack() && currentBounds.contains(position)) { int entrySize = entrySize(); int width = innerBounds.width / entrySize; int currentX = 0; int currentY = 0; List> entriesPoints = Lists.newArrayList(); for (Entry entry : this.entries.