diff --git a/examples/postInit/roots.groovy b/examples/postInit/roots.groovy
index 82e829b1f..5236f3a0a 100644
--- a/examples/postInit/roots.groovy
+++ b/examples/postInit/roots.groovy
@@ -208,8 +208,8 @@ mods.roots.pacifist.recipeBuilder()
// Predicates:
-// Predicates are used in Transmution and RunicShearBlock. They either match all blockstates of a block, or all blockstates
-// that have the given properties that match the input blockstate.
+// Predicates are used in Transmutation and RunicShearBlock. They either match all blockstates of a block, or all
+// blockstates that have the given properties that match the input blockstate.
mods.roots.predicates.stateBuilder()
.blockstate(blockstate('minecraft:red_flower'))
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Admonition.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Admonition.java
index 52cf9b91d..a735ed589 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Admonition.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Admonition.java
@@ -18,7 +18,7 @@
* The localization key for the admonition description, should be in the format of
*
*
- * groovyscript.wiki.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.note{index of note in array}
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.note{index}
*
*
* @return localization key for the admonition description
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Example.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Example.java
index 04c47382a..bb9c3b9c9 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Example.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Example.java
@@ -27,10 +27,15 @@
public @interface Example {
/**
- * For recipe builders, this will be a string that is a valid one-line series of methods to create a Recipe Builder that will
+ * For basic recipe builders, this will be a string that is a valid one-line series of methods to create a Recipe Builder that will
* pass the {@link com.cleanroommc.groovyscript.helper.recipe.IRecipeBuilder#validate() IRecipeBuilder#validate()} check and be successfully registered.
- *
- * For methods, this should be exclusive the parameters of the method. e.g. {@code "item('minecraft:clay')"}
+ * {@code ".do('thing').and('other')"}
+ *
+ * For complex recipe builders, those that have one or more parameters, in the creation method,
+ * the above is true after an initial segment for the creation. {@code "('init').do('thing').and('other')"}
+ *
+ * For methods, this should be exclusive the parameters of the method. e.g. {@code "item('minecraft:clay')"}
+ *
* Any comments for the wiki should be marked by
*
* /*()*{@literal /}
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/MethodDescription.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/MethodDescription.java
index 35b1688fc..598d2f136 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/MethodDescription.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/MethodDescription.java
@@ -11,9 +11,15 @@
* All fields are optional, and most have default values generated in {@link Example}.
*
*
+ * - {@link #method()} either contains nothing if annotated on a method or contains a
+ * string that targets the desired method in conjunction with {@link MethodOverride}.
+ * To target a method, if only a single method has the given name, excluding
+ * bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist},
+ * the target may be the method name.
+ * Otherwise, the target must be the name and full descriptor of the method.
* - {@link #description()} is a localization key that is autogenerated to be
*
- * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.{@link Method#getName()}
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}
*
*
* - {@link #example()} is an array of {@link Example}s In situations where either a single {@link Example} with multiple lines or
@@ -28,6 +34,22 @@
@Target(ElementType.METHOD)
public @interface MethodDescription {
+ /**
+ * If this {@link MethodDescription} annotation is attached to a method, this element is set to the name of the method they are attached to.
+ * When annotated on a method directly, this should not be set, as it has no functionality.
+ *
+ * If this is not annotated to a method, this should either be the method name
+ * (if only a single method has the given name)
+ * or needs to be the name and full descriptor of the method.
+ *
+ * Methods that are bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist}
+ * cannot be targeted.
+ *
+ * @return the target method, if not annotated to a method directly.
+ * @see MethodOverride
+ */
+ String method() default "";
+
/**
* The localization key for a description of the compat.
*
@@ -35,9 +57,9 @@
* {@link net.minecraft.client.resources.I18n#format(String, Object...) I18n.format(description())}
*
* If this is empty, will fall back to generating a description based on
- * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.{@link Method#getName()}.
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.
* Then, if that does not have a lang key defined, it will attempt to use a global lang key based on the method name
- * groovyscript.wiki.{@link Method#getName()}
+ * groovyscript.wiki.{@link Method#getName() {methodName}}
* if that also does not have a lang key defined, will log a missing key in the {@code groovy.log} file.
*
* @return localization key for method description
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/MethodOverride.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/MethodOverride.java
new file mode 100644
index 000000000..3b9b101ae
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/MethodOverride.java
@@ -0,0 +1,39 @@
+package com.cleanroommc.groovyscript.api.documentation.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Allows a {@link RegistryDescription} to override any
+ * {@link MethodDescription} or {@link RecipeBuilderDescription} declarations.
+ *
+ * Methods can be referred to by name if there is only one method with the given name
+ * in the class, otherwise must be referred to by the method name + method signature.
+ *
+ * While this can be used for any method, it is preferred to only use it for
+ * methods that require it - namely, methods that are declared in a parent class
+ * and not overridden in the focused class.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({}) // No targets allowed
+public @interface MethodOverride {
+
+ /**
+ * An override to other {@link MethodDescription} declarations, and only used for {@link MethodDescription} instances which
+ * should have custom data for the class they are accessed from.
+ *
+ * @return array of method description annotations for the class
+ * @see MethodDescription
+ */
+ MethodDescription[] method() default {};
+
+ /**
+ * An override to other {@link RecipeBuilderDescription} declarations, and only used for {@link RecipeBuilderDescription} instances which
+ * should have custom data for the class they are accessed from.
+ *
+ * @return array of method description annotations for the class
+ * @see RecipeBuilderDescription
+ */
+ RecipeBuilderDescription[] recipeBuilder() default {};
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Property.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Property.java
index 22b61e6ad..3248f561c 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Property.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/Property.java
@@ -16,7 +16,7 @@
*
* -
* {@link ElementType#METHOD}: Marks the field targeted by {@link #property()} within the class the attached method returns with this {@link Property}.
- * Can only be attached via being inside {@link RecipeBuilderDescription#requirement()}.
+ * Can be attached via being inside {@link RecipeBuilderOverride#requirement()}.
*
*
*
@@ -24,7 +24,7 @@
*
* - {@link #value()} is a localization key that is autogenerated to be
*
- * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link Field#getName()}.value
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Field#getName() {fieldName}}.value
*
* and states what the property does.
*
@@ -53,7 +53,7 @@
/**
* The localization key for the name of the compat, will default to generating
*
- * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.{@link Field#getName()}.value
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Field#getName() {fieldName}}.value
*
*
* @return localization key for what the target field will accomplish
@@ -219,7 +219,7 @@
* Wrapper to allow repeatable instances of {@link Property}.
* If more than one {@link Property} is applied to anywhere other than a class, it will generate an error.
* For a given Field. only a single {@link Property} should be attached,
- * and for a given Method, all {@link Property} annotations should be placed inside {@link RecipeBuilderDescription#requirement()}
+ * and for a given Method, all {@link Property} annotations should be placed inside {@link RecipeBuilderOverride#requirement()}
*
* @see Property
*/
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderDescription.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderDescription.java
index a4f6416fd..77eea1917 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderDescription.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderDescription.java
@@ -4,7 +4,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import java.lang.reflect.Field;
+import java.lang.reflect.Method;
/**
* Marks the given Method as the initializing method for a Recipe Builder, indicating it returns a Recipe Builder class.
@@ -12,13 +12,29 @@
* allowing chaining of methods to quickly and cleanly create complicated objects which may or may not require some values.
*
*
- * - {@link #example()} is an array of {@link Example}s In situations where either a single {@link Example} with multiple lines or
- * multiple {@link Example}s could be used, using multiple {@link Example}s is preferable.
- * - {@link #requirement()} is a localization key that is autogenerated to be
+ *
- {@link #title()} is a localization key that is autogenerated to be
*
- * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.{@link Field#getName()}
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.title
*
+ * to name the Recipe Builder.
*
+ * - {@link #description()} is a localization key that is autogenerated to be
+ *
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.description
+ *
+ * to describe the method used to create the Recipe Builder.
+ *
+ * - {@link #method()} either contains nothing if annotated on a method or contains a
+ * string that targets the desired method in conjunction with {@link MethodOverride}.
+ * To target a method, if only a single method has the given name, excluding
+ * bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist},
+ * the target may be the method name.
+ * Otherwise, the target must be the name and full descriptor of the method.
+ * - {@link #clazz()} is the class being targeted by the recipe builder. By default this is the return value of the method.
+ * - {@link #example()} is an array of {@link Example}s In situations where either a single {@link Example} with multiple lines or
+ * multiple {@link Example}s could be used, using multiple {@link Example}s is preferable.
+ * - {@link #override()} allows creating overrides for the {@link Property}, {@link RecipeBuilderMethodDescription}, and {@link RecipeBuilderRegistrationMethod}
+ * annotated in the builder using {@link RecipeBuilderOverride}.
* - {@link #priority()} is an integer that influences the sorting of the {@link RecipeBuilderDescription} relative to other {@link RecipeBuilderDescription}s.
*
*/
@@ -26,6 +42,63 @@
@Target(ElementType.METHOD)
public @interface RecipeBuilderDescription {
+ /**
+ * The localization key for the name of the builder, if different from Recipe Builder.
+ *
+ * This should be used when there is more than one way to create a Recipe Builder
+ * for the given class.
+ *
+ * Generates the title via minecraft's localization files via
+ * {@link net.minecraft.client.resources.I18n#format(String, Object...) I18n.format(description())}
+ *
+ * If this is empty, will fall back to generating a description based on
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.title.
+ * Then, if that does not have a lang key defined, it will use the global default for recipe builders of
+ * groovyscript.wiki.recipe_builder.title.
+ *
+ * @return localization key for method title
+ */
+ String title() default "";
+
+ /**
+ * The localization key for a description of the compat.
+ *
+ * This should always be used when the creation method accepts parameters.
+ * In most cases this should be changed so that each parameter is an individual builder method,
+ * but in some situations this is not possible, and so must be documented accordingly.
+ *
+ * When a builder method with one or more parameters does not have a localization key set,
+ * if it does not use a lang key, it will log a missing key in the {@code groovy.log} file.
+ *
+ * Generates a description via minecraft's localization files via
+ * {@link net.minecraft.client.resources.I18n#format(String, Object...) I18n.format(description())}
+ *
+ * If this is empty, will fall back to generating a description based on
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.{@link Method#getName() {methodName}}.description.
+ * Then, if that does not have a lang key defined, it will use the global default for recipe builders of
+ * groovyscript.wiki.recipe_builder.description.
+ *
+ * @return localization key for method description
+ */
+ String description() default "";
+
+ /**
+ * If this {@link RecipeBuilderDescription} annotation is attached to a method, this element is set to the name of the method they are attached to.
+ * When annotated on a method directly, this should not be set, as it has no functionality.
+ *
+ * @return the target method, if not annotated to a method directly.
+ * @see MethodOverride
+ */
+ String method() default "";
+
+ /**
+ * The builder class. By default, this will use the return class of the target method.
+ * If this is undesired, specify the real class here.
+ *
+ * @return the class used by the builder, if different from the return type of the target method
+ */
+ Class> clazz() default void.class;
+
/**
* An array of examples, which will then be formatted and generated for both the wiki and the text script files.
*
@@ -40,9 +113,24 @@
*
* @return array of requirements unique to the recipe builder being accessed via this method
* @see Property
+ * @deprecated use {@link #override()} and {@link RecipeBuilderOverride#requirement()}
*/
+ @Deprecated
Property[] requirement() default {};
+ /**
+ * Allows overriding the {@link Property}, {@link RecipeBuilderMethodDescription}, and {@link RecipeBuilderRegistrationMethod} annotations
+ * for the builder class.
+ * This should only be used in situations where custom data that does not apply to the class normally
+ * is used.
+ *
+ * @return overrides for the Recipe Builder annotations
+ * @see Property
+ * @see RecipeBuilderMethodDescription
+ * @see RecipeBuilderRegistrationMethod
+ */
+ RecipeBuilderOverride override() default @RecipeBuilderOverride;
+
/**
* Priority of the method, relative to other Recipe Builder methods in the same class.
* Priorities sort entries such that lowest is first, with ties being broken via alphabetical sorting of the method name.
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderMethodDescription.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderMethodDescription.java
index 38e42f9e8..27a2be03a 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderMethodDescription.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderMethodDescription.java
@@ -12,7 +12,13 @@
* allowing chaining of methods to quickly and cleanly create complicated objects which may or may not require some values.
* The field element is autogenerated to be equal to the method name by default.
*
- * - {@link #field()} is an array that defaults to {@link Method#getName()} if not overridden, and indicates the target field(s) that the method modifies.
+ * - {@link #method()} either contains nothing if annotated on a method or contains a
+ * string that targets the desired method in conjunction with {@link RecipeBuilderOverride}.
+ * To target a method, if only a single method has the given name, excluding
+ * bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist},
+ * the target may be the method name.
+ * Otherwise, the target must be the name and full descriptor of the method.
+ * - {@link #field()} is an array that defaults to {@link Method#getName() Method#getName()} if not overridden, and indicates the target field(s) that the method modifies.
* - {@link #priority()} is an integer that influences the sorting of the {@link RecipeBuilderMethodDescription} relative to other {@link RecipeBuilderMethodDescription}s.
*
*/
@@ -20,6 +26,22 @@
@Target(ElementType.METHOD)
public @interface RecipeBuilderMethodDescription {
+ /**
+ * If this {@link RecipeBuilderMethodDescription} annotation is attached to a method, this element is set to the name of the method they are attached to.
+ * When annotated on a method directly, this should not be set, as it has no functionality.
+ *
+ * If this is not annotated to a method, this should either be the method name
+ * (if only a single method has the given name)
+ * or needs to be the name and full descriptor of the method.
+ *
+ * Methods that are bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist}
+ * cannot be targeted.
+ *
+ * @return the target method, if not annotated to a method directly.
+ * @see RecipeBuilderOverride
+ */
+ String method() default "";
+
/**
* An array of all fields this method modifies. By default, it checks for a field with the same name as the method.
*
@@ -29,7 +51,7 @@
/**
* Priority of the method, relative to other {@link RecipeBuilderMethodDescription}s modifying the shared {@link Property}.
- * Priorities sort entries such that lowest is first, then by the length of {@link Method#getName()}, then by {@link String#compareToIgnoreCase} of {@link Method#getName()}.
+ * Priorities sort entries such that lowest is first, then by the length of {@link Method#getName() Method#getName()}, then by {@link String#compareToIgnoreCase} of {@link Method#getName() Method#getName()}.
*
* @return the method priority
*/
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderOverride.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderOverride.java
new file mode 100644
index 000000000..848944676
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderOverride.java
@@ -0,0 +1,48 @@
+package com.cleanroommc.groovyscript.api.documentation.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Allows a {@link RegistryDescription} to override any
+ * {@link RecipeBuilderMethodDescription}, {@link RecipeBuilderRegistrationMethod}, or {@link Property} declarations.
+ *
+ * Methods can be referred to by name if there is only one method with the given name
+ * in the class, otherwise must be referred to by the method name + method signature.
+ *
+ * While this can be used for any method, it is preferred to only use it for
+ * methods that require it - namely, methods that are declared in a parent class
+ * and not overridden in the focused class.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({}) // No targets allowed
+public @interface RecipeBuilderOverride {
+
+ /**
+ * An override to other {@link Property} declarations,
+ * and should only be used for {@link Property} instances which
+ * should have custom data for the class they are accessed from.
+ *
+ * @return array of property annotations for fields for the builder class
+ */
+ Property[] requirement() default {};
+
+ /**
+ * An override to other {@link RecipeBuilderMethodDescription} declarations,
+ * and should only be used for {@link RecipeBuilderMethodDescription} instances which
+ * should have custom data for the class they are accessed from.
+ *
+ * @return array of method description annotations for the builder class
+ */
+ RecipeBuilderMethodDescription[] method() default {};
+
+ /**
+ * An override to other {@link RecipeBuilderRegistrationMethod} declarations,
+ * and should only be used for {@link RecipeBuilderRegistrationMethod} instances which
+ * should have custom data for the class they are accessed from.
+ *
+ * @return array of registry annotations for the builder class
+ */
+ RecipeBuilderRegistrationMethod[] register() default {};
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderRegistrationMethod.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderRegistrationMethod.java
index 78fe53263..ca5eb5e58 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderRegistrationMethod.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RecipeBuilderRegistrationMethod.java
@@ -8,11 +8,42 @@
/**
* Indicates that the method is the final step used in a RecipeBuilder, and adds the recipe created
* by the prior methods of the RecipeBuilder to the registry.
+ *
+ * In most cases, there will only be a single registration method.
+ * By convention, the name for this method should be {@code register}.
+ *
+ *
+ * - {@link #method()} either contains nothing if annotated on a method or contains a
+ * string that targets the desired method in conjunction with {@link RecipeBuilderOverride}.
+ * To target a method, if only a single method has the given name, excluding
+ * bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist},
+ * the target may be the method name.
+ * Otherwise, the target must be the name and full descriptor of the method.
+ * - {@link #hierarchy()} is an integer that controls the precedence of the {@link RecipeBuilderRegistrationMethod} annotation when multiple versions of it exist for a single field.
+ * A lower hierarchy overrides a higher one, with the default having a value of 10.
+ * - {@link #priority()} is an integer that influences the sorting of the {@link RecipeBuilderRegistrationMethod} relative to other {@link RecipeBuilderRegistrationMethod RecipeBuilderRegistrationMethods}.
+ *
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RecipeBuilderRegistrationMethod {
+ /**
+ * If this {@link RecipeBuilderDescription} annotation is attached to a method, this element is set to the name of the method they are attached to.
+ * When annotated on a method directly, this should not be set, as it has no functionality.
+ *
+ * If this is not annotated to a method, this should either be the method name
+ * (if only a single method has the given name)
+ * or needs to be the name and full descriptor of the method.
+ *
+ * Methods that are bridge, non-public, Object, or methods annotated with {@link com.cleanroommc.groovyscript.api.GroovyBlacklist}
+ * cannot be targeted.
+ *
+ * @return the target method, if not annotated to a method directly.
+ * @see MethodOverride
+ */
+ String method() default "";
+
/**
* Hierarchy of the property, relative to other properties applying to the same method.
* Annotations on methods that return {@link Object} are of lower priority by default.
diff --git a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RegistryDescription.java b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RegistryDescription.java
index ad81d596c..93aff28e3 100644
--- a/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RegistryDescription.java
+++ b/src/main/java/com/cleanroommc/groovyscript/api/documentation/annotations/RegistryDescription.java
@@ -11,15 +11,19 @@
*
* -
* {@link #title()} is a localization key that is autogenerated with a base of
- *
groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.title
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.title
*
* -
* {@link #description()} is a localization key that is autogenerated with a base of
- *
groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.description
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.description
*
* - {@link #linkGenerator()} is the name, typically a modid, of a {@link com.cleanroommc.groovyscript.documentation.linkgenerator.ILinkGenerator ILinkGenerator}
* contained in {@link com.cleanroommc.groovyscript.documentation.linkgenerator.LinkGeneratorHooks LinkGeneratorHooks}.
* This will generate a link from the wiki to the source code of the specific file the class {@link RegistryDescription} annotates is in.
+ * -
+ * {@link #override()} is the way to set the {@link MethodDescription} and {@link RecipeBuilderDescription} annotations for methods that are
+ * declared in the parent class but not in the annotated class, and need a custom annotation (often for examples).
+ *
* - {@link #location()} is the name of a {@link com.cleanroommc.groovyscript.sandbox.LoadStage} and controls where all methods
* inside the {@link RegistryDescription} are generated.
* - {@link #reloadability()} determines the status of the compat, defaulting to fully reloadable ({@link Reloadability#FULLY}).
@@ -37,7 +41,7 @@
/**
* The localization key for the name of the compat, will default to generating
*
- * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.title
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.title
*
*
* @return localization key for the compat name
@@ -47,7 +51,7 @@
/**
* The localization key for the description of the compat, will default to generating
*
- * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() GroovyContainer#getModId()}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() VirtualizedRegistry#getName()}.description
+ * groovyscript.wiki.{@link com.cleanroommc.groovyscript.compat.mods.GroovyContainer#getModId() {modId}}.{@link com.cleanroommc.groovyscript.registry.VirtualizedRegistry#getName() {name}}.description
*
*
* @return localization key for the compat description
@@ -59,7 +63,7 @@
* Addons should create their own instance of the {@link com.cleanroommc.groovyscript.documentation.linkgenerator.ILinkGenerator ILinkGenerator} class,
* preferably with the name of the generator being set to the modid.
* If it is not set or a corresponding LinkGenerator does not exist, the {@link com.cleanroommc.groovyscript.documentation.linkgenerator.ILinkGenerator ILinkGenerator}
- * converts to a link towards CleanroomMC's Groovyscript repo set to view the repo at a specific version tag.
+ * converts to a link towards CleanroomMC's Groovyscript repo set to view the repo at a specific version tag.
*
* @return a string corresponding to a {@link com.cleanroommc.groovyscript.documentation.linkgenerator.ILinkGenerator ILinkGenerator}, which controls how the source code link is generated.
* @see com.cleanroommc.groovyscript.documentation.linkgenerator.ILinkGenerator ILinkGenerator
@@ -72,6 +76,24 @@
*/
String location() default "postInit";
+ /**
+ * An override to {@link MethodDescription} or {@link RecipeBuilderDescription} declarations,
+ * using the wrapper class {@link MethodOverride}.
+ *
+ * Methods can be referred to by name if there is only one method with the given name
+ * in the class, otherwise must be referred to by the method name + method descriptor.
+ *
+ * While this can be used for any method, it is preferred to only use it for
+ * methods that require it - namely, methods that are declared in a parent class
+ * and not overridden in the focused class. Primarily used for examples of those methods.
+ *
+ * @return the MethodOverride annotation containing any number of {@link MethodDescription} or {@link RecipeBuilderDescription} annotations
+ * @see MethodOverride
+ * @see MethodDescription
+ * @see RecipeBuilderDescription
+ */
+ MethodOverride override() default @MethodOverride;
+
/**
* Is this compat reloadable in-game, and does reloading have any potential problems? Defaults to fully reloadable.
*
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Centrifuge.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Centrifuge.java
index 41306fadf..65e4b59a5 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Centrifuge.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Centrifuge.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TileCentrifuge;
@@ -10,7 +9,7 @@
@RegistryDescription(admonition = {
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING),
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.output_slots", type = Admonition.Type.WARNING),
-})
+}, override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("fluid('enrichedlava')"))))
public class Centrifuge extends BaseRegistry {
@RecipeBuilderDescription(
@@ -24,12 +23,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TileCentrifuge.class;
}
- @Override
- @MethodDescription(example = @Example("fluid('enrichedlava')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "fluidInput", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(lte = 12), value = "groovyscript.wiki.advancedrocketry.output.value")
@Property(property = "fluidOutput", comp = @Comp(lte = 4))
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/ChemicalReactor.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/ChemicalReactor.java
index f045bc5cd..5a772fd12 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/ChemicalReactor.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/ChemicalReactor.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TileChemicalReactor;
@@ -10,7 +9,10 @@
@RegistryDescription(admonition = {
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING),
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.input_slots", type = Admonition.Type.WARNING),
-})
+}, override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('minecraft:leather_helmet')")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:bone')"))
+}))
public class ChemicalReactor extends BaseRegistry {
@RecipeBuilderDescription(
@@ -24,18 +26,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TileChemicalReactor.class;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:leather_helmet')"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:bone')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(lte = 8, unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "fluidInput", comp = @Comp(lte = 2, unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "output", comp = @Comp(lte = 4, unique = "groovyscript.wiki.advancedrocketry.output.required"), value = "groovyscript.wiki.advancedrocketry.output.value")
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Crystallizer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Crystallizer.java
index f8247aecf..38eb55472 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Crystallizer.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Crystallizer.java
@@ -1,13 +1,17 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TileCrystallizer;
import zmaster587.libVulpes.tile.multiblock.TileMultiblockMachine;
-@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING))
+@RegistryDescription(
+ admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING),
+ override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('libvulpes:productgem')")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('libvulpes:productingot', 3)"))
+ }))
public class Crystallizer extends BaseRegistry {
@RecipeBuilderDescription(
@@ -21,18 +25,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TileCrystallizer.class;
}
- @Override
- @MethodDescription(example = @Example("item('libvulpes:productgem')"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('libvulpes:productingot', 3)"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(lte = 4, unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "fluidInput", comp = @Comp(lte = 1, unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "output", comp = @Comp(lte = 4, unique = "groovyscript.wiki.advancedrocketry.output.required"), value = "groovyscript.wiki.advancedrocketry.output.value")
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/CuttingMachine.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/CuttingMachine.java
index b3ee14d1e..430308aca 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/CuttingMachine.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/CuttingMachine.java
@@ -1,13 +1,17 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TileCuttingMachine;
import zmaster587.libVulpes.tile.multiblock.TileMultiblockMachine;
-@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING))
+@RegistryDescription(
+ admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING),
+ override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('minecraft:planks', 1)")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('advancedrocketry:alienwood')"))
+ }))
public class CuttingMachine extends BaseRegistry {
@RecipeBuilderDescription(
@@ -21,18 +25,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TileCuttingMachine.class;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:planks', 1)"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('advancedrocketry:alienwood')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(gte = 1, lte = 4))
@Property(
property = "output",
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/ElectricArcFurnace.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/ElectricArcFurnace.java
index 3cb9871b3..a0c03d7fe 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/ElectricArcFurnace.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/ElectricArcFurnace.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TileElectricArcFurnace;
@@ -12,7 +11,10 @@
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.input_slots", type = Admonition.Type.WARNING),
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.output_slots", type = Admonition.Type.WARNING),
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.hatch_count_11", type = Admonition.Type.INFO),
-})
+}, override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('libvulpes:productingot', 3)")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:iron_ingot')"))
+}))
public class ElectricArcFurnace extends BaseRegistry {
@RecipeBuilderDescription(
@@ -26,18 +28,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TileElectricArcFurnace.class;
}
- @Override
- @MethodDescription(example = @Example("item('libvulpes:productingot', 3)"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:iron_ingot')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "fluidInput", comp = @Comp(unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "output", comp = @Comp(unique = "groovyscript.wiki.advancedrocketry.output.required"), value = "groovyscript.wiki.advancedrocketry.output.value")
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Electrolyser.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Electrolyser.java
index e1808da92..5778534be 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Electrolyser.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Electrolyser.java
@@ -1,13 +1,17 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TileElectrolyser;
import zmaster587.libVulpes.tile.multiblock.TileMultiblockMachine;
-@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING))
+@RegistryDescription(
+ admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING),
+ override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example(value = "fluid('oxygen')", commented = true)),
+ @MethodDescription(method = "removeByInput", example = @Example("fluid('water')"))
+ }))
public class Electrolyser extends BaseRegistry {
@RecipeBuilderDescription(
@@ -21,18 +25,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TileElectrolyser.class;
}
- @Override
- @MethodDescription(example = @Example(value = "fluid('oxygen')", commented = true))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("fluid('water')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "fluidInput", comp = @Comp(eq = 1))
@Property(property = "fluidOutput", comp = @Comp(gte = 1, lte = 2))
public static class RecipeBuilder extends BaseRegistry.MultiblockRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Lathe.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Lathe.java
index 42515250f..18fa3340f 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Lathe.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/Lathe.java
@@ -1,13 +1,17 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TileLathe;
import zmaster587.libVulpes.tile.multiblock.TileMultiblockMachine;
-@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING))
+@RegistryDescription(
+ admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING),
+ override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('libvulpes:productrod', 4)")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('libvulpes:productingot', 6)"))
+ }))
public class Lathe extends BaseRegistry {
@RecipeBuilderDescription(
@@ -21,18 +25,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TileLathe.class;
}
- @Override
- @MethodDescription(example = @Example("item('libvulpes:productrod', 4)"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('libvulpes:productingot', 6)"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(gte = 1, lte = 4))
@Property(property = "output", comp = @Comp(gte = 1, lte = 4), value = "groovyscript.wiki.advancedrocketry.output.value")
public static class RecipeBuilder extends BaseRegistry.MultiblockRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/PrecisionAssembler.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/PrecisionAssembler.java
index d0ee7ca33..805045dfe 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/PrecisionAssembler.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/PrecisionAssembler.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TilePrecisionAssembler;
@@ -12,7 +11,10 @@
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.input_slots", type = Admonition.Type.WARNING),
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.output_slots", type = Admonition.Type.WARNING),
@Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.hatch_count_6", type = Admonition.Type.INFO),
-})
+}, override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('advancedrocketry:atmanalyser')")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:redstone_block')"))
+}))
public class PrecisionAssembler extends BaseRegistry {
@RecipeBuilderDescription(
@@ -26,18 +28,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TilePrecisionAssembler.class;
}
- @Override
- @MethodDescription(example = @Example("item('advancedrocketry:atmanalyser')"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:redstone_block')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "fluidInput", comp = @Comp(unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "output", comp = @Comp(unique = "groovyscript.wiki.advancedrocketry.output.required"), value = "groovyscript.wiki.advancedrocketry.output.value")
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/PrecisionLaserEtcher.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/PrecisionLaserEtcher.java
index 682de307b..2032bf27d 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/PrecisionLaserEtcher.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/PrecisionLaserEtcher.java
@@ -1,13 +1,17 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TilePrecisionLaserEtcher;
import zmaster587.libVulpes.tile.multiblock.TileMultiblockMachine;
-@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING))
+@RegistryDescription(
+ admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING),
+ override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('advancedrocketry:itemcircuitplate')")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:redstone_block')"))
+ }))
public class PrecisionLaserEtcher extends BaseRegistry {
@RecipeBuilderDescription(
@@ -21,18 +25,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TilePrecisionLaserEtcher.class;
}
- @Override
- @MethodDescription(example = @Example("item('advancedrocketry:itemcircuitplate')"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:redstone_block')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(gte = 1, lte = 4))
@Property(
property = "output",
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/RollingMachine.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/RollingMachine.java
index fd88739ba..7e78f9523 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/RollingMachine.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/RollingMachine.java
@@ -1,13 +1,17 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import zmaster587.advancedRocketry.tile.multiblock.machine.TileRollingMachine;
import zmaster587.libVulpes.tile.multiblock.TileMultiblockMachine;
-@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING))
+@RegistryDescription(
+ admonition = @Admonition(value = "groovyscript.wiki.advancedrocketry.admonition.weights", type = Admonition.Type.WARNING),
+ override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('libvulpes:productsheet', 1)")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('libvulpes:productplate')"))
+ }))
public class RollingMachine extends BaseRegistry {
@RecipeBuilderDescription(
@@ -21,18 +25,6 @@ protected Class extends TileMultiblockMachine> getMachineClass() {
return TileRollingMachine.class;
}
- @Override
- @MethodDescription(example = @Example("item('libvulpes:productsheet', 1)"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('libvulpes:productplate')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(lte = 4, unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "fluidInput", comp = @Comp(lte = 1, unique = "groovyscript.wiki.advancedrocketry.input.required"))
@Property(property = "output", comp = @Comp(gte = 1, lte = 4), value = "groovyscript.wiki.advancedrocketry.output.value")
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/SmallPlatePresser.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/SmallPlatePresser.java
index deb9a1a21..340696f71 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/SmallPlatePresser.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/advancedrocketry/SmallPlatePresser.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.advancedrocketry;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import net.minecraft.item.ItemBlock;
@@ -9,7 +8,10 @@
import java.util.Arrays;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByOutput", example = @Example("item('libvulpes:productplate', 2)")),
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:iron_block')"))
+}))
public class SmallPlatePresser extends BaseRegistry {
@RecipeBuilderDescription(
@@ -23,18 +25,6 @@ protected Class> getMachineClass() {
return BlockSmallPlatePress.class;
}
- @Override
- @MethodDescription(example = @Example("item('libvulpes:productplate', 2)"))
- public boolean removeByOutput(IIngredient output) {
- return super.removeByOutput(output);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:iron_block')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
-
@Property(property = "input", comp = @Comp(eq = 1, unique = "groovyscript.wiki.advancedrocketry.input.block"))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends BaseRegistry.RecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/Dissolver.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/Dissolver.java
index 4c04ae343..ca30bcf03 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/Dissolver.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/alchemistry/Dissolver.java
@@ -51,7 +51,6 @@ public boolean removeByInput(IIngredient input) {
}
@Property(property = "input", comp = @Comp(eq = 1))
- @Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
@Property(comp = @Comp(gte = 1))
@@ -85,6 +84,12 @@ public RecipeBuilder probabilityOutput(Collection probabilityOutputs)
return this.probabilityOutput(100, probabilityOutputs);
}
+ @Override
+ @RecipeBuilderMethodDescription(field = "probabilityGroup")
+ public RecipeBuilder output(ItemStack probabilityOutputs) {
+ return this.probabilityOutput(100, probabilityOutputs);
+ }
+
@Override
@RecipeBuilderMethodDescription(field = "probabilityGroup")
public RecipeBuilder output(ItemStack... probabilityOutputs) {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/arcaneworld/RitualWrapper.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/arcaneworld/RitualWrapper.java
index f67a0565c..08d9bedef 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/arcaneworld/RitualWrapper.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/arcaneworld/RitualWrapper.java
@@ -41,7 +41,7 @@ public RitualWrapper() {
// ... which would merge them somehow. need to figure that out.
// applies, inspirations.Cauldron, ID.*, and any new places.
- @RecipeBuilderDescription(example = @Example(".ritualCreateItem().input(item('minecraft:stone') * 5, item('minecraft:diamond'), item('minecraft:clay')).output(item('minecraft:clay')).translationKey('groovyscript.demo_output').name('groovyscript:custom_name')"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".ritualCreateItem().input(item('minecraft:stone') * 5, item('minecraft:diamond'), item('minecraft:clay')).output(item('minecraft:clay')).translationKey('groovyscript.demo_output').name('groovyscript:custom_name')"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "output"),
@Property(property = "entity"),
@Property(property = "time"),
@@ -49,61 +49,61 @@ public RitualWrapper() {
@Property(property = "command"),
@Property(property = "onActivate"),
@Property(property = "ritualType"),
- })
+ }))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:stone'), item('minecraft:stone'), item('minecraft:clay')).translationKey('groovyscript.demo_arena').entity(entity('minecraft:chicken'))"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:stone'), item('minecraft:stone'), item('minecraft:clay')).translationKey('groovyscript.demo_arena').entity(entity('minecraft:chicken'))"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.ARENA"),
@Property(property = "entity")
- })
+ }))
public RecipeBuilder recipeBuilderArena() {
return new RecipeBuilder().ritualArena();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:clay')).translationKey('groovyscript.demo_command').command('say hi', 'give @p minecraft:coal 5')"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:clay')).translationKey('groovyscript.demo_command').command('say hi', 'give @p minecraft:coal 5')"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.COMMAND"),
@Property(property = "command")
- })
+ }))
public RecipeBuilder recipeBuilderCommand() {
return new RecipeBuilder().ritualCommand();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:diamond')).translationKey('groovyscript.demo_create_item').output(item('minecraft:diamond'))"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:diamond')).translationKey('groovyscript.demo_create_item').output(item('minecraft:diamond'))"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.CREATE_ITEM"),
@Property(property = "output")
- })
+ }))
public RecipeBuilder recipeBuilderCreateItem() {
return new RecipeBuilder().ritualCreateItem();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_dragon_breath')"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_dragon_breath')"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.DRAGON_BREATH"),
- })
+ }))
public RecipeBuilder recipeBuilderDragonBreath() {
return new RecipeBuilder().ritualDragonBreath();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_dungeon')"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_dungeon')"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.DUNGEON"),
- })
+ }))
public RecipeBuilder recipeBuilderDungeon() {
return new RecipeBuilder().ritualDungeon();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:stone'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_summon').entity(entity('minecraft:chicken'))"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:stone'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_summon').entity(entity('minecraft:chicken'))"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.SUMMON"),
@Property(property = "entity")
- })
+ }))
public RecipeBuilder recipeBuilderSummon() {
return new RecipeBuilder().ritualSummon();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_time').time(5000)"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:clay'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_time').time(5000)"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.TIME"),
@Property(property = "time")
- })
+ }))
public RecipeBuilder recipeBuilderTime() {
return new RecipeBuilder().ritualTime();
}
@@ -112,18 +112,18 @@ public RecipeBuilder recipeBuilderTime() {
@Example(".input(item('minecraft:diamond'), item('minecraft:gold_ingot'), item('minecraft:clay')).translationKey('groovyscript.demo_weather_clear').weatherClear()"),
@Example(".input(item('minecraft:gold_ingot'), item('minecraft:diamond'), item('minecraft:clay')).translationKey('groovyscript.demo_weather_rain').weatherRain()"),
@Example(".input(item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:gold_ingot')).translationKey('groovyscript.demo_weather_thunder').weatherThunder()")
- }, requirement = {
+ }, override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.WEATHER"),
@Property(property = "weatherType")
- })
+ }))
public RecipeBuilder recipeBuilderWeather() {
return new RecipeBuilder().ritualWeather();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_custom').onActivate({ World world, BlockPos blockPos, EntityPlayer player, ItemStack... itemStacks -> { log.info blockPos } })"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond'), item('minecraft:diamond'), item('minecraft:clay'), item('minecraft:clay')).translationKey('groovyscript.demo_custom').onActivate({ World world, BlockPos blockPos, EntityPlayer player, ItemStack... itemStacks -> { log.info blockPos } })"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "ritualType", defaultValue = "RitualType.CUSTOM"),
@Property(property = "onActivate")
- })
+ }))
public RecipeBuilder recipeBuilderCustom() {
return new RecipeBuilder().ritualCustom();
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/Fountain.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/Fountain.java
index f92c45d34..853d55782 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/Fountain.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/Fountain.java
@@ -38,22 +38,22 @@ public void afterScriptLoad() {
}
}
- @MethodDescription(description = "groovyscript.wiki.astralsorcery.fountain.add0", type = MethodDescription.Type.ADDITION)
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
public void add(FluidStack fluid, int rarity, int guaranteedAmt, int addRand) {
this.add(fluid.getFluid(), rarity, guaranteedAmt, addRand);
}
- @MethodDescription(description = "groovyscript.wiki.astralsorcery.fountain.add1", type = MethodDescription.Type.ADDITION)
+ @MethodDescription(type = MethodDescription.Type.ADDITION)
public void add(Fluid fluid, int rarity, int guaranteedAmt, int addRand) {
this.add(FluidRarityEntryAccessor.createFluidRarityEntry(fluid, rarity, guaranteedAmt, addRand));
}
- @MethodDescription(description = "groovyscript.wiki.astralsorcery.fountain.remove0", example = @Example("fluid('lava')"))
+ @MethodDescription(example = @Example("fluid('lava')"))
public void remove(FluidStack entry) {
this.remove(entry.getFluid());
}
- @MethodDescription(description = "groovyscript.wiki.astralsorcery.fountain.remove1")
+ @MethodDescription
public void remove(Fluid entry) {
getRecipes().removeIf(fluidRarityEntry -> {
if (fluidRarityEntry.fluid != null && fluidRarityEntry.fluid.equals(entry)) {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/starlightaltar/StarlightAltar.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/starlightaltar/StarlightAltar.java
index 9948da799..c39ed74f2 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/starlightaltar/StarlightAltar.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/astralsorcery/starlightaltar/StarlightAltar.java
@@ -15,36 +15,36 @@
@RegistryDescription
public class StarlightAltar extends VirtualizedRegistry {
- @RecipeBuilderDescription(priority = 100, requirement = {
+ @RecipeBuilderDescription(priority = 100, override = @RecipeBuilderOverride(requirement = {
@Property(property = "ingredientMatrix", comp = @Comp(gte = 1, lte = 9, unique = "groovyscript.wiki.craftingrecipe.matrix.required")),
@Property(property = "starlightRequired", comp = @Comp(gte = 1, lte = 1000))
- }, example = @Example(".output(item('minecraft:water_bucket')).row(' ').row(' B ').row(' ').key('B', item('minecraft:bucket')).starlight(500).craftTime(10)"))
+ }), example = @Example(".output(item('minecraft:water_bucket')).row(' ').row(' B ').row(' ').key('B', item('minecraft:bucket')).starlight(500).craftTime(10)"))
public static AltarRecipeBuilder.Shaped discoveryRecipeBuilder() {
return new AltarRecipeBuilder.Shaped(3, 3, TileAltar.AltarLevel.DISCOVERY);
}
- @RecipeBuilderDescription(priority = 200, requirement = {
+ @RecipeBuilderDescription(priority = 200, override = @RecipeBuilderOverride(requirement = {
@Property(property = "ingredientMatrix", comp = @Comp(gte = 1, lte = 13, unique = "groovyscript.wiki.craftingrecipe.matrix.required")),
@Property(property = "starlightRequired", comp = @Comp(gte = 1, lte = 2000))
- })
+ }))
public static AltarRecipeBuilder.Shaped attunementRecipeBuilder() {
return new AltarRecipeBuilder.Shaped(5, 5, TileAltar.AltarLevel.ATTUNEMENT);
}
- @RecipeBuilderDescription(priority = 300, requirement = {
+ @RecipeBuilderDescription(priority = 300, override = @RecipeBuilderOverride(requirement = {
@Property(property = "ingredientMatrix", comp = @Comp(gte = 1, lte = 21, unique = "groovyscript.wiki.craftingrecipe.matrix.required")),
@Property(property = "starlightRequired", comp = @Comp(gte = 1, lte = 4000))
- }, example = @Example(".output(item('minecraft:pumpkin')).matrix('ss ss', 's s', ' d ', 's s', 'ss ss').key('s', item('minecraft:pumpkin_seeds')).key('d', ore('dirt'))"))
+ }), example = @Example(".output(item('minecraft:pumpkin')).matrix('ss ss', 's s', ' d ', 's s', 'ss ss').key('s', item('minecraft:pumpkin_seeds')).key('d', ore('dirt'))"))
public static AltarRecipeBuilder.Shaped constellationRecipeBuilder() {
return new AltarRecipeBuilder.Shaped(5, 5, TileAltar.AltarLevel.CONSTELLATION_CRAFT);
}
- @RecipeBuilderDescription(priority = 400, requirement = {
+ @RecipeBuilderDescription(priority = 400, override = @RecipeBuilderOverride(requirement = {
@Property(property = "ingredientMatrix", comp = @Comp(gte = 1, lte = 25, unique = "groovyscript.wiki.craftingrecipe.matrix.required")),
@Property(property = "outerIngredients", comp = @Comp(gte = 0, lte = 24)),
@Property(property = "starlightRequired", comp = @Comp(gte = 1, lte = 8000)),
@Property(property = "requiredConstellation")
- }, example = @Example(".output(item('astralsorcery:itemrockcrystalsimple').setSize(300).setPurity(50).setCutting(50)).matrix('sssss', 'sgggs', 'sgdgs', 'sgggs', 'sssss').key('s', item('minecraft:pumpkin')).key('g', ore('treeLeaves')).key('d', item('minecraft:diamond_block')).outerInput(item('astralsorcery:blockmarble')).outerInput(ore('ingotAstralStarmetal')).outerInput(fluid('astralsorcery.liquidstarlight') * 1000).outerInput(ore('treeSapling')).constellation(constellation('discidia'))"))
+ }), example = @Example(".output(item('astralsorcery:itemrockcrystalsimple').setSize(300).setPurity(50).setCutting(50)).matrix('sssss', 'sgggs', 'sgdgs', 'sgggs', 'sssss').key('s', item('minecraft:pumpkin')).key('g', ore('treeLeaves')).key('d', item('minecraft:diamond_block')).outerInput(item('astralsorcery:blockmarble')).outerInput(ore('ingotAstralStarmetal')).outerInput(fluid('astralsorcery.liquidstarlight') * 1000).outerInput(ore('treeSapling')).constellation(constellation('discidia'))"))
public static AltarRecipeBuilder.Shaped traitRecipeBuilder() {
return new AltarRecipeBuilder.Shaped(5, 5, TileAltar.AltarLevel.TRAIT_CRAFT);
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/compactmachines/Miniaturization.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/compactmachines/Miniaturization.java
index 9b906a1c9..ce82b4c6f 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/compactmachines/Miniaturization.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/compactmachines/Miniaturization.java
@@ -140,7 +140,7 @@ public RecipeBuilder ticks(int ticks) {
return this;
}
- @RecipeBuilderMethodDescription
+ @RecipeBuilderMethodDescription(field = "ticks")
public RecipeBuilder duration(int duration) {
return ticks(duration);
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/inspirations/Cauldron.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/inspirations/Cauldron.java
index dbb44cd39..b3ba92e62 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/inspirations/Cauldron.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/inspirations/Cauldron.java
@@ -41,7 +41,7 @@ private static boolean compareFluids(Object first, Object second) {
return false;
}
- @RecipeBuilderDescription(example = @Example(".standard().input(item('minecraft:gold_ingot')).fluidInput(fluid('lava')).output(item('minecraft:clay')).boiling().sound(sound('minecraft:block.anvil.destroy')).levels(3)"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".standard().input(item('minecraft:gold_ingot')).fluidInput(fluid('lava')).output(item('minecraft:clay')).boiling().sound(sound('minecraft:block.anvil.destroy')).levels(3)"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "type"),
@Property(property = "input"),
@Property(property = "output"),
@@ -53,80 +53,80 @@ private static boolean compareFluids(Object first, Object second) {
@Property(property = "boiling"),
@Property(property = "levels"),
@Property(property = "sound")
- })
+ }))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond')).output(item('minecraft:clay')).fluidInput(fluid('lava')).levels(3).sound(sound('minecraft:block.anvil.destroy'))"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond')).output(item('minecraft:clay')).fluidInput(fluid('lava')).levels(3).sound(sound('minecraft:block.anvil.destroy'))"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "input"),
@Property(property = "output"),
@Property(property = "fluidInput"),
@Property(property = "boiling"),
@Property(property = "levels"),
@Property(property = "sound")
- })
+ }))
public RecipeBuilder recipeBuilderStandard() {
return new RecipeBuilder().standard();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:stone:3')).fluidInput(fluid('water')).fluidOutput(fluid('milk')).levels(2)"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:stone:3')).fluidInput(fluid('water')).fluidOutput(fluid('milk')).levels(2)"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "input"),
@Property(property = "fluidInput"),
@Property(property = "fluidOutput"),
@Property(property = "boiling"),
@Property(property = "levels"),
@Property(property = "sound")
- })
+ }))
public RecipeBuilder recipeBuilderTransform() {
return new RecipeBuilder().transform();
}
- @RecipeBuilderDescription(example = @Example(".output(item('minecraft:clay')).fluidInput(fluid('milk'), fluid('lava'))"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".output(item('minecraft:clay')).fluidInput(fluid('milk'), fluid('lava'))"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "fluidInput", comp = @Comp(eq = 2)),
@Property(property = "output")
- })
+ }))
public RecipeBuilder recipeBuilderMix() {
return new RecipeBuilder().mix();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:clay')).fluidInput(fluid('milk')).sound(sound('minecraft:block.anvil.destroy'))"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:clay')).fluidInput(fluid('milk')).sound(sound('minecraft:block.anvil.destroy'))"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "input"),
@Property(property = "output"),
@Property(property = "fluidInput"),
@Property(property = "boiling"),
@Property(property = "sound")
- })
+ }))
public RecipeBuilder recipeBuilderFill() {
return new RecipeBuilder().fill();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond_block')).inputPotion(potionType('minecraft:fire_resistance')).outputPotion(potionType('minecraft:strength'))"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond_block')).inputPotion(potionType('minecraft:fire_resistance')).outputPotion(potionType('minecraft:strength'))"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "input"),
@Property(property = "inputPotion"),
@Property(property = "outputPotion")
- })
+ }))
public RecipeBuilder recipeBuilderBrewing() {
return new RecipeBuilder().brewing();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:gold_block')).output(item('minecraft:diamond_block')).inputPotion(potionType('minecraft:fire_resistance')).levels(2)"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:gold_block')).output(item('minecraft:diamond_block')).inputPotion(potionType('minecraft:fire_resistance')).levels(2)"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "input"),
@Property(property = "output"),
@Property(property = "inputPotion", comp = @Comp(gte = 0, lte = 1)),
@Property(property = "boiling"),
@Property(property = "levels")
- })
+ }))
public RecipeBuilder recipeBuilderPotion() {
return new RecipeBuilder().potion();
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:gold_block')).output(item('minecraft:diamond_block')).dye('blue').levels(2)"), requirement = {
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:gold_block')).output(item('minecraft:diamond_block')).dye('blue').levels(2)"), override = @RecipeBuilderOverride(requirement = {
@Property(property = "input"),
@Property(property = "output"),
@Property(property = "dye"),
@Property(property = "levels")
- })
+ }))
public RecipeBuilder recipeBuilderDye() {
return new RecipeBuilder().dye();
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/DryingBasin.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/DryingBasin.java
index 49608b96d..16d43258d 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/DryingBasin.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/DryingBasin.java
@@ -29,7 +29,7 @@ public boolean isEnabled() {
@RecipeBuilderDescription(example = {
@Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:clay')).fluidInput(fluid('water') * 500).fluidOutput(fluid('lava') * 2000).mechanical().duration(5)"),
@Example(".output(item('minecraft:clay')).fluidInput(fluid('water') * 2000)")
- }, requirement = @Property(property = "basic", defaultValue = "true"))
+ }, override = @RecipeBuilderOverride(requirement = @Property(property = "basic", defaultValue = "true")))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder().basic();
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/MechanicalDryingBasin.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/MechanicalDryingBasin.java
index 2344006dc..7448231ba 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/MechanicalDryingBasin.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/MechanicalDryingBasin.java
@@ -20,7 +20,7 @@ public boolean isEnabled() {
return Configs.isEnabled(BlockMechanicalDryingBasinConfig.class);
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond')).fluidInput(fluid('water') * 50).fluidOutput(fluid('lava') * 20000).duration(300)"), requirement = @Property(property = "mechanical", defaultValue = "true"))
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond')).fluidInput(fluid('water') * 50).fluidOutput(fluid('lava') * 20000).duration(300)"), override = @RecipeBuilderOverride(requirement = @Property(property = "mechanical", defaultValue = "true")))
public DryingBasin.RecipeBuilder recipeBuilder() {
return new DryingBasin.RecipeBuilder().mechanical();
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/MechanicalSqueezer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/MechanicalSqueezer.java
index 3d36bed97..e019560bf 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/MechanicalSqueezer.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/MechanicalSqueezer.java
@@ -21,7 +21,7 @@ public boolean isEnabled() {
return Configs.isEnabled(BlockMechanicalSqueezerConfig.class);
}
- @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond')).output(item('minecraft:clay') * 16, 0.9F)"), requirement = @Property(property = "mechanical", defaultValue = "true"))
+ @RecipeBuilderDescription(example = @Example(".input(item('minecraft:diamond')).output(item('minecraft:clay') * 16, 0.9F)"), override = @RecipeBuilderOverride(requirement = @Property(property = "mechanical", defaultValue = "true")))
public Squeezer.RecipeBuilder recipeBuilder() {
return new Squeezer.RecipeBuilder().mechanical();
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/Squeezer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/Squeezer.java
index 55b6f1f97..3bddd6ea0 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/Squeezer.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/integrateddynamics/Squeezer.java
@@ -33,7 +33,7 @@ public boolean isEnabled() {
@Example(".input(item('minecraft:clay')).output(item('minecraft:clay_ball'), 1F).output(item('minecraft:clay_ball') * 2, 0.7F).output(item('minecraft:clay_ball') * 10, 0.2F).fluidOutput(fluid('lava') * 2000).mechanical().duration(5)"),
@Example(".input(item('minecraft:gold_ingot')).output(item('minecraft:clay'), 0.5F)"),
@Example(".input(item('minecraft:diamond')).fluidOutput(fluid('lava') * 10)")
- }, requirement = @Property(property = "basic", defaultValue = "true"))
+ }, override = @RecipeBuilderOverride(requirement = @Property(property = "basic", defaultValue = "true")))
public RecipeBuilder recipeBuilder() {
return new RecipeBuilder().basic();
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandler.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandler.java
index 99f3dff0e..87864c839 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandler.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandler.java
@@ -77,7 +77,7 @@ public String getErrorMsg() {
}
}
- @RegistryDescription
+ @RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:gravel')"))))
public static class RotaryGrinder extends SimpleRecipeHandler {
RotaryGrinder() {
@@ -88,15 +88,9 @@ public static class RotaryGrinder extends SimpleRecipeHandler {
protected int getDefaultTime() {
return Config.rotaryGrinderProcessTime;
}
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:gravel')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
}
- @RegistryDescription
+ @RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:gravel')"))))
public static class MagneticReassembler extends SimpleRecipeHandler {
MagneticReassembler() {
@@ -107,11 +101,5 @@ public static class MagneticReassembler extends SimpleRecipeHandler {
protected int getDefaultTime() {
return Config.magneticReassemblerProcessTime;
}
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:gravel')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
}
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerSecondaryOutput.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerSecondaryOutput.java
index e44a017bc..3242004f5 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerSecondaryOutput.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/prodigytech/SimpleRecipeHandlerSecondaryOutput.java
@@ -87,7 +87,7 @@ public String getErrorMsg() {
}
}
- @RegistryDescription
+ @RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("ore('plankWood')"))))
public static class HeatSawmill extends SimpleRecipeHandlerSecondaryOutput {
HeatSawmill() {
@@ -98,15 +98,9 @@ public static class HeatSawmill extends SimpleRecipeHandlerSecondaryOutput {
protected int getDefaultTime() {
return Config.heatSawmillProcessTime;
}
-
- @Override
- @MethodDescription(example = @Example("ore('plankWood')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
}
- @RegistryDescription
+ @RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("ore('oreLapis')"))))
public static class OreRefinery extends SimpleRecipeHandlerSecondaryOutput {
OreRefinery() {
@@ -117,11 +111,5 @@ public static class OreRefinery extends SimpleRecipeHandlerSecondaryOutput {
protected int getDefaultTime() {
return Config.oreRefineryProcessTime;
}
-
- @Override
- @MethodDescription(example = @Example("ore('oreLapis')"))
- public boolean removeByInput(IIngredient input) {
- return super.removeByInput(input);
- }
}
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/AlloySmelter.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/AlloySmelter.java
index 0d87819dc..4cb0d9fd3 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/AlloySmelter.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/AlloySmelter.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:ingot:4')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:ingot:5')"))
+}))
public class AlloySmelter extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.alloySmelter;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:ingot:4')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:ingot:5')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 2))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/AssemblingMachine.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/AssemblingMachine.java
index 4fc485554..a2eb7f527 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/AssemblingMachine.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/AssemblingMachine.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:plates:35')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:part:29')"))
+}))
public class AssemblingMachine extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.assemblingMachine;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:plates:35')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:part:29')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 2))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/BlastFurnace.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/BlastFurnace.java
index 9d376a182..b373ac499 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/BlastFurnace.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/BlastFurnace.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,12 @@
import techreborn.api.Reference;
import techreborn.api.recipe.machines.BlastFurnaceRecipe;
-@RegistryDescription(admonition = @Admonition(value = "groovyscript.wiki.techreborn.blast_furnace.note0", type = Admonition.Type.INFO))
+@RegistryDescription(
+ admonition = @Admonition(value = "groovyscript.wiki.techreborn.blast_furnace.note0", type = Admonition.Type.INFO),
+ override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:dust:1')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:ingot:12')"))
+ }))
public class BlastFurnace extends AbstractGenericTechRebornRegistry {
@RecipeBuilderDescription(example = {
@@ -26,18 +30,6 @@ public String reference() {
return Reference.BLAST_FURNACE_RECIPE;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:dust:1')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:ingot:12')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(gte = 1, lte = 2))
@Property(property = "output", comp = @Comp(gte = 1, lte = 2))
public static class RecipeBuilder extends AbstractRecipeBuilder {
@@ -83,7 +75,16 @@ public void validate(GroovyLog.Msg msg) {
public @Nullable BlastFurnaceRecipe register() {
if (!validate()) return null;
ItemStack output2 = output.size() >= 2 ? output.get(1) : null;
- BlastFurnaceRecipe recipe = new BlastFurnaceRecipe(Helper.getStackFromIIngredient(input.get(0)), input.size() == 2 ? Helper.getStackFromIIngredient(input.get(1)) : null, output.get(0), output2, time, perTick, neededHeat);
+ BlastFurnaceRecipe recipe = new BlastFurnaceRecipe(
+ Helper.getStackFromIIngredient(input.get(0)),
+ input.size() == 2
+ ? Helper.getStackFromIIngredient(input.get(1))
+ : null,
+ output.get(0),
+ output2,
+ time,
+ perTick,
+ neededHeat);
ModSupport.TECH_REBORN.get().blastFurnace.add(recipe);
return recipe;
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Centrifuge.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Centrifuge.java
index 4ac86c021..9a24c1adb 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Centrifuge.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Centrifuge.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:dust:33')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'fluidmethane', 'Amount': 1000]])"))
+}))
public class Centrifuge extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.centrifuge;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:dust:33')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'fluidmethane', 'Amount': 1000]])"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(gte = 1, lte = 2))
@Property(property = "output", comp = @Comp(gte = 1, lte = 4))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ChemicalReactor.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ChemicalReactor.java
index 1c6202912..58db26500 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ChemicalReactor.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ChemicalReactor.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'water', 'Amount': 1000]])")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'water', 'Amount': 1000]])"))
+}))
public class ChemicalReactor extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.chemicalReactor;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'water', 'Amount': 1000]])"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'water', 'Amount': 1000]])"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 2))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Compressor.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Compressor.java
index f689b4bb4..eef3db950 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Compressor.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Compressor.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:diamond')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:plates:36')"))
+}))
public class Compressor extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.compressor;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:diamond')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:plates:36')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/DieselGenerator.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/DieselGenerator.java
index 35bb8f3ea..7413befc4 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/DieselGenerator.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/DieselGenerator.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,7 @@
import reborncore.api.praescriptum.fuels.FuelHandler;
import techreborn.api.recipe.Fuels;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("fluid('fluiddiesel')"))))
public class DieselGenerator extends AbstractGeneratorRegistry {
@RecipeBuilderDescription(example = {
@@ -26,12 +25,6 @@ public FuelHandler handler() {
return Fuels.dieselGenerator;
}
- @Override
- @MethodDescription(example = @Example("fluid('fluiddiesel')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
@Property(property = "fluidInput", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/DistillationTower.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/DistillationTower.java
index 89a878114..a6e40e168 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/DistillationTower.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/DistillationTower.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,10 @@
import techreborn.api.Reference;
import techreborn.api.recipe.machines.DistillationTowerRecipe;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'fluidoil', 'Amount': 1000]])")),
+ @MethodDescription(method = "removeByOutput", example = @Example(value = "item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'fluidmethane', 'Amount': 1000]])", commented = true))
+}))
public class DistillationTower extends AbstractGenericTechRebornRegistry {
@RecipeBuilderDescription(example = {
@@ -26,18 +28,6 @@ public String reference() {
return Reference.DISTILLATION_TOWER_RECIPE;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'fluidoil', 'Amount': 1000]])"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example(value = "item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'fluidmethane', 'Amount': 1000]])", commented = true))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(gte = 1, lte = 2))
@Property(property = "output", comp = @Comp(gte = 1, lte = 4))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Extractor.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Extractor.java
index 7045aa674..a5acf725c 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Extractor.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Extractor.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:slime_ball')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('minecraft:wool')"))
+}))
public class Extractor extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.extractor;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:slime_ball')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:wool')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/GasTurbine.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/GasTurbine.java
index 1b4e0b805..a305ef043 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/GasTurbine.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/GasTurbine.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,7 @@
import reborncore.api.praescriptum.fuels.FuelHandler;
import techreborn.api.recipe.Fuels;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("fluid('fluidhydrogen')"))))
public class GasTurbine extends AbstractGeneratorRegistry {
@RecipeBuilderDescription(example = {
@@ -26,12 +25,6 @@ public FuelHandler handler() {
return Fuels.gasTurbine;
}
- @Override
- @MethodDescription(example = @Example("fluid('fluidhydrogen')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
@Property(property = "fluidInput", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Grinder.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Grinder.java
index 76454564f..41bad879c 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Grinder.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Grinder.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:coal_ore')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('minecraft:diamond')"))
+}))
public class Grinder extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.grinder;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:coal_ore')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:diamond')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ImplosionCompressor.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ImplosionCompressor.java
index 52b4a03e0..6eff8398e 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ImplosionCompressor.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ImplosionCompressor.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,10 @@
import techreborn.api.Reference;
import techreborn.api.recipe.machines.ImplosionCompressorRecipe;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:ingot:22')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('minecraft:diamond')"))
+}))
public class ImplosionCompressor extends AbstractGenericTechRebornRegistry {
@RecipeBuilderDescription(example = {
@@ -26,18 +28,6 @@ public String reference() {
return Reference.IMPLOSION_COMPRESSOR_RECIPE;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:ingot:22')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:diamond')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(gte = 1, lte = 2))
@Property(property = "output", comp = @Comp(gte = 1, lte = 2))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialElectrolyzer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialElectrolyzer.java
index cda0fbe9c..ce932a2df 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialElectrolyzer.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialElectrolyzer.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,10 @@
import techreborn.api.Reference;
import techreborn.api.recipe.machines.IndustrialElectrolyzerRecipe;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:dye:15')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:dust:1')"))
+}))
public class IndustrialElectrolyzer extends AbstractGenericTechRebornRegistry {
@RecipeBuilderDescription(example = {
@@ -26,18 +28,6 @@ public String reference() {
return Reference.INDUSTRIAL_ELECTROLYZER_RECIPE;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:dye:15')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:dust:1')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(gte = 1, lte = 2))
@Property(property = "output", comp = @Comp(gte = 1, lte = 4))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialGrinder.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialGrinder.java
index fbbf81970..aae944129 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialGrinder.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialGrinder.java
@@ -11,7 +11,7 @@
import techreborn.api.Reference;
import techreborn.api.recipe.machines.IndustrialGrinderRecipe;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:dust:53')"))))
public class IndustrialGrinder extends AbstractGenericTechRebornRegistry {
@RecipeBuilderDescription(example = {
@@ -45,12 +45,6 @@ public void removeByInput(IIngredient input) {
});
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:dust:53')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "fluidInput", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(gte = 1, lte = 4))
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialSawmill.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialSawmill.java
index e0f687eca..73014a51d 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialSawmill.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/IndustrialSawmill.java
@@ -11,7 +11,7 @@
import techreborn.api.Reference;
import techreborn.api.recipe.machines.IndustrialSawmillRecipe;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByOutput", example = @Example("item('minecraft:planks:4')"))))
public class IndustrialSawmill extends AbstractGenericTechRebornRegistry {
@RecipeBuilderDescription(example = {
@@ -45,12 +45,6 @@ public void removeByInput(IIngredient input) {
});
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:planks:4')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "fluidInput", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(gte = 1, lte = 3))
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/PlasmaGenerator.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/PlasmaGenerator.java
index 8a4e68e18..1a28aff43 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/PlasmaGenerator.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/PlasmaGenerator.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,7 @@
import reborncore.api.praescriptum.fuels.FuelHandler;
import techreborn.api.recipe.Fuels;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("fluid('fluidheliumplasma')"))))
public class PlasmaGenerator extends AbstractGeneratorRegistry {
@RecipeBuilderDescription(example = {
@@ -26,12 +25,6 @@ public FuelHandler handler() {
return Fuels.plasmaGenerator;
}
- @Override
- @MethodDescription(example = @Example("fluid('fluidheliumplasma')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
@Property(property = "fluidInput", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/PlateBendingMachine.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/PlateBendingMachine.java
index 88bb9eac6..2ba9cbe7b 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/PlateBendingMachine.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/PlateBendingMachine.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:gold_ingot')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:plates:36')"))
+}))
public class PlateBendingMachine extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.plateBendingMachine;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:gold_ingot')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:plates:36')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Scrapbox.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Scrapbox.java
index 936ef5c16..4b906d15a 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Scrapbox.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/Scrapbox.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -9,7 +8,7 @@
import techreborn.api.Reference;
import techreborn.api.recipe.machines.ScrapboxRecipe;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByOutput", example = @Example("item('minecraft:diamond')"))))
public class Scrapbox extends AbstractGenericTechRebornRegistry {
@RecipeBuilderDescription(example = {
@@ -25,12 +24,6 @@ public String reference() {
return Reference.SCRAPBOX_RECIPE;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:diamond')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/SemiFluidGenerator.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/SemiFluidGenerator.java
index befe342c5..e8d6ab01e 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/SemiFluidGenerator.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/SemiFluidGenerator.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,7 @@
import reborncore.api.praescriptum.fuels.FuelHandler;
import techreborn.api.recipe.Fuels;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("fluid('fluidbiofuel')"))))
public class SemiFluidGenerator extends AbstractGeneratorRegistry {
@RecipeBuilderDescription(example = {
@@ -26,12 +25,6 @@ public FuelHandler handler() {
return Fuels.semiFluidGenerator;
}
- @Override
- @MethodDescription(example = @Example("fluid('fluidbiofuel')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
@Property(property = "fluidInput", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/SolidCanningMachine.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/SolidCanningMachine.java
index c8874c7b1..98ecdfd8c 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/SolidCanningMachine.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/SolidCanningMachine.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:ingot:23')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:part:46')"))
+}))
public class SolidCanningMachine extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.solidCanningMachine;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:ingot:23')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:part:46')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 2))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ThermalGenerator.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ThermalGenerator.java
index 371663e09..0bab58cff 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ThermalGenerator.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/ThermalGenerator.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -10,7 +9,7 @@
import reborncore.api.praescriptum.fuels.FuelHandler;
import techreborn.api.recipe.Fuels;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = @MethodDescription(method = "removeByInput", example = @Example("fluid('lava')"))))
public class ThermalGenerator extends AbstractGeneratorRegistry {
@RecipeBuilderDescription(example = {
@@ -26,12 +25,6 @@ public FuelHandler handler() {
return Fuels.thermalGenerator;
}
- @Override
- @MethodDescription(example = @Example("fluid('lava')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
@Property(property = "fluidInput", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/VacuumFreezer.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/VacuumFreezer.java
index 757662471..f43acc4fe 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/VacuumFreezer.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/VacuumFreezer.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -9,7 +8,10 @@
import techreborn.api.Reference;
import techreborn.api.recipe.machines.VacuumFreezerRecipe;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'water', 'Amount': 1000]])")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('minecraft:packed_ice')"))
+}))
public class VacuumFreezer extends AbstractGenericTechRebornRegistry {
@RecipeBuilderDescription(example = {
@@ -25,18 +27,6 @@ public String reference() {
return Reference.VACUUM_FREEZER_RECIPE;
}
- @Override
- @MethodDescription(example = @Example("item('techreborn:dynamiccell').withNbt(['Fluid': ['FluidName': 'water', 'Amount': 1000]])"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('minecraft:packed_ice')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/WireMill.java b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/WireMill.java
index 5d3cfe9d7..f4c9c30a0 100644
--- a/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/WireMill.java
+++ b/src/main/java/com/cleanroommc/groovyscript/compat/mods/techreborn/WireMill.java
@@ -1,7 +1,6 @@
package com.cleanroommc.groovyscript.compat.mods.techreborn;
import com.cleanroommc.groovyscript.api.GroovyLog;
-import com.cleanroommc.groovyscript.api.IIngredient;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder;
@@ -12,7 +11,10 @@
import java.util.stream.Collectors;
-@RegistryDescription
+@RegistryDescription(override = @MethodOverride(method = {
+ @MethodDescription(method = "removeByInput", example = @Example("item('minecraft:gold_ingot')")),
+ @MethodDescription(method = "removeByOutput", example = @Example("item('techreborn:cable')"))
+}))
public class WireMill extends AbstractPraescriptumRegistry {
@RecipeBuilderDescription(example = {
@@ -28,18 +30,6 @@ public RecipeHandler handler() {
return Recipes.wireMill;
}
- @Override
- @MethodDescription(example = @Example("item('minecraft:gold_ingot')"))
- public void removeByInput(IIngredient input) {
- super.removeByInput(input);
- }
-
- @Override
- @MethodDescription(example = @Example("item('techreborn:cable')"))
- public void removeByOutput(IIngredient output) {
- super.removeByOutput(output);
- }
-
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder {
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/Builder.java b/src/main/java/com/cleanroommc/groovyscript/documentation/Builder.java
index d9d72801f..f2c5604ec 100644
--- a/src/main/java/com/cleanroommc/groovyscript/documentation/Builder.java
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/Builder.java
@@ -2,7 +2,12 @@
import com.cleanroommc.groovyscript.api.GroovyLog;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
-import com.google.common.collect.ComparisonChain;
+import com.cleanroommc.groovyscript.documentation.helper.AdmonitionBuilder;
+import com.cleanroommc.groovyscript.documentation.helper.CodeBlockBuilder;
+import com.cleanroommc.groovyscript.documentation.helper.descriptor.DescriptorHelper;
+import com.cleanroommc.groovyscript.documentation.helper.descriptor.MethodAnnotation;
+import com.cleanroommc.groovyscript.documentation.helper.ComparisonHelper;
+import com.cleanroommc.groovyscript.documentation.helper.LangHelper;
import it.unimi.dsi.fastutil.chars.Char2CharArrayMap;
import it.unimi.dsi.fastutil.chars.Char2CharMap;
import net.minecraft.client.resources.I18n;
@@ -13,6 +18,8 @@
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
@@ -30,21 +37,36 @@ public class Builder {
}
};
- private final String reference;
+ private final String location;
private final Method builderMethod;
private final RecipeBuilderDescription annotation;
private final Map fields;
- private final Map> methods;
- private final List registrationMethods;
+ private final Map>> methods;
+ private final List> registrationMethods;
- public Builder(Method builderMethod, String reference, String baseTranslationKey) {
+ public Builder(Method builderMethod, RecipeBuilderDescription annotation, String location) {
this.builderMethod = builderMethod;
- this.reference = reference;
- this.annotation = builderMethod.getAnnotation(RecipeBuilderDescription.class);
- Class> builderClass = builderMethod.getReturnType();
- this.fields = gatherFields(builderClass, annotation, baseTranslationKey);
- this.methods = gatherMethods(builderClass, fields);
- this.registrationMethods = gatherRegistrationMethods(builderClass);
+ this.location = location;
+ this.annotation = annotation;
+ Class> builderClass = annotation.clazz() == void.class ? builderMethod.getReturnType() : annotation.clazz();
+ var methodSignatures = generateOfClass(builderClass, annotation);
+ this.fields = gatherFields(builderClass, annotation, Registry.BASE_LANG_LOCATION + "." + location);
+ this.methods = gatherMethods(methodSignatures, fields);
+ this.registrationMethods = gatherRegistrationMethods(methodSignatures);
+ }
+
+ private static DescriptorHelper.OfClass generateOfClass(Class> clazz, RecipeBuilderDescription annotation) {
+ var methodSignatures = DescriptorHelper.generateOfClass(clazz);
+ if (annotation != null) {
+ var override = annotation.override();
+ for (var entry : override.method()) {
+ methodSignatures.addAnnotation(entry.method(), entry);
+ }
+ for (var entry : override.register()) {
+ methodSignatures.addAnnotation(entry.method(), entry);
+ }
+ }
+ return methodSignatures;
}
private static List getPropertyAnnotationsFromClassRecursive(Class> clazz) {
@@ -60,8 +82,10 @@ private static Map gatherFields(Class> builderClas
List allFields = getAllFields(builderClass);
for (Field field : allFields) {
List annotations = Stream.of(
- // Attached to the builder method's requirements field, an uncommon location for specific overrides
+ // (deprecated) Attached to the builder method's requirements field, an uncommon location for specific overrides
Arrays.stream(annotation.requirement()).filter(r -> r.property().equals(field.getName())),
+ // Attached to the builder method's override of the requirements field, an uncommon location for specific overrides
+ Arrays.stream(annotation.override().requirement()).filter(r -> r.property().equals(field.getName())),
// Attached to the class or any parent classes, to create/override requirements set in the parent
getPropertyAnnotationsFromClassRecursive(builderClass).stream().filter(r -> r.property().equals(field.getName())),
// Attached to the field, the typical place for property information to be created
@@ -71,7 +95,7 @@ private static Map gatherFields(Class> builderClas
return false;
}))
.flatMap(x -> x)
- .sorted((left, right) -> ComparisonChain.start().compare(left.hierarchy(), right.hierarchy()).result())
+ .sorted(ComparisonHelper::property)
.collect(Collectors.toList());
if (!annotations.isEmpty()) {
@@ -82,47 +106,40 @@ private static Map gatherFields(Class> builderClas
return fields;
}
- private static Map> gatherMethods(Class> builderClass, Map fields) {
- Map> fieldToModifyingMethods = new HashMap<>();
- for (Method method : builderClass.getMethods()) {
- if (!method.isAnnotationPresent(RecipeBuilderMethodDescription.class)) continue;
- RecipeBuilderMethod pair = new RecipeBuilderMethod(method);
- for (String target : pair.targetFields()) {
- if (fields.get(target) != null && fields.get(target).isIgnoringInheritedMethods() && !Arrays.asList(builderClass.getDeclaredMethods()).contains(method)) {
- continue;
+ private static Map>> gatherMethods(DescriptorHelper.OfClass methodSignatures, Map fields) {
+ Map>> fieldToModifyingMethods = new HashMap<>();
+
+ BiPredicate isDocumented = (method, fieldName) -> {
+ if (method.getDeclaringClass() == methodSignatures.getClazz()) return true;
+ var field = fields.get(fieldName);
+ return field == null || !field.isIgnoringInheritedMethods();
+ };
+
+ for (var method : methodSignatures.getMethods(RecipeBuilderMethodDescription.class)) {
+ if (method.annotation().field().length == 0) {
+ var field = method.method().getName();
+ if (isDocumented.test(method.method(), field)) {
+ fieldToModifyingMethods.computeIfAbsent(field, k -> new ArrayList<>()).add(method);
+ }
+ } else {
+ for (var field : method.annotation().field()) {
+ if (isDocumented.test(method.method(), field)) {
+ fieldToModifyingMethods.computeIfAbsent(field, k -> new ArrayList<>()).add(method);
+ }
}
- fieldToModifyingMethods.computeIfAbsent(target, k -> new ArrayList<>()).add(pair);
}
}
-
- fieldToModifyingMethods.forEach(
- (key, value) -> value.sort(
- (left, right) -> ComparisonChain.start()
- .compare(left.getAnnotation().priority(), right.getAnnotation().priority())
- .compare(left.getMethod().getName().length(), right.getMethod().getName().length())
- .compare(left.getMethod().getName(), right.getMethod().getName(), String::compareToIgnoreCase)
- .result()));
-
+ fieldToModifyingMethods.values().forEach(value -> value.sort(ComparisonHelper::recipeBuilderMethod));
return fieldToModifyingMethods;
}
- private static List gatherRegistrationMethods(Class> builderClass) {
- return Arrays.stream(builderClass.getMethods())
- .filter(x -> x.isAnnotationPresent(RecipeBuilderRegistrationMethod.class))
- .sorted(
- (left, right) -> ComparisonChain.start()
- .compare(left.getAnnotation(RecipeBuilderRegistrationMethod.class).hierarchy(), right.getAnnotation(RecipeBuilderRegistrationMethod.class).hierarchy())
- // Specifically de-prioritize Object classes
- .compareFalseFirst(left.getReturnType() == Object.class, right.getReturnType() == Object.class)
- .result())
+ private static List> gatherRegistrationMethods(DescriptorHelper.OfClass methodSignatures) {
+ return methodSignatures.getMethods(RecipeBuilderRegistrationMethod.class)
+ .stream()
+ .sorted(ComparisonHelper::recipeBuilderRegistrationHierarchy)
// Ensure only the first method with a given name is used
- .filter(distinctByKey(Method::getName))
- .sorted(
- (left, right) -> ComparisonChain.start()
- .compare(left.getAnnotation(RecipeBuilderRegistrationMethod.class).priority(), right.getAnnotation(RecipeBuilderRegistrationMethod.class).priority())
- .compare(left.getName().length(), right.getName().length())
- .compare(left.getName(), right.getName(), String::compareToIgnoreCase)
- .result())
+ .filter(distinctByKey(x -> x.method().getName()))
+ .sorted(ComparisonHelper::recipeBuilderRegistration)
.collect(Collectors.toList());
}
@@ -142,26 +159,10 @@ private static List getAllFields(Class> clazz) {
return fields;
}
- /**
- * Obtains the normal default value of a class, and allows for properties to avoid having to state the default value unless it is explicitly changed.
- */
- private static String defaultValueConverter(Class> clazz) {
- if (clazz.equals(Boolean.class) || clazz.equals(boolean.class)) return "false";
- if (clazz.equals(Byte.class) || clazz.equals(byte.class)) return "0";
- if (clazz.equals(Character.class) || clazz.equals(char.class)) return "\u0000";
- if (clazz.equals(Double.class) || clazz.equals(double.class)) return "0.0d";
- if (clazz.equals(Float.class) || clazz.equals(float.class)) return "0.0f";
- if (clazz.equals(Integer.class) || clazz.equals(int.class)) return "0";
- if (clazz.equals(Long.class) || clazz.equals(long.class)) return "0";
- if (clazz.equals(Short.class) || clazz.equals(short.class)) return "0";
- if (clazz.equals(String.class)) return "";
- return "null";
- }
-
/**
* Converts a single string into an array of strings.
* Groups of code surrounded by square braces (`[]`) or single quotes (`''`) are split onto separate lines.
- * Otherwise, each line starts with a period (`.`) provided that it is not contained within any special zones (comment, string, brackets, etc)
+ * Otherwise, each line starts with a period (`.`) provided that it is not contained within any special zones (comment, string, brackets, etc.)
*/
private static List generateParts(String content) {
List parts = new ArrayList<>();
@@ -220,7 +221,7 @@ else if (!req.isEmpty() && current == req.get(req.size() - 1)) {
return output;
}
- public String builderAdmonition() {
+ public String builderExampleAdmonition() {
if (annotation.example().length == 0) return "";
return new AdmonitionBuilder()
.note(new CodeBlockBuilder().line(builder(false).split("\n")).annotation(annotations()).generate())
@@ -229,6 +230,7 @@ public String builderAdmonition() {
.generate();
}
+ @SuppressWarnings("StringBufferMayBeStringBuilder")
public String builderExampleFile() {
Matcher matcher = Documentation.ANNOTATION_COMMENT_LOCATION.matcher(builder(true));
StringBuffer sb = new StringBuffer();
@@ -246,7 +248,7 @@ public String builder(boolean canBeCommented) {
}
public List annotations() {
- return Arrays.stream(annotation.example()).flatMap(example -> Arrays.stream(example.annotations())).map(Documentation::translate).collect(Collectors.toList());
+ return Arrays.stream(annotation.example()).flatMap(example -> Arrays.stream(example.annotations())).map(LangHelper::translate).collect(Collectors.toList());
}
public String documentMethods() {
@@ -254,28 +256,32 @@ public String documentMethods() {
methods.keySet().forEach(target -> {
if (fields.containsKey(target)) return;
- GroovyLog.get().warn("Couldn't find field '{}' referenced in a method used for recipe builder '{}'", target, reference);
+ GroovyLog.get().warn("Couldn't find field '{}' referenced in a method used for recipe builder '{}'", target, location);
});
if (fields.values().stream().anyMatch(FieldDocumentation::isUsed)) {
out.append(documentFields());
} else {
- GroovyLog.get().warn("Couldn't find any fields being used for recipe builder '{}'", reference);
+ GroovyLog.get().warn("Couldn't find any fields being used for recipe builder '{}'", location);
}
+ return out.toString();
+ }
+
+ public String documentRegistration() {
+ StringBuilder out = new StringBuilder();
if (registrationMethods.isEmpty()) {
- GroovyLog.get().warn("Couldn't find any registration methods for recipe builder '{}'", reference);
+ GroovyLog.get().warn("Couldn't find any registration methods for recipe builder '{}'", location);
} else {
- for (Method registerMethod : registrationMethods) {
+ for (var registerMethod : registrationMethods) {
out.append("- ");
- String returnType = registerMethod.getAnnotatedReturnType().getType().getTypeName();
- if ("void".equals(returnType) || "null".equals(returnType)) out.append(I18n.format("groovyscript.wiki.register"));
- else out.append(I18n.format("groovyscript.wiki.register_return", returnType));
+ String returnType = registerMethod.method().getAnnotatedReturnType().getType().getTypeName();
+ if ("void".equals(returnType) || "null".equals(returnType)) out.append(I18n.format("groovyscript.wiki.recipe_builder.register"));
+ else out.append(I18n.format("groovyscript.wiki.recipe_builder.register_return", returnType));
out.append("\n\n");
- out.append(new CodeBlockBuilder().line(String.format("%s()", registerMethod.getName())).indentation(1).toString());
+ out.append(new CodeBlockBuilder().line(String.format("%s()", registerMethod.method().getName())).indentation(1).toString());
}
}
-
return out.toString();
}
@@ -283,7 +289,7 @@ public StringBuilder documentFields() {
StringBuilder out = new StringBuilder();
fields.values()
.stream()
- .sorted()
+ .sorted(ComparisonHelper::field)
.filter(FieldDocumentation::isUsed)
.forEach(fieldDocumentation -> {
@@ -306,28 +312,80 @@ public StringBuilder documentFields() {
out.append("\n\n");
- List recipeBuilderMethods = methods.get(fieldDocumentation.getField().getName());
+ var recipeBuilderMethods = methods.get(fieldDocumentation.getField().getName());
if (recipeBuilderMethods == null || recipeBuilderMethods.isEmpty()) {
- GroovyLog.get().warn("Couldn't find any methods targeting field '{}' in recipe builder '{}'", fieldDocumentation.getField().getName(), reference);
+ GroovyLog.get().warn("Couldn't find any methods targeting field '{}' in recipe builder '{}'", fieldDocumentation.getField().getName(), location);
} else {
- out.append(
- new CodeBlockBuilder()
- .line(
- recipeBuilderMethods.stream()
- .sorted()
- .map(RecipeBuilderMethod::shortMethodSignature)
- .distinct()
- .collect(Collectors.toList()))
- .indentation(1)
- .toString());
+ var lines = recipeBuilderMethods.stream()
+ .sorted(ComparisonHelper::recipeBuilderMethod)
+ .map(MethodAnnotation::method)
+ .map(DescriptorHelper::shortSignature)
+ .distinct()
+ .collect(Collectors.toList());
+ out.append(new CodeBlockBuilder().line(lines).indentation(1).toString());
}
});
return out;
}
+ public String generateAdmonition() {
+ var admonition = new AdmonitionBuilder();
+ admonition.type(Admonition.Type.ABSTRACT).hasTitle(true).title(title());
+
+ // the --- creates a page break indicator, which is used to separate blocks - but it should only do so for blocks that exist.
+ Consumer addBlock = block -> {
+ if (!block.isEmpty()) admonition.note("\n").note("---").note("\n").note(block.split("\n"));
+ };
+
+ addBlock.accept(creationMethod());
+ addBlock.accept(documentMethods());
+ addBlock.accept(documentRegistration());
+ addBlock.accept(builderExampleAdmonition());
+ admonition.note("\n");
+ return admonition.generate();
+ }
+
+ public boolean hasComplexMethod() {
+ return builderMethod.getParameterTypes().length != 0;
+ }
+
+ private String title() {
+ String lang = annotation.title();
+ String registryDefault = String.format("%s.%s.%s.title", Registry.BASE_LANG_LOCATION, location, builderMethod.getName());
+ String globalDefault = String.format("%s.recipe_builder.title", Registry.BASE_LANG_LOCATION);
+
+ if (lang.isEmpty()) {
+ if (I18n.hasKey(registryDefault)) lang = registryDefault;
+ else lang = globalDefault;
+ }
+
+ return LangHelper.translate(lang);
+ }
+
+ public String creationMethod() {
+ StringBuilder out = new StringBuilder();
+ String lang = annotation.description();
+ String registryDefault = String.format("%s.%s.%s.description", Registry.BASE_LANG_LOCATION, location, builderMethod.getName());
+ String globalDefault = String.format("%s.recipe_builder.description", Registry.BASE_LANG_LOCATION);
+
+ if (lang.isEmpty()) {
+ // If the method is complex, we want to require defining the key via the annotation or as the registryDefault.
+ if (I18n.hasKey(registryDefault) || hasComplexMethod()) lang = registryDefault;
+ else lang = globalDefault;
+ }
+
+ var example = Registry.BASE_ACCESS_COMPAT + "." + location + "." + DescriptorHelper.shortSignature(builderMethod);
+
+ out.append("- ").append(LangHelper.ensurePeriod(LangHelper.translate(lang))).append("\n\n");
+ out.append(new CodeBlockBuilder().line(example).indentation(1).toString());
+ return out.toString();
+ }
+
private String createBuilder(Example example, boolean canBeCommented) {
StringBuilder out = new StringBuilder();
+ var methodLocation = Registry.BASE_ACCESS_COMPAT + "." + location + "." + builderMethod.getName();
+ var error = GroovyLog.msg("Error creating example for " + methodLocation).error();
var prependComment = canBeCommented && example.commented();
@@ -335,20 +393,39 @@ private String createBuilder(Example example, boolean canBeCommented) {
if (!example.def().isEmpty()) out.append("def ").append(example.def()).append(" = ");
- out.append(reference).append(".").append(builderMethod.getName()).append("()");
- if (!example.value().isEmpty() || !registrationMethods.isEmpty()) out.append("\n");
+ out.append(methodLocation);
- out.append(String.join("", getOutputs(generateParts(example.value()))));
+ var exampleText = String.join("", getOutputs(generateParts(example.value())));
- if (!registrationMethods.isEmpty()) out.append(" .").append(String.format("%s()", registrationMethods.get(0).getName()));
+ if (exampleText.isEmpty()) {
+ out.append("()").append("\n");
+ } else {
+ if (hasComplexMethod()) {
+ if (!example.value().startsWith("(")) {
+ error.add("provided example for a recipe builder with parameters did not begin with a '('").post();
+ return "";
+ }
+ // trim to remove the starting indent so the builder method doesn't have 4 spaces between start
+ out.append(exampleText.trim()).append("\n");
+ } else {
+ if (!example.value().startsWith(".")) {
+ error.add("provided example for a recipe builder without parameters did not begin with a '.'").post();
+ return "";
+ }
+ out.append("()").append("\n").append(exampleText);
+ }
+ }
+
+
+ if (!registrationMethods.isEmpty()) out.append(" .").append(String.format("%s()", registrationMethods.get(0).method().getName()));
var exampleMethod = prependComment ? out.toString().replace("\n", "\n//") : out.toString();
return exampleMethod + "\n";
}
- private static class FieldDocumentation implements Comparable {
+ public static class FieldDocumentation {
private static final Function, String> SERIAL_COMMA_LIST = list -> {
int last = list.size() - 1;
@@ -371,14 +448,14 @@ public FieldDocumentation(Field field, List annotations, String langLo
}
private static String parseComparisonRequirements(Comp comp, EnumSet usedTypes) {
- return usedTypes.stream().sorted().map(type -> Documentation.translate(type.getKey(), switch (type) {
+ return usedTypes.stream().sorted().map(type -> LangHelper.translate(type.getKey(), switch (type) {
case GT -> comp.gt();
case GTE -> comp.gte();
case EQ -> comp.eq();
case LTE -> comp.lte();
case LT -> comp.lt();
case NOT -> comp.not();
- case UNI -> Documentation.translate(comp.unique());
+ case UNI -> LangHelper.translate(comp.unique());
})).collect(Collectors.collectingAndThen(Collectors.toList(), SERIAL_COMMA_LIST));
}
@@ -411,7 +488,7 @@ public String getDefaultValue() {
.filter(x -> !x.defaultValue().isEmpty())
.findFirst()
.map(Property::defaultValue)
- .orElse(defaultValueConverter(getField().getType()));
+ .orElse(DescriptorHelper.defaultValueConverter(getField().getType()));
}
public String getValue() {
@@ -437,8 +514,8 @@ public String getComparison() {
return "";
}
return Arrays.stream(comparison.get())
- .sorted((left, right) -> ComparisonChain.start().compare(left.type(), right.type()).result())
- .map(x -> Documentation.translate(x.type().getKey(), x.value()))
+ .sorted(ComparisonHelper::comp)
+ .map(x -> LangHelper.translate(x.type().getKey(), x.value()))
.collect(Collectors.joining(String.format(" %s ", I18n.format("groovyscript.wiki.and"))));
}
@@ -451,7 +528,7 @@ public String getRequirement() {
.map(Property::requirement)
.filter(x -> !x.isEmpty())
.findFirst()
- .map(Documentation::translate)
+ .map(LangHelper::translate)
.orElse("");
}
@@ -464,64 +541,12 @@ public boolean isUsed() {
}
private String getFieldTypeInlineCode() {
- //return "`#!groovy " + Exporter.simpleSignature(getField().getAnnotatedType().getType().getTypeName()) + "`. ";
- return "`" + Exporter.simpleSignature(getField().getAnnotatedType().getType().getTypeName()) + "`. ";
+ //return "`#!groovy " + DescriptorHelper.simpleTypeName(getField().getAnnotatedType().getType().getTypeName()) + "`. ";
+ return "`" + DescriptorHelper.simpleTypeName(getField().getAnnotatedType().getType().getTypeName()) + "`. ";
}
public String getDescription() {
- return "- " + getFieldTypeInlineCode() + Documentation.ensurePeriod(Documentation.translate(getLangKey()));
- }
-
- @Override
- public int compareTo(@NotNull FieldDocumentation comp) {
- return ComparisonChain.start()
- .compare(this.priority(), comp.priority())
- .compare(this.getField().getName().length(), comp.getField().getName().length())
- .compare(this.getField().getName(), comp.getField().getName(), String::compareToIgnoreCase)
- .result();
- }
- }
-
-
- private static class RecipeBuilderMethod implements Comparable {
-
- private final Method method;
- private final RecipeBuilderMethodDescription annotation;
-
- public RecipeBuilderMethod(Method method) {
- this.method = method;
- this.annotation = method.getAnnotation(RecipeBuilderMethodDescription.class);
- }
-
- public Method getMethod() {
- return method;
- }
-
- public RecipeBuilderMethodDescription getAnnotation() {
- return annotation;
- }
-
- public List targetFields() {
- return getAnnotation().field().length == 0 ? Collections.singletonList(getMethod().getName()) : Arrays.asList(getAnnotation().field());
- }
-
- public String shortMethodSignature() {
- return String.format("%s(%s)", getMethod().getName(), Exporter.simpleSignature(getMethod()));
- }
-
- @Override
- public int compareTo(@NotNull RecipeBuilderMethod comp) {
- String thisSignature = this.shortMethodSignature();
- String compSignature = comp.shortMethodSignature();
- String thisPart = thisSignature.substring(0, thisSignature.indexOf("("));
- String compPart = compSignature.substring(0, compSignature.indexOf("("));
- return ComparisonChain.start()
- .compare(this.getAnnotation().priority(), comp.getAnnotation().priority())
- .compare(thisPart.length(), compPart.length())
- .compare(thisPart, compPart, String::compareToIgnoreCase)
- .compare(thisSignature.length(), compSignature.length())
- .compare(thisSignature, compSignature, String::compareToIgnoreCase)
- .result();
+ return "- " + getFieldTypeInlineCode() + LangHelper.ensurePeriod(LangHelper.translate(getLangKey()));
}
}
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/Documentation.java b/src/main/java/com/cleanroommc/groovyscript/documentation/Documentation.java
index b5762d50c..c97f45c13 100644
--- a/src/main/java/com/cleanroommc/groovyscript/documentation/Documentation.java
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/Documentation.java
@@ -7,22 +7,20 @@
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.documentation.format.IFormat;
import com.cleanroommc.groovyscript.documentation.format.OutputFormat;
+import com.cleanroommc.groovyscript.documentation.helper.GenerationFlags;
+import com.cleanroommc.groovyscript.documentation.helper.LangHelper;
import com.cleanroommc.groovyscript.sandbox.LoadStage;
-import com.google.common.collect.ImmutableSet;
-import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
-import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
-import java.util.Set;
import java.util.regex.Pattern;
public class Documentation {
- // Matches /*()*/ or /*()!*/ and captures if theres an !
+ // Matches /*()*/ or /*()!*/ and captures if there's an !
public static final Pattern ANNOTATION_COMMENT_LOCATION = Pattern.compile("/\\*\\(\\)(!?)\\*/");
public static final int MAX_LINE_LENGTH = 120;
public static final boolean USE_DEFAULT_BRANCH = FMLLaunchHandler.isDeobfuscatedEnvironment();
@@ -32,37 +30,10 @@ public class Documentation {
public static final IFormat DEFAULT_FORMAT = OutputFormat.VITEPRESS;
- private static final boolean GENERATE_EXAMPLES = false;
- private static final boolean GENERATE_WIKI = false;
- // Kills the game as soon as the wiki or examples are generated.
- private static final boolean TEST_AND_CRASH = false;
-
- private static final boolean LOG_MISSING_KEYS = true;
-
- private static final Set missingLangKeys = new ObjectLinkedOpenHashSet<>();
- private static final Set PUNCTUATION_CHARACTERS = ImmutableSet.of('.', '!', '?');
-
public static void generate() {
- if (isGenerateExamples()) generateExamples();
- if (isGenerateWiki()) generateWiki();
- if (isTestAndCrash()) FMLCommonHandler.instance().exitJava(0, false);
- }
-
- private static boolean isGenerateExamples() {
- return GENERATE_EXAMPLES || Boolean.parseBoolean(System.getProperty("groovyscript.generate_examples"));
- }
-
- private static boolean isGenerateWiki() {
- return GENERATE_WIKI || Boolean.parseBoolean(System.getProperty("groovyscript.generate_wiki"));
- }
-
- private static boolean isTestAndCrash() {
- return TEST_AND_CRASH || Boolean.parseBoolean(System.getProperty("groovyscript.generate_and_crash"));
- }
-
- private static boolean isLogMissingKeys() {
- String property = System.getProperty("groovyscript.log_missing_lang_keys");
- return property == null ? LOG_MISSING_KEYS : Boolean.parseBoolean(property);
+ if (GenerationFlags.GENERATE_EXAMPLES) generateExamples();
+ if (GenerationFlags.GENERATE_WIKI) generateWiki();
+ if (GenerationFlags.GENERATE_AND_CRASH) FMLCommonHandler.instance().exitJava(0, false);
}
public static void generateExamples() {
@@ -80,7 +51,7 @@ public static void generateExamples() {
} catch (IOException e) {
GroovyScript.LOGGER.throwing(e);
}
- logAnyMissingKeys();
+ logMissing();
}
public static void generateWiki() {
@@ -90,7 +61,7 @@ public static void generateWiki() {
if (!mod.isLoaded()) continue;
File target = new File(WIKI, mod.getModId());
if (target.exists() || Files.createDirectories(target.toPath()) != null) {
- Exporter.generateWiki(target, mod);
+ Exporter.generateWiki(DEFAULT_FORMAT, target, mod);
} else {
GroovyLog.get().error("Error creating file at {} to generate wiki files in", target);
}
@@ -98,27 +69,11 @@ public static void generateWiki() {
} catch (IOException e) {
GroovyScript.LOGGER.throwing(e);
}
- logAnyMissingKeys();
- }
-
- public static void logAnyMissingKeys() {
- if (!missingLangKeys.isEmpty()) {
- GroovyLog.Msg log = GroovyLog.msg("Missing the following localization keys");
- missingLangKeys.stream().sorted().forEach(log::add);
- log.debug().post();
- missingLangKeys.clear();
- }
- }
-
- public static String translate(String translateKey, Object... parameters) {
- if (isLogMissingKeys() && !I18n.hasKey(translateKey)) {
- missingLangKeys.add(translateKey);
- }
- return I18n.format(translateKey, parameters);
+ logMissing();
}
- public static String ensurePeriod(String string) {
- if (string.isEmpty()) return "";
- return PUNCTUATION_CHARACTERS.contains(string.charAt(string.length() - 1)) ? string : string + ".";
+ private static void logMissing() {
+ LangHelper.logAnyMissingKeys();
+ Exporter.logSkippedClasses();
}
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/Exporter.java b/src/main/java/com/cleanroommc/groovyscript/documentation/Exporter.java
index 3418e305a..571dd97b1 100644
--- a/src/main/java/com/cleanroommc/groovyscript/documentation/Exporter.java
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/Exporter.java
@@ -6,88 +6,52 @@
import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
import com.cleanroommc.groovyscript.compat.mods.GroovyContainer;
import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer;
-import com.google.common.collect.ComparisonChain;
+import com.cleanroommc.groovyscript.documentation.format.IFormat;
+import com.cleanroommc.groovyscript.documentation.helper.ComparisonHelper;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.client.resources.I18n;
import java.io.File;
import java.io.IOException;
-import java.lang.reflect.AnnotatedType;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
+import java.util.*;
public class Exporter {
private static final String INDEX_FILE_NAME = "index.md";
private static final String NAV_FILE_NAME = "!navigation.md";
private static final String PRINT_MOD_DETECTED = "log.info 'mod \\'%s\\' detected, running script'";
- private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("(?>\\b)(?>[a-zA-Z0-9_]+\\.)+([a-zA-Z0-9_$]+)");
- public static String simpleSignature(Method method) {
- return adjustVarArgs(method, signature(method, Exporter::simpleSignature));
- }
-
- public static String simpleSignature(Method method, Map types) {
- return adjustVarArgs(method, signature(method, param -> Exporter.simpleSignature(types.getOrDefault(param, param))));
- }
-
- private static String signature(Method method, Function parseParameterFunction) {
- return Arrays.stream(method.getAnnotatedParameterTypes())
- .map(AnnotatedType::getType)
- .map(Type::getTypeName)
- .map(parseParameterFunction)
- .collect(Collectors.joining(", "));
- }
-
- public static String simpleSignature(String name) {
- return CLASS_NAME_PATTERN.matcher(name).replaceAll("$1").replaceAll("\\$", ".");
- }
+ private static final Map> SKIPPED_CLASSES = new Object2ObjectOpenHashMap<>();
- private static String adjustVarArgs(Method method, String signature) {
- return method.isVarArgs() ? convertVarArgs(signature) : signature;
- }
-
- private static String convertVarArgs(String name) {
- return name.substring(0, name.lastIndexOf("[]")) + "..." + name.substring(name.lastIndexOf("[]") + 2);
- }
-
-
- public static void generateWiki(File folder, GroovyContainer extends GroovyPropertyContainer> mod) {
+ public static void generateWiki(IFormat format, File folder, GroovyContainer extends GroovyPropertyContainer> mod) {
List fileLinks = new ArrayList<>();
- List registries = mod.get()
- .getRegistries()
- .stream()
- .filter(x -> x.getClass().isAnnotationPresent(RegistryDescription.class))
- .distinct()
- .sorted(
- (left, right) -> ComparisonChain.start()
- .compare(left.getClass().getAnnotation(RegistryDescription.class).priority(), right.getClass().getAnnotation(RegistryDescription.class).priority())
- .compare(left.getName(), right.getName())
- .result())
- .collect(Collectors.toList());
+ Set registries = new HashSet<>();
+ for (INamed named : mod.get().getRegistries()) {
+ var annotation = named.getClass().getAnnotation(RegistryDescription.class);
+ if (annotation == null) {
+ SKIPPED_CLASSES.put(mod.getModId() + "." + named.getName(), named.getClass());
+ } else {
+ registries.add(named);
+ }
+ }
if (registries.isEmpty()) return;
- for (INamed registry : registries) {
- Registry example = new Registry(mod, registry);
-
- String location = String.format("%s.md", registry.getName());
- fileLinks.add(String.format("* [%s](./%s)", example.getTitle(), location));
- try {
- File file = new File(folder, location);
- Files.write(file.toPath(), example.documentationBlock().trim().concat("\n").getBytes());
- } catch (IOException e) {
- GroovyScript.LOGGER.throwing(e);
- }
- }
+ registries.stream()
+ .sorted(ComparisonHelper::iNamed)
+ .forEach(registry -> {
+ Registry example = new Registry(mod, registry);
+ String location = String.format("%s.md", registry.getName());
+ fileLinks.add(String.format("* [%s](./%s)", example.getTitle(), location));
+ try {
+ File file = new File(folder, location);
+ Files.write(file.toPath(), example.documentationBlock().trim().concat("\n").getBytes());
+ } catch (IOException e) {
+ GroovyScript.LOGGER.throwing(e);
+ }
+ });
// TODO add bracket handlers
// maybe also add commands?
@@ -95,7 +59,7 @@ public static void generateWiki(File folder, GroovyContainer extends GroovyPro
StringBuilder index = new StringBuilder()
.append("---")
.append("\n")
- .append(Documentation.DEFAULT_FORMAT.removeTableOfContentsText())
+ .append(format.removeTableOfContentsText())
.append("\n") // Removes the table of contents from the sidebar of indexes.
.append("---")
.append("\n\n\n")
@@ -131,7 +95,7 @@ public static void generateWiki(File folder, GroovyContainer extends GroovyPro
GroovyScript.LOGGER.throwing(e);
}
- if (Documentation.DEFAULT_FORMAT.requiresNavFile()) {
+ if (format.requiresNavFile()) {
try {
File file = new File(folder, NAV_FILE_NAME);
Files.write(file.toPath(), navigation.toString().getBytes());
@@ -156,27 +120,28 @@ public static void generateExamples(String target, GroovyContainer extends Gro
.append("\n");
// Iterate through every registry of the mod once, in alphabetical order.
- List registries = mod.get()
- .getRegistries()
- .stream()
- .distinct()
- .filter(x -> x.getClass().isAnnotationPresent(RegistryDescription.class))
- .filter(x -> x.getClass().getAnnotation(RegistryDescription.class).location().equals(target))
- .sorted(
- (left, right) -> ComparisonChain.start()
- .compare(left.getClass().getAnnotation(RegistryDescription.class).priority(), right.getClass().getAnnotation(RegistryDescription.class).priority())
- .compare(left.getName(), right.getName())
- .result())
- .collect(Collectors.toList());
+ Set registries = new HashSet<>();
+ for (INamed named : mod.get().getRegistries()) {
+ var annotation = named.getClass().getAnnotation(RegistryDescription.class);
+ if (annotation == null) {
+ SKIPPED_CLASSES.put(mod.getModId() + "." + named.getName(), named.getClass());
+ } else {
+ if (annotation.location().equals(target)) {
+ registries.add(named);
+ }
+ }
+ }
if (registries.isEmpty()) return;
- for (INamed registry : registries) {
- GroovyLog.msg("Generating examples for the mod {} and registry '{}'.", mod.toString(), registry.getName()).debug().post();
- Registry example = new Registry(mod, registry);
- imports.addAll(example.getImports());
- body.append(example.exampleBlock());
- }
+ registries.stream()
+ .sorted(ComparisonHelper::iNamed)
+ .forEach(registry -> {
+ GroovyLog.msg("Generating examples for the mod {} and registry '{}'.", mod.toString(), registry.getName()).debug().post();
+ Registry example = new Registry(mod, registry);
+ imports.addAll(example.getImports());
+ body.append(example.exampleBlock());
+ });
if (!imports.isEmpty()) header.append("\n");
imports.stream().distinct().sorted().forEach(i -> header.append("import ").append(i).append("\n"));
@@ -194,4 +159,12 @@ public static void generateExamples(String target, GroovyContainer extends Gro
GroovyScript.LOGGER.throwing(e);
}
}
+
+ public static void logSkippedClasses() {
+ if (SKIPPED_CLASSES.isEmpty()) return;
+ GroovyLog.Msg log = GroovyLog.msg("Skipped documenting the following potentially valid locations (this may be the correct behavior!)");
+ SKIPPED_CLASSES.forEach((key, value) -> log.add(key + ": " + value.getName()));
+ log.debug().post();
+ SKIPPED_CLASSES.clear();
+ }
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/Registry.java b/src/main/java/com/cleanroommc/groovyscript/documentation/Registry.java
index f790aa22f..9974e2be5 100644
--- a/src/main/java/com/cleanroommc/groovyscript/documentation/Registry.java
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/Registry.java
@@ -1,12 +1,16 @@
package com.cleanroommc.groovyscript.documentation;
-import com.cleanroommc.groovyscript.api.GroovyBlacklist;
import com.cleanroommc.groovyscript.api.INamed;
import com.cleanroommc.groovyscript.api.documentation.annotations.*;
import com.cleanroommc.groovyscript.compat.mods.GroovyContainer;
import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer;
+import com.cleanroommc.groovyscript.documentation.helper.AdmonitionBuilder;
+import com.cleanroommc.groovyscript.documentation.helper.CodeBlockBuilder;
+import com.cleanroommc.groovyscript.documentation.helper.descriptor.DescriptorHelper;
+import com.cleanroommc.groovyscript.documentation.helper.descriptor.MethodAnnotation;
+import com.cleanroommc.groovyscript.documentation.helper.ComparisonHelper;
+import com.cleanroommc.groovyscript.documentation.helper.LangHelper;
import com.cleanroommc.groovyscript.documentation.linkgenerator.LinkGeneratorHooks;
-import com.google.common.collect.ComparisonChain;
import net.minecraft.client.resources.I18n;
import org.apache.commons.lang3.text.WordUtils;
@@ -17,10 +21,12 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-
public class Registry {
+ public static final String BASE_LANG_LOCATION = "groovyscript.wiki";
+ public static final String BASE_ACCESS_COMPAT = "mods";
private static final Pattern PERIOD_END_PATTERN = Pattern.compile("\\.$");
+
private final GroovyContainer extends GroovyPropertyContainer> mod;
private final INamed registry;
private final String baseTranslationKey;
@@ -28,46 +34,39 @@ public class Registry {
private final Class> registryClass;
private final RegistryDescription description;
private final Map types;
- private final List recipeBuilderMethods;
- private final EnumMap> methods = new EnumMap<>(MethodDescription.Type.class);
- private final List imports;
+ private final List recipeBuilders;
+ private final EnumMap>> methods;
+ private final List imports = new ArrayList<>();
public Registry(GroovyContainer extends GroovyPropertyContainer> mod, INamed registry) {
this.mod = mod;
this.registry = registry;
- this.baseTranslationKey = String.format("groovyscript.wiki.%s.%s", mod.getModId(), registry.getName());
- this.reference = String.format("mods.%s.%s", mod.getModId(), registry.getName());
+ var location = mod.getModId() + "." + registry.getName();
+ this.baseTranslationKey = BASE_LANG_LOCATION + "." + location;
+ this.reference = BASE_ACCESS_COMPAT + "." + location;
this.registryClass = registry.getClass();
this.description = registryClass.getAnnotation(RegistryDescription.class);
this.types = generateTypes(registryClass);
+ var methodSignatures = generateOfClass(registryClass);
- List recipeBuilderMethods = new ArrayList<>();
- Map> methods = new EnumMap<>(MethodDescription.Type.class);
- for (MethodDescription.Type value : MethodDescription.Type.values()) methods.put(value, new ArrayList<>());
- List imports = new ArrayList<>();
-
- for (Method method : registryClass.getMethods()) {
- // skip bridge methods as they are overridden by a child method.
- if (method.isBridge()) continue;
- if (method.isAnnotationPresent(GroovyBlacklist.class)) continue;
- if (method.isAnnotationPresent(RecipeBuilderDescription.class)) {
- recipeBuilderMethods.add(method);
- for (Example example : method.getAnnotation(RecipeBuilderDescription.class).example()) {
- Collections.addAll(imports, example.imports());
- }
- }
- if (method.isAnnotationPresent(MethodDescription.class)) {
- MethodDescription description = method.getAnnotation(MethodDescription.class);
- methods.get(description.type()).add(method);
- for (Example example : description.example()) {
- Collections.addAll(imports, example.imports());
- }
- }
- }
+ List> recipeBuilderMethods = new ArrayList<>();
+ this.methods = new EnumMap<>(MethodDescription.Type.class);
+ for (MethodDescription.Type value : MethodDescription.Type.values()) this.methods.put(value, new ArrayList<>());
- this.recipeBuilderMethods = sortGrSRecipeBuilderDescriptionMethods(recipeBuilderMethods);
- methods.forEach((k, v) -> this.methods.put(k, sortGrSMethodDescriptionMethods(v)));
- this.imports = imports;
+ for (var entry : methodSignatures.getMethods(RecipeBuilderDescription.class)) {
+ recipeBuilderMethods.add(entry);
+ addImports(entry.annotation().example());
+ }
+ for (var entry : methodSignatures.getMethods(MethodDescription.class)) {
+ methods.get(entry.annotation().type()).add(entry);
+ addImports(entry.annotation().example());
+ }
+ this.recipeBuilders = recipeBuilderMethods
+ .stream()
+ .sorted(ComparisonHelper::recipeBuilder)
+ .map(x -> new Builder(x.method(), x.annotation(), location))
+ .collect(Collectors.toList());
+ methods.values().forEach(value -> value.sort(ComparisonHelper::method));
}
/**
@@ -87,43 +86,23 @@ private static Map generateTypes(Class> registryClass) {
return types;
}
- private static List sortGrSRecipeBuilderDescriptionMethods(List methods) {
- methods.sort(
- (left, right) -> ComparisonChain.start()
- .compareFalseFirst(left.isAnnotationPresent(RecipeBuilderDescription.class), right.isAnnotationPresent(RecipeBuilderDescription.class))
- .compare(left.getAnnotation(RecipeBuilderDescription.class).priority(), right.getAnnotation(RecipeBuilderDescription.class).priority())
- .compare(left.getName(), right.getName(), String::compareToIgnoreCase)
- .compare(Exporter.simpleSignature(left), Exporter.simpleSignature(right), String::compareToIgnoreCase)
- .result());
- return methods;
- }
-
- private static List sortGrSMethodDescriptionMethods(List methods) {
- methods.sort(
- (left, right) -> ComparisonChain.start()
- .compareFalseFirst(left.isAnnotationPresent(MethodDescription.class), right.isAnnotationPresent(MethodDescription.class))
- .compare(left.getAnnotation(MethodDescription.class).priority(), right.getAnnotation(MethodDescription.class).priority())
- .compare(left.getName(), right.getName(), String::compareToIgnoreCase)
- .compare(Exporter.simpleSignature(left), Exporter.simpleSignature(right), String::compareToIgnoreCase)
- .result());
- return methods;
- }
-
- private static List getExamples(Method method) {
- return method.isAnnotationPresent(MethodDescription.class)
- ? new ArrayList<>(Arrays.asList(method.getAnnotation(MethodDescription.class).example()))
- : new ArrayList<>();
+ private static DescriptorHelper.OfClass generateOfClass(Class> clazz) {
+ var methodSignatures = DescriptorHelper.generateOfClass(clazz);
+ var description = clazz.getAnnotation(RegistryDescription.class);
+ if (description != null) {
+ var override = description.override();
+ for (var annotation : override.method()) {
+ methodSignatures.addAnnotation(annotation.method(), annotation);
+ }
+ for (var annotation : override.recipeBuilder()) {
+ methodSignatures.addAnnotation(annotation.method(), annotation);
+ }
+ }
+ return methodSignatures;
}
- private static List sortExamples(List examples) {
- examples.sort(
- (left, right) -> ComparisonChain.start()
- .compare(left.priority(), right.priority())
- .compareFalseFirst(left.commented(), right.commented())
- .compare(left.value().length(), right.value().length())
- .compare(left.value(), right.value())
- .result());
- return examples;
+ private void addImports(Example... examples) {
+ for (var example : examples) Collections.addAll(imports, example.imports());
}
public List getImports() {
@@ -135,12 +114,12 @@ public String getFileSourceCodeLink() {
}
public String getTitle() {
- return Documentation.translate(description.title().isEmpty() ? String.format("%s.title", baseTranslationKey) : description.title());
+ return LangHelper.translate(description.title().isEmpty() ? String.format("%s.title", baseTranslationKey) : description.title());
}
public String getDescription() {
- return Documentation.ensurePeriod(
- Documentation.translate(description.description().isEmpty() ? String.format("%s.description", baseTranslationKey) : description.description())
+ return LangHelper.ensurePeriod(
+ LangHelper.translate(description.description().isEmpty() ? String.format("%s.description", baseTranslationKey) : description.description())
.replace("\"", "\\\""));
}
@@ -149,8 +128,10 @@ public String exampleBlock() {
out.append("// ").append(getTitle()).append(":").append("\n");
out.append("// ").append(WordUtils.wrap(getDescription(), Documentation.MAX_LINE_LENGTH, "\n// ", false)).append("\n\n");
out.append(documentMethodDescriptionType(MethodDescription.Type.REMOVAL));
- for (Method method : recipeBuilderMethods) out.append(new Builder(method, reference, baseTranslationKey).builderExampleFile()).append("\n");
- if (!recipeBuilderMethods.isEmpty()) out.append("\n");
+ if (!recipeBuilders.isEmpty()) {
+ for (var builder : recipeBuilders) out.append(builder.builderExampleFile()).append("\n");
+ out.append("\n");
+ }
out.append(documentMethodDescriptionType(MethodDescription.Type.ADDITION));
out.append(documentMethodDescriptionType(MethodDescription.Type.VALUE));
return out.toString();
@@ -205,7 +186,7 @@ private String generateDescription() {
.title(note.title())
.hasTitle(note.hasTitle())
.format(note.format())
- .note(Documentation.ensurePeriod(Documentation.translate(note.value())))
+ .note(LangHelper.ensurePeriod(LangHelper.translate(note.value())))
.generate());
out.append("\n\n");
}
@@ -218,7 +199,7 @@ private String generateIdentifier() {
List packages = mod.getAliases()
.stream()
- .flatMap(modID -> registry.getAliases().stream().map(alias -> String.format("mods.%s.%s", modID, alias)))
+ .flatMap(modID -> registry.getAliases().stream().map(alias -> String.format("%s.%s.%s", Registry.BASE_ACCESS_COMPAT, modID, alias)))
.collect(Collectors.toList());
int target = packages.indexOf(reference);
@@ -246,19 +227,10 @@ private String recipeBuilder() {
.append(I18n.format("groovyscript.wiki.recipe_builder_note", Documentation.DEFAULT_FORMAT.linkToBuilder()))
.append("\n\n");
- for (int i = 0; i < recipeBuilderMethods.size(); i++) {
- Builder builder = new Builder(recipeBuilderMethods.get(i), reference, baseTranslationKey);
- out.append(
- new AdmonitionBuilder()
- .type(Admonition.Type.ABSTRACT)
- .hasTitle(true)
- .title(methodExample(recipeBuilderMethods.get(i)))
- .note(builder.documentMethods().split("\n"))
- .note("\n")
- .note(builder.builderAdmonition().split("\n"))
- .note("\n")
- .generate());
- if (i < recipeBuilderMethods.size() - 1) out.append("\n\n");
+ int size = recipeBuilders.size();
+ for (int i = 0; i < size; i++) {
+ out.append(recipeBuilders.get(i).generateAdmonition());
+ if (i < size - 1) out.append("\n\n");
}
return out.toString();
}
@@ -274,43 +246,43 @@ public String documentationBlock() {
if (!methods.get(MethodDescription.Type.VALUE).isEmpty()) {
out.append("## ").append(I18n.format("groovyscript.wiki.editing_values")).append("\n\n").append(documentMethods(methods.get(MethodDescription.Type.VALUE))).append("\n");
}
- if (!methods.get(MethodDescription.Type.ADDITION).isEmpty() || !recipeBuilderMethods.isEmpty()) {
- out.append("## ").append(Documentation.translate(description.category().adding())).append("\n\n");
+ if (!methods.get(MethodDescription.Type.ADDITION).isEmpty() || !recipeBuilders.isEmpty()) {
+ out.append("## ").append(LangHelper.translate(description.category().adding())).append("\n\n");
if (!methods.get(MethodDescription.Type.ADDITION).isEmpty()) {
out.append(documentMethods(methods.get(MethodDescription.Type.ADDITION))).append("\n");
}
- if (!recipeBuilderMethods.isEmpty()) {
+ if (!recipeBuilders.isEmpty()) {
out.append(recipeBuilder()).append("\n\n");
}
}
if (!methods.get(MethodDescription.Type.REMOVAL).isEmpty()) {
- out.append("## ").append(Documentation.translate(description.category().removing())).append("\n\n").append(documentMethods(methods.get(MethodDescription.Type.REMOVAL))).append("\n");
+ out.append("## ").append(LangHelper.translate(description.category().removing())).append("\n\n").append(documentMethods(methods.get(MethodDescription.Type.REMOVAL))).append("\n");
}
if (!methods.get(MethodDescription.Type.QUERY).isEmpty()) {
- out.append("## ").append(Documentation.translate(description.category().query())).append("\n\n").append(documentMethods(methods.get(MethodDescription.Type.QUERY), true)).append("\n");
+ out.append("## ").append(LangHelper.translate(description.category().query())).append("\n\n").append(documentMethods(methods.get(MethodDescription.Type.QUERY), true)).append("\n");
}
out.append("\n");
return out.toString();
}
- public String documentMethods(List methods) {
+ public String documentMethods(List> methods) {
return documentMethods(methods, false);
}
- public String documentMethods(List methods, boolean preventExamples) {
+ public String documentMethods(List> methods, boolean preventExamples) {
StringBuilder out = new StringBuilder();
List exampleLines = new ArrayList<>();
List annotations = new ArrayList<>();
- for (Method method : methods) {
+ for (MethodAnnotation method : methods) {
out.append(methodDescription(method));
- if (method.getAnnotation(MethodDescription.class).example().length > 0 && Arrays.stream(method.getAnnotation(MethodDescription.class).example()).anyMatch(x -> !x.value().isEmpty())) {
- exampleLines.addAll(Arrays.stream(method.getAnnotation(MethodDescription.class).example()).flatMap(example -> Stream.of(methodExample(method, example.value()))).collect(Collectors.toList()));
- } else if (method.getParameterTypes().length == 0) {
- exampleLines.add(methodExample(method));
+ if (method.annotation().example().length > 0 && Arrays.stream(method.annotation().example()).anyMatch(x -> !x.value().isEmpty())) {
+ exampleLines.addAll(Arrays.stream(method.annotation().example()).flatMap(example -> Stream.of(methodExample(method.method(), example.value()))).collect(Collectors.toList()));
+ } else if (method.method().getParameterTypes().length == 0) {
+ exampleLines.add(methodExample(method.method()));
}
- Arrays.stream(method.getAnnotation(MethodDescription.class).example()).map(Example::annotations).flatMap(Arrays::stream).forEach(annotations::add);
+ Arrays.stream(method.annotation().example()).map(Example::annotations).flatMap(Arrays::stream).forEach(annotations::add);
}
if (!exampleLines.isEmpty() && !preventExamples) {
@@ -329,21 +301,21 @@ public String documentMethods(List methods, boolean preventExamples) {
return out.toString();
}
- private String methodDescription(Method method) {
- String desc = method.getAnnotation(MethodDescription.class).description();
- String registryDefault = String.format("%s.%s", baseTranslationKey, method.getName());
- String globalDefault = String.format("groovyscript.wiki.%s", method.getName());
- // If `desc` isn't defined, check the `registryDefault` key. If it exists, use it.
- // Then, check the `globalDefault` key. If it exists use it. Otherwise, we want to still use the `registryDefault` for logging a missing key.
- String lang = desc.isEmpty()
- ? I18n.hasKey(registryDefault) || !I18n.hasKey(globalDefault) ? registryDefault : globalDefault
- : desc;
+ public String methodDescription(MethodAnnotation method) {
+ String lang = method.annotation().description();
+ String registryDefault = String.format("%s.%s", baseTranslationKey, method.method().getName());
+ String globalDefault = String.format("%s.%s", Registry.BASE_LANG_LOCATION, method.method().getName());
+ if (lang.isEmpty()) {
+ // If the `globalDefault` is not defined, we always want to use `registryDefault` for logging the missing key.
+ if (I18n.hasKey(registryDefault) || !I18n.hasKey(globalDefault)) lang = registryDefault;
+ else lang = globalDefault;
+ }
return String.format(
"- %s:\n\n%s",
- PERIOD_END_PATTERN.matcher(Documentation.translate(lang)).replaceAll(""),
+ PERIOD_END_PATTERN.matcher(LangHelper.translate(lang)).replaceAll(""),
new CodeBlockBuilder()
- .line(methodExample(method, Exporter.simpleSignature(method, types)))
+ .line(methodExample(method.method(), DescriptorHelper.simpleParameters(method.method(), types)))
.indentation(1)
.toString());
}
@@ -357,16 +329,18 @@ private String methodExample(Method method) {
return String.format("%s.%s()", reference, method.getName());
}
- private String examples(Method method) {
+ private String examples(MethodAnnotation method) {
StringBuilder out = new StringBuilder();
- for (Example example : sortExamples(getExamples(method))) {
- if (example.commented()) out.append("// ");
- if (!example.def().isEmpty()) out.append("def ").append(example.def()).append(" = ");
- out.append(reference).append(".").append(method.getName());
- if (example.value().isEmpty()) out.append("()");
- else out.append("(").append(example.value()).append(")");
- out.append("\n");
- }
+ Arrays.stream(method.annotation().example())
+ .sorted(ComparisonHelper::example)
+ .forEach(example -> {
+ if (example.commented()) out.append("// ");
+ if (!example.def().isEmpty()) out.append("def ").append(example.def()).append(" = ");
+ out.append(reference).append(".").append(method.method().getName());
+ if (example.value().isEmpty()) out.append("()");
+ else out.append("(").append(example.value()).append(")");
+ out.append("\n");
+ });
return out.toString();
}
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/format/IFormat.java b/src/main/java/com/cleanroommc/groovyscript/documentation/format/IFormat.java
index be39cf5b3..4aa768fca 100644
--- a/src/main/java/com/cleanroommc/groovyscript/documentation/format/IFormat.java
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/format/IFormat.java
@@ -50,7 +50,7 @@ public interface IFormat {
boolean hasTitleTemplate();
/**
- * @return if admonitions allow additional indentation within the block or if doing so will break the markdown parser
+ * @return if admonitions allow additional indentation within the block or if doing so will break the Markdown parser
*/
boolean allowsIndentation();
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/AdmonitionBuilder.java b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/AdmonitionBuilder.java
similarity index 95%
rename from src/main/java/com/cleanroommc/groovyscript/documentation/AdmonitionBuilder.java
rename to src/main/java/com/cleanroommc/groovyscript/documentation/helper/AdmonitionBuilder.java
index 6d4601019..9bf5b90e0 100644
--- a/src/main/java/com/cleanroommc/groovyscript/documentation/AdmonitionBuilder.java
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/AdmonitionBuilder.java
@@ -1,6 +1,7 @@
-package com.cleanroommc.groovyscript.documentation;
+package com.cleanroommc.groovyscript.documentation.helper;
import com.cleanroommc.groovyscript.api.documentation.annotations.Admonition;
+import com.cleanroommc.groovyscript.documentation.Documentation;
import com.cleanroommc.groovyscript.documentation.format.IFormat;
import org.apache.commons.lang3.StringUtils;
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/CodeBlockBuilder.java b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/CodeBlockBuilder.java
similarity index 94%
rename from src/main/java/com/cleanroommc/groovyscript/documentation/CodeBlockBuilder.java
rename to src/main/java/com/cleanroommc/groovyscript/documentation/helper/CodeBlockBuilder.java
index fcbd41729..61e0699b9 100644
--- a/src/main/java/com/cleanroommc/groovyscript/documentation/CodeBlockBuilder.java
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/CodeBlockBuilder.java
@@ -1,5 +1,6 @@
-package com.cleanroommc.groovyscript.documentation;
+package com.cleanroommc.groovyscript.documentation.helper;
+import com.cleanroommc.groovyscript.documentation.Documentation;
import com.cleanroommc.groovyscript.documentation.format.IFormat;
import org.apache.commons.lang3.StringUtils;
@@ -71,6 +72,7 @@ public List generate() {
return generate(Documentation.DEFAULT_FORMAT);
}
+ @SuppressWarnings("StringBufferMayBeStringBuilder")
public List generate(IFormat format) {
List out = new ArrayList<>();
String indent = StringUtils.repeat(" ", indentation);
@@ -81,7 +83,7 @@ public List generate(IFormat format) {
if (!annotations.isEmpty()) out.add("");
- if (Documentation.DEFAULT_FORMAT.usesFocusInCodeBlocks()) {
+ if (format.usesFocusInCodeBlocks()) {
int i = 0;
for (int x = 0; x < out.size(); x++) {
Matcher matcher = Documentation.ANNOTATION_COMMENT_LOCATION.matcher(out.get(x));
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/helper/ComparisonHelper.java b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/ComparisonHelper.java
new file mode 100644
index 000000000..8b7fe7be0
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/ComparisonHelper.java
@@ -0,0 +1,115 @@
+package com.cleanroommc.groovyscript.documentation.helper;
+
+import com.cleanroommc.groovyscript.api.INamed;
+import com.cleanroommc.groovyscript.api.documentation.annotations.*;
+import com.cleanroommc.groovyscript.documentation.Builder;
+import com.cleanroommc.groovyscript.documentation.helper.descriptor.DescriptorHelper;
+import com.cleanroommc.groovyscript.documentation.helper.descriptor.MethodAnnotation;
+import com.google.common.collect.ComparisonChain;
+
+import java.lang.reflect.Method;
+
+/**
+ * A helper class for comparing various documentation elements against each other.
+ *
+ */
+public final class ComparisonHelper {
+
+ private ComparisonHelper() {}
+
+ public static int iNamed(INamed left, INamed right) {
+ return ComparisonChain.start()
+ .compare(left.getClass().getAnnotation(RegistryDescription.class).priority(), right.getClass().getAnnotation(RegistryDescription.class).priority())
+ .compare(left.getName(), right.getName())
+ .result();
+ }
+
+ public static int method(MethodAnnotation left, MethodAnnotation right) {
+ return ComparisonHelper.comparePriorityAndMethod(left.annotation().priority(), right.annotation().priority(), left.method(), right.method());
+ }
+
+ public static int recipeBuilder(MethodAnnotation left, MethodAnnotation right) {
+ return ComparisonHelper.comparePriorityAndMethod(left.annotation().priority(), right.annotation().priority(), left.method(), right.method());
+ }
+
+ public static int example(Example left, Example right) {
+ var leftValue = left.value();
+ var rightValue = right.value();
+ return ComparisonChain.start()
+ .compare(left.priority(), right.priority())
+ .compareFalseFirst(left.commented(), right.commented())
+ .compare(leftValue.length(), rightValue.length())
+ .compare(leftValue, rightValue)
+ .result();
+ }
+
+ public static int recipeBuilderMethod(MethodAnnotation left, MethodAnnotation right) {
+ String leftSignature = DescriptorHelper.shortSignature(left.method());
+ String rightSignature = DescriptorHelper.shortSignature(right.method());
+ String leftPart = leftSignature.substring(0, leftSignature.indexOf("("));
+ String rightPart = rightSignature.substring(0, rightSignature.indexOf("("));
+ return ComparisonChain.start()
+ .compare(left.annotation().priority(), right.annotation().priority())
+ .compare(leftPart.length(), rightPart.length())
+ .compare(leftPart, rightPart, String::compareToIgnoreCase)
+ .compare(leftSignature.length(), rightSignature.length())
+ .compare(leftSignature, rightSignature, String::compareToIgnoreCase)
+ .result();
+ }
+
+ /**
+ * In order to ensure the filtering process filters out the correct entries,
+ * we sort the stream before filtering.
+ * The way we sort is different from the usual {@link #recipeBuilderRegistration},
+ * and targets hierarchy and tries to skip returns of Object.
+ */
+ public static int recipeBuilderRegistrationHierarchy(MethodAnnotation left, MethodAnnotation right) {
+ return ComparisonChain.start()
+ .compare(left.annotation().hierarchy(), right.annotation().hierarchy())
+ // Specifically de-prioritize Object classes
+ .compareFalseFirst(left.method().getReturnType() == Object.class, right.method().getReturnType() == Object.class)
+ .result();
+ }
+
+ public static int recipeBuilderRegistration(MethodAnnotation left, MethodAnnotation right) {
+ var leftName = left.method().getName();
+ var rightName = right.method().getName();
+ return ComparisonChain.start()
+ .compare(left.annotation().priority(), right.annotation().priority())
+ .compare(leftName.length(), rightName.length())
+ .compare(leftName, rightName, String::compareToIgnoreCase)
+ .result();
+ }
+
+ public static int field(Builder.FieldDocumentation left, Builder.FieldDocumentation right) {
+ var leftName = left.getField().getName();
+ var rightName = right.getField().getName();
+ return ComparisonChain.start()
+ .compare(left.priority(), right.priority())
+ .compare(leftName.length(), rightName.length())
+ .compare(leftName, rightName, String::compareToIgnoreCase)
+ .result();
+ }
+
+ public static int property(Property left, Property right) {
+ return ComparisonChain.start()
+ .compare(left.hierarchy(), right.hierarchy())
+ .result();
+ }
+
+ @SuppressWarnings("deprecation")
+ public static int comp(Comp left, Comp right) {
+ return ComparisonChain.start()
+ .compare(left.type(), right.type())
+ .result();
+ }
+
+ private static int comparePriorityAndMethod(int leftPriority, int rightPriority, Method leftMethod, Method rightName) {
+ return ComparisonChain.start()
+ .compare(leftPriority, rightPriority)
+ .compare(leftMethod.getName(), rightName.getName(), String::compareToIgnoreCase)
+ .compare(DescriptorHelper.simpleParameters(leftMethod), DescriptorHelper.simpleParameters(rightName), String::compareToIgnoreCase)
+ .result();
+
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/helper/GenerationFlags.java b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/GenerationFlags.java
new file mode 100644
index 000000000..b59699ef7
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/GenerationFlags.java
@@ -0,0 +1,10 @@
+package com.cleanroommc.groovyscript.documentation.helper;
+
+public class GenerationFlags {
+
+ public static final boolean GENERATE_EXAMPLES = Boolean.getBoolean("groovyscript.generate_examples");
+ public static final boolean GENERATE_WIKI = Boolean.getBoolean("groovyscript.generate_wiki");
+ // Kills the game as soon as the wiki or examples are generated.
+ public static final boolean GENERATE_AND_CRASH = Boolean.getBoolean("groovyscript.generate_and_crash");
+ public static final boolean LOG_MISSING_LANG_KEYS = Boolean.getBoolean("groovyscript.log_missing_lang_keys");
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/helper/LangHelper.java b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/LangHelper.java
new file mode 100644
index 000000000..28027a110
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/LangHelper.java
@@ -0,0 +1,45 @@
+package com.cleanroommc.groovyscript.documentation.helper;
+
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import it.unimi.dsi.fastutil.chars.CharOpenHashSet;
+import it.unimi.dsi.fastutil.chars.CharSet;
+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+import net.minecraft.client.resources.I18n;
+
+import java.util.Set;
+
+public class LangHelper {
+
+ private static final Set MISSING_LANG_KEYS = new ObjectOpenHashSet<>();
+ private static final CharSet PUNCTUATION_CHARACTERS;
+
+ static {
+ PUNCTUATION_CHARACTERS = new CharOpenHashSet();
+ PUNCTUATION_CHARACTERS.add('.');
+ PUNCTUATION_CHARACTERS.add('!');
+ PUNCTUATION_CHARACTERS.add('?');
+ PUNCTUATION_CHARACTERS.add(',');
+ PUNCTUATION_CHARACTERS.add(':');
+ PUNCTUATION_CHARACTERS.add(';');
+ }
+
+ public static void logAnyMissingKeys() {
+ if (MISSING_LANG_KEYS.isEmpty()) return;
+ GroovyLog.Msg log = GroovyLog.msg("Missing the following localization keys");
+ MISSING_LANG_KEYS.stream().sorted().forEach(log::add);
+ log.debug().post();
+ MISSING_LANG_KEYS.clear();
+ }
+
+ public static String translate(String translateKey, Object... parameters) {
+ if (GenerationFlags.LOG_MISSING_LANG_KEYS && !I18n.hasKey(translateKey)) {
+ MISSING_LANG_KEYS.add(translateKey);
+ }
+ return I18n.format(translateKey, parameters);
+ }
+
+ public static String ensurePeriod(String string) {
+ if (string.isEmpty()) return "";
+ return PUNCTUATION_CHARACTERS.contains(string.charAt(string.length() - 1)) ? string : string + ".";
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/helper/descriptor/DescriptorHelper.java b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/descriptor/DescriptorHelper.java
new file mode 100644
index 000000000..e6827f6ee
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/descriptor/DescriptorHelper.java
@@ -0,0 +1,288 @@
+package com.cleanroommc.groovyscript.documentation.helper.descriptor;
+
+import com.cleanroommc.groovyscript.api.GroovyBlacklist;
+import com.cleanroommc.groovyscript.api.GroovyLog;
+import it.unimi.dsi.fastutil.objects.Object2CharMap;
+import it.unimi.dsi.fastutil.objects.Object2CharOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+public class DescriptorHelper {
+
+ /**
+ * Holds a mapping from Java type names to native type codes.
+ */
+ private static final Object2CharMap> PRIMITIVE_TO_TERM;
+ /**
+ * Blocks checking of methods that are a bridge, not public, from Object, or annotated with {@link GroovyBlacklist}.
+ */
+ private static final Predicate DEFAULT_EXCLUSION;
+ private static final Pattern CLASS_NAME_PATTERN;
+
+ static {
+ PRIMITIVE_TO_TERM = new Object2CharOpenHashMap<>();
+ PRIMITIVE_TO_TERM.put(byte.class, 'B');
+ PRIMITIVE_TO_TERM.put(char.class, 'C');
+ PRIMITIVE_TO_TERM.put(short.class, 'S');
+ PRIMITIVE_TO_TERM.put(int.class, 'I');
+ PRIMITIVE_TO_TERM.put(long.class, 'J');
+ PRIMITIVE_TO_TERM.put(float.class, 'F');
+ PRIMITIVE_TO_TERM.put(double.class, 'D');
+ PRIMITIVE_TO_TERM.put(void.class, 'V');
+ PRIMITIVE_TO_TERM.put(boolean.class, 'Z');
+ var objectMethods = new ObjectOpenHashSet<>(Object.class.getMethods());
+ DEFAULT_EXCLUSION = m -> m.isBridge() || !Modifier.isPublic(m.getModifiers()) || objectMethods.contains(m) || m.isAnnotationPresent(GroovyBlacklist.class);
+ // Pattern captures the final valid class
+ CLASS_NAME_PATTERN = Pattern.compile("(?>\\b)(?>[a-zA-Z_$][a-zA-Z\\d_$]*\\.)+([a-zA-Z_$][a-zA-Z\\d_$]*)");
+ }
+
+ /**
+ * A short signature of the method where the type of each parameter
+ * only uses the class name and the return type is omitted.
+ *
+ * @param method the method to parse
+ * @return a short and compact method signature, omitting the return type
+ */
+ public static String shortSignature(Method method) {
+ return method.getName() + '(' + simpleParameters(method) + ')';
+ }
+
+ /**
+ * A clean and readable string for the parameters of the given method.
+ *
+ * @param method the method to parse
+ * @return the classes of the parameters of the method
+ */
+ public static String simpleParameters(Method method) {
+ return adjustVarArgs(method, parameters(method, Function.identity()));
+ }
+
+ /**
+ * A clean and readable string for the parameters of the given method,
+ * modified to ensure generics are replaced with the relevant class.
+ *
+ * @param method the method to parse
+ * @param types replacement types for the param's type name. Used to replace generics with the relevant class
+ * @return the classes of the parameters of the method, with the parameters being modified by the map
+ */
+ public static String simpleParameters(Method method, Map types) {
+ return adjustVarArgs(method, parameters(method, param -> types.getOrDefault(param, param)));
+ }
+
+ /**
+ * @param method the method to parse
+ * @param parseParameter modifies type names
+ * @return the parameters of the given method, modified via the parseParameter
+ */
+ private static String parameters(Method method, Function parseParameter) {
+ var joiner = new StringJoiner(", ");
+ for (var annotatedType : method.getAnnotatedParameterTypes()) {
+ joiner.add(DescriptorHelper.simpleTypeName(parseParameter.apply(annotatedType.getType().getTypeName())));
+ }
+ return joiner.toString();
+ }
+
+ /**
+ * Remove the package and replaces the {@code $} for inner classes with a {@code .} to improve the appearance.
+ *
+ * @param name the name to modify, typically a {@link java.lang.reflect.Type#getTypeName() Type#getTypeName()}
+ * @return a pretty type name
+ */
+ public static String simpleTypeName(String name) {
+ return CLASS_NAME_PATTERN.matcher(name).replaceAll("$1").replace('$', '.');
+ }
+
+ /**
+ * If the method uses varargs, replaces the last {@code []} in the parameters with {@code ...} to represent varargs.
+ *
+ * @return the method parameters, respecting varargs
+ */
+ private static String adjustVarArgs(Method method, String parameters) {
+ if (method.isVarArgs()) {
+ int loc = parameters.lastIndexOf("[]");
+ return parameters.substring(0, loc) + "..." + parameters.substring(loc + 2);
+ }
+ return parameters;
+ }
+
+ /**
+ * @param method the method to get the descriptor of
+ * @return the method name and descriptor
+ */
+ public static String getDescriptor(Method method) {
+ var result = new StringBuilder();
+ result.append(method.getName());
+ result.append('(');
+ for (var parameterType : method.getParameterTypes()) {
+ result.append(getDescriptor(parameterType));
+ }
+ result.append(')');
+ result.append(getDescriptor(method.getReturnType()));
+ return result.toString();
+ }
+
+ /**
+ * @param clazz the class to get the descriptor of
+ * @return the descriptor string of the target class
+ */
+ private static String getDescriptor(Class> clazz) {
+ if (clazz.isArray()) return '[' + getDescriptor(clazz.getComponentType());
+ if (clazz.isPrimitive()) return String.valueOf(PRIMITIVE_TO_TERM.getChar(clazz));
+ return 'L' + clazz.getName().replace('.', '/') + ';';
+ }
+
+ /**
+ * Obtains the standard default value of a field for its class.
+ * The {@code double}, {@code float}, and {@code long} classes have their types attached.
+ *
+ * @param clazz the class to get the default value of
+ * @return the default value of the provided class
+ */
+ public static String defaultValueConverter(Class> clazz) {
+ if (clazz.equals(boolean.class)) return "false";
+ if (clazz.equals(byte.class)) return "0";
+ if (clazz.equals(char.class)) return "\u0000";
+ if (clazz.equals(double.class)) return "0.0d";
+ if (clazz.equals(float.class)) return "0.0f";
+ if (clazz.equals(int.class)) return "0";
+ if (clazz.equals(long.class)) return "0L";
+ if (clazz.equals(short.class)) return "0";
+ return "null";
+ }
+
+ /**
+ * @param clazz the class to generate the {@link OfClass} of
+ * @return a helper class for processing the methods of an object for use in GroovyScript
+ */
+ public static OfClass generateOfClass(Class> clazz) {
+ return new OfClass(clazz, DEFAULT_EXCLUSION);
+ }
+
+ public static class OfClass {
+
+ private final Class> clazz;
+ private final Set validMethods = new ObjectOpenHashSet<>();
+ private final Map descriptorToMethod = new Object2ObjectOpenHashMap<>();
+ private final Map nameToMethod = new Object2ObjectOpenHashMap<>();
+ private final Map, List>> annotationToMethods = new Object2ObjectOpenHashMap<>();
+ private final Map> nameToSignatures = new Object2ObjectOpenHashMap<>();
+
+ public OfClass(Class> clazz, Predicate exclude) {
+ this.clazz = clazz;
+ for (var method : clazz.getMethods()) {
+ if (exclude.test(method)) continue;
+ validMethods.add(method);
+ addBasicMethod(method);
+ for (var annotation : method.getDeclaredAnnotations()) {
+ addAnnotation(method, annotation);
+ }
+ }
+ }
+
+ /**
+ * Performs multiple operations to add the given method
+ * to the relevant maps.
+ * Primarily handles methods with duplicate names.
+ *
+ * @param method method to map if not a duplicate
+ */
+ private void addBasicMethod(Method method) {
+ var name = method.getName();
+ var descriptor = DescriptorHelper.getDescriptor(method);
+ descriptorToMethod.put(descriptor, method);
+ var list = nameToSignatures.computeIfAbsent(name, k -> new ArrayList<>());
+ if (list.isEmpty()) {
+ // if the list is empty, then there are no methods with the same name yet and the method should be added to the simple name->method map
+ nameToMethod.put(name, method);
+ } else {
+ // if there are methods with the same name, make sure to remove the method from the simple name->method map
+ nameToMethod.remove(name);
+ }
+ // add the descriptor to the name->descriptor map, ensuring the list will not be empty in the future
+ list.add(descriptor);
+ }
+
+ /**
+ * @return the class being examined
+ */
+ public Class> getClazz() {
+ return clazz;
+ }
+
+ /**
+ * Adds the given method and annotation to the relevant map.
+ * Can be called outside this method to support overrides.
+ */
+ public void addAnnotation(Method method, Annotation annotation) {
+ if (method == null || annotation == null) {
+ GroovyLog.msg("Could not add the method '{}' and annotation '{}' to the list due to one of them being null!", method, annotation)
+ .error()
+ .post();
+ return;
+ }
+ annotationToMethods.computeIfAbsent(annotation.annotationType(), k -> new ArrayList<>())
+ .add(new MethodAnnotation<>(method, annotation));
+ }
+
+ /**
+ * @see #addAnnotation(Method, Annotation)
+ */
+ public void addAnnotation(String method, Annotation annotation) {
+ addAnnotation(getMethod(method), annotation);
+ }
+
+ /**
+ * @return all methods that pass the exclusion filter
+ */
+ public Set getValidMethods() {
+ return validMethods;
+ }
+
+ /**
+ * @param annotation the target annotation
+ * @param the annotation type
+ * @return all methods in the class that are annotated with the given method or were overridden via {@link #addAnnotation(Method, Annotation)}
+ */
+ @SuppressWarnings("unchecked")
+ public @NotNull List> getMethods(Class annotation) {
+ return (List>) (Object) annotationToMethods.getOrDefault(annotation, new ArrayList<>());
+ }
+
+ /**
+ * The method can be obtained via the method name, provided that there is only a single
+ * method with the given name.
+ * Otherwise, the method can only be obtained via the full method descriptor.
+ *
+ * @param target the name of the method or the method descriptor
+ * @return the method that is being targeted, if there is one and only one, otherwise log an error and return null
+ */
+ public @Nullable Method getMethod(@NotNull String target) {
+ var output = descriptorToMethod.get(target);
+ if (output != null) return output;
+ var methodSignatures = nameToSignatures.get(target);
+ if (methodSignatures.size() > 1) {
+ GroovyLog.msg("The target '{}' is a duplicate name, use one of the following descriptors instead", target)
+ .add("'" + String.join("', '", methodSignatures) + "'")
+ .warn()
+ .post();
+ }
+ output = nameToMethod.get(target);
+ if (output == null) {
+ GroovyLog.msg("Could not find target '{}' matching any method names or descriptors in the class {}", target, clazz)
+ .error()
+ .post();
+ }
+ return output;
+ }
+ }
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/helper/descriptor/MethodAnnotation.java b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/descriptor/MethodAnnotation.java
new file mode 100644
index 000000000..2402425bb
--- /dev/null
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/helper/descriptor/MethodAnnotation.java
@@ -0,0 +1,11 @@
+package com.cleanroommc.groovyscript.documentation.helper.descriptor;
+
+import com.github.bsideup.jabel.Desugar;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+@Desugar
+public record MethodAnnotation (Method method, A annotation) {
+
+}
diff --git a/src/main/java/com/cleanroommc/groovyscript/documentation/linkgenerator/BasicLinkGenerator.java b/src/main/java/com/cleanroommc/groovyscript/documentation/linkgenerator/BasicLinkGenerator.java
index 4e0aebd7a..0a5cae60b 100644
--- a/src/main/java/com/cleanroommc/groovyscript/documentation/linkgenerator/BasicLinkGenerator.java
+++ b/src/main/java/com/cleanroommc/groovyscript/documentation/linkgenerator/BasicLinkGenerator.java
@@ -6,7 +6,7 @@
/**
* Parses a class and converts it into a relative link to a website.
- * By default, converts files to a location on CleanroomMC's Groovyscript repository and uses Groovyscript's version,
+ * By default, converts files to a location on the CleanroomMC Groovyscript repository and uses GroovyScript's version,
* but can be completely overwritten to link to anywhere.
*
* An addon should replace {@link #domain()} and {@link #version()} with a link to their own repo, e.g.
@@ -15,6 +15,15 @@
*/
public class BasicLinkGenerator implements ILinkGenerator {
+ /**
+ * Ensure that the domain and path are separated by a {@code /} so the url isn't invalid due a missing slash.
+ * (this was a common issue).
+ */
+ private static String ensureSlash(String input) {
+ if (input.charAt(input.length() - 1) == '/') return input;
+ return input + '/';
+ }
+
@Override
public String id() {
return GroovyScript.ID;
@@ -46,6 +55,6 @@ protected String trimmedLocation(String location) {
@Override
public String convert(String location) {
- return domain() + path() + trimmedLocation(location) + extension();
+ return ensureSlash(domain()) + ensureSlash(path()) + trimmedLocation(location) + extension();
}
}
diff --git a/src/main/java/com/cleanroommc/groovyscript/server/GroovyScriptDocumentationProvider.java b/src/main/java/com/cleanroommc/groovyscript/server/GroovyScriptDocumentationProvider.java
index f555ce26f..f9897baa5 100644
--- a/src/main/java/com/cleanroommc/groovyscript/server/GroovyScriptDocumentationProvider.java
+++ b/src/main/java/com/cleanroommc/groovyscript/server/GroovyScriptDocumentationProvider.java
@@ -6,6 +6,7 @@
import com.cleanroommc.groovyscript.api.documentation.annotations.RegistryDescription;
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
import com.cleanroommc.groovyscript.documentation.Registry;
+import com.cleanroommc.groovyscript.documentation.helper.descriptor.MethodAnnotation;
import net.prominic.groovyls.compiler.ast.ASTContext;
import net.prominic.groovyls.compiler.documentation.IDocumentationProvider;
import net.prominic.groovyls.compiler.util.GroovyReflectionUtils;
@@ -14,7 +15,6 @@
import org.codehaus.groovy.ast.MethodNode;
import org.jetbrains.annotations.Nullable;
-import java.util.Collections;
import java.util.Objects;
public class GroovyScriptDocumentationProvider implements IDocumentationProvider {
@@ -35,7 +35,8 @@ public class GroovyScriptDocumentationProvider implements IDocumentationProvider
var method = GroovyReflectionUtils.resolveMethodFromMethodNode(methodNode, context);
if (method != null && method.isAnnotationPresent(MethodDescription.class)) {
- return new Registry(groovyContainer, methodRegistry.get()).documentMethods(Collections.singletonList(method), true);
+ return new Registry(groovyContainer, methodRegistry.get())
+ .methodDescription(new MethodAnnotation<>(method, method.getAnnotation(MethodDescription.class)));
}
}
diff --git a/src/main/resources/assets/groovyscript/lang/en_us.lang b/src/main/resources/assets/groovyscript/lang/en_us.lang
index a60f19190..7fdc16fea 100644
--- a/src/main/resources/assets/groovyscript/lang/en_us.lang
+++ b/src/main/resources/assets/groovyscript/lang/en_us.lang
@@ -90,8 +90,11 @@ groovyscript.wiki.input.value=Sets the item inputs of the recipe
groovyscript.wiki.output.value=Sets the item outputs of the recipe
groovyscript.wiki.fluidInput.value=Sets the fluid inputs of the recipe
groovyscript.wiki.fluidOutput.value=Sets the fluid outputs of the recipe
-groovyscript.wiki.register=First validates the builder, outputting errors to the log file if the validation failed, then registers the builder.
-groovyscript.wiki.register_return=First validates the builder, returning `null` and outputting errors to the log file if the validation failed, then registers the builder and returns the registered object. (returns `null` or `%s`).
+
+groovyscript.wiki.recipe_builder.title=Recipe Builder
+groovyscript.wiki.recipe_builder.description=Create the Recipe Builder
+groovyscript.wiki.recipe_builder.register=First validates the builder, outputting errors to the log file if the validation failed, then registers the builder.
+groovyscript.wiki.recipe_builder.register_return=First validates the builder, returning `null` and outputting errors to the log file if the validation failed, then registers the builder and returns the registered object. (returns `null` or `%s`).
groovyscript.wiki.craftingrecipe.matrix.required=either the key-based matrix or the ingredient-based matrix can be defined, not both
groovyscript.wiki.craftingrecipe.output.value=Sets the item output
@@ -342,6 +345,26 @@ groovyscript.wiki.arcanearchives.gem_cutting_table.note0=While more than 8 items
# Arcane World
groovyscript.wiki.arcaneworld.ritual.title=Ritual
groovyscript.wiki.arcaneworld.ritual.description=Converts up to 5 input itemstacks into a wide number of possible effects, including spawning entities, opening a portal to a dungeon dimension to fight a mob, awarding an output itemstack, running commands, and even entirely customized effects.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilder.title=Standard Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilder.description=Create a Recipe Builder for any type of recipe, always requiring up to 5 input itemstacks and a translation key.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderArena.title=Arena Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderArena.description=Create a Recipe Builder for an arena recipe, with the basic values and an entity. Teleports the player to a custom dimension to fight the entity when completed.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderCommand.title=Command Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderCommand.description=Create a Recipe Builder for a command recipe, with the basic values and an number of commands. Runs those commands when completed.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderCreateItem.title=CreateItem Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderCreateItem.description=Create a Recipe Builder for a create item recipe, with the basic values and an output itemstack. Spawns the itemstack in-world when completed.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderDragonBreath.title=DragonBreath Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderDragonBreath.description=Create a Recipe Builder for a dragon breath recipe, with only the basic values. Summons Dragons Breath when completed.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderDungeon.title=Dungeon Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderDungeon.description=Create a Recipe Builder for a dungeon recipe, with only the basic values. Teleports the player to a custom dimension with a dungeon when completed.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderSummon.title=Summon Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderSummon.description=Create a Recipe Builder for a summon recipe, with the basic values and an entity. Spawns that entity when completed.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderTime.title=Time Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderTime.description=Create a Recipe Builder for a time recipe, with the basic values and a time integer. Rapidly changes the time of day to the set time when completed.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderWeather.title=Weather Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderWeather.description=Create a Recipe Builder for a weather recipe, with the basic values and a weather value. Changes the weather type to the given value when completed.
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderCustom.title=Custom Recipe Builder
+groovyscript.wiki.arcaneworld.ritual.recipeBuilderCustom.description=Create a Recipe Builder for a custom recipe, with the basic values and a closure. Runs the closure when completed.
groovyscript.wiki.arcaneworld.ritual.time.value=Sets the amount of time that is passed when the Time Ritual is activated
groovyscript.wiki.arcaneworld.ritual.entity.value=Sets the entity spawned when the Arena or Summon Rituals are activated
groovyscript.wiki.arcaneworld.ritual.command.value=Sets the commands that will be run when the Command Ritual is activated
@@ -366,6 +389,12 @@ groovyscript.wiki.astralsorcery.chalice_interaction.probabilities.value=Sets the
groovyscript.wiki.astralsorcery.constellation.title=Constellation
groovyscript.wiki.astralsorcery.constellation.description=Create a custom Constellation.
groovyscript.wiki.astralsorcery.constellation.addSignatureItem=Adds to the constellations signature items, which control the Constellation Paper and Mantle of Stars recipes. Only the first 4 will be used.
+groovyscript.wiki.astralsorcery.constellation.constellationBuilder.title=Constellation Builder
+groovyscript.wiki.astralsorcery.constellation.constellationBuilder.description=Create a builder to create new custom Constellations
+groovyscript.wiki.astralsorcery.constellation.constellationMapEffectBuilder.title=ConstellationMapEffect Builder
+groovyscript.wiki.astralsorcery.constellation.constellationMapEffectBuilder.description=Create a builder to control the Potion Effects and Enchantments the Constellation can create
+groovyscript.wiki.astralsorcery.constellation.signatureItems.title=Signature Items Builder
+groovyscript.wiki.astralsorcery.constellation.signatureItems.description=Create a builder to control the Signature Items used for the Constellation Paper and Mantle of Stars recipes
groovyscript.wiki.astralsorcery.constellation.color.value=Sets the color of the Constellation
groovyscript.wiki.astralsorcery.constellation.name.value=Sets the name of the Constellation
groovyscript.wiki.astralsorcery.constellation.type.value=Sets the type of Constellation
@@ -386,14 +415,14 @@ groovyscript.wiki.astralsorcery.constellation.removeAll=Removes all Constellatio
groovyscript.wiki.astralsorcery.fountain.title=Fountain
groovyscript.wiki.astralsorcery.fountain.description=Adds virtual aquifers that can be accessed via the Evershifting Fountain's Necromantic Prime.
-groovyscript.wiki.astralsorcery.fountain.add0=Adds recipes in the format `fluid`, `rarity`, `guaranteedAmt`, `addRand`
-groovyscript.wiki.astralsorcery.fountain.add1=Adds recipes in the format `fluid`, `rarity`, `guaranteedAmt`, `addRand`
+groovyscript.wiki.astralsorcery.fountain.add=Adds recipes in the format `fluid`, `rarity`, `guaranteedAmt`, `addRand`
+groovyscript.wiki.astralsorcery.fountain.chanceHelper.title=Chance Helper
+groovyscript.wiki.astralsorcery.fountain.chanceHelper.description=Create a Builder for fluids obtainable from the Necromantic Prime
groovyscript.wiki.astralsorcery.fountain.variance.value=Sets the maximum amount of additional fluid that can be generated in a chunk
groovyscript.wiki.astralsorcery.fountain.minimumAmount.value=Sets the minimum amount of fluid in a chunk
groovyscript.wiki.astralsorcery.fountain.fluid.value=Sets the fluid being generated
groovyscript.wiki.astralsorcery.fountain.rarity.value=Sets the frequency the fluid generates in a chunk
-groovyscript.wiki.astralsorcery.fountain.remove0=Removes an entry matching the given `FluidStack`
-groovyscript.wiki.astralsorcery.fountain.remove1=Removes an entry matching the given `Fluid`
+groovyscript.wiki.astralsorcery.fountain.remove=Removes an entry matching the given `fluid`
groovyscript.wiki.astralsorcery.grindstone.title=Grindstone
groovyscript.wiki.astralsorcery.grindstone.description=Converts an item into an itemstack with a chance of getting twice the amount after right clicking the grindstone based on weight.
@@ -454,6 +483,8 @@ groovyscript.wiki.astralsorcery.research.description=Add custom Research Pages t
groovyscript.wiki.astralsorcery.research.addNode=Adds a new node to the given category in the format `category`, `node`
groovyscript.wiki.astralsorcery.research.connectNodes=Adds a connection between two nodes
groovyscript.wiki.astralsorcery.research.moveNode=Moves the node with the given name to the x and y co-ords specified in the format `name`, `x`, `z`
+groovyscript.wiki.astralsorcery.research.researchBuilder.title=Research Builder
+groovyscript.wiki.astralsorcery.research.researchBuilder.description=Create a builder to create research pages
groovyscript.wiki.astralsorcery.research.node.value=Sets the itemstack representing the node in the category
groovyscript.wiki.astralsorcery.research.pages.value=Sets the pages visible within the node
groovyscript.wiki.astralsorcery.research.name.value=Sets the unlocalized name of the node
@@ -466,6 +497,14 @@ groovyscript.wiki.astralsorcery.research.getNode=Returns the node with the given
groovyscript.wiki.astralsorcery.starlight_altar.title=Starlight Altar
groovyscript.wiki.astralsorcery.starlight_altar.description=Allows creation of shaped recipes in the Astral Sorcery Crafting Altar chain.
+groovyscript.wiki.astralsorcery.starlight_altar.discoveryRecipeBuilder.title=Discovery Altar Recipe Builder
+groovyscript.wiki.astralsorcery.starlight_altar.discoveryRecipeBuilder.description=Create a Recipe Builder for Astral Sorcery Crafting recipes for the Discovery (1st) tier of the Starlight Altar
+groovyscript.wiki.astralsorcery.starlight_altar.attunementRecipeBuilder.title=Attunement Altar Recipe Builder
+groovyscript.wiki.astralsorcery.starlight_altar.attunementRecipeBuilder.description=Create a Recipe Builder for Astral Sorcery Crafting recipes for the Attunement (2nd) tier of the Starlight Altar
+groovyscript.wiki.astralsorcery.starlight_altar.constellationRecipeBuilder.title=Constellation Altar Recipe Builder
+groovyscript.wiki.astralsorcery.starlight_altar.constellationRecipeBuilder.description=Create a Recipe Builder for Astral Sorcery Crafting recipes for the Constellation (3rd) tier of the Starlight Altar
+groovyscript.wiki.astralsorcery.starlight_altar.traitRecipeBuilder.title=Trait Altar Recipe Builder
+groovyscript.wiki.astralsorcery.starlight_altar.traitRecipeBuilder.description=Create a Recipe Builder for Astral Sorcery Crafting recipes for the Trait tier (4th) of the Starlight Altar
groovyscript.wiki.astralsorcery.starlight_altar.craftingTickTime.value=Sets how long the craft will take to complete in ticks
groovyscript.wiki.astralsorcery.starlight_altar.requiredConstellation.value=Sets the required Constellation for the Rock Crystal to be attuned to. Only applies to Iridescent Altars
groovyscript.wiki.astralsorcery.starlight_altar.name.value=Sets the name of the recipe, should be unique
@@ -494,6 +533,10 @@ groovyscript.wiki.avaritia.extreme_crafting.title=Extreme Crafting
groovyscript.wiki.avaritia.extreme_crafting.description=A normal crafting table, by 9x9 instead.
groovyscript.wiki.avaritia.extreme_crafting.addShaped=Adds a shaped crafting recipe in the format `output`, `input`
groovyscript.wiki.avaritia.extreme_crafting.addShapeless=Adds a shapeless crafting recipe in the format `output`, `input`
+groovyscript.wiki.avaritia.extreme_crafting.shapedBuilder.title=Shaped Extreme Crafting Recipe Builder
+groovyscript.wiki.avaritia.extreme_crafting.shapedBuilder.description=Create a Recipe Builder for Shaped Extreme Crafting recipes
+groovyscript.wiki.avaritia.extreme_crafting.shapelessBuilder.title=Shapeless Extreme Crafting Recipe Builder
+groovyscript.wiki.avaritia.extreme_crafting.shapelessBuilder.description=Create a Recipe Builder for Shapeless Extreme Crafting recipes
# Atum 2
@@ -521,6 +564,10 @@ groovyscript.wiki.betterwithaddons.fire_net.note0=Because the Fire Net needs Lav
groovyscript.wiki.betterwithaddons.infuser.title=Ancestral Infusion Crafting
groovyscript.wiki.betterwithaddons.infuser.description=Converts a custom crafting recipe an output itemstack, consuming Spirits from the Infused Soul Sand placed below the Ancestral Infuser if placed within the appropriate multiblock. The multiblock is either Soul Sand or Infused Soul Sand placed below the Ancestral Infuser and exclusively air blocks adjacent to the Infuser and Soul Sand blocks.
groovyscript.wiki.betterwithaddons.infuser.spirits.value=Sets the amount of spirits consumed
+groovyscript.wiki.betterwithaddons.infuser.shapedBuilder.title=Shaped Infusion Recipe Builder
+groovyscript.wiki.betterwithaddons.infuser.shapedBuilder.description=Create a Recipe Builder for Shaped Infusion Crafting recipes
+groovyscript.wiki.betterwithaddons.infuser.shapelessBuilder.title=Shapeless Infusion Recipe Builder
+groovyscript.wiki.betterwithaddons.infuser.shapelessBuilder.description=Create a Recipe Builder for Shapeless Infusion Crafting recipes
groovyscript.wiki.betterwithaddons.lure_tree.title=Alicio Tree Foods
groovyscript.wiki.betterwithaddons.lure_tree.description=Converts an input item into an amount of food for the tree to gradually consume, eventually summoning a random creature nearby.
@@ -569,6 +616,10 @@ groovyscript.wiki.betterwithaddons.water_net.description=Converts an input item
# Better With Mods
groovyscript.wiki.betterwithmods.anvil_crafting.title=Anvil Crafting
groovyscript.wiki.betterwithmods.anvil_crafting.description=Similar to a normal crafting table, but 4x4 instead.
+groovyscript.wiki.betterwithmods.anvil_crafting.shapedBuilder.title=Shaped Anvil Recipe Builder
+groovyscript.wiki.betterwithmods.anvil_crafting.shapedBuilder.description=Create a Recipe Builder for Shaped Anvil Crafting recipes
+groovyscript.wiki.betterwithmods.anvil_crafting.shapelessBuilder.title=Shapeless Anvil Recipe Builder
+groovyscript.wiki.betterwithmods.anvil_crafting.shapelessBuilder.description=Create a Recipe Builder for Shapeless Anvil Crafting recipes
groovyscript.wiki.betterwithmods.cauldron.title=Cauldron
groovyscript.wiki.betterwithmods.cauldron.description=Converts a large number of items into other items, with the ability to require specific amounts of heat.
@@ -761,6 +812,8 @@ groovyscript.wiki.botania.apothecary.add=Adds recipes in the format `output`, `i
groovyscript.wiki.botania.brew.title=Brew Effect
groovyscript.wiki.botania.brew.description=Creates a custom brew, but not a recipe for the brew.
+groovyscript.wiki.botania.brew.brewBuilder.title=Brew Builder
+groovyscript.wiki.botania.brew.brewBuilder.description=Create a builder to create custom brews
groovyscript.wiki.botania.brew.canInfuseBloodPendant.value=Sets if the custom brew can be infused on a Tainted Blood Pendant, making it a persistent effect at the cost of mana
groovyscript.wiki.botania.brew.effects.value=Sets the potion effects, quantity, and duration of each when consuming the potion
groovyscript.wiki.botania.brew.cost.value=Sets the base mana cost to make the brew. The Tainted Blood Pendant and Incense Stick recipes will cost 10 times as much mana
@@ -789,6 +842,8 @@ groovyscript.wiki.botania.entry.title=Lexicon Entry
groovyscript.wiki.botania.entry.description=Entry creates a new entry in a given category.
groovyscript.wiki.botania.entry.setKnowledgeType=Sets the Knowledge type of the given entry in the format `entry`, `type`
groovyscript.wiki.botania.entry.add=Adds a new Lexica Botania entry to the given Category in the format `name`, `category`
+groovyscript.wiki.botania.entry.entryBuilder.title=Entry Builder
+groovyscript.wiki.botania.entry.entryBuilder.description=Create a builder for custom entries in Lexica Botania Pages
groovyscript.wiki.botania.entry.pages.value=Sets the Pages attached to the Entry
groovyscript.wiki.botania.entry.name.value=Sets the unlocalized name of the Entry
groovyscript.wiki.botania.entry.icon.value=Sets the default icon of the Entry
@@ -1158,6 +1213,10 @@ groovyscript.wiki.extendedcrafting.ender_crafting.addShaped1=Adds a shaped craft
groovyscript.wiki.extendedcrafting.ender_crafting.addShapeless0=Adds a shapeless crafting recipe in the format `output`, `input`
groovyscript.wiki.extendedcrafting.ender_crafting.addShapeless1=Adds a shapeless crafting recipe in the format `time`, `output`, `input`
groovyscript.wiki.extendedcrafting.ender_crafting.time.value=Sets the duration in seconds for the recipe, reduced by each Ender Accelerator
+groovyscript.wiki.extendedcrafting.ender_crafting.shapedBuilder.title=ShapedEnder Crafting Recipe Builder
+groovyscript.wiki.extendedcrafting.ender_crafting.shapedBuilder.description=Create a Recipe Builder for Shaped Ender Crafting Table recipes
+groovyscript.wiki.extendedcrafting.ender_crafting.shapelessBuilder.title=Shapeless Ender Crafting Recipe Builder
+groovyscript.wiki.extendedcrafting.ender_crafting.shapelessBuilder.description=Create a Recipe Builder for Shapeless Ender Crafting Table recipes
groovyscript.wiki.extendedcrafting.table_crafting.title=Table Crafting
groovyscript.wiki.extendedcrafting.table_crafting.description=A normal crafting recipe, but requiring either a specific tier, or at least a given tier, from 3x3 to 9x9.
@@ -1166,6 +1225,10 @@ groovyscript.wiki.extendedcrafting.table_crafting.addShaped1=Adds a shaped craft
groovyscript.wiki.extendedcrafting.table_crafting.addShapeless0=Adds a shapeless crafting recipe in the format `output`, `input`
groovyscript.wiki.extendedcrafting.table_crafting.addShapeless1=Adds a shapeless crafting recipe in the format `tier`, `output`, `input`
groovyscript.wiki.extendedcrafting.table_crafting.tier.value=Sets the tier of table required, with 0 indicating any table size that can fit the recipe
+groovyscript.wiki.extendedcrafting.table_crafting.shapedBuilder.title=Shaped Extreme Crafting Recipe Builder
+groovyscript.wiki.extendedcrafting.table_crafting.shapedBuilder.description=Create a Recipe Builder for Shaped Extreme Crafting Table recipes
+groovyscript.wiki.extendedcrafting.table_crafting.shapelessBuilder.title=Shapeless Extreme Crafting Recipe Builder
+groovyscript.wiki.extendedcrafting.table_crafting.shapelessBuilder.description=Create a Recipe Builder for Shapeless Extreme Crafting Table recipes
# Extra Botany
@@ -1529,6 +1592,22 @@ groovyscript.wiki.inspirations.anvil_smashing.removeByOutput=Removes all Anvil S
groovyscript.wiki.inspirations.cauldron.title=Cauldron
groovyscript.wiki.inspirations.cauldron.description=Converts up to 1 itemstack and up to 1 fluid into up to 1 itemstack or up to 1 fluid, with a boiling boolean and variable amount of fluid consumed or produced.
groovyscript.wiki.inspirations.cauldron.note=Cauldrons have a cap of either 3 or 4 levels, depending on the config.
+groovyscript.wiki.inspirations.cauldron.recipeBuilder.title=Recipe Builder
+groovyscript.wiki.inspirations.cauldron.recipeBuilder.description=Create a Recipe Builder for any type of recipe
+groovyscript.wiki.inspirations.cauldron.recipeBuilderStandard.title=Standard Recipe Builder
+groovyscript.wiki.inspirations.cauldron.recipeBuilderStandard.description=Create a Recipe Builder for a standard recipe, with an input itemstack, input fluidstack, output itemstack, level of fluid consumed, and sound
+groovyscript.wiki.inspirations.cauldron.recipeBuilderTransform.title=Transform Recipe Builder
+groovyscript.wiki.inspirations.cauldron.recipeBuilderTransform.description=Create a Recipe Builder for a transform recipe, with an input itemstack, input fluidstack, output fluidstack, and level of fluid consumed
+groovyscript.wiki.inspirations.cauldron.recipeBuilderMix.title=Mix Recipe Builder
+groovyscript.wiki.inspirations.cauldron.recipeBuilderMix.description=Create a Recipe Builder for a mix recipe, with an two input fluidstacks and an output itemstack
+groovyscript.wiki.inspirations.cauldron.recipeBuilderFill.title=Fill Recipe Builder
+groovyscript.wiki.inspirations.cauldron.recipeBuilderFill.description=Create a Recipe Builder for a fill recipe, with an input itemstack, input fluidstack, output itemstack and sound
+groovyscript.wiki.inspirations.cauldron.recipeBuilderBrewing.title=Brewing Recipe Builder
+groovyscript.wiki.inspirations.cauldron.recipeBuilderBrewing.description=Create a Recipe Builder for a brewing recipe, with an input itemstack, input potion, and output potion
+groovyscript.wiki.inspirations.cauldron.recipeBuilderPotion.title=Potion Recipe Builder
+groovyscript.wiki.inspirations.cauldron.recipeBuilderPotion.description=Create a Recipe Builder for a potion recipe, with an input itemstack, input potion, output itemstack, and level of fluid consumed
+groovyscript.wiki.inspirations.cauldron.recipeBuilderDye.title=Dye Recipe Builder
+groovyscript.wiki.inspirations.cauldron.recipeBuilderDye.description=Create a Recipe Builder for a dye recipe, with an input itemstack, output itemstack, level of fluid, and dye color
groovyscript.wiki.inspirations.cauldron.dye.value=Sets the dye color fluid required for the input
groovyscript.wiki.inspirations.cauldron.type.value=Sets what type of recipe is being processed
groovyscript.wiki.inspirations.cauldron.sound.value=Sets the sound played when the recipe is crafted
@@ -1574,6 +1653,8 @@ groovyscript.wiki.jei.category.description=Modify the Categories visible in JEI,
groovyscript.wiki.jei.category.note0=Hidden Categories will still take up load time, and recipes contained within can still be processed. This only prevents seeing Categories.
groovyscript.wiki.jei.category.note1=Use the command `/gs jeiCategories` to log the UIDs of all JEI Categories to the `groovy.log` file!
groovyscript.wiki.jei.category.annotation=Note that `classes.GenericRecipeCategory` must be defined elsewhere, and this example presumes certain fields and methods exist.
+groovyscript.wiki.jei.category.categoryBuilder.title=Category Builder
+groovyscript.wiki.jei.category.categoryBuilder.description=Create a builder for custom JEI categories
groovyscript.wiki.jei.category.id.value=Sets the ID of the Category, which must be unique among all other Categories
groovyscript.wiki.jei.category.wrapper.value=Sets the `IRecipeWrapper`s used by the Category to generate entries
groovyscript.wiki.jei.category.catalyst.value=Sets the catalyst ingredients of the Category, which must belong to a class that has ingredient handling in JEI
@@ -2152,7 +2233,9 @@ groovyscript.wiki.roots.pacifist.removeByEntity=Removes the Pacifist entry for t
groovyscript.wiki.roots.pacifist.removeByName=Removes the Pacifist entry with the given name
groovyscript.wiki.roots.predicates.title=Predicates
-groovyscript.wiki.roots.predicates.description=Predicates are used in Transmution and RunicShearBlock. They either match all blockstates of a block, or all blockstates that have the given properties that match the input blockstate.
+groovyscript.wiki.roots.predicates.description=Predicates are used in Transmutation and RunicShearBlock. They either match all blockstates of a block, or all blockstates that have the given properties that match the input blockstate.
+groovyscript.wiki.roots.predicates.stateBuilder.title=State Builder
+groovyscript.wiki.roots.predicates.stateBuilder.description=Create a builder for custom State Predicates for other Roots methods
groovyscript.wiki.roots.predicates.below.value=Sets if the predicate checks the block below for validation
groovyscript.wiki.roots.predicates.above.value=Sets if the predicate checks the block above for validation
groovyscript.wiki.roots.predicates.blockstate.value=Sets the IBlockState compared against
@@ -2194,6 +2277,9 @@ groovyscript.wiki.roots.spells.title=Spells
groovyscript.wiki.roots.spells.description=Controls the recipe for the given spell, the sound, all properties, the base cost, and each modifier's cost.
groovyscript.wiki.roots.spells.list.value=Sets a list of all cost types used to construct a complex Cost object
groovyscript.wiki.roots.spells.spell.value=Sets the spell being modified
+groovyscript.wiki.roots.spells.costBuilder.title=Cost Builder
+groovyscript.wiki.roots.spells.costBuilder.description=Create a builder to create the cost of spell modifiers
+groovyscript.wiki.roots.spells.recipeBuilder=Create a Recipe Builder for the spell dust
# TODO missing modifying spells
groovyscript.wiki.roots.summon_creature.title=Summon Creature
@@ -2352,6 +2438,10 @@ groovyscript.wiki.techreborn.rolling_machine.title=Rolling Machine
groovyscript.wiki.techreborn.rolling_machine.description=Converts a custom crafting recipe into an output itemstack.
groovyscript.wiki.techreborn.rolling_machine.addShaped=Adds a shaped crafting recipe in the format `output`, `input`
groovyscript.wiki.techreborn.rolling_machine.addShapeless=Adds a shapeless crafting recipe in the format `output`, `input`
+groovyscript.wiki.techreborn.rolling_machine.shapedBuilder.title=Shaped Rolling Machine Recipe Builder
+groovyscript.wiki.techreborn.rolling_machine.shapedBuilder.description=Create a Recipe Builder for Shaped Rolling Machine Crafting recipes
+groovyscript.wiki.techreborn.rolling_machine.shapelessBuilder.title=Shapeless Rolling Machine Recipe Builder
+groovyscript.wiki.techreborn.rolling_machine.shapelessBuilder.description=Create a Recipe Builder for Shapeless Rolling Machine Crafting recipes
groovyscript.wiki.techreborn.scrapbox.title=Scrapbox
groovyscript.wiki.techreborn.scrapbox.description=Converts a scrapbox into a random itemstack output, either via manual player interaction or via a machine with a given process time, consuming energy per tick.
@@ -2434,9 +2524,15 @@ groovyscript.wiki.thaumcraft.arcane_workbench.aspects.value=Sets the Aspect Crys
groovyscript.wiki.thaumcraft.arcane_workbench.aspects.required=that every Aspect can only be one of the main 6 (`aer`, `ignis`, `aqua`, `terra`, `ordo`, `perditio`), and to a maximum of 64 each
groovyscript.wiki.thaumcraft.arcane_workbench.researchKey.value=Sets the research required to craft the recipe
groovyscript.wiki.thaumcraft.arcane_workbench.remove=Removes the recipe with the matching name
+groovyscript.wiki.thaumcraft.arcane_workbench.shapedBuilder.title=Shaped Arcane Crafting Recipe Builder
+groovyscript.wiki.thaumcraft.arcane_workbench.shapedBuilder.description=Create a Recipe Builder for Shaped Arcane Crafting recipes
+groovyscript.wiki.thaumcraft.arcane_workbench.shapelessBuilder.title=Shapeless Arcane Crafting Recipe Builder
+groovyscript.wiki.thaumcraft.arcane_workbench.shapelessBuilder.description=Create a Recipe Builder for Shapeless Arcane Crafting recipes
groovyscript.wiki.thaumcraft.aspect.title=Aspect Creator
groovyscript.wiki.thaumcraft.aspect.description=Creates a custom Aspect.
+groovyscript.wiki.thaumcraft.aspect.aspectBuilder.title=Aspect Builder
+groovyscript.wiki.thaumcraft.aspect.aspectBuilder.description=Create a builder to create a custom aspect
groovyscript.wiki.thaumcraft.aspect.tag.value=Sets the name of the new Aspect
groovyscript.wiki.thaumcraft.aspect.tag.required=the name must be a unique string
groovyscript.wiki.thaumcraft.aspect.blend.value=Sets the blend value of the Aspect
@@ -2446,6 +2542,8 @@ groovyscript.wiki.thaumcraft.aspect.components.value=Sets the other Aspects that
groovyscript.wiki.thaumcraft.aspect_helper.title=Entity/Block Aspects
groovyscript.wiki.thaumcraft.aspect_helper.description=Controls what Aspects are attached to entities or items.
+groovyscript.wiki.thaumcraft.aspect_helper.aspectBuilder.title=Aspect Builder
+groovyscript.wiki.thaumcraft.aspect_helper.aspectBuilder.description=Create a helper to modify the provided entity or object with the given aspects. This is not a traditional builder.
groovyscript.wiki.thaumcraft.aspect_helper.target.required=either entity or object must be defined, but not both
groovyscript.wiki.thaumcraft.aspect_helper.entity.value=Sets the entity being modified
groovyscript.wiki.thaumcraft.aspect_helper.object.value=Sets the item being modified
@@ -2470,6 +2568,8 @@ groovyscript.wiki.thaumcraft.crucible.add=Adds recipes in the format `researchKe
groovyscript.wiki.thaumcraft.dust_trigger.title=Dust Trigger
groovyscript.wiki.thaumcraft.dust_trigger.description=Converts a block in-world into an item, when interacting with it with Salis Mundus, potentially requiring a specific research to be completed.
+groovyscript.wiki.thaumcraft.dust_trigger.triggerBuilder.title=Dust Trigger Builder
+groovyscript.wiki.thaumcraft.dust_trigger.triggerBuilder.description=Create a builder to make a Salis Mundus conversion recipe
groovyscript.wiki.thaumcraft.dust_trigger.target.required=either ore or target must be defined, but not both
groovyscript.wiki.thaumcraft.dust_trigger.ore.value=Sets the input as an ore
groovyscript.wiki.thaumcraft.dust_trigger.output.value=Sets the output item, which will be dropped on the ground
@@ -2493,6 +2593,8 @@ groovyscript.wiki.thaumcraft.loot_bag.removeAll=Removes all items from the targe
groovyscript.wiki.thaumcraft.research.title=Research
groovyscript.wiki.thaumcraft.research.description=Create or modify existing research entries, which contain helpful information and unlock recipes, and can be gated behind specific items or events.
+groovyscript.wiki.thaumcraft.research.researchCategoryBuilder.title=Research Category Builder
+groovyscript.wiki.thaumcraft.research.researchCategoryBuilder.description=Create a builder to make a custom research category
groovyscript.wiki.thaumcraft.research.key.value=Sets a unique research key
groovyscript.wiki.thaumcraft.research.icon.value=Sets the icon to be used for the research category tab
groovyscript.wiki.thaumcraft.research.formula.value=Sets the aspects required to gain knowledge in this category