Resolve impasse from Enchanted Books, fixes #1825

This commit is contained in:
PikaMug 2021-10-31 06:26:36 -04:00
parent 5b0ab9c817
commit 095fd8c419
6 changed files with 115 additions and 50 deletions

View File

@ -131,7 +131,7 @@
<dependency>
<groupId>com.github.PikaMug</groupId>
<artifactId>LocaleLib</artifactId>
<version>2.2</version>
<version>2.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>

View File

@ -12,12 +12,14 @@
package me.blackvein.quests;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import java.util.Collection;
import java.util.LinkedList;
/**
* Quest objective data for a specified Quester
*/
public class QuestData {
private final Quester quester;

View File

@ -54,6 +54,7 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.Crops;
import org.jetbrains.annotations.NotNull;
@ -429,7 +430,6 @@ public class Quester implements Comparable<Quester> {
* @param quest The quest to start
* @param ignoreRequirements Whether to ignore Requirements
*/
@SuppressWarnings("deprecation")
public void takeQuest(final Quest quest, final boolean ignoreRequirements) {
if (quest == null) {
return;
@ -1926,6 +1926,67 @@ public class Quester implements Comparable<Quester> {
}
}
/**
* Mark book as enchanted if Quester has such an objective
*
* @param quest The quest for which the item is being enchanted
* @param itemStack The book being enchanted
*/
public void enchantBook(final Quest quest, final ItemStack itemStack,
final Map<Enchantment, Integer> enchantsToAdd) {
int currentIndex = -1;
final LinkedList<Integer> matches = new LinkedList<>();
for (final ItemStack is : getQuestData(quest).itemsEnchanted) {
currentIndex++;
if (is.getItemMeta() instanceof EnchantmentStorageMeta) {
if (((EnchantmentStorageMeta)is.getItemMeta()).getStoredEnchants().equals(enchantsToAdd)) {
matches.add(currentIndex);
}
}
}
if (matches.isEmpty()) {
return;
}
for (final Integer match : matches) {
final LinkedList<ItemStack> items = new LinkedList<>(getQuestData(quest).itemsEnchanted);
final ItemStack found = items.get(match);
final int amount = found.getAmount();
final int toEnchant = getCurrentStage(quest).itemsToEnchant.get(match).getAmount();
final ObjectiveType type = ObjectiveType.ENCHANT_ITEM;
final QuesterPreUpdateObjectiveEvent preEvent = new QuesterPreUpdateObjectiveEvent(this, quest,
new Objective(type, amount, toEnchant));
plugin.getServer().getPluginManager().callEvent(preEvent);
final int newAmount = itemStack.getAmount() + amount;
final Material m = itemStack.getType();
if (amount < toEnchant) {
if (newAmount >= toEnchant) {
found.setAmount(toEnchant);
getQuestData(quest).itemsEnchanted.set(items.indexOf(found), found);
finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null, null,
null, null, null);
// Multiplayer
dispatchMultiplayerObjectives(quest, getCurrentStage(quest), (final Quester q) -> {
q.getQuestData(quest).itemsEnchanted.set(items.indexOf(found), found);
q.finishObjective(quest, new Objective(type, new ItemStack(m, 1), found), null, null, null,
null, null, null, null);
return null;
});
} else {
found.setAmount(newAmount);
getQuestData(quest).itemsEnchanted.set(items.indexOf(found), found);
}
return;
}
final QuesterPostUpdateObjectiveEvent postEvent = new QuesterPostUpdateObjectiveEvent(this, quest,
new Objective(type, itemStack.getAmount() + amount, toEnchant));
plugin.getServer().getPluginManager().callEvent(postEvent);
}
}
/**
* Mark item as enchanted if Quester has such an objective
*
@ -1935,15 +1996,17 @@ public class Quester implements Comparable<Quester> {
public void enchantItem(final Quest quest, final ItemStack itemStack) {
int currentIndex = -1;
final LinkedList<Integer> matches = new LinkedList<>();
for (final ItemStack is : getQuestData(quest).itemsEnchanted) {
currentIndex++;
if (!is.getEnchantments().isEmpty()) {
if (ItemUtil.compareItems(itemStack, is, true) == 0) {
matches.add(currentIndex);
}
} else {
if (ItemUtil.compareItems(itemStack, is, true) == -4) {
matches.add(currentIndex);
if (!itemStack.getType().equals(Material.BOOK)) {
for (final ItemStack is : getQuestData(quest).itemsEnchanted) {
currentIndex++;
if (!is.getEnchantments().isEmpty()) {
if (ItemUtil.compareItems(itemStack, is, true) == 0) {
matches.add(currentIndex);
}
} else {
if (ItemUtil.compareItems(itemStack, is, true) == -4) {
matches.add(currentIndex);
}
}
}
}
@ -2113,7 +2176,6 @@ public class Quester implements Comparable<Quester> {
* @param npc The NPC being delivered to
* @param itemStack The item being delivered
*/
@SuppressWarnings("deprecation")
public void deliverToNPC(final Quest quest, final NPC npc, final ItemStack itemStack) {
if (npc == null) {
return;
@ -3283,12 +3345,12 @@ public class Quester implements Comparable<Quester> {
}
}
if (!quest.getStage(stage).citizensToKill.isEmpty()) {
for (final Integer toKill : quest.getStage(stage).citizensToKill) {
for (final Integer ignored : quest.getStage(stage).citizensToKill) {
data.citizensNumKilled.add(0);
}
}
if (!quest.getStage(stage).mobsToKill.isEmpty()) {
for (final EntityType toKill : quest.getStage(stage).mobsToKill) {
for (final EntityType ignored : quest.getStage(stage).mobsToKill) {
data.mobNumKilled.add(0);
}
}

View File

@ -1266,7 +1266,7 @@ public class Quests extends JavaPlugin implements ConversationAbandonedListener
}
if (getSettings().canTranslateNames() && is.hasItemMeta()) {
// Bukkit version is 1.9+
localeManager.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
localeManager.sendMessage(quester.getPlayer(), message, is.getType(), is.getDurability(),
is.getEnchantments(), is.getItemMeta());
} else if (getSettings().canTranslateNames() && !is.hasItemMeta()
&& Material.getMaterial("LINGERING_POTION") == null) {

View File

@ -153,11 +153,7 @@ public class ItemListener implements Listener {
if (plugin.canUseQuests(evt.getEnchanter().getUniqueId())) {
final ItemStack enchantedItem = evt.getItem().clone();
enchantedItem.setAmount(1);
try {
enchantedItem.addEnchantments(evt.getEnchantsToAdd());
} catch (final IllegalArgumentException e) {
// Ignore
}
enchantedItem.addUnsafeEnchantments(evt.getEnchantsToAdd());
final Quester quester = plugin.getQuester(evt.getEnchanter().getUniqueId());
final ObjectiveType type = ObjectiveType.ENCHANT_ITEM;
final Set<String> dispatchedQuestIDs = new HashSet<>();
@ -168,12 +164,20 @@ public class ItemListener implements Listener {
if (quester.getCurrentQuests().containsKey(quest)
&& quester.getCurrentStage(quest).containsObjective(type)) {
quester.enchantItem(quest, enchantedItem);
if (enchantedItem.getType().equals(Material.BOOK)) {
quester.enchantBook(quest, enchantedItem, evt.getEnchantsToAdd());
} else {
quester.enchantItem(quest, enchantedItem);
}
}
dispatchedQuestIDs.addAll(quester.dispatchMultiplayerEverything(quest, type, (final Quester q, final Quest cq) -> {
if (!dispatchedQuestIDs.contains(cq.getId())) {
q.enchantItem(cq, enchantedItem);
if (enchantedItem.getType().equals(Material.BOOK)) {
q.enchantBook(cq, enchantedItem, evt.getEnchantsToAdd());
} else {
q.enchantItem(cq, enchantedItem);
}
}
return null;
}));

View File

@ -173,13 +173,16 @@ public class ItemUtil {
return -5;
}
if (one.getType().equals(Material.ENCHANTED_BOOK)) {
final EnchantmentStorageMeta esMeta1 = (EnchantmentStorageMeta) one.getItemMeta();
final EnchantmentStorageMeta esMeta2 = (EnchantmentStorageMeta) two.getItemMeta();
if (esMeta1.hasStoredEnchants() && !esMeta2.hasStoredEnchants()) {
return -6;
}
if (!esMeta1.getStoredEnchants().equals(esMeta2.getStoredEnchants())) {
return -6;
if (one.getItemMeta() instanceof EnchantmentStorageMeta
&& two.getItemMeta() instanceof EnchantmentStorageMeta) {
final EnchantmentStorageMeta esMeta1 = (EnchantmentStorageMeta) one.getItemMeta();
final EnchantmentStorageMeta esMeta2 = (EnchantmentStorageMeta) two.getItemMeta();
if (esMeta1.hasStoredEnchants() && !esMeta2.hasStoredEnchants()) {
return -6;
}
if (!esMeta1.getStoredEnchants().equals(esMeta2.getStoredEnchants())) {
return -6;
}
}
}
return 0;
@ -453,45 +456,39 @@ public class ItemUtil {
* @return formatted string, or null if invalid stack
*/
public static String serializeItemStack(final ItemStack is) {
String serial;
final StringBuilder serial;
if (is == null) {
return null;
}
serial = "name-" + is.getType().name();
serial += ":amount-" + is.getAmount();
serial = new StringBuilder("name-" + is.getType().name());
serial.append(":amount-").append(is.getAmount());
if (is.getDurability() != 0) {
serial += ":data-" + is.getDurability();
serial.append(":data-").append(is.getDurability());
}
if (!is.getEnchantments().isEmpty()) {
for (final Entry<Enchantment, Integer> e : is.getEnchantments().entrySet()) {
serial += ":enchantment-" + e.getKey().getName() + " " + e.getValue();
serial.append(":enchantment-").append(e.getKey().getName()).append(" ").append(e.getValue());
}
}
if (is.hasItemMeta()) {
final ItemMeta meta = is.getItemMeta();
if (meta.hasDisplayName()) {
serial += ":displayname-" + meta.getDisplayName();
serial.append(":displayname-").append(meta.getDisplayName());
}
if (meta.hasLore()) {
for (final String s : meta.getLore()) {
serial += ":lore-" + s;
serial.append(":lore-").append(s);
}
}
final LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
map.putAll(meta.serialize());
if (map.containsKey("lore")) {
map.remove("lore");
}
if (map.containsKey("display-name")) {
map.remove("display-name");
}
final LinkedHashMap<String, Object> map = new LinkedHashMap<>(meta.serialize());
map.remove("lore");
map.remove("display-name");
for (final String key : map.keySet()) {
serial += ":" + key + "-" + map.get(key).toString().replace("minecraft:", "minecraft|");
serial.append(":").append(key).append("-").append(map.get(key).toString().replace("minecraft:", "minecraft|"));
}
}
return serial;
return serial.toString();
}
/**
@ -516,7 +513,7 @@ public class ItemUtil {
* @return true display or item name, plus durability and amount, plus enchantments
*/
public static String getDisplayString(final ItemStack is) {
StringBuilder text;
final StringBuilder text;
if (is == null) {
return null;
}
@ -576,7 +573,7 @@ public class ItemUtil {
if (is == null) {
return null;
}
String text = "";
final String text;
if (is.getItemMeta() != null && is.getItemMeta().hasDisplayName()) {
text = "" + ChatColor.DARK_AQUA + ChatColor.ITALIC + is.getItemMeta().getDisplayName();
} else {