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

Recipe Support #7150

Open
wants to merge 46 commits into
base: dev/feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2b18331
Starter Commit
TheAbsolutionism Oct 8, 2024
5301401
Shapeless Addition
TheAbsolutionism Oct 9, 2024
5aaf2a6
Testing Stuff
TheAbsolutionism Oct 9, 2024
bd2c23f
Testing Fix
TheAbsolutionism Oct 9, 2024
50bb139
More additions
TheAbsolutionism Oct 10, 2024
29bc2e8
Additional Updates + Changes
TheAbsolutionism Oct 11, 2024
d73bad2
Further Additions
TheAbsolutionism Oct 12, 2024
23d4dc0
Fuse Changes
TheAbsolutionism Oct 12, 2024
fbefde4
Tests (Stopping Point)
TheAbsolutionism Oct 12, 2024
a687e0f
Some Fixes
TheAbsolutionism Oct 13, 2024
1f79ed6
Additional Changes + Fixes
TheAbsolutionism Oct 15, 2024
5c3a8c0
Fuzes Wishlist
TheAbsolutionism Oct 15, 2024
78c5411
Almost Done
TheAbsolutionism Oct 16, 2024
ebc9428
Fix Imports
TheAbsolutionism Oct 16, 2024
793c3ee
One more fix
TheAbsolutionism Oct 16, 2024
9a628ea
Fix Test
TheAbsolutionism Oct 16, 2024
9307a02
Merge remote-tracking branch 'upstream/dev/feature' into dev/Recipes
TheAbsolutionism Oct 16, 2024
ed8f1db
Change RecipeType class register
TheAbsolutionism Oct 16, 2024
1cc3c24
Module + Changes
TheAbsolutionism Oct 16, 2024
48a6c1f
Fuse's Changes
TheAbsolutionism Oct 16, 2024
db3e501
Partial Changes
TheAbsolutionism Oct 17, 2024
2d611e0
More Partial Changes
TheAbsolutionism Oct 19, 2024
3c37524
RecipeWrapper
TheAbsolutionism Oct 31, 2024
250c69f
Merge remote-tracking branch 'upstream/dev/feature' into dev/Recipes
TheAbsolutionism Oct 31, 2024
3bd9c4a
Additional Changes
TheAbsolutionism Nov 1, 2024
06d8346
Remove "runtime"
TheAbsolutionism Nov 5, 2024
4b8ba57
Merge branch 'dev/feature' into dev/Recipes
TheAbsolutionism Nov 6, 2024
530ac32
Merge branch 'dev/feature' into dev/Recipes
TheAbsolutionism Nov 8, 2024
0b712cc
Merge branch 'dev/feature' into dev/Recipes
TheAbsolutionism Nov 11, 2024
76716cb
Merge branch 'dev/feature' into dev/Recipes
Efnilite Nov 12, 2024
1087525
Requested Changes
TheAbsolutionism Nov 13, 2024
e801263
Additional Changes
TheAbsolutionism Nov 13, 2024
ab7edc5
Fix Errors
TheAbsolutionism Nov 13, 2024
99250ad
Fix Docs
TheAbsolutionism Nov 13, 2024
e2193ea
Requested Changes
TheAbsolutionism Nov 16, 2024
2eea7a6
More Changes
TheAbsolutionism Nov 16, 2024
6268513
Whoops
TheAbsolutionism Nov 16, 2024
149b842
Partial Changes
TheAbsolutionism Nov 17, 2024
14972f3
Merge remote-tracking branch 'upstream/dev/feature' into dev/Recipes
TheAbsolutionism Nov 23, 2024
0e5e1e4
Secspressions!
TheAbsolutionism Nov 23, 2024
cb52649
Remove Duplicated Module
TheAbsolutionism Nov 24, 2024
f6bdb2f
Merge branch 'dev/feature' into dev/Recipes
TheAbsolutionism Dec 9, 2024
04ba9fc
Changes + Additions
TheAbsolutionism Dec 9, 2024
9f97e4f
Fix Cond
TheAbsolutionism Dec 9, 2024
64834b0
Merge branch 'dev/Recipes' of https://github.com/TheAbsolutionism/Skr…
TheAbsolutionism Dec 9, 2024
b4e809c
Check Lambda
TheAbsolutionism Dec 9, 2024
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
2 changes: 2 additions & 0 deletions src/main/java/ch/njol/skript/Skript.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
import org.skriptlang.skript.bukkit.SkriptMetrics;
import org.skriptlang.skript.bukkit.breeding.BreedingModule;
import org.skriptlang.skript.bukkit.displays.DisplayModule;
import org.skriptlang.skript.bukkit.recipes.RecipeModule;
import org.skriptlang.skript.lang.comparator.Comparator;
import org.skriptlang.skript.lang.comparator.Comparators;
import org.skriptlang.skript.lang.converter.Converter;
Expand Down Expand Up @@ -557,6 +558,7 @@ public void onEnable() {
// todo: become proper module once registry api is merged
DisplayModule.load();
BreedingModule.load();
RecipeModule.load();
} catch (final Exception e) {
exception(e, "Could not load required .class files: " + e.getLocalizedMessage());
setEnabled(false);
Expand Down
113 changes: 113 additions & 0 deletions src/main/java/ch/njol/skript/bukkitutil/NamespacedUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package ch.njol.skript.bukkitutil;

import ch.njol.skript.Skript;
import ch.njol.util.NonNullPair;
import com.google.common.collect.Sets;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.NotNull;

import java.util.Locale;
import java.util.Set;

public class NamespacedUtils {

private static final Set<Character> LEGAL_NAMESPACE_CHARS = Sets.newHashSet(ArrayUtils.toObject("abcdefghijklmnopqrstuvwxyz0123456789._-/".toCharArray()));

/**
* Gets a namespaced key. This method will try to get existing keys first, but if that fails
* it will create the key in Skript's namespace.
*
* @param key the unparsed key
* @return the resulting NamespacedKey
*/
public static NamespacedKey getNamespacedKey(@NotNull String key) {
NamespacedKey namespacedKey = NamespacedKey.fromString(key, Skript.getInstance());
if (namespacedKey != null)
return namespacedKey;

return createNamespacedKey(key);
}

/**
* Creates a namespaced key in Skript's namespace encoded to avoid the character limitations of a normal key.
* This key will be created in Skript's namespace.
*
* @param key The key to use
* @return a NamespacedKey with the encoded key in corresponding Namespace
*/
public static NamespacedKey createNamespacedKey(@NotNull String key) {
StringBuilder encodedKeyBuilder = new StringBuilder();
// keys must be all lowercase
key = key.toLowerCase(Locale.ENGLISH).replace(' ', '_');
int keyLength = key.length();
for (int i = 0; i < keyLength; i++) {
char currentChar = key.charAt(i);
// if this character is legal to use in a namespace key
if (LEGAL_NAMESPACE_CHARS.contains(currentChar)) {
// if the original string had a ".x" in it, we need to escape it
// so decoding doesn't think it's a hex sequence
if (currentChar == '.' && key.charAt(i + 1) == 'x') {
i += 1; // skip the "x"
encodedKeyBuilder.append(".x");
encodedKeyBuilder.append(Integer.toHexString('.'));
encodedKeyBuilder.append(".x");
encodedKeyBuilder.append(Integer.toHexString('x'));
// if we're not at the end and the next char is a legal char, add the trailing dot
// to represent the end of the hex sequence
if (i != (keyLength - 1) && LEGAL_NAMESPACE_CHARS.contains(key.charAt(i + 1)))
encodedKeyBuilder.append('.');
} else {
// we are dealing with a legal character, so we can just append it
encodedKeyBuilder.append(currentChar);
}
} else {
// add ".x(hex code)" to the encoded key
encodedKeyBuilder.append(".x");
encodedKeyBuilder.append(Integer.toHexString(currentChar));
// only add the trailing dot if the next character is a legal character
if (i != (keyLength - 1) && LEGAL_NAMESPACE_CHARS.contains(key.charAt(i + 1)))
encodedKeyBuilder.append('.');
}
}
return NamespacedKey.fromString(encodedKeyBuilder.toString(), Skript.getInstance());
}

/**
* Decodes a NamespacedKey encoded by #getNamespacedKey
*
* @param namespacedKey the namespaced key to decode
* @return a Pair with the first element as the namespace and the second as the decoded key
*/
public static NonNullPair<String, String> decodeNamespacedKey(NamespacedKey namespacedKey) {
String encodedKey = namespacedKey.getKey();
StringBuilder decodedKeyBuilder = new StringBuilder();
int encodedKeyLength = encodedKey.length();
int lastCharIndex = encodedKeyLength - 1;
for (int i = 0; i < encodedKeyLength; i++) {
char currentChar = encodedKey.charAt(i);
// if we are encountering a ".x" hex sequence
if (i != lastCharIndex && currentChar == '.' && encodedKey.charAt(i + 1) == 'x') {
i += 2; // skip the ".x" so it isn't part of our hex string
StringBuilder hexString = new StringBuilder();
// The hex sequence continues until a . is encountered or we reach the end of the string
while (i <= lastCharIndex && encodedKey.charAt(i) != '.') {
hexString.append(encodedKey.charAt(i));
i++;
}
// if the . was the start of another ".x" hex sequence, back up by 1 character
if (i <= lastCharIndex && encodedKey.charAt(i + 1) == 'x')
i--;
// parse the hex sequence to a char
char decodedChar = (char) Long.parseLong(hexString.toString(), 16);
decodedKeyBuilder.append(decodedChar);
} else {
// this is just a normal character, not a hex sequence
// so we can just append it
decodedKeyBuilder.append(currentChar);
}
}
return new NonNullPair<>(namespacedKey.getNamespace(), decodedKeyBuilder.toString());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,7 @@ public Player get(final PrepareItemCraftEvent e) {
return null;
}
}, 0);

// CraftEvents - recipe namespaced key strings
EventValues.registerEventValue(CraftItemEvent.class, String.class, new Getter<String, CraftItemEvent>() {
@Nullable
Expand Down Expand Up @@ -1428,6 +1429,7 @@ public ItemStack get(CraftItemEvent e) {
return e.getRecipe().getResult();
}
}, 0);

//InventoryOpenEvent
EventValues.registerEventValue(InventoryOpenEvent.class, Player.class, new Getter<Player, InventoryOpenEvent>() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.skriptlang.skript.bukkit.recipes;

import org.bukkit.inventory.recipe.CookingBookCategory;
import org.bukkit.inventory.recipe.CraftingBookCategory;

TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved
/**
* Enum for converting Bukkit recipe categories into one usable by Skript.
*/
public enum RecipeCategory {

CRAFTING_BUILDING(CraftingBookCategory.BUILDING),
CRAFTING_EQUIPMENT(CraftingBookCategory.EQUIPMENT),
CRAFTING_MISC(CraftingBookCategory.MISC),
CRAFTING_REDSTONE(CraftingBookCategory.REDSTONE),

COOKING_BLOCKS(CookingBookCategory.BLOCKS),
COOKING_FOOD(CookingBookCategory.FOOD),
COOKING_MISC(CookingBookCategory.MISC);

private Enum<?> category;
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved

RecipeCategory(Enum<?> category) {
this.category = category;
}

public Enum<?> getCategory() {
return category;
}

public static RecipeCategory convertBukkitToSkript(Enum<?> category) {
for (RecipeCategory recipeCategory : RecipeCategory.values()) {
if (recipeCategory.category.equals(category))
return recipeCategory;
}
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package org.skriptlang.skript.bukkit.recipes;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.classes.EnumClassInfo;
import ch.njol.skript.expressions.base.EventValueExpression;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.registrations.EventValues;
import ch.njol.skript.util.Getter;
import org.bukkit.Bukkit;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.event.player.PlayerRecipeDiscoverEvent;
import org.bukkit.inventory.Recipe;
import org.jetbrains.annotations.Nullable;
import org.skriptlang.skript.lang.comparator.Comparator;
import org.skriptlang.skript.lang.comparator.Comparators;
import org.skriptlang.skript.lang.comparator.Relation;
import org.skriptlang.skript.bukkit.recipes.RecipeUtils.RecipeType;

import java.io.IOException;

public class RecipeModule {

public static void load() throws IOException {
Skript.getAddonInstance().loadClasses("org.skriptlang.skript.bukkit.recipes", "elements");

// --- CLASSES --- //

Classes.registerClass(new ClassInfo<>(Recipe.class, "recipe")
.user("recipes?")
.name("Recipe")
.description("Represents a recipe.")
.usage("recipes")
.examples("all recipes")
.since("INSERT VERSION")
.defaultExpression(new EventValueExpression<>(Recipe.class)));

Classes.registerClass(new EnumClassInfo<>(RecipeCategory.class, "recipecategory", "recipe categories")
.user("recipe ?categor(y|ies)")
.name("Recipe Category")
.description("Represents the different categories of recipes.")
.since("INSERT VERSION")
);

Classes.registerClass(new EnumClassInfo<>(RecipeType.class, "recipetype", "recipe types")
.user("recipe ?types?")
.name("Recipe Type")
.description("Represents the type of a recipe.")
.since("INSERT VERSION")
);

// --- COMPARATORS --- //

Comparators.registerComparator(RecipeType.class, RecipeType.class, new Comparator<RecipeType, RecipeType>() {
@Override
public Relation compare(RecipeType type1, RecipeType type2) {
if (type1.getRecipeClass() != null && type2.getRecipeClass() != null)
return Relation.get(type2.getRecipeClass().isAssignableFrom(type1.getRecipeClass()));
return Relation.NOT_EQUAL;
}
});

// --- EVENT VALUES --- //

//PrepareItemCraftEvent
EventValues.registerEventValue(PrepareItemCraftEvent.class, Recipe.class, new Getter<Recipe, PrepareItemCraftEvent>() {
@Override
public @Nullable Recipe get(PrepareItemCraftEvent event) {
return event.getRecipe();
}
}, EventValues.TIME_NOW);

//CraftItemEvent
EventValues.registerEventValue(CraftItemEvent.class, Recipe.class, new Getter<Recipe, CraftItemEvent>() {
@Override
public @Nullable Recipe get(CraftItemEvent event) {
TheAbsolutionism marked this conversation as resolved.
Show resolved Hide resolved
return event.getRecipe();
}
}, EventValues.TIME_NOW);

// PlayerRecipeDiscoverEvent
EventValues.registerEventValue(PlayerRecipeDiscoverEvent.class, Recipe.class, new Getter<Recipe, PlayerRecipeDiscoverEvent>() {
@Override
public @Nullable Recipe get(PlayerRecipeDiscoverEvent event) {
return Bukkit.getRecipe(event.getRecipe());
}
}, EventValues.TIME_NOW);

}

}
Loading