mirror of
https://github.com/AlmostReliable/almostunified.git
synced 2024-11-14 11:15:23 -05:00
add support for custom ingredient types and add api endpoint
This commit is contained in:
parent
259f847395
commit
ad177ad311
11 changed files with 209 additions and 7 deletions
|
@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning].
|
|||
|
||||
## Unreleased
|
||||
|
||||
- added support for custom ingredient types
|
||||
- added API endpoint for registering custom ingredient unifiers
|
||||
- fixed recipe viewer integration endpoints for Fabric
|
||||
- fixed unnecessary memory usage for debug handler
|
||||
- fixed Mekanism recipe unifier using wrong recipe keys
|
||||
|
|
|
@ -2,11 +2,13 @@ package com.almostreliable.unified.api.plugin;
|
|||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifier;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifierRegistry;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeUnifier;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeUnifierRegistry;
|
||||
|
||||
/**
|
||||
* Implemented by plugins that wish to register their own {@link RecipeUnifier}s.
|
||||
* Implemented by plugins that wish to register their own unifiers.
|
||||
* <p>
|
||||
* NeoForge plugins should attach the {@link AlmostUnifiedNeoPlugin} annotation for discovery.<br>
|
||||
* Fabric plugins should use the {@code almostunified} entrypoint.
|
||||
|
@ -34,4 +36,12 @@ public interface AlmostUnifiedPlugin {
|
|||
* @param registry the {@link RecipeUnifierRegistry} to register with
|
||||
*/
|
||||
default void registerRecipeUnifiers(RecipeUnifierRegistry registry) {}
|
||||
|
||||
/**
|
||||
* Allows registration of custom {@link CustomIngredientUnifier}s.
|
||||
*
|
||||
* @param registry the {@link CustomIngredientUnifierRegistry} to register with
|
||||
* @since 1.2.0
|
||||
*/
|
||||
default void registerCustomIngredientUnifiers(CustomIngredientUnifierRegistry registry) {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.almostreliable.unified.api.unification.recipe;
|
||||
|
||||
import com.almostreliable.unified.api.plugin.AlmostUnifiedPlugin;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Implemented on custom ingredient unifiers.
|
||||
* <p>
|
||||
* Custom unifiers will tell Almost Unified how to handle specific ingredients.<br>
|
||||
* When the unification process encounters a {@link JsonObject} that contains a {@code type} property, it will check
|
||||
* if a custom unifier is associated with that type and call
|
||||
* {@link CustomIngredientUnifier#unify(UnificationHelper, JsonObject)}. If no unifier is found, the default
|
||||
* transformation will be used.
|
||||
* <p>
|
||||
* Unifiers can be registered for a specific type. Registering a custom unifier will skip the default transformation
|
||||
* of the {@link JsonObject} for the given type.
|
||||
* <p>
|
||||
* Registration is handled in {@link CustomIngredientUnifierRegistry} which can be obtained in
|
||||
* {@link AlmostUnifiedPlugin#registerCustomIngredientUnifiers(CustomIngredientUnifierRegistry)}.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface CustomIngredientUnifier {
|
||||
|
||||
/**
|
||||
* Uses of the given {@link UnificationHelper} to unify the given ingredient {@link JsonObject}.
|
||||
* <p>
|
||||
* The unifier only receives the serialized ingredient as {@link JsonObject} without the {@code type} property.<br>
|
||||
* If changes to the {@link JsonObject} are necessary, the original {@link JsonObject} should be modified in-place.
|
||||
* The method should return true if the {@link JsonObject} was modified.
|
||||
*
|
||||
* @param helper the helper to aid in the unification
|
||||
* @param jsonObject the ingredient to unify as a {@link JsonObject}
|
||||
* @return true if the ingredient was changed, false otherwise
|
||||
*/
|
||||
boolean unify(UnificationHelper helper, JsonObject jsonObject);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.almostreliable.unified.api.unification.recipe;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The registry holding all {@link CustomIngredientUnifier}s.
|
||||
* <p>
|
||||
* {@link CustomIngredientUnifier}s can be registered per type.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public interface CustomIngredientUnifierRegistry {
|
||||
|
||||
/**
|
||||
* Registers a {@link CustomIngredientUnifier} for a specific type.
|
||||
* <p>
|
||||
* If a custom ingredient unifier is associated with the given type, the internal transformation for the
|
||||
* {@link JsonObject} will be skipped.
|
||||
*
|
||||
* @param type the type to register the custom ingredient unifier for
|
||||
* @param customIngredientUnifier the custom ingredient unifier
|
||||
*/
|
||||
void registerForType(ResourceLocation type, CustomIngredientUnifier customIngredientUnifier);
|
||||
|
||||
/**
|
||||
* Retrieves the respective {@link CustomIngredientUnifier} for the given type.
|
||||
*
|
||||
* @param type the type to retrieve the {@link CustomIngredientUnifier} for
|
||||
* @return the {@link CustomIngredientUnifier} for the given type
|
||||
*/
|
||||
@Nullable
|
||||
CustomIngredientUnifier getCustomIngredientUnifier(ResourceLocation type);
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package com.almostreliable.unified.api.unification.recipe;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.almostreliable.unified.api.constant.RecipeConstants;
|
||||
import com.almostreliable.unified.api.unification.TagSubstitutions;
|
||||
import com.almostreliable.unified.api.unification.UnificationLookup;
|
||||
|
@ -35,6 +37,16 @@ public interface UnificationHelper {
|
|||
*/
|
||||
UnificationLookup getUnificationLookup();
|
||||
|
||||
/**
|
||||
* Returns the {@link CustomIngredientUnifier} for the given type used in the {@link JsonObject}.
|
||||
*
|
||||
* @param type the value of the type property of the {@link JsonObject} as a {@link ResourceLocation}
|
||||
* @return the {@link CustomIngredientUnifier} or null if no custom unifier is associated with the given type
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Nullable
|
||||
CustomIngredientUnifier getCustomIngredientUnifier(ResourceLocation type);
|
||||
|
||||
/**
|
||||
* Fetches all entries of the given {@link RecipeJson} under the specified keys and unifies them as inputs.<br>
|
||||
* Entries treated as inputs will be converted to tags if possible.
|
||||
|
|
|
@ -5,6 +5,7 @@ import net.minecraft.resources.ResourceLocation;
|
|||
import com.almostreliable.unified.AlmostUnifiedCommon;
|
||||
import com.almostreliable.unified.api.constant.ModConstants;
|
||||
import com.almostreliable.unified.api.plugin.AlmostUnifiedPlugin;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifierRegistry;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeUnifierRegistry;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -61,6 +62,10 @@ public final class PluginManager {
|
|||
INSTANCE = new PluginManager(sortedPlugins);
|
||||
}
|
||||
|
||||
public void registerCustomIngredientUnifiers(CustomIngredientUnifierRegistry registry) {
|
||||
forEachPlugin(plugin -> plugin.registerCustomIngredientUnifiers(registry));
|
||||
}
|
||||
|
||||
public void registerRecipeUnifiers(RecipeUnifierRegistry registry) {
|
||||
forEachPlugin(plugin -> plugin.registerRecipeUnifiers(registry));
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.almostreliable.unified.api.unification.TagSubstitutions;
|
|||
import com.almostreliable.unified.api.unification.UnificationEntry;
|
||||
import com.almostreliable.unified.api.unification.UnificationLookup;
|
||||
import com.almostreliable.unified.api.unification.UnificationSettings;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifierRegistry;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeUnifierRegistry;
|
||||
import com.almostreliable.unified.compat.PluginManager;
|
||||
import com.almostreliable.unified.compat.viewer.ItemHider;
|
||||
|
@ -25,6 +26,7 @@ import com.almostreliable.unified.config.UnificationConfig;
|
|||
import com.almostreliable.unified.unification.TagInheritance;
|
||||
import com.almostreliable.unified.unification.TagSubstitutionsImpl;
|
||||
import com.almostreliable.unified.unification.UnificationSettingsImpl;
|
||||
import com.almostreliable.unified.unification.recipe.CustomIngredientUnifierRegistryImpl;
|
||||
import com.almostreliable.unified.unification.recipe.RecipeTransformer;
|
||||
import com.almostreliable.unified.unification.recipe.RecipeUnifierRegistryImpl;
|
||||
import com.almostreliable.unified.utils.DebugHandler;
|
||||
|
@ -48,14 +50,16 @@ import java.util.stream.Collectors;
|
|||
public final class AlmostUnifiedRuntimeImpl implements AlmostUnifiedRuntime {
|
||||
|
||||
private final Collection<? extends UnificationSettings> unificationSettings;
|
||||
private final CustomIngredientUnifierRegistry customIngredientUnifierRegistry;
|
||||
private final RecipeUnifierRegistry recipeUnifierRegistry;
|
||||
private final TagSubstitutions tagSubstitutions;
|
||||
private final Placeholders placeholders;
|
||||
private final UnificationLookup compositeUnificationLookup;
|
||||
private final DebugHandler debugHandler;
|
||||
|
||||
private AlmostUnifiedRuntimeImpl(Collection<? extends UnificationSettings> unificationSettings, RecipeUnifierRegistry recipeUnifierRegistry, TagSubstitutions tagSubstitutions, Placeholders placeholders, DebugConfig debugConfig) {
|
||||
private AlmostUnifiedRuntimeImpl(Collection<? extends UnificationSettings> unificationSettings, CustomIngredientUnifierRegistry customIngredientUnifierRegistry, RecipeUnifierRegistry recipeUnifierRegistry, TagSubstitutions tagSubstitutions, Placeholders placeholders, DebugConfig debugConfig) {
|
||||
this.unificationSettings = unificationSettings;
|
||||
this.customIngredientUnifierRegistry = customIngredientUnifierRegistry;
|
||||
this.recipeUnifierRegistry = recipeUnifierRegistry;
|
||||
this.tagSubstitutions = tagSubstitutions;
|
||||
this.placeholders = placeholders;
|
||||
|
@ -79,6 +83,8 @@ public final class AlmostUnifiedRuntimeImpl implements AlmostUnifiedRuntime {
|
|||
debugConfig.shouldLogInvalidTags()
|
||||
);
|
||||
|
||||
CustomIngredientUnifierRegistry customIngredientUnifierRegistry = new CustomIngredientUnifierRegistryImpl();
|
||||
PluginManager.instance().registerCustomIngredientUnifiers(customIngredientUnifierRegistry);
|
||||
RecipeUnifierRegistry recipeUnifierRegistry = new RecipeUnifierRegistryImpl();
|
||||
PluginManager.instance().registerRecipeUnifiers(recipeUnifierRegistry);
|
||||
// TODO: add plugin support for registering config defaults
|
||||
|
@ -102,6 +108,7 @@ public final class AlmostUnifiedRuntimeImpl implements AlmostUnifiedRuntime {
|
|||
|
||||
return new AlmostUnifiedRuntimeImpl(
|
||||
unificationSettings,
|
||||
customIngredientUnifierRegistry,
|
||||
recipeUnifierRegistry,
|
||||
tagSubstitutions,
|
||||
placeholderConfig,
|
||||
|
@ -191,7 +198,9 @@ public final class AlmostUnifiedRuntimeImpl implements AlmostUnifiedRuntime {
|
|||
debugHandler.onRunStart(recipes, compositeUnificationLookup);
|
||||
|
||||
debugHandler.measure(() -> {
|
||||
var transformer = new RecipeTransformer(recipeUnifierRegistry, unificationSettings);
|
||||
var transformer = new RecipeTransformer(customIngredientUnifierRegistry,
|
||||
recipeUnifierRegistry,
|
||||
unificationSettings);
|
||||
return transformer.transformRecipes(recipes);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package com.almostreliable.unified.unification.recipe;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifier;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifierRegistry;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CustomIngredientUnifierRegistryImpl implements CustomIngredientUnifierRegistry {
|
||||
|
||||
private final Map<ResourceLocation, CustomIngredientUnifier> ingredientUnifiersByType = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void registerForType(ResourceLocation type, CustomIngredientUnifier customIngredientUnifier) {
|
||||
ingredientUnifiersByType.put(type, customIngredientUnifier);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CustomIngredientUnifier getCustomIngredientUnifier(ResourceLocation type) {
|
||||
return ingredientUnifiersByType.get(type);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import net.minecraft.resources.ResourceLocation;
|
|||
import com.almostreliable.unified.AlmostUnifiedCommon;
|
||||
import com.almostreliable.unified.api.unification.UnificationLookup;
|
||||
import com.almostreliable.unified.api.unification.UnificationSettings;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifierRegistry;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeJson;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeUnifier;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeUnifierRegistry;
|
||||
|
@ -36,12 +37,14 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class RecipeTransformer {
|
||||
|
||||
private final CustomIngredientUnifierRegistry customIngredientUnifierRegistry;
|
||||
private final RecipeUnifierRegistry factory;
|
||||
private final Collection<? extends UnificationSettings> unificationSettings;
|
||||
private final DuplicateConfig duplicateConfig;
|
||||
private final RecipeTypePropertiesLogger propertiesLogger = new RecipeTypePropertiesLogger();
|
||||
|
||||
public RecipeTransformer(RecipeUnifierRegistry factory, Collection<? extends UnificationSettings> unificationSettings) {
|
||||
public RecipeTransformer(CustomIngredientUnifierRegistry customIngredientUnifierRegistry, RecipeUnifierRegistry factory, Collection<? extends UnificationSettings> unificationSettings) {
|
||||
this.customIngredientUnifierRegistry = customIngredientUnifierRegistry;
|
||||
this.factory = factory;
|
||||
this.unificationSettings = unificationSettings;
|
||||
this.duplicateConfig = Config.load(DuplicateConfig.NAME, DuplicateConfig.SERIALIZER);
|
||||
|
@ -188,7 +191,7 @@ public class RecipeTransformer {
|
|||
continue;
|
||||
}
|
||||
|
||||
UnificationHelperImpl helper = new UnificationHelperImpl(settings);
|
||||
UnificationHelperImpl helper = new UnificationHelperImpl(customIngredientUnifierRegistry, settings);
|
||||
RecipeUnifier unifier = factory.getRecipeUnifier(recipe);
|
||||
unifier.unify(helper, json);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import net.minecraft.tags.TagKey;
|
|||
import com.almostreliable.unified.api.AlmostUnified;
|
||||
import com.almostreliable.unified.api.constant.RecipeConstants;
|
||||
import com.almostreliable.unified.api.unification.UnificationLookup;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifier;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifierRegistry;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeJson;
|
||||
import com.almostreliable.unified.api.unification.recipe.UnificationHelper;
|
||||
|
||||
|
@ -18,7 +20,14 @@ import com.google.gson.JsonPrimitive;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public record UnificationHelperImpl(UnificationLookup getUnificationLookup) implements UnificationHelper {
|
||||
public record UnificationHelperImpl(CustomIngredientUnifierRegistry customIngredientUnifierRegistry,
|
||||
UnificationLookup getUnificationLookup) implements UnificationHelper {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CustomIngredientUnifier getCustomIngredientUnifier(ResourceLocation type) {
|
||||
return customIngredientUnifierRegistry.getCustomIngredientUnifier(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unifyInputs(RecipeJson recipe, String... keys) {
|
||||
|
@ -57,6 +66,9 @@ public record UnificationHelperImpl(UnificationLookup getUnificationLookup) impl
|
|||
|
||||
@Override
|
||||
public boolean unifyInputObject(JsonObject jsonObject, String... keys) {
|
||||
Boolean modified = handleCustomIngredientUnification(jsonObject);
|
||||
if (modified != null) return modified;
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
for (String key : keys.length == 0 ? RecipeConstants.DEFAULT_INPUT_INNER_KEYS : keys) {
|
||||
|
@ -157,6 +169,9 @@ public record UnificationHelperImpl(UnificationLookup getUnificationLookup) impl
|
|||
|
||||
@Override
|
||||
public boolean unifyOutputObject(JsonObject jsonObject, boolean tagsToItems, String... keys) {
|
||||
Boolean modified = handleCustomIngredientUnification(jsonObject);
|
||||
if (modified != null) return modified;
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
for (String key : keys.length == 0 ? RecipeConstants.DEFAULT_OUTPUT_INNER_KEYS : keys) {
|
||||
|
@ -220,4 +235,34 @@ public record UnificationHelperImpl(UnificationLookup getUnificationLookup) impl
|
|||
if (entry == null || entry.id().equals(item)) return null;
|
||||
return new JsonPrimitive(entry.id().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles custom ingredient unification.
|
||||
* <p>
|
||||
* This method checks if the given {@link JsonObject} has a {@code type} property and if a
|
||||
* {@link CustomIngredientUnifier} is associated with that type. If not, it will return null and the default logic
|
||||
* should continue. Otherwise, it will return whether the {@link CustomIngredientUnifier} modified the
|
||||
* {@link JsonObject}.
|
||||
*
|
||||
* @param jsonObject the ingredient {@link JsonObject} to unify
|
||||
* @return true if the ingredient was changed, false otherwise, or null if no unifier was found
|
||||
*/
|
||||
@Nullable
|
||||
private Boolean handleCustomIngredientUnification(JsonObject jsonObject) {
|
||||
if (!(jsonObject.get("type") instanceof JsonPrimitive jsonPrimitive)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ResourceLocation type = ResourceLocation.tryParse(jsonPrimitive.getAsString());
|
||||
if (type == null) return null;
|
||||
|
||||
CustomIngredientUnifier unifier = getCustomIngredientUnifier(type);
|
||||
if (unifier == null) return null;
|
||||
|
||||
jsonObject.remove("type"); // avoids looping when calling helper methods within ingredient unifiers
|
||||
boolean changed = unifier.unify(this, jsonObject);
|
||||
jsonObject.addProperty("type", type.toString());
|
||||
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import com.almostreliable.unified.api.unification.ModPriorities;
|
|||
import com.almostreliable.unified.api.unification.StoneVariants;
|
||||
import com.almostreliable.unified.api.unification.TagSubstitutions;
|
||||
import com.almostreliable.unified.api.unification.UnificationLookup;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifier;
|
||||
import com.almostreliable.unified.api.unification.recipe.CustomIngredientUnifierRegistry;
|
||||
import com.almostreliable.unified.api.unification.recipe.RecipeUnifier;
|
||||
import com.almostreliable.unified.api.unification.recipe.UnificationHelper;
|
||||
import com.almostreliable.unified.unification.ModPrioritiesImpl;
|
||||
|
@ -109,7 +111,7 @@ public class TestUtils {
|
|||
|
||||
|
||||
public static UnificationHelper recipeHelper() {
|
||||
return new UnificationHelperImpl(unificationLookup());
|
||||
return new UnificationHelperImpl(new CustomIngredientUnifierRegistryImpl(), unificationLookup());
|
||||
}
|
||||
|
||||
public static void assertUnify(RecipeUnifier unifier, String jsonActual, String jsonExpected) {
|
||||
|
@ -174,4 +176,16 @@ public class TestUtils {
|
|||
|
||||
fail(sb.toString());
|
||||
}
|
||||
|
||||
private static class CustomIngredientUnifierRegistryImpl implements CustomIngredientUnifierRegistry {
|
||||
|
||||
@Override
|
||||
public void registerForType(ResourceLocation type, CustomIngredientUnifier customIngredientUnifier) {}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CustomIngredientUnifier getCustomIngredientUnifier(ResourceLocation type) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue