Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the Comp annotation easier to use #236

Merged
merged 23 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9a84bf6
place key directly in enum
WaitingIdly Aug 31, 2024
ad64c89
convert comp
WaitingIdly Aug 31, 2024
f7ae70c
convert old format into new comp format
WaitingIdly Aug 31, 2024
f5e70f3
convert requirement into unique on comp
WaitingIdly Aug 31, 2024
b0ded96
join via serial comma
WaitingIdly Aug 31, 2024
e772060
rename method to parseComparisonRequirements
WaitingIdly Aug 31, 2024
b9031a1
convert unique to lang keys, improve quality
WaitingIdly Aug 31, 2024
ec63078
remove default values from comp
WaitingIdly Aug 31, 2024
2d84166
ensure text isnt empty before adding
WaitingIdly Aug 31, 2024
ef076c6
allow removing types and provide examples
WaitingIdly Aug 31, 2024
1037ce1
remove types in valid situations
WaitingIdly Aug 31, 2024
0d3f1a1
remove use of Integer.MAX_VALUE in comp
WaitingIdly Aug 31, 2024
d4ea987
adjust magmatic smeltery text
WaitingIdly Aug 31, 2024
f34999f
move used types to enum
WaitingIdly Aug 31, 2024
a07e797
increase javadocs for Comp
WaitingIdly Aug 31, 2024
d6229ae
remove unneeded types arrays
WaitingIdly Aug 31, 2024
3ce91e7
change default value to not be 0
WaitingIdly Aug 31, 2024
28a09e1
get first used type instead of just "first"
WaitingIdly Aug 31, 2024
9797bf5
Merge branch 'master' into improve-comp
WaitingIdly Aug 31, 2024
d86de2d
update new compat with new comp elements
WaitingIdly Sep 1, 2024
1322c31
Merge remote-tracking branch 'origin/master' into improve-comp
WaitingIdly Oct 2, 2024
85ac822
convert deprecated elements of recent pyrotech
WaitingIdly Oct 2, 2024
cbacbca
update examples file for prodigytech
WaitingIdly Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions examples/postInit/prodigytech.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ mods.prodigytech.explosion_furnace.recipeBuilder()
// Explosion Furnace Additives:
// Turn an item into an explosive or into a dampener when inserted into the Explosion Furnace.

// mods.prodigytech.explosion_furnace_additives.removeAllDampeners()
// mods.prodigytech.explosion_furnace_additives.removeAllExplosives()
mods.prodigytech.explosion_furnace_additives.removeDampener(ore('dustAsh'))
mods.prodigytech.explosion_furnace_additives.removeExplosive(ore('gunpowder'))
// mods.prodigytech.explosion_furnace_additives.removeAllDampeners()
// mods.prodigytech.explosion_furnace_additives.removeAllExplosives()

mods.prodigytech.explosion_furnace_additives.addDampener(item('minecraft:stone'), 50)
mods.prodigytech.explosion_furnace_additives.addExplosive(item('minecraft:cobblestone'), 50)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,102 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.EnumSet;

