Eco enchant compatibility (#13)

Also fix issue with IF framework (gui framework) for 1.21
This commit is contained in:
alexcrea 2024-06-25 20:22:48 +02:00 committed by GitHub
commit 97f175462d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 914 additions and 504 deletions

View file

@ -49,7 +49,10 @@ Currently, there is not a lot of compatible plugin
Here is a list of supported plugins with support status: Here is a list of supported plugins with support status:
- [Enchantment²](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/): - [Enchantment²](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/):
Officially supported but still experimental. Automatic configuration translation. Officially supported but still experimental. Automatic configuration.
- [EcoEnchant](https://www.spigotmc.org/resources/50-sale-%E2%8C%9B-ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/):
Officially supported but still experimental. Need a server restart to add newly added enchantment.
Automatic configuration on restart.
If you like Custom Anvil to support a specific custom enchantment plugin. If you like Custom Anvil to support a specific custom enchantment plugin.
You can ask, but please note implementing compatibility will be considered You can ask, but please note implementing compatibility will be considered

View file

@ -1,10 +1,11 @@
plugins { plugins {
kotlin("jvm") version "1.6.21" kotlin("jvm") version "1.9.24"
java java
id("com.github.johnrengelman.shadow").version("7.1.2")
} }
group = "xyz.alexcrea" group = "xyz.alexcrea"
version = "1.5.0" version = "1.5.1"
repositories { repositories {
mavenCentral() mavenCentral()
@ -12,6 +13,9 @@ repositories {
// ProtocoLib // ProtocoLib
maven (url = "https://repo.dmulloy2.net/repository/public/" ) maven (url = "https://repo.dmulloy2.net/repository/public/" )
// EcoEnchants
maven(url = "https://repo.auxilor.io/repository/maven-public/")
} }
dependencies { dependencies {
@ -21,7 +25,7 @@ dependencies {
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT")
// Gui library // Gui library
compileOnly("com.github.stefvanschie.inventoryframework:IF:0.10.14") implementation("com.github.stefvanschie.inventoryframework:IF:0.10.14")
// Protocolib // Protocolib
compileOnly("com.comphenix.protocol:ProtocolLib:5.1.0") compileOnly("com.comphenix.protocol:ProtocolLib:5.1.0")
@ -29,6 +33,10 @@ dependencies {
// EnchantsSquaredRewritten // EnchantsSquaredRewritten
compileOnly(files("libs/EnchantsSquared.jar")) compileOnly(files("libs/EnchantsSquared.jar"))
// EcoEnchants
compileOnly("com.willfp:EcoEnchants:12.5.1")
compileOnly("com.willfp:eco:6.70.1")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0") testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
@ -55,3 +63,8 @@ val fatJar = tasks.register<Jar>("fatJar") {
tasks.getByName("build") { tasks.getByName("build") {
dependsOn(fatJar) dependsOn(fatJar)
} }
// Shadow recesary dependency
tasks.shadowJar {
relocate("com.github.stefvanschie.inventoryframework", "xyz.alexcrea.inventoryframework")
}

View file

@ -0,0 +1,34 @@
package xyz.alexcrea.cuanvil.enchant;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public interface AdditionalTestEnchantment {
/**
* Test if the provided enchantments can be compatible with this enchantment. only non-Custom Anvil conflict.
* @param enchantments Immutable map of validated enchantments for the item.
* @param itemMat Material of the tested item.
* @return If there is a conflict with the enchantments.
*/
boolean isEnchantConflict(
@NotNull Map<CAEnchantment, Integer> enchantments,
@NotNull Material itemMat);
/**
* Test if the provided item can be compatible with this enchantment. only non-Custom Anvil conflict.
* @param enchantments Immutable map of validated enchantments for the item.
* @param itemMat Material of the tested item.
* @param item Provide a new instance of the used item stack with the partial enchantment applied.
* @return If there is a conflict with the enchantment and the item.
*/
boolean isItemConflict(
@NotNull Map<CAEnchantment, Integer> enchantments,
@NotNull Material itemMat,
@NotNull ItemStack item);
}

View file

@ -0,0 +1,243 @@
package xyz.alexcrea.cuanvil.enchant;
import io.delilaheve.util.ItemUtil;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.dependency.EnchantmentSquaredDependency;
import xyz.alexcrea.cuanvil.group.ConflictType;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
/**
* Represent an enchantment compatible with Custom Anvil.
* One issue with custom anvil is: it does not handle well duplicate key name (ignoring namespace) as the plugin was coded with vanilla enchantment in head
*/
public interface CAEnchantment {
/**
* Get the default rarity of this enchant.
* @return The default rarity of this enchant.
*/
@NotNull
EnchantmentRarity defaultRarity();
/**
* Get the enchantment key.
* @return The enchantment key.
*/
@NotNull
NamespacedKey getKey();
/**
* Get the enchantment name.
* @return The enchantment name.
*/
@NotNull
String getName();
/**
* Get the default maximum level of this enchantment.
* @return The default maximum level of this enchantment.
*/
int defaultMaxLevel();
/**
* Check if the enchantment have specialised group operation.
* @return If the enchantment is optimised for group operation.
*/
boolean isOptimised();
/**
* Check if the player is allowed to use this enchantment.
* @param player The player to test.
* @return If the player is allowed to use this enchantment.
*/
boolean isAllowed(@NotNull HumanEntity player);
/**
* Add a conflict to this enchantment conflict list.
* @param conflict The conflict to add.
*/
void addConflict(@NotNull EnchantConflictGroup conflict);
/**
* Remove a conflict from the conflict list of this enchantment.
* @param conflict The conflict to remove from this enchantment.
*/
void removeConflict(@NotNull EnchantConflictGroup conflict);
/**
* Clear Custom Anvil conflicts for this enchantment.
*/
void clearConflict();
/**
* Get a collection of Custom Anvil conflict containing this enchantment.
* @return A collection of Custom Anvil conflict containing this enchantment.
*/
@NotNull Collection<EnchantConflictGroup> getConflicts();
/**
* Get current level of the enchantment.
* @param item Item to search the level for.
*/
int getLevel(@NotNull ItemStack item);
/**
* Get current level of the enchantment.
* @param item Item to search the level for.
* @param meta Meta of the provided item. It will not be changed and not be set on the item.
* @return Current leve of this enchantment on item. or 0 if absent.
*/
int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta);
/**
* Check if this enchantment is present on the provided level.
* @param item The item to set the enchantment level.
* @return If the enchantment have been found.
*/
boolean isEnchantmentPresent(@NotNull ItemStack item);
/**
* Check if this enchantment is present on the provided level.
* @param item The item to set the enchantment level.
* @param meta Meta of the provided item. It will not be changed and not be set on the item.
* @return If the enchantment have been found.
*/
boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta);
/**
* Force add an enchantment at the provided level.
* @param item The item to set the enchantment level.
* @param level The level to set the enchantment to.
*/
void addEnchantmentUnsafe(@NotNull ItemStack item, int level);
/**
* Remove this enchantment from the provided ItemStack.
* @param item The item to remove the enchantment.
*/
void removeFrom(@NotNull ItemStack item);
// Static functions
/**
* Clear every enchantment from this item.
* @param item Item to be cleared from enchantments.
*/
static void clearEnchants(@NotNull ItemStack item){
ItemMeta meta = item.getItemMeta();
if(meta == null) return;
// Clean Vanilla enchants
if (ItemUtil.INSTANCE.isEnchantedBook(item)) {
EnchantmentStorageMeta bookMeta = (EnchantmentStorageMeta) meta;
bookMeta.getStoredEnchants().forEach(
(enchantment, leve) -> bookMeta.removeStoredEnchant(enchantment)
);
} else {
item.getEnchantments().forEach(
(enchantment, leve) -> item.removeEnchantment(enchantment)
);
}
// Clean Enchant Squared enchants
EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
if(enchantmentSquared != null){
enchantmentSquared.clearEnchantments(item);
}
// Clean unoptimised enchants
for (CAEnchantment enchant : CAEnchantmentRegistry.getInstance().unoptimisedValues()) {
if(enchant.isEnchantmentPresent(item)){
enchant.removeFrom(item);
}
}
}
/**
* Get enchantments of an item.
* @param item Item to get enchantment from.
* @return A map of the set enchantments and there's respective levels.
*/
static Map<CAEnchantment, Integer> getEnchants(@NotNull ItemStack item){
Map<CAEnchantment, Integer> enchantments = new HashMap<>();
CAEnchantmentRegistry registry = CAEnchantmentRegistry.getInstance();
ItemMeta meta = item.getItemMeta();
if(meta == null) return enchantments;
// Vanilla optimised get
if (ItemUtil.INSTANCE.isEnchantedBook(item)) {
((EnchantmentStorageMeta)meta).getStoredEnchants().forEach(
(enchantment, level) -> enchantments.put(registry.getByKey(enchantment.getKey()), level)
);
} else {
item.getEnchantments().forEach(
(enchantment, level) -> enchantments.put(registry.getByKey(enchantment.getKey()), level)
);
}
// Enchants Squared get
EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
if(enchantmentSquared != null){
enchantmentSquared.getEnchantmentsSquared(item, enchantments);
}
// Unoptimised enchantment get
findEnchantsFromSelectedList(item, meta, enchantments, registry.unoptimisedValues());
return enchantments;
}
/**
* Find enchantments of an item. only test the enchantment from the list.
* @param item Item to get enchantment from.
* @param meta Meta of the provided item.
* @param enchantments Map of enchantment to complete.
* @param enchantmentToTest Enchantment to test
*/
static void findEnchantsFromSelectedList(
@NotNull ItemStack item,
@NotNull ItemMeta meta,
@NotNull Map<CAEnchantment, Integer> enchantments,
@NotNull Collection<CAEnchantment> enchantmentToTest){
for (CAEnchantment enchantment : enchantmentToTest) {
if(enchantment.isEnchantmentPresent(item, meta)){
enchantments.put(enchantment, enchantment.getLevel(item, meta));
}
}
}
/**
* Gets an array of all the registered enchantments.
* @return Array of enchantment.
*/
static @Nullable CAEnchantment getByKey(@NotNull NamespacedKey key){
return CAEnchantmentRegistry.getInstance().getByKey(key);
}
/**
* Gets a list of all the unoptimised enchantments.
* @return List of enchantment.
*/
static @Nullable CAEnchantment getByName(@NotNull String name){
return CAEnchantmentRegistry.getInstance().getByName(name);
}
}

View file

@ -0,0 +1,115 @@
package xyz.alexcrea.cuanvil.enchant;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.group.ConflictType;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
public abstract class CAEnchantmentBase implements CAEnchantment {
@NotNull
private final NamespacedKey key;
@NotNull
private final String name;
@NotNull
private final EnchantmentRarity defaultRarity;
private final int defaultMaxLevel;
private final List<EnchantConflictGroup> conflicts;
/**
* Constructor of Wrapped Enchantment.
* @param key The enchantment's key.
* @param defaultRarity Default rarity the enchantment should be.
* @param defaultMaxLevel Default max level the enchantment can be applied with.
*/
protected CAEnchantmentBase(
@NotNull NamespacedKey key,
@Nullable EnchantmentRarity defaultRarity,
int defaultMaxLevel){
this.key = key;
this.name = key.getKey();
this.defaultMaxLevel = defaultMaxLevel;
this.defaultRarity = Objects.requireNonNullElse(defaultRarity, EnchantmentRarity.COMMON);
this.conflicts = new ArrayList<>();
}
@NotNull
@Override
public final EnchantmentRarity defaultRarity(){
return defaultRarity;
}
@NotNull
@Override
public final NamespacedKey getKey(){
return key;
}
@NotNull
@Override
public final String getName(){
return name;
}
@Override
public final int defaultMaxLevel(){
return defaultMaxLevel;
}
@Override
public boolean isOptimised(){
return false;
}
@Override
public boolean isAllowed(@NotNull HumanEntity player){
return true;
}
public int getLevel(@NotNull ItemStack item){
ItemMeta meta = item.getItemMeta();
if(meta == null) return 0;
return getLevel(item, meta);
}
public boolean isEnchantmentPresent(@NotNull ItemStack item){
ItemMeta meta = item.getItemMeta();
if(meta == null) return false;
return isEnchantmentPresent(item, meta);
}
@Override
public void addConflict(@NotNull EnchantConflictGroup conflict){
this.conflicts.add(conflict);
}
@Override
public void removeConflict(@NotNull EnchantConflictGroup conflict){
this.conflicts.remove(conflict);
}
@Override
public void clearConflict(){
this.conflicts.clear();
}
@Override
public @NotNull List<EnchantConflictGroup> getConflicts() {
return conflicts;
}
}

View file

@ -0,0 +1,135 @@
package xyz.alexcrea.cuanvil.enchant;
import io.delilaheve.CustomAnvil;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.enchant.wrapped.CAVanillaEnchantment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
public class CAEnchantmentRegistry {
private static final CAEnchantmentRegistry instance = new CAEnchantmentRegistry();
public static CAEnchantmentRegistry getInstance() {
return instance;
}
// Register enchantment functions
private final HashMap<NamespacedKey, CAEnchantment> byKeyMap;
private final HashMap<String, CAEnchantment> byNameMap;
private final List<CAEnchantment> unoptimisedValues;
private CAEnchantmentRegistry() {
byKeyMap = new HashMap<>();
byNameMap = new HashMap<>();
unoptimisedValues = new ArrayList<>();
}
/**
* This should only be called on main of custom anvil.
* If called more than one time, chance of thing being broken will be high.
*/
public void registerStartupEnchantments(){
for (Enchantment enchantment : Enchantment.values()) {
register(new CAVanillaEnchantment(enchantment));
}
if(DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility() != null){
DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility().registerEnchantments();
}
if(DependencyManager.INSTANCE.getEcoEnchantCompatibility() != null){
DependencyManager.INSTANCE.getEcoEnchantCompatibility().registerEnchantments();
}
}
/**
* Can be used to register new enchantment.
* <p>
* No guarantee that the enchantment will be present on the config gui if registered late.
* (By late I mean after custom anvil startup.)
* @param enchantment The enchantment to be registered.
*/
public void register(@NotNull CAEnchantment enchantment){
if(byKeyMap.containsKey(enchantment.getKey())){
CustomAnvil.instance.getLogger().log(Level.WARNING,
"Duplicate registered enchantment. This should NOT happen.",
new IllegalStateException(enchantment.getKey()+" enchantment was already registered"));
return;
}
if(byNameMap.containsKey(enchantment.getName())){
CustomAnvil.instance.getLogger().log(Level.WARNING,
"Duplicate registered enchantment name. There will have issue. " +
"\nI hope this do not happen to you on a production server. If it do, there is probably a plugin trying to register an enchantment with the same name than another one",
new IllegalStateException(enchantment.getKey()+" enchantment name was already registered"));
}
byKeyMap.put(enchantment.getKey(), enchantment);
byNameMap.put(enchantment.getName(), enchantment);
if(!enchantment.isOptimised()){
unoptimisedValues.add(enchantment);
}
}
/**
* Can be used to unregister new enchantment.
* Please be cautious with this function.
* It should probably rarely be used.
* <p>
* No guarantee that the enchantment will absent if the config guis if unregistered late.
* (By late I mean after custom anvil startup.)
* @param enchantment The enchantment to be unregistered.
*/
public void unregister(CAEnchantment enchantment){
if(enchantment == null) return;
byKeyMap.remove(enchantment.getKey());
byNameMap.remove(enchantment.getName());
unoptimisedValues.remove(enchantment);
}
/**
* Gets the enchantment by the provided key.
* @param key Key to fetch.
* @return Registered enchantment. null if absent.
*/
public @Nullable CAEnchantment getByKey(@NotNull NamespacedKey key){
return byKeyMap.get(key);
}
/**
* Gets the enchantment by the provided name.
* @param name Name to fetch.
* @return Registered enchantment. null if absent.
*/
public @Nullable CAEnchantment getByName(@NotNull String name){
return byNameMap.get(name);
}
/**
* Gets an array of all the registered enchantments.
* @return Array of enchantment.
*/
@NotNull
public Collection<CAEnchantment> values() {
return byKeyMap.values();
}
/**
* Gets a list of all the unoptimised enchantments.
* @return List of enchantment.
*/
@NotNull
public List<CAEnchantment> unoptimisedValues() {
return unoptimisedValues;
}
}

View file

@ -1,344 +0,0 @@
package xyz.alexcrea.cuanvil.enchant;
import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ItemUtil;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.dependency.EnchantmentSquaredDependency;
import xyz.alexcrea.cuanvil.enchant.wrapped.VanillaEnchantment;
import java.util.*;
import java.util.logging.Level;
/**
* Represent any enchantment.
* One issue with the plugin is: it does not handle well duplicate key name (ignoring namespace) as the plugin was coded with vanilla enchantment in head
*/
public abstract class WrappedEnchantment {
@NotNull
private final NamespacedKey key;
@NotNull
private final String name;
@NotNull
private final EnchantmentRarity defaultRarity;
private final int defaultMaxLevel;
/**
* Constructor of Wrapped Enchantment.
* @param key The enchantment's key.
* @param defaultRarity Default rarity the enchantment should be.
* @param defaultMaxLevel Default max level the enchantment can be applied with.
*/
protected WrappedEnchantment(
@NotNull NamespacedKey key,
@Nullable EnchantmentRarity defaultRarity,
int defaultMaxLevel){
this.key = key;
this.name = key.getKey();
this.defaultMaxLevel = defaultMaxLevel;
if(defaultRarity == null) this.defaultRarity = EnchantmentRarity.COMMON;
else this.defaultRarity = defaultRarity;
}
/**
* Get the default rarity of this enchant.
* @return The default rarity of this enchant.
*/
@NotNull
public final EnchantmentRarity defaultRarity(){
return defaultRarity;
}
/**
* Get the enchantment key.
* @return The enchantment key.
*/
@NotNull
public final NamespacedKey getKey(){
return key;
}
/**
* Get the enchantment name.
* @return The enchantment name.
*/
@NotNull
public final String getName(){
return name;
}
/**
* Get the default maximum level of this enchantment.
* @return The default maximum level of this enchantment.
*/
public final int defaultMaxLevel(){return defaultMaxLevel;}
/**
* Check if the enchantment have specialised group operation.
* @return If the enchantment is optimised for group operation.
*/
protected boolean isOptimised(){
return false;
}
/**
* Check if the player is allowed to use this enchantment.
* @param player The player to test.
* @return If the player is allowed to use this enchantment.
*/
public boolean isAllowed(@NotNull HumanEntity player){
return true;
}
/**
* Get current level of the enchantment.
* @param item Item to search the level for.
*/
public int getLevel(@NotNull ItemStack item){
ItemMeta meta = item.getItemMeta();
if(meta == null) return 0;
return getLevel(item, meta);
}
/**
* Get current level of the enchantment.
* @param item Item to search the level for.
* @param meta Meta of the provided item. It will not be changed and not be set on the item.
* @return Current leve of this enchantment on item. or 0 if absent.
*/
public abstract int getLevel(@NotNull ItemStack item, @NotNull ItemMeta meta);
/**
* Check if this enchantment is present on the provided level.
* @param item The item to set the enchantment level.
* @return If the enchantment have been found.
*/
public boolean isEnchantmentPresent(@NotNull ItemStack item){
ItemMeta meta = item.getItemMeta();
if(meta == null) return false;
return isEnchantmentPresent(item, meta);
}
/**
* Check if this enchantment is present on the provided level.
* @param item The item to set the enchantment level.
* @param meta Meta of the provided item. It will not be changed and not be set on the item.
* @return If the enchantment have been found.
*/
public abstract boolean isEnchantmentPresent(@NotNull ItemStack item, @NotNull ItemMeta meta);
/**
* Force add an enchantment at the provided level.
* @param item The item to set the enchantment level.
* @param level The level to set the enchantment to.
*/
public abstract void addEnchantmentUnsafe(@NotNull ItemStack item, int level);
/**
* Remove this enchantment from the provided ItemStack.
* @param item The item to remove the enchantment.
*/
public abstract void removeFrom(@NotNull ItemStack item);
// Static functions
/**
* Clear every enchantment from this item.
* @param item Item to be cleared from enchantments.
*/
public static void clearEnchants(@NotNull ItemStack item){
ItemMeta meta = item.getItemMeta();
if(meta == null) return;
// Clean Vanilla enchants
if (ItemUtil.INSTANCE.isEnchantedBook(item)) {
EnchantmentStorageMeta bookMeta = (EnchantmentStorageMeta) meta;
bookMeta.getStoredEnchants().forEach(
(enchantment, leve) -> bookMeta.removeStoredEnchant(enchantment)
);
} else {
item.getEnchantments().forEach(
(enchantment, leve) -> item.removeEnchantment(enchantment)
);
}
// Clean Enchant Squared enchants
EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
if(enchantmentSquared != null){
enchantmentSquared.clearEnchantments(item);
}
// Clean unoptimised enchants
for (WrappedEnchantment enchant : unoptimisedValues()) {
if(enchant.isEnchantmentPresent(item)){
enchant.removeFrom(item);
}
}
}
/**
* Get enchantments of an item.
* @param item Item to get enchantment from.
* @return A map of the set enchantments and there's respective levels.
*/
public static Map<WrappedEnchantment, Integer> getEnchants(@NotNull ItemStack item){
Map<WrappedEnchantment, Integer> enchantments = new HashMap<>();
ItemMeta meta = item.getItemMeta();
if(meta == null) return enchantments;
// Vanilla optimised get
if (ItemUtil.INSTANCE.isEnchantedBook(item)) {
((EnchantmentStorageMeta)meta).getStoredEnchants().forEach(
(enchantment, level) -> enchantments.put(getByKey(enchantment.getKey()), level)
);
} else {
item.getEnchantments().forEach(
(enchantment, level) -> enchantments.put(getByKey(enchantment.getKey()), level)
);
}
// Enchants Squared get
EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
if(enchantmentSquared != null){
enchantmentSquared.getEnchantmentsSquared(item, enchantments);
}
// Unoptimised enchantment get
findEnchantsFromSelectedList(item, meta, enchantments, unoptimisedValues());
return enchantments;
}
/**
* Find enchantments of an item. only test the enchantment from the list.
* @param item Item to get enchantment from.
* @param meta Meta of the provided item.
* @param enchantments Map of enchantment to complete.
* @param enchantmentToTest Enchantment to test
*/
private static void findEnchantsFromSelectedList(
@NotNull ItemStack item,
@NotNull ItemMeta meta,
@NotNull Map<WrappedEnchantment, Integer> enchantments,
@NotNull Collection<WrappedEnchantment> enchantmentToTest){
for (WrappedEnchantment enchantment : enchantmentToTest) {
if(enchantment.isEnchantmentPresent(item, meta)){
enchantments.put(enchantment, enchantment.getLevel(item, meta));
}
}
}
// Register enchantment functions
private static final HashMap<NamespacedKey, WrappedEnchantment> BY_KEY = new HashMap<>();
private static final HashMap<String, WrappedEnchantment> BY_NAME = new HashMap<>();
private static final List<WrappedEnchantment> UNOPTIMISED_ENCHANTMENT = new ArrayList<>();
/**
* This should only be called on main of custom anvil.
* If called more than one time, chance of thing being broken will be high.
*/
public static void registerEnchantments(){
for (Enchantment enchantment : Enchantment.values()) {
register(new VanillaEnchantment(enchantment));
}
if(DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility() != null){
DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility().registerEnchantments();
}
}
/**
* Can be used to register new enchantment.
* <p>
* No guarantee that the enchantment will be present on the config gui if registered late.
* (By late I mean after custom anvil startup.)
* @param enchantment The enchantment to be registered.
*/
public static void register(@NotNull WrappedEnchantment enchantment){
if(BY_KEY.containsKey(enchantment.getKey())){
CustomAnvil.instance.getLogger().log(Level.WARNING,
"Duplicate registered enchantment. This should NOT happen.",
new IllegalStateException(enchantment.getKey()+" enchantment was already registered"));
return;
}
if(BY_NAME.containsKey(enchantment.getName())){
CustomAnvil.instance.getLogger().log(Level.WARNING,
"Duplicate registered enchantment name. There will have issue. " +
"\nI hope this do not happen to you on a production server. If it do, there is probably a plugin trying to register an enchantment with the same name than another one",
new IllegalStateException(enchantment.getKey()+" enchantment name was already registered"));
}
BY_KEY.put(enchantment.getKey(), enchantment);
BY_NAME.put(enchantment.getName(), enchantment);
if(!enchantment.isOptimised()){
UNOPTIMISED_ENCHANTMENT.add(enchantment);
}
}
/**
* Can be used to unregister new enchantment.
* Please be cautious with this function.
* It should probably rarely be used.
* <p>
* No guarantee that the enchantment will absent if the config guis if unregistered late.
* (By late I mean after custom anvil startup.)
* @param enchantment The enchantment to be unregistered.
*/
public static void unregister(@NotNull WrappedEnchantment enchantment){
BY_KEY.remove(enchantment.getKey());
BY_NAME.remove(enchantment.getName());
}
/**
* Gets the enchantment by the provided key.
* @param key Key to fetch.
* @return Registered enchantment. null if absent.
*/
public static @Nullable WrappedEnchantment getByKey(@NotNull NamespacedKey key){
return BY_KEY.get(key);
}
/**
* Gets the enchantment by the provided name.
* @param name Name to fetch.
* @return Registered enchantment. null if absent.
*/
public static @Nullable WrappedEnchantment getByName(@NotNull String name){
return BY_NAME.get(name);
}
/**
* Gets an array of all the registered enchantments.
* @return Array of enchantment.
*/
@NotNull
public static WrappedEnchantment[] values() {
return BY_KEY.values().toArray(new WrappedEnchantment[0]);
}
/**
* Gets a list of all the unoptimised enchantments.
* @return List of enchantment.
*/
@NotNull
private static List<WrappedEnchantment> unoptimisedValues() {
return UNOPTIMISED_ENCHANTMENT;
}
}

View file

@ -0,0 +1,59 @@
package xyz.alexcrea.cuanvil.enchant.wrapped;
import com.willfp.ecoenchants.enchant.EcoEnchant;
import com.willfp.ecoenchants.target.EnchantmentTarget;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
import xyz.alexcrea.cuanvil.group.ConflictType;
import java.util.Map;
import java.util.function.Supplier;
public class CAEcoEnchant extends CAVanillaEnchantment implements AdditionalTestEnchantment {
private final @NotNull EcoEnchant ecoEnchant;
public CAEcoEnchant(@NotNull EcoEnchant enchant) {
super(enchant.getEnchantment(), EnchantmentRarity.COMMON);
this.ecoEnchant = enchant;
}
@Override
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
if(!enchantments.isEmpty()) {
if (this.ecoEnchant.getConflictsWithEverything()) {
return true;
}
for (CAEnchantment other : enchantments.keySet()) {
if(other instanceof CAVanillaEnchantment otherVanilla
&& this.ecoEnchant.conflictsWith(otherVanilla.getEnchant())){
return true;
}
}
}
return false;
}
@Override
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments,
@NotNull Material itemMat,
@NotNull ItemStack item) {
if(Material.ENCHANTED_BOOK.equals(itemMat)){
return false;
}
for (EnchantmentTarget target : this.ecoEnchant.getTargets()) {
if(target.matches(item)){
return false;
}
}
return true;
}
}

View file

@ -8,16 +8,16 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.dependency.DependencyManager; import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentBase;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
public class EnchantSquaredEnchantment extends WrappedEnchantment { public class CAEnchantSquaredEnchantment extends CAEnchantmentBase {
public final @NotNull CustomEnchant enchant; public final @NotNull CustomEnchant enchant;
public EnchantSquaredEnchantment(@NotNull CustomEnchant enchant) { public CAEnchantSquaredEnchantment(@NotNull CustomEnchant enchant) {
super(Objects.requireNonNull( super(Objects.requireNonNull(
Objects.requireNonNull(DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility()).getKeyFromEnchant(enchant)), Objects.requireNonNull(DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility()).getKeyFromEnchant(enchant)),
EnchantmentRarity.COMMON, EnchantmentRarity.COMMON,
@ -27,7 +27,7 @@ public class EnchantSquaredEnchantment extends WrappedEnchantment {
} }
@Override @Override
protected boolean isOptimised() { public boolean isOptimised() {
return true; return true;
} }

View file

@ -6,26 +6,30 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentBase;
import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties; import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment;
import java.util.Locale; import java.util.Locale;
public class VanillaEnchantment extends WrappedEnchantment { public class CAVanillaEnchantment extends CAEnchantmentBase {
private final @NotNull Enchantment enchantment; private final @NotNull Enchantment enchantment;
public VanillaEnchantment(@NotNull Enchantment enchantment){ public CAVanillaEnchantment(@NotNull Enchantment enchantment, @Nullable EnchantmentRarity rarity){
super(enchantment.getKey(), super(enchantment.getKey(),
getRarity(enchantment), rarity,
enchantment.getMaxLevel()); enchantment.getMaxLevel());
this.enchantment = enchantment; this.enchantment = enchantment;
}
public CAVanillaEnchantment(@NotNull Enchantment enchantment){
this(enchantment, getRarity(enchantment));
} }
@Override @Override
protected boolean isOptimised() { public boolean isOptimised() {
return true; return true;
} }
@ -77,6 +81,7 @@ public class VanillaEnchantment extends WrappedEnchantment {
} }
@NotNull
public static EnchantmentRarity getRarity(Enchantment enchantment){ public static EnchantmentRarity getRarity(Enchantment enchantment){
try { try {
return EnchantmentProperties.valueOf(enchantment.getKey().getKey().toUpperCase(Locale.ENGLISH)).getRarity(); return EnchantmentProperties.valueOf(enchantment.getKey().getKey().toUpperCase(Locale.ENGLISH)).getRarity();
@ -85,4 +90,8 @@ public class VanillaEnchantment extends WrappedEnchantment {
} }
} }
@NotNull
protected Enchantment getEnchant() {
return this.enchantment;
}
} }

View file

@ -1,15 +1,15 @@
package xyz.alexcrea.cuanvil.gui.config; package xyz.alexcrea.cuanvil.gui.config;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import java.util.Set; import java.util.Set;
public interface SelectEnchantmentContainer { public interface SelectEnchantmentContainer {
Set<WrappedEnchantment> getSelectedEnchantments(); Set<CAEnchantment> getSelectedEnchantments();
boolean setSelectedEnchantments(Set<WrappedEnchantment> enchantments); boolean setSelectedEnchantments(Set<CAEnchantment> enchantments);
Set<WrappedEnchantment> illegalEnchantments(); Set<CAEnchantment> illegalEnchantments();
} }

View file

@ -3,7 +3,7 @@ package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem; import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import com.github.stefvanschie.inventoryframework.pane.util.Pattern; import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
@ -19,7 +19,7 @@ import java.util.function.Consumer;
* *
* @param <T> Type of the factory of the type of setting the gui should edit. * @param <T> Type of the factory of the type of setting the gui should edit.
*/ */
public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFactory> extends SettingGuiListConfigGui<WrappedEnchantment, T> implements ValueUpdatableGui { public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFactory> extends SettingGuiListConfigGui<CAEnchantment, T> implements ValueUpdatableGui {
/** /**
* Constructor for a gui displaying available enchantment to edit a enchantment setting. * Constructor for a gui displaying available enchantment to edit a enchantment setting.
@ -36,7 +36,7 @@ public abstract class AbstractEnchantConfigGui<T extends SettingGui.SettingGuiFa
} }
@Override @Override
protected Collection<WrappedEnchantment> getEveryDisplayableInstanceOfGeneric() { protected Collection<CAEnchantment> getEveryDisplayableInstanceOfGeneric() {
return GuiSharedConstant.SORTED_ENCHANTMENT_LIST; return GuiSharedConstant.SORTED_ENCHANTMENT_LIST;
} }

View file

@ -13,7 +13,6 @@ import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List;
public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRecipe, CustomRecipeSubSettingGui> { public class CustomRecipeConfigGui extends MappedGuiListConfigGui<AnvilCustomRecipe, CustomRecipeSubSettingGui> {

View file

@ -15,7 +15,6 @@ import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List;
public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGroup, EnchantConflictSubSettingGui> { public class EnchantConflictGui extends MappedGuiListConfigGui<EnchantConflictGroup, EnchantConflictSubSettingGui> {

View file

@ -5,14 +5,17 @@ import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import xyz.alexcrea.cuanvil.config.ConfigHolder; import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties; import xyz.alexcrea.cuanvil.enchant.EnchantmentProperties;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment;
import xyz.alexcrea.cuanvil.gui.config.settings.EnchantCostSettingsGui; import xyz.alexcrea.cuanvil.gui.config.settings.EnchantCostSettingsGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
/** /**
* Global Config gui for enchantment cost settings. * Global Config gui for enchantment cost settings.
@ -36,7 +39,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
} }
@Override @Override
public EnchantCostSettingsGui.EnchantCostSettingFactory createFactory(WrappedEnchantment enchant) { public EnchantCostSettingsGui.EnchantCostSettingFactory createFactory(CAEnchantment enchant) {
String key = enchant.getKey().getKey().toLowerCase(Locale.ENGLISH); String key = enchant.getKey().getKey().toLowerCase(Locale.ENGLISH);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key); String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key);
@ -59,7 +62,7 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
} }
@Override @Override
public GuiItem itemFromFactory(WrappedEnchantment enchantment, EnchantCostSettingsGui.EnchantCostSettingFactory factory) { public GuiItem itemFromFactory(CAEnchantment enchantment, EnchantCostSettingsGui.EnchantCostSettingFactory factory) {
// Get item properties // Get item properties
int itemCost = factory.getConfiguredValue(); int itemCost = factory.getConfiguredValue();
int bookCost = factory.getConfiguredBookValue(); int bookCost = factory.getConfiguredBookValue();

View file

@ -3,7 +3,7 @@ package xyz.alexcrea.cuanvil.gui.config.global;
import com.github.stefvanschie.inventoryframework.gui.GuiItem; import com.github.stefvanschie.inventoryframework.gui.GuiItem;
import org.bukkit.Material; import org.bukkit.Material;
import xyz.alexcrea.cuanvil.config.ConfigHolder; import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui; import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
import xyz.alexcrea.cuanvil.util.CasedStringUtil; import xyz.alexcrea.cuanvil.util.CasedStringUtil;
@ -32,7 +32,7 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
} }
@Override @Override
public IntSettingsGui.IntSettingFactory createFactory(WrappedEnchantment enchant) { public IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant) {
String key = enchant.getKey().getKey().toLowerCase(Locale.ROOT); String key = enchant.getKey().getKey().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key); String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key);
@ -47,7 +47,7 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
} }
@Override @Override
public GuiItem itemFromFactory(WrappedEnchantment enchantment, IntSettingsGui.IntSettingFactory inventoryFactory) { public GuiItem itemFromFactory(CAEnchantment enchantment, IntSettingsGui.IntSettingFactory inventoryFactory) {
return inventoryFactory.getItem( return inventoryFactory.getItem(
Material.ENCHANTED_BOOK, Material.ENCHANTED_BOOK,
inventoryFactory.getTitle()); inventoryFactory.getTitle());

View file

@ -17,7 +17,6 @@ import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List;
public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, GroupConfigSubSettingGui> { public class GroupConfigGui extends MappedGuiListConfigGui<IncludeGroup, GroupConfigSubSettingGui> {

View file

@ -15,7 +15,6 @@ import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List;
public class UnitRepairConfigGui extends MappedGuiListConfigGui<Material, UnitRepairElementListGui> { public class UnitRepairConfigGui extends MappedGuiListConfigGui<Material, UnitRepairElementListGui> {

View file

@ -20,7 +20,10 @@ import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.UUID;
public abstract class ElementListConfigGui< T > extends ChestGui implements ValueUpdatableGui { public abstract class ElementListConfigGui< T > extends ChestGui implements ValueUpdatableGui {

View file

@ -10,7 +10,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder; import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup; import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import xyz.alexcrea.cuanvil.group.EnchantConflictManager; import xyz.alexcrea.cuanvil.group.EnchantConflictManager;
@ -117,9 +117,9 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
Supplier<Boolean> deleteSupplier = () -> { Supplier<Boolean> deleteSupplier = () -> {
EnchantConflictManager manager = ConfigHolder.CONFLICT_HOLDER.getConflictManager(); EnchantConflictManager manager = ConfigHolder.CONFLICT_HOLDER.getConflictManager();
// Remove from manager // Remove from enchantment
for (WrappedEnchantment enchantment : this.enchantConflict.getEnchants()) { for (CAEnchantment enchantment : this.enchantConflict.getEnchants()) {
manager.removeConflictFromMap(enchantment, this.enchantConflict); enchantment.removeConflict(this.enchantConflict);
} }
manager.conflictList.remove(this.enchantConflict); manager.conflictList.remove(this.enchantConflict);
@ -164,12 +164,12 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
// Prepare enchantment lore // Prepare enchantment lore
ArrayList<String> enchantLore = new ArrayList<>(); ArrayList<String> enchantLore = new ArrayList<>();
enchantLore.add("\u00A77Allow you to select a list of \u00A75Enchantments \u00A77that this conflict should include"); enchantLore.add("\u00A77Allow you to select a list of \u00A75Enchantments \u00A77that this conflict should include");
Set<WrappedEnchantment> enchants = getSelectedEnchantments(); Set<CAEnchantment> enchants = getSelectedEnchantments();
if (enchants.isEmpty()) { if (enchants.isEmpty()) {
enchantLore.add("\u00A77There is no included enchantment for this conflict."); enchantLore.add("\u00A77There is no included enchantment for this conflict.");
} else { } else {
enchantLore.add("\u00A77List of included enchantment for this conflict:"); enchantLore.add("\u00A77List of included enchantment for this conflict:");
Iterator<WrappedEnchantment> enchantIterator = enchants.iterator(); Iterator<CAEnchantment> enchantIterator = enchants.iterator();
boolean greaterThanMax = enchants.size() > 5; boolean greaterThanMax = enchants.size() > 5;
int maxindex = (greaterThanMax ? 4 : enchants.size()); int maxindex = (greaterThanMax ? 4 : enchants.size());
@ -243,12 +243,12 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
// Select enchantment container methods // Select enchantment container methods
@Override @Override
public Set<WrappedEnchantment> getSelectedEnchantments() { public Set<CAEnchantment> getSelectedEnchantments() {
return this.enchantConflict.getEnchants(); return this.enchantConflict.getEnchants();
} }
@Override @Override
public boolean setSelectedEnchantments(Set<WrappedEnchantment> enchantments) { public boolean setSelectedEnchantments(Set<CAEnchantment> enchantments) {
if (!this.shouldWork) { if (!this.shouldWork) {
CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed"); CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict + " enchants but sub config is destroyed");
return false; return false;
@ -260,7 +260,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
// Save on file configuration // Save on file configuration
String[] enchantKeys = new String[enchantments.size()]; String[] enchantKeys = new String[enchantments.size()];
int index = 0; int index = 0;
for (WrappedEnchantment enchantment : enchantments) { for (CAEnchantment enchantment : enchantments) {
enchantKeys[index++] = enchantment.getKey().getKey(); enchantKeys[index++] = enchantment.getKey().getKey();
} }
ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict + ".enchantments", enchantKeys); ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict + ".enchantments", enchantKeys);
@ -280,7 +280,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
} }
@Override @Override
public Set<WrappedEnchantment> illegalEnchantments() { public Set<CAEnchantment> illegalEnchantments() {
return Collections.emptySet(); return Collections.emptySet();
} }

View file

@ -12,7 +12,8 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder; import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer; import xyz.alexcrea.cuanvil.gui.config.SelectEnchantmentContainer;
import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui; import xyz.alexcrea.cuanvil.gui.config.list.SettingGuiListConfigGui;
@ -22,14 +23,13 @@ import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class EnchantSelectSettingGui extends SettingGuiListConfigGui<WrappedEnchantment, EnchantSelectSettingGui.DummyFactory> implements SettingGui { public class EnchantSelectSettingGui extends SettingGuiListConfigGui<CAEnchantment, EnchantSelectSettingGui.DummyFactory> implements SettingGui {
private final SelectEnchantmentContainer enchantContainer; private final SelectEnchantmentContainer enchantContainer;
private final Set<WrappedEnchantment> selectedEnchant; private final Set<CAEnchantment> selectedEnchant;
private final GuiItem saveItem; private final GuiItem saveItem;
private boolean displayUnselected; private boolean displayUnselected;
@ -62,19 +62,19 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<WrappedEnch
} }
@Override @Override
protected Collection<WrappedEnchantment> getEveryDisplayableInstanceOfGeneric() { protected Collection<CAEnchantment> getEveryDisplayableInstanceOfGeneric() {
Stream<WrappedEnchantment> toDisplayStream; Stream<CAEnchantment> toDisplayStream;
if(this.displayUnselected){ if(this.displayUnselected){
toDisplayStream = Arrays.stream(WrappedEnchantment.values()); toDisplayStream = CAEnchantmentRegistry.getInstance().values().stream();
}else{ }else{
toDisplayStream = this.selectedEnchant.stream(); toDisplayStream = this.selectedEnchant.stream();
} }
Set<WrappedEnchantment> illegalEnchantments = this.enchantContainer.illegalEnchantments(); Set<CAEnchantment> illegalEnchantments = this.enchantContainer.illegalEnchantments();
return toDisplayStream return toDisplayStream
.filter(enchantment -> !illegalEnchantments.contains(enchantment)) .filter(enchantment -> !illegalEnchantments.contains(enchantment))
.collect(Collectors.toList()); .toList();
} }
@Override @Override
@ -84,7 +84,7 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<WrappedEnch
} }
@Override @Override
protected GuiItem itemFromFactory(WrappedEnchantment enchantment, DummyFactory factory) { protected GuiItem itemFromFactory(CAEnchantment enchantment, DummyFactory factory) {
boolean isIn = this.selectedEnchant.contains(enchantment); boolean isIn = this.selectedEnchant.contains(enchantment);
Material usedMaterial; Material usedMaterial;
@ -151,7 +151,7 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<WrappedEnch
item.setItemMeta(meta); item.setItemMeta(meta);
} }
private Consumer<InventoryClickEvent> getEnchantItemConsumer(WrappedEnchantment enchant, GuiItem guiItem) { private Consumer<InventoryClickEvent> getEnchantItemConsumer(CAEnchantment enchant, GuiItem guiItem) {
return event -> { return event -> {
event.setCancelled(true); event.setCancelled(true);
@ -180,7 +180,7 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<WrappedEnch
@Override @Override
public boolean hadChange() { public boolean hadChange() {
Set<WrappedEnchantment> baseGroup = this.enchantContainer.getSelectedEnchantments(); Set<CAEnchantment> baseGroup = this.enchantContainer.getSelectedEnchantments();
return baseGroup.size() != this.selectedEnchant.size() || return baseGroup.size() != this.selectedEnchant.size() ||
!baseGroup.containsAll(this.selectedEnchant); !baseGroup.containsAll(this.selectedEnchant);
} }
@ -209,7 +209,7 @@ public class EnchantSelectSettingGui extends SettingGuiListConfigGui<WrappedEnch
return null; return null;
} }
@Override @Override
protected DummyFactory createFactory(WrappedEnchantment generic) { protected DummyFactory createFactory(CAEnchantment generic) {
return null; return null;
} }

View file

@ -6,7 +6,6 @@ import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;

View file

@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui; import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
import xyz.alexcrea.cuanvil.gui.config.settings.AbstractSettingGui;
import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui; import xyz.alexcrea.cuanvil.gui.config.settings.SettingGui;
import java.util.ArrayList; import java.util.ArrayList;

View file

@ -7,20 +7,18 @@ import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
import java.util.Arrays; import java.util.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class GuiSharedConstant { public class GuiSharedConstant {
public static final List<WrappedEnchantment> SORTED_ENCHANTMENT_LIST; public static final List<CAEnchantment> SORTED_ENCHANTMENT_LIST;
static { static {
SORTED_ENCHANTMENT_LIST = Arrays.asList(WrappedEnchantment.values()); SORTED_ENCHANTMENT_LIST = new ArrayList<>(CAEnchantmentRegistry.getInstance().values());
SORTED_ENCHANTMENT_LIST.sort(Comparator.comparing(ench -> ench.getKey().getKey())); SORTED_ENCHANTMENT_LIST.sort(Comparator.comparing(ench -> ench.getKey().getKey()));
} }

View file

@ -99,7 +99,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
// Test for merge // Test for merge
if (first.canMergeWith(second)) { if (first.canMergeWith(second)) {
val newEnchants = first.findEnchantments() val newEnchants = first.findEnchantments()
.combineWith(second.findEnchantments(), first.type, player) .combineWith(second.findEnchantments(), first, player)
val resultItem = first.clone() val resultItem = first.clone()
resultItem.setEnchantmentsUnsafe(newEnchants) resultItem.setEnchantmentsUnsafe(newEnchants)
@ -436,20 +436,20 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
val rightIsFormBook = right.isEnchantedBook() val rightIsFormBook = right.isEnchantedBook()
val resultEnchs = result.findEnchantments() val resultEnchs = result.findEnchantments()
val resultEnchsKeys = HashSet(resultEnchs.keys) val resultEnchsKeys = HashMap(resultEnchs)
for (enchantment in right.findEnchantments()) { for (enchantment in right.findEnchantments()) {
// count enchant as illegal enchant if it conflicts with another enchant or not in result // count enchant as illegal enchant if it conflicts with another enchant or not in result
if ((enchantment.key !in resultEnchsKeys)) { if ((enchantment.key !in resultEnchsKeys)) {
resultEnchsKeys.add(enchantment.key) resultEnchsKeys[enchantment.key] = enchantment.value
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting( val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(
resultEnchsKeys, resultEnchsKeys,
result.type, result,
enchantment.key enchantment.key
) )
resultEnchsKeys.remove(enchantment.key) resultEnchsKeys.remove(enchantment.key)
if (ConflictType.BIG_CONFLICT == conflictType) { if (ConflictType.ENCHANTMENT_CONFLICT == conflictType) {
illegalPenalty += ConfigOptions.sacrificeIllegalCost illegalPenalty += ConfigOptions.sacrificeIllegalCost
CustomAnvil.verboseLog("Big conflict. Adding illegal price penalty") CustomAnvil.verboseLog("Big conflict. Adding illegal price penalty")
} }

View file

@ -8,7 +8,7 @@ import xyz.alexcrea.cuanvil.command.EditConfigExecutor
import xyz.alexcrea.cuanvil.command.ReloadExecutor import xyz.alexcrea.cuanvil.command.ReloadExecutor
import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant
import xyz.alexcrea.cuanvil.listener.ChatEventListener import xyz.alexcrea.cuanvil.listener.ChatEventListener
@ -94,7 +94,7 @@ class CustomAnvil : JavaPlugin() {
DependencyManager.loadDependency() DependencyManager.loadDependency()
// Register enchantments // Register enchantments
WrappedEnchantment.registerEnchantments() CAEnchantmentRegistry.getInstance().registerStartupEnchantments()
// Load chat listener // Load chat listener
chatListener = ChatEventListener() chatListener = ChatEventListener()
@ -108,7 +108,7 @@ class CustomAnvil : JavaPlugin() {
Update_1_21.handleUpdate() Update_1_21.handleUpdate()
// Handle custom enchant config // Handle custom enchant config
DependencyManager.handleConfigChanges() DependencyManager.handleConfigChanges(this)
// Load gui constants //TODO maybe something better later // Load gui constants //TODO maybe something better later
MainConfigGui.getInstance().init(DependencyManager.packetManager) MainConfigGui.getInstance().init(DependencyManager.packetManager)

View file

@ -3,7 +3,7 @@ package io.delilaheve.util
import io.delilaheve.CustomAnvil import io.delilaheve.CustomAnvil
import io.delilaheve.util.EnchantmentUtil.enchantmentName import io.delilaheve.util.EnchantmentUtil.enchantmentName
import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment
/** /**
* Config option accessors * Config option accessors
@ -239,7 +239,7 @@ object ConfigOptions {
/** /**
* Get the given [enchantment]'s limit * Get the given [enchantment]'s limit
*/ */
fun enchantLimit(enchantment: WrappedEnchantment): Int { fun enchantLimit(enchantment: CAEnchantment): Int {
return enchantLimit(enchantment.enchantmentName) return enchantLimit(enchantment.enchantmentName)
} }
@ -273,7 +273,7 @@ object ConfigOptions {
* it's source [isFromBook] * it's source [isFromBook]
*/ */
fun enchantmentValue( fun enchantmentValue(
enchantment: WrappedEnchantment, enchantment: CAEnchantment,
isFromBook: Boolean isFromBook: Boolean
): Int { ): Int {
return enchantmentValue(enchantment.enchantmentName, isFromBook) return enchantmentValue(enchantment.enchantmentName, isFromBook)
@ -307,7 +307,7 @@ object ConfigOptions {
return enchantmentValue("sweeping", isFromBook) return enchantmentValue("sweeping", isFromBook)
} }
val enchantment = WrappedEnchantment.getByName(enchantmentName) val enchantment = CAEnchantment.getByName(enchantmentName)
if(enchantment != null){ if(enchantment != null){
val rarity = enchantment.defaultRarity() val rarity = enchantment.defaultRarity()

View file

@ -1,10 +1,10 @@
package io.delilaheve.util package io.delilaheve.util
import io.delilaheve.CustomAnvil import io.delilaheve.CustomAnvil
import org.bukkit.Material
import org.bukkit.entity.HumanEntity import org.bukkit.entity.HumanEntity
import org.bukkit.inventory.ItemStack
import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.group.ConflictType import xyz.alexcrea.cuanvil.group.ConflictType
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -17,18 +17,19 @@ object EnchantmentUtil {
/** /**
* Enchantment name without namespace * Enchantment name without namespace
*/ */
val WrappedEnchantment.enchantmentName: String val CAEnchantment.enchantmentName: String
get() = key.key get() = key.key
/** /**
* Combine 2 sets of enchantments according to our configuration * Combine 2 sets of enchantments according to our configuration
*/ */
fun Map<WrappedEnchantment, Int>.combineWith( fun Map<CAEnchantment, Int>.combineWith(
other: Map<WrappedEnchantment, Int>, other: Map<CAEnchantment, Int>,
mat: Material, item: ItemStack,
player: HumanEntity player: HumanEntity
) = mutableMapOf<WrappedEnchantment, Int>().apply { ) = mutableMapOf<CAEnchantment, Int>().apply {
putAll(this@combineWith) putAll(this@combineWith)
other.forEach { (enchantment, level) -> other.forEach { (enchantment, level) ->
if(!enchantment.isAllowed(player)) return@forEach if(!enchantment.isAllowed(player)) return@forEach
@ -44,7 +45,7 @@ object EnchantmentUtil {
// Add the enchantment if it doesn't have conflicts, or if player is allowed to bypass enchantment restrictions // Add the enchantment if it doesn't have conflicts, or if player is allowed to bypass enchantment restrictions
this[enchantment] = cappedLevel this[enchantment] = cappedLevel
val conflictType = val conflictType =
ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys, mat, enchantment) ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this, item, enchantment)
if (!player.hasPermission(CustomAnvil.bypassFusePermission) && if (!player.hasPermission(CustomAnvil.bypassFusePermission) &&
(conflictType != ConflictType.NO_CONFLICT) (conflictType != ConflictType.NO_CONFLICT)
) { ) {
@ -55,11 +56,11 @@ object EnchantmentUtil {
} }
// Enchantment already in result list // Enchantment already in result list
else { else {
val oldLevel = this[enchantment]!! // <- should not be null. see the comment above val oldLevel = this[enchantment]!! // <- should not be null. (enchantment already in result list)
// ... and they are conflicting // ... and they are conflicting
val conflictType = val conflictType =
ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys, mat, enchantment) ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this, item, enchantment)
if ((conflictType != ConflictType.NO_CONFLICT) if ((conflictType != ConflictType.NO_CONFLICT)
&& !player.hasPermission(CustomAnvil.bypassFusePermission) && !player.hasPermission(CustomAnvil.bypassFusePermission)
) { ) {

View file

@ -3,7 +3,7 @@ package io.delilaheve.util
import org.bukkit.Material.ENCHANTED_BOOK import org.bukkit.Material.ENCHANTED_BOOK
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.Damageable import org.bukkit.inventory.meta.Damageable
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -21,13 +21,13 @@ object ItemUtil {
/** /**
* Find the enchantment map for this [ItemStack] and return it as a [MutableMap] * Find the enchantment map for this [ItemStack] and return it as a [MutableMap]
*/ */
fun ItemStack.findEnchantments(): MutableMap<WrappedEnchantment, Int> = WrappedEnchantment.getEnchants(this) fun ItemStack.findEnchantments(): MutableMap<CAEnchantment, Int> = CAEnchantment.getEnchants(this)
/** /**
* Apply an [enchantments] map to this [ItemStack] * Apply an [enchantments] map to this [ItemStack]
*/ */
fun ItemStack.setEnchantmentsUnsafe(enchantments: Map<WrappedEnchantment, Int>) { fun ItemStack.setEnchantmentsUnsafe(enchantments: Map<CAEnchantment, Int>) {
WrappedEnchantment.clearEnchants(this) CAEnchantment.clearEnchants(this)
//TODO maybe faster methode to add vanilla enchantment. maybe move this function to wrapped enchantment //TODO maybe faster methode to add vanilla enchantment. maybe move this function to wrapped enchantment
enchantments.forEach { (enchantment, level) -> enchantments.forEach { (enchantment, level) ->

View file

@ -1,14 +1,17 @@
package xyz.alexcrea.cuanvil.dependency package xyz.alexcrea.cuanvil.dependency
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.plugin.Plugin
import xyz.alexcrea.cuanvil.dependency.protocolib.NoProtocoLib import xyz.alexcrea.cuanvil.dependency.protocolib.NoProtocoLib
import xyz.alexcrea.cuanvil.dependency.protocolib.PacketManager import xyz.alexcrea.cuanvil.dependency.protocolib.PacketManager
import xyz.alexcrea.cuanvil.dependency.protocolib.ProtocoLibWrapper import xyz.alexcrea.cuanvil.dependency.protocolib.ProtocoLibWrapper
import java.io.File
object DependencyManager { object DependencyManager {
lateinit var packetManager: PacketManager lateinit var packetManager: PacketManager
var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null
var ecoEnchantCompatibility: EcoEnchantDependency? = null
fun loadDependency(){ fun loadDependency(){
val pluginManager = Bukkit.getPluginManager() val pluginManager = Bukkit.getPluginManager()
@ -24,11 +27,19 @@ object DependencyManager {
enchantmentSquaredCompatibility!!.disableAnvilListener() enchantmentSquaredCompatibility!!.disableAnvilListener()
} }
// EcoEnchants dependency
if(pluginManager.isPluginEnabled("EcoEnchants")){
ecoEnchantCompatibility = EcoEnchantDependency(pluginManager.getPlugin("EcoEnchants")!!)
ecoEnchantCompatibility!!.disableAnvilListener()
} }
fun handleConfigChanges() { }
fun handleConfigChanges(plugin: Plugin) {
val folder = File(plugin.dataFolder, "compatibility")
enchantmentSquaredCompatibility?.registerPluginConfiguration() enchantmentSquaredCompatibility?.registerPluginConfiguration()
ecoEnchantCompatibility?.registerPluginConfiguration(folder)
} }

View file

@ -0,0 +1,78 @@
package xyz.alexcrea.cuanvil.dependency
import com.willfp.ecoenchants.enchant.EcoEnchants
import io.delilaheve.CustomAnvil
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.plugin.Plugin
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import xyz.alexcrea.cuanvil.enchant.wrapped.CAEcoEnchant
import java.io.File
class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) {
init {
CustomAnvil.instance.logger.info("Eco Enchant Detected !")
}
fun disableAnvilListener(){
PrepareAnvilEvent.getHandlerList().unregister(this.ecoEnchantPlugin)
}
fun registerEnchantments() {
val registery = CAEnchantmentRegistry.getInstance()
for (ecoEnchant in EcoEnchants.values()) {
val enchantments: CAEnchantment = CAEcoEnchant(ecoEnchant)
registery.unregister(registery.getByKey(ecoEnchant.enchantment.key)) // As eco enchants are considered real enchantment, we need to unregister it.
registery.register(enchantments)
}
}
fun registerPluginConfiguration(folder: File){
val compatibilityFile = File(folder, "ecoEnchant.yml")
if(compatibilityFile.exists()){
folder.mkdirs()
compatibilityFile.createNewFile()
}
val config = YamlConfiguration.loadConfiguration(compatibilityFile)
val defaultConfig = ConfigHolder.DEFAULT_CONFIG.config
var doSave = false
for (ecoEnchant in EcoEnchants.values()) {
val enchantment = CAEnchantmentRegistry.getInstance().getByKey(ecoEnchant.enchantmentKey)
if(enchantment == null){
CustomAnvil.instance.logger.warning("Could not find " + ecoEnchant.enchantmentKey + "testing compatibility.")
continue
}
// Write enchantment value if needed
val testPath = "default.${enchantment.key.key}"
if(!config.getBoolean(testPath, false)){
doSave = true
config[testPath] = true
defaultConfig["enchant_limits.${enchantment.key.key}"] = enchantment.defaultMaxLevel()
val rarity = enchantment.defaultRarity()
defaultConfig["enchant_values.${enchantment.key.key}.item"] = rarity.itemValue
defaultConfig["enchant_values.${enchantment.key.key}.book"] = rarity.bookValue
}
}
if(doSave){
config.save(compatibilityFile)
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true)
CustomAnvil.instance.logger.info("Saved default for new eco enchant enchantments.")
}
}
}

View file

@ -8,16 +8,14 @@ import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import org.bukkit.plugin.Plugin import org.bukkit.plugin.Plugin
import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.enchant.wrapped.EnchantSquaredEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import xyz.alexcrea.cuanvil.enchant.wrapped.CAEnchantSquaredEnchantment
import java.util.* import java.util.*
import kotlin.collections.ArrayList
class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin) { class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin) {
fun disableAnvilListener(){ init {
PrepareAnvilEvent.getHandlerList().unregister(this.enchantmentSquaredPlugin)
CustomAnvil.instance.logger.info("Enchantment Squared Detected !") CustomAnvil.instance.logger.info("Enchantment Squared Detected !")
CustomAnvil.instance.logger.info("Please be aware that Custom Anvil is bypassing Enchantment Squared ") CustomAnvil.instance.logger.info("Please be aware that Custom Anvil is bypassing Enchantment Squared ")
CustomAnvil.instance.logger.info( CustomAnvil.instance.logger.info(
@ -28,14 +26,22 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
"configuration values.") "configuration values.")
} }
fun disableAnvilListener(){
PrepareAnvilEvent.getHandlerList().unregister(this.enchantmentSquaredPlugin)
}
fun registerEnchantments(){ fun registerEnchantments(){
for (enchant in CustomEnchantManager.getInstance().allEnchants.values) { for (enchant in CustomEnchantManager.getInstance().allEnchants.values) {
WrappedEnchantment.register(EnchantSquaredEnchantment(enchant)) CAEnchantmentRegistry.getInstance().register(
CAEnchantSquaredEnchantment(
enchant
)
)
} }
} }
fun getEnchantmentsSquared(item: ItemStack, enchantments: MutableMap<WrappedEnchantment, Int>) { fun getEnchantmentsSquared(item: ItemStack, enchantments: MutableMap<CAEnchantment, Int>) {
val customEnchants = CustomEnchantManager.getInstance().getItemsEnchantsFromPDC(item) val customEnchants = CustomEnchantManager.getInstance().getItemsEnchantsFromPDC(item)
customEnchants.forEach{ customEnchants.forEach{
@ -51,8 +57,8 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
fun getKeyFromEnchant(enchant: CustomEnchant): NamespacedKey{ fun getKeyFromEnchant(enchant: CustomEnchant): NamespacedKey{
return NamespacedKey.fromString(enchant.type.lowercase(Locale.getDefault()), this.enchantmentSquaredPlugin)!! return NamespacedKey.fromString(enchant.type.lowercase(Locale.getDefault()), this.enchantmentSquaredPlugin)!!
} }
private fun getWrappedEnchant(enchant: CustomEnchant): WrappedEnchantment{ private fun getWrappedEnchant(enchant: CustomEnchant): CAEnchantment {
return WrappedEnchantment.getByKey(getKeyFromEnchant(enchant))!! return CAEnchantment.getByKey(getKeyFromEnchant(enchant))!!
} }
@ -65,9 +71,9 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
CustomAnvil.instance.logger.info("Preparing configuration for Enchantment Squared...") CustomAnvil.instance.logger.info("Preparing configuration for Enchantment Squared...")
// Prepare enchantments // Prepare enchantments
val esEnchantments = ArrayList<EnchantSquaredEnchantment>() val esEnchantments = ArrayList<CAEnchantSquaredEnchantment>()
CustomEnchantManager.getInstance().allEnchants.forEach { (_, enchant) -> CustomEnchantManager.getInstance().allEnchants.forEach { (_, enchant) ->
esEnchantments.add(getWrappedEnchant(enchant) as EnchantSquaredEnchantment) esEnchantments.add(getWrappedEnchant(enchant) as CAEnchantSquaredEnchantment)
} }
// Write default level limit and xp cost // Write default level limit and xp cost
@ -114,7 +120,7 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
if(!groupConfig.isConfigurationSection("hoes")){ if(!groupConfig.isConfigurationSection("hoes")){
groupConfig["hoes.type"] = "include" groupConfig["hoes.type"] = "include"
groupConfig["hoes.items"] = listOf("wooden_hoe", "stone_ho", "iron_hoe", "diamond_hoe", "golden_hoe", "netherite_hoe") groupConfig["hoes.items"] = listOf("wooden_hoe", "stone_hoe", "iron_hoe", "diamond_hoe", "golden_hoe", "netherite_hoe")
} }
if(!groupConfig.isConfigurationSection("shield")){ if(!groupConfig.isConfigurationSection("shield")){
@ -134,7 +140,7 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
} }
private fun writeMaterialRestriction(esEnchantments: List<EnchantSquaredEnchantment>){ private fun writeMaterialRestriction(esEnchantments: List<CAEnchantSquaredEnchantment>){
val conflictConfig = ConfigHolder.CONFLICT_HOLDER.config val conflictConfig = ConfigHolder.CONFLICT_HOLDER.config
for (enchantment in esEnchantments) { for (enchantment in esEnchantments) {
val restrictionName = "restriction_${enchantment.key.key}" val restrictionName = "restriction_${enchantment.key.key}"
@ -158,9 +164,9 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
} }
} }
private fun writeEnchantmentConflicts(esEnchantments: List<EnchantSquaredEnchantment>){ private fun writeEnchantmentConflicts(esEnchantments: List<CAEnchantSquaredEnchantment>){
val otherEnchants = ArrayList<WrappedEnchantment>() val otherEnchants = ArrayList<CAEnchantment>()
otherEnchants.addAll(WrappedEnchantment.values()) otherEnchants.addAll(CAEnchantmentRegistry.getInstance().values())
for (enchantment in esEnchantments) { for (enchantment in esEnchantments) {
otherEnchants.remove(enchantment) otherEnchants.remove(enchantment)
@ -174,7 +180,7 @@ class EnchantmentSquaredDependency(private val enchantmentSquaredPlugin: Plugin)
} }
} }
private fun writeConflict(enchantment1: WrappedEnchantment, enchantment2: WrappedEnchantment){ private fun writeConflict(enchantment1: CAEnchantment, enchantment2: CAEnchantment){
val conflictConfig = ConfigHolder.CONFLICT_HOLDER.config val conflictConfig = ConfigHolder.CONFLICT_HOLDER.config
val conflictPath = "${enchantment1.name}_with_${enchantment2.name}_conflict" val conflictPath = "${enchantment1.name}_with_${enchantment2.name}_conflict"

View file

@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.group
import io.delilaheve.CustomAnvil import io.delilaheve.CustomAnvil
import org.bukkit.Material import org.bukkit.Material
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment
class EnchantConflictGroup( class EnchantConflictGroup(
private val name: String, private val name: String,
@ -10,13 +10,13 @@ class EnchantConflictGroup(
var minBeforeBlock: Int var minBeforeBlock: Int
) { ) {
private val enchantments = HashSet<WrappedEnchantment>() private val enchantments = HashSet<CAEnchantment>()
fun addEnchantment(enchant: WrappedEnchantment) { fun addEnchantment(enchant: CAEnchantment) {
enchantments.add(enchant) enchantments.add(enchant)
} }
fun allowed(enchants: Set<WrappedEnchantment>, mat: Material): Boolean { fun allowed(enchants: Set<CAEnchantment>, mat: Material): Boolean {
if (enchantments.size < minBeforeBlock) { if (enchantments.size < minBeforeBlock) {
CustomAnvil.verboseLog("Conflicting bc of to many enchantments") CustomAnvil.verboseLog("Conflicting bc of to many enchantments")
return true return true
@ -44,11 +44,11 @@ class EnchantConflictGroup(
return this.cantConflict return this.cantConflict
} }
fun getEnchants(): HashSet<WrappedEnchantment> { fun getEnchants(): HashSet<CAEnchantment> {
return enchantments return enchantments
} }
fun setEnchants(enchants: Set<WrappedEnchantment>) { fun setEnchants(enchants: Set<CAEnchantment>) {
enchantments.clear() enchantments.clear()
enchantments.addAll(enchants) enchantments.addAll(enchants)
} }

View file

@ -1,11 +1,15 @@
package xyz.alexcrea.cuanvil.group package xyz.alexcrea.cuanvil.group
import io.delilaheve.CustomAnvil import io.delilaheve.CustomAnvil
import org.bukkit.Material
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.ConfigurationSection
import org.bukkit.enchantments.Enchantment import org.bukkit.enchantments.Enchantment
import xyz.alexcrea.cuanvil.enchant.WrappedEnchantment import org.bukkit.inventory.ItemStack
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
import java.util.*
import kotlin.collections.ArrayList
class EnchantConflictManager { class EnchantConflictManager {
@ -28,48 +32,40 @@ class EnchantConflictManager {
// 1.20.5 compatibility TODO better update system // 1.20.5 compatibility TODO better update system
private val SWEEPING_EDGE_ENCHANT = private val SWEEPING_EDGE_ENCHANT =
WrappedEnchantment.getByKey(NamespacedKey.minecraft("sweeping_edge")) ?: CAEnchantment.getByKey(NamespacedKey.minecraft("sweeping_edge")) ?:
WrappedEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key) CAEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key)
} }
private lateinit var conflictMap: HashMap<WrappedEnchantment, ArrayList<EnchantConflictGroup>>
lateinit var conflictList: ArrayList<EnchantConflictGroup> lateinit var conflictList: ArrayList<EnchantConflictGroup>
// Read and prepare all conflict // Read and prepare all conflict
fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager) { fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager) {
conflictMap = HashMap()
conflictList = ArrayList() conflictList = ArrayList()
// Clear conflict if exist
for (enchant in CAEnchantmentRegistry.getInstance().values()) {
enchant.clearConflict()
}
val keys = config.getKeys(false) val keys = config.getKeys(false)
for (key in keys) { for (key in keys) {
val section = config.getConfigurationSection(key)!! val section = config.getConfigurationSection(key)!!
val conflict = createConflict(section, itemManager, key) val conflict = createConflict(section, itemManager, key)
addToMap(conflict) addConflictToEnchantments(conflict)
conflictList.add(conflict) conflictList.add(conflict)
} }
} }
// Add the conflict to the map // Add the conflict to enchantments
private fun addToMap(conflict: EnchantConflictGroup) { private fun addConflictToEnchantments(conflict: EnchantConflictGroup) {
conflict.getEnchants().forEach { enchant -> conflict.getEnchants().forEach { enchant ->
addConflictToConflictMap(enchant, conflict) enchant.addConflict(conflict)
} }
} }
fun addConflictToConflictMap(enchant: WrappedEnchantment, conflict: EnchantConflictGroup) {
if (!conflictMap.containsKey(enchant)) {
conflictMap[enchant] = ArrayList()
}
conflictMap[enchant]!!.add(conflict)
}
fun removeConflictFromMap(enchant: WrappedEnchantment, conflict: EnchantConflictGroup): Boolean {
return conflictMap[enchant]!!.remove(conflict)
}
// create and read a conflict from a yaml section // create and read a conflict from a yaml section
private fun createConflict( private fun createConflict(
section: ConfigurationSection, section: ConfigurationSection,
@ -85,14 +81,14 @@ class EnchantConflictManager {
for (enchantName in enchantList) { for (enchantName in enchantList) {
val enchant = getEnchantByName(enchantName) val enchant = getEnchantByName(enchantName)
if (enchant == null) { if (enchant == null) {
if (!futureUse) { if (!futureUse) { //TODO future use will be deprecated once the new update system is finished
CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName") CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName")
} }
continue continue
} }
conflict.addEnchantment(enchant) conflict.addEnchantment(enchant)
} }
if (conflict.getEnchants().size == 0) { if (conflict.getEnchants().isEmpty()) {
if (!futureUse) { //TODO future use will be deprecated once the new update system is finished if (!futureUse) { //TODO future use will be deprecated once the new update system is finished
CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not do anything") CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not do anything")
} }
@ -101,7 +97,7 @@ class EnchantConflictManager {
return conflict return conflict
} }
private fun getEnchantByName(enchantName: String): WrappedEnchantment? { private fun getEnchantByName(enchantName: String): CAEnchantment? {
// Temporary solution for 1.20.5 // Temporary solution for 1.20.5
when(enchantName){ when(enchantName){
@ -110,7 +106,7 @@ class EnchantConflictManager {
} }
} }
return WrappedEnchantment.getByName(enchantName) return CAEnchantment.getByName(enchantName)
} }
@ -151,35 +147,87 @@ class EnchantConflictManager {
return group return group
} }
fun isConflicting(base: Set<WrappedEnchantment>, mat: Material, newEnchant: WrappedEnchantment): ConflictType { fun isConflicting(appliedEnchants: Map<CAEnchantment, Int>, item: ItemStack, newEnchant: CAEnchantment): ConflictType {
val mat = item.type
CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${mat.key}") CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${mat.key}")
val conflictList = conflictMap[newEnchant] ?: return ConflictType.NO_CONFLICT val conflictList = newEnchant.conflicts
CustomAnvil.verboseLog("Did not get skipped")
var result = ConflictType.NO_CONFLICT var result = ConflictType.NO_CONFLICT
for (conflict in conflictList) { for (conflict in conflictList) {
CustomAnvil.verboseLog("Is against $conflict") CustomAnvil.verboseLog("Is against $conflict")
val allowed = conflict.allowed(base, mat) val allowed = conflict.allowed(appliedEnchants.keys, mat)
CustomAnvil.verboseLog("Was against $conflict and conflicting: ${!allowed} ") CustomAnvil.verboseLog("Was against $conflict and conflicting: ${!allowed} ")
if (!allowed) { if (!allowed) {
if (conflict.getEnchants().size <= 1) { if (conflict.getEnchants().size <= 1) {
result = ConflictType.SMALL_CONFLICT result = ConflictType.ITEM_CONFLICT
CustomAnvil.verboseLog("Small conflict, continuing") CustomAnvil.verboseLog("Small conflict, continuing")
} else { } else {
CustomAnvil.verboseLog("Big conflict, probably stoping") CustomAnvil.verboseLog("Big conflict, probably stoping")
return ConflictType.BIG_CONFLICT return ConflictType.ENCHANTMENT_CONFLICT
} }
} }
} }
return result
val immutableEnchants = Collections.unmodifiableMap(appliedEnchants)
for (appliedEnchant in appliedEnchants) {
if(appliedEnchant is AdditionalTestEnchantment){
val doConflict = appliedEnchant.isEnchantConflict(immutableEnchants, mat)
if(doConflict){
return ConflictType.ENCHANTMENT_CONFLICT
}
;
}
}
if((result != ConflictType.ITEM_CONFLICT) && (newEnchant is AdditionalTestEnchantment)){
val partialItem = createPartialResult(item, immutableEnchants)
if(newEnchant.isItemConflict(immutableEnchants, mat, partialItem)){
return ConflictType.ITEM_CONFLICT
} }
} }
enum class ConflictType { return result;
NO_CONFLICT, }
SMALL_CONFLICT,
BIG_CONFLICT
private fun createPartialResult(item: ItemStack, enchantments: Map<CAEnchantment, Int>): ItemStack {
val newItem = item.clone()
CAEnchantment.clearEnchants(newItem)
enchantments.forEach{//TODO maybe bulk add if possible
enchantment -> enchantment.key.addEnchantmentUnsafe(newItem, enchantment.value)
}
return newItem
}
}
/**
* Provide information about the current conflict.
*/
enum class ConflictType(private val importance: Int) {
/**
* Allowed to proceed the anvil process.
*/
NO_CONFLICT(0),
/**
* Inform that the anvil process should not change the current applied enchantment.
*/
ITEM_CONFLICT(1),
/**
* Inform that the anvil process should not change the current applied enchantment.
* Also add sacrificeIllegalCost for every enchantment marked as big conflict.
*/
ENCHANTMENT_CONFLICT(2);
fun getWorstConflict(otherConflict: ConflictType): ConflictType {
return if(this.importance > otherConflict.importance) this
else otherConflict
}
} }

View file

@ -1,14 +1,13 @@
main: io.delilaheve.CustomAnvil main: io.delilaheve.CustomAnvil
name: CustomAnvil name: CustomAnvil
prefix: "Custom Anvil" prefix: "Custom Anvil"
version: 1.5.0 version: 1.5.1
description: Allow to customise anvil mechanics description: Allow to customise anvil mechanics
api-version: 1.16 api-version: 1.16
load: POSTWORLD load: POSTWORLD
authors: [ DelilahEve, alexcrea ] authors: [ DelilahEve, alexcrea ]
libraries: libraries:
- org.jetbrains.kotlin:kotlin-stdlib:1.6.21 - org.jetbrains.kotlin:kotlin-stdlib:1.9.24
- com.github.stefvanschie.inventoryframework:IF:0.10.14
commands: commands:
anvilconfigreload: anvilconfigreload:
@ -47,3 +46,5 @@ softdepend:
- UnsafeEnchantsPlus - UnsafeEnchantsPlus
- ProtocolLib - ProtocolLib
- EnchantsSquared - EnchantsSquared
- EcoEnchants
- eco