mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-24 00:26:16 +02:00
255 lines
No EOL
9 KiB
Kotlin
255 lines
No EOL
9 KiB
Kotlin
package xyz.alexcrea.cuanvil.group
|
|
|
|
import io.delilaheve.CustomAnvil
|
|
import org.bukkit.NamespacedKey
|
|
import org.bukkit.configuration.ConfigurationSection
|
|
import org.bukkit.enchantments.Enchantment
|
|
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.*
|
|
|
|
class EnchantConflictManager {
|
|
|
|
companion object {
|
|
// Path for the enchantments list
|
|
const val ENCH_LIST_PATH = "enchantments"
|
|
|
|
// Path for group list related to the conflict
|
|
const val CONFLICT_GROUP_PATH = "notAffectedGroups"
|
|
|
|
// Path for the maximum number of enchantment before validating the conflict
|
|
const val ENCH_MAX_PATH = "maxEnchantmentBeforeConflict"
|
|
|
|
// Path for a flag: if the enchantment will be used in the last supported version
|
|
// TODO maybe replace this system by a list of "future" enchantment.
|
|
private const val FUTURE_USE_PATH = "useInFuture"
|
|
|
|
// Default name for a joining group
|
|
const val DEFAULT_GROUP_NAME = "joinedGroup"
|
|
|
|
// 1.20.5 compatibility TODO better update system
|
|
private val SWEEPING_EDGE_ENCHANT = Collections.singletonList<CAEnchantment>(
|
|
CAEnchantment.getByKey(NamespacedKey.minecraft("sweeping_edge")) ?:
|
|
CAEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key))
|
|
|
|
}
|
|
|
|
lateinit var conflictList: ArrayList<EnchantConflictGroup>
|
|
|
|
// Read and prepare all conflict
|
|
fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager) {
|
|
conflictList = ArrayList()
|
|
|
|
// Clear conflict if exist
|
|
for (enchant in CAEnchantmentRegistry.getInstance().values()) {
|
|
enchant.clearConflict()
|
|
}
|
|
|
|
val keys = config.getKeys(false)
|
|
for (key in keys) {
|
|
val section = config.getConfigurationSection(key)!!
|
|
val conflict = createConflict(section, itemManager, key)
|
|
|
|
addConflict(conflict)
|
|
}
|
|
|
|
}
|
|
|
|
fun addConflict(conflict: EnchantConflictGroup){
|
|
addConflictToEnchantments(conflict)
|
|
conflictList.add(conflict)
|
|
}
|
|
|
|
fun removeConflict(conflict: EnchantConflictGroup){
|
|
removeConflictFromEnchantments(conflict)
|
|
conflictList.remove(conflict)
|
|
}
|
|
|
|
// Add the conflict to enchantments
|
|
private fun addConflictToEnchantments(conflict: EnchantConflictGroup) {
|
|
conflict.getEnchants().forEach { enchant ->
|
|
enchant.addConflict(conflict)
|
|
}
|
|
}
|
|
|
|
// Remove the conflict from enchantments
|
|
private fun removeConflictFromEnchantments(conflict: EnchantConflictGroup) {
|
|
conflict.getEnchants().forEach { enchant ->
|
|
enchant.removeConflict(conflict)
|
|
}
|
|
}
|
|
|
|
// create and read a conflict from a yaml section
|
|
private fun createConflict(
|
|
section: ConfigurationSection,
|
|
itemManager: ItemGroupManager,
|
|
conflictName: String
|
|
): EnchantConflictGroup {
|
|
// Is it planed for the future
|
|
val futureUse = section.getBoolean(FUTURE_USE_PATH, false)
|
|
// Create conflict
|
|
val conflict = createConflictObject(section, itemManager, conflictName)
|
|
// Read and add enchantment to conflict
|
|
val enchantList = section.getStringList(ENCH_LIST_PATH)
|
|
for (enchantName in enchantList) {
|
|
val enchants = getEnchantByIdentifier(enchantName)
|
|
if (enchants.isEmpty()) {
|
|
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")
|
|
}
|
|
continue
|
|
}
|
|
conflict.addEnchantments(enchants)
|
|
}
|
|
if (conflict.getEnchants().isEmpty()) {
|
|
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")
|
|
}
|
|
}
|
|
|
|
return conflict
|
|
}
|
|
|
|
private fun getEnchantByIdentifier(enchantName: String): List<CAEnchantment> {
|
|
val key = NamespacedKey.fromString(enchantName)
|
|
if(key != null){
|
|
val enchantment = CAEnchantment.getByKey(key)
|
|
if(enchantment != null) return Collections.singletonList(enchantment)
|
|
|
|
}
|
|
|
|
// Temporary solution for 1.20.5
|
|
when(enchantName){
|
|
"minecraft:sweeping", "sweeping",
|
|
"minecraft:sweeping_edge", "sweeping_edge" -> {
|
|
return SWEEPING_EDGE_ENCHANT
|
|
}
|
|
}
|
|
|
|
return CAEnchantment.getListByName(enchantName)
|
|
}
|
|
|
|
|
|
private fun createConflictObject(
|
|
section: ConfigurationSection,
|
|
itemManager: ItemGroupManager,
|
|
conflictName: String
|
|
): EnchantConflictGroup {
|
|
// Get the maximum number of enchantment before validating the conflict
|
|
var minBeforeBlock = section.getInt(ENCH_MAX_PATH, 0)
|
|
if (minBeforeBlock < 0) {
|
|
minBeforeBlock = 0
|
|
CustomAnvil.instance.logger.warning("Conflict $conflictName have an invalid value of $ENCH_MAX_PATH")
|
|
CustomAnvil.instance.logger.warning("It should be more or equal to 0. default to 0")
|
|
}
|
|
// Find or create the selected group for the conflict
|
|
val groupList = section.getStringList(CONFLICT_GROUP_PATH)
|
|
val finalGroup = IncludeGroup(DEFAULT_GROUP_NAME)
|
|
for (groupName in groupList) {
|
|
finalGroup.addToPolicy(findGroup(groupName, itemManager, conflictName))
|
|
}
|
|
|
|
// Return conflict
|
|
return EnchantConflictGroup(conflictName, finalGroup, minBeforeBlock)
|
|
}
|
|
|
|
private fun findGroup(
|
|
groupName: String,
|
|
itemManager: ItemGroupManager,
|
|
conflictName: String
|
|
): AbstractMaterialGroup {
|
|
val group = itemManager.get(groupName)
|
|
if (group == null) {
|
|
CustomAnvil.instance.logger.warning("Material group $groupName do not exist but is ask by conflict $conflictName")
|
|
return IncludeGroup("error_placeholder")
|
|
}
|
|
|
|
return group
|
|
}
|
|
|
|
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}")
|
|
val conflictList = newEnchant.conflicts
|
|
|
|
var result = ConflictType.NO_CONFLICT
|
|
for (conflict in conflictList) {
|
|
CustomAnvil.verboseLog("Is against $conflict")
|
|
val allowed = conflict.allowed(appliedEnchants.keys, mat)
|
|
CustomAnvil.verboseLog("Was against $conflict and conflicting: ${!allowed} ")
|
|
if (!allowed) {
|
|
if (conflict.getEnchants().size <= 1) {
|
|
result = ConflictType.ITEM_CONFLICT
|
|
CustomAnvil.verboseLog("Small conflict, continuing")
|
|
} else {
|
|
CustomAnvil.verboseLog("Big conflict, probably stoping")
|
|
return ConflictType.ENCHANTMENT_CONFLICT
|
|
}
|
|
}
|
|
}
|
|
|
|
val immutableEnchants = Collections.unmodifiableMap(appliedEnchants)
|
|
for (appliedEnchant in appliedEnchants.keys) {
|
|
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
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
private fun createPartialResult(item: ItemStack, enchantments: Map<CAEnchantment, Int>): ItemStack {
|
|
val newItem = item.clone()
|
|
|
|
CAEnchantment.clearEnchants(newItem)
|
|
enchantments.forEach{
|
|
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
|
|
|
|
}
|
|
|
|
} |