/* * This file is licensed under the MIT License, part of Roughly Enough Items. * Copyright (c) 2018, 2019, 2020 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package me.shedaniel.rei.impl; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.gui.config.DisplayPanelLocation; import me.shedaniel.rei.api.registry.screen.ExclusionZones; import me.shedaniel.rei.api.registry.screen.ScreenRegistry; 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.world.InteractionResult; import org.jetbrains.annotations.ApiStatus; import java.util.Collection; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.function.Supplier; @ApiStatus.Internal @Environment(EnvType.CLIENT) public class ExclusionZonesImpl implements ExclusionZones { private static final Comparator RECTANGLE_COMPARER = Comparator.comparingLong(Rectangle::hashCode); private long lastArea = -1; private Multimap, Supplier>> list = HashMultimap.create(); @Override public boolean isHandingScreen(Class screen) { return Screen.class.isAssignableFrom(screen); } @Override public float getPriority() { return -5f; } @Override public InteractionResult isInZone(double mouseX, double mouseY) { Class screenClass = Minecraft.getInstance().screen.getClass(); for (Map.Entry, Collection>>> collectionEntry : list.asMap().entrySet()) { if (collectionEntry.getKey().isAssignableFrom(screenClass)) { for (Supplier> listSupplier : collectionEntry.getValue()) { for (Rectangle zone : listSupplier.get()) { if (zone.contains(mouseX, mouseY)) { return InteractionResult.FAIL; } } } } } return InteractionResult.PASS; } @Override public boolean shouldRecalculateArea(DisplayPanelLocation location, Rectangle rectangle) { long current = currentHashCode(location); if (lastArea == current) return false; lastArea = current; return true; } private long currentHashCode(DisplayPanelLocation location) { return areasHashCode(ScreenRegistry.getInstance().getOverlayBounds(location, Minecraft.getInstance().screen), getExclusionZones(Minecraft.getInstance().screen.getClass(), false)); } @Override public List getExclusionZones(Class currentScreenClass, boolean sort) { List rectangles = Lists.newArrayList(); for (Map.Entry, Collection>>> collectionEntry : list.asMap().entrySet()) { if (collectionEntry.getKey().isAssignableFrom(currentScreenClass)) { for (Supplier> listSupplier : collectionEntry.getValue()) { rectangles.addAll(listSupplier.get()); } } } if (sort) { rectangles.sort(RECTANGLE_COMPARER); } return rectangles; } @Override public int getZonesCount() { return list.size(); } @Override public void register(Class screenClass, Supplier> supplier) { list.put(screenClass, supplier); } private long areasHashCode(Rectangle rectangle, List exclusionZones) { int hashCode = 31 + (rectangle == null ? 0 : rectangle.hashCode()); for (Rectangle e : exclusionZones) hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode()); return hashCode; } }