From 664815d74ffdc030fd52f0ed0480b1cd615ef384 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Tue, 19 Jul 2022 00:06:17 +0800 Subject: Add InputMethods, Close #574 --- .../rei/api/client/config/ConfigObject.java | 6 ++ .../me/shedaniel/rei/api/client/gui/Renderer.java | 1 - .../api/client/gui/config/SearchFieldLocation.java | 2 +- .../rei/api/client/gui/widgets/Label.java | 2 - .../rei/api/client/gui/widgets/Tooltip.java | 1 - .../rei/api/client/overlay/ScreenOverlay.java | 6 +- .../rei/api/client/plugins/REIClientPlugin.java | 12 ++++ .../client/registry/transfer/TransferHandler.java | 2 - .../rei/api/client/search/SearchProvider.java | 19 +++++- .../method/CharacterUnpackingInputMethod.java | 61 +++++++++++++++++++ .../rei/api/client/search/method/InputMethod.java | 68 ++++++++++++++++++++++ .../client/search/method/InputMethodRegistry.java | 49 ++++++++++++++++ .../rei/api/common/entry/EntryIngredient.java | 1 - .../shedaniel/rei/api/common/entry/EntryStack.java | 6 +- .../entry/settings/EntrySettingsAdapter.java | 2 - .../rei/api/common/util/CollectionUtils.java | 37 ++++++++++++ 16 files changed, 257 insertions(+), 18 deletions(-) create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/search/method/CharacterUnpackingInputMethod.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethod.java create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethodRegistry.java (limited to 'api/src/main') 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 3b0e0efbb..4da17b6c0 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 @@ -30,7 +30,9 @@ import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.gui.config.*; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -235,6 +237,10 @@ public interface ConfigObject { */ int getMaxRecipesPageHeight(); + @ApiStatus.Experimental + @Nullable + ResourceLocation getInputMethodId(); + boolean doesDisableRecipeBook(); boolean doesFixTabCloseContainer(); diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/Renderer.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/Renderer.java index 317fed296..b2e714e08 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/Renderer.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/Renderer.java @@ -24,7 +24,6 @@ package me.shedaniel.rei.api.client.gui; import com.mojang.blaze3d.vertex.PoseStack; -import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/config/SearchFieldLocation.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/config/SearchFieldLocation.java index 762ae020f..82d722359 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/config/SearchFieldLocation.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/config/SearchFieldLocation.java @@ -37,6 +37,6 @@ public enum SearchFieldLocation { @Override public String toString() { - return I18n.get("config.roughlyenoughitems.layout.searchFieldLocation.%s", name().toLowerCase(Locale.ROOT)); + return I18n.get("config.roughlyenoughitems.layout.searchFieldLocation.%s".formatted(name().toLowerCase(Locale.ROOT))); } } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Label.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Label.java index b1d3c0bd9..3f0719bf2 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Label.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Label.java @@ -28,13 +28,11 @@ import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.REIRuntime; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; -import java.util.stream.Stream; public abstract class Label extends WidgetWithBounds { public static final int LEFT_ALIGNED = -1; diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Tooltip.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Tooltip.java index a9caf9577..3e10dd28c 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Tooltip.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/widgets/Tooltip.java @@ -32,7 +32,6 @@ import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.impl.ClientInternals; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; import net.minecraft.network.chat.Component; import net.minecraft.world.inventory.tooltip.TooltipComponent; import org.jetbrains.annotations.ApiStatus; diff --git a/api/src/main/java/me/shedaniel/rei/api/client/overlay/ScreenOverlay.java b/api/src/main/java/me/shedaniel/rei/api/client/overlay/ScreenOverlay.java index a45a854b7..f7f5c481e 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/overlay/ScreenOverlay.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/overlay/ScreenOverlay.java @@ -27,17 +27,15 @@ import me.shedaniel.rei.api.client.gui.drag.DraggingContext; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import org.jetbrains.annotations.ApiStatus; import java.util.Optional; @Environment(EnvType.CLIENT) public abstract class ScreenOverlay extends WidgetWithBounds { - @ApiStatus.Internal - public abstract void closeOverlayMenu(); - public abstract void queueReloadOverlay(); + public abstract void queueReloadSearch(); + public abstract DraggingContext getDraggingContext(); public abstract boolean isNotInExclusionZones(double mouseX, double mouseY); diff --git a/api/src/main/java/me/shedaniel/rei/api/client/plugins/REIClientPlugin.java b/api/src/main/java/me/shedaniel/rei/api/client/plugins/REIClientPlugin.java index f3ff9408d..deeca9ff3 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/plugins/REIClientPlugin.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/plugins/REIClientPlugin.java @@ -33,6 +33,7 @@ import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; import me.shedaniel.rei.api.client.registry.screen.ExclusionZones; import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry; +import me.shedaniel.rei.api.client.search.method.InputMethodRegistry; import me.shedaniel.rei.api.client.subsets.SubsetsRegistry; import me.shedaniel.rei.api.common.plugins.REIPlugin; import net.fabricmc.api.EnvType; @@ -145,6 +146,17 @@ public interface REIClientPlugin extends REIPlugin { default void registerConfigAddons(ConfigAddonRegistry registry) { } + /** + * Registers new input methods. + * + * @param registry the registry + * @since 8.3 + */ + @ApiStatus.OverrideOnly + @ApiStatus.Experimental + default void registerInputMethods(InputMethodRegistry registry) { + } + @Override default Class getPluginProviderClass() { return REIClientPlugin.class; diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java index f1c6e7879..7974ddd7a 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java @@ -27,12 +27,10 @@ import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.api.common.entry.EntryIngredient; -import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.impl.ClientInternals; 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.network.chat.Component; import net.minecraft.world.inventory.AbstractContainerMenu; diff --git a/api/src/main/java/me/shedaniel/rei/api/client/search/SearchProvider.java b/api/src/main/java/me/shedaniel/rei/api/client/search/SearchProvider.java index b31c4ee16..a337e5e17 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/search/SearchProvider.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/search/SearchProvider.java @@ -24,10 +24,12 @@ package me.shedaniel.rei.api.client.search; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.client.search.method.InputMethod; import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.registry.Reloadable; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import org.jetbrains.annotations.ApiStatus; @Environment(EnvType.CLIENT) public interface SearchProvider extends Reloadable { @@ -39,8 +41,21 @@ public interface SearchProvider extends Reloadable { * Creates a search filter, which respects user's config options and * respects argument prefixes. * - * @param searchTerm the search term of the filter + * @param filter the search term of the filter * @return the search filter */ - SearchFilter createFilter(String searchTerm); + default SearchFilter createFilter(String filter) { + return createFilter(filter, InputMethod.active()); + } + + /** + * Creates a search filter, which respects user's config options and + * respects argument prefixes. + * + * @param filter the search term of the filter + * @param inputMethod the input method of the filter + * @return the search filter + */ + @ApiStatus.Experimental + SearchFilter createFilter(String filter, InputMethod inputMethod); } 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 new file mode 100644 index 000000000..f14e1b334 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/search/method/CharacterUnpackingInputMethod.java @@ -0,0 +1,61 @@ +/* + * 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.api.client.search.method; + +import it.unimi.dsi.fastutil.ints.IntList; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.stream.Collectors; + +@ApiStatus.Experimental +public interface CharacterUnpackingInputMethod extends InputMethod { + List expendSourceChar(int codePoint); + + @Override + default boolean contains(String str, IntList substr) { + // This is implemented in the runtime + throw new UnsupportedOperationException(); + } + + @Override + @Nullable + default String suggestInputString(String str) { + return str.codePoints().mapToObj(c -> { + List chars = expendSourceChar(c); + String result; + if (chars.isEmpty()) return result = ((char) c) + ""; + result = chars.get(0).phonemes().stream() + .flatMap(integers -> integers.intStream().mapToObj(value -> ((char) value) + "")) + .collect(Collectors.joining()); + if (result.codePointCount(0, result.length()) == 1 && result.codePointAt(0) == c) { + return result; + } + return " " + result + " "; + }).collect(Collectors.joining()).trim().replace(" ", " "); + } + + record ExpendedChar(List phonemes) {} +} 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 new file mode 100644 index 000000000..90e6ba092 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethod.java @@ -0,0 +1,68 @@ +/* + * 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.api.client.search.method; + +import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +@ApiStatus.Experimental +public interface InputMethod { + static InputMethod active() { + return InputMethodRegistry.getInstance().getOrDefault(ConfigObject.getInstance().getInputMethodId()); + } + + static List getAllLocales() { + return CollectionUtils.map(Minecraft.getInstance().getLanguageManager().getLanguages(), info -> + new Locale(info.getCode(), Component.literal(info.getName()))); + } + + List getMatchingLocales(); + + Iterable expendFilter(String filter); + + boolean contains(String str, T substr); + + @Nullable + default String suggestInputString(String str) { + return null; + } + + CompletableFuture prepare(Executor executor); + + CompletableFuture dispose(Executor executor); + + Component getName(); + + Component getDescription(); + + record Locale(String code, Component name) {} +} diff --git a/api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethodRegistry.java b/api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethodRegistry.java new file mode 100644 index 000000000..357a182cd --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/search/method/InputMethodRegistry.java @@ -0,0 +1,49 @@ +/* + * 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.api.client.search.method; + +import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.common.plugins.PluginManager; +import me.shedaniel.rei.api.common.registry.Reloadable; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +@ApiStatus.Experimental +public interface InputMethodRegistry extends Reloadable { + static InputMethodRegistry getInstance() { + return PluginManager.getClientInstance().get(InputMethodRegistry.class); + } + + void add(ResourceLocation id, InputMethod inputMethod); + + @Nullable + InputMethod get(@Nullable ResourceLocation id); + + InputMethod getOrDefault(@Nullable ResourceLocation id); + + Map> getAll(); +} diff --git a/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryIngredient.java b/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryIngredient.java index ae9925788..fd6302218 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryIngredient.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryIngredient.java @@ -31,7 +31,6 @@ import org.jetbrains.annotations.ApiStatus; import java.util.List; import java.util.function.Predicate; -import java.util.function.Supplier; import java.util.function.UnaryOperator; import java.util.stream.Collector; import java.util.stream.Collectors; diff --git a/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryStack.java b/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryStack.java index 6e3dbb673..485cfcfef 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryStack.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/entry/EntryStack.java @@ -25,7 +25,6 @@ package me.shedaniel.rei.api.common.entry; import dev.architectury.utils.Env; import dev.architectury.utils.EnvExecutor; -import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer; import me.shedaniel.rei.api.client.entry.renderer.EntryRendererRegistry; @@ -50,7 +49,10 @@ import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Stream; diff --git a/api/src/main/java/me/shedaniel/rei/api/common/entry/settings/EntrySettingsAdapter.java b/api/src/main/java/me/shedaniel/rei/api/common/entry/settings/EntrySettingsAdapter.java index 6a8506197..dc8ae19ed 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/entry/settings/EntrySettingsAdapter.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/entry/settings/EntrySettingsAdapter.java @@ -24,8 +24,6 @@ package me.shedaniel.rei.api.common.entry.settings; import me.shedaniel.rei.api.common.entry.EntryStack; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; diff --git a/api/src/main/java/me/shedaniel/rei/api/common/util/CollectionUtils.java b/api/src/main/java/me/shedaniel/rei/api/common/util/CollectionUtils.java index 44bb9da1f..c80e0dc25 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/util/CollectionUtils.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/util/CollectionUtils.java @@ -421,4 +421,41 @@ public class CollectionUtils { public static Ingredient toIngredient(Iterable stacks) { return Ingredient.of(StreamSupport.stream(stacks.spliterator(), false)); } + + @SafeVarargs + public static List concatUnmodifiable(List... lists) { + return new ListConcatenationView<>(lists); + } + + /** + * A list which acts as view of the concatenation of a number of lists. + */ + private static class ListConcatenationView extends AbstractList { + private final List[] lists; + + @SafeVarargs + public ListConcatenationView(List... lists) { + this.lists = lists; + } + + @Override + public E get(int ix) { + int localIx = ix; + for (List l : lists) { + if (localIx < 0) throw new IndexOutOfBoundsException(ix); + if (localIx < l.size()) return l.get(localIx); + localIx -= l.size(); + } + return null; + } + + @Override + public int size() { + int size = 0; + for (List l : lists) { + size += l.size(); + } + return size; + } + } } -- cgit