Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions api/src/main/java/dev/jsinco/brewery/api/brew/BrewManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import dev.jsinco.brewery.api.breweries.CauldronType;
import dev.jsinco.brewery.api.ingredient.Ingredient;
import dev.jsinco.brewery.api.meta.MetaData;
import dev.jsinco.brewery.api.recipe.RecipeMatcher;

import java.util.List;
import java.util.Map;
Expand All @@ -17,6 +18,11 @@ public interface BrewManager<I> {
*/
Brew createBrew(List<BrewingStep> steps);

/**
* @param steps Steps of the brewing process
* @param meta Extra meta data
* @return A new brew with specified steps and meta
*/
Brew createBrew(List<BrewingStep> steps, MetaData meta);

/**
Expand Down Expand Up @@ -72,4 +78,9 @@ public interface BrewManager<I> {
* @return A new distill step
*/
BrewingStep.Distill distillStep(int runs);

/**
* @return A recipe matcher builder
*/
RecipeMatcher.Builder<I> matcher();
}
23 changes: 23 additions & 0 deletions api/src/main/java/dev/jsinco/brewery/api/brew/BrewQuality.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import org.jspecify.annotations.Nullable;

import java.util.Optional;

public enum BrewQuality {
BAD(0xFF0000),
GOOD(0xFFA500),
Expand All @@ -14,6 +16,10 @@ public enum BrewQuality {
this.color = color;
}

/**
* @param overrideQuality The quality of the score, null is failed
* @return the maximum score for each quality
*/
public static double maxScore(@Nullable BrewQuality overrideQuality) {
return switch (overrideQuality) {
case BAD -> 0.6D - Math.ulp(0.6D);
Expand All @@ -23,6 +29,23 @@ public static double maxScore(@Nullable BrewQuality overrideQuality) {
};
}

/**
* @param score A brew score between 0-1
* @return The quality of the score, or empty if score is failed
*/
public static Optional<BrewQuality> quality(double score) {
if (score >= 0.8) {
return Optional.of(BrewQuality.EXCELLENT);
}
if (score >= 0.6) {
return Optional.of(BrewQuality.GOOD);
}
if (score > 0) {
return Optional.of(BrewQuality.BAD);
}
return Optional.empty();
}

/**
* @return An integer with RGB color representing this quality
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
*
* @param <I> Item stack
*/
@Deprecated(forRemoval = true)
public interface IngredientManager<I> {

Pattern INGREDIENT_META_DATA_RE = Pattern.compile("\\{(.*)\\}");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package dev.jsinco.brewery.api.ingredient;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import dev.jsinco.brewery.api.util.BreweryKey;
import dev.jsinco.brewery.api.util.BreweryRegistry;
import dev.jsinco.brewery.api.util.Pair;
import dev.jsinco.brewery.api.util.StringUtil;
import org.jspecify.annotations.NonNull;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* Used to avoid completable future hell
*
* @param <I> The item stack type
*/
public interface ResolvedIngredientManager<I> {
Pattern INGREDIENT_META_DATA_RE = Pattern.compile("\\{(.*)\\}");
Pattern INGREDIENT_META_DATA_KEY_RE = Pattern.compile("[^,{}]+");

/**
* @param itemStack An item stack
* @return An ingredient of the item stack
*/
Ingredient getIngredient(@NonNull I itemStack);

/**
* @param ingredient An ingredient
* @return An item stack representation of that ingredient
*/
Optional<I> toItem(Ingredient ingredient);

/**
* @param ingredientStr A string representing the ingredient
* @return An optionally present ingredient
*/
Optional<Ingredient> getIngredient(@NonNull String ingredientStr);

/**
* Deserialize the ingredient with meta data. Meta data is within curly brackets
*
* @param serializedIngredient Serialized form of the ingredient
* @return An optionally present ingredient
* @throws IllegalArgumentException if the ingredient meta in the string was invalid
*/
default Optional<Ingredient> deserializeIngredient(@NonNull String serializedIngredient) throws IllegalArgumentException {
Matcher matcher = INGREDIENT_META_DATA_RE.matcher(serializedIngredient);
if (!matcher.find()) {
return getIngredient(serializedIngredient);
}
String meta = matcher.group(1);
String id = matcher.replaceAll("");
if (meta.isBlank()) {
return getIngredient(id);
}
ImmutableMap.Builder<IngredientMeta<?>, Object> metaBuilder = new ImmutableMap.Builder<>();
StringUtil.complexSplit(meta)
.forEach(metaElement -> addMeta(metaElement, metaBuilder));
return getIngredient(id)
.map(ingredient -> new IngredientWithMeta(ingredient, metaBuilder.build()));
}

private void addMeta(String metaElement, ImmutableMap.Builder<IngredientMeta<?>, Object> metaBuilder) {
String[] split = metaElement.split("=", 2);
Preconditions.checkArgument(split.length == 2, "Invalid ingredient meta pattern, missing '=' sign: " + metaElement);
String key = split[0].strip();
Preconditions.checkArgument(INGREDIENT_META_DATA_KEY_RE.matcher(key).matches(), "Invalid ingredient meta key pattern, disallowed symbol: " + key);
String value = split[1].strip();

IngredientMeta<?> ingredientMeta = BreweryRegistry.INGREDIENT_META.get(BreweryKey.parse(key));
Preconditions.checkArgument(ingredientMeta != null, "Invalid ingredient meta, unknown key: " + key);
Object deserialized = ingredientMeta.serializer().deserialize(value);
metaBuilder.put(ingredientMeta, deserialized);
}

/**
* Serialize the ingredient with meta data. Meta data is within curly brackets
*
* @param ingredient Ingredient to serialize
* @return Ingredient in serialized form
* @throws IllegalArgumentException If the ingredient contains invalid meta data
*/
default String serializeIngredient(Ingredient ingredient) throws IllegalArgumentException {
if (!(ingredient instanceof IngredientWithMeta metaIngredient)) {
return ingredient.key().toString();
}
Map<IngredientMeta<?>, Object> meta = metaIngredient.meta();
return String.format("%s{%s}", metaIngredient.key(),
meta.entrySet()
.stream()
.map(entry -> entry.getKey().key().minimalized() + "=" + entry.getKey().serializer().serialize(entry.getValue()))
.collect(Collectors.joining(","))
);
}

/**
* @param ingredientStr A string with the format [ingredient-name]/[runs]. Allows not specifying runs, where it will default to 1
* @return An ingredient/runs pair
* @throws IllegalArgumentException if the ingredients string is invalid
*/
Pair<Ingredient, Integer> getIngredientWithAmount(String ingredientStr) throws IllegalArgumentException;

/**
*
* @param ingredientStr A string with the format [ingredient-name]/[runs]. Allows not specifying runs, where it will default to 1
* @param allowMeta Whether meta should be allowed
* @return An ingredient/runs pair
* @throws IllegalArgumentException if the ingredients string is invalid
*/
Pair<Ingredient, Integer> getIngredientWithAmount(String ingredientStr, boolean allowMeta) throws IllegalArgumentException;

/**
* Parse a list of strings into a map of ingredients with runs
*
* @param stringList A list of strings with valid formatting, see {@link #getIngredientWithAmount(String)}
* @return A map representing ingredients with runs
* @throws IllegalArgumentException if there's any invalid ingredient string
*/
Map<Ingredient, Integer> getIngredientsWithAmount(List<String> stringList) throws IllegalArgumentException;

/**
* Utility method, merge ingredients amount of both maps
*
* @param mutableIngredientsMap A map of ingredients with amount
* @param ingredients A map of ingredients with amount
*/
static void merge(Map<Ingredient, Integer> mutableIngredientsMap, Map<Ingredient, Integer> ingredients) {
for (Map.Entry<Ingredient, Integer> ingredient : ingredients.entrySet()) {
insertIngredientIntoMap(mutableIngredientsMap, new Pair<>(ingredient.getKey(), ingredient.getValue()));
}
}

/**
* Utility method, insert ingredient into a map of ingredients with amount
*
* @param mutableIngredientsMap Ingredients map with amounts
* @param ingredient A pair with ingredient and amounts
*/
static void insertIngredientIntoMap(Map<Ingredient, Integer> mutableIngredientsMap, Pair<Ingredient, Integer> ingredient) {
int amount = mutableIngredientsMap.computeIfAbsent(ingredient.first(), ignored -> 0);
mutableIngredientsMap.put(ingredient.first(), amount + ingredient.second());
}

/**
* Parse a list of strings into a map of ingredients with runs
*
* @param stringList A list of strings with valid formatting, see {@link #getIngredientWithAmount(String)}
* @param withMeta True if meta parsing is allowed
* @return A map representing ingredients with runs
* @throws IllegalArgumentException if there's any invalid ingredient string
*/
Map<Ingredient, Integer> getIngredientsWithAmount(List<String> stringList, boolean withMeta) throws
IllegalArgumentException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

public interface RecipeMatcher<I> {

/**
* Match against a brew.
*
* @param brew A brew to match against
* @return The result of the match
*/
RecipeMatcherResult<I> match(Brew brew);


Expand Down
29 changes: 28 additions & 1 deletion api/src/main/java/dev/jsinco/brewery/api/util/CancelState.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,46 @@

public sealed interface CancelState {

/**
* Send a message to the audience
*
* @param audience The audience
*/
void sendMessage(@Nullable Audience audience);

/**
* The action should cancel silently
*/
record Cancelled() implements CancelState {
@Override
public void sendMessage(@Nullable Audience audience) {
// NO-OP
}
}

/**
* The action should cancel with a message
*
* @param message Cancel message
*/
record PermissionDenied(Component message) implements CancelState {

@Override
public void sendMessage(@Nullable Audience audience) {
if(audience == null) {
if (audience == null) {
return;
}
audience.sendMessage(message);
}
}

/**
* The action should continue silently
*/
record Allowed() implements CancelState {
@Override
public void sendMessage(@Nullable Audience audience) {
// NO-OP
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
import dev.jsinco.brewery.api.effect.DrunksManager;
import dev.jsinco.brewery.api.effect.modifier.ModifierManager;
import dev.jsinco.brewery.api.ingredient.IngredientManager;
import dev.jsinco.brewery.api.ingredient.ResolvedIngredientManager;
import dev.jsinco.brewery.api.integration.IntegrationManager;
import dev.jsinco.brewery.api.recipe.RecipeRegistry;
import dev.jsinco.brewery.api.structure.PlacedStructureRegistry;
import dev.jsinco.brewery.bukkit.api.effect.DrunkEventManager;
import org.bukkit.inventory.ItemStack;

import java.util.concurrent.CompletableFuture;

public interface TheBrewingProjectApi {

/**
Expand Down Expand Up @@ -53,6 +56,11 @@ public interface TheBrewingProjectApi {
*/
IngredientManager<ItemStack> getIngredientManager();

/**
* @return An ingredient-item stack bridge future
*/
CompletableFuture<ResolvedIngredientManager<ItemStack>> getResolvedIngredientManager();

/**
* @return A manager for events
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package dev.jsinco.brewery.bukkit.api.event.structure;

import dev.jsinco.brewery.api.breweries.BarrelAccess;
import dev.jsinco.brewery.api.util.CancelState;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.Nullable;

public class BarrelCreateEvent extends BreweryCreateEvent {

private static final HandlerList HANDLERS = new HandlerList();

private final BarrelAccess barrel;

public BarrelCreateEvent(CancelState state, @Nullable Player player, Location location, BarrelAccess barrel) {
super(state, player, location);
this.barrel = barrel;
}

/**
* The barrel that was created.
*/
public BarrelAccess getBarrel() {
return this.barrel;
}

@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}

public static HandlerList getHandlerList() {
return HANDLERS;
}
}
Loading
Loading