diff options
| author | shedaniel <daniel@shedaniel.me> | 2022-12-12 21:22:51 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2022-12-12 21:26:43 +0800 |
| commit | e2979ca8bdf49a5db0f944085caec284fde3d00b (patch) | |
| tree | 886f4ae7fdba33fc6ebcf25ea9d5de864480a087 | |
| parent | 75020d8ffd08bca7404cc3fbd713e314d7b45324 (diff) | |
| parent | ffc551e61bdafd765dfcf03028568935e2d8c635 (diff) | |
| download | RoughlyEnoughItems-e2979ca8bdf49a5db0f944085caec284fde3d00b.tar.gz RoughlyEnoughItems-e2979ca8bdf49a5db0f944085caec284fde3d00b.tar.bz2 RoughlyEnoughItems-e2979ca8bdf49a5db0f944085caec284fde3d00b.zip | |
Merge remote-tracking branch 'origin/9.x-1.19' into 10.x-1.19.3
# Conflicts:
# runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/CraftableFilterButtonWidget.java
# runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionEntryWidget.java
44 files changed, 1419 insertions, 223 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java index a932071db..f62e3590a 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java @@ -265,6 +265,9 @@ public interface ConfigObject { boolean doDisplayFavoritesTooltip(); + @ApiStatus.Experimental + boolean doDisplayIMEHints(); + boolean doesFastEntryRendering(); boolean doesCacheEntryRendering(); diff --git a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteMenuEntry.java b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteMenuEntry.java index 61655c432..35bc5a10c 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteMenuEntry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteMenuEntry.java @@ -23,14 +23,29 @@ package me.shedaniel.rei.api.client.favorites; +import dev.architectury.utils.value.BooleanValue; import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.impl.ClientInternals; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; +import java.util.List; + @Environment(EnvType.CLIENT) public abstract class FavoriteMenuEntry extends Widget { + @ApiStatus.Experimental + public static FavoriteMenuEntry createSubMenu(Component text, List<FavoriteMenuEntry> entries) { + return ClientInternals.createSubMenuEntry(text, entries); + } + + @ApiStatus.Experimental + public static FavoriteMenuEntry createToggle(Component text, BooleanValue value) { + return ClientInternals.createToggleEntry(text, value); + } + @Nullable @ApiStatus.Internal public Runnable closeMenu = null; diff --git a/api/src/main/java/me/shedaniel/rei/api/client/search/method/CharacterUnpackingInputMethod.java b/api/src/main/java/me/shedaniel/rei/api/client/search/method/CharacterUnpackingInputMethod.java index f14e1b334..c27f25dbd 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/search/method/CharacterUnpackingInputMethod.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/search/method/CharacterUnpackingInputMethod.java @@ -24,6 +24,7 @@ package me.shedaniel.rei.api.client.search.method; import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.util.Mth; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -45,9 +46,9 @@ public interface CharacterUnpackingInputMethod extends InputMethod<IntList> { default String suggestInputString(String str) { return str.codePoints().mapToObj(c -> { List<ExpendedChar> chars = expendSourceChar(c); - String result; - if (chars.isEmpty()) return result = ((char) c) + ""; - result = chars.get(0).phonemes().stream() + if (chars.isEmpty()) return ((char) c) + ""; + int i = Mth.floor((System.currentTimeMillis() / 1000L % (double) chars.size())); + String result = chars.get(i).phonemes().stream() .flatMap(integers -> integers.intStream().mapToObj(value -> ((char) value) + "")) .collect(Collectors.joining()); if (result.codePointCount(0, result.length()) == 1 && result.codePointAt(0) == c) { diff --git a/api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethod.java b/api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethod.java index 90e6ba092..6a19e5ecb 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethod.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethod.java @@ -24,6 +24,7 @@ package me.shedaniel.rei.api.client.search.method; import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry; import me.shedaniel.rei.api.common.util.CollectionUtils; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; @@ -34,35 +35,141 @@ import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +/** + * An input method to match a search filter to another source input. + * + * @param <T> the type of expansion from the search filter + * @see me.shedaniel.rei.impl.client.search.method.DefaultInputMethod + */ @ApiStatus.Experimental public interface InputMethod<T> { + /** + * Returns the active input method. + * + * @return the active input method + */ static InputMethod<?> active() { return InputMethodRegistry.getInstance().getOrDefault(ConfigObject.getInstance().getInputMethodId()); } + /** + * Returns the list of all Minecraft supported locales. + * + * @return the list of all Minecraft supported locales + */ static List<Locale> getAllLocales() { return CollectionUtils.map(Minecraft.getInstance().getLanguageManager().getLanguages(), info -> new Locale(info.getCode(), Component.literal(info.getName()))); } + /** + * Returns the list of locales that are supported by this input method. + * You should use {@link #getAllLocales()} to get the list of all Minecraft supported locales. + * + * @return the list of locales that are supported by this input method + */ List<Locale> getMatchingLocales(); + /** + * Returns all the possible expansions from the search filter. + * + * @param filter the search filter + * @return all the possible expansions from the search filter + */ Iterable<T> expendFilter(String filter); + /** + * Returns whether the search filter matches the input. + * + * @param str the input + * @param substr the expanded search filter + * @return whether the search filter matches the input + */ boolean contains(String str, T substr); + /** + * Returns a suggested expansion from the search filter. + * + * @param str the input + * @return a suggested expansion from the search filter, or {@code null} if no suggestion is available + */ @Nullable default String suggestInputString(String str) { return null; } + /** + * Prepares the input method for activation. + * + * @param executor the executor to run the preparation on + * @return a future that completes when the preparation is done + */ CompletableFuture<Void> prepare(Executor executor); + /** + * Prepares the input method for activation. + * + * @param executor the executor to run the preparation on + * @param progressCallback the callback to call when the progress is updated + * @return a future that completes when the preparation is done + */ + default CompletableFuture<Void> prepare(Executor executor, ProgressCallback progressCallback) { + progressCallback.onProgress(0.0); + return prepare(executor).whenComplete((aVoid, throwable) -> progressCallback.onProgress(1.0)); + } + + /** + * Disposes the input method. + * + * @param executor the executor to run the disposal on + * @return a future that completes when the disposal is done + */ CompletableFuture<Void> dispose(Executor executor); + /** + * Disposes the input method. + * + * @param executor the executor to run the disposal on + * @param progressCallback the callback to call when the progress is updated + * @return a future that completes when the disposal is done + */ + default CompletableFuture<Void> dispose(Executor executor, ProgressCallback progressCallback) { + progressCallback.onProgress(0.0); + return dispose(executor).whenComplete((aVoid, throwable) -> progressCallback.onProgress(1.0)); + } + + /** + * Returns the name of this input method. + * + * @return the name of this input method + */ Component getName(); + /** + * Returns the description of this input method. + * + * @return the description of this input method + */ Component getDescription(); + /** + * Returns the list of menu entries that will be used as options. + * + * @return the list of menu entries that will be used as options + */ + default List<FavoriteMenuEntry> getOptionsMenuEntries() { + return List.of(); + } + record Locale(String code, Component name) {} + + @FunctionalInterface + interface ProgressCallback { + /** + * Called when the progress of the preparation is updated. + * + * @param progress the progress of the preparation, between 0.0 and 1.0 + */ + void onProgress(double progress); + } } diff --git a/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java b/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java index 6efe3c553..77bba4f8b 100644 --- a/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java +++ b/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java @@ -24,12 +24,14 @@ package me.shedaniel.rei.impl; import com.mojang.serialization.DataResult; +import dev.architectury.utils.value.BooleanValue; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.ClientHelper; import me.shedaniel.rei.api.client.entry.filtering.FilteringRuleTypeRegistry; import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; +import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry; import me.shedaniel.rei.api.client.gui.DrawableConsumer; import me.shedaniel.rei.api.client.gui.Renderer; import me.shedaniel.rei.api.client.gui.widgets.*; @@ -70,6 +72,8 @@ public final class ClientInternals { private static Supplier<EntryRenderer<?>> emptyEntryRenderer = ClientInternals::throwNotSetup; private static Supplier<FilteringRuleTypeRegistry> filteringRuleTypeRegistry = ClientInternals::throwNotSetup; private static BiFunction<Supplier<DataResult<FavoriteEntry>>, Supplier<CompoundTag>, FavoriteEntry> delegateFavoriteEntry = (supplier, toJson) -> throwNotSetup(); + private static BiFunction<Component, List<FavoriteMenuEntry>, FavoriteMenuEntry> subMenuEntry = (supplier, toJson) -> throwNotSetup(); + private static BiFunction<Component, BooleanValue, FavoriteMenuEntry> toggleEntry = (supplier, toJson) -> throwNotSetup(); private static Function<CompoundTag, DataResult<FavoriteEntry>> favoriteEntryFromJson = (object) -> throwNotSetup(); private static Function<Boolean, ClickArea.Result> clickAreaHandlerResult = (result) -> throwNotSetup(); private static BiConsumer<List<ClientTooltipComponent>, TooltipComponent> clientTooltipComponentProvider = (tooltip, result) -> throwNotSetup(); @@ -149,6 +153,14 @@ public final class ClientInternals { return delegateFavoriteEntry.apply(supplier, toJoin); } + public static FavoriteMenuEntry createSubMenuEntry(Component name, List<FavoriteMenuEntry> entries) { + return subMenuEntry.apply(name, entries); + } + + public static FavoriteMenuEntry createToggleEntry(Component name, BooleanValue value) { + return toggleEntry.apply(name, value); + } + public static DataResult<FavoriteEntry> favoriteEntryFromJson(CompoundTag tag) { return favoriteEntryFromJson.apply(tag); } diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java index 16558a54e..b911f9968 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java @@ -34,6 +34,7 @@ import dev.architectury.event.events.client.ClientGuiEvent; import dev.architectury.event.events.client.ClientRecipeUpdateEvent; import dev.architectury.event.events.client.ClientScreenInputEvent; import dev.architectury.networking.NetworkManager; +import dev.architectury.utils.value.BooleanValue; import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.ConfigObject; @@ -41,6 +42,7 @@ import me.shedaniel.rei.api.client.entry.filtering.FilteringRuleTypeRegistry; import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; +import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry; import me.shedaniel.rei.api.client.gui.screen.DisplayScreen; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; @@ -66,6 +68,8 @@ import me.shedaniel.rei.impl.client.entry.renderer.EntryRendererRegistryImpl; import me.shedaniel.rei.impl.client.favorites.DelegatingFavoriteEntryProviderImpl; import me.shedaniel.rei.impl.client.favorites.FavoriteEntryTypeRegistryImpl; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; +import me.shedaniel.rei.impl.client.gui.modules.entries.SubMenuEntry; +import me.shedaniel.rei.impl.client.gui.modules.entries.ToggleMenuEntry; import me.shedaniel.rei.impl.client.gui.widget.InternalWidgets; import me.shedaniel.rei.impl.client.gui.widget.QueuedTooltip; import me.shedaniel.rei.impl.client.gui.widget.TooltipContextImpl; @@ -151,6 +155,8 @@ public class RoughlyEnoughItemsCoreClient { ClientInternals.attachInstance((BiFunction<@Nullable Point, Collection<Tooltip.Entry>, Tooltip>) QueuedTooltip::impl, "tooltipProvider"); ClientInternals.attachInstance((TriFunction<Point, @Nullable TooltipFlag, Boolean, TooltipContext>) TooltipContextImpl::new, "tooltipContextProvider"); ClientInternals.attachInstance((Function<Object, Tooltip.Entry>) QueuedTooltip.TooltipEntryImpl::new, "tooltipEntryProvider"); + ClientInternals.attachInstance((BiFunction<Component, List<FavoriteMenuEntry>, FavoriteMenuEntry>) SubMenuEntry::new, "subMenuEntry"); + ClientInternals.attachInstance((BiFunction<Component, BooleanValue, FavoriteMenuEntry>) (text, value) -> ToggleMenuEntry.of(text, value::get, value), "toggleEntry"); ClientInternals.attachInstance((Function<@Nullable Boolean, ClickArea.Result>) successful -> new ClickArea.Result() { private List<CategoryIdentifier<?>> categories = Lists.newArrayList(); private BooleanSupplier execute = () -> { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java index a18d7aeab..6b2e7c5c8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java @@ -280,6 +280,15 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { } @Override + public boolean doDisplayIMEHints() { + return advanced.tooltips.displayIMEHints; + } + + public void setDoDisplayIMEHints(boolean displayIMEHints) { + advanced.tooltips.displayIMEHints = displayIMEHints; + } + + @Override public boolean doesFastEntryRendering() { return advanced.miscellaneous.newFastEntryRendering; } @@ -661,6 +670,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { public static class Tooltips { @Comment("Declares whether REI should append mod names to entries.") private boolean appendModNames = true; @Comment("Declares whether favorites tooltip should be displayed.") private boolean displayFavoritesTooltip = false; + @ConfigEntry.Gui.Excluded private boolean displayIMEHints = true; } public static class Layout { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java index fe6abb1ba..7ceaa4123 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java @@ -59,6 +59,7 @@ import me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget; import me.shedaniel.rei.impl.client.gui.widget.entrylist.PaginatedEntryListWidget; import me.shedaniel.rei.impl.client.gui.widget.entrylist.ScrolledEntryListWidget; import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesListWidget; +import me.shedaniel.rei.impl.client.gui.widget.hint.HintsContainerWidget; import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchField; import me.shedaniel.rei.impl.common.util.RectangleUtils; import net.minecraft.client.Minecraft; @@ -86,10 +87,11 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { private Rectangle bounds; private Window window; private Widget configButton; - private CurrentDraggingStack draggingStack = new CurrentDraggingStack(); + private final CurrentDraggingStack draggingStack = new CurrentDraggingStack(); @Nullable public DefaultDisplayChoosePageWidget choosePageWidget; - private MenuHolder menuHolder = new MenuHolder(); + private final MenuHolder menuHolder = new MenuHolder(); + private final HintsContainerWidget hintsWidget = new HintsContainerWidget(); public static EntryListWidget getEntryListWidget() { boolean widgetScrolled = ConfigObject.getInstance().isEntryListWidgetScrolled(); @@ -118,7 +120,7 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { } public static ScreenOverlayImpl getInstance() { - return (ScreenOverlayImpl) REIRuntime.getInstance().getOverlay().get(); + return (ScreenOverlayImpl) REIRuntime.getInstance().getOverlay().orElseThrow(); } public void tick() { @@ -183,6 +185,8 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { } this.widgets.add(draggingStack); + this.widgets.add(InternalWidgets.wrapLateRenderable(hintsWidget)); + this.hintsWidget.init(); } private Rectangle getSearchFieldArea() { @@ -294,6 +298,8 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { for (Widget widget : widgets) { if (widget instanceof LateRenderable && widget != menuHolder.widget()) widget.render(matrices, mouseX, mouseY, delta); + else if (widget instanceof OverlaySearchField field) + field.laterRender(matrices, mouseX, mouseY, delta); } matrices.pushPose(); matrices.translate(0, 0, 500); @@ -347,6 +353,8 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { return false; if (menuHolder.mouseScrolled(mouseX, mouseY, amount)) return true; + if (hintsWidget.mouseScrolled(mouseX, mouseY, amount)) + return true; if (isInside(mouseX, mouseY) && getEntryListWidget().mouseScrolled(mouseX, mouseY, amount)) { return true; } @@ -357,6 +365,7 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { for (Widget widget : widgets) if (widget != getEntryListWidget() && (favoritesListWidget == null || widget != favoritesListWidget) && widget != menuHolder.widget() + && widget != hintsWidget && widget.mouseScrolled(mouseX, mouseY, amount)) return true; return false; @@ -488,6 +497,13 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { REIRuntimeImpl.getSearchField().setFocused(false); return true; } + if (hintsWidget.mouseClicked(mouseX, mouseY, button)) { + this.setFocused(hintsWidget); + if (button == 0) + this.setDragging(true); + REIRuntimeImpl.getSearchField().setFocused(false); + return true; + } } if (ConfigObject.getInstance().areClickableRecipeArrowsEnabled()) { Screen screen = Minecraft.getInstance().screen; @@ -500,7 +516,7 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay { return false; } for (GuiEventListener element : widgets) { - if (element != configButton && element != menuHolder.widget() && element.mouseClicked(mouseX, mouseY, button)) { + if (element != configButton && element != menuHolder.widget() && element != hintsWidget && element.mouseClicked(mouseX, mouseY, button)) |
