diff --git a/pom.xml b/pom.xml
index 7a579b0..372de0f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,6 +55,15 @@
spigotmc-repo
https://hub.spigotmc.org/nexus/content/repositories/snapshots/
+
+ essentialsx-releases
+ EssentialsX API Repository
+ https://repo.essentialsx.net/releases
+
+
+ paper-repo
+ https://repo.papermc.io/repository/maven-public/
+
@@ -75,5 +84,11 @@
26.0.2
compile
+
+ net.essentialsx
+ EssentialsX
+ 2.21.2
+ provided
+
diff --git a/src/main/java/fr/molzonas/painfulloss/PainfulLoss.java b/src/main/java/fr/molzonas/painfulloss/PainfulLoss.java
index f609eee..5c9cc2f 100644
--- a/src/main/java/fr/molzonas/painfulloss/PainfulLoss.java
+++ b/src/main/java/fr/molzonas/painfulloss/PainfulLoss.java
@@ -3,18 +3,25 @@ package fr.molzonas.painfulloss;
import fr.molzonas.painfulloss.commands.PainfulLossCommand;
import fr.molzonas.painfulloss.enums.PropertiesEnum;
import fr.molzonas.painfulloss.listeners.DeathListener;
+import fr.molzonas.painfulloss.provider.CountPriceProvider;
+import fr.molzonas.painfulloss.provider.EssentialsPriceProvider;
+import fr.molzonas.painfulloss.provider.PriceProvider;
import fr.molzonas.painfulloss.utils.Message;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
+import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Locale;
+import java.util.Optional;
+import java.util.logging.Level;
public final class PainfulLoss extends JavaPlugin {
public static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
public static final String DEFAULT_LOCALE_TAG = "en-US";
@Getter private static PainfulLoss instance = null;
+ @Getter private static PriceProvider priceProvider = null;
@Override
public void onEnable() {
@@ -23,13 +30,14 @@ public final class PainfulLoss extends JavaPlugin {
configurationInit();
langInit();
registerCommands();
+ initPriceProvider();
registerListeners();
- Bukkit.getLogger().info("[PainfulLoss] Plugin has been enabled!");
+ info("Plugin has been enabled!");
}
@Override
public void onDisable() {
- Bukkit.getLogger().info("[PainfulLoss] Plugin has been disabled!");
+ info("Plugin has been disabled!");
}
private void configurationInit() {
@@ -56,9 +64,54 @@ public final class PainfulLoss extends JavaPlugin {
Bukkit.getPluginManager().registerEvents(new DeathListener(), this);
}
+ private void initPriceProvider() {
+ Optional ultimateShopProvider = Optional.empty();
+ Optional essentialsProvider = Optional.empty();
+ PriceProvider countProvider = new CountPriceProvider();
+
+ // Ultimate Shop
+ Plugin ultimateShop = getServer().getPluginManager().getPlugin("UltimateShop");
+ if (ultimateShop != null && ultimateShop.isEnabled()) {
+ info("UltimateShop detected (but inactive for Painful Loss)");
+ }
+
+ // Essentials
+ Plugin essentials = getServer().getPluginManager().getPlugin("Essentials");
+ if (essentials instanceof com.earth2me.essentials.IEssentials ess && essentials.isEnabled()) {
+ EssentialsPriceProvider epp = new EssentialsPriceProvider(ess);
+ if (epp.isReady()) {
+ essentialsProvider = Optional.of(epp);
+ info("Essentials detected, worth.yml loaded");
+ } else {
+ info("Essentials detected, worth.yml empty or unavailable");
+ }
+ }
+
+ // Selection
+ String provider = PropertiesEnum.PRICE_PROVIDER.getValue();
+ if (provider != null) {
+ switch (provider.toLowerCase()) {
+ case "ultimateshop": priceProvider = ultimateShopProvider.orElse(countProvider); break;
+ case "essentials": priceProvider = essentialsProvider.orElse(countProvider); break;
+ default: priceProvider = countProvider; break;
+ }
+ } else {
+ priceProvider = ultimateShopProvider.orElse(essentialsProvider.orElse(countProvider));
+ }
+ }
+
public void reload() {
reloadConfig();
Message.clearCache();
langInit();
+ initPriceProvider();
+ }
+
+ public static void log(Level level, String message) {
+ Bukkit.getLogger().log(level, "[Painful Loss] {0}", message);
+ }
+
+ public static void info(String message) {
+ PainfulLoss.log(Level.INFO, message);
}
}
diff --git a/src/main/java/fr/molzonas/painfulloss/commands/PainfulLossCommand.java b/src/main/java/fr/molzonas/painfulloss/commands/PainfulLossCommand.java
index 5f679d9..4e5ea6f 100644
--- a/src/main/java/fr/molzonas/painfulloss/commands/PainfulLossCommand.java
+++ b/src/main/java/fr/molzonas/painfulloss/commands/PainfulLossCommand.java
@@ -2,6 +2,7 @@ package fr.molzonas.painfulloss.commands;
import fr.molzonas.painfulloss.PainfulLoss;
import fr.molzonas.painfulloss.utils.Message;
+import fr.molzonas.painfulloss.utils.PriceCalculator;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@@ -17,7 +18,8 @@ import java.util.Locale;
public class PainfulLossCommand implements CommandExecutor, TabCompleter {
@Override
- public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] args) {
+ public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command,
+ @NotNull String s, @NotNull String[] args) {
if (args.length == 0) {
commandSender.sendMessage(Message.of("plugin.help"));
return true;
@@ -27,6 +29,7 @@ public class PainfulLossCommand implements CommandExecutor, TabCompleter {
case "reload" -> commandReload(commandSender);
case "help" -> commandHelp(commandSender);
case "test" -> commandTest(commandSender, args);
+ case "worth" -> commandWorth(commandSender, args);
default -> commandUnknown(commandSender);
};
}
@@ -39,12 +42,14 @@ public class PainfulLossCommand implements CommandExecutor, TabCompleter {
}
private boolean commandNotAutorised(CommandSender commandSender) {
- commandSender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4You don't have the permission to execute this command !"));
+ commandSender.sendMessage(ChatColor.translateAlternateColorCodes('&',
+ "&4You don't have the permission to execute this command !"));
return true;
}
private boolean commandHelp(CommandSender commandSender) {
- commandSender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&4G&3i&et &ag&co&9o&dd"));
+ commandSender.sendMessage(ChatColor.translateAlternateColorCodes('&',
+ "&4G&3i&et &ag&co&9o&dd"));
return true;
}
@@ -54,7 +59,7 @@ public class PainfulLossCommand implements CommandExecutor, TabCompleter {
locale = Locale.forLanguageTag(args[1].trim());
}
if (commandSender instanceof Player p) {
- p.sendMessage(Message.of("death.summary", locale, p.getName(), 12345));
+ p.sendMessage(Message.of("death.summary.count", locale, p.getName(), 12345));
p.sendMessage(Message.of("death.topitem", locale, "Netherite Chestplate", 7890));
} else {
var text = Message.of("death.summary.first", locale, "Console", 42);
@@ -68,9 +73,26 @@ public class PainfulLossCommand implements CommandExecutor, TabCompleter {
return false;
}
+ private boolean commandWorth(CommandSender commandSender, String[] args) {
+ if (args.length == 1 && commandSender instanceof Player p && commandSender.hasPermission("painfulloss.worth")) {
+ commandSender.sendMessage(Message.of("command.worth", PriceCalculator.estimate(p)));
+ } else if (args.length == 2 && commandSender.hasPermission("painfulloss.worth.other")) {
+ Player p = PainfulLoss.getInstance().getServer().getPlayer(args[1]);
+ if (p == null) {
+ commandSender.sendMessage(Message.of("command.worth.unknownplayer", args[1]));
+ return true;
+ }
+ commandSender.sendMessage(Message.of("command.worth.other", PriceCalculator.estimate(p)));
+ } else {
+ return commandNotAutorised(commandSender);
+ }
+ return false;
+ }
@Override
- public @Nullable List onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] args) {
+ public @Nullable List onTabComplete(@NotNull CommandSender commandSender,
+ @NotNull Command command, @NotNull String s,
+ @NotNull String[] args) {
List completions = new ArrayList<>();
if (args.length == 1) {
completions.add("test");
diff --git a/src/main/java/fr/molzonas/painfulloss/enums/PropertiesEnum.java b/src/main/java/fr/molzonas/painfulloss/enums/PropertiesEnum.java
index 68f2258..95a1211 100644
--- a/src/main/java/fr/molzonas/painfulloss/enums/PropertiesEnum.java
+++ b/src/main/java/fr/molzonas/painfulloss/enums/PropertiesEnum.java
@@ -5,11 +5,17 @@ import lombok.Getter;
public enum PropertiesEnum {
LOCALE("locale", PainfulLoss.DEFAULT_LOCALE_TAG),
- DEBUG("debug", "false");
+ DEBUG("debug", "false"),
+ PRICE_PROVIDER("priceProvider")
+ ;
@Getter private final String path;
@Getter private String fallback = null;
+ PropertiesEnum(String path) {
+ this.path = path;
+ }
+
PropertiesEnum(String path, String fallback) {
this.path = path;
this.fallback = fallback;
diff --git a/src/main/java/fr/molzonas/painfulloss/listeners/DeathListener.java b/src/main/java/fr/molzonas/painfulloss/listeners/DeathListener.java
index d7435f2..8c7ad0b 100644
--- a/src/main/java/fr/molzonas/painfulloss/listeners/DeathListener.java
+++ b/src/main/java/fr/molzonas/painfulloss/listeners/DeathListener.java
@@ -1,6 +1,8 @@
package fr.molzonas.painfulloss.listeners;
+import fr.molzonas.painfulloss.PainfulLoss;
import fr.molzonas.painfulloss.utils.Message;
+import fr.molzonas.painfulloss.utils.PriceCalculator;
import org.bukkit.GameRule;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -9,6 +11,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
@@ -27,8 +30,23 @@ public class DeathListener implements Listener {
if (lostItems.isEmpty()) return;
- int cnt = lostItems.stream().mapToInt(ItemStack::getAmount).sum();
+ double total = PriceCalculator.estimate(lostItems);
- player.sendMessage(Message.of("death.summary", player.getName(), cnt));
+ if (PainfulLoss.getPriceProvider().isCountBased()) {
+ player.sendMessage(Message.of("death.summary.count", player.getName(), total));
+ } else {
+ player.sendMessage(Message.of("death.summary.value", player.getName(), numberFormat(total)));
+ }
+ }
+
+ protected static String nameFormat(ItemStack s) {
+ ItemMeta meta = s.getItemMeta();
+ if (meta != null && meta.hasDisplayName()) return meta.getDisplayName();
+ return s.getType().name();
+ }
+
+ protected static String numberFormat(double v) {
+ if (v == (long) v) return String.format("%d", (long) v);
+ return String.format(Message.getCurrentLocale(), "%.2f", v);
}
}
diff --git a/src/main/java/fr/molzonas/painfulloss/provider/CountPriceProvider.java b/src/main/java/fr/molzonas/painfulloss/provider/CountPriceProvider.java
new file mode 100644
index 0000000..4ee8b60
--- /dev/null
+++ b/src/main/java/fr/molzonas/painfulloss/provider/CountPriceProvider.java
@@ -0,0 +1,22 @@
+package fr.molzonas.painfulloss.provider;
+
+import org.bukkit.inventory.ItemStack;
+
+import java.util.Optional;
+
+public class CountPriceProvider implements PriceProvider{
+ @Override
+ public String getName() {
+ return "Count";
+ }
+
+ @Override
+ public Optional getPrice(ItemStack stack) {
+ return Optional.of((double) stack.getAmount());
+ }
+
+ @Override
+ public boolean isCountBased() {
+ return true;
+ }
+}
diff --git a/src/main/java/fr/molzonas/painfulloss/provider/EssentialsPriceProvider.java b/src/main/java/fr/molzonas/painfulloss/provider/EssentialsPriceProvider.java
new file mode 100644
index 0000000..0c3decf
--- /dev/null
+++ b/src/main/java/fr/molzonas/painfulloss/provider/EssentialsPriceProvider.java
@@ -0,0 +1,36 @@
+package fr.molzonas.painfulloss.provider;
+
+import com.earth2me.essentials.Worth;
+import com.earth2me.essentials.IEssentials;
+import org.bukkit.inventory.ItemStack;
+
+import java.math.BigDecimal;
+import java.util.Optional;
+
+public class EssentialsPriceProvider implements PriceProvider {
+ private final IEssentials plugin;
+ private final Worth worth;
+ public EssentialsPriceProvider(IEssentials plugin) {
+ this.plugin = plugin;
+ this.worth = plugin.getWorth();
+ }
+
+ @Override
+ public String getName() {
+ return "Essentials";
+ }
+
+ @Override
+ public Optional getPrice(ItemStack stack) {
+ if (stack == null || stack.getAmount() <= 0) return Optional.empty();
+
+ try {
+ BigDecimal price = worth.getPrice(plugin, stack);
+ if (price == null) return Optional.empty();
+ if (price.signum() < 0) return Optional.empty();
+ return Optional.of(price.doubleValue());
+ } catch (Exception e) {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/src/main/java/fr/molzonas/painfulloss/provider/PriceProvider.java b/src/main/java/fr/molzonas/painfulloss/provider/PriceProvider.java
new file mode 100644
index 0000000..86e2179
--- /dev/null
+++ b/src/main/java/fr/molzonas/painfulloss/provider/PriceProvider.java
@@ -0,0 +1,12 @@
+package fr.molzonas.painfulloss.provider;
+
+import org.bukkit.inventory.ItemStack;
+
+import java.util.Optional;
+
+public interface PriceProvider {
+ String getName();
+ Optional getPrice(ItemStack stack);
+ default boolean isReady() { return true; }
+ default boolean isCountBased() { return false; }
+}
diff --git a/src/main/java/fr/molzonas/painfulloss/utils/Message.java b/src/main/java/fr/molzonas/painfulloss/utils/Message.java
index 48d5632..2a08768 100644
--- a/src/main/java/fr/molzonas/painfulloss/utils/Message.java
+++ b/src/main/java/fr/molzonas/painfulloss/utils/Message.java
@@ -1,6 +1,7 @@
package fr.molzonas.painfulloss.utils;
import fr.molzonas.painfulloss.PainfulLoss;
+import lombok.Getter;
import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull;
@@ -14,7 +15,7 @@ public class Message {
private static final String DIRECTORY = "lang";
private static final String BUNDLE_NAME = "messages";
private static final ConcurrentHashMap CACHE = new ConcurrentHashMap<>();
- private static Locale currentLocale = Locale.ENGLISH;
+ @Getter private static Locale currentLocale = Locale.ENGLISH;
private Message() {}
diff --git a/src/main/java/fr/molzonas/painfulloss/utils/PriceCalculator.java b/src/main/java/fr/molzonas/painfulloss/utils/PriceCalculator.java
new file mode 100644
index 0000000..74deeac
--- /dev/null
+++ b/src/main/java/fr/molzonas/painfulloss/utils/PriceCalculator.java
@@ -0,0 +1,31 @@
+package fr.molzonas.painfulloss.utils;
+
+import fr.molzonas.painfulloss.PainfulLoss;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.List;
+
+public class PriceCalculator {
+ private PriceCalculator() {}
+
+ public static Double estimate(Player player) {
+ return estimate(player.getInventory().getContents());
+ }
+
+ public static Double estimate(ItemStack[] items) {
+ double rs = 0d;
+ for (ItemStack item : items) {
+ rs += estimate(item);
+ }
+ return rs;
+ }
+
+ public static Double estimate(List items) {
+ return items.stream().mapToDouble(PriceCalculator::estimate).sum();
+ }
+
+ public static Double estimate(ItemStack item) {
+ return PainfulLoss.getPriceProvider().getPrice(item).orElse(0d);
+ }
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 530e0fd..80afabd 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -1,5 +1,27 @@
-# Available : en-US, fr-FR
+# Available : en-US, fr-FR, and more if you add your own files
locale: en-US
# Dev option, you won't have to enable it, trust me
-debug: false
\ No newline at end of file
+debug: false
+
+# Select the price provider between Essentials (worth.yml), UltimateShop (value) and Count (number of items).
+# Keep it empty will take the first available in order between UltimateShop, Essentials and Count.
+priceProvider:
+
+# How estimations works,
+estimation:
+ xp:
+ enabled: true
+ price_per_point: 0.5
+ show_in_message: true
+ show_in_message_with_level: true
+
+ enchant:
+ enabled: true
+ default_per_level: 0
+ table:
+ SHARPNESS: 100
+ EFFICIENCY: 100
+ UNBREAKING: 50
+ FORTUNE: 300
+ MENDING: 1000
\ No newline at end of file
diff --git a/src/main/resources/lang/messages_en.properties b/src/main/resources/lang/messages_en.properties
index f4cd121..56de8f4 100644
--- a/src/main/resources/lang/messages_en.properties
+++ b/src/main/resources/lang/messages_en.properties
@@ -1,4 +1,8 @@
-death.summary=&c{0} lost &e{1}&c.
+death.summary.value=&c{0} lost the equivalent of &e{1}$&c.
+death.summary.count=&c{0} lost &e{1}&c item(s).
death.topitem=&7Most valuable: &6{0} &7(&e{1}&7)
+command.worth=&6Your full inventory is worth {0}$.
+command.worth.other=&6{0} full inventory is worth {1}$.
+command.worth.unknownplayer=&cThe requested player ({0}) has not been found.
plugin.reload=&aPainfulLoss has successfully reloaded.
plugin.unknown=&4Unknown command. Please use &c/painfullost help &4to get some help.
\ No newline at end of file
diff --git a/src/main/resources/lang/messages_fr.properties b/src/main/resources/lang/messages_fr.properties
index 763e44c..5b08dbc 100644
--- a/src/main/resources/lang/messages_fr.properties
+++ b/src/main/resources/lang/messages_fr.properties
@@ -1,4 +1,8 @@
-death.summary=&c{0} a perdu &e{1}&c.
+death.summary.value=&c{0} a perdu l'équivalent de &e{1}$&c.
+death.summary.count=&c{0} a perdu &e{1}&c item(s).
death.topitem=&7Objet le plus cher : &6{0} &7(&e{1}&7)
+command.worth=&6Votre inventaire complet vaut {0}$.
+command.worth.other=&6L''inventaire complet de {0} vaut {1}$.
+command.worth.unknownplayer=&cLe joueur demandé ({0}) n''a pas été trouvé.
plugin.reload=&aPainfulLoss a été rechargé avec succès.
plugin.unknown=&4Commande inconnue. Merci d'utiliser &c/painfulloss help &4pour obtenir de l'aide.
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index fe68653..7293f7d 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -2,12 +2,19 @@ name: PainfulLoss
version: '1.0'
main: fr.molzonas.painfulloss.PainfulLoss
api-version: '1.20'
+softdepend: [Essentials, UltimateShop]
author: Molzonas
commands:
painfulloss:
description: Base command for Painfulloss
- usage: /painfulloss
+ usage: /painfulloss
permissions:
painfulloss.admin:
description: Access to PainfulLoss admin commands
+ default: op
+ painfulloss.worth:
+ description: Worth your own inventory
+ default: true
+ painfulloss.worth.other:
+ description: Worth other players inventory
default: op
\ No newline at end of file