From 071c79369c1373f066a317d8ab03c5674110cbcf Mon Sep 17 00:00:00 2001 From: EpiCanard Date: Sat, 11 Mar 2023 21:44:04 +0100 Subject: [PATCH] Add a PlaceholderExpansion to check light level --- .gitignore | 2 + README.md | 23 +++ pom.xml | 63 +++++++ .../checklight/CheckLightExpansion.java | 173 ++++++++++++++++++ 4 files changed, 261 insertions(+) create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/fr/freebuild/papi/expansion/checklight/CheckLightExpansion.java diff --git a/.gitignore b/.gitignore index a1c2a23..e8b13f6 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +target/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..263d578 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ + +# CheckLightExpansion + +Expose a placeholder to check if the player as a specific light in inventory. + +## Properties and action + +The placeholder checklight expose 2 properties : +- level : It specify the level of light wanted. It can be a value between 1 and 15 or "no" for no nbt level +- amount : The quantity wanted + +And one action : +- remove : Remove the items matching the expectation. + +## Output + +The placeholder will output "no" if the placeholder can't find the wanted lights and "yes" if it can; + +## Examples + +`%checklight_level:2_amount:5%` -> Check the player have 5 light with level 2 +`%checklight_level:2_level:no_amount:5%` -> Check the player have 5 light with level 2 or without nbt level +`%checklight_remove_level:2_amount:5%` -> Check the player have 5 light with level 2 and remove them diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a06935c --- /dev/null +++ b/pom.xml @@ -0,0 +1,63 @@ + + 4.0.0 + + fr.freebuild.papi.expansion.checklight + checklight-expansion + 1.0.0 + + PAPI-Expansion-CheckLight + PlaceholderAPI expansion to check light + + + 1.8 + 1.8 + UTF-8 + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + placeholderapi + https://repo.extendedclip.com/content/repositories/placeholderapi/ + + + + + + + org.spigotmc + spigot-api + 1.19.3-R0.1-SNAPSHOT + provided + + + me.clip + placeholderapi + 2.11.2 + provided + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.2 + + ${project.name} + + + true + true + + + + + + + + diff --git a/src/main/java/fr/freebuild/papi/expansion/checklight/CheckLightExpansion.java b/src/main/java/fr/freebuild/papi/expansion/checklight/CheckLightExpansion.java new file mode 100644 index 0000000..72c6961 --- /dev/null +++ b/src/main/java/fr/freebuild/papi/expansion/checklight/CheckLightExpansion.java @@ -0,0 +1,173 @@ +package fr.freebuild.papi.expansion.checklight; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; + +public class CheckLightExpansion extends PlaceholderExpansion { + + private String craftItemStackPath; + + + public CheckLightExpansion() { + String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + this.craftItemStackPath = "org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"; + } + + @Override + public String getAuthor() { + return "Freebuild"; + } + + @Override + public String getIdentifier() { + return "checklight"; + } + + @Override + public String getVersion() { + return "1.0.0"; + } + + private class ParsingFailedException extends Exception { + public ParsingFailedException(String message) { + super(message); + } + } + + /** + * Expose a placeholder to check if the player as a specific light in inventory. + * + * The placeholder checklight expose 2 properties : + * - level : It specify the level of light wanted. It can be a value between 1 and 15 or "no" for no nbt level + * - amount : The quantity wanted + * And one action : + * - remove : Remove it if it match the expectation. + * + * Examples : + * %checklight_level:2_amount:5% -> Check the player have 5 light with level 2 + * %checklight_level:2_level:no_amount:5% -> Check the player have 5 light with level 2 or without nbt level + * %checklight_remove_level:2_amount:5% -> Check the player have 5 light with level 2 and remove them + */ + @Override + public String onPlaceholderRequest(Player player, String param) { + if (player == null) + return null; + + try { + return handleRequest(player, param.split("_")); + } catch (ParsingFailedException e) { + return e.getMessage(); + } + } + + private String handleRequest(Player player, String[] args) throws ParsingFailedException { + + List levels = new ArrayList<>(); + Integer amount = 1; + Boolean remove = false; + for (int i = 0; i < args.length; i++) { + if (args[i].equalsIgnoreCase("remove")) + remove = true; + if (args[i].startsWith("level:")) + levels.add(parseIntArg(args[i], "level", 0, 15)); + if (args[i].startsWith("amount:")) + amount = parseIntArg(args[i], "amount", 1, null); + } + + ItemStack[] contents = player.getInventory().getContents(); + + Integer remaining = amount; + List toDelete = new ArrayList<>(); + + for (int i = 0; i < contents.length && remaining > 0; i++) { + ItemStack item = contents[i]; + + if(item != null && item.getType() == Material.LIGHT) { + try { + Integer lightLevel = getNbtLevel(item); + if (levels.stream().anyMatch(level -> lightLevel == level)) { + Integer amountToRemove = Math.min(remaining, item.getAmount()); + remaining -= amountToRemove; + ItemStack itemToDelete = item.clone(); + itemToDelete.setAmount(amountToRemove); + toDelete.add(itemToDelete); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + if (remove && remaining <= 0) { + toDelete.forEach(it -> player.getInventory().removeItem(it)); + } + + return (remaining > 0) ? "no" : "yes"; + } + + private Integer parseIntArg(String arg, String name, Integer start, Integer end) throws ParsingFailedException { + try { + String value = arg.substring(name.length() + 1); + if (value.equals("no")) + return null; + Integer num = Integer.parseInt(value); + if (start != null && num < start) { + num = start; + } + if (end != null && num > end) { + num = end; + } + return num; + } catch (Exception e) { + e.printStackTrace(); + throw new ParsingFailedException(String.format("Invalid value for %s. Expecting: %[] fromObjectToClass(Object[] args) { + Class[] classes = new Class[0]; + + if (args != null) { + classes = new Class[args.length]; + for (int i = 0; i < args.length; i++) { + classes[i] = args[i].getClass(); + } + } + return classes; + } +}