Switch to NamespacedKeys for enchantments

- Switched to using NamespacedKeys for enchantments instead of their names. This means that all properly registered custom enchantments are supported in one go.
- Removed the overengineered enchantment platform stuff. That was built with the idea that every custom enchantment plugin would have their own way of implementing custom enchantments. However, now that I found out that custom enchantments can just be registered using NamespacedKeys, none of this is required anymore.
This commit is contained in:
Pim van der Loos 2020-12-14 13:17:52 +01:00
parent 9d737eeed5
commit 03d0f9492e
No known key found for this signature in database
GPG Key ID: C16F020ADAE6D5A8
11 changed files with 314 additions and 344 deletions

View File

@ -20,13 +20,16 @@ import nl.pim16aap2.armoredElytra.util.messages.Messages;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
public class ArmoredElytra extends JavaPlugin implements Listener public class ArmoredElytra extends JavaPlugin implements Listener
@ -35,6 +38,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener
.get(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]); .get(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]);
private static ArmoredElytra INSTANCE; private static ArmoredElytra INSTANCE;
private final Set<Enchantment> allowedEnchantments = new HashSet<>();
private Messages messages; private Messages messages;
private ConfigLoader config; private ConfigLoader config;
@ -107,8 +111,8 @@ public class ArmoredElytra extends JavaPlugin implements Listener
// Log all allowed enchantments. // Log all allowed enchantments.
myLogger(Level.INFO, ("Allowed enchantments:")); myLogger(Level.INFO, ("Allowed enchantments:"));
for (final String s : config.allowedEnchantments()) for (final Enchantment enchantment : config.allowedEnchantments())
myLogger(Level.INFO, " - " + s); myLogger(Level.INFO, " - " + enchantment.toString());
} }
else else
{ {

View File

@ -1,69 +0,0 @@
package nl.pim16aap2.armoredElytra.enchantment;
import org.bukkit.inventory.ItemStack;
import java.util.Collection;
import java.util.Map;
class EnchantmentContainer
{
private Map<String, Integer> enchantments;
private final IEnchantmentPlatform manager;
public EnchantmentContainer(final Map<String, Integer> enchantments, final IEnchantmentPlatform manager)
{
this.enchantments = enchantments;
this.manager = manager;
}
/**
* Removes any entries from the list of enchantments that do not exist in the provided filter.
*
* @param allowed The names of enchantments (upper case) that are allowed. Any names not in this list are removed.
* @return This instance.
*/
public EnchantmentContainer filter(final Collection<String> allowed)
{
if (!enchantments.isEmpty())
enchantments.keySet().retainAll(allowed);
return this;
}
/**
* Applies the enchantments to an itemstack.
*
* @param is The itemstack to apply the enchantments to.
*/
public void apply(final ItemStack is)
{
manager.applyEnchantments(is, enchantments);
}
/**
* Merges this container with another one.
*/
public void merge(EnchantmentContainer other)
{
if (!(manager.getClass() == other.manager.getClass()))
throw new RuntimeException("Trying to add enchantment containers of different types!");
enchantments = manager.merge(enchantments, other.enchantments);
}
/**
* Gets the number of enchantments in this container.
*/
public int size()
{
return enchantments.size();
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder("[");
enchantments.forEach((k, v) -> sb.append("\"").append(k).append("\" (").append(v).append("), "));
String ret = sb.toString();
ret = ret.length() > 1 ? ret.substring(0, ret.length() - 2) : ret;
return ret + "]";
}
}

View File

@ -1,71 +0,0 @@
package nl.pim16aap2.armoredElytra.enchantment;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class EnchantmentManager
{
private final List<EnchantmentContainer> containers = new ArrayList<>();
private Integer count = null;
public EnchantmentManager(final ItemStack is)
{
EnchantmentPlatformManager.get().getPlatforms().forEach(platform ->
containers.add(platform.getEnchantments(is)));
Collection<String> filter = ArmoredElytra.getInstance().getConfigLoader().allowedEnchantments();
containers.forEach(container -> container.filter(filter));
}
/**
* Merges this EnchantmentManager with another one.
*
* @param other The EnchantmentManager to merge into the current one.
* @return The instance of the current EnchantmentManager.
*/
public EnchantmentManager merge(final EnchantmentManager other)
{
for (int idx = 0; idx < containers.size(); ++idx)
containers.get(idx).merge(other.containers.get(idx));
count = null; // Reset count, as it's no longer up-to-date.
return this;
}
/**
* Applies all the enchantments to the provided itemstack.
*
* @param is The itemstack to apply all enchantments to.
*/
public void apply(final ItemStack is)
{
containers.forEach(container -> container.apply(is));
}
/**
* Gets the total number of enchantments.
*
* @return The total number of enchantments.
*/
public int getEnchantmentCount()
{
if (count != null)
return count;
count = 0;
for (EnchantmentContainer container : containers)
count += container.size();
return count;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder("Enchantments: \n");
containers.forEach(container -> sb.append(container.toString()).append("\n"));
return sb.toString();
}
}

View File

@ -1,30 +0,0 @@
package nl.pim16aap2.armoredElytra.enchantment;
import java.util.ArrayList;
import java.util.List;
public class EnchantmentPlatformManager
{
private static final EnchantmentPlatformManager INSTANCE = new EnchantmentPlatformManager();
private final List<IEnchantmentPlatform> platforms = new ArrayList<>();
private EnchantmentPlatformManager()
{
addPlatform(new VanillaEnchantmentPlatform());
}
public static EnchantmentPlatformManager get()
{
return INSTANCE;
}
public void addPlatform(final IEnchantmentPlatform platform)
{
platforms.add(platform);
}
public List<IEnchantmentPlatform> getPlatforms()
{
return platforms;
}
}

View File

@ -1,22 +0,0 @@
package nl.pim16aap2.armoredElytra.enchantment;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
interface IEnchantmentPlatform
{
EnchantmentContainer getEnchantmentsFromItem(final ItemStack is);
EnchantmentContainer getEnchantmentsFromBook(final ItemStack is);
default EnchantmentContainer getEnchantments(final ItemStack is)
{
return is.getType() == Material.ENCHANTED_BOOK ? getEnchantmentsFromBook(is) : getEnchantmentsFromItem(is);
}
void applyEnchantments(final ItemStack is, final Map<String, Integer> enchantments);
Map<String, Integer> merge(final Map<String, Integer> first, final Map<String, Integer> second);
}

View File

@ -1,131 +0,0 @@
package nl.pim16aap2.armoredElytra.enchantment;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.util.Util;
import org.bukkit.Bukkit;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
class VanillaEnchantmentPlatform implements IEnchantmentPlatform
{
private Map<String, Integer> getNamedEnchantments(final Map<Enchantment, Integer> enchantments)
{
final Map<String, Integer> enchantmentsStr = new HashMap<>(enchantments.size());
enchantments.forEach((k, v) -> enchantmentsStr.put(k.getName(), v));
return enchantmentsStr;
}
private Map<Enchantment, Integer> getEnchantments(final Map<String, Integer> enchantments)
{
final Map<Enchantment, Integer> enchantmentsStr = new HashMap<>(enchantments.size());
enchantments.forEach((k, v) -> enchantmentsStr.put(Enchantment.getByName(k), v));
return enchantmentsStr;
}
@Override
public EnchantmentContainer getEnchantmentsFromItem(final ItemStack is)
{
return new EnchantmentContainer(getNamedEnchantments(is.getEnchantments()), this);
}
@Override
public EnchantmentContainer getEnchantmentsFromBook(final ItemStack is)
{
if (!is.hasItemMeta())
return new EnchantmentContainer(new HashMap<>(0), this);
EnchantmentStorageMeta meta = (EnchantmentStorageMeta) is.getItemMeta();
if (meta == null || !meta.hasStoredEnchants())
return new EnchantmentContainer(new HashMap<>(0), this);
return new EnchantmentContainer(getNamedEnchantments(meta.getStoredEnchants()), this);
}
@Override
public void applyEnchantments(final ItemStack is, final Map<String, Integer> enchantments)
{
enchantments.forEach(
(enchantmentName, level) ->
{
Enchantment enchantment = Enchantment.getByName(enchantmentName);
if (enchantment == null)
{
Bukkit.getLogger().log(Level.INFO, "Failed to find enchantment: \"" + enchantmentName + "\"");
return;
}
is.addUnsafeEnchantment(enchantment, level);
}
);
}
@Override
public Map<String, Integer> merge(final Map<String, Integer> first, final Map<String, Integer> second)
{
if (second == null || second.isEmpty())
return first;
if (first == null || first.isEmpty())
return second;
Map<Enchantment, Integer> enchantments0 = getEnchantments(first);
Map<Enchantment, Integer> enchantments1 = getEnchantments(second);
Map<Enchantment, Integer> combined = new HashMap<>(enchantments0);
for (Map.Entry<Enchantment, Integer> entry : enchantments1.entrySet())
{
Integer enchantLevel = enchantments0.get(entry.getKey());
if (enchantLevel != null)
{
if (entry.getValue().equals(enchantLevel) && entry.getValue() < entry.getKey().getMaxLevel())
enchantLevel = entry.getValue() + 1;
else if (entry.getValue() > enchantLevel)
enchantLevel = entry.getValue();
// If the enchantment level has changed,
if (!enchantLevel.equals(enchantments0.get(entry.getKey())))
{
combined.remove(entry.getKey());
combined.put(entry.getKey(), enchantLevel);
}
}
else
combined.put(entry.getKey(), entry.getValue());
}
if (!ArmoredElytra.getInstance().getConfigLoader().allowMultipleProtectionEnchantments())
{
// Get the protection enchantment rating for both enchantment sets.
int protVal0 = Util.getProtectionEnchantmentsVal(enchantments0);
int protVal1 = Util.getProtectionEnchantmentsVal(enchantments1);
// If they have different protection enchantments, keep enchantment1's enchantments
// And remove the protection enchantment from enchantments0.
if (protVal0 != 0 && protVal1 != 0 && protVal0 != protVal1)
switch (protVal0)
{
case 1:
combined.remove(Enchantment.PROTECTION_ENVIRONMENTAL);
break;
case 2:
combined.remove(Enchantment.PROTECTION_EXPLOSIONS);
break;
case 4:
combined.remove(Enchantment.PROTECTION_FALL);
break;
case 8:
combined.remove(Enchantment.PROTECTION_FIRE);
break;
case 16:
combined.remove(Enchantment.PROTECTION_PROJECTILE);
break;
}
}
return getNamedEnchantments(combined);
}
}

View File

@ -1,14 +1,15 @@
package nl.pim16aap2.armoredElytra.handlers; package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.enchantment.EnchantmentManager;
import nl.pim16aap2.armoredElytra.util.Action; import nl.pim16aap2.armoredElytra.util.Action;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.EnchantmentContainer;
import nl.pim16aap2.armoredElytra.util.Util; import nl.pim16aap2.armoredElytra.util.Util;
import nl.pim16aap2.armoredElytra.util.XMaterial; import nl.pim16aap2.armoredElytra.util.XMaterial;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType;
@ -90,7 +91,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
} }
// Handle all anvil related stuff for this plugin. // Handle all anvil related stuff for this plugin.
@EventHandler @EventHandler(priority = EventPriority.HIGHEST)
private void onAnvilInventoryOpen(PrepareAnvilEvent event) private void onAnvilInventoryOpen(PrepareAnvilEvent event)
{ {
Player player = (Player) event.getView().getPlayer(); Player player = (Player) event.getView().getPlayer();
@ -115,7 +116,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
ArmorTier newTier = ArmorTier.NONE; ArmorTier newTier = ArmorTier.NONE;
ArmorTier curTier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemA); ArmorTier curTier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemA);
short durability = 0; short durability = 0;
EnchantmentManager enchantments = new EnchantmentManager(itemA); EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemA, plugin);
switch (action) switch (action)
{ {
@ -128,12 +129,12 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
durability = (short) (-itemA.getType().getMaxDurability() - itemA.getDurability() durability = (short) (-itemA.getType().getMaxDurability() - itemA.getDurability()
- itemB.getDurability()); - itemB.getDurability());
durability = durability < 0 ? 0 : durability; durability = durability < 0 ? 0 : durability;
enchantments.merge(new EnchantmentManager(itemB)); enchantments.merge(EnchantmentContainer.getEnchantments(itemB, plugin));
break; break;
case CREATE: case CREATE:
newTier = Util.armorToTier(itemB.getType()); newTier = Util.armorToTier(itemB.getType());
durability = 0; durability = 0;
enchantments.merge(new EnchantmentManager(itemB)); enchantments.merge(EnchantmentContainer.getEnchantments(itemB, plugin));
break; break;
case ENCHANT: case ENCHANT:
newTier = curTier; newTier = curTier;
@ -141,7 +142,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
// If there aren't any illegal enchantments on the book, continue as normal. // If there aren't any illegal enchantments on the book, continue as normal.
// Otherwise... Block. // Otherwise... Block.
EnchantmentManager enchantmentsB = new EnchantmentManager(itemB); EnchantmentContainer enchantmentsB = EnchantmentContainer.getEnchantments(itemB, plugin);
if (enchantmentsB.getEnchantmentCount() > 0) if (enchantmentsB.getEnchantmentCount() > 0)
{ {
enchantments.merge(enchantmentsB); enchantments.merge(enchantmentsB);
@ -159,7 +160,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
if (plugin.playerHasCraftPerm(player, newTier)) if (plugin.playerHasCraftPerm(player, newTier))
{ {
result = new ItemStack(Material.ELYTRA, 1); result = new ItemStack(Material.ELYTRA, 1);
enchantments.apply(result); enchantments.applyEnchantments(result);
result.setDurability(durability); result.setDurability(durability);
result = ArmoredElytra.getInstance().getNbtEditor() result = ArmoredElytra.getInstance().getNbtEditor()

View File

@ -1,8 +1,8 @@
package nl.pim16aap2.armoredElytra.handlers; package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.enchantment.EnchantmentManager;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.EnchantmentContainer;
import nl.pim16aap2.armoredElytra.util.Util; import nl.pim16aap2.armoredElytra.util.Util;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
@ -40,7 +40,7 @@ public class SmithingTableHandler extends ArmoredElytraHandler implements Listen
return; return;
final ArmorTier newTier = Util.armorToTier(itemStackB.getType()); final ArmorTier newTier = Util.armorToTier(itemStackB.getType());
final EnchantmentManager enchantments = new EnchantmentManager(itemStackA); EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemStackA, plugin);
final Player player = (Player) event.getView().getPlayer(); final Player player = (Player) event.getView().getPlayer();
final ItemStack result; final ItemStack result;
@ -49,7 +49,7 @@ public class SmithingTableHandler extends ArmoredElytraHandler implements Listen
result = ArmoredElytra.getInstance().getNbtEditor() result = ArmoredElytra.getInstance().getNbtEditor()
.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), newTier, .addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), newTier,
plugin.getConfigLoader().unbreakable()); plugin.getConfigLoader().unbreakable());
enchantments.apply(result); enchantments.applyEnchantments(result);
event.setResult(result); event.setResult(result);
} }
} }

