├── .gitattributes ├── screenshots ├── screenshot0.png ├── screenshot1.png ├── screenshot2.png ├── screenshot3.png └── screenshot4.png ├── src └── main │ ├── resources │ ├── plugin.yml │ └── config.yml │ └── java │ └── cn │ └── kevyn │ └── payfordeath │ ├── PFDCommand.java │ ├── utils │ ├── ConfigHelper.java │ ├── PFDBean.java │ └── StringFormula.java │ ├── PayForDeath.java │ └── PFDListener.java ├── LICENSE ├── .gitignore ├── pom.xml └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /screenshots/screenshot0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/9vek/PayForDeath/HEAD/screenshots/screenshot0.png -------------------------------------------------------------------------------- /screenshots/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/9vek/PayForDeath/HEAD/screenshots/screenshot1.png -------------------------------------------------------------------------------- /screenshots/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/9vek/PayForDeath/HEAD/screenshots/screenshot2.png -------------------------------------------------------------------------------- /screenshots/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/9vek/PayForDeath/HEAD/screenshots/screenshot3.png -------------------------------------------------------------------------------- /screenshots/screenshot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/9vek/PayForDeath/HEAD/screenshots/screenshot4.png -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: PayForDeath 2 | version: ${project.version} 3 | main: cn.kevyn.payfordeath.PayForDeath 4 | api-version: 1.18 5 | author: kevyn 6 | description: let your players pay for keeping inventory and level when death 7 | depend: [Vault] 8 | website: kevyn.cn 9 | permissions: 10 | pfd.reload: 11 | default: op 12 | pfd.ignore.*: 13 | default: false 14 | pfd.exempt.*: 15 | default: false 16 | commands: 17 | pfd-reload: 18 | description: PayForDeath's reload command 19 | permission: pfd.reload 20 | -------------------------------------------------------------------------------- /src/main/java/cn/kevyn/payfordeath/PFDCommand.java: -------------------------------------------------------------------------------- 1 | package cn.kevyn.payfordeath; 2 | 3 | import org.bukkit.command.Command; 4 | import org.bukkit.command.CommandExecutor; 5 | import org.bukkit.command.CommandSender; 6 | 7 | public class PFDCommand implements CommandExecutor { 8 | 9 | 10 | @Override 11 | public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) { 12 | 13 | if (command.getName().equals("pfd-reload")) { 14 | PayForDeath.INSTANCE.onReload(); 15 | return true; 16 | } 17 | 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Kevyn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | default: 2 | enable: false 3 | # formulas 4 | # supported operations: + - * / () 5 | # placeholders you can use: 6 | # : the player's level 7 | # : the player's balance 8 | # invalid formula will always return 0.0 9 | # see the below for an example 10 | deduct-formula: 0 11 | # -1 to switch off this check 12 | upper-limit-formula: -1 13 | keep-inventory: false 14 | keep-level: false 15 | clear-instead-of-drop: false 16 | notice-by-action-bar: false 17 | notice-by-console: false 18 | # placeholders you can use in messages: 19 | # : the player's name 20 | # : the world the player death 21 | # : the world the player respawn 22 | # : the money deducted 23 | # : the player's balance before the deduction 24 | # : the player's balance after the deduction 25 | kept-message: §l§byou paid §e$§b, inventory and levels kept。now u have §e$ §9^_^ 26 | unkept-message: §l§cyou didn't have §e$§c, inventory and levels lost in §e §9x_x 27 | exempt-message: §l§eyou have the privilege to keep items and levels for free in §e §9^_^ 28 | ignore-message: §l§7PFD's features are disabled on you 29 | 30 | # write your world-specific config below 31 | # just write the settings you want to override in this world 32 | # missing settings will read from default 33 | exampleResourceWorld: 34 | enable: true 35 | deduct-formula: 10 + 10 * 36 | upper-limit-formula: 10 + 0.5 * 37 | keep-inventory: true 38 | keep-level: true 39 | notice-by-action-bar: true 40 | 41 | exampleMainWorld: 42 | enable: true 43 | keep-inventory: true 44 | keep-level: true 45 | notice-by-action-bar: true 46 | kept-message: §l§bFree to keep all things in main world §9^_^ 47 | 48 | exampleDangerWorld: 49 | enable: true 50 | notice-by-action-bar: true 51 | kept-message: §l§cpay for death is not allowed in this world §9c_c -------------------------------------------------------------------------------- /src/main/java/cn/kevyn/payfordeath/utils/ConfigHelper.java: -------------------------------------------------------------------------------- 1 | package cn.kevyn.payfordeath.utils; 2 | 3 | import org.bukkit.configuration.Configuration; 4 | import org.bukkit.configuration.ConfigurationSection; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | public class ConfigHelper { 11 | 12 | private static ConfigHelper instance; 13 | public static ConfigHelper getInstance(Configuration config, boolean initDefault) { 14 | 15 | instance = new ConfigHelper(config, initDefault); 16 | return instance; 17 | 18 | } 19 | 20 | private Configuration config; 21 | private Map sections; 22 | 23 | private ConfigHelper (Configuration config, boolean initDefault) { 24 | 25 | this.config = config; 26 | this.sections = new HashMap<>(); 27 | 28 | if (initDefault) { 29 | loadSection("default"); 30 | } 31 | 32 | } 33 | 34 | public ConfigurationSection getSection(String name) { 35 | 36 | if (!sections.containsKey(name)) { 37 | loadSection(name); 38 | } 39 | 40 | return sections.get(name); 41 | } 42 | 43 | private void loadSection(String name) { 44 | 45 | ConfigurationSection section = config.getConfigurationSection(name); 46 | 47 | if (section == null) { 48 | sections.put(name, sections.get("default")); 49 | return; 50 | } 51 | 52 | if (!name.equals("default")) { 53 | 54 | ConfigurationSection defaultSection = getSection("default"); 55 | Set defaultKeys = defaultSection.getKeys(true); 56 | for (String key : defaultKeys) { 57 | if (section.get(key) == null) { 58 | section.set(key, defaultSection.get(key)); 59 | } 60 | } 61 | 62 | } 63 | 64 | sections.put(name, section); 65 | 66 | } 67 | 68 | public Configuration getConfig() { 69 | return config; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/cn/kevyn/payfordeath/utils/PFDBean.java: -------------------------------------------------------------------------------- 1 | package cn.kevyn.payfordeath.utils; 2 | 3 | import cn.kevyn.payfordeath.PayForDeath; 4 | import org.bukkit.configuration.ConfigurationSection; 5 | import org.bukkit.entity.Player; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class PFDBean { 11 | 12 | private static List pfdBeans = new ArrayList<>(); 13 | 14 | public static PFDBean get(Player player) { 15 | for (PFDBean pfdBean : pfdBeans) { 16 | if (pfdBean.getPlayer() == player){ 17 | return pfdBean; 18 | } 19 | } 20 | return null; 21 | } 22 | 23 | public static void add(PFDBean pfdBean) { 24 | pfdBeans.add(pfdBean); 25 | } 26 | 27 | public static void remove(PFDBean pfdBean) { 28 | pfdBeans.remove(pfdBean); 29 | } 30 | 31 | private Player player; 32 | private String deathWorldName; 33 | private String status; 34 | private double balance; 35 | private double ransom; 36 | private ConfigurationSection config; 37 | 38 | public Player getPlayer() { 39 | return player; 40 | } 41 | 42 | public void setPlayer(Player player) { 43 | this.player = player; 44 | this.deathWorldName = player.getWorld().getName(); 45 | this.balance = PayForDeath.INSTANCE.getEconomy().getBalance(player); 46 | this.config = PayForDeath.INSTANCE.getConfigHelper().getSection(deathWorldName); 47 | } 48 | 49 | public String getStatus() { 50 | return status; 51 | } 52 | 53 | public void setStatus(String status) { 54 | this.status = status; 55 | } 56 | 57 | public double getBalance() { 58 | return balance; 59 | } 60 | 61 | public double getRansom() { 62 | return ransom; 63 | } 64 | 65 | public void setRansom(double ransom) { 66 | this.ransom = ransom; 67 | } 68 | 69 | public String getDeathWorldName() { 70 | return deathWorldName; 71 | } 72 | 73 | public ConfigurationSection getConfig() { 74 | return config; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | .vscode/ 4 | 5 | *.iml 6 | *.ipr 7 | *.iws 8 | 9 | # IntelliJ 10 | out/ 11 | 12 | # Compiled class file 13 | *.class 14 | 15 | # Log file 16 | *.log 17 | 18 | # BlueJ files 19 | *.ctxt 20 | 21 | # Package Files # 22 | *.jar 23 | *.war 24 | *.nar 25 | *.ear 26 | *.zip 27 | *.tar.gz 28 | *.rar 29 | 30 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 31 | hs_err_pid* 32 | 33 | *~ 34 | 35 | # temporary files which can be created if a process still has a handle open of a deleted file 36 | .fuse_hidden* 37 | 38 | # KDE directory preferences 39 | .directory 40 | 41 | # Linux trash folder which might appear on any partition or disk 42 | .Trash-* 43 | 44 | # .nfs files are created when an open file is removed but is still being accessed 45 | .nfs* 46 | 47 | # General 48 | .DS_Store 49 | .AppleDouble 50 | .LSOverride 51 | 52 | # Icon must end with two \r 53 | Icon 54 | 55 | # Thumbnails 56 | ._* 57 | 58 | # Files that might appear in the root of a volume 59 | .DocumentRevisions-V100 60 | .fseventsd 61 | .Spotlight-V100 62 | .TemporaryItems 63 | .Trashes 64 | .VolumeIcon.icns 65 | .com.apple.timemachine.donotpresent 66 | 67 | # Directories potentially created on remote AFP share 68 | .AppleDB 69 | .AppleDesktop 70 | Network Trash Folder 71 | Temporary Items 72 | .apdisk 73 | 74 | # Windows thumbnail cache files 75 | Thumbs.db 76 | Thumbs.db:encryptable 77 | ehthumbs.db 78 | ehthumbs_vista.db 79 | 80 | # Dump file 81 | *.stackdump 82 | 83 | # Folder config file 84 | [Dd]esktop.ini 85 | 86 | # Recycle Bin used on file shares 87 | $RECYCLE.BIN/ 88 | 89 | # Windows Installer files 90 | *.cab 91 | *.msi 92 | *.msix 93 | *.msm 94 | *.msp 95 | 96 | # Windows shortcuts 97 | *.lnk 98 | 99 | target/ 100 | 101 | pom.xml.tag 102 | pom.xml.releaseBackup 103 | pom.xml.versionsBackup 104 | pom.xml.next 105 | 106 | release.properties 107 | dependency-reduced-pom.xml 108 | buildNumber.properties 109 | .mvn/timing.properties 110 | .mvn/wrapper/maven-wrapper.jar 111 | .flattened-pom.xml 112 | 113 | # Common working directory 114 | run/ 115 | -------------------------------------------------------------------------------- /src/main/java/cn/kevyn/payfordeath/utils/StringFormula.java: -------------------------------------------------------------------------------- 1 | package cn.kevyn.payfordeath.utils; 2 | 3 | public class StringFormula { 4 | 5 | private static boolean isNumber(String str) { 6 | 7 | for (int i = 0; i < str.length(); i++) { 8 | if (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '.' && str.charAt(i) != ' ') { 9 | return false; 10 | } 11 | } 12 | return true; 13 | } 14 | 15 | public static Double getResult(String str) { 16 | 17 | // 递归头 18 | if (str.isEmpty() || isNumber(str)) { 19 | return str.isEmpty() ? 0 : Double.parseDouble(str); 20 | } 21 | 22 | //递归体 23 | if (str.contains(")")) { 24 | // 最后一个左括号 25 | int lIndex = str.lastIndexOf("("); 26 | // 对于的右括号 27 | int rIndex = str.indexOf(")", lIndex); 28 | return getResult(str.substring(0, lIndex) + getResult(str.substring(lIndex + 1, rIndex)) + str.substring(rIndex + 1)); 29 | } 30 | if (str.contains("+")) { 31 | int index = str.lastIndexOf("+"); 32 | return getResult(str.substring(0, index)) + getResult(str.substring(index + 1)); 33 | } 34 | if (str.contains("-")) { 35 | int index = str.lastIndexOf("-"); 36 | return getResult(str.substring(0, index)) - getResult(str.substring(index + 1)); 37 | } 38 | if (str.contains("*")) { 39 | int index = str.lastIndexOf("*"); 40 | return getResult(str.substring(0, index)) * getResult(str.substring(index + 1)); 41 | } 42 | if (str.contains("/")) { 43 | int index = str.lastIndexOf("/"); 44 | return getResult(str.substring(0, index)) / getResult(str.substring(index + 1)); 45 | } 46 | 47 | // 出错 48 | return 0.0; 49 | } 50 | 51 | public static double calculate(String formula, PFDBean pfdBean) { 52 | String lv = pfdBean.getPlayer().getLevel()+""; 53 | String bal = pfdBean.getBalance()+""; 54 | double ransom = getResult(formula.replace("", lv).replace("", bal)); 55 | return ransom > 0 ? ransom : 0; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | cn.kevyn 6 | PayForDeath 7 | 2.7 8 | jar 9 | 10 | PayForDeath 11 | 12 | let your players pay for keeping inventory and level when death 13 | 14 | 17 15 | UTF-8 16 | 17 | kevyn.cn 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 3.8.1 25 | 26 | 1.8 27 | 1.8 28 | 29 | 30 | 31 | org.apache.maven.plugins 32 | maven-shade-plugin 33 | 3.2.4 34 | 35 | 36 | package 37 | 38 | shade 39 | 40 | 41 | false 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | src/main/resources 50 | true 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | spigotmc-repo 59 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 60 | 61 | 62 | 63 | sonatype 64 | https://oss.sonatype.org/content/groups/public/ 65 | 66 | 67 | 68 | minecraft 69 | https://nexus.hc.to/content/repositories/pub_releases/ 70 | 71 | 72 | 73 | 74 | 75 | 76 | org.spigotmc 77 | spigot-api 78 | 1.19-R0.1-SNAPSHOT 79 | provided 80 | 81 | 82 | net.milkbowl.vault 83 | VaultAPI 84 | 1.7 85 | provided 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/main/java/cn/kevyn/payfordeath/PayForDeath.java: -------------------------------------------------------------------------------- 1 | package cn.kevyn.payfordeath; 2 | 3 | import cn.kevyn.payfordeath.utils.ConfigHelper; 4 | import net.milkbowl.vault.economy.Economy; 5 | import net.milkbowl.vault.permission.Permission; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.plugin.RegisteredServiceProvider; 8 | import org.bukkit.plugin.java.JavaPlugin; 9 | 10 | public class PayForDeath extends JavaPlugin { 11 | 12 | public static PayForDeath INSTANCE; 13 | 14 | public PayForDeath() { 15 | PayForDeath.INSTANCE = this; 16 | } 17 | 18 | public final String ENABLE = "[PayForDeath]" + ChatColor.BLUE + " plugin is now enabled!"; 19 | public final String DISABLE = "[PayForDeath]" + ChatColor.RED + " plugin is now disabled!"; 20 | public final String RELOAD = "[PayForDeath]" + ChatColor.GREEN + " config is now successfully reloaded!"; 21 | 22 | private ConfigHelper configHelper; 23 | private Economy economy; 24 | private Permission permissions; 25 | 26 | @Override 27 | public void onEnable() { 28 | super.onEnable(); 29 | 30 | saveDefaultConfig(); 31 | configHelper = ConfigHelper.getInstance(getConfig(), true); 32 | 33 | if (dependenciesReady()) { 34 | if (permissions == null) { 35 | getServer().getConsoleSender().sendMessage(ChatColor.RED + "[PayForDeath] permissions provider not found" ); 36 | } 37 | } 38 | else { 39 | getServer().getPluginManager().disablePlugin(this); 40 | return; 41 | } 42 | 43 | this.getCommand("pfd-reload").setExecutor(new PFDCommand()); 44 | this.getServer().getPluginManager().registerEvents(new PFDListener(), this); 45 | this.getServer().getConsoleSender().sendMessage(ENABLE); 46 | 47 | } 48 | 49 | @Override 50 | public void onDisable() { 51 | super.onDisable(); 52 | this.getServer().getConsoleSender().sendMessage(DISABLE); 53 | } 54 | 55 | public void onReload() { 56 | reloadConfig(); 57 | configHelper = ConfigHelper.getInstance(getConfig(), true); 58 | getServer().getConsoleSender().sendMessage(RELOAD); 59 | } 60 | 61 | private boolean dependenciesReady() { 62 | 63 | if (getServer().getPluginManager().getPlugin("Vault") == null) { 64 | return false; 65 | } 66 | 67 | RegisteredServiceProvider rspe = getServer().getServicesManager().getRegistration(Economy.class); 68 | RegisteredServiceProvider rspp = getServer().getServicesManager().getRegistration(Permission.class); 69 | 70 | if (rspe == null) { 71 | getServer().getConsoleSender().sendMessage(ChatColor.RED + "[PayForDeath] Economy provider is required but not found" ); 72 | return false; 73 | } 74 | 75 | economy = rspe.getProvider(); 76 | 77 | if (economy == null) { 78 | getServer().getConsoleSender().sendMessage(ChatColor.RED + "[PayForDeath] Economy provider is required but not found" ); 79 | return false; 80 | } 81 | 82 | permissions = rspp == null ? null : rspp.getProvider(); 83 | 84 | return true; 85 | 86 | } 87 | 88 | public Economy getEconomy() { 89 | return economy; 90 | } 91 | 92 | public Permission getPermissions() { 93 | return permissions; 94 | } 95 | 96 | public ConfigHelper getConfigHelper() { 97 | return configHelper; 98 | } 99 | 100 | public static void main(String[] args) { 101 | 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PayForDeath 2 | a minecraft spigot plugin that add death penalty feature to the server 3 | 4 | SpigotMC release: (https://www.spigotmc.org/resources/payfordeath.94328/) 5 | 6 | MCBBS release: <\<机制\>蛋挞君的死亡赎金——让玩家花钱赎回死亡掉落的等级和物品吧!<1.12-1.17>>(https://www.mcbbs.net/thread-1213517-1-1.html) 7 | 8 | ## INTRODUCTION 9 | 10 | Many death penalty plugins are either too heavy or outdated, and Kevyn's PayForDeath is a lightweight death penalty plugin base on Vault's money system. 11 | 12 | The main feature is very simple: **Players must have enough money to avoid dropping levels and items on death.** It supports different configurations in different world, and the money deduction node can be completely customized. 13 | 14 | This provides an elegant way to increase the cost of death, at the same time, it can enrich the economic system of your server, so that the player's money can be used for one more purpose. 15 | 16 | ![IMG](screenshots/screenshot0.png) 17 | 18 | ![IMG](screenshots/screenshot1.png) 19 | 20 | ![IMG](screenshots/screenshot2.png) 21 | 22 | ![IMG](screenshots/screenshot3.png) 23 | 24 | ![IMG](screenshots/screenshot4.png) 25 | 26 | 27 | 28 | ## FEATURES 29 | 30 | - You can set how much a player needs to pay to keep his levels and items 31 | 32 | - Configure kept content: item, level, or both 33 | 34 | - Calculate ransom by a Formula you write 35 | 36 | - The amount of money can increase with the **player's level** or the **player's balance** 37 | 38 | - Customize **messages' text** , send by **action bar** or **console** 39 | 40 | - You can configure **clearing** items and exp instead of **dropping** them 41 | 42 | - Give a **different configuration** to each world 43 | 44 | - **Exempt** (free to keep all) or **ignore** (disable this plugin on) a player 45 | 46 | - Messages now support some placeholders **** 47 | 48 | - Read the configuration file for more details (sorry no English-comment version in the jar, you can find a English version below) 49 | 50 | 51 | 52 | ## INSTALLATION 53 | 54 | - Drag to plugins folder 55 | 56 | - **Dependencies**: 57 | 58 | - **Vault** 59 | - Any **economy plugin** 60 | - Any **permissions management plugin**. 61 | - **EssentialX + LuckPerms** is one of the best choices 62 | 63 | - Please **fully test before use**. If you encounter any problem, please send me feedback 64 | 65 | - If you have used the old version of this plugin before, **please delete the configuration file of the old version manually** before updating 66 | 67 | - The default configuration of the plugin is equivalent to turning off all those functions. Please adjust the configuration yourself 68 | 69 | - Recommended to install with online rewards, kill mobs rewards or other money-rewards plugins :) 70 | 71 | 72 | 73 | ## USAGES 74 | 75 | - **Commands**: 76 | 77 | ```yaml 78 | # reload the plugin's config file 79 | # you can only use it in console 80 | /pfd-reload 81 | ``` 82 | 83 | - **Permissions**: 84 | 85 | ```yaml 86 | # give it to player who you want to save items and levels completely free of charge 87 | pfd.exempt. 88 | 89 | # give it to player who you want to disable this plugin's features on 90 | pfd.ignore. 91 | ``` 92 | 93 | - **Configuration**: 94 | 95 | ```yaml 96 | default: 97 | enable: false 98 | # formulas 99 | # supported operations: + - * / () 100 | # placeholders you can use: 101 | # : the player's level 102 | # : the player's balance 103 | # invalid formula will always return 0.0 104 | # see the below for an example 105 | deduct-formula: 0 106 | # -1 to switch off this check 107 | upper-limit-formula: -1 108 | keep-inventory: false 109 | keep-level: false 110 | clear-instead-of-drop: false 111 | notice-by-action-bar: false 112 | notice-by-console: false 113 | # placeholders you can use in messages: 114 | # : the player's name 115 | # : the world the player death 116 | # : the world the player respawn 117 | # : the money deducted 118 | # : the player's balance before the deduction 119 | # : the player's balance after the deduction 120 | kept-message: §l§byou paid §e$§b, inventory and levels kept。now u have §e$ §9^_^ 121 | unkept-message: §l§cyou didn't have §e$§c, inventory and levels lost in §e §9x_x 122 | exempt-message: §l§eyou have the privilege to keep items and levels for free in §e §9^_^ 123 | 124 | # write your world-specific config below 125 | # just write the settings you want to override in this world 126 | # missing settings will read from default 127 | exampleResourceWorld: 128 | enable: true 129 | deduct-formula: 10 + 10 * 130 | upper-limit-formula: 10 + 0.5 * 131 | keep-inventory: true 132 | keep-level: true 133 | notice-by-action-bar: true 134 | 135 | exampleMainWorld: 136 | enable: true 137 | keep-inventory: true 138 | keep-level: true 139 | notice-by-action-bar: true 140 | kept-message: §l§bFree to keep all things in main world §9^_^ 141 | 142 | exampleDangerWorld: 143 | enable: true 144 | notice-by-action-bar: true 145 | kept-message: §l§cpay for death is not allowed in this world §9c_c 146 | ``` 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /src/main/java/cn/kevyn/payfordeath/PFDListener.java: -------------------------------------------------------------------------------- 1 | package cn.kevyn.payfordeath; 2 | 3 | import cn.kevyn.payfordeath.utils.PFDBean; 4 | import cn.kevyn.payfordeath.utils.StringFormula; 5 | import net.md_5.bungee.api.ChatMessageType; 6 | import net.md_5.bungee.api.chat.TextComponent; 7 | import net.milkbowl.vault.economy.Economy; 8 | import net.milkbowl.vault.permission.Permission; 9 | import org.bukkit.configuration.ConfigurationSection; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.event.EventHandler; 12 | import org.bukkit.event.Listener; 13 | import org.bukkit.event.entity.PlayerDeathEvent; 14 | import org.bukkit.event.player.PlayerRespawnEvent; 15 | 16 | public class PFDListener implements Listener { 17 | 18 | public static PFDListener INSTANCE; 19 | 20 | private Economy economy; 21 | private Permission permission; 22 | 23 | public PFDListener() { 24 | PFDListener.INSTANCE = this; 25 | economy = PayForDeath.INSTANCE.getEconomy(); 26 | permission = PayForDeath.INSTANCE.getPermissions(); 27 | } 28 | 29 | @EventHandler 30 | public void onPlayerDeath(PlayerDeathEvent event) { 31 | 32 | Player player = event.getEntity(); 33 | PFDBean pfdBean = new PFDBean(); 34 | pfdBean.setPlayer(player); 35 | 36 | ConfigurationSection config = pfdBean.getConfig(); 37 | String worldName = pfdBean.getDeathWorldName(); 38 | double balance = pfdBean.getBalance(); 39 | 40 | if (!config.getBoolean("enable")) { 41 | return; 42 | } 43 | 44 | if (permission != null) { 45 | 46 | if (permission.has(player, "pfd.ignore." + worldName) || permission.has(player, "pfd.ignore.*")) { 47 | pfdBean.setStatus("ignore"); 48 | } 49 | 50 | else if (permission.has(player, "pfd.exempt." + worldName) || permission.has(player, "pfd.exempt.*")) { 51 | event.setKeepInventory(true); 52 | event.setKeepLevel(true); 53 | event.getDrops().clear(); 54 | event.setDroppedExp(0); 55 | pfdBean.setStatus("exempt"); 56 | } 57 | 58 | } 59 | 60 | if (pfdBean.getStatus() == null) { 61 | 62 | String deductFormula = config.getString("deduct-formula"); 63 | double ransom = StringFormula.calculate(deductFormula, pfdBean); 64 | 65 | String upperLimitFormula = config.getString("upper-limit-formula"); 66 | 67 | if (!upperLimitFormula.equals("-1")) { 68 | 69 | double max = StringFormula.calculate(upperLimitFormula, pfdBean); 70 | 71 | if (max >= 0) { 72 | ransom = ransom < max ? ransom : max; 73 | } 74 | 75 | } 76 | 77 | pfdBean.setRansom(ransom); 78 | 79 | if (balance >= ransom || ransom == 0) { 80 | 81 | if (config.getBoolean("keep-inventory")) { 82 | event.setKeepInventory(true); 83 | event.getDrops().clear(); 84 | } 85 | 86 | if (config.getBoolean("keep-level")) { 87 | event.setKeepLevel(true); 88 | event.setDroppedExp(0); 89 | } 90 | 91 | economy.withdrawPlayer(player, ransom); 92 | pfdBean.setStatus("kept"); 93 | 94 | } else { 95 | 96 | event.setKeepInventory(false); 97 | event.setKeepLevel(false); 98 | pfdBean.setStatus("unkept"); 99 | 100 | if (config.getBoolean("clear-instead-of-drop")) { 101 | event.getDrops().clear(); 102 | event.setDroppedExp(0); 103 | } 104 | 105 | } 106 | } 107 | 108 | PFDBean.add(pfdBean); 109 | 110 | } 111 | 112 | @EventHandler 113 | public void onPlayerRespawn(PlayerRespawnEvent event) { 114 | Player player = event.getPlayer(); 115 | PFDBean pfdBean = PFDBean.get(player); 116 | 117 | if (pfdBean == null) { 118 | return; 119 | } 120 | 121 | noticePlayer(pfdBean); 122 | 123 | PFDBean.remove(pfdBean); 124 | 125 | } 126 | 127 | private void noticePlayer(PFDBean pfdBean) { 128 | Player player = pfdBean.getPlayer(); 129 | ConfigurationSection config = pfdBean.getConfig(); 130 | String playerName = player.getName(); 131 | String deathWorld = pfdBean.getDeathWorldName(); 132 | String respawnWorld = player.getWorld().getName(); 133 | String oldBalance = String.format("%.2f", pfdBean.getBalance()); 134 | String ransom = String.format("%.2f", pfdBean.getRansom()); 135 | String newBalance = String.format("%.2f", PayForDeath.INSTANCE.getEconomy().getBalance(player)); 136 | String message = config.getString(pfdBean.getStatus() + "-message"); 137 | if (message == null) { 138 | message = ""; 139 | } 140 | message = message.replace("", playerName) 141 | .replace("", deathWorld) 142 | .replace("", respawnWorld) 143 | .replace("", oldBalance) 144 | .replace("", ransom) 145 | .replace("", newBalance); 146 | 147 | if (config.getBoolean("notice-by-action-bar")) { 148 | TextComponent textComponent = new TextComponent(message); 149 | player.spigot().sendMessage(ChatMessageType.ACTION_BAR, textComponent); 150 | } 151 | if (config.getBoolean("notice-by-console")) { 152 | player.sendMessage(message); 153 | } 154 | 155 | } 156 | 157 | } 158 | --------------------------------------------------------------------------------