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