View File

@ -2,7 +2,9 @@ package nl.pim16aap2.armoredElytra.util;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import nl.pim16aap2.armoredElytra.ArmoredElytra;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
@ -29,7 +31,7 @@ public class ConfigLoader
private int DIAMONDS_TO_FULL; private int DIAMONDS_TO_FULL;
private int NETHERITE_TO_FULL; private int NETHERITE_TO_FULL;
private boolean noFlightDurability; private boolean noFlightDurability;
private LinkedHashSet<String> allowedEnchantments; private LinkedHashSet<Enchantment> allowedEnchantments;
private boolean allowMultipleProtectionEnchantments; private boolean allowMultipleProtectionEnchantments;
private boolean craftingInSmithingTable; private boolean craftingInSmithingTable;
private boolean bypassWearPerm; private boolean bypassWearPerm;
@ -70,8 +72,9 @@ public class ConfigLoader
"List of enchantments that are allowed to be put on an armored elytra.", "List of enchantments that are allowed to be put on an armored elytra.",
"If you do not want to allow any enchantments at all, remove them all and add \"NONE\"", "If you do not want to allow any enchantments at all, remove them all and add \"NONE\"",
"You can find supported enchantments here:", "You can find supported enchantments here:",
"https://hub.spigotmc.org/javadocs/spigot/org/bukkit/enchantments/Enchantment.html", "https://github.com/PimvanderLoos/ArmoredElytra/blob/master/vanillaEnchantments",
"Note that only 1 protection enchantment (PROTECTION_FIRE, PROTECTION_ENVIRONMENTAL etc) can be active on an elytra." "If you install additional enchantment plugins, you can add their enchantments as well.",
"Just add their 'NamespacedKey'. Ask the enchantment plugin dev for more info if you need it."
}; };
String[] updateComment = String[] updateComment =
{ {
@ -119,9 +122,10 @@ public class ConfigLoader
// Set default list of allowed enchantments. // Set default list of allowed enchantments.
List<String> defaultAllowedEnchantments = new ArrayList<>( List<String> defaultAllowedEnchantments = new ArrayList<>(
Arrays.asList("DURABILITY", "PROTECTION_FIRE", "PROTECTION_EXPLOSIONS", Arrays.asList("minecraft:unbreaking", "minecraft:fire_protection", "minecraft:blast_protection",
"PROTECTION_PROJECTILE", "PROTECTION_ENVIRONMENTAL", "minecraft:projectile_protection", "minecraft:protection",
"THORNS", "BINDING_CURSE", "VANISHING_CURSE", "MENDING")); "minecraft:thorns", "minecraft:binding_curse", "minecraft:vanishing_curse",
"minecraft:mending"));
FileConfiguration config = plugin.getConfig(); FileConfiguration config = plugin.getConfig();
@ -145,8 +149,26 @@ public class ConfigLoader
defaultAllowedEnchantments = addNewConfigOption(config, "allowedEnchantments", defaultAllowedEnchantments, defaultAllowedEnchantments = addNewConfigOption(config, "allowedEnchantments", defaultAllowedEnchantments,
enchantmentsComment); enchantmentsComment);
defaultAllowedEnchantments.replaceAll(String::toUpperCase);
allowedEnchantments = new LinkedHashSet<>(defaultAllowedEnchantments); allowedEnchantments = new LinkedHashSet<>();
defaultAllowedEnchantments.forEach(
fullKey ->
{
String[] keyParts = fullKey.split(":", 2);
if (keyParts.length < 2)
{
Bukkit.getLogger().warning("\"" + fullKey + "\" is not a valid NamespacedKey!");
return;
}
NamespacedKey key = new NamespacedKey(keyParts[0], keyParts[1]);
Enchantment enchantment = Enchantment.getByKey(key);
if (enchantment == null)
{
Bukkit.getLogger().warning("The enchantment \"" + fullKey + "\" could not be found!");
return;
}
allowedEnchantments.add(enchantment);
});
allowMultipleProtectionEnchantments = addNewConfigOption(config, "allowMultipleProtectionEnchantments", false, allowMultipleProtectionEnchantments = addNewConfigOption(config, "allowMultipleProtectionEnchantments", false,
allowMultipleProtectionEnchantmentsComment); allowMultipleProtectionEnchantmentsComment);
@ -280,7 +302,7 @@ public class ConfigLoader
return noFlightDurability; return noFlightDurability;
} }
public LinkedHashSet<String> allowedEnchantments() public LinkedHashSet<Enchantment> allowedEnchantments()
{ {
return allowedEnchantments; return allowedEnchantments;
} }

