Skip to content

Commit 97b37b9

Browse files
authored
Feat/player dynamic (#34)
* fix: ia hook (#23) * Feat/improve (#25) * Feat/improve (#27) * fix: ia hook (#23) * feat: improve * feat: remove some useless usage of variable * version 3.0.0 (#32) * Feat/improve (#25) * Feat/improve (#27) * fix: ia hook (#23) * feat: improve * feat: remove some useless usage of variable * Hotfix/air recipe (#30) * fix: ia hook (#23) * Feat/improve (#25) * Feat/improve (#27) * fix: ia hook (#23) * feat: improve * feat: remove some useless usage of variable * fix: air in recipe doesn't work * Feat/modernize (#31) * feat: modernize * feat: version * fix: shapeless craft * fix: set handler highest and add result manually * fix: remove useless properties * feat: java version * feat: improve jitpack * feat: add dynamic player when it's possible during a craft * fix: compilation error
1 parent 839b5e4 commit 97b37b9

File tree

9 files changed

+155
-72
lines changed

9 files changed

+155
-72
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package fr.traqueur.recipes.api;
2+
3+
import org.bukkit.Material;
4+
import org.bukkit.inventory.ItemStack;
5+
import org.bukkit.util.io.BukkitObjectInputStream;
6+
7+
import java.io.ByteArrayInputStream;
8+
import java.io.IOException;
9+
import java.io.ObjectInputStream;
10+
import java.util.Base64;
11+
import java.util.zip.GZIPInputStream;
12+
13+
public class Util {
14+
15+
/**
16+
* This method is used to get the itemstack from base64 string
17+
* @param base64itemstack the base64 item stack.
18+
* @return the item stack.
19+
*/
20+
public static ItemStack getItemStack(String base64itemstack) {
21+
try {
22+
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.getDecoder().decode(base64itemstack));
23+
GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
24+
ObjectInputStream objectInputStream = new BukkitObjectInputStream(gzipInputStream);
25+
Object deserialized = objectInputStream.readObject();
26+
objectInputStream.close();
27+
28+
if (!(deserialized instanceof ItemStack)) {
29+
throw new IllegalArgumentException("The deserialized object is not an ItemStack.");
30+
}
31+
32+
return (ItemStack) deserialized;
33+
} catch (IOException exception) {
34+
throw new IllegalArgumentException("The itemstack " + base64itemstack + " is not a valid base64 or corrupted: " + exception.getMessage());
35+
} catch (ClassNotFoundException exception) {
36+
throw new IllegalArgumentException("The itemstack " + base64itemstack + " contains an unknown class: " + exception.getMessage());
37+
} catch (IllegalArgumentException exception) {
38+
throw new IllegalArgumentException("The itemstack " + base64itemstack + " is not valid: " + exception.getMessage());
39+
}
40+
}
41+
42+
public static String fromItemStack(ItemStack itemStack) {
43+
try {
44+
java.io.ByteArrayOutputStream byteArrayOutputStream = new java.io.ByteArrayOutputStream();
45+
java.util.zip.GZIPOutputStream gzipOutputStream = new java.util.zip.GZIPOutputStream(byteArrayOutputStream);
46+
org.bukkit.util.io.BukkitObjectOutputStream bukkitObjectOutputStream = new org.bukkit.util.io.BukkitObjectOutputStream(gzipOutputStream);
47+
bukkitObjectOutputStream.writeObject(itemStack);
48+
bukkitObjectOutputStream.close();
49+
return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
50+
} catch (IOException e) {
51+
throw new IllegalArgumentException("The itemstack " + itemStack + " cannot be serialized: " + e.getMessage());
52+
}
53+
}
54+
55+
/**
56+
* This method is used to get the material from the string.
57+
* @param material the material string.
58+
* @return the material.
59+
*/
60+
public static Material getMaterial(String material) {
61+
try {
62+
return Material.valueOf(material.toUpperCase());
63+
} catch (IllegalArgumentException e) {
64+
throw new IllegalArgumentException("The material " + material + " isn't valid.");
65+
}
66+
}
67+
68+
}

src/main/java/fr/traqueur/recipes/api/domains/Recipe.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ default Recipe addIngredient(Material material, Character sign) {
211211
* @param experience The experience of the recipe.
212212
* @return The item recipe.
213213
*/
214-
default ItemRecipe getItemRecipe(List<Ingredient> ingredientList, RecipeType type, String[] pattern, int cookingTime, String name, String group, String category, ItemStack result, int amount, float experience) {
214+
default ItemRecipe getItemRecipe(List<Ingredient> ingredientList, RecipeType type, String[] pattern, int cookingTime, String name, String group, String category, String result, int amount, float experience) {
215215
if (ingredientList.isEmpty()) {
216216
throw new IllegalArgumentException("Ingredients are not set");
217217
}

src/main/java/fr/traqueur/recipes/api/hook/Hook.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import fr.traqueur.recipes.api.domains.Ingredient;
44
import fr.traqueur.recipes.impl.hook.Hooks;
55
import org.bukkit.Bukkit;
6+
import org.bukkit.entity.Player;
67
import org.bukkit.inventory.ItemStack;
78
import org.bukkit.plugin.java.JavaPlugin;
9+
import org.jetbrains.annotations.Nullable;
810

911
import java.util.ArrayList;
1012
import java.util.List;
@@ -52,7 +54,10 @@ default boolean isEnable() {
5254
/**
5355
* Get the ItemStack from a result part
5456
* @param resultPart The result part to get the ItemStack from
57+
* @param player The player (can be null) if needed for dynamic items generation
58+
* This method are called when a recipe is register so, player is null at this moment
59+
* but when crafting, player are provided to get the correct item (not in Furnace)
5560
* @return The ItemStack from the result part
5661
*/
57-
ItemStack getItemStack(String resultPart);
62+
ItemStack getItemStack(@Nullable Player player, String resultPart);
5863
}

src/main/java/fr/traqueur/recipes/impl/PrepareCraftListener.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
import fr.traqueur.recipes.api.domains.Ingredient;
66
import fr.traqueur.recipes.impl.domains.ItemRecipe;
77
import org.bukkit.Material;
8+
import org.bukkit.entity.Player;
89
import org.bukkit.event.EventHandler;
910
import org.bukkit.event.EventPriority;
1011
import org.bukkit.event.Listener;
1112
import org.bukkit.event.block.BlockCookEvent;
13+
import org.bukkit.event.inventory.FurnaceSmeltEvent;
1214
import org.bukkit.event.inventory.PrepareItemCraftEvent;
1315
import org.bukkit.event.inventory.PrepareSmithingEvent;
1416
import org.bukkit.inventory.*;
@@ -62,6 +64,7 @@ public void onSmelt(BlockCookEvent event) {
6264
if(event.isCancelled()) {
6365
return;
6466
}
67+
6568
ItemStack item = event.getSource();
6669
if (item == null || item.getType() == Material.AIR) return;
6770
ItemStack result = event.getResult();
@@ -81,6 +84,7 @@ public void onSmelt(BlockCookEvent event) {
8184
event.setCancelled(true);
8285
} else {
8386
this.api.debug("The smelting recipe %s is good.", itemRecipe.getKey());
87+
event.setResult(itemRecipe.toBukkitItemStack(null));
8488
}
8589
});
8690
}
@@ -131,6 +135,7 @@ && isSimilar(base, baseIngredient)
131135
return;
132136
}
133137
this.api.debug("The smithing recipe %s is good.", itemRecipe.getKey());
138+
event.setResult(itemRecipe.toBukkitItemStack((Player) event.getViewers().getFirst()));
134139
}
135140
}
136141

