1.0.0
First Version.
This commit is contained in:
commit
0ed8e725e7
11 files changed
+1009
No files matched your search
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.rsscripting</groupId>
|
||||
<artifactId>rs-disenchanter</artifactId>
|
||||
<name>RS-DISenchanter</name>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<defaultGoal>clean package</defaultGoal>
|
||||
|
||||
<plugins>
|
||||
|
||||
<!-- Java Compiler -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Create the final plugin JAR -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Rename final JAR: 0.1.0 -> 0-1-0 -->
|
||||
<!-- Rename final JAR: 0.1.0 -> 0-1-0 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>rename-final-jar</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<move todir="${project.build.directory}" failonerror="true">
|
||||
<fileset dir="${project.build.directory}">
|
||||
<include name="${project.build.finalName}.jar"/>
|
||||
</fileset>
|
||||
<mapper type="regexp"
|
||||
from="rs-disenchanter-(.*)\.jar"
|
||||
to="RS-DISenchanter-\1.jar"/>
|
||||
</move>
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
<!-- Resource filtering allows plugin.yml to use ${project.version} -->
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>papermc-repo</id>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.21.11-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="minecraft" name="Minecraft">
|
||||
<configuration>
|
||||
<autoDetectTypes>
|
||||
<platformType>PAPER</platformType>
|
||||
</autoDetectTypes>
|
||||
<projectReimportVersion>1</projectReimportVersion>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.rsscripting.rsdisenchanter;
|
||||
|
||||
import com.rsscripting.rsdisenchanter.command.DisenchantCommand;
|
||||
import com.rsscripting.rsdisenchanter.language.LanguageManager;
|
||||
import com.rsscripting.rsdisenchanter.listener.DisenchanterListener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public final class RSDISenchanter extends JavaPlugin {
|
||||
|
||||
private LanguageManager languageManager;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
saveDefaultConfig();
|
||||
|
||||
languageManager = new LanguageManager(this);
|
||||
languageManager.load();
|
||||
|
||||
getCommand("disenchant").setExecutor(new DisenchantCommand(this));
|
||||
|
||||
getServer().getPluginManager().registerEvents(
|
||||
new DisenchanterListener(this),
|
||||
this
|
||||
);
|
||||
|
||||
getLogger().info("RS-DISenchanter enabled.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLogger().info("RS-DISenchanter disabled.");
|
||||
}
|
||||
|
||||
public LanguageManager getLanguageManager() {
|
||||
return languageManager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.rsscripting.rsdisenchanter.command;
|
||||
|
||||
import com.rsscripting.rsdisenchanter.RSDISenchanter;
|
||||
import com.rsscripting.rsdisenchanter.gui.DisenchanterGUI;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class DisenchantCommand implements CommandExecutor {
|
||||
|
||||
private final RSDISenchanter plugin;
|
||||
|
||||
public DisenchantCommand(RSDISenchanter plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(
|
||||
CommandSender sender,
|
||||
Command command,
|
||||
String label,
|
||||
String[] args
|
||||
) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage(
|
||||
plugin.getLanguageManager().get("messages.general.player-only")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("rsdisenchanter.use")) {
|
||||
player.sendMessage(
|
||||
plugin.getLanguageManager().get("messages.general.no-permission")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
new DisenchanterGUI(plugin).open(player);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.rsscripting.rsdisenchanter.enchantment;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EnchantmentManager {
|
||||
|
||||
/**
|
||||
* Gets all enchantments on an item.
|
||||
*/
|
||||
public Map<Enchantment, Integer> getEnchantments(ItemStack item) {
|
||||
Map<Enchantment, Integer> enchantments = new LinkedHashMap<>();
|
||||
|
||||
if (item == null) {
|
||||
return enchantments;
|
||||
}
|
||||
|
||||
if (item.getItemMeta() instanceof EnchantmentStorageMeta bookMeta) {
|
||||
enchantments.putAll(bookMeta.getStoredEnchants());
|
||||
} else {
|
||||
enchantments.putAll(item.getEnchantments());
|
||||
}
|
||||
|
||||
return enchantments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets only cursed enchantments on an item.
|
||||
*/
|
||||
public Map<Enchantment, Integer> getCurses(ItemStack item) {
|
||||
Map<Enchantment, Integer> curses = new LinkedHashMap<>();
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> entry :
|
||||
getEnchantments(item).entrySet()) {
|
||||
|
||||
if (entry.getKey().isCursed()) {
|
||||
curses.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return curses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all non-cursed enchantments on an item.
|
||||
*/
|
||||
public Map<Enchantment, Integer> getNormalEnchantments(ItemStack item) {
|
||||
Map<Enchantment, Integer> enchantments = new LinkedHashMap<>();
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> entry :
|
||||
getEnchantments(item).entrySet()) {
|
||||
|
||||
if (!entry.getKey().isCursed()) {
|
||||
enchantments.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return enchantments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a standard Minecraft enchanted book.
|
||||
*/
|
||||
public ItemStack createEnchantedBook(
|
||||
Enchantment enchantment,
|
||||
int level
|
||||
) {
|
||||
ItemStack book = new ItemStack(Material.ENCHANTED_BOOK);
|
||||
|
||||
EnchantmentStorageMeta meta =
|
||||
(EnchantmentStorageMeta) book.getItemMeta();
|
||||
|
||||
if (meta != null) {
|
||||
meta.addStoredEnchant(enchantment, level, true);
|
||||
book.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return book;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which enchantments should currently be displayed.
|
||||
*
|
||||
* Curses always take priority. Normal enchantments are displayed
|
||||
* only after all curses have been removed.
|
||||
*/
|
||||
public Map<Enchantment, Integer> getDisplayEnchantments(ItemStack item) {
|
||||
Map<Enchantment, Integer> curses = getCurses(item);
|
||||
|
||||
if (!curses.isEmpty()) {
|
||||
return curses;
|
||||
}
|
||||
|
||||
return getNormalEnchantments(item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.rsscripting.rsdisenchanter.gui;
|
||||
|
||||
import com.rsscripting.rsdisenchanter.RSDISenchanter;
|
||||
import com.rsscripting.rsdisenchanter.enchantment.EnchantmentManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import java.util.HashMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DisenchanterGUI implements InventoryHolder {
|
||||
|
||||
private final RSDISenchanter plugin;
|
||||
private final Inventory inventory;
|
||||
private final Map<Enchantment, Integer> removedCurseBooks = new HashMap<>();
|
||||
|
||||
public DisenchanterGUI(RSDISenchanter plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
String title = plugin.getLanguageManager()
|
||||
.get("gui.titles.disenchanter");
|
||||
|
||||
inventory = Bukkit.createInventory(this, 27, title);
|
||||
|
||||
setupInventory();
|
||||
}
|
||||
|
||||
private void setupInventory() {
|
||||
ItemStack glass = createGlassPane();
|
||||
|
||||
// Left 3x3 border
|
||||
inventory.setItem(0, glass);
|
||||
inventory.setItem(1, glass);
|
||||
inventory.setItem(2, glass);
|
||||
|
||||
inventory.setItem(9, glass);
|
||||
inventory.setItem(11, glass);
|
||||
|
||||
inventory.setItem(18, glass);
|
||||
inventory.setItem(19, glass);
|
||||
inventory.setItem(20, glass);
|
||||
}
|
||||
|
||||
private ItemStack createGlassPane() {
|
||||
ItemStack item = new ItemStack(Material.GRAY_STAINED_GLASS_PANE);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
if (meta != null) {
|
||||
meta.setDisplayName(
|
||||
plugin.getLanguageManager()
|
||||
.get("items.gui.glass-pane.name")
|
||||
);
|
||||
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public void open(Player player) {
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
|
||||
public RSDISenchanter getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory getInventory() {
|
||||
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public void displayEnchantments(
|
||||
Map<Enchantment, Integer> enchantments,
|
||||
EnchantmentManager enchantmentManager
|
||||
) {
|
||||
clearBookSlots();
|
||||
|
||||
int[] bookSlots = {
|
||||
3, 4, 5, 6, 7, 8,
|
||||
12, 13, 14, 15, 16, 17,
|
||||
21, 22, 23, 24, 25, 26
|
||||
};
|
||||
|
||||
int slotIndex = 0;
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
|
||||
|
||||
if (slotIndex >= bookSlots.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
ItemStack book = enchantmentManager.createEnchantedBook(
|
||||
entry.getKey(),
|
||||
entry.getValue()
|
||||
);
|
||||
|
||||
inventory.setItem(bookSlots[slotIndex], book);
|
||||
slotIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
public void clearBookSlots() {
|
||||
int[] bookSlots = {
|
||||
3, 4, 5, 6, 7, 8,
|
||||
12, 13, 14, 15, 16, 17,
|
||||
21, 22, 23, 24, 25, 26
|
||||
};
|
||||
|
||||
for (int slot : bookSlots) {
|
||||
inventory.setItem(slot, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void recordRemovedCurse(Enchantment enchantment) {
|
||||
removedCurseBooks.merge(enchantment, 1, Integer::sum);
|
||||
}
|
||||
|
||||
public Map<Enchantment, Integer> getRemovedCurseBooks() {
|
||||
return new HashMap<>(removedCurseBooks);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.rsscripting.rsdisenchanter.language;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
public class LanguageManager {
|
||||
|
||||
private final JavaPlugin plugin;
|
||||
private FileConfiguration language;
|
||||
|
||||
public LanguageManager(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
String languageName = plugin.getConfig().getString("language", "en_us");
|
||||
|
||||
File languageFolder = new File(plugin.getDataFolder(), "language");
|
||||
|
||||
if (!languageFolder.exists() && !languageFolder.mkdirs()) {
|
||||
plugin.getLogger().warning("Could not create language folder.");
|
||||
}
|
||||
|
||||
File languageFile = new File(languageFolder, languageName + ".yml");
|
||||
|
||||
if (!languageFile.exists()) {
|
||||
plugin.saveResource("language/" + languageName + ".yml", false);
|
||||
}
|
||||
|
||||
language = YamlConfiguration.loadConfiguration(languageFile);
|
||||
}
|
||||
|
||||
public String get(String path) {
|
||||
if (language == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String message = language.getString(path, "");
|
||||
String prefix = language.getString("prefix", "");
|
||||
|
||||
message = message.replace("{prefix}", prefix);
|
||||
|
||||
return color(message);
|
||||
}
|
||||
|
||||
public String get(String path, Map<String, String> variables) {
|
||||
String message = get(path);
|
||||
|
||||
for (Map.Entry<String, String> entry : variables.entrySet()) {
|
||||
message = message.replace(
|
||||
"{" + entry.getKey() + "}",
|
||||
entry.getValue()
|
||||
);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getEnchantmentName(Enchantment enchantment) {
|
||||
return get("enchantments." + enchantment.getKey().getKey());
|
||||
}
|
||||
|
||||
private String color(String message) {
|
||||
return ChatColor.translateAlternateColorCodes('&', message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
package com.rsscripting.rsdisenchanter.listener;
|
||||
|
||||
import com.rsscripting.rsdisenchanter.RSDISenchanter;
|
||||
import com.rsscripting.rsdisenchanter.enchantment.EnchantmentManager;
|
||||
import com.rsscripting.rsdisenchanter.gui.DisenchanterGUI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class DisenchanterListener implements Listener {
|
||||
|
||||
private final RSDISenchanter plugin;
|
||||
private final EnchantmentManager enchantmentManager;
|
||||
|
||||
public DisenchanterListener(RSDISenchanter plugin) {
|
||||
this.plugin = plugin;
|
||||
this.enchantmentManager = new EnchantmentManager();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (!(event.getInventory().getHolder() instanceof DisenchanterGUI gui)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.isShiftClick()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
int rawSlot = event.getRawSlot();
|
||||
|
||||
// Player inventory.
|
||||
if (rawSlot >= event.getView().getTopInventory().getSize()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Center input slot.
|
||||
if (rawSlot == 10) {
|
||||
if (event.getWhoClicked() instanceof Player player) {
|
||||
Bukkit.getScheduler().runTask(
|
||||
plugin,
|
||||
() -> validateInput(player, gui)
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBookSlot(rawSlot)) {
|
||||
event.setCancelled(true);
|
||||
|
||||
if (!(event.getWhoClicked() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack book = event.getCurrentItem();
|
||||
|
||||
if (book == null || book.getType().isAir()) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleBookClick(player, gui, book, rawSlot);
|
||||
return;
|
||||
}
|
||||
|
||||
// All other GUI slots are protected.
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
if (!(event.getInventory().getHolder() instanceof DisenchanterGUI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(event.getPlayer() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack item = event.getInventory().getItem(10);
|
||||
|
||||
if (item == null || item.getType().isAir()) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.getInventory().setItem(10, null);
|
||||
|
||||
Map<Integer, ItemStack> leftovers = player.getInventory().addItem(item);
|
||||
|
||||
for (ItemStack leftover : leftovers.values()) {
|
||||
player.getWorld().dropItemNaturally(
|
||||
player.getLocation(),
|
||||
leftover
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryDrag(InventoryDragEvent event) {
|
||||
if (!(event.getInventory().getHolder() instanceof DisenchanterGUI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int slot : event.getRawSlots()) {
|
||||
if (slot != 10) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateInput(Player player, DisenchanterGUI gui) {
|
||||
|
||||
ItemStack item = gui.getInventory().getItem(10);
|
||||
|
||||
if (item == null || item.getType().isAir()) {
|
||||
gui.clearBookSlots();
|
||||
return;
|
||||
}
|
||||
|
||||
if (enchantmentManager.getEnchantments(item).isEmpty()) {
|
||||
|
||||
gui.clearBookSlots();
|
||||
|
||||
gui.getInventory().setItem(10, null);
|
||||
|
||||
player.getInventory().addItem(item);
|
||||
|
||||
player.sendMessage(
|
||||
plugin.getLanguageManager()
|
||||
.get("messages.general.no-enchantments")
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gui.displayEnchantments(
|
||||
enchantmentManager.getDisplayEnchantments(item),
|
||||
enchantmentManager
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isBookSlot(int slot) {
|
||||
return slot == 3 || slot == 4 || slot == 5
|
||||
|| slot == 6 || slot == 7 || slot == 8
|
||||
|| slot == 12 || slot == 13 || slot == 14
|
||||
|| slot == 15 || slot == 16 || slot == 17
|
||||
|| slot == 21 || slot == 22 || slot == 23
|
||||
|| slot == 24 || slot == 25 || slot == 26;
|
||||
}
|
||||
|
||||
private void handleBookClick(
|
||||
Player player,
|
||||
DisenchanterGUI gui,
|
||||
ItemStack book,
|
||||
int bookSlot
|
||||
) {
|
||||
if (!(book.getItemMeta() instanceof EnchantmentStorageMeta meta)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<Enchantment, Integer> storedEnchantments =
|
||||
meta.getStoredEnchants();
|
||||
|
||||
if (storedEnchantments.size() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map.Entry<Enchantment, Integer> entry =
|
||||
storedEnchantments.entrySet().iterator().next();
|
||||
|
||||
Enchantment enchantment = entry.getKey();
|
||||
int level = entry.getValue();
|
||||
|
||||
ItemStack item = gui.getInventory().getItem(10);
|
||||
|
||||
if (item == null || item.getType().isAir()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enchantmentManager.getEnchantments(item)
|
||||
.containsKey(enchantment)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enchantment.isCursed()) {
|
||||
handleCurseClick(player, gui, item, enchantment, level, bookSlot);
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack resultBook = enchantmentManager.createEnchantedBook(
|
||||
enchantment,
|
||||
level
|
||||
);
|
||||
|
||||
Map<Integer, ItemStack> leftovers =
|
||||
player.getInventory().addItem(resultBook);
|
||||
|
||||
if (!leftovers.isEmpty()) {
|
||||
player.sendMessage(
|
||||
plugin.getLanguageManager()
|
||||
.get("messages.inventory.full")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
item.removeEnchantment(enchantment);
|
||||
|
||||
gui.getInventory().setItem(10, item);
|
||||
|
||||
// Remove the book that was clicked.
|
||||
gui.getInventory().setItem(bookSlot, null);
|
||||
|
||||
gui.displayEnchantments(
|
||||
enchantmentManager.getDisplayEnchantments(item),
|
||||
enchantmentManager
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
private void handleCurseClick(
|
||||
Player player,
|
||||
DisenchanterGUI gui,
|
||||
ItemStack item,
|
||||
Enchantment enchantment,
|
||||
int level,
|
||||
int bookSlot
|
||||
) {
|
||||
ItemStack resultBook = enchantmentManager.createEnchantedBook(
|
||||
enchantment,
|
||||
level
|
||||
);
|
||||
|
||||
Map<Integer, ItemStack> leftovers =
|
||||
player.getInventory().addItem(resultBook);
|
||||
|
||||
if (!leftovers.isEmpty()) {
|
||||
player.sendMessage(
|
||||
plugin.getLanguageManager()
|
||||
.get("messages.inventory.full")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
double destructionChance =
|
||||
plugin.getConfig().getDouble(
|
||||
"curse-destruction-chance",
|
||||
5.0
|
||||
);
|
||||
|
||||
double roll = Math.random() * 100.0;
|
||||
|
||||
if (roll < destructionChance) {
|
||||
destroyFailedCurseSession(player, gui, item, enchantment);
|
||||
return;
|
||||
}
|
||||
|
||||
// Successful curse removal.
|
||||
item.removeEnchantment(enchantment);
|
||||
|
||||
gui.getInventory().setItem(10, item);
|
||||
gui.getInventory().setItem(bookSlot, null);
|
||||
|
||||
gui.recordRemovedCurse(enchantment);
|
||||
|
||||
String message = plugin.getLanguageManager()
|
||||
.get("messages.curse.removed")
|
||||
.replace(
|
||||
"{enchantment}",
|
||||
plugin.getLanguageManager()
|
||||
.getEnchantmentName(enchantment)
|
||||
)
|
||||
.replace("{item}", getItemName(item));
|
||||
|
||||
player.sendMessage(message);
|
||||
|
||||
gui.displayEnchantments(
|
||||
enchantmentManager.getDisplayEnchantments(item),
|
||||
enchantmentManager
|
||||
);
|
||||
}
|
||||
|
||||
private void destroyFailedCurseSession(
|
||||
Player player,
|
||||
DisenchanterGUI gui,
|
||||
ItemStack item,
|
||||
Enchantment failedCurse
|
||||
) {
|
||||
removeSessionCurseBooks(
|
||||
player,
|
||||
gui.getRemovedCurseBooks()
|
||||
);
|
||||
|
||||
gui.getInventory().setItem(10, null);
|
||||
gui.clearBookSlots();
|
||||
|
||||
String message = plugin.getLanguageManager()
|
||||
.get("messages.curse.failed")
|
||||
.replace(
|
||||
"{enchantment}",
|
||||
plugin.getLanguageManager()
|
||||
.getEnchantmentName(failedCurse)
|
||||
)
|
||||
.replace(
|
||||
"{item}",
|
||||
getItemName(item)
|
||||
);
|
||||
|
||||
player.sendMessage(message);
|
||||
|
||||
player.closeInventory();
|
||||
}
|
||||
|
||||
private void removeSessionCurseBooks(
|
||||
Player player,
|
||||
Map<Enchantment, Integer> booksToRemove
|
||||
) {
|
||||
for (Map.Entry<Enchantment, Integer> entry :
|
||||
booksToRemove.entrySet()) {
|
||||
|
||||
Enchantment enchantment = entry.getKey();
|
||||
int amountToRemove = entry.getValue();
|
||||
|
||||
for (ItemStack inventoryItem :
|
||||
player.getInventory().getContents()) {
|
||||
|
||||
if (amountToRemove <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (inventoryItem == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(inventoryItem.getItemMeta()
|
||||
instanceof EnchantmentStorageMeta meta)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<Enchantment, Integer> stored =
|
||||
meta.getStoredEnchants();
|
||||
|
||||
if (stored.size() != 1
|
||||
|| !stored.containsKey(enchantment)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int removeAmount = Math.min(
|
||||
amountToRemove,
|
||||
inventoryItem.getAmount()
|
||||
);
|
||||
|
||||
inventoryItem.setAmount(
|
||||
inventoryItem.getAmount() - removeAmount
|
||||
);
|
||||
|
||||
amountToRemove -= removeAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getItemName(ItemStack item) {
|
||||
if (item.hasItemMeta()
|
||||
&& item.getItemMeta().hasDisplayName()) {
|
||||
return item.getItemMeta().getDisplayName();
|
||||
}
|
||||
|
||||
String name = item.getType().name()
|
||||
.toLowerCase()
|
||||
.replace('_', ' ');
|
||||
|
||||
return Character.toUpperCase(name.charAt(0))
|
||||
+ name.substring(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# ==========================================
|
||||
# RS-DISenchanter Configuration
|
||||
# ==========================================
|
||||
|
||||
# Language file to use.
|
||||
# The file must exist in the language folder.
|
||||
language: en_us
|
||||
|
||||
# Chance, in percent, that an item is destroyed
|
||||
# when attempting to remove a curse.
|
||||
#
|
||||
# 0 = Never destroyed
|
||||
# 5 = 5% chance
|
||||
# 100 = Always destroyed
|
||||
curse-destruction-chance: 5
|
||||
@@ -0,0 +1,86 @@
|
||||
# ==========================================
|
||||
# RS-DISenchanter - English Language File
|
||||
# ==========================================
|
||||
|
||||
gui:
|
||||
|
||||
titles:
|
||||
disenchanter: "&8Disenchanter"
|
||||
|
||||
|
||||
messages:
|
||||
|
||||
general:
|
||||
no-permission: "{prefix}&cYou do not have permission to use the Disenchanter."
|
||||
player-only: "{prefix}&cThis command can only be used by a player."
|
||||
invalid-item: "{prefix}&cThat item cannot be used in the Disenchanter."
|
||||
no-enchantments: "{prefix}&cThat item has no enchantments to remove."
|
||||
|
||||
|
||||
curse:
|
||||
removed: "{prefix}&aYou successfully removed {enchantment} from the {item}."
|
||||
failed: "{prefix}&cBad luck! You failed to remove {enchantment} from the {item} and the {item} was destroyed."
|
||||
|
||||
disenchant:
|
||||
completed: "{prefix}&aThe enchantment was successfully removed."
|
||||
|
||||
inventory:
|
||||
full: "{prefix}&cYour inventory is full."
|
||||
|
||||
|
||||
items:
|
||||
|
||||
gui:
|
||||
glass-pane:
|
||||
name: " "
|
||||
|
||||
|
||||
errors:
|
||||
|
||||
language:
|
||||
file-not-found: "{prefix}&cThe language file could not be found."
|
||||
invalid-language: "{prefix}&cThe configured language file is invalid."
|
||||
|
||||
enchantments:
|
||||
aqua_affinity: "Aqua Affinity"
|
||||
bane_of_arthropods: "Bane of Arthropods"
|
||||
binding_curse: "Curse of Binding"
|
||||
blast_protection: "Blast Protection"
|
||||
breach: "Breach"
|
||||
channeling: "Channeling"
|
||||
density: "Density"
|
||||
depth_strider: "Depth Strider"
|
||||
efficiency: "Efficiency"
|
||||
feather_falling: "Feather Falling"
|
||||
fire_aspect: "Fire Aspect"
|
||||
fortune: "Fortune"
|
||||
frost_walker: "Frost Walker"
|
||||
impaling: "Impaling"
|
||||
knockback: "Knockback"
|
||||
looting: "Looting"
|
||||
loyalty: "Loyalty"
|
||||
luck_of_the_sea: "Luck of the Sea"
|
||||
lure: "Lure"
|
||||
mending: "Mending"
|
||||
multishot: "Multishot"
|
||||
piercing: "Piercing"
|
||||
power: "Power"
|
||||
projectile_protection: "Projectile Protection"
|
||||
protection: "Protection"
|
||||
punch: "Punch"
|
||||
quick_charge: "Quick Charge"
|
||||
respiration: "Respiration"
|
||||
riptide: "Riptide"
|
||||
sharpness: "Sharpness"
|
||||
silk_touch: "Silk Touch"
|
||||
smite: "Smite"
|
||||
soul_speed: "Soul Speed"
|
||||
sweeping_edge: "Sweeping Edge"
|
||||
swift_sneak: "Swift Sneak"
|
||||
thorns: "Thorns"
|
||||
unbreaking: "Unbreaking"
|
||||
vanishing_curse: "Curse of Vanishing"
|
||||
wind_burst: "Wind Burst"
|
||||
|
||||
|
||||
prefix: "&8[&dDisenchanter&8] "
|
||||
@@ -0,0 +1,17 @@
|
||||
name: RS-DISenchanter
|
||||
version: ${project.version}
|
||||
main: com.rsscripting.rsdisenchanter.RSDISenchanter
|
||||
api-version: '1.21'
|
||||
author: Big Pappa, Atlas
|
||||
description: Enchantment/Cursed Item Removal Tool
|
||||
|
||||
commands:
|
||||
disenchant:
|
||||
description: Opens the Disenchanter
|
||||
usage: /disenchant
|
||||
permission: rsdisenchanter.use
|
||||
|
||||
permissions:
|
||||
rsdisenchanter.use:
|
||||
description: Allows the player to use the Disenchanter
|
||||
default: true
|
||||
Reference in new issue
Block a user