View File

@ -0,0 +1,228 @@
package nl.pim16aap2.armoredElytra.util;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class EnchantmentContainer
{
private Map<Enchantment, Integer> enchantments;
/**
* Creates a new {@link EnchantmentContainer} from a map of enchantments.
*
* @param enchantments The enchantments.
* @param plugin The {@link ArmoredElytra} instance to use for obtaining the list of allowed enchantments. See
* {@link ConfigLoader#allowedEnchantments()}.
*/
public EnchantmentContainer(final Map<Enchantment, Integer> enchantments, final ArmoredElytra plugin)
{
this(enchantments);
this.filter(plugin.getConfigLoader().allowedEnchantments());
}
private EnchantmentContainer(final Map<Enchantment, Integer> enchantments)
{
this.enchantments = new HashMap<>(enchantments);
}
/**
* Gets all the enchantments from an item.
*
* @param is The item.
* @param plugin The {@link ArmoredElytra} instance to use.
* @return A new {@link EnchantmentContainer} with the enchantments from the item.
*/
public static EnchantmentContainer getEnchantments(final ItemStack is, final ArmoredElytra plugin)
{
return is.getType() == Material.ENCHANTED_BOOK ?
getEnchantmentsFromBook(is, plugin) :
getEnchantmentsFromItem(is, plugin);
}
/**
* Gets all the enchantments from an item that is not a book.
*
* @param is The item.
* @param plugin The {@link ArmoredElytra} instance to use.
* @return A new {@link EnchantmentContainer} with the enchantments from the item.
*/
private static EnchantmentContainer getEnchantmentsFromItem(final ItemStack is, final ArmoredElytra plugin)
{
return new EnchantmentContainer(is.getEnchantments(), plugin);
}
/**
* Gets all the enchantments from a book.
*
* @param is The book.
* @param plugin The {@link ArmoredElytra} instance to use.
* @return A new enchantment container with the enchantments from the book.
*/
private static EnchantmentContainer getEnchantmentsFromBook(final ItemStack is, final ArmoredElytra plugin)
{
if (!is.hasItemMeta())
return new EnchantmentContainer(new HashMap<>(0), plugin);
final EnchantmentStorageMeta meta = (EnchantmentStorageMeta) is.getItemMeta();
if (meta == null || !meta.hasStoredEnchants())
return new EnchantmentContainer(new HashMap<>(0), plugin);
return new EnchantmentContainer(meta.getStoredEnchants(), plugin);
}
/**
* Gets the total number of enchantments in this container.
*
* @return The total number of enchantments in this container.
*/
public int getEnchantmentCount()
{
return enchantments.size();
}
/**
* Removes any entries from the list of enchantments that do not exist in the provided filter.
*
* @param allowed The names of enchantments (upper case) that are allowed. Any names not in this list are removed.
*/
public void filter(final Collection<Enchantment> allowed)
{
if (!enchantments.isEmpty())
enchantments.keySet().retainAll(allowed);
}
/**
* Applies the enchantments to an itemstack.
*
* @param is The itemstack to apply the enchantments to.
*/
public void applyEnchantments(final ItemStack is)
{
is.addUnsafeEnchantments(enchantments);
}
/**
* Merges this container with another one.
*/
public void merge(EnchantmentContainer other)
{
enchantments = merge(this.enchantments, other.enchantments);
}
/**
* Gets the number of enchantments in this container.
*/
public int size()
{
return enchantments.size();
}
/**
* Checks if this container is empty.
*
* @return True if there are exactly 0 enchantments in this container.
*/
public boolean isEmpty()
{
return enchantments.isEmpty();
}
/**
* Merges two enchantment containers.
*
* @param first The first enchantment container.
* @param second The second enchantment container. In case of conflicts, this will take precedence.
* @return The new map of enchantments.
*/
public static EnchantmentContainer merge(final EnchantmentContainer first, final EnchantmentContainer second)
{
return new EnchantmentContainer(merge(first.enchantments, second.enchantments));
}
/**
* Merges two maps of enchantments.
*
* @param first The first maps of enchantments.
* @param second The second maps of enchantments. In case of conflicts, this will take precedence.
* @return The new map of enchantments.
*/
private static Map<Enchantment, Integer> merge(final Map<Enchantment, Integer> first,
final Map<Enchantment, Integer> second)
{
if (second == null || second.isEmpty())
return first;
if (first == null || first.isEmpty())
return second;
final Map<Enchantment, Integer> combined = new HashMap<>(first);
for (Map.Entry<Enchantment, Integer> entry : second.entrySet())
{
Integer enchantLevel = first.get(entry.getKey());
if (enchantLevel != null)
{
if (entry.getValue().equals(enchantLevel) && entry.getValue() < entry.getKey().getMaxLevel())
enchantLevel = entry.getValue() + 1;
else if (entry.getValue() > enchantLevel)
enchantLevel = entry.getValue();
// If the enchantment level has changed,
if (!enchantLevel.equals(first.get(entry.getKey())))
{
combined.remove(entry.getKey());
combined.put(entry.getKey(), enchantLevel);
}
}
else
combined.put(entry.getKey(), entry.getValue());
}
if (!ArmoredElytra.getInstance().getConfigLoader().allowMultipleProtectionEnchantments())
{
// Get the protection enchantment rating for both enchantment sets.
int protVal0 = Util.getProtectionEnchantmentsVal(first);
int protVal1 = Util.getProtectionEnchantmentsVal(second);
// If they have different protection enchantments, keep enchantment1's enchantments
// And remove the protection enchantment from enchantments0.
if (protVal0 != 0 && protVal1 != 0 && protVal0 != protVal1)
switch (protVal0)
{
case 1:
combined.remove(Enchantment.PROTECTION_ENVIRONMENTAL);
break;
case 2:
combined.remove(Enchantment.PROTECTION_EXPLOSIONS);
break;
case 4:
combined.remove(Enchantment.PROTECTION_FALL);
break;
case 8:
combined.remove(Enchantment.PROTECTION_FIRE);
break;
case 16:
combined.remove(Enchantment.PROTECTION_PROJECTILE);
break;
}
}
return combined;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder("[");
enchantments.forEach((k, v) -> sb.append("\"").append(k).append("\" (").append(v).append("), "));
String ret = sb.toString();
ret = ret.length() > 1 ? ret.substring(0, ret.length() - 2) : ret;
return ret + "]";
}
}

38
vanillaEnchantments Normal file
View File

@ -0,0 +1,38 @@
minecraft:feather_falling
minecraft:frost_walker
minecraft:unbreaking
minecraft:projectile_protection
minecraft:knockback
minecraft:respiration
minecraft:punch
minecraft:protection
minecraft:blast_protection
minecraft:lure
minecraft:impaling
minecraft:smite
minecraft:silk_touch
minecraft:infinity
minecraft:thorns
minecraft:luck_of_the_sea
minecraft:multishot
minecraft:vanishing_curse
minecraft:fire_aspect
minecraft:depth_strider
minecraft:flame
minecraft:piercing
minecraft:fire_protection
minecraft:sharpness
minecraft:power
minecraft:sweeping
minecraft:aqua_affinity
minecraft:binding_curse
minecraft:bane_of_arthropods
minecraft:soul_speed
minecraft:looting
minecraft:efficiency
minecraft:mending
minecraft:riptide
minecraft:quick_charge
minecraft:fortune
minecraft:loyalty
minecraft:channeling