diff options
Diffstat (limited to 'runtime-engine/favorites/src/main/java')
3 files changed, 429 insertions, 0 deletions
diff --git a/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/favorites/DelegatingFavoriteEntryProviderImpl.java b/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/favorites/DelegatingFavoriteEntryProviderImpl.java new file mode 100644 index 000000000..97ede0acf --- /dev/null +++ b/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/favorites/DelegatingFavoriteEntryProviderImpl.java @@ -0,0 +1,125 @@ +/* + * 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.impl.client.favorites; + +import com.mojang.serialization.DataResult; +import me.shedaniel.rei.api.client.favorites.FavoriteEntry; +import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry; +import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.impl.ClientInternals; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; + +import java.util.Collection; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Supplier; + +public class DelegatingFavoriteEntryProviderImpl implements ClientInternals.DelegatingFavoriteEntryProvider { + @Override + public FavoriteEntry delegate(Supplier<DataResult<FavoriteEntry>> result, Supplier<CompoundTag> tag) { + return new DelegatedFavoriteEntry(result, tag); + } + + private static class DelegatedFavoriteEntry extends FavoriteEntry { + private final Supplier<DataResult<FavoriteEntry>> supplier; + private final Supplier<CompoundTag> toJson; + private FavoriteEntry value = null; + + public DelegatedFavoriteEntry(Supplier<DataResult<FavoriteEntry>> supplier, Supplier<CompoundTag> toJson) { + this.supplier = supplier; + this.toJson = toJson; + } + + @Override + public FavoriteEntry getUnwrapped() { + synchronized (this) { + if (this.value == null) { + DataResult<FavoriteEntry> result = supplier.get(); + this.value = result.getOrThrow(false, error -> {}); + } + } + return Objects.requireNonNull(value).getUnwrapped(); + } + + @Override + public UUID getUuid() { + return getUnwrapped().getUuid(); + } + + @Override + public boolean isInvalid() { + try { + return getUnwrapped().isInvalid(); + } catch (Exception e) { + return true; + } + } + + @Override + public Renderer getRenderer(boolean showcase) { + return getUnwrapped().getRenderer(showcase); + } + + @Override + public boolean doAction(int button) { + return getUnwrapped().doAction(button); + } + + @Override + public Optional<Supplier<Collection<FavoriteMenuEntry>>> getMenuEntries() { + return getUnwrapped().getMenuEntries(); + } + + @Override + public long hashIgnoreAmount() { + return getUnwrapped().hashIgnoreAmount(); + } + + @Override + public FavoriteEntry copy() { + return FavoriteEntry.delegateResult(supplier, toJson); + } + + @Override + public ResourceLocation getType() { + return getUnwrapped().getType(); + } + + @Override + public CompoundTag save(CompoundTag tag) { + if (toJson == null) { + return getUnwrapped().save(tag); + } + + return tag.merge(toJson.get()); + } + + @Override + public boolean isSame(FavoriteEntry other) { + return getUnwrapped().isSame(other.getUnwrapped()); + } + } +} diff --git a/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java b/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java new file mode 100644 index 000000000..39de487d9 --- /dev/null +++ b/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/favorites/FavoriteEntryTypeRegistryImpl.java @@ -0,0 +1,150 @@ +/* + * 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.impl.client.favorites; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import me.shedaniel.rei.api.client.config.ConfigManager; +import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.favorites.FavoriteEntry; +import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; +import me.shedaniel.rei.api.client.favorites.SystemFavoriteEntryProvider; +import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.common.registry.ReloadStage; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesEntriesManager; +import me.shedaniel.rei.impl.common.InternalLogger; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@ApiStatus.Internal +public class FavoriteEntryTypeRegistryImpl implements FavoriteEntryType.Registry { + private final BiMap<ResourceLocation, FavoriteEntryType<?>> registry = HashBiMap.create(); + private final Map<Component, FavoriteEntryType.Section> sections = Maps.newConcurrentMap(); + private final List<FavoriteEntryType.Section> sectionsList = Lists.newCopyOnWriteArrayList(); + + @Override + public ReloadStage getStage() { + return ReloadStage.START; + } + + @Override + public void acceptPlugin(REIClientPlugin plugin) { + plugin.registerFavorites(this); + } + + @Override + public void register(ResourceLocation id, FavoriteEntryType<?> type) { + this.registry.put(id, type); + InternalLogger.getInstance().debug("Added favorite entry type [%s]: %s", id, type); + } + + @Override + public <A extends FavoriteEntry> @Nullable FavoriteEntryType<A> get(ResourceLocation id) { + return (FavoriteEntryType<A>) this.registry.get(id); + } + + @Override + @Nullable + public ResourceLocation getId(FavoriteEntryType<?> type) { + return this.registry.inverse().get(type); + } + + @Override + public FavoriteEntryType.Section getOrCrateSection(Component text) { + return sections.computeIfAbsent(text, $ -> { + SectionImpl section = new SectionImpl($); + sectionsList.add(section); + return section; + }); + } + + @Override + public Iterable<FavoriteEntryType.Section> sections() { + return sectionsList; + } + + @Override + public <A extends FavoriteEntry> void registerSystemFavorites(SystemFavoriteEntryProvider<A> provider) { + } + + @Override + public void startReload() { + this.registry.clear(); + this.sections.clear(); + this.sectionsList.clear(); + } + + @Override + public void endReload() { + if (ConfigObject.getInstance().isFavoritesEnabled()) { + FavoritesEntriesManager.INSTANCE.getConfigFavoriteEntries().removeIf(FavoriteEntry::isInvalid); + FavoritesEntriesManager.INSTANCE.getConfigHiddenFavoriteEntries().removeIf(FavoriteEntry::isInvalid); + + ConfigManager.getInstance().saveConfig(); + } + + InternalLogger.getInstance().debug("Registered %d favorite entry types", registry.size()); + } + + private static class SectionImpl implements FavoriteEntryType.Section { + private final Component text; + private final List<CompoundEntry> entries = new ArrayList<>(); + + public SectionImpl(Component text) { + this.text = text; + } + + @Override + public void add(boolean defaultFavorited, FavoriteEntry... entries) { + this.entries.addAll(CollectionUtils.map(entries, + entry -> new CompoundEntry(entry, defaultFavorited))); + } + + @Override + public Component getText() { + return text; + } + + @Override + public List<FavoriteEntry> getEntries() { + return CollectionUtils.map(entries, CompoundEntry::entry); + } + + @Override + public List<FavoriteEntry> getDefaultEntries() { + return CollectionUtils.filterAndMap(entries, CompoundEntry::defaultFavorited, CompoundEntry::entry); + } + + public record CompoundEntry(FavoriteEntry entry, boolean defaultFavorited) {} + } +} diff --git a/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/FavoritesEntriesManager.java b/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/FavoritesEntriesManager.java new file mode 100644 index 000000000..2f92bc197 --- /dev/null +++ b/runtime-engine/favorites/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/FavoritesEntriesManager.java @@ -0,0 +1,154 @@ +/* + * 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.impl.client.gui.widget.favorites; + +import me.shedaniel.rei.api.client.REIRuntime; +import me.shedaniel.rei.api.client.config.ConfigManager; +import me.shedaniel.rei.api.client.favorites.FavoriteEntry; +import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; +import me.shedaniel.rei.api.client.overlay.OverlayListWidget; +import me.shedaniel.rei.api.client.overlay.ScreenOverlay; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.client.config.ConfigManagerInternal; +import me.shedaniel.rei.impl.client.favorites.MutableFavoritesList; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class FavoritesEntriesManager { + public static final FavoritesEntriesManager INSTANCE = new FavoritesEntriesManager(); + + public List<FavoriteEntry> getConfigFavoriteEntries() { + ConfigManagerInternal manager = ConfigManagerInternal.getInstance(); + return (List<FavoriteEntry>) manager.get("basics.favorites"); + } + + public List<FavoriteEntry> getConfigHiddenFavoriteEntries() { + ConfigManagerInternal manager = ConfigManagerInternal.getInstance(); + return (List<FavoriteEntry>) manager.get("basics.hiddenFavorites"); + } + + private Stream<FavoriteEntry> getDefaultFavorites() { + return StreamSupport.stream(FavoriteEntryType.registry().sections().spliterator(), false) + .flatMap(section -> section.getDefaultEntries().stream()); + } + + public List<FavoriteEntry> getFavorites() { + List<FavoriteEntry> defaultFavorites = getDefaultFavorites().collect(Collectors.toList()); + defaultFavorites.removeAll(getConfigHiddenFavoriteEntries()); + + List<FavoriteEntry> favorites = new ArrayList<>(getConfigFavoriteEntries()); + defaultFavorites.removeAll(favorites); + favorites.addAll(0, defaultFavorites); + favorites.removeIf(FavoriteEntry::isInvalid); + return favorites; + } + + public void remove(FavoriteEntry entry) { + getConfigFavoriteEntries().remove(entry); + if (getDefaultFavorites().anyMatch(e -> e.equals(entry)) && !getConfigHiddenFavoriteEntries().contains(entry)) { + getConfigHiddenFavoriteEntries().add(entry); + } + + ConfigManager.getInstance().saveConfig(); + REIRuntime.getInstance().getOverlay().flatMap(ScreenOverlay::getFavoritesList).ifPresent(OverlayListWidget::queueReloadSearch); + } + + public void add(FavoriteEntry entry) { + List<FavoriteEntry> defaultFavorites = getDefaultFavorites().toList(); + + getConfigFavoriteEntries().remove(entry); + if (CollectionUtils.anyMatch(defaultFavorites, e -> e.equals(entry)) && !getConfigHiddenFavoriteEntries().contains(entry)) { + getConfigHiddenFavoriteEntries().add(entry); + } + + for (int i = defaultFavorites.size() - 1; i >= 0; i--) { + FavoriteEntry e = defaultFavorites.get(i); + if (!getConfigFavoriteEntries().contains(e) && !getConfigHiddenFavoriteEntries().contains(e)) { + getConfigFavoriteEntries().add(0, e); + } + } + + getConfigHiddenFavoriteEntries().remove(entry); + if (!CollectionUtils.anyMatch(defaultFavorites, e -> e.equals(entry))) { + getConfigFavoriteEntries().add(entry); + } + + ConfigManager.getInstance().saveConfig(); + REIRuntime.getInstance().getOverlay().flatMap(ScreenOverlay::getFavoritesList).ifPresent(OverlayListWidget::queueReloadSearch); + } + + public void setEntries(List<FavoriteEntry> entries) { + List<FavoriteEntry> defaultFavorites = getDefaultFavorites().toList(); + List<FavoriteEntry> hiddenDefaultFavorites = new ArrayList<>(defaultFavorites); + hiddenDefaultFavorites.removeAll(entries); + getConfigHiddenFavoriteEntries().clear(); + getConfigHiddenFavoriteEntries().addAll(hiddenDefaultFavorites); + getConfigFavoriteEntries().clear(); + getConfigFavoriteEntries().addAll(entries); + + ConfigManager.getInstance().saveConfig(); + REIRuntime.getInstance().getOverlay().flatMap(ScreenOverlay::getFavoritesList).ifPresent(OverlayListWidget::queueReloadSearch); + } + + public List<FavoriteEntry> asListView() { + return new ListView(); + } + + private class ListView extends AbstractList<FavoriteEntry> implements MutableFavoritesList { + @Override + public FavoriteEntry get(int index) { + return getFavorites().get(index); + } + + @Override + public int size() { + return getFavorites().size(); + } + + @Override + public void add(int index, FavoriteEntry entry) { + FavoritesEntriesManager.this.add(entry); + } + + @Override + public boolean remove(Object o) { + if (o instanceof FavoriteEntry) { + FavoritesEntriesManager.this.remove((FavoriteEntry) o); + return true; + } else { + return false; + } + } + + @Override + public void setAll(List<FavoriteEntry> entries) { + FavoritesEntriesManager.this.setEntries(entries); + } + } +} |
