diff --git a/src/main/java/com/extendedclip/papi/expansion/player/PlayerExpansion.java b/src/main/java/com/extendedclip/papi/expansion/player/PlayerExpansion.java
index 1790ae3..d14254d 100644
--- a/src/main/java/com/extendedclip/papi/expansion/player/PlayerExpansion.java
+++ b/src/main/java/com/extendedclip/papi/expansion/player/PlayerExpansion.java
@@ -24,28 +24,14 @@
 import me.clip.placeholderapi.PlaceholderAPIPlugin;
 import me.clip.placeholderapi.expansion.Configurable;
 import me.clip.placeholderapi.expansion.PlaceholderExpansion;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.Material;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.World;
+import org.bukkit.*;
 import org.bukkit.enchantments.Enchantment;
 import org.bukkit.entity.Player;
 import org.bukkit.potion.PotionEffectType;
 
 import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.durability;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.format12;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.format24;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.getBiome;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.getCapitalizedBiome;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.getEmptySlots;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.getDirection;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.getTotalExperience;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.getXZDirection;
-import static com.extendedclip.papi.expansion.player.PlayerUtil.itemInHand;
+
+import static com.extendedclip.papi.expansion.player.PlayerUtil.*;
 
 public final class PlayerExpansion extends PlaceholderExpansion implements Configurable {
     private String low;
@@ -195,6 +181,18 @@ public String onRequest(OfflinePlayer player, String identifier) {
             return "0";
         }
 
+        if (identifier.startsWith("has_unlocked_recipe_")) {
+            if (identifier.split("has_unlocked_recipe_").length > 1) {
+                String recipeName = identifier.split("has_unlocked_recipe_")[1];
+                try {
+                    return bool(p.hasDiscoveredRecipe(NamespacedKey.minecraft(recipeName)));
+                } catch (IllegalArgumentException e) {
+                    return "invalid recipe"; // could be false instead
+                }
+            }
+            return bool(false);
+        }
+
         if (identifier.startsWith("locale")) {
             String localeStr = PlayerUtil.getLocale(p);
             String localeStrISO = localeStr.replace("_", "-");
@@ -223,6 +221,9 @@ public String onRequest(OfflinePlayer player, String identifier) {
         }
 
         switch (identifier) {
+            case "recipes_list":
+                return p.getDiscoveredRecipes().toString(); // sort of ugly (i dont see the use case either)
+
             case "absorption": {
                 if (VersionHelper.HAS_ABSORPTION_METHODS) {
                     return Integer.toString((int) p.getAbsorptionAmount());