aboutsummaryrefslogtreecommitdiff
path: root/api/src
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2022-07-27 23:25:27 +0800
committershedaniel <daniel@shedaniel.me>2022-08-26 10:52:27 +0900
commit05069aa62b09f02a8cd6e526ec58a30347a56500 (patch)
treeacb90d01f0a06de7c6b540eefeeee8259016f8ac /api/src
parent685861c91bbb8a8a882da51381d392f1310d061d (diff)
downloadRoughlyEnoughItems-05069aa62b09f02a8cd6e526ec58a30347a56500.tar.gz
RoughlyEnoughItems-05069aa62b09f02a8cd6e526ec58a30347a56500.tar.bz2
RoughlyEnoughItems-05069aa62b09f02a8cd6e526ec58a30347a56500.zip
WIP Module
Diffstat (limited to 'api/src')
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/entry/renderer/EntryRenderer.java4
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java2
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/overlay/OverlayListWidget.java2
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntry.java42
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntryRegistry.java2
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java8
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/registry/entry/PreFilteredEntryList.java51
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/search/SearchFilter.java20
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/search/SearchProvider.java14
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/common/registry/ParentReloadable.java5
-rw-r--r--api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java60
-rw-r--r--api/src/main/java/me/shedaniel/rei/impl/Internals.java78
12 files changed, 238 insertions, 50 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/entry/renderer/EntryRenderer.java b/api/src/main/java/me/shedaniel/rei/api/client/entry/renderer/EntryRenderer.java
index c51309603..2aa203aa9 100644
--- a/api/src/main/java/me/shedaniel/rei/api/client/entry/renderer/EntryRenderer.java
+++ b/api/src/main/java/me/shedaniel/rei/api/client/entry/renderer/EntryRenderer.java
@@ -29,7 +29,7 @@ import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.gui.widgets.Tooltip;
import me.shedaniel.rei.api.client.gui.widgets.TooltipContext;
import me.shedaniel.rei.api.common.entry.EntryStack;
-import me.shedaniel.rei.impl.ClientInternals;
+import me.shedaniel.rei.api.common.entry.type.BuiltinEntryTypes;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.jetbrains.annotations.ApiStatus;
@@ -46,7 +46,7 @@ import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public interface EntryRenderer<T> extends EntryRendererProvider<T> {
static <T> EntryRenderer<T> empty() {
- return ClientInternals.getEmptyEntryRenderer();
+ return (EntryRenderer<T>) BuiltinEntryTypes.EMPTY.getDefinition().getRenderer();
}
@Environment(EnvType.CLIENT)
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java
index 35a5e8f96..d80c567b0 100644
--- a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java
+++ b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java
@@ -80,7 +80,7 @@ public interface FavoriteEntryType<T extends FavoriteEntry> {
default void add(FavoriteEntry... entries) {
add(false, entries);
}
-
+
@ApiStatus.Experimental
void add(boolean defaultFavorited, FavoriteEntry... entries);
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/overlay/OverlayListWidget.java b/api/src/main/java/me/shedaniel/rei/api/client/overlay/OverlayListWidget.java
index 1fa784806..57e7e8999 100644
--- a/api/src/main/java/me/shedaniel/rei/api/client/overlay/OverlayListWidget.java
+++ b/api/src/main/java/me/shedaniel/rei/api/client/overlay/OverlayListWidget.java
@@ -54,4 +54,6 @@ public interface OverlayListWidget {
* @return whether the mouse is within the overlay list widget
*/
boolean containsMouse(Point point);
+
+ void queueReloadSearch();
}
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntry.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntry.java
new file mode 100644
index 000000000..a3623970a
--- /dev/null
+++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntry.java
@@ -0,0 +1,42 @@
+/*
+ * 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.registry.entry;
+
+import me.shedaniel.rei.api.common.entry.EntryStack;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.ResourceLocation;
+import org.jetbrains.annotations.ApiStatus;
+
+@ApiStatus.Experimental
+public interface CollapsibleEntry {
+ ResourceLocation getId();
+
+ Component getName();
+
+ boolean matches(EntryStack<?> stack, long hashExact);
+
+ boolean isExpanded();
+
+ void setExpanded(boolean expanded);
+}
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntryRegistry.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntryRegistry.java
index c24ca5e2a..4de3468eb 100644
--- a/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntryRegistry.java
+++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/CollapsibleEntryRegistry.java
@@ -44,7 +44,7 @@ import java.util.function.Predicate;
* and collect tags together.
*/
@ApiStatus.Experimental
-public interface CollapsibleEntryRegistry extends Reloadable<REIClientPlugin> {
+public interface CollapsibleEntryRegistry extends Reloadable<REIClientPlugin>, List<CollapsibleEntry> {
/**
* @return the {@link CollapsibleEntryRegistry} instance
*/
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java
index 63ed14d72..49dec73bb 100644
--- a/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java
+++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/EntryRegistry.java
@@ -83,7 +83,9 @@ public interface EntryRegistry extends Reloadable<REIClientPlugin> {
* @return the unmodifiable list of filtered entry stacks,
* only available <b>after</b> plugins reload.
*/
- List<EntryStack<?>> getPreFilteredList();
+ default List<EntryStack<?>> getPreFilteredList() {
+ return PreFilteredEntryList.getInstance().getList();
+ }
/**
* Applies the filtering rules to the entry list, is rather computational expensive.
@@ -154,7 +156,9 @@ public interface EntryRegistry extends Reloadable<REIClientPlugin> {
// TODO Re-evaluate the need for this
@ApiStatus.Internal
- Collection<EntryStack<?>> refilterNew(boolean warn, Collection<EntryStack<?>> entries);
+ default Collection<EntryStack<?>> refilterNew(boolean warn, Collection<EntryStack<?>> entries) {
+ return PreFilteredEntryList.getInstance().refilterNew(warn, entries);
+ }
/**
* Checks if a stack is already registered.
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/PreFilteredEntryList.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/PreFilteredEntryList.java
new file mode 100644
index 000000000..f9bd53422
--- /dev/null
+++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/entry/PreFilteredEntryList.java
@@ -0,0 +1,51 @@
+/*
+ * 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.registry.entry;
+
+import me.shedaniel.rei.api.client.plugins.REIClientPlugin;
+import me.shedaniel.rei.api.common.entry.EntryStack;
+import me.shedaniel.rei.api.common.registry.Reloadable;
+import me.shedaniel.rei.impl.ClientInternals;
+import me.shedaniel.rei.impl.Internals;
+import org.jetbrains.annotations.ApiStatus;
+
+import java.util.Collection;
+import java.util.List;
+
+@ApiStatus.Experimental
+public interface PreFilteredEntryList extends Reloadable<REIClientPlugin> {
+ static PreFilteredEntryList getInstance() {
+ return ClientInternals.getPreFilteredEntryList();
+ }
+
+ // TODO Re-evaluate the need for this
+ @ApiStatus.Internal
+ Collection<EntryStack<?>> refilterNew(boolean warn, Collection<EntryStack<?>> entries);
+
+ /**
+ * @return the unmodifiable list of filtered entry stacks,
+ * only available <b>after</b> plugins reload.
+ */
+ List<EntryStack<?>> getList();
+}
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/search/SearchFilter.java b/api/src/main/java/me/shedaniel/rei/api/client/search/SearchFilter.java
index 80b4987df..0bc7f8fff 100644
--- a/api/src/main/java/me/shedaniel/rei/api/client/search/SearchFilter.java
+++ b/api/src/main/java/me/shedaniel/rei/api/client/search/SearchFilter.java
@@ -23,9 +23,12 @@
package me.shedaniel.rei.api.client.search;
+import it.unimi.dsi.fastutil.ints.IntIntPair;
import me.shedaniel.rei.api.common.entry.EntryStack;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
+import net.minecraft.network.chat.Style;
+import org.jetbrains.annotations.ApiStatus;
import java.util.Collection;
import java.util.function.Predicate;
@@ -80,4 +83,21 @@ public interface SearchFilter extends Predicate<EntryStack<?>> {
*/
default void prepareFilter(Collection<EntryStack<?>> stacks) {
}
+
+ /**
+ * Processes the decoration of the search filter.
+ *
+ * @param sink the decoration sink
+ */
+ @ApiStatus.Experimental
+ default void processDecoration(ParseDecorationSink sink) {
+ }
+
+ interface ParseDecorationSink {
+ void addQuote(int index);
+
+ void addSplitter(int index);
+
+ void addPart(IntIntPair range, Style style, boolean usingGrammar, Collection<IntIntPair> grammarRanges, int index);
+ }
}
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 a337e5e17..9ec3af0b1 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
@@ -58,4 +58,18 @@ public interface SearchProvider extends Reloadable<REIClientPlugin> {
*/
@ApiStatus.Experimental
SearchFilter createFilter(String filter, InputMethod<?> inputMethod);
+
+ /**
+ * Clears the search cache.
+ */
+ @ApiStatus.Experimental
+ void clearCache();
+
+ /**
+ * Returns whether the search provider has cached.
+ *
+ * @return whether the search provider has cached
+ */
+ @ApiStatus.Experimental
+ boolean hasCache();
}
diff --git a/api/src/main/java/me/shedaniel/rei/api/common/registry/ParentReloadable.java b/api/src/main/java/me/shedaniel/rei/api/common/registry/ParentReloadable.java
index 44039e240..e91f19245 100644
--- a/api/src/main/java/me/shedaniel/rei/api/common/registry/ParentReloadable.java
+++ b/api/src/main/java/me/shedaniel/rei/api/common/registry/ParentReloadable.java
@@ -24,6 +24,7 @@
package me.shedaniel.rei.api.common.registry;
import me.shedaniel.rei.api.common.plugins.REIPlugin;
+import me.shedaniel.rei.impl.Internals;
import java.util.List;
@@ -32,6 +33,10 @@ public interface ParentReloadable<P extends REIPlugin<?>> extends Reloadable<P>
void registerReloadable(Reloadable<? extends P> reloadable);
+ default <R extends Reloadable<? extends P>> void registerReloadable(Class<R> reloadableClass) {
+ registerReloadable(Internals.resolveService(reloadableClass));
+ }
+
@Override
default void startReload() {
for (ReloadStage stage : ReloadStage.values()) {
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 36456399b..60c6399fd 100644
--- a/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java
+++ b/api/src/main/java/me/shedaniel/rei/impl/ClientInternals.java
@@ -28,18 +28,17 @@ import com.mojang.serialization.DataResult;
import me.shedaniel.math.Point;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.ClientHelper;
-import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer;
import me.shedaniel.rei.api.client.favorites.FavoriteEntry;
import me.shedaniel.rei.api.client.gui.DrawableConsumer;
import me.shedaniel.rei.api.client.gui.Renderer;
import me.shedaniel.rei.api.client.gui.widgets.*;
import me.shedaniel.rei.api.client.plugins.REIClientPlugin;
+import me.shedaniel.rei.api.client.registry.entry.PreFilteredEntryList;
import me.shedaniel.rei.api.client.registry.screen.ClickArea;
import me.shedaniel.rei.api.client.view.ViewSearchBuilder;
import me.shedaniel.rei.api.common.entry.EntryIngredient;
import me.shedaniel.rei.api.common.plugins.PluginManager;
-import net.fabricmc.api.EnvType;
-import net.fabricmc.api.Environment;
+import net.minecraft.ReportedException;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.nbt.CompoundTag;
@@ -55,19 +54,17 @@ import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.function.Supplier;
+import java.util.function.*;
@ApiStatus.Internal
public final class ClientInternals {
- private static Supplier<ClientHelper> clientHelper = ClientInternals::throwNotSetup;
- private static Supplier<WidgetsProvider> widgetsProvider = ClientInternals::throwNotSetup;
- private static Supplier<ViewSearchBuilder> viewSearchBuilder = ClientInternals::throwNotSetup;
- private static Supplier<PluginManager<REIClientPlugin>> clientPluginManager = ClientInternals::throwNotSetup;
- private static Supplier<EntryRenderer<?>> emptyEntryRenderer = ClientInternals::throwNotSetup;
- private static BiFunction<Supplier<DataResult<FavoriteEntry>>, Supplier<CompoundTag>, FavoriteEntry> delegateFavoriteEntry = (supplier, toJson) -> throwNotSetup();
+ private static final ClientHelper CLIENT_HELPER = resolveService(ClientHelper.class);
+ private static final WidgetsProvider WIDGETS_PROVIDER = resolveService(WidgetsProvider.class);
+ private static final ViewSearchBuilder VIEW_SEARCH_BUILDER = resolveService(ViewSearchBuilder.class);
+ private static final PluginManager<REIClientPlugin> CLIENT_PLUGIN_MANAGER = Internals.createPluginManager(
+ REIClientPlugin.class,
+ UnaryOperator.identity());
+ private static final DelegatingFavoriteEntryProvider DELEGATE_FAVORITE_ENTRY = resolveService(DelegatingFavoriteEntryProvider.class);
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();
@@ -77,6 +74,16 @@ public final class ClientInternals {
private static Supplier<List<String>> jeiCompatMods = ClientInternals::throwNotSetup;
private static Supplier<Object> builtinClientPlugin = ClientInternals::throwNotSetup;
private static Function<List<EntryIngredient>, TooltipComponent> missingTooltip = (stacks) -> throwNotSetup();
+ private static BiConsumer<ReportedException, String> crashHandler = (exception, component) -> throwNotSetup();
+ private static Supplier<PreFilteredEntryList> preFilteredEntryList = ClientInternals::throwNotSetup;
+
+ public static <T> T resolveService(Class<T> serviceClass) {
+ return Internals.resolveService(serviceClass);
+ }
+
+ public static <T> List<T> resolveServices(Class<T> serviceClass) {
+ return Internals.resolveServices(serviceClass);
+ }
private static <T> T throwNotSetup() {
throw new AssertionError("REI Internals have not been initialized!");
@@ -108,15 +115,15 @@ public final class ClientInternals {
}
public static ClientHelper getClientHelper() {
- return clientHelper.get();
+ return CLIENT_HELPER;
}
public static WidgetsProvider getWidgetsProvider() {
- return widgetsProvider.get();
+ return WIDGETS_PROVIDER;
}
public static ViewSearchBuilder createViewSearchBuilder() {
- return viewSearchBuilder.get();
+ return VIEW_SEARCH_BUILDER;
}
public static Object getBuiltinPlugin() {
@@ -144,30 +151,33 @@ public final class ClientInternals {
}
public static FavoriteEntry delegateFavoriteEntry(Supplier<DataResult<FavoriteEntry>> supplier, Supplier<CompoundTag> toJoin) {
- return delegateFavoriteEntry.apply(supplier, toJoin);
+ return DELEGATE_FAVORITE_ENTRY.delegate(supplier, toJoin);
}
public static DataResult<FavoriteEntry> favoriteEntryFromJson(CompoundTag tag) {
return favoriteEntryFromJson.apply(tag);
}
- public static <T> EntryRenderer<T> getEmptyEntryRenderer() {
- return emptyEntryRenderer.get().cast();
- }
-
public static List<String> getJeiCompatMods() {
return jeiCompatMods.get();
}
public static PluginManager<REIClientPlugin> getPluginManager() {
- return clientPluginManager.get();
+ return CLIENT_PLUGIN_MANAGER;
}
public static TooltipComponent createMissingTooltip(List<EntryIngredient> stacks) {
return missingTooltip.apply(stacks);
}
- @Environment(EnvType.CLIENT)
+ public static PreFilteredEntryList getPreFilteredEntryList() {
+ return preFilteredEntryList.get();
+ }
+
+ public static void crash(ReportedException exception, String component) {
+ crashHandler.accept(exception, component);
+ }
+
public interface WidgetsProvider {
boolean isRenderingPanel(Panel panel);
@@ -207,4 +217,8 @@ public final class ClientInternals {
WidgetWithBounds wrapPadded(int padLeft, int padRight, int padTop, int padBottom, WidgetWithBounds widget);
}
+
+ public interface DelegatingFavoriteEntryProvider {
+ FavoriteEntry delegate(Supplier<DataResult<FavoriteEntry>> result, Supplier<CompoundTag> tag);
+ }
}
diff --git a/api/src/main/java/me/shedaniel/rei/impl/Internals.java b/api/src/main/java/me/shedaniel/rei/impl/Internals.java
index 1e64c2c57..dd24614e6 100644
--- a/api/src/main/java/me/shedaniel/rei/impl/Internals.java
+++ b/api/src/main/java/me/shedaniel/rei/impl/Internals.java
@@ -31,9 +31,9 @@ import me.shedaniel.rei.api.common.entry.comparison.EntryComparator;
import me.shedaniel.rei.api.common.entry.type.EntryDefinition;
import me.shedaniel.rei.api.common.entry.type.EntryType;
import me.shedaniel.rei.api.common.plugins.PluginManager;
+import me.shedaniel.rei.api.common.plugins.PluginView;
import me.shedaniel.rei.api.common.plugins.REIPlugin;
import me.shedaniel.rei.api.common.plugins.REIServerPlugin;
-import me.shedaniel.rei.api.common.transfer.info.MenuInfoRegistry;
import me.shedaniel.rei.impl.common.InternalLogger;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
@@ -41,31 +41,51 @@ import net.minecraft.util.Unit;
import org.jetbrains.annotations.ApiStatus;
import java.lang.reflect.Field;
-import java.util.function.Function;
+import java.util.List;
+import java.util.ServiceLoader;
import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
+import java.util.stream.Collectors;
@ApiStatus.Internal
public final class Internals {
- private static Supplier<EntryStackProvider> entryStackProvider = Internals::throwNotSetup;
- private static Supplier<EntryIngredientProvider> entryIngredientProvider = Internals::throwNotSetup;
- private static Function<ResourceLocation, EntryType<?>> entryTypeDeferred = (object) -> throwNotSetup();
- private static Supplier<PluginManager<REIPlugin<?>>> commonPluginManager = Internals::throwNotSetup;
- private static Supplier<PluginManager<REIServerPlugin>> serverPluginManager = Internals::throwNotSetup;
- private static Supplier<NbtHasherProvider> nbtHasherProvider = Internals::throwNotSetup;
- private static Function<String, CategoryIdentifier<?>> categoryIdentifier = (object) -> throwNotSetup();
- private static Supplier<MenuInfoRegistry> stubMenuInfoRegistry = Internals::throwNotSetup;
+ private static final EntryStackProvider ENTRY_STACK_PROVIDER = resolveService(EntryStackProvider.class);
+ private static final EntryIngredientProvider ENTRY_INGREDIENT_PROVIDER = resolveService(EntryIngredientProvider.class);
+ private static final DeferringEntryTypeProvider ENTRY_TYPE_DEFERRED = resolveService(DeferringEntryTypeProvider.class);
+ private static final PluginManagerConstructor PLUGIN_MANAGER_CONSTRUCTOR = resolveService(PluginManagerConstructor.class);
+ private static final PluginManager<REIPlugin<?>> COMMON_PLUGIN_MANAGER = createPluginManager(
+ (Class<REIPlugin<?>>) (Class<?>) REIPlugin.class,
+ UnaryOperator.identity());
+ private static final PluginManager<REIServerPlugin> SERVER_PLUGIN_MANAGER = createPluginManager(
+ REIServerPlugin.class,
+ view -> view.then(COMMON_PLUGIN_MANAGER.view()));
+ private static final NbtHasherProvider NBT_HASHER_PROVIDER = resolveService(NbtHasherProvider.class);
+ private static final CategoryIdentifierConstructor CATEGORY_IDENTIFIER_CONSTRUCTOR = resolveService(CategoryIdentifierConstructor.class);
private static Supplier<InternalLogger> logger = Internals::throwNotSetup;
private static <T> T throwNotSetup() {
throw new AssertionError("REI Internals have not been initialized!");
}
- @ApiStatus.Internal
- public static <T> void attachInstance(T instance, Class<T> clazz) {
- attachInstanceSupplier(instance, clazz.getSimpleName());
+ public static <T> T resolveService(Class<T> serviceClass) {
+ ServiceLoader<T> loader = ServiceLoader.load(serviceClass);
+ List<ServiceLoader.Provider<T>> providers = loader.stream().toList();
+ if (providers.isEmpty()) {
+ throw new IllegalArgumentException("No service providers found for class " + serviceClass.getName());
+ } else if (providers.size() > 1) {
+ throw new IllegalArgumentException("Multiple service providers found for class " + serviceClass.getName() + ": " +
+ providers.stream().map(provider -> provider.type().getName())
+ .collect(Collectors.joining(", ")));
+ } else {
+ return providers.get(0).get();
+ }
+ }
+
+ public static <T> List<T> resolveServices(Class<T> serviceClass) {
+ ServiceLoader<T> loader = ServiceLoader.load(serviceClass);
+ return loader.stream().map(ServiceLoader.Provider::get).toList();
}
- @ApiStatus.Internal
public static <T> void attachInstanceSupplier(T instance, String name) {
attachInstance((Supplier<T>) () -> instance, name);
}
@@ -86,31 +106,35 @@ public final class Internals {
}
public static EntryStackProvider getEntryStackProvider() {
- return entryStackProvider.get();
+ return ENTRY_STACK_PROVIDER;
}
public static EntryIngredientProvider getEntryIngredientProvider() {
- return entryIngredientProvider.get();
+ return ENTRY_INGREDIENT_PROVIDER;
}
public static EntryType<?> deferEntryType(ResourceLocation id) {
- return entryTypeDeferred.apply(id);
+ return ENTRY_TYPE_DEFERRED.get(id);
+ }
+
+ public static <P extends REIPlugin<?>> PluginManager<P> createPluginManager(Class<P> clazz, UnaryOperator<PluginView<P>> constructor) {
+ return PLUGIN_MANAGER_CONSTRUCTOR.create(clazz, constructor);
}
public static PluginManager<REIPlugin<?>> getPluginManager() {
- return commonPluginManager.get();
+ return COMMON_PLUGIN_MANAGER;
}
public static PluginManager<REIServerPlugin> getServerPluginManager() {
- return serverPluginManager.get();
+ return SERVER_PLUGIN_MANAGER;
}
public static EntryComparator<Tag> getNbtHasher(String[] ignoredKeys) {
- return nbtHasherProvider.get().provide(ignoredKeys);
+ return NBT_HASHER_PROVIDER.provide(ignoredKeys);
}
public static <T extends Display> CategoryIdentifier<T> getCategoryIdentifier(String location) {
- return (CategoryIdentifier<T>) categoryIdentifier.apply(location);
+ return CATEGORY_IDENTIFIER_CONSTRUCTOR.create(location);
}
public static InternalLogger getInternalLogger() {
@@ -137,7 +161,19 @@ public final class Internals {
EntryIngredient.Builder builder(int initialCapacity);
}
+ public interface PluginManagerConstructor {
+ <P extends REIPlugin<?>> PluginManager<P> create(Class<P> clazz, UnaryOperator<PluginView<P>> constructor);
+ }
+
public interface NbtHasherProvider {
EntryComparator<Tag> provide(String... ignoredKeys);
}
+
+ public interface DeferringEntryTypeProvider {
+ EntryType<?> get(ResourceLocation id);
+ }
+
+ public interface CategoryIdentifierConstructor {
+ <T extends Display> CategoryIdentifier<T> create(String location);
+ }
}