Compare commits

...

9 commits

24 changed files with 467 additions and 60 deletions

View file

@ -12,11 +12,11 @@ plugins {
signing signing
id("cn.lalaki.central").version("1.2.5") id("cn.lalaki.central").version("1.2.5")
// Paper // Paper
id("io.papermc.paperweight.userdev") version "1.7.3" apply false id("io.papermc.paperweight.userdev") version "2.0.0-beta.8" apply false
} }
group = "xyz.alexcrea" group = "xyz.alexcrea"
version = "1.6.13" version = "1.7.0"
repositories { repositories {
// EcoEnchants // EcoEnchants
@ -39,15 +39,19 @@ dependencies {
// EcoEnchants // EcoEnchants
compileOnly("com.willfp:EcoEnchants:12.5.1") compileOnly("com.willfp:EcoEnchants:12.5.1")
compileOnly("com.willfp:eco:6.70.1") compileOnly("com.willfp:eco:6.70.1")
compileOnly(project(":impl:LegacyEcoEnchant"))
// ExcellentEnchants // ExcellentEnchants
compileOnly(files("libs/nightcore-2.6.4.jar")) compileOnly(files("libs/nightcore-2.6.4.jar"))
compileOnly(files("libs/ExcellentEnchants-4.2.2.jar")) compileOnly(files("libs/ExcellentEnchants-4.2.2.jar"))
compileOnly(files("libs/ExcellentEnchants 4.1.0-striped.jar")) compileOnly(files("libs/ExcellentEnchants 4.1.0-striped.jar")) // For legacy excellent enchants
// Disenchantment // Disenchantment
compileOnly("cz.kominekjan:Disenchantment:v5.4.0") compileOnly("cz.kominekjan:Disenchantment:v5.4.0")
// HavenBags
compileOnly(files("libs/HavenBags-1.30.1.1729.jar"))
// Include nms // Include nms
implementation(project(":nms:nms-common")) implementation(project(":nms:nms-common"))
implementation(project(":nms:v1_17R1", configuration = "reobf")) implementation(project(":nms:v1_17R1", configuration = "reobf"))

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View file

@ -0,0 +1,15 @@
group = rootProject.group
version = rootProject.version
plugins {
kotlin("jvm") version "2.0.21"
}
// Imitate needed class and method to support legacy version of EcoEnchant
dependencies {
// Spigot api
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT")
}

View file

@ -0,0 +1,26 @@
package com.willfp.ecoenchants.enchantments;
import com.willfp.ecoenchants.enchantments.meta.EnchantmentTarget;
import com.willfp.ecoenchants.enchantments.meta.EnchantmentType;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* Mock class for legacy package of eco enchants
*/
public class EcoEnchant {
public boolean conflictsWith(@NotNull Enchantment enchant) {
return false;
}
public Set<EnchantmentTarget> getTargets() {
return null;
}
public EnchantmentType getType() {
return null;
}
}

View file

@ -0,0 +1,14 @@
package com.willfp.ecoenchants.enchantments;
import java.util.List;
/**
* Mock class for legacy package of eco enchants
*/
public class EcoEnchants {
public static List<EcoEnchant> values(){
return null; // We don't care here.
}
}

View file

@ -0,0 +1,16 @@
package com.willfp.ecoenchants.enchantments.meta;
import org.bukkit.Material;
import java.util.Set;
/**
* Mock class for legacy package of eco enchants
*/
public class EnchantmentTarget {
public Set<Material> getMaterials() {
return null;
}
}

View file

@ -0,0 +1,9 @@
package com.willfp.ecoenchants.enchantments.meta;
public class EnchantmentType {
public boolean isSingular() {
return false;
}
}

Binary file not shown.

View file

@ -24,7 +24,7 @@ repositories {
// Configure used version of kotlin and java // Configure used version of kotlin and java
java { java {
disableAutoTargetJvm() disableAutoTargetJvm()
toolchain.languageVersion.set(JavaLanguageVersion.of(16)) toolchain.languageVersion.set(JavaLanguageVersion.of(17))
} }
// Set target version // Set target version

View file

@ -38,3 +38,5 @@ include("nms:v1_21R2")
findProject(":nms:v1_21R2")?.name = "v1_21R2" findProject(":nms:v1_21R2")?.name = "v1_21R2"
include("nms:v1_21R3") include("nms:v1_21R3")
findProject(":nms:v1_21R3")?.name = "v1_21R3" findProject(":nms:v1_21R3")?.name = "v1_21R3"
include(":impl:LegacyEcoEnchant")
findProject(":impl:LegacyEcoEnchant")?.name = "LegacyEcoEnchant"

View file

@ -5,6 +5,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.enchant.bulk.BukkitEnchantBulkOperation; import xyz.alexcrea.cuanvil.enchant.bulk.BukkitEnchantBulkOperation;
import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation; import xyz.alexcrea.cuanvil.enchant.bulk.BulkCleanEnchantOperation;
import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation; import xyz.alexcrea.cuanvil.enchant.bulk.BulkGetEnchantOperation;
@ -16,6 +17,7 @@ import java.util.logging.Level;
public class CAEnchantmentRegistry { public class CAEnchantmentRegistry {
private static final CAEnchantmentRegistry instance = new CAEnchantmentRegistry(); private static final CAEnchantmentRegistry instance = new CAEnchantmentRegistry();
public static CAEnchantmentRegistry getInstance() { public static CAEnchantmentRegistry getInstance() {
return instance; return instance;
} }
@ -49,7 +51,7 @@ public class CAEnchantmentRegistry {
* This should only be called on main of custom anvil. * This should only be called on main of custom anvil.
* If called more than one time, chance of thing being broken will be high. * If called more than one time, chance of thing being broken will be high.
*/ */
public void registerBukkit(){ public void registerBukkit() {
// Register enchantment // Register enchantment
for (Enchantment enchantment : Enchantment.values()) { for (Enchantment enchantment : Enchantment.values()) {
register(new CABukkitEnchantment(enchantment)); register(new CABukkitEnchantment(enchantment));
@ -59,7 +61,6 @@ public class CAEnchantmentRegistry {
BukkitEnchantBulkOperation bukkitOperation = new BukkitEnchantBulkOperation(); BukkitEnchantBulkOperation bukkitOperation = new BukkitEnchantBulkOperation();
optimisedGetOperators.add(bukkitOperation); optimisedGetOperators.add(bukkitOperation);
optimisedCleanOperators.add(bukkitOperation); optimisedCleanOperators.add(bukkitOperation);
} }
private static boolean hasWarnedRegistering = false; private static boolean hasWarnedRegistering = false;
@ -69,20 +70,30 @@ public class CAEnchantmentRegistry {
* <p> * <p>
* No guarantee that the enchantment will be present on the config gui if registered late. * No guarantee that the enchantment will be present on the config gui if registered late.
* (By late I mean after custom anvil startup.) * (By late I mean after custom anvil startup.)
*
* @param enchantment The enchantment to be registered. * @param enchantment The enchantment to be registered.
* @return If the operation was successful. * @return If the operation was successful.
*/ */
public boolean register(@NotNull CAEnchantment enchantment){ public boolean register(@NotNull CAEnchantment enchantment) {
if(byKeyMap.containsKey(enchantment.getKey())){ if (byKeyMap.containsKey(enchantment.getKey())) {
if (!enchantment.equals(byKeyMap.get(enchantment.getKey()))) {
// We are trying to register the exact same enchantment. so we just skip it.
return false;
}
if(ConfigHolder.DEFAULT_CONFIG.getConfig().getBoolean("caution_secret_do_not_log_duplicated_registered_key", false)){
return false;
}
CustomAnvil.instance.getLogger().log(Level.WARNING, CustomAnvil.instance.getLogger().log(Level.WARNING,
"Duplicate registered enchantment. This should NOT happen any time.\n" + "Duplicate distinct registered enchantment. This should NOT happen any time.\n" +
"If you are a custom anvil developer. You maybe custom anvil detected your enchantment as a bukkit enchantment. " + "If you are a custom anvil developer: Maybe custom anvil detected your enchantment as a bukkit enchantment. " +
"maybe remove enchantment with the same key before registering yours", "you should maybe remove enchantment with the same key before registering yours",
new IllegalStateException(enchantment.getKey()+" enchantment was already registered")); new IllegalStateException("enchantment " + enchantment.getKey() + " was already registered"));
return false; return false;
} }
if((!hasWarnedRegistering) && byNameMap.containsKey(enchantment.getName())){ if ((!hasWarnedRegistering) && byNameMap.containsKey(enchantment.getName())) {
hasWarnedRegistering = true; hasWarnedRegistering = true;
CustomAnvil.instance.getLogger().log(Level.WARNING, CustomAnvil.instance.getLogger().log(Level.WARNING,
@ -96,10 +107,10 @@ public class CAEnchantmentRegistry {
nameSortedEnchantments.add(enchantment); nameSortedEnchantments.add(enchantment);
if(!enchantment.isGetOptimised()){ if (!enchantment.isGetOptimised()) {
unoptimisedGetValues.add(enchantment); unoptimisedGetValues.add(enchantment);
} }
if(!enchantment.isCleanOptimised()){ if (!enchantment.isCleanOptimised()) {
unoptimisedCleanValues.add(enchantment); unoptimisedCleanValues.add(enchantment);
} }
@ -113,12 +124,13 @@ public class CAEnchantmentRegistry {
* <p> * <p>
* No guarantee that the enchantment will absent if the config guis if unregistered late. * No guarantee that the enchantment will absent if the config guis if unregistered late.
* (By late I mean after custom anvil startup.) * (By late I mean after custom anvil startup.)
*
* @param enchantment The enchantment to be unregistered. * @param enchantment The enchantment to be unregistered.
* @return If the operation was successful. * @return If the operation was successful.
*/ */
public boolean unregister(@Nullable CAEnchantment enchantment){ public boolean unregister(@Nullable CAEnchantment enchantment) {
if(enchantment == null) return false; if (enchantment == null) return false;
byKeyMap.remove(enchantment.getKey()); byKeyMap.remove(enchantment.getKey());
byNameMap.get(enchantment.getName()).remove(enchantment); byNameMap.get(enchantment.getName()).remove(enchantment);
@ -131,42 +143,45 @@ public class CAEnchantmentRegistry {
/** /**
* Gets the enchantment by the provided key. * Gets the enchantment by the provided key.
*
* @param key Key to fetch. * @param key Key to fetch.
* @return Registered enchantment. null if absent. * @return Registered enchantment. null if absent.
*/ */
@Nullable @Nullable
public CAEnchantment getByKey(@NotNull NamespacedKey key){ public CAEnchantment getByKey(@NotNull NamespacedKey key) {
return byKeyMap.get(key); return byKeyMap.get(key);
} }
/** /**
* Gets the enchantment by the provided name. * Gets the enchantment by the provided name.
*
* @param name Name to fetch. * @param name Name to fetch.
* @return Registered enchantment. null if absent. * @return Registered enchantment. null if absent.
*
* @deprecated use {@link #getListByName(String)} * @deprecated use {@link #getListByName(String)}
*/ */
@Deprecated(since = "1.6.3") @Deprecated(since = "1.6.3")
@Nullable @Nullable
public CAEnchantment getByName(@NotNull String name){ public CAEnchantment getByName(@NotNull String name) {
List<CAEnchantment> enchantments = getListByName(name); List<CAEnchantment> enchantments = getListByName(name);
if(enchantments.isEmpty()) return null; if (enchantments.isEmpty()) return null;
return enchantments.get(0); return enchantments.get(0);
} }
/** /**
* Gets list of enchantment using the provided name. * Gets list of enchantment using the provided name.
*
* @param name Name to fetch. * @param name Name to fetch.
* @return List of registered enchantment. * @return List of registered enchantment.
*/ */
@NotNull @NotNull
public List<CAEnchantment> getListByName(@NotNull String name){ public List<CAEnchantment> getListByName(@NotNull String name) {
return byNameMap.getOrDefault(name, Collections.emptyList()); return byNameMap.getOrDefault(name, Collections.emptyList());
} }
/** /**
* Gets an array of all the registered enchantments. * Gets an array of all the registered enchantments.
*
* @return Array of enchantments. * @return Array of enchantments.
*/ */
@NotNull @NotNull
@ -176,6 +191,7 @@ public class CAEnchantmentRegistry {
/** /**
* Gets a map of all the registered enchantments. * Gets a map of all the registered enchantments.
*
* @return Immutable map of enchantments. * @return Immutable map of enchantments.
*/ */
public Map<NamespacedKey, CAEnchantment> registeredEnchantments() { public Map<NamespacedKey, CAEnchantment> registeredEnchantments() {
@ -184,6 +200,7 @@ public class CAEnchantmentRegistry {
/** /**
* Gets a list of all the unoptimised get operation enchantments. * Gets a list of all the unoptimised get operation enchantments.
*
* @return List of unoptimised enchantments. * @return List of unoptimised enchantments.
*/ */
@NotNull @NotNull
@ -193,6 +210,7 @@ public class CAEnchantmentRegistry {
/** /**
* Gets a list of all the unoptimised clean operation enchantments. * Gets a list of all the unoptimised clean operation enchantments.
*
* @return List of unoptimised enchantments. * @return List of unoptimised enchantments.
*/ */
@NotNull @NotNull
@ -202,6 +220,7 @@ public class CAEnchantmentRegistry {
/** /**
* Get "clean optimised operation" for get enchantments. * Get "clean optimised operation" for get enchantments.
*
* @return Mutable "clean enchantments optimised operation" list. * @return Mutable "clean enchantments optimised operation" list.
*/ */
public List<BulkCleanEnchantOperation> getOptimisedCleanOperators() { public List<BulkCleanEnchantOperation> getOptimisedCleanOperators() {
@ -210,6 +229,7 @@ public class CAEnchantmentRegistry {
/** /**
* Get "get optimised operation" for get enchantments. * Get "get optimised operation" for get enchantments.
*
* @return Mutable "get enchantments optimised operation" list. * @return Mutable "get enchantments optimised operation" list.
*/ */
public List<BulkGetEnchantOperation> getOptimisedGetOperators() { public List<BulkGetEnchantOperation> getOptimisedGetOperators() {
@ -218,6 +238,7 @@ public class CAEnchantmentRegistry {
/** /**
* Get custom anvil enchantment sorted by name. * Get custom anvil enchantment sorted by name.
*
* @return An immutable sorted set of every registered enchantment sorted by name. * @return An immutable sorted set of every registered enchantment sorted by name.
*/ */
public SortedSet<CAEnchantment> getNameSortedEnchantments() { public SortedSet<CAEnchantment> getNameSortedEnchantments() {

View file

@ -1,7 +1,9 @@
package xyz.alexcrea.cuanvil.enchant.bulk; package xyz.alexcrea.cuanvil.enchant.bulk;
import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ItemUtil; import io.delilaheve.util.ItemUtil;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack; 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;
@ -14,18 +16,29 @@ import java.util.Map;
public class BukkitEnchantBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation { public class BukkitEnchantBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation {
@Override @Override
public void bulkGet(@NotNull Map<CAEnchantment, Integer> enchantmentList, @NotNull ItemStack item, @NotNull ItemMeta meta) { public void bulkGet(@NotNull Map<CAEnchantment, Integer> enchantmentMap, @NotNull ItemStack item, @NotNull ItemMeta meta) {
if (ItemUtil.INSTANCE.isEnchantedBook(item)) { if (ItemUtil.INSTANCE.isEnchantedBook(item)) {
((EnchantmentStorageMeta)meta).getStoredEnchants().forEach((enchantment, level) -> ((EnchantmentStorageMeta) meta).getStoredEnchants().forEach((enchantment, level) ->
enchantmentList.put(EnchantmentApi.getByKey(enchantment.getKey()), level) addEnchantment(enchantmentMap, enchantment, level)
); );
} else { } else {
item.getEnchantments().forEach((enchantment, level) -> item.getEnchantments().forEach((enchantment, level) ->
enchantmentList.put(EnchantmentApi.getByKey(enchantment.getKey()), level) addEnchantment(enchantmentMap, enchantment, level)
); );
} }
} }
public void addEnchantment(@NotNull Map<CAEnchantment, Integer> enchantmentMap, @NotNull Enchantment enchantment, int level) {
CAEnchantment enchant = EnchantmentApi.getByKey(enchantment.getKey());
if (enchant == null) {
CustomAnvil.instance.getLogger().warning("Enchantment of key " + enchantment.getKey() +
" somehow not found in CustomAnvil ?");
return;
}
enchantmentMap.put(enchant, level);
}
@Override @Override
public void bulkClear(@NotNull ItemStack item) { public void bulkClear(@NotNull ItemStack item) {
if (item.getType() != Material.ENCHANTED_BOOK) { if (item.getType() != Material.ENCHANTED_BOOK) {

View file

@ -14,10 +14,10 @@ public interface BulkGetEnchantOperation {
/** /**
* Bulk get part of the stored enchantment of this item. * Bulk get part of the stored enchantment of this item.
* @param enchantmentList Mutable map of collected enchantment. should b * @param enchantmentMap Mutable map of collected enchantment. should b
* @param item The item to get enchantment from. Should not get edited. * @param item The item to get enchantment from. Should not get edited.
* @param meta The item meta to get enchantment from. Should not get edited. * @param meta The item meta to get enchantment from. Should not get edited.
*/ */
void bulkGet(@NotNull Map<CAEnchantment, Integer> enchantmentList, @NotNull ItemStack item, @NotNull ItemMeta meta); void bulkGet(@NotNull Map<CAEnchantment, Integer> enchantmentMap, @NotNull ItemStack item, @NotNull ItemMeta meta);
} }

View file

@ -14,10 +14,10 @@ import java.util.Map;
public class EnchantSquaredBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation { public class EnchantSquaredBulkOperation implements BulkGetEnchantOperation, BulkCleanEnchantOperation {
@Override @Override
public void bulkGet(@NotNull Map<CAEnchantment, Integer> enchantmentList, @NotNull ItemStack item, @NotNull ItemMeta meta) { public void bulkGet(@NotNull Map<CAEnchantment, Integer> enchantmentMap, @NotNull ItemStack item, @NotNull ItemMeta meta) {
EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility(); EnchantmentSquaredDependency enchantmentSquared = DependencyManager.INSTANCE.getEnchantmentSquaredCompatibility();
if(enchantmentSquared != null){ if(enchantmentSquared != null){
enchantmentSquared.getEnchantmentsSquared(item, enchantmentList); enchantmentSquared.getEnchantmentsSquared(item, enchantmentMap);
} }
} }

View file

@ -157,4 +157,13 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
} }
@Override
public boolean equals(Object obj) {
if(!(obj instanceof CABukkitEnchantment other)){
return false;
}
return this.enchantment.equals(other.getEnchant());
}
} }

View file

@ -2,6 +2,7 @@ package xyz.alexcrea.cuanvil.enchant.wrapped;
import com.willfp.ecoenchants.enchant.EcoEnchant; import com.willfp.ecoenchants.enchant.EcoEnchant;
import com.willfp.ecoenchants.target.EnchantmentTarget; import com.willfp.ecoenchants.target.EnchantmentTarget;
import com.willfp.ecoenchants.type.EnchantmentType;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -9,6 +10,7 @@ import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment; import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity; import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestEnchantment { public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestEnchantment {
@ -22,19 +24,34 @@ public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestE
@Override @Override
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) { public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
if(!enchantments.isEmpty()) { if (enchantments.isEmpty()) return false;
if (this.ecoEnchant.getConflictsWithEverything()) {
if (this.ecoEnchant.getConflictsWithEverything()) {
return true;
}
HashMap<EnchantmentType, Integer> typeAmountMap = new HashMap<>();
for (CAEnchantment other : enchantments.keySet()) {
if (other instanceof CABukkitEnchantment otherVanilla
&& this.ecoEnchant.conflictsWith(otherVanilla.getEnchant())) {
return true; return true;
} }
for (CAEnchantment other : enchantments.keySet()) { if (other instanceof CAEcoEnchant ecoOther) {
if(other instanceof CABukkitEnchantment otherVanilla EnchantmentType type = ecoOther.ecoEnchant.getType();
&& this.ecoEnchant.conflictsWith(otherVanilla.getEnchant())){ typeAmountMap.putIfAbsent(type, 0);
int amount = typeAmountMap.get(type) + 1;
if (amount > type.getLimit()) {
return true; return true;
} }
typeAmountMap.put(type, amount);
} }
} }
return false; return false;
} }
@ -42,12 +59,12 @@ public class CAEcoEnchant extends CABukkitEnchantment implements AdditionalTestE
public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments, public boolean isItemConflict(@NotNull Map<CAEnchantment, Integer> enchantments,
@NotNull Material itemMat, @NotNull Material itemMat,
@NotNull ItemStack item) { @NotNull ItemStack item) {
if(Material.ENCHANTED_BOOK.equals(itemMat)){ if (Material.ENCHANTED_BOOK.equals(itemMat)) {
return false; return false;
} }
for (EnchantmentTarget target : this.ecoEnchant.getTargets()) { for (EnchantmentTarget target : this.ecoEnchant.getTargets()) {
if(target.matches(item)){ if (target.matches(item)) {
return false; return false;
} }
} }

View file

@ -16,15 +16,20 @@ import java.util.Objects;
public class CAEnchantSquaredEnchantment extends CAEnchantmentBase { public class CAEnchantSquaredEnchantment extends CAEnchantmentBase {
public final @NotNull CustomEnchant enchant; public final @NotNull CustomEnchant enchant;
public CAEnchantSquaredEnchantment(@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,
enchant.getMaxLevel()); enchant.getMaxLevel());
this.enchant = enchant; this.enchant = enchant;
} }
public @NotNull CustomEnchant getEnchant() {
return enchant;
}
@Override @Override
public boolean isGetOptimised() { public boolean isGetOptimised() {
return true; return true;
@ -61,4 +66,14 @@ public class CAEnchantSquaredEnchantment extends CAEnchantmentBase {
CustomEnchantManager.getInstance().removeEnchant(item, this.enchant.getType()); CustomEnchantManager.getInstance().removeEnchant(item, this.enchant.getType());
} }
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CAEnchantSquaredEnchantment other)) {
return false;
}
return this.enchant.equals(other.getEnchant());
}
} }

View file

@ -0,0 +1,65 @@
package xyz.alexcrea.cuanvil.enchant.wrapped;
import com.willfp.ecoenchants.enchantments.EcoEnchant;
import com.willfp.ecoenchants.enchantments.meta.EnchantmentTarget;
import com.willfp.ecoenchants.enchantments.meta.EnchantmentType;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
import java.util.Map;
public class CALegacyEcoEnchant extends CABukkitEnchantment implements AdditionalTestEnchantment {
private final @NotNull EcoEnchant ecoEnchant;
public CALegacyEcoEnchant(@NotNull EcoEnchant ecoEnchant, @NotNull Enchantment enchantment) {
super(enchantment, EnchantmentRarity.COMMON);
this.ecoEnchant = ecoEnchant;
}
@Override
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
if (enchantments.isEmpty()) return false;
EnchantmentType type = this.ecoEnchant.getType();
boolean isSingular = type.isSingular();
for (CAEnchantment other : enchantments.keySet()) {
if (other instanceof CABukkitEnchantment otherVanilla
&& this.ecoEnchant.conflictsWith(otherVanilla.getEnchant())) {
return true;
}
if (isSingular &&
other != this &&
(other instanceof CALegacyEcoEnchant otherEco) &&
type.equals(otherEco.ecoEnchant.getType())) {
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.getMaterials().contains(itemMat)) {
return false;
}
}
return true;
}
}

View file

@ -28,13 +28,14 @@ object DependencyManager {
var excellentEnchantsCompatibility: ExcellentEnchantsDependency? = null var excellentEnchantsCompatibility: ExcellentEnchantsDependency? = null
var disenchantmentCompatibility: DisenchantmentDependency? = null var disenchantmentCompatibility: DisenchantmentDependency? = null
var havenBagsCompatibility: HavenBagsDependency? = null
fun loadDependency(){ fun loadDependency() {
val pluginManager = Bukkit.getPluginManager() val pluginManager = Bukkit.getPluginManager()
// Bukkit or Paper scheduler ? // Bukkit or Paper scheduler ?
isFolia = testIsFolia() isFolia = testIsFolia()
scheduler = if(isFolia) { scheduler = if (isFolia) {
CustomAnvil.instance.logger.info("Folia detected... Custom Anvil Folia support is experimental. issues are more likely to happens.") CustomAnvil.instance.logger.info("Folia detected... Custom Anvil Folia support is experimental. issues are more likely to happens.")
FoliaScheduler() FoliaScheduler()
@ -46,29 +47,35 @@ object DependencyManager {
externGuiTester = GuiTesterSelector.selectGuiTester externGuiTester = GuiTesterSelector.selectGuiTester
// Enchantment Squared dependency // Enchantment Squared dependency
if(pluginManager.isPluginEnabled("EnchantsSquared")){ if (pluginManager.isPluginEnabled("EnchantsSquared")) {
enchantmentSquaredCompatibility = EnchantmentSquaredDependency(pluginManager.getPlugin("EnchantsSquared")!!) enchantmentSquaredCompatibility = EnchantmentSquaredDependency(pluginManager.getPlugin("EnchantsSquared")!!)
enchantmentSquaredCompatibility!!.disableAnvilListener() enchantmentSquaredCompatibility!!.disableAnvilListener()
} }
// EcoEnchants dependency // EcoEnchants dependency
if(pluginManager.isPluginEnabled("EcoEnchants")){ if (pluginManager.isPluginEnabled("EcoEnchants")) {
ecoEnchantCompatibility = EcoEnchantDependency(pluginManager.getPlugin("EcoEnchants")!!) ecoEnchantCompatibility = EcoEnchantDependency(pluginManager.getPlugin("EcoEnchants")!!)
ecoEnchantCompatibility!!.disableAnvilListener() ecoEnchantCompatibility!!.disableAnvilListener()
} }
// Excellent Enchants dependency // Excellent Enchants dependency
if(pluginManager.isPluginEnabled("ExcellentEnchants")){ if (pluginManager.isPluginEnabled("ExcellentEnchants")) {
excellentEnchantsCompatibility = ExcellentEnchantsDependency() excellentEnchantsCompatibility = ExcellentEnchantsDependency()
excellentEnchantsCompatibility!!.redirectListeners() excellentEnchantsCompatibility!!.redirectListeners()
} }
// Disenchantment dependency // Disenchantment dependency
if(pluginManager.isPluginEnabled("Disenchantment")){ if (pluginManager.isPluginEnabled("Disenchantment")) {
disenchantmentCompatibility = DisenchantmentDependency() disenchantmentCompatibility = DisenchantmentDependency()
disenchantmentCompatibility!!.redirectListeners() disenchantmentCompatibility!!.redirectListeners()
} }
// HavenBags dependency
if (pluginManager.isPluginEnabled("HavenBags")) {
havenBagsCompatibility = HavenBagsDependency()
havenBagsCompatibility!!.redirectListeners()
}
} }
fun handleCompatibilityConfig() { fun handleCompatibilityConfig() {
@ -83,7 +90,7 @@ object DependencyManager {
} }
fun handleConfigReload(){ fun handleConfigReload() {
// Register enchantment of compatible plugin and load configuration change. // Register enchantment of compatible plugin and load configuration change.
handleCompatibilityConfig() handleCompatibilityConfig()
@ -95,14 +102,18 @@ object DependencyManager {
fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean { fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
var bypass = false var bypass = false
// Test if disenchantment used special prepare anvil // Test if disenchantment used prepare anvil
if(disenchantmentCompatibility?.testPrepareAnvil(event, player) == true) bypass = true if (disenchantmentCompatibility?.testPrepareAnvil(event, player) == true) bypass = true
// Test excellent enchantments used special prepare anvil // Test heaven bags used prepare anvil
if(!bypass && (excellentEnchantsCompatibility?.testPrepareAnvil(event) == true)) bypass = true if (!bypass && (havenBagsCompatibility?.testPrepareAnvil(event, player) == true)) bypass = true
// Test excellent enchantments used prepare anvil
if (!bypass && (excellentEnchantsCompatibility?.testPrepareAnvil(event) == true)) bypass = true
// Test if the inventory is a gui(version specific) // Test if the inventory is a gui(version specific)
if(!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true if (!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true
return bypass return bypass
} }
@ -114,14 +125,17 @@ object DependencyManager {
fun tryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean { fun tryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean {
var bypass = false var bypass = false
// Test if disenchantment used special event click // Test if disenchantment used event click
if(disenchantmentCompatibility?.testAnvilResult(event, inventory) == true) bypass = true if (disenchantmentCompatibility?.testAnvilResult(event, inventory) == true) bypass = true
// Test if disenchantment used special event click // Test if haven bag used event click
if(!bypass && (excellentEnchantsCompatibility?.testAnvilResult(event) == true)) bypass = true if (!bypass && (havenBagsCompatibility?.testAnvilResult(event, inventory) == true)) bypass = true
// Test if disenchantment used event click
if (!bypass && (excellentEnchantsCompatibility?.testAnvilResult(event) == true)) bypass = true
// Test if the inventory is a gui(version specific) // Test if the inventory is a gui(version specific)
if(!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true if (!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true
return bypass return bypass
} }

View file

@ -10,11 +10,29 @@ import xyz.alexcrea.cuanvil.enchant.wrapped.CAEcoEnchant
class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) { class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) {
private val isLegacy: Boolean
private val legacyDependency: LegacyEcoEnchantDependency?
init { init {
CustomAnvil.instance.logger.info("Eco Enchant Detected !") CustomAnvil.instance.logger.info("Eco Enchant Detected !")
var isLegacy = true
try {
Class.forName("com.willfp.ecoenchants.enchant.EcoEnchants")
isLegacy = false
} catch (_: ClassNotFoundException) {
}
this.isLegacy = isLegacy;
if (isLegacy) {
this.legacyDependency = LegacyEcoEnchantDependency()
} else {
this.legacyDependency = null
}
} }
fun disableAnvilListener(){ fun disableAnvilListener() {
PrepareAnvilEvent.getHandlerList().unregister(this.ecoEnchantPlugin) PrepareAnvilEvent.getHandlerList().unregister(this.ecoEnchantPlugin)
} }
@ -22,6 +40,11 @@ class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) {
fun registerEnchantments() { fun registerEnchantments() {
CustomAnvil.instance.logger.info("Preparing Eco Enchant compatibility...") CustomAnvil.instance.logger.info("Preparing Eco Enchant compatibility...")
if (isLegacy) {
legacyDependency!!.registerEnchantments();
return
}
val enchantments = EcoEnchants.values() val enchantments = EcoEnchants.values()
for (ecoEnchant in enchantments) { for (ecoEnchant in enchantments) {
EnchantmentApi.unregisterEnchantment(ecoEnchant.enchantment) // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant. EnchantmentApi.unregisterEnchantment(ecoEnchant.enchantment) // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant.
@ -34,14 +57,19 @@ class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) {
} }
fun handleConfigReload() { fun handleConfigReload() {
if (isLegacy) {
legacyDependency!!.handleConfigReload()
return
}
// Should not happen in known case. // Should not happen in known case.
if(this.ecoEnchantOldEnchantments == null) return if (this.ecoEnchantOldEnchantments == null) return
val newEnchantments = EcoEnchants.values() val newEnchantments = EcoEnchants.values()
// Add new enchantments // Add new enchantments
for (ecoEnchant in newEnchantments) for (ecoEnchant in newEnchantments)
if(!this.ecoEnchantOldEnchantments!!.contains(ecoEnchant)) if (!this.ecoEnchantOldEnchantments!!.contains(ecoEnchant))
EnchantmentApi.registerEnchantment(CAEcoEnchant(ecoEnchant)) EnchantmentApi.registerEnchantment(CAEcoEnchant(ecoEnchant))
// Remove old enchantments that not now currently used // Remove old enchantments that not now currently used

View file

@ -0,0 +1,92 @@
package xyz.alexcrea.cuanvil.dependency
import io.delilaheve.CustomAnvil
import org.bukkit.entity.HumanEntity
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.AnvilInventory
import org.bukkit.inventory.ItemStack
import org.bukkit.plugin.RegisteredListener
import valorless.havenbags.BagSkin
import valorless.havenbags.BagUpgrade
import valorless.havenbags.HavenBags
import valorless.havenbags.prevention.EquipPrevention
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
class HavenBagsDependency {
init {
CustomAnvil.instance.logger.info("Heaven Bags Detected !")
}
private lateinit var bagUpgrade: BagUpgrade
private lateinit var bagSkin: BagSkin
fun redirectListeners() {
val toUnregister = ArrayList<RegisteredListener>()
// get required PrepareAnvilEvent listener
for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) {
val listener = registeredListener.listener
if (listener is BagUpgrade) {
bagUpgrade = listener
toUnregister.add(registeredListener)
}
if (listener is BagSkin) {
bagSkin = listener
toUnregister.add(registeredListener)
}
}
for (listener in toUnregister) {
PrepareAnvilEvent.getHandlerList().unregister(listener)
InventoryClickEvent.getHandlerList().unregister(listener)
}
}
fun testPrepareAnvil(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
val previousResult = event.result
event.result = null
// Test if event change the result
bagSkin.onPrepareAnvil(event)
if (event.result != null) {
CustomAnvil.log("Detected pre anvil heaven bag anvil skin.")
AnvilXpUtil.setAnvilInvXp(event.inventory, event.view, player, event.inventory.repairCost)
return true
}
bagUpgrade.onPrepareAnvil(event)
if (event.result != null) {
CustomAnvil.log("Detected pre anvil heaven bag anvil upgrade.")
AnvilXpUtil.setAnvilInvXp(event.inventory, event.view, player, event.inventory.repairCost)
return true
}
event.result = previousResult
return false
}
fun testAnvilResult(event: InventoryClickEvent, inventory: AnvilInventory): Boolean {
val result = inventory.getItem(PrepareAnvilListener.ANVIL_OUTPUT_SLOT)?.clone()
if (HavenBags.IsBag(result)) {
CustomAnvil.log("Detected anvil click haven bag bypass.")
bagUpgrade.onInventoryClick(event)
bagSkin.onInventoryClick(event)
return true;
}
return false
}
private fun testAnvilInventoryChange(inventory: AnvilInventory, previous: ItemStack?): Boolean {
val currentResult = inventory.getItem(PrepareAnvilListener.ANVIL_OUTPUT_SLOT)
return currentResult == previous
}
}

View file

@ -0,0 +1,46 @@
package xyz.alexcrea.cuanvil.dependency
import com.willfp.ecoenchants.enchantments.EcoEnchant
import com.willfp.ecoenchants.enchantments.EcoEnchants
import org.bukkit.enchantments.Enchantment
import xyz.alexcrea.cuanvil.api.EnchantmentApi
import xyz.alexcrea.cuanvil.enchant.wrapped.CALegacyEcoEnchant
class LegacyEcoEnchantDependency {
private var ecoEnchantOldEnchantments: MutableSet<EcoEnchant>? = null
fun registerEnchantments() {
val enchantments = EcoEnchants.values()
for (ecoEnchant in enchantments) {
ecoEnchant as Enchantment
EnchantmentApi.unregisterEnchantment(ecoEnchant) // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant.
EnchantmentApi.registerEnchantment(CALegacyEcoEnchant(ecoEnchant, ecoEnchant))
}
ecoEnchantOldEnchantments = HashSet(enchantments)
}
fun handleConfigReload() {
// Should not happen in known case.
if (this.ecoEnchantOldEnchantments == null) return
val newEnchantments = EcoEnchants.values()
// Add new enchantments
for (ecoEnchant in newEnchantments)
if (!this.ecoEnchantOldEnchantments!!.contains(ecoEnchant))
EnchantmentApi.registerEnchantment(CALegacyEcoEnchant(ecoEnchant, ecoEnchant as Enchantment))
// Remove old enchantments that not now currently used
this.ecoEnchantOldEnchantments!!.removeAll(newEnchantments)
for (oldEnchantment in this.ecoEnchantOldEnchantments!!) {
EnchantmentApi.unregisterEnchantment(oldEnchantment as Enchantment)
}
this.ecoEnchantOldEnchantments = HashSet(newEnchantments)
}
}

View file

@ -191,7 +191,7 @@ class EnchantConflictManager {
} }
val immutableEnchants = Collections.unmodifiableMap(appliedEnchants) val immutableEnchants = Collections.unmodifiableMap(appliedEnchants)
for (appliedEnchant in appliedEnchants) { for (appliedEnchant in appliedEnchants.keys) {
if(appliedEnchant is AdditionalTestEnchantment){ if(appliedEnchant is AdditionalTestEnchantment){
val doConflict = appliedEnchant.isEnchantConflict(immutableEnchants, mat) val doConflict = appliedEnchant.isEnchantConflict(immutableEnchants, mat)
if(doConflict){ if(doConflict){

View file

@ -58,3 +58,4 @@ softdepend:
- EcoEnchants - EcoEnchants
- eco - eco
- ExcellentEnchants - ExcellentEnchants
- HavenBags