@@ -161,13 +166,13 @@ public void onPrepareCraft(PrepareItemCraftEvent event) {
161166
if(recipe instanceof ShapedRecipe shapedRecipe && itemRecipe.recipeType() == RecipeType.CRAFTING_SHAPED) {
162167
if (!shapedRecipe.getKey().equals(itemRecipe.getKey())) continue;
163168
this.api.debug("The recipe %s is a shaped recipe.", itemRecipe.getKey());
164-
this.checkGoodShapedRecipe(itemRecipe, event);
169+
this.checkGoodShapedRecipe((Player) event.getViewers().getFirst(), itemRecipe, event);
165170
}
166171

167172
if(recipe instanceof ShapelessRecipe shapelessRecipe && itemRecipe.recipeType() == RecipeType.CRAFTING_SHAPELESS) {
168173
if(!shapelessRecipe.getKey().equals(itemRecipe.getKey())) continue;
169174
this.api.debug("The recipe %s is a shapeless recipe.", itemRecipe.getKey());
170-
this.checkGoodShapelessRecipe(itemRecipe, event);
175+
this.checkGoodShapelessRecipe((Player) event.getViewers().getFirst(), itemRecipe, event);
171176
}
172177
}
173178
}
@@ -177,7 +182,7 @@ public void onPrepareCraft(PrepareItemCraftEvent event) {
177182
* @param itemRecipe the item recipe
178183
* @param event the event
179184
*/
180-
private void checkGoodShapedRecipe(ItemRecipe itemRecipe, PrepareItemCraftEvent event) {
185+
private void checkGoodShapedRecipe(Player player, ItemRecipe itemRecipe, PrepareItemCraftEvent event) {
181186
ItemStack[] matrix = event.getInventory().getMatrix();
182187
String[] pattern = Arrays.stream(itemRecipe.pattern()).map(s -> s.split("")).flatMap(Arrays::stream).toArray(String[]::new);
183188

@@ -214,15 +219,15 @@ private void checkGoodShapedRecipe(ItemRecipe itemRecipe, PrepareItemCraftEvent
214219
}
215220

216221
this.api.debug("The shaped recipe %s is good.", itemRecipe.getKey());
217-
event.getInventory().setResult(itemRecipe.result());
222+
event.getInventory().setResult(itemRecipe.toBukkitItemStack(player));
218223
}
219224

220225
/**
221226
* Check if the recipe is good for a shapeless recipe.
222227
* @param itemRecipe the item recipe
223228
* @param event the event
224229
*/
225-
private void checkGoodShapelessRecipe(ItemRecipe itemRecipe, PrepareItemCraftEvent event) {
230+
private void checkGoodShapelessRecipe(Player player, ItemRecipe itemRecipe, PrepareItemCraftEvent event) {
226231
List<ItemStack> matrix = new ArrayList<>(Arrays.stream(event.getInventory().getMatrix()).filter(Objects::nonNull).filter(it -> it.getType() != Material.AIR).toList());
227232
Ingredient[] itemIngredients = itemRecipe.ingredients();
228233

@@ -251,6 +256,6 @@ private void checkGoodShapelessRecipe(ItemRecipe itemRecipe, PrepareItemCraftEve
251256
}
252257

253258
this.api.debug("The shapeless recipe %s is good.", itemRecipe.getKey());
254-
event.getInventory().setResult(itemRecipe.result());
259+
event.getInventory().setResult(itemRecipe.toBukkitItemStack(player));
255260
}
256261
}

src/main/java/fr/traqueur/recipes/impl/domains/ItemRecipe.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
package fr.traqueur.recipes.impl.domains;
22

33
import fr.traqueur.recipes.api.RecipeType;
4+
import fr.traqueur.recipes.api.Util;
45
import fr.traqueur.recipes.api.domains.Ingredient;
6+
import fr.traqueur.recipes.api.hook.Hook;
7+
import org.bukkit.Material;
58
import org.bukkit.NamespacedKey;
9+
import org.bukkit.entity.Player;
610
import org.bukkit.inventory.*;
711
import org.bukkit.inventory.recipe.CookingBookCategory;
812
import org.bukkit.inventory.recipe.CraftingBookCategory;
13+
import org.bukkit.util.io.BukkitObjectInputStream;
14+
15+
import java.io.ByteArrayInputStream;
16+
import java.io.IOException;
17+
import java.io.ObjectInputStream;
18+
import java.util.Base64;
19+
import java.util.zip.GZIPInputStream;
920

1021
/**
1122
* This class represents a recipe for an item
@@ -20,7 +31,7 @@
2031
* @param cookingTime The cooking time of the recipe
2132
* @param experience The experience of the recipe
2233
*/
23-
public record ItemRecipe(String recipeName, String group, String category, RecipeType recipeType, ItemStack result, int amount, Ingredient[] ingredients,
34+
public record ItemRecipe(String recipeName, String group, String category, RecipeType recipeType, String result, int amount, Ingredient[] ingredients,
2435
String[] pattern, int cookingTime, float experience) {
2536

2637
/**
@@ -114,12 +125,32 @@ public Recipe toBukkitRecipe(NamespacedKey key, ItemStack result) {
114125
* @return The bukkit recipe
115126
*/
116127
public Recipe toBukkitRecipe() {
117-
ItemStack result = new ItemStack(this.result());
118-
result.setAmount(this.amount());
128+
ItemStack result = this.toBukkitItemStack(null);
119129
NamespacedKey key = this.getKey();
120130
return this.toBukkitRecipe(key, result);
121131
}
122132

133+
public ItemStack toBukkitItemStack(Player player) {
134+
ItemStack result;
135+
String[] resultParts = this.result.split(":");
136+
if(resultParts.length == 1) {
137+
result = Util.getItemStack(resultParts[0]);
138+
} else {
139+
result = switch (resultParts[0]) {
140+
case "material" -> new ItemStack(Util.getMaterial(resultParts[1]));
141+
case "item", "base64" -> Util.getItemStack(resultParts[1]);
142+
default -> Hook.HOOKS.stream()
143+
.filter(Hook::isEnable)
144+
.filter(hook -> hook.getPluginName().equalsIgnoreCase(resultParts[0]))
145+
.findFirst()
146+
.orElseThrow(() -> new IllegalArgumentException("The result " + this.result + " isn't valid."))
147+
.getItemStack(player, resultParts[1]);
148+
};
149+
}
150+
result.setAmount(this.amount());
151+
return result;
152+
}
153+
123154
/**
124155
* Get the key of the recipe
125156
* @return The key of the recipe

src/main/java/fr/traqueur/recipes/impl/domains/recipes/RecipeBuilder.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.traqueur.recipes.impl.domains.recipes;
22

33
import fr.traqueur.recipes.api.RecipeType;
4+
import fr.traqueur.recipes.api.Util;
45
import fr.traqueur.recipes.api.domains.Ingredient;
56
import fr.traqueur.recipes.api.domains.Recipe;
67
import fr.traqueur.recipes.impl.domains.ItemRecipe;
@@ -28,7 +29,7 @@ public class RecipeBuilder implements Recipe {
2829
/**
2930
* The result of the recipe.
3031
*/
31-
private ItemStack result;
32+
private String result;
3233

3334
/**
3435
* The amount of the result.
@@ -85,7 +86,7 @@ public Recipe setResult(ItemStack result) {
8586
if(type == null) {
8687
throw new IllegalArgumentException("Recipe type is not set");
8788
}
88-
this.result = result;
89+
this.result = Util.fromItemStack(result);
8990
return this;
9091
}
9192

0 commit comments

Comments
 (0)