From 542eb5154ebce387312ca3691f743b89e4aef99e Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sat, 27 Feb 2021 17:14:08 +0800 Subject: Remove depending on Cloth API, switching to architectury Signed-off-by: shedaniel --- .../me/shedaniel/rei/impl/ScreenRegistryImpl.java | 184 ++++++++++++++++----- 1 file changed, 145 insertions(+), 39 deletions(-) (limited to 'runtime/src/main/java/me/shedaniel/rei/impl/ScreenRegistryImpl.java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/ScreenRegistryImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/ScreenRegistryImpl.java index 7432de512..a2f933723 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/ScreenRegistryImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/ScreenRegistryImpl.java @@ -23,58 +23,81 @@ package me.shedaniel.rei.impl; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import com.mojang.blaze3d.platform.Window; import me.shedaniel.math.Rectangle; -import me.shedaniel.rei.api.registry.screens.ExclusionZones; -import me.shedaniel.rei.api.registry.screens.DisplayBoundsProvider; -import me.shedaniel.rei.api.registry.screens.OverlayDecider; -import me.shedaniel.rei.api.registry.screens.ScreenRegistry; +import me.shedaniel.rei.api.FocusedStackProvider; +import me.shedaniel.rei.api.ScreenClickAreaProvider; import me.shedaniel.rei.api.gui.config.DisplayPanelLocation; +import me.shedaniel.rei.api.ingredient.EntryStack; +import me.shedaniel.rei.api.ingredient.util.EntryStacks; +import me.shedaniel.rei.api.plugins.REIPlugin; +import me.shedaniel.rei.api.registry.screen.*; import me.shedaniel.rei.api.util.CollectionUtils; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.inventory.AbstractContainerMenu; +import org.apache.commons.lang3.mutable.Mutable; +import org.apache.commons.lang3.mutable.MutableObject; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; @ApiStatus.Internal @Environment(EnvType.CLIENT) public class ScreenRegistryImpl implements ScreenRegistry { - private List screenDisplayBoundsHandlers = Lists.newArrayList(); - private Map, List> deciderSortedCache = Maps.newHashMap(); + private Multimap, ClickArea> clickAreas = HashMultimap.create(); + private List focusedStackProviders = new ArrayList<>(); + private List deciders = new ArrayList<>(); + private Map, List> cache = new HashMap<>(); private ExclusionZones exclusionZones; - private Class tempScreen; + private Class tmpScreen; @Override - public List getSortedOverlayDeciders(Class screenClass) { - List possibleCached = deciderSortedCache.get(screenClass); + public void acceptPlugin(REIPlugin plugin) { + plugin.registerScreens(this); + plugin.registerExclusionZones(exclusionZones()); + } + + @Override + public List getDeciders(Class screenClass) { + List possibleCached = cache.get(screenClass); if (possibleCached != null) { return possibleCached; } - tempScreen = screenClass; - List deciders = CollectionUtils.filter(screenDisplayBoundsHandlers, this::filterResponsible); - deciderSortedCache.put(screenClass, deciders); + tmpScreen = screenClass; + List deciders = CollectionUtils.filterToList(this.deciders, this::filterResponsible); + cache.put(screenClass, deciders); + tmpScreen = null; return deciders; } + private boolean filterResponsible(OverlayDecider handler) { + return handler.isHandingScreen(tmpScreen); + } + @Override - public List getAllOverlayDeciders() { - return Collections.unmodifiableList(screenDisplayBoundsHandlers); + public List getDeciders() { + return Collections.unmodifiableList(deciders); } @Override - public Rectangle getOverlayBounds(DisplayPanelLocation location, T screen) { + public Rectangle getOverlayBounds(DisplayPanelLocation location, T screen) { Window window = Minecraft.getInstance().getWindow(); int scaledWidth = window.getGuiScaledWidth(); int scaledHeight = window.getGuiScaledHeight(); - for (OverlayDecider decider : getSortedOverlayDeciders(screen.getClass())) { + for (OverlayDecider decider : getDeciders(screen.getClass())) { if (decider instanceof DisplayBoundsProvider) { Rectangle containerBounds = ((DisplayBoundsProvider) decider).getScreenBounds(screen); if (location == DisplayPanelLocation.LEFT) { @@ -89,16 +112,35 @@ public class ScreenRegistryImpl implements ScreenRegistry { return new Rectangle(); } - private boolean filterResponsible(OverlayDecider handler) { - return handler.isHandingScreen(tempScreen); + @Nullable + @Override + public EntryStack getFocusedStack(T screen) { + for (FocusedStackProvider provider : focusedStackProviders) { + InteractionResultHolder> result = Objects.requireNonNull(provider.provide(screen)); + if (result.getResult() == InteractionResult.SUCCESS) { + if (result != null && !result.getObject().isEmpty()) + return result.getObject(); + return null; + } else if (result.getResult() == InteractionResult.FAIL) + return null; + } + + return null; + } + + @Override + public void registerDecider(OverlayDecider decider) { + deciders.add(decider); + deciders.sort(Comparator.reverseOrder()); + clickAreas.clear(); + cache.clear(); + tmpScreen = null; } @Override - public void registerHandler(OverlayDecider decider) { - screenDisplayBoundsHandlers.add(decider); - screenDisplayBoundsHandlers.sort(Comparator.reverseOrder()); - deciderSortedCache.clear(); - tempScreen = null; + public void registerFocusedStack(FocusedStackProvider provider) { + focusedStackProviders.add(provider); + focusedStackProviders.sort(Comparator.reverseOrder()); } @Override @@ -106,18 +148,82 @@ public class ScreenRegistryImpl implements ScreenRegistry { return exclusionZones; } - @ApiStatus.Internal - public void setExclusionZones(ExclusionZones exclusionZones) { - registerHandler(exclusionZones); - this.exclusionZones = exclusionZones; + @Override + public > void registerContainerClickArea(ScreenClickAreaProvider provider, Class screenClass, ResourceLocation... categories) { + registerClickArea(screen -> { + Rectangle rectangle = provider.provide(screen).clone(); + rectangle.translate(screen.leftPos, screen.topPos); + return rectangle; + }, screenClass, categories); + } + + @Override + public void registerClickArea(Class screenClass, ClickArea area) { + clickAreas.put(screenClass, area); + } + + @Override + @Nullable + public Set handleClickArea(Class screenClass, ClickArea.ClickAreaContext context) { + Mutable> categories = new MutableObject<>(null); + for (ClickArea area : this.clickAreas.get(screenClass)) { + ClickArea.Result result = ((ClickArea) area).handle(context); + + if (result.isSuccessful()) { + if (categories.getValue() == null) { + categories.setValue(new LinkedHashSet<>()); + } + result.getCategories().collect(Collectors.toCollection(categories::getValue)); + } + } + return categories.getValue(); } - @ApiStatus.Internal @Override - public void resetData() { - screenDisplayBoundsHandlers.clear(); - deciderSortedCache.clear(); - tempScreen = null; - setExclusionZones(new ExclusionZonesImpl()); + public void startReload() { + clickAreas.clear(); + deciders.clear(); + cache.clear(); + focusedStackProviders.clear(); + tmpScreen = null; + + registerDefault(); + } + + private void registerDefault() { + registerDecider(this.exclusionZones = new ExclusionZonesImpl()); + registerDecider(new OverlayDecider() { + @Override + public boolean isHandingScreen(Class screen) { + return true; + } + + @Override + public InteractionResult shouldScreenBeOverlaid(Class screen) { + return AbstractContainerScreen.class.isAssignableFrom(screen) ? InteractionResult.SUCCESS : InteractionResult.PASS; + } + + @Override + public float getPriority() { + return -10; + } + }); + registerFocusedStack(new FocusedStackProvider() { + @Override + @NotNull + public InteractionResultHolder> provide(Screen screen) { + if (screen instanceof AbstractContainerScreen) { + AbstractContainerScreen containerScreen = (AbstractContainerScreen) screen; + if (containerScreen.hoveredSlot != null && !containerScreen.hoveredSlot.getItem().isEmpty()) + return InteractionResultHolder.success(EntryStacks.of(containerScreen.hoveredSlot.getItem())); + } + return InteractionResultHolder.pass(EntryStack.empty()); + } + + @Override + public double getPriority() { + return -10.0; + } + }); } } -- cgit