/**
* Used by {@link Property Properties} to determine what are valid values for the {@link Property}.
* Frequently used in an array containing two entries, indicating minimum and maximum bounds.
* Used for comparisons by {@link Property Properties} to determine what are valid values for the {@link Property}.
* <p>
* Fully written out, it uses the array {@link #types()} to store the types being tracked,
* and the corresponding element to store what the value being compared against is.
* <p>
* However, to improve the ease of use, some information can be assumed by default and are thus optional.
* <p>
* If {@link #types()} is empty, elements that do not match the default value will be checked.
* This means that in most cases {@link #types()} does not need to be declared.
* <br>
* The only exception is if any of {@link #gt()}, {@link #gte()}, {@link #eq()}, {@link #lte()}, {@link #lt()},
* {@link #not()}, or {@link #unique()} elements match the default value,
* which is {@link Integer#MIN_VALUE} for the {@link #gt()}, {@link #gte()}, {@link #eq()}, {@link #lte()}, and {@link #lt()} elements and
* an empty string ({@code ""}) for both {@link #not()} and {@link #unique()} elements.
* In this situation, {@link #types()} will need to contain all relevant {@link Type Types}.
*
* @see Property#valid()
* @see Property#comp()
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ /* No targets allowed */})
public @interface Comp {

/**
* @return the method of comparison
* @deprecated use {@link #types()} instead
*/
@Deprecated
Type type() default Type.EQ;

/**
* @return the value that {@link #type()} compares with
* @deprecated use {@link #lt()}, {@link #lte()}, {@link #gte()}, {@link #gt()}, {@link #eq()}, {@link #not()}, or {@link #unique()} instead
*/
String value();
@Deprecated
String value() default "";

/**
* @return an array of types to compare with. In most cases, this can be assumed.
*/
Type[] types() default {};

/**
* The value represent less than.
* Enabled either via being set to a non-default value, or by adding {@link Comp.Type#LT} to the {@link #types()} element.
*
* @return if enabled, the value used to represent less than
*/
int lt() default Integer.MIN_VALUE;

/**
* The value represent less than or equal to.
* Enabled either via being set to a non-default value, or by adding {@link Comp.Type#LTE} to the {@link #types()} element.
*
* @return if enabled, the value used to represent less than or equal to
*/
int lte() default Integer.MIN_VALUE;

/**
* The value represent greater than or equal to.
* Enabled either via being set to a non-default value, or by adding {@link Comp.Type#GTE} to the {@link #types()} element.
*
* @return if enabled, the value used to represent greater than or equal to
*/
int gte() default Integer.MIN_VALUE;

/**
* The value represent greater than.
* Enabled either via being set to a non-default value, or by adding {@link Comp.Type#GT} to the {@link #types()} element.
*
* @return if enabled, the value used to represent greater than
*/
int gt() default Integer.MIN_VALUE;

/**
* The value represent equal to.
* Enabled either via being set to a non-default value, or by adding {@link Comp.Type#EQ} to the {@link #types()} element.
*
* @return if enabled, the value used to represent equal to
*/
int eq() default Integer.MIN_VALUE;

/**
* The value represent not equal to.
* Enabled either via being set to a non-default value, or by adding {@link Comp.Type#NOT} to the {@link #types()} element.
*
* @return if enabled, the value used to represent not equal to
*/
String not() default "";

/**
* @return if {@link #types()} contains {@link Comp.Type#UNI}, the lang key used to represent the unique description
*/
String unique() default "";

/**
* Used to determine the type of comparison. Contains a symbol representation and a localization key.
Expand Down Expand Up @@ -63,24 +139,49 @@
* <th>!=</th>
* <th>groovyscript.wiki.not</th>
* </tr>
* <tr>
* <th>UNI</th>
* <th>!?</th>
* <th>groovyscript.wiki.unique</th>
* </tr>
* </table>
*/
enum Type {
GT(">", "greater_than"),
GTE(">=", "greater_than_or_equal_to"),
EQ("==", "equal_to"),
LTE("<=", "less_than_or_equal_to"),
LT("<", "less_than"),
NOT("!=", "not");

private static final String baseLocalizationPath = "groovyscript.wiki.";
GT(">", "groovyscript.wiki.greater_than"),
GTE(">=", "groovyscript.wiki.greater_than_or_equal_to"),
EQ("==", "groovyscript.wiki.equal_to"),
LTE("<=", "groovyscript.wiki.less_than_or_equal_to"),
LT("<", "groovyscript.wiki.less_than"),
NOT("!=", "groovyscript.wiki.not"),
UNI("!?", "groovyscript.wiki.unique");

private final String symbol;
private final String key;

Type(String symbol, String key) {
this.symbol = symbol;
this.key = baseLocalizationPath + key;
this.key = key;
}

/**
* Creates an EnumSet based on the given {@link Comp}.
* If {@link Comp#types()} has any elements, the types contained will be used.
* Otherwise, any non-default values for the individual elements will be used.
*
* @param comp the {@link Comp} instance to be parsed
* @return a set containing the types that are used in the Comp
*/
public static EnumSet<Type> getUsedTypes(Comp comp) {
if (comp.types().length > 0) return EnumSet.of(comp.types()[0], comp.types());
var usedTypes = EnumSet.noneOf(Comp.Type.class);
if (comp.gt() != Integer.MIN_VALUE) usedTypes.add(Comp.Type.GT);
if (comp.gte() != Integer.MIN_VALUE) usedTypes.add(Comp.Type.GTE);
if (comp.eq() != Integer.MIN_VALUE) usedTypes.add(Comp.Type.EQ);
if (comp.lte() != Integer.MIN_VALUE) usedTypes.add(Comp.Type.LTE);
if (comp.lt() != Integer.MIN_VALUE) usedTypes.add(Comp.Type.LT);
if (!comp.not().isEmpty()) usedTypes.add(Comp.Type.NOT);
if (!comp.unique().isEmpty()) usedTypes.add(Comp.Type.UNI);
return usedTypes;
}

public String getSymbol() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
* </li>
* <li>{@link #property()} either contains nothing if {@link Property} was created attached to a field, or the relevant {@link Field#getName()} string.</li>
* <li>{@link #defaultValue()} a string containing the default value of the property. If empty, defaults to {@code null}.</li>
* <li>{@link #valid()} is an array of {@link Comp} that indicates the requirements of the {@link Property} to pass validation.</li>
* <li>{@link #requirement()} is a localization key that states the requirements for the property to pass validation provided the requirements are too
* complex to represent via {@link #valid()}.</li>
* <li>{@link #comp()} is a {@link Comp} that indicates the requirements of the {@link Property} to pass validation.</li>
* <li>{@link #ignoresInheritedMethods()} if this {@link Property} annotation requires any methods targeting the {@link Property} to not be inherited methods.</li>
* <li>{@link #needsOverride()} if this {@link Property} annotation needs another {@link Property} annotation with this element set to {@code true} to function.
* Used in wrapper classes, such as {@link com.cleanroommc.groovyscript.helper.recipe.AbstractRecipeBuilder AbstractRecipeBuilder}, where some or all of the fields may not be needed in subclasses.</li>
Expand Down Expand Up @@ -79,48 +77,107 @@
String defaultValue() default "";

/**
* The primary way to document properties, supplemented by {@link #requirement()}.
* @deprecated {@link #comp()}
*/
@Deprecated
Comp[] valid() default {};

/**
* The primary way to document properties.
* The three main ways this element is used is to refer to:
* <br>- a number: Would indicate comparing directly against the number.
* <br>- an array or list: Would indicate comparing against the length of the array/list.
* <br>- another object: Would use to indicate {@code not null} is required.
* <p>
* In almost all cases, the {@link Comp#types()} element can be assumed due to the values of the desired
* elements being set to a non-default value. For the int elements, the default value is {@link Integer#MIN_VALUE},
* and for the String elements, the default value is an empty string.
* <p>
* Here is a quick shortcut table to better understand what the logic is:
*
* <table>
* <tr>
* <th>validation</th>
* <th>code</th>
* <th>logic</th>
* </tr>
* <tr>
* <td><code>N/A</code></td>
* <td><code>@Comp</code></td>
* <td>no validation is applied</td>
* </tr>
* <tr>
* <td><code>x == 1</code></td>
* <td><code>valid = @Comp("1")</code></td>
* <td><code>@Comp({@link Comp#types types} = {@link Comp.Type#EQ EQ}, {@link Comp#eq eq} = 1)</code></td>
* <td>types checks eq, eq is set to 1</td>
* </tr>
* <tr>
* <td><code>x != 1</code></td>
* <td><code>valid = @Comp(value = "1", type = Comp.Type.NOT)</code></td>
* <td><code>x == 1</code></td>
* <td><code>@Comp({@link Comp#eq eq} = 1)</code></td>
* <td>^1</td>
* </tr>
* <tr>
* <td><code>x != null</code></td>
* <td><code>valid = @Comp(value = "null", type = Comp.Type.NOT)</code></td>
* <td><code>x > 0</code></td>
* <td><code>@Comp({@link Comp#types types} = {@link Comp.Type#GT GT}, {@link Comp#gt gt} = 0)</code></td>
* <td>types checks gt, gt is set to 0</td>
* </tr>
* <tr>
* <td><code>x > 0</code></td>
* <td><code>valid = @Comp(value = "0", type = Comp.Type.GT)</code></td>
* <td><code>@Comp({@link Comp#gt gt} = 0)</code></td>
* <td>^1</td>
* </tr>
* <tr>
* <td><code>x >= 0</code></td>
* <td><code>@Comp({@link Comp#types types} = {@link Comp.Type#GTE GTE}, {@link Comp#gte gte} = 0)</code></td>
* <td>types checks gte, gte is set to 0</td>
* </tr>
* <tr>
* <td><code>x != 1</code></td>
* <td><code>@Comp({@link Comp#types types} = {@link Comp.Type#NOT NOT}, {@link Comp#not not} = "1")</code></td>
* <td>types checks not, not is set to "1"</td>
* </tr>
* <tr>
* <td><code>x != null</code></td>
* <td><code>@Comp({@link Comp#not not} = "null")</code></td>
* <td>^1</td>
* </tr>
* <tr>
* <td><code>x >= 0 && x <= 5</code></td>
* <td><code>valid = {{@literal @}Comp(value = "0", type = Comp.Type.GTE), @Comp(value = "5", type = Comp.Type.LTE)}</code></td>
* <td><code>@Comp({@link Comp#types types} = {{@link Comp.Type#GTE GTE}, {@link Comp.Type#LTE LTE}}, {@link Comp#gte gte} = 0, {@link Comp#lte lte} = 5)</code></td>
* <td>types checks gte and lte, gte is set to 0 and lte is set to 5</td>
* </tr>
* <tr>
* <td><code>x > 0 && x <= 2</code></td>
* <td><code>@Comp({@link Comp#gt gt} = 0, {@link Comp#lte lte} = 2)</code></td>
* <td>^1</td>
* </tr>
* <tr>
* <td><code>complex logic</code></td>
* <td><code>@Comp({@link Comp#unique unique} = "complex logic")</code></td>
* <td>^1</td>
* </tr>
* <tr>
* <td><code>x >= 0 && complex logic</code></td>
* <td><code>@Comp({@link Comp#gte gte} = 0, {@link Comp#unique unique} = "complex logic")</code></td>
* <td>^1</td>
* </tr>
* <tr>
* <td><code>x >= 1 && x <= 9 && complex logic</code></td>
* <td><code>@Comp({@link Comp#gte gte} = 1, {@link Comp#lte lte} = 9, {@link Comp#unique unique} = "complex logic")</code></td>
* <td>^1</td>
* </tr>
* </table>
*
* @return an array of {@link Comp} entries indicating valid values for the property to be.
* ^1 = if types is empty, any non-default values are used
*
* @return a {@link Comp} indicating valid values for the property to be.
*/
Comp[] valid() default {};
Comp comp() default @Comp;

/**
* A localization key to declare validation requirements that are too complex to represent in {@link #valid()}.
*
* @return a string describing the valid value(s) for the field to be to pass validation
* @deprecated use {@link #comp()} instead, via {@code @Comp(types = Comp.Type.UNI, unique = "lang-key-here")}
*/
@Deprecated
String requirement() default "";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ public boolean removeByOutput(ItemStack output) {
});
}

@Property(property = "input", valid = @Comp("1"))
@Property(property = "output", valid = @Comp("1"))
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder<LensConversionRecipe> {

@Property(defaultValue = "1", valid = @Comp(type = Comp.Type.GT, value = "0"))
@Property(defaultValue = "1", comp = @Comp(gt = 0))
private int energyUse = 1;
@Property(defaultValue = "ActuallyAdditionsAPI.lensDefaultConversion", valid = @Comp(value = "null", type = Comp.Type.NOT))
@Property(defaultValue = "ActuallyAdditionsAPI.lensDefaultConversion", comp = @Comp(not = "null"))
private Lens type = ActuallyAdditionsAPI.lensDefaultConversion;

@RecipeBuilderMethodDescription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ public boolean removeByOutput(ItemStack output) {
});
}

@Property(property = "output", valid = @Comp("1"))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder<BallOfFurReturn> {

@Property(valid = @Comp(type = Comp.Type.GTE, value = "0"))
@Property(comp = @Comp(gte = 0))
private int weight;

@RecipeBuilderMethodDescription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ public boolean removeByOutput(ItemStack output) {
});
}

@Property(property = "input", valid = @Comp("1"))
@Property(property = "output", valid = @Comp("1"))
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(eq = 1))
public static class RecipeBuilder extends AbstractRecipeBuilder<CompostRecipe> {

@Property(property = "inputDisplay", valid = @Comp(type = Comp.Type.NOT, value = "null"))
@Property(property = "inputDisplay", comp = @Comp(not = "null"))
private IBlockState inputDisplay;
@Property(property = "outputDisplay", valid = @Comp(type = Comp.Type.NOT, value = "null"))
@Property(property = "outputDisplay", comp = @Comp(not = "null"))
private IBlockState outputDisplay;

@RecipeBuilderMethodDescription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ public boolean removeByOutput(ItemStack output) {
});
}

@Property(property = "input", valid = @Comp("1"))
@Property(property = "output", valid = {@Comp(type = Comp.Type.GTE, value = "1"), @Comp(type = Comp.Type.LTE, value = "2")})
@Property(property = "input", comp = @Comp(eq = 1))
@Property(property = "output", comp = @Comp(gte = 1, lte = 2))
public static class RecipeBuilder extends AbstractRecipeBuilder<CrusherRecipe> {

@Property(valid = {@Comp(type = Comp.Type.GTE, value = "0"), @Comp(type = Comp.Type.LTE, value = "100")})
@Property(comp = @Comp(gte = 0, lte = 100))
private int chance;

@RecipeBuilderMethodDescription
Expand Down
Loading