aboutsummaryrefslogtreecommitdiff
path: root/runtime-engine/configs/src
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2022-07-28 01:39:41 +0800
committershedaniel <daniel@shedaniel.me>2022-08-26 10:52:28 +0900
commit9954713e457a5a5d80025432961b56ab0003bbb0 (patch)
treed26b3a09f824e58edd2ad7df39e6c4f48fcc6bb9 /runtime-engine/configs/src
parentc85b3d49f6d88e7e92b06bacca1ce93db7b75fd0 (diff)
downloadRoughlyEnoughItems-9954713e457a5a5d80025432961b56ab0003bbb0.tar.gz
RoughlyEnoughItems-9954713e457a5a5d80025432961b56ab0003bbb0.tar.bz2
RoughlyEnoughItems-9954713e457a5a5d80025432961b56ab0003bbb0.zip
More work on config module
Diffstat (limited to 'runtime-engine/configs/src')
-rw-r--r--runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java59
-rw-r--r--runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java10
-rw-r--r--runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/RecipeScreenTypeEntry.java1
-rw-r--r--runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java118
-rw-r--r--runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/UncertainDisplayViewingScreen.java304
-rw-r--r--runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/gui/credits/CreditsEntryListWidget.java216
-rw-r--r--runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/gui/credits/CreditsScreen.java165
7 files changed, 820 insertions, 53 deletions
diff --git a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java
index 2970c5b62..df956d185 100644
--- a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java
+++ b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java
@@ -23,7 +23,6 @@
package me.shedaniel.rei.impl.client.config;
-import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mojang.blaze3d.platform.InputConstants;
@@ -51,6 +50,7 @@ import me.shedaniel.rei.api.client.REIRuntime;
import me.shedaniel.rei.api.client.config.ConfigManager;
import me.shedaniel.rei.api.client.config.addon.ConfigAddonRegistry;
import me.shedaniel.rei.api.client.config.entry.EntryStackProvider;
+import me.shedaniel.rei.api.client.entry.filtering.FilteringRule;
import me.shedaniel.rei.api.client.favorites.FavoriteEntry;
import me.shedaniel.rei.api.client.gui.config.CheatingMode;
import me.shedaniel.rei.api.client.gui.config.DisplayScreenType;
@@ -58,14 +58,11 @@ import me.shedaniel.rei.api.client.gui.config.SyntaxHighlightingMode;
import me.shedaniel.rei.api.client.overlay.ScreenOverlay;
import me.shedaniel.rei.api.client.registry.entry.EntryRegistry;
import me.shedaniel.rei.api.common.entry.EntryStack;
-import me.shedaniel.rei.api.common.util.CollectionUtils;
import me.shedaniel.rei.api.common.util.ImmutableTextComponent;
-import me.shedaniel.rei.impl.client.REIRuntimeImpl;
+import me.shedaniel.rei.impl.Internals;
import me.shedaniel.rei.impl.client.config.addon.ConfigAddonRegistryImpl;
import me.shedaniel.rei.impl.client.config.entries.*;
-import me.shedaniel.rei.impl.client.entry.filtering.FilteringRule;
import me.shedaniel.rei.impl.client.entry.filtering.rules.ManualFilteringRule;
-import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl;
import me.shedaniel.rei.impl.client.gui.credits.CreditsScreen;
import me.shedaniel.rei.impl.client.gui.performance.entry.PerformanceEntry;
import me.shedaniel.rei.impl.common.InternalLogger;
@@ -88,7 +85,6 @@ import org.jetbrains.annotations.ApiStatus;
import java.lang.reflect.Field;
import java.util.*;
-import java.util.function.Consumer;
import java.util.function.Supplier;
import static me.shedaniel.autoconfig.util.Utils.getUnsafely;
@@ -123,18 +119,9 @@ public class ConfigManagerImpl implements ConfigManagerInternal {
guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) ->
Collections.singletonList(new SearchFilterSyntaxHighlightingEntry(new TranslatableComponent(i13n), getUnsafely(field, config, SyntaxHighlightingMode.COLORFUL), getUnsafely(field, defaults), type -> setUnsafely(field, config, type)))
, (field) -> field.getType() == SyntaxHighlightingMode.class, ConfigObjectImpl.UseSpecialSearchFilterSyntaxHighlightingScreen.class);
- guiRegistry.registerAnnotationProvider((i13n, field, config, defaults, guiProvider) -> {
- List<EntryStack<?>> value = CollectionUtils.map(Utils.<List<EntryStackProvider<?>>>getUnsafely(field, config, new ArrayList<>()), EntryStackProvider::provide);
- List<EntryStack<?>> defaultValue = CollectionUtils.map(Utils.<List<EntryStackProvider<?>>>getUnsafely(field, defaults), EntryStackProvider::provide);
- Consumer<List<EntryStack<?>>> saveConsumer = (newValue) -> {
- setUnsafely(field, config, CollectionUtils.map(newValue, EntryStackProvider::ofStack));
- };
- return REIRuntime.getInstance().getPreviousContainerScreen() == null || Minecraft.getInstance().getConnection() == null || Minecraft.getInstance().getConnection().getRecipeManager() == null ?
- Collections.singletonList(new NoFilteringEntry(220, value, defaultValue, saveConsumer))
- :
- Collections.singletonList(new FilteringEntry(220, value, ((ConfigObjectImpl.Advanced.Filtering) config).filteringRules, defaultValue, saveConsumer, list -> ((ConfigObjectImpl.Advanced.Filtering) config).filteringRules = Lists.newArrayList(list)));
- }
- , (field) -> field.getType() == List.class, ConfigObjectImpl.UseFilteringScreen.class);
+ for (SystemSetup setup : Internals.resolveServices(SystemSetup.class)) {
+ setup.setup(guiRegistry);
+ }
InternalLogger.getInstance().info("Config loaded");
saveConfig();
}
@@ -234,32 +221,6 @@ public class ConfigManagerImpl implements ConfigManagerInternal {
}
});
- // FilteringRule
- builder.registerSerializer(FilteringRule.class, (value, marshaller) -> {
- try {
- return marshaller.serialize(FilteringRule.save(value, new CompoundTag()));
- } catch (Exception e) {
- e.printStackTrace();
- return JsonNull.INSTANCE;
- }
- });
- builder.registerDeserializer(Tag.class, FilteringRule.class, (value, marshaller) -> {
- try {
- return FilteringRule.read((CompoundTag) value);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- });
- builder.registerDeserializer(String.class, FilteringRule.class, (value, marshaller) -> {
- try {
- return FilteringRule.read(TagParser.parseTag(value));
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- });
-
// FavoriteEntry
builder.registerSerializer(FavoriteEntry.class, (value, marshaller) -> {
try {
@@ -282,6 +243,10 @@ public class ConfigManagerImpl implements ConfigManagerInternal {
}
});
+ for (SystemSetup setup : Internals.resolveServices(SystemSetup.class)) {
+ setup.setup(builder);
+ }
+
return builder.build();
}
@@ -295,7 +260,7 @@ public class ConfigManagerImpl implements ConfigManagerInternal {
@Override
public void saveConfig() {
- if (getConfig().getFilteringRules().stream().noneMatch(filteringRule -> filteringRule instanceof ManualFilteringRule)) {
+ if (getConfig().getFilteringRules().stream().noneMatch(FilteringRule::isManual)) {
getConfig().getFilteringRules().add(new ManualFilteringRule());
}
AutoConfig.getConfigHolder(ConfigObjectImpl.class).registerLoadListener((configHolder, configObject) -> {
@@ -427,8 +392,8 @@ public class ConfigManagerImpl implements ConfigManagerInternal {
saveConfig();
EntryRegistry.getInstance().refilter();
REIRuntime.getInstance().getOverlay().ifPresent(ScreenOverlay::queueReloadOverlay);
- if (REIRuntimeImpl.getSearchField() != null) {
- ScreenOverlayImpl.getEntryListWidget().updateSearch(REIRuntimeImpl.getSearchField().getText(), true);
+ if (REIRuntime.getInstance().getSearchTextField() != null) {
+ REIRuntime.getInstance().getOverlay().ifPresent(ScreenOverlay::queueReloadSearch);
}
}).build();
});
diff --git a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
index d0b63a1ff..ae2008f0a 100644
--- a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
+++ b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
@@ -33,10 +33,10 @@ import me.shedaniel.clothconfig2.api.Modifier;
import me.shedaniel.clothconfig2.api.ModifierKeyCode;
import me.shedaniel.rei.api.client.config.ConfigObject;
import me.shedaniel.rei.api.client.config.entry.EntryStackProvider;
+import me.shedaniel.rei.api.client.entry.filtering.FilteringRule;
import me.shedaniel.rei.api.client.favorites.FavoriteEntry;
import me.shedaniel.rei.api.client.gui.config.*;
-import me.shedaniel.rei.impl.client.entry.filtering.FilteringRule;
-import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesEntriesManager;
+import me.shedaniel.rei.impl.ClientInternals;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
@@ -341,7 +341,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
@Override
public List<FavoriteEntry> getFavoriteEntries() {
- return FavoritesEntriesManager.INSTANCE.asListView();
+ return ClientInternals.getFavoritesEntriesList();
}
public List<FavoriteEntry> getConfigFavoriteEntries() {
@@ -368,7 +368,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
}
@ApiStatus.Internal
- public List<FilteringRule<?>> getFilteringRules() {
+ public List<FilteringRule> getFilteringRules() {
return advanced.filtering.filteringRules;
}
@@ -652,7 +652,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
public static class Filtering {
@UseFilteringScreen private List<EntryStackProvider<?>> filteredStacks = new ArrayList<>();
public boolean shouldFilterDisplays = true;
- @ConfigEntry.Gui.Excluded public List<FilteringRule<?>> filteringRules = new ArrayList<>();
+ @ConfigEntry.Gui.Excluded public List<FilteringRule> filteringRules = new ArrayList<>();
}
}
}
diff --git a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/RecipeScreenTypeEntry.java b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/RecipeScreenTypeEntry.java
index bc37f2a35..514f8bd3f 100644
--- a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/RecipeScreenTypeEntry.java
+++ b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/RecipeScreenTypeEntry.java
@@ -28,7 +28,6 @@ import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.vertex.PoseStack;
import me.shedaniel.clothconfig2.gui.entries.TooltipListEntry;
import me.shedaniel.rei.api.client.gui.config.DisplayScreenType;
-import me.shedaniel.rei.impl.client.gui.screen.UncertainDisplayViewingScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.chat.NarratorChatListener;
import net.minecraft.client.gui.components.AbstractWidget;
diff --git a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java
new file mode 100644
index 000000000..45ab4ef4e
--- /dev/null
+++ b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/ReloadPluginsEntry.java
@@ -0,0 +1,118 @@
+/*
+ * 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.config.entries;
+
+import com.google.common.collect.ImmutableList;
+import com.mojang.blaze3d.platform.Window;
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
+import me.shedaniel.rei.RoughlyEnoughItemsCore;
+import me.shedaniel.rei.RoughlyEnoughItemsCoreClient;
+import me.shedaniel.rei.api.client.search.SearchProvider;
+import me.shedaniel.rei.api.common.plugins.PluginManager;
+import me.shedaniel.rei.impl.client.gui.screen.ConfigReloadingScreen;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.chat.NarratorChatListener;
+import net.minecraft.client.gui.components.AbstractWidget;
+import net.minecraft.client.gui.components.Button;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.narration.NarratableEntry;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.util.Unit;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.List;
+import java.util.Optional;
+
+@ApiStatus.Internal
+public class ReloadPluginsEntry extends AbstractConfigListEntry<Unit> {
+ private int width;
+ private AbstractWidget reloadPluginsButton = new Button(0, 0, 0, 20, NarratorChatListener.NO_TITLE, button -> {
+ RoughlyEnoughItemsCore.PERFORMANCE_LOGGER.clear();
+ RoughlyEnoughItemsCoreClient.reloadPlugins(null, null);
+ }) {
+ @Override
+ public void render(PoseStack matrices, int mouseX, int mouseY, float delta) {
+ if (PluginManager.areAnyReloading()) {
+ Screen screen = Minecraft.getInstance().screen;
+ Minecraft.getInstance().setScreen(new ConfigReloadingScreen(new TranslatableComponent("text.rei.config.is.reloading"), PluginManager::areAnyReloading, () -> Minecraft.getInstance().setScreen(screen)));
+ } else {
+ super.render(matrices, mouseX, mouseY, delta);
+ }
+ }
+ };
+ private AbstractWidget reloadSearchButton = new Button(0, 0, 0, 20, NarratorChatListener.NO_TITLE, button -> {
+ SearchProvider.getInstance().clearCache();
+ });
+ private List<AbstractWidget> children = ImmutableList.of(reloadPluginsButton, reloadSearchButton);
+
+ public ReloadPluginsEntry(int width) {
+ super(NarratorChatListener.NO_TITLE, false);
+ this.width = width;
+ reloadPluginsButton.setMessage(new TranslatableComponent("text.rei.reload_config"));
+ reloadSearchButton.setMessage(new TranslatableComponent("text.rei.reload_search"));
+ }
+
+ @Override
+ public Unit getValue() {
+ return Unit.INSTANCE;
+ }
+
+ @Override
+ public Optional<Unit> getDefaultValue() {
+ return Optional.of(Unit.INSTANCE);
+ }
+
+ @Override
+ public void save() {
+
+ }
+
+ @Override
+ public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isSelected, float delta) {
+ super.render(matrices, index, y, x, entryWidth, entryHeight, mouseX, mouseY, isSelected, delta);
+ Window window = Minecraft.getInstance().getWindow();
+ this.reloadPluginsButton.active = this.isEditable();
+ this.reloadPluginsButton.y = y;
+ this.reloadPluginsButton.setWidth(width / 2 - 2);
+ this.reloadPluginsButton.x = x + entryWidth / 2 - width / 2;
+ this.reloadPluginsButton.render(matrices, mouseX, mouseY, delta);
+ this.reloadSearchButton.active = this.isEditable() && SearchProvider.getInstance().hasCache();
+ this.reloadSearchButton.y = y;
+ this.reloadSearchButton.setWidth(width / 2 - 2);
+ this.reloadSearchButton.x = x + entryWidth / 2 + 2;
+ this.reloadSearchButton.render(matrices, mouseX, mouseY, delta);
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return children;
+ }
+
+ @Override
+ public List<? extends NarratableEntry> narratables() {
+ return children;
+ }
+}
diff --git a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/UncertainDisplayViewingScreen.java b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/UncertainDisplayViewingScreen.java
new file mode 100644
index 000000000..96c3542c6
--- /dev/null
+++ b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/config/entries/UncertainDisplayViewingScreen.java
@@ -0,0 +1,304 @@
+/*
+ * 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.config.entries;
+
+import com.google.common.collect.Lists;
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.PoseStack;
+import com.mojang.math.Matrix4f;
+import dev.architectury.platform.Platform;
+import it.unimi.dsi.fastutil.booleans.BooleanConsumer;
+import me.shedaniel.clothconfig2.api.ScissorsHandler;
+import me.shedaniel.clothconfig2.api.animator.NumberAnimator;
+import me.shedaniel.clothconfig2.api.animator.ValueAnimator;
+import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget;
+import me.shedaniel.clothconfig2.impl.EasingMethod;
+import me.shedaniel.math.Point;
+import me.shedaniel.math.Rectangle;
+import me.shedaniel.rei.api.client.ClientHelper;
+import me.shedaniel.rei.api.client.REIRuntime;
+import me.shedaniel.rei.api.client.config.ConfigObject;
+import me.shedaniel.rei.api.client.gui.config.DisplayScreenType;
+import me.shedaniel.rei.api.client.gui.widgets.Button;
+import me.shedaniel.rei.api.client.gui.widgets.Widget;
+import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds;
+import me.shedaniel.rei.api.client.gui.widgets.Widgets;
+import me.shedaniel.rei.api.common.util.ImmutableTextComponent;
+import me.shedaniel.rei.impl.ClientInternals;
+import me.shedaniel.rei.impl.client.config.ConfigManagerInternal;
+import net.minecraft.ChatFormatting;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.chat.NarratorChatListener;
+import net.minecraft.client.gui.components.AbstractSliderButton;
+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.network.chat.TextComponent;
+import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.util.FormattedCharSequence;
+import net.minecraft.util.Mth;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@ApiStatus.Internal
+public class UncertainDisplayViewingScreen extends Screen {
+ private static final ResourceLocation DEFAULT = new ResourceLocation("roughlyenoughitems", "textures/gui/screenshot_default.png");
+ private static final ResourceLocation COMPOSITE = new ResourceLocation("roughlyenoughitems", "textures/gui/screenshot_composite.png");
+ private final List<Widget> widgets;
+ protected long start;
+ protected long duration;
+ private boolean isSet;
+ private boolean original;
+ private double frame = 0;
+ private double target = 0;
+ private BooleanConsumer callback;
+ private Button button;
+ private Screen parent;
+ private Widget slider;
+ private boolean showTips;
+ public NumberAnimator<Double> scroll = ValueAnimator.ofDouble();
+ private List<String> allModsUsingJEI = null;
+ private boolean jeiEnabled = false;
+
+ public UncertainDisplayViewingScreen(Screen parent, DisplayScreenType type, boolean showTips, BooleanConsumer callback) {
+ super(ImmutableTextComponent.EMPTY);
+ this.widgets = Lists.newArrayList();
+ if (type == DisplayScreenType.UNSET) {
+ this.isSet = false;
+ this.original = true;
+ } else {
+ this.isSet = true;
+ this.original = type == DisplayScreenType.ORIGINAL;
+ moveFrameTo(original ? 0 : 1, false, 0);
+ }
+ this.scroll.setAs(0);
+ this.callback = callback;
+ this.parent = parent;
+ this.showTips = showTips;
+ if (showTips && false && Platform.isForge()) {
+ this.jeiEnabled = ConfigObject.getInstance().isJEICompatibilityLayerEnabled();
+ allModsUsingJEI = ClientInternals.getJeiCompatMods().stream()
+ .distinct()
+ .map(ClientHelper.getInstance()::getModFromModId)
+ .collect(Collectors.toList());
+ }
+ }
+
+ public final double clamp(double v) {
+ return clamp(v, 30);
+ }
+
+ public final double clamp(double v, double clampExtension) {
+ return Mth.clamp(v, -clampExtension, 1 + clampExtension);
+ }
+
+ private void moveFrameTo(double value, boolean animated, long duration) {
+ target = clamp(value);
+
+ if (animated) {
+ start = System.currentTimeMillis();
+ this.duration = duration;
+ } else {
+ frame = target;
+ }
+ }
+
+ @Override
+ public void init() {
+ this.children().clear();
+ this.widgets.clear();
+ this._children().add(button = Widgets.createButton(new Rectangle(width / 2 - 100, height - 40, 200, 20), NarratorChatListener.NO_TITLE)
+ .onRender((matrices, button) -> {
+ button.setEnabled(isSet);
+ if (scroll.target() != 0 && allModsUsingJEI != null) {
+ button.setText(new TranslatableComponent("gui.done"));
+ } else {
+ button.setText(isSet ? new TranslatableComponent("text.rei.select") : new TranslatableComponent("config.roughlyenoughitems.recipeScreenType.unset"));
+ }
+ })
+ .onClick(button -> {
+ if (scroll.target() == 0 && allModsUsingJEI != null) {
+ scroll.setTo(200, 450);
+ } else if (allModsUsingJEI != null && jeiEnabled) {
+ ConfigManagerInternal.getInstance().set("advanced.enableJeiCompatibilityLayer", jeiEnabled);
+ Minecraft.getInstance().setScreen(REIRuntime.getInstance().getPreviousScreen());
+ } else {
+ callback.accept(original);
+ }
+ }));
+ this.widgets.add(transformScroll(new ScreenTypeSelection(width / 2 - 200 - 5, height / 2 - 112 / 2 - 10, DisplayScreenType.ORIGINAL)));
+ this.widgets.add(transformScroll(Widgets.createLabel(new Point(width / 2 - 200 - 5 + 104, height / 2 - 112 / 2 + 115), new TranslatableComponent("config.roughlyenoughitems.recipeScreenType.original")).noShadow().color(-1124073473)));
+ this.widgets.add(transformScroll(new ScreenTypeSelection(width / 2 + 5, height / 2 - 112 / 2 - 10, DisplayScreenType.COMPOSITE)));
+ this.widgets.add(transformScroll(Widgets.createLabel(new Point(width / 2 + 5 + 104, height / 2 - 112 / 2 + 115), new TranslatableComponent("config.roughlyenoughitems.recipeScreenType.composite")).noShadow().color(-1124073473)));
+ this.widgets.add(slider = transformScroll(Widgets.wrapVanillaWidget(new AbstractSliderButton(width / 2 - 100, height * 2 - 64, 200, 20, new TranslatableComponent("text.rei.jei_compat.false"), 0) {
+ @Override
+ protected void updateMessage() {
+ setMessage(new TranslatableComponent("text.rei.jei_compat." + (jeiEnabled = value == 1f)));
+ }
+
+ @Override
+ protected void applyValue() {
+
+ }
+
+ @Override
+ public void renderButton(PoseStack poseStack, int i, int j, float f) {
+ y = UncertainDisplayViewingScreen.this.height * 2 - 64;
+ super.renderButton(poseStack, i, j, f);
+ y = UncertainDisplayViewingScreen.this.height * 2 - 64 - (int) (scroll.floatValue() / 200f * height);
+ }
+ })));
+ this._children().addAll(widgets);
+ }
+
+ public List<GuiEventListener> _children() {
+ return (List<GuiEventListener>) children();
+ }
+
+ private Widget transformScroll(Widget widget) {
+ return Widgets.withTranslate(widget, () -> Matrix4f.createTranslateMatrix(0, -(scroll.floatValue() / 200f * height), 0));
+ }
+
+ @Override
+ public void render(PoseStack matrices, int int_1, int int_2, float float_1) {
+ scroll.update(float_1);
+ if (this.minecraft.level != null) {
+ renderBackground(matrices);
+ } else {
+ this.fillGradient(matrices, 0, 0, this.width, this.height, -16777216, -16777216);
+ }
+ if (scroll.target() == 0) {
+ drawCenteredString(matrices, this.font, new TranslatableComponent("text.rei.recipe_screen_type.selection"), this.width / 2, 20, 16777215);
+ } else {
+ drawCenteredString(matrices, this.font, new TranslatableComponent("text.rei.jei_compat"), this.width / 2, 20, 16777215);
+ }
+ ScissorsHandler.INSTANCE.scissor(new Rectangle(0, 20 + font.lineHeight + 2, width, height - 42));
+ if (showTips) {
+ float i = 32 - (scroll.floatValue() / 200f * height);
+ for (FormattedCharSequence s : this.font.split(new TranslatableComponent("text.rei.recipe_screen_type.selection.sub").withStyle(ChatFormatting.GRAY), width - 30)) {
+ font.drawShadow(matrices, s, width / 2 - font.width(s) / 2, i, -1);
+ i += 10;
+ }
+ if (allModsUsingJEI != null) {
+ i = 32 + height - (scroll.floatValue() / 200f * height);
+ for (FormattedCharSequence s : this.font.split(new TranslatableComponent("text.rei.jei_compat.sub", new TranslatableComponent("text.rei.jei_compat.sub.stability"),
+ new TextComponent(String.join(", ", allModsUsingJEI))).withStyle(ChatFormatting.GRAY), width - 30)) {
+ font.drawShadow(matrices, s, width / 2 - font.width(s) / 2, i, -1);
+ i += 10;
+ }
+ }
+ }
+ super.render(matrices, int_1, int_2, float_1);
+ for (Widget widget : widgets) {
+ widget.render(matrices, int_1, int_2, float_1);
+ }
+ if (isSet) {
+ matrices.pushPose();
+ matrices.translate(0, -(scroll.floatValue() / 200f * height), 0);
+ updateFramePosition(float_1);
+ int x = (int) (width / 2 - 205 + (210 * frame));
+ int y = height / 2 - 112 / 2 - 10;
+ fillGradient(matrices, x - 2, y - 4, x - 6 + 208, y - 4 + 2, -1778384897, -1778384897);
+ fillGradient(matrices, x - 2, y - 4 + 126 - 2, x - 6 + 208, y - 4 + 126, -1778384897, -1778384897);
+ fillGradient(matrices, x - 4, y - 4, x - 4 + 2, y - 4 + 126, -1778384897, -1778384897);
+ fillGradient(matrices, x - 4 + 208 - 2, y - 4, x - 4 + 208, y - 4 + 126, -1778384897, -1778384897);
+ matrices.popPose();
+ }
+ ScissorsHandler.INSTANCE.removeLastScissor();
+ button.render(matrices, int_1, int_2, float_1);
+ }
+
+ private void updateFramePosition(float delta) {
+ target = clamp(target);
+ if (!DynamicNewSmoothScrollingEntryListWidget.Precision.almostEquals(frame, target, DynamicNewSmoothScrollingEntryListWidget.Precision.FLOAT_EPSILON))
+ frame = ease(frame, target, Math.min((System.currentTimeMillis() - start) / (double) duration * delta * 3.0D, 1));
+ else
+ frame = target;
+ }
+
+ private double ease(double start, double end, double amount) {
+ return start + (end - start) * EasingMethod.EasingMethodImpl.LINEAR.apply(amount);
+ }
+
+ @Override
+ public boolean keyPressed(int int_1, int int_2, int int_3) {
+ if (int_1 == 256 || this.minecraft.options.keyInventory.matches(int_1, int_2)) {
+ Minecraft.getInstance().setScreen(parent);
+ if (parent instanceof AbstractContainerScreen) {
+ REIRuntime.getInstance().getOverlay().get().queueReloadOverlay();
+ }
+ return true;
+ }
+ return super.keyPressed(int_1, int_2, int_3);
+ }
+
+ @Override
+ public boolean mouseDragged(double d, double e, int i, double f, double g) {
+ return slider.mouseDragged(d, e, i, f, g) || super.mouseDragged(d, e, i, f, g);
+ }
+
+ public class ScreenTypeSelection extends WidgetWithBounds {
+ private final DisplayScreenType type;
+ private Rectangle bounds;
+
+ public ScreenTypeSelection(int x, int y, DisplayScreenType type) {
+ this.type = type;
+ this.bounds = new Rectangle(x - 4 + 16, y - 4, 176 + 8, 120 + 8);
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return bounds;
+ }
+
+ @Override
+ public void render(PoseStack matrices, int i, int i1, float delta) {
+ RenderSystem.setShaderTexture(0, type == DisplayScreenType.ORIGINAL ? DEFAULT : COMPOSITE);
+ blit(matrices, bounds.x + (type == DisplayScreenType.ORIGINAL ? 8 : 4), bounds.y + 4, bounds.width - 8, bounds.height - 8, 113, type == DisplayScreenType.ORIGINAL ? 16 : 27, 854 - 113 * 2, 480 - 27 * 2, 854, 480);
+ }
+
+ @Override
+ public boolean mouseClicked(double double_1, double double_2, int int_1) {
+ if (containsMouse(double_1, double_2)) {
+ original = (type == DisplayScreenType.ORIGINAL);
+ if (!isSet) {
+ moveFrameTo(original ? 0 : 1, false, 0);
+ }
+ isSet = true;
+ moveFrameTo(original ? 0 : 1, true, 500);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return Collections.emptyList();
+ }
+ }
+}
diff --git a/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/gui/credits/CreditsEntryListWidget.java b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/gui/credits/CreditsEntryListWidget.java
new file mode 100644
index 000000000..9a576014c
--- /dev/null
+++ b/runtime-engine/configs/src/main/java/me/shedaniel/rei/impl/client/gui/credits/CreditsEntryListWidget.java
@@ -0,0 +1,216 @@
+/*
+ * 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.credits;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.gui.widget.DynamicSmoothScrollingEntryListWidget;
+import me.shedaniel.rei.impl.client.gui.text.TextTransformations;
+import net.minecraft.ChatFormatting;
+import net.minecraft.Util;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiComponent;
+import net.minecraft.client.gui.narration.NarratableEntry;
+import net.minecraft.client.resources.sounds.SimpleSoundInstance;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TextComponent;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.util.FormattedCharSequence;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.List;
+
+@ApiStatus.Internal
+public class CreditsEntryListWidget extends DynamicSmoothScrollingEntryListWidget<CreditsEntryListWidget.CreditsItem> {
+ private boolean inFocus;
+
+ public CreditsEntryListWidget(Minecraft client, int width, int height, int startY, int endY) {
+ super(client, width, height, startY, endY, GuiComponent.BACKGROUND_LOCATION);
+ }
+
+ @Override
+ public boolean changeFocus(boolean boolean_1) {
+ if (