Skip to content

Commit c8d56c4

Browse files
committed
Implement custom crafting recipes
1 parent 344c8e3 commit c8d56c4

8 files changed

Lines changed: 161 additions & 6 deletions

File tree

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package io.github.kiber2009.plugin.contentapi;
22

3+
import io.github.kiber2009.plugin.contentapi.api.recipe.CustomCraftingRecipe;
4+
import io.github.kiber2009.plugin.contentapi.registry.recipe.RecipeGlobalRegistry;
35
import org.bukkit.event.EventHandler;
46
import org.bukkit.event.Listener;
57
import org.bukkit.event.inventory.PrepareItemCraftEvent;
68

79
final class RecipesManager implements Listener {
810
@EventHandler
911
private static void onPrepareItemCraft(final PrepareItemCraftEvent event) {
10-
// TODO
12+
if (event.isRepair())
13+
return;
14+
15+
final CustomCraftingRecipe recipe = RecipeGlobalRegistry.CRAFTING.get(event.getInventory().getMatrix());
16+
if (recipe != null)
17+
event.getInventory().setResult(recipe.getResult());
1118
}
1219
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.github.kiber2009.plugin.contentapi.api.recipe;
2+
3+
import org.bukkit.inventory.ItemStack;
4+
import org.jspecify.annotations.NonNull;
5+
import org.jspecify.annotations.Nullable;
6+
7+
import java.util.function.Predicate;
8+
9+
public interface CustomCraftingRecipe extends CustomRecipe, Predicate<@Nullable ItemStack @NonNull []> {}

src/main/java/io/github/kiber2009/plugin/contentapi/api/recipe/CustomRecipe.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22

33
import org.bukkit.inventory.ItemStack;
44
import org.jspecify.annotations.NonNull;
5-
import org.jspecify.annotations.Nullable;
65

76
public interface CustomRecipe {
87
@NonNull ItemStack getResult();
9-
10-
boolean match(final @Nullable ItemStack @NonNull [] matrix);
118
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package io.github.kiber2009.plugin.contentapi.api.recipe.crafting;
2+
3+
import io.github.kiber2009.plugin.contentapi.api.recipe.CustomCraftingRecipe;
4+
import org.bukkit.inventory.ItemStack;
5+
import org.jspecify.annotations.NonNull;
6+
import org.jspecify.annotations.Nullable;
7+
8+
import java.util.function.Predicate;
9+
10+
public class CustomShapedCraftingRecipe implements CustomCraftingRecipe {
11+
private static final byte[][] OFFSETS = {{0, 0}, {0, 1}, {1, 0}, {1, 1}};
12+
13+
private final ItemStack result;
14+
private final Predicate<ItemStack>[] matrix;
15+
16+
public CustomShapedCraftingRecipe(final @NonNull Predicate<@Nullable ItemStack> @NonNull [] matrix,
17+
final @NonNull ItemStack result) {
18+
if (matrix.length != 4 && matrix.length != 9)
19+
throw new IllegalArgumentException("Invalid matrix size");
20+
this.matrix = matrix;
21+
this.result = result;
22+
}
23+
24+
@Override
25+
public @NonNull ItemStack getResult() {
26+
return result.clone();
27+
}
28+
29+
@Override
30+
public boolean test(final @Nullable ItemStack @NonNull [] matrix) {
31+
if (matrix.length == 4 && this.matrix.length == 9)
32+
return false;
33+
34+
if (matrix.length == this.matrix.length) {
35+
for (int i = 0; i < matrix.length; i++)
36+
if (!this.matrix[i].test(matrix[i]))
37+
return false;
38+
return true;
39+
}
40+
41+
for (final byte[] off : OFFSETS) {
42+
boolean fits = true;
43+
44+
for (int i = 0; i < 2 && fits; i++)
45+
for (int j = 0; j < 2; j++)
46+
if (!this.matrix[(off[0] + i) * 3 + off[1] + j].test(matrix[i * 2 + j])) {
47+
fits = false;
48+
break;
49+
}
50+
51+
if (fits)
52+
return true;
53+
}
54+
return false;
55+
}
56+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package io.github.kiber2009.plugin.contentapi.api.recipe.crafting;
2+
3+
import io.github.kiber2009.plugin.contentapi.api.recipe.CustomCraftingRecipe;
4+
import org.bukkit.inventory.ItemStack;
5+
import org.jspecify.annotations.NonNull;
6+
import org.jspecify.annotations.Nullable;
7+
8+
import java.util.function.Predicate;
9+
10+
public class CustomShapelessCraftingRecipe implements CustomCraftingRecipe {
11+
private final ItemStack result;
12+
private final Predicate<ItemStack>[] ingredients;
13+
14+
@SafeVarargs
15+
public CustomShapelessCraftingRecipe(final @NonNull ItemStack result,
16+
final @NonNull Predicate<@NonNull ItemStack> @NonNull ... ingredients) {
17+
if (ingredients.length > 9)
18+
throw new IllegalArgumentException("Too many ingredients");
19+
this.result = result;
20+
this.ingredients = ingredients;
21+
}
22+
23+
@Override
24+
public @NonNull ItemStack getResult() {
25+
return result.clone();
26+
}
27+
28+
@Override
29+
public boolean test(final @Nullable ItemStack @NonNull [] matrix) {
30+
if (matrix.length < ingredients.length)
31+
return false;
32+
33+
final boolean[] used = new boolean[ingredients.length];
34+
int usedCount = 0;
35+
36+
for (final ItemStack elem : matrix) {
37+
if (elem == null)
38+
continue;
39+
40+
boolean found = false;
41+
for (int i = 0; i < ingredients.length; i++)
42+
if (!used[i] && ingredients[i].test(elem)) {
43+
used[i] = true;
44+
usedCount++;
45+
found = true;
46+
break;
47+
}
48+
49+
if (!found)
50+
return false;
51+
}
52+
53+
return usedCount == ingredients.length;
54+
}
55+
}

src/main/java/io/github/kiber2009/plugin/contentapi/registry/GlobalRegistry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
import java.util.Objects;
1212
import java.util.Set;
1313

14-
public sealed class GlobalRegistry<T> permits ItemGlobalRegistry {
14+
public class GlobalRegistry<T> {
1515
@SuppressWarnings("StaticInitializerReferencesSubClass")
1616
public static final ItemGlobalRegistry ITEMS = new ItemGlobalRegistry();
1717

18-
private final Map<NamespacedKey, T> map = new HashMap<>();
18+
protected final Map<NamespacedKey, T> map = new HashMap<>();
1919

2020
protected void registerItem(final @NonNull NamespacedKey key, final @NonNull T value) {
2121
if (map.containsKey(key))
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.github.kiber2009.plugin.contentapi.registry.recipe;
2+
3+
import io.github.kiber2009.plugin.contentapi.api.recipe.CustomCraftingRecipe;
4+
import org.bukkit.inventory.ItemStack;
5+
import org.jspecify.annotations.NonNull;
6+
import org.jspecify.annotations.Nullable;
7+
8+
public final class CraftingRecipeGlobalRegistry extends RecipeGlobalRegistry<CustomCraftingRecipe> {
9+
CraftingRecipeGlobalRegistry() {
10+
}
11+
12+
public @Nullable CustomCraftingRecipe get(final @Nullable ItemStack @NonNull [] matrix) {
13+
for (final CustomCraftingRecipe recipe : map.values())
14+
if (recipe.test(matrix))
15+
return recipe;
16+
return null;
17+
}
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.github.kiber2009.plugin.contentapi.registry.recipe;
2+
3+
import io.github.kiber2009.plugin.contentapi.api.recipe.CustomRecipe;
4+
import io.github.kiber2009.plugin.contentapi.registry.GlobalRegistry;
5+
6+
public sealed class RecipeGlobalRegistry<T extends CustomRecipe> extends GlobalRegistry<T>
7+
permits CraftingRecipeGlobalRegistry {
8+
@SuppressWarnings("StaticInitializerReferencesSubClass")
9+
public static final CraftingRecipeGlobalRegistry CRAFTING = new CraftingRecipeGlobalRegistry();
10+
11+
RecipeGlobalRegistry() {
12+
}
13+
}

0 commit comments

Comments
 (0)