mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 16:16:17 +02:00
alpha version up & cleanup code.
This commit is contained in:
parent
1b83c8db81
commit
00fba2f4b0
40 changed files with 893 additions and 718 deletions
|
|
@ -39,9 +39,10 @@ class AnvilEventListener : Listener {
|
|||
private const val ANVIL_INPUT_LEFT = 0
|
||||
private const val ANVIL_INPUT_RIGHT = 1
|
||||
private const val ANVIL_OUTPUT_SLOT = 2
|
||||
|
||||
// static slot container
|
||||
private val NO_SLOT = SlotContainer(SlotType.NO_SLOT,0)
|
||||
private val CURSOR_SLOT = SlotContainer(SlotType.CURSOR,0)
|
||||
private val NO_SLOT = SlotContainer(SlotType.NO_SLOT, 0)
|
||||
private val CURSOR_SLOT = SlotContainer(SlotType.CURSOR, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -55,15 +56,15 @@ class AnvilEventListener : Listener {
|
|||
|
||||
// Should find player
|
||||
val player = event.view.player
|
||||
if(!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
|
||||
// Test rename lonely item
|
||||
if(second == null){
|
||||
if (second == null) {
|
||||
val resultItem = first.clone()
|
||||
var anvilCost = handleRename(resultItem, inventory)
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
if(first == resultItem){
|
||||
if (first == resultItem) {
|
||||
CustomAnvil.log("no right item, But input is same as output")
|
||||
event.result = null
|
||||
return
|
||||
|
|
@ -71,7 +72,7 @@ class AnvilEventListener : Listener {
|
|||
// We don't manually set item here as vanilla do it (renaming)
|
||||
//event.result = null
|
||||
|
||||
anvilCost+= calculatePenalty(first,null,resultItem)
|
||||
anvilCost += calculatePenalty(first, null, resultItem)
|
||||
|
||||
handleAnvilXp(inventory, event, anvilCost)
|
||||
return
|
||||
|
|
@ -91,19 +92,19 @@ class AnvilEventListener : Listener {
|
|||
if (!first.isEnchantedBook() && !second.isEnchantedBook()) {
|
||||
// we only need to be concerned with repair when neither item is a book
|
||||
val repaired = resultItem.repairFrom(first, second)
|
||||
anvilCost += if(repaired) ConfigOptions.itemRepairCost else 0
|
||||
anvilCost += if (repaired) ConfigOptions.itemRepairCost else 0
|
||||
}
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
if(first == resultItem){
|
||||
if (first == resultItem) {
|
||||
CustomAnvil.log("Mergable with second, But input is same as output")
|
||||
event.result = null
|
||||
return
|
||||
}
|
||||
// As calculatePenalty edit result, we need to calculate penalty after checking equality
|
||||
anvilCost+= calculatePenalty(first, second, resultItem)
|
||||
anvilCost += calculatePenalty(first, second, resultItem)
|
||||
// Calculate rename cost
|
||||
anvilCost+= handleRename(resultItem, inventory)
|
||||
anvilCost += handleRename(resultItem, inventory)
|
||||
|
||||
// Finally, we set result
|
||||
event.result = resultItem
|
||||
|
|
@ -114,19 +115,19 @@ class AnvilEventListener : Listener {
|
|||
|
||||
// Test for unit repair
|
||||
val unitRepairAmount = first.getRepair(second)
|
||||
if(unitRepairAmount != null){
|
||||
if (unitRepairAmount != null) {
|
||||
val resultItem = first.clone()
|
||||
var anvilCost = handleRename(resultItem, inventory)
|
||||
|
||||
val repairAmount = resultItem.unitRepair(second.amount, unitRepairAmount)
|
||||
if(repairAmount > 0){
|
||||
anvilCost += repairAmount*ConfigOptions.unitRepairCost
|
||||
if (repairAmount > 0) {
|
||||
anvilCost += repairAmount * ConfigOptions.unitRepairCost
|
||||
}
|
||||
// We do not care about right item penalty for unit repair
|
||||
anvilCost+= calculatePenalty(first,null,resultItem)
|
||||
anvilCost += calculatePenalty(first, null, resultItem)
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
if(first == resultItem){
|
||||
if (first == resultItem) {
|
||||
CustomAnvil.log("unit repair, But input is same as output")
|
||||
event.result = null
|
||||
return
|
||||
|
|
@ -134,16 +135,16 @@ class AnvilEventListener : Listener {
|
|||
event.result = resultItem
|
||||
|
||||
handleAnvilXp(inventory, event, anvilCost)
|
||||
}else{
|
||||
} else {
|
||||
CustomAnvil.log("no anvil fuse type found")
|
||||
event.result = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory): Int{
|
||||
private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory): Int {
|
||||
// Rename item and add renaming cost
|
||||
resultItem.itemMeta?.let {
|
||||
if(!it.displayName.contentEquals(inventory.renameText)){
|
||||
if (!it.displayName.contentEquals(inventory.renameText)) {
|
||||
it.setDisplayName(inventory.renameText)
|
||||
resultItem.itemMeta = it
|
||||
return ConfigOptions.itemRenameCost
|
||||
|
|
@ -158,9 +159,11 @@ class AnvilEventListener : Listener {
|
|||
@EventHandler(ignoreCancelled = true)
|
||||
fun anvilExtractionCheck(event: InventoryClickEvent) {
|
||||
val player = event.whoClicked as? Player ?: return
|
||||
if(!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
val inventory = event.inventory as? AnvilInventory ?: return
|
||||
if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return }
|
||||
if (event.rawSlot != ANVIL_OUTPUT_SLOT) {
|
||||
return
|
||||
}
|
||||
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
|
||||
val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||
val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||
|
|
@ -172,110 +175,117 @@ class AnvilEventListener : Listener {
|
|||
|| (unitRepairResult != null)
|
||||
|
||||
// True if there was no change or not allowed
|
||||
if((output == inventory.getItem(ANVIL_INPUT_LEFT))
|
||||
|| !allowed){
|
||||
if ((output == inventory.getItem(ANVIL_INPUT_LEFT))
|
||||
|| !allowed
|
||||
) {
|
||||
|
||||
event.result = Event.Result.DENY
|
||||
return
|
||||
}
|
||||
if(rightItem == null){
|
||||
if (rightItem == null) {
|
||||
event.result = Event.Result.ALLOW
|
||||
return
|
||||
}
|
||||
if(canMerge){
|
||||
if (canMerge) {
|
||||
event.result = Event.Result.ALLOW
|
||||
}else if(unitRepairResult != null){
|
||||
onUnitRepairExtract(leftItem, rightItem, output,
|
||||
unitRepairResult, event, player, inventory)
|
||||
} else if (unitRepairResult != null) {
|
||||
onUnitRepairExtract(
|
||||
leftItem, rightItem, output,
|
||||
unitRepairResult, event, player, inventory
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun onUnitRepairExtract(leftItem: ItemStack,
|
||||
rightItem: ItemStack,
|
||||
output: ItemStack,
|
||||
unitRepairResult: Double,
|
||||
event: InventoryClickEvent,
|
||||
player: Player,
|
||||
inventory: AnvilInventory){
|
||||
private fun onUnitRepairExtract(
|
||||
leftItem: ItemStack,
|
||||
rightItem: ItemStack,
|
||||
output: ItemStack,
|
||||
unitRepairResult: Double,
|
||||
event: InventoryClickEvent,
|
||||
player: Player,
|
||||
inventory: AnvilInventory
|
||||
) {
|
||||
val resultCopy = leftItem.clone()
|
||||
val resultAmount = resultCopy.unitRepair(
|
||||
rightItem.amount, unitRepairResult)
|
||||
rightItem.amount, unitRepairResult
|
||||
)
|
||||
|
||||
// To avoid vanilla, we cancel the event for unit repair
|
||||
event.result = Event.Result.DENY
|
||||
event.isCancelled = true
|
||||
// And we give the item manually
|
||||
// But first we check if we should give the item
|
||||
val slotDestination = getActionSlot(event,player)
|
||||
if(slotDestination.type == SlotType.NO_SLOT) return
|
||||
val slotDestination = getActionSlot(event, player)
|
||||
if (slotDestination.type == SlotType.NO_SLOT) return
|
||||
|
||||
// Test repair cost
|
||||
var repairCost = 0
|
||||
if(player.gameMode != GameMode.CREATIVE){
|
||||
if (player.gameMode != GameMode.CREATIVE) {
|
||||
// Get repairCost
|
||||
leftItem.itemMeta?.let { leftMeta ->
|
||||
val leftName = leftMeta.displayName
|
||||
output.itemMeta?.let {
|
||||
if(!leftName.contentEquals(it.displayName)){
|
||||
repairCost+= ConfigOptions.itemRenameCost
|
||||
if (!leftName.contentEquals(it.displayName)) {
|
||||
repairCost += ConfigOptions.itemRenameCost
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repairCost+= calculatePenalty(leftItem,null,resultCopy)
|
||||
repairCost+= resultAmount*ConfigOptions.unitRepairCost
|
||||
repairCost += calculatePenalty(leftItem, null, resultCopy)
|
||||
repairCost += resultAmount * ConfigOptions.unitRepairCost
|
||||
|
||||
if((inventory.maximumRepairCost < repairCost)
|
||||
|| (player.level < repairCost)) return
|
||||
if ((inventory.maximumRepairCost < repairCost)
|
||||
|| (player.level < repairCost)
|
||||
) return
|
||||
}
|
||||
// If not creative middle click...
|
||||
if(event.click != ClickType.MIDDLE){
|
||||
if (event.click != ClickType.MIDDLE) {
|
||||
// We remove what should be removed
|
||||
inventory.setItem(ANVIL_INPUT_LEFT,null)
|
||||
rightItem.amount-= resultAmount
|
||||
inventory.setItem(ANVIL_INPUT_RIGHT,rightItem)
|
||||
inventory.setItem(ANVIL_INPUT_LEFT, null)
|
||||
rightItem.amount -= resultAmount
|
||||
inventory.setItem(ANVIL_INPUT_RIGHT, rightItem)
|
||||
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
||||
player.level-= repairCost
|
||||
player.level -= repairCost
|
||||
}
|
||||
|
||||
// Finally, we add the item to the player
|
||||
if(slotDestination.type == SlotType.CURSOR){
|
||||
if (slotDestination.type == SlotType.CURSOR) {
|
||||
player.setItemOnCursor(output)
|
||||
}else{// We assume SlotType == SlotType.INVENTORY
|
||||
player.inventory.setItem(slotDestination.slot,output)
|
||||
} else {// We assume SlotType == SlotType.INVENTORY
|
||||
player.inventory.setItem(slotDestination.slot, output)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination slot or "NO_SLOT" slot container if there is no slot available
|
||||
*/
|
||||
private fun getActionSlot(event: InventoryClickEvent, player: Player): SlotContainer{
|
||||
if(event.isShiftClick){
|
||||
private fun getActionSlot(event: InventoryClickEvent, player: Player): SlotContainer {
|
||||
if (event.isShiftClick) {
|
||||
val inventory = player.inventory
|
||||
val firstEmpty = inventory.firstEmpty()
|
||||
if(firstEmpty == -1){
|
||||
val firstEmpty = inventory.firstEmpty()
|
||||
if (firstEmpty == -1) {
|
||||
return NO_SLOT
|
||||
}
|
||||
//check hotbare full
|
||||
var slotIndex = 8
|
||||
while(slotIndex >= 0 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)){
|
||||
while (slotIndex >= 0 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)) {
|
||||
slotIndex--
|
||||
}
|
||||
if(slotIndex >= 0){
|
||||
return SlotContainer(SlotType.INVENTORY,slotIndex)
|
||||
if (slotIndex >= 0) {
|
||||
return SlotContainer(SlotType.INVENTORY, slotIndex)
|
||||
}
|
||||
slotIndex = 35 //4*9 - 1 (max of player inventory)
|
||||
while(slotIndex >= 9 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)){
|
||||
while (slotIndex >= 9 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)) {
|
||||
slotIndex--
|
||||
}
|
||||
if(slotIndex < 9){
|
||||
if (slotIndex < 9) {
|
||||
return NO_SLOT
|
||||
}
|
||||
return SlotContainer(SlotType.INVENTORY,slotIndex)
|
||||
}else{
|
||||
if(player.itemOnCursor.type != Material.AIR){
|
||||
return SlotContainer(SlotType.INVENTORY, slotIndex)
|
||||
} else {
|
||||
if (player.itemOnCursor.type != Material.AIR) {
|
||||
return NO_SLOT
|
||||
}
|
||||
return CURSOR_SLOT
|
||||
|
|
@ -286,24 +296,29 @@ class AnvilEventListener : Listener {
|
|||
* Function to calculate work penalty of anvil work
|
||||
* Also change result work penalty
|
||||
*/
|
||||
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int{
|
||||
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int {
|
||||
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
|
||||
// Calculate work penalty
|
||||
val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0
|
||||
val rightPenalty =
|
||||
if(right == null){ 0 }
|
||||
else{ (right.itemMeta as? Repairable)?.repairCost ?: 0 }
|
||||
if (right == null) {
|
||||
0
|
||||
} else {
|
||||
(right.itemMeta as? Repairable)?.repairCost ?: 0
|
||||
}
|
||||
|
||||
// Try to set work penalty for the result item
|
||||
result.itemMeta?.let {
|
||||
(it as? Repairable)?.repairCost = leftPenalty*2+1
|
||||
(it as? Repairable)?.repairCost = leftPenalty * 2 + 1
|
||||
result.itemMeta = it
|
||||
}
|
||||
|
||||
CustomAnvil.log("Calculated penalty: " +
|
||||
"leftPenalty: $leftPenalty, " +
|
||||
"rightPenalty: $rightPenalty, " +
|
||||
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}")
|
||||
CustomAnvil.log(
|
||||
"Calculated penalty: " +
|
||||
"leftPenalty: $leftPenalty, " +
|
||||
"rightPenalty: $rightPenalty, " +
|
||||
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}"
|
||||
)
|
||||
|
||||
return leftPenalty + rightPenalty
|
||||
}
|
||||
|
|
@ -312,7 +327,7 @@ class AnvilEventListener : Listener {
|
|||
* Function to calculate right enchantment values
|
||||
* it include enchantment placed on final item and conflicting enchantment
|
||||
*/
|
||||
private fun getRightValues(right: ItemStack, result:ItemStack) : Int {
|
||||
private fun getRightValues(right: ItemStack, result: ItemStack): Int {
|
||||
// Calculate right value and illegal enchant penalty
|
||||
var illegalPenalty = 0
|
||||
var rightValue = 0
|
||||
|
|
@ -323,12 +338,16 @@ class AnvilEventListener : Listener {
|
|||
|
||||
for (enchantment in right.findEnchantments()) {
|
||||
// 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)
|
||||
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(resultEnchsKeys,result.type,enchantment.key)
|
||||
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(
|
||||
resultEnchsKeys,
|
||||
result.type,
|
||||
enchantment.key
|
||||
)
|
||||
resultEnchsKeys.remove(enchantment.key)
|
||||
|
||||
if(ConflictType.BIG_CONFLICT == conflictType){
|
||||
if (ConflictType.BIG_CONFLICT == conflictType) {
|
||||
illegalPenalty += ConfigOptions.sacrificeIllegalCost
|
||||
}
|
||||
continue
|
||||
|
|
@ -342,9 +361,11 @@ class AnvilEventListener : Listener {
|
|||
rightValue += value
|
||||
|
||||
}
|
||||
CustomAnvil.log("Calculated right values: " +
|
||||
"rightValue: $rightValue, " +
|
||||
"illegalPenalty: $illegalPenalty")
|
||||
CustomAnvil.log(
|
||||
"Calculated right values: " +
|
||||
"rightValue: $rightValue, " +
|
||||
"illegalPenalty: $illegalPenalty"
|
||||
)
|
||||
|
||||
return rightValue + illegalPenalty
|
||||
}
|
||||
|
|
@ -352,15 +373,16 @@ class AnvilEventListener : Listener {
|
|||
/**
|
||||
* Display xp needed for the work on the anvil inventory
|
||||
*/
|
||||
private fun handleAnvilXp(inventory: AnvilInventory,
|
||||
event: PrepareAnvilEvent,
|
||||
anvilCost: Int){
|
||||
private fun handleAnvilXp(
|
||||
inventory: AnvilInventory,
|
||||
event: PrepareAnvilEvent,
|
||||
anvilCost: Int
|
||||
) {
|
||||
// Test repair cost limit
|
||||
val finalAnvilCost: Int
|
||||
if (ConfigOptions.limitRepairCost) {
|
||||
finalAnvilCost = min(anvilCost, ConfigOptions.limitRepairValue)
|
||||
}else{
|
||||
finalAnvilCost = anvilCost
|
||||
val finalAnvilCost = if (ConfigOptions.limitRepairCost) {
|
||||
min(anvilCost, ConfigOptions.limitRepairValue)
|
||||
} else {
|
||||
anvilCost
|
||||
}
|
||||
|
||||
/* Because Minecraft likes to have the final say in the repair cost displayed
|
||||
|
|
@ -383,7 +405,7 @@ class AnvilEventListener : Listener {
|
|||
|
||||
|
||||
private class SlotContainer(val type: SlotType, val slot: Int)
|
||||
private enum class SlotType{
|
||||
private enum class SlotType {
|
||||
CURSOR,
|
||||
INVENTORY,
|
||||
NO_SLOT
|
||||
|
|
|
|||
|
|
@ -24,17 +24,22 @@ class CustomAnvil : JavaPlugin() {
|
|||
|
||||
// Permission string required to use the plugin's features
|
||||
const val affectedByPluginPermission = "ca.affected"
|
||||
|
||||
// Permission string required to bypass enchantment conflicts test
|
||||
const val bypassFusePermission = "ca.bypass.fuse"
|
||||
|
||||
// Permission string required to bypass enchantment conflicts test
|
||||
const val bypassLevelPermission = "ca.bypass.level"
|
||||
|
||||
// Permission string required to reload the config
|
||||
const val commandReloadPermission = "ca.command.reload"
|
||||
|
||||
// Permission string required to edit the plugin's config
|
||||
const val editConfigPermission = "ca.config.edit"
|
||||
|
||||
// Command Name to reload the config
|
||||
const val commandReloadName = "anvilconfigreload"
|
||||
|
||||
// Test command name
|
||||
const val commandTestName = "customanvilconfig"
|
||||
|
||||
|
|
@ -71,7 +76,7 @@ class CustomAnvil : JavaPlugin() {
|
|||
|
||||
// Disable old plugin name if exist
|
||||
val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus")
|
||||
if(potentialPlugin != null){
|
||||
if (potentialPlugin != null) {
|
||||
Bukkit.getPluginManager().disablePlugin(potentialPlugin)
|
||||
logger.warning("An old version of this plugin was detected")
|
||||
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
|
||||
|
|
@ -83,7 +88,7 @@ class CustomAnvil : JavaPlugin() {
|
|||
|
||||
// Load config
|
||||
val success = ConfigHolder.loadConfig()
|
||||
if(!success) return
|
||||
if (!success) return
|
||||
|
||||
// Load metrics
|
||||
val metric = Metrics(this, bstatsPluginId)
|
||||
|
|
@ -98,26 +103,28 @@ class CustomAnvil : JavaPlugin() {
|
|||
)
|
||||
}
|
||||
|
||||
fun reloadResource(resourceName: String,
|
||||
hardFailSafe:Boolean = true): YamlConfiguration?{
|
||||
fun reloadResource(
|
||||
resourceName: String,
|
||||
hardFailSafe: Boolean = true
|
||||
): YamlConfiguration? {
|
||||
// Save default resource
|
||||
val file = File(dataFolder,resourceName)
|
||||
if(!file.exists()){
|
||||
saveResource(resourceName,false)
|
||||
val file = File(dataFolder, resourceName)
|
||||
if (!file.exists()) {
|
||||
saveResource(resourceName, false)
|
||||
}
|
||||
// Load resource
|
||||
val yamlConfig = YamlConfiguration()
|
||||
try {
|
||||
val configReader = FileReader(file)
|
||||
yamlConfig.load(configReader)
|
||||
} catch (test: Exception){
|
||||
if(hardFailSafe){
|
||||
} catch (test: Exception) {
|
||||
if (hardFailSafe) {
|
||||
// This is important and may impact gameplay if it does not load.
|
||||
// Failsafe is to stop the plugin
|
||||
logger.severe("Resource $resourceName Could not be load or reload.")
|
||||
logger.severe("Disabling plugin.")
|
||||
Bukkit.getPluginManager().disablePlugin(this)
|
||||
}else{
|
||||
} else {
|
||||
logger.warning("Resource $resourceName Could not be load or reload.")
|
||||
}
|
||||
return null
|
||||
|
|
|
|||
|
|
@ -12,67 +12,94 @@ object ConfigOptions {
|
|||
|
||||
// Path for default enchantment limits
|
||||
private const val DEFAULT_LIMIT_PATH = "default_limit"
|
||||
|
||||
// Path for limiting repair cost
|
||||
const val LIMIT_REPAIR_COST = "limit_repair_cost"
|
||||
|
||||
// Path for repair value limit
|
||||
const val LIMIT_REPAIR_VALUE = "limit_repair_value"
|
||||
|
||||
// Path for level cost on item repair
|
||||
const val ITEM_REPAIR_COST = "item_repair_cost"
|
||||
|
||||
// Path for level cost on unit repair
|
||||
const val UNIT_REPAIR_COST = "unit_repair_cost"
|
||||
|
||||
// Path for level cost on item renaming
|
||||
const val ITEM_RENAME_COST = "item_rename_cost"
|
||||
|
||||
// Path for level cost on illegal enchantment on sacrifice
|
||||
const val SACRIFICE_ILLEGAL_COST = "sacrifice_illegal_enchant_cost"
|
||||
|
||||
// Path for removing repair cost limits
|
||||
const val REMOVE_REPAIR_LIMIT = "remove_repair_limit"
|
||||
|
||||
// Root path for enchantment limits
|
||||
const val ENCHANT_LIMIT_ROOT = "enchant_limits"
|
||||
|
||||
// Root path for enchantment values
|
||||
const val ENCHANT_VALUES_ROOT = "enchant_values"
|
||||
|
||||
// Keys for specific enchantment values
|
||||
private const val KEY_BOOK = "book"
|
||||
private const val KEY_ITEM = "item"
|
||||
|
||||
// Debug logging toggle path
|
||||
private const val DEBUG_LOGGING = "debug_log"
|
||||
|
||||
// Debug verbose logging toggle path
|
||||
private const val VERBOSE_DEBUG_LOGGING = "debug_log_verbose"
|
||||
|
||||
// Default value for enchantment limits
|
||||
private const val DEFAULT_ENCHANT_LIMIT = 5
|
||||
|
||||
// Default value for limiting repair cost
|
||||
const val DEFAULT_LIMIT_REPAIR = false
|
||||
|
||||
// Default value for repair cost limit
|
||||
const val DEFAULT_LIMIT_REPAIR_VALUE = 39
|
||||
|
||||
// Default value for level cost on item repair
|
||||
const val DEFAULT_ITEM_REPAIR_COST = 2
|
||||
|
||||
// Default value for level cost per unit repair
|
||||
const val DEFAULT_UNIT_REPAIR_COST = 1
|
||||
|
||||
// Default value for level cost on item renaming
|
||||
const val DEFAULT_ITEM_RENAME_COST = 1
|
||||
|
||||
// Default value for level cost on illegal enchantment on sacrifice
|
||||
const val DEFAULT_SACRIFICE_ILLEGAL_COST = 1
|
||||
|
||||
// Valid range for repair cost limit
|
||||
@JvmField
|
||||
val REPAIR_LIMIT_RANGE = 1..39
|
||||
|
||||
// Valid range for repair cost
|
||||
@JvmField
|
||||
val REPAIR_COST_RANGE = 0..255
|
||||
|
||||
// Valid range for rename cost
|
||||
@JvmField
|
||||
val ITEM_RENAME_COST_RANGE = 0..255
|
||||
|
||||
// Valid range for illegal enchantment conflict cost
|
||||
@JvmField
|
||||
val SACRIFICE_ILLEGAL_COST_RANGE = 0..255
|
||||
|
||||
// Default for removing repair cost limits
|
||||
const val DEFAULT_REMOVE_LIMIT = false
|
||||
|
||||
// Valid range for an enchantment limit
|
||||
@JvmField
|
||||
val ENCHANT_LIMIT_RANGE = 1..255
|
||||
|
||||
// Default value for an enchantment multiplier
|
||||
private const val DEFAULT_ENCHANT_VALUE = 0
|
||||
|
||||
// Default value for debug logging
|
||||
private const val DEFAULT_DEBUG_LOG = false
|
||||
|
||||
// Default value for debug logging
|
||||
private const val DEFAULT_VERBOSE_DEBUG_LOG = false
|
||||
|
||||
|
|
@ -155,6 +182,7 @@ object ConfigOptions {
|
|||
.takeIf { it in SACRIFICE_ILLEGAL_COST_RANGE }
|
||||
?: DEFAULT_SACRIFICE_ILLEGAL_COST
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to remove repair cost limit
|
||||
*/
|
||||
|
|
@ -217,8 +245,9 @@ object ConfigOptions {
|
|||
/**
|
||||
* Get an array of key of basic config options
|
||||
*/
|
||||
fun getBasicConfigKeys(): Array<String>{
|
||||
return arrayOf(DEFAULT_LIMIT_PATH,
|
||||
fun getBasicConfigKeys(): Array<String> {
|
||||
return arrayOf(
|
||||
DEFAULT_LIMIT_PATH,
|
||||
LIMIT_REPAIR_COST,
|
||||
LIMIT_REPAIR_VALUE,
|
||||
ITEM_REPAIR_COST,
|
||||
|
|
|
|||
|
|
@ -34,43 +34,51 @@ object EnchantmentUtil {
|
|||
if (!containsKey(enchantment)) {
|
||||
// Add the enchantment if it doesn't have conflicts, or if player is allowed to bypass enchantment restrictions
|
||||
this[enchantment] = level
|
||||
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys,mat,enchantment);
|
||||
if(!player.hasPermission(CustomAnvil.bypassFusePermission) &&
|
||||
(conflictType != ConflictType.NO_CONFLICT)){
|
||||
val conflictType =
|
||||
ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys, mat, enchantment)
|
||||
if (!player.hasPermission(CustomAnvil.bypassFusePermission) &&
|
||||
(conflictType != ConflictType.NO_CONFLICT)
|
||||
) {
|
||||
CustomAnvil.verboseLog("Enchantment not yet in result list, but there is conflict (${enchantment.key}, conflict: $conflictType)")
|
||||
this.remove(enchantment)
|
||||
}
|
||||
|
||||
}
|
||||
// Enchantment already in result list
|
||||
else{
|
||||
else {
|
||||
// ... and they are conflicting
|
||||
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys,mat,enchantment)
|
||||
if((conflictType != ConflictType.NO_CONFLICT)
|
||||
&& !player.hasPermission(CustomAnvil.bypassFusePermission)){
|
||||
val conflictType =
|
||||
ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys, mat, enchantment)
|
||||
if ((conflictType != ConflictType.NO_CONFLICT)
|
||||
&& !player.hasPermission(CustomAnvil.bypassFusePermission)
|
||||
) {
|
||||
CustomAnvil.verboseLog("Enchantment already in result list, and they are conflicting (${enchantment.key}, conflict: $conflictType)")
|
||||
return@forEach
|
||||
}
|
||||
|
||||
// ... and they're not the same level
|
||||
if(this[enchantment] != other[enchantment]){
|
||||
if (this[enchantment] != other[enchantment]) {
|
||||
val newLevel = max(this[enchantment] ?: 0, other[enchantment] ?: 0)
|
||||
// apply the greater of the two if non-zero
|
||||
|
||||
if (newLevel > 0) { this[enchantment] = newLevel }
|
||||
if (newLevel > 0) {
|
||||
this[enchantment] = newLevel
|
||||
}
|
||||
}
|
||||
// ... and they're the same level
|
||||
else {
|
||||
// try to increase the enchantment level by 1
|
||||
var newLevel = this[enchantment]!! +1
|
||||
var newLevel = this[enchantment]!! + 1
|
||||
// Get max level or 255 if player can bypass
|
||||
val maxLevel = if(player.hasPermission(CustomAnvil.bypassLevelPermission)){
|
||||
val maxLevel = if (player.hasPermission(CustomAnvil.bypassLevelPermission)) {
|
||||
255
|
||||
}else{
|
||||
} else {
|
||||
ConfigOptions.enchantLimit(enchantment)
|
||||
}
|
||||
newLevel = min(newLevel, maxLevel)
|
||||
if (newLevel > 0) { this[enchantment] = newLevel }
|
||||
if (newLevel > 0) {
|
||||
this[enchantment] = newLevel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ object ItemUtil {
|
|||
(itemMeta as? Damageable)?.let {
|
||||
val durability = type.maxDurability.toInt()
|
||||
val firstDamage = (first.itemMeta as? Damageable)?.damage ?: 0
|
||||
if( firstDamage == 0) return false
|
||||
if (firstDamage == 0) return false
|
||||
|
||||
val firstDurability = durability - firstDamage
|
||||
val secondDamage = (second.itemMeta as? Damageable)?.damage ?: 0
|
||||
|
|
@ -96,12 +96,12 @@ object ItemUtil {
|
|||
(itemMeta as? Damageable)?.let {
|
||||
val durability = type.maxDurability.toInt()
|
||||
val firstDamage = it.damage
|
||||
if( firstDamage == 0) return 0
|
||||
if (firstDamage == 0) return 0
|
||||
var unitCount = 0
|
||||
var damage = firstDamage
|
||||
while((unitCount < unitAmount) && (damage > 0)){
|
||||
while ((unitCount < unitAmount) && (damage > 0)) {
|
||||
unitCount++
|
||||
damage = ceil(firstDamage - durability*percentPerUnit*unitCount).toInt()
|
||||
damage = ceil(firstDamage - durability * percentPerUnit * unitCount).toInt()
|
||||
}
|
||||
|
||||
it.damage = max(damage, 0)
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions
|
|||
class EditConfigExecutor : CommandExecutor {
|
||||
|
||||
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
|
||||
if(!sender.hasPermission(CustomAnvil.editConfigPermission)) {
|
||||
if (!sender.hasPermission(CustomAnvil.editConfigPermission)) {
|
||||
sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM)
|
||||
return false
|
||||
}
|
||||
if(sender !is HumanEntity) return false
|
||||
if (sender !is HumanEntity) return false
|
||||
MainConfigGui.INSTANCE.show(sender)
|
||||
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@ import xyz.alexcrea.cuanvil.util.MetricsUtil
|
|||
|
||||
class ReloadExecutor : CommandExecutor {
|
||||
override fun onCommand(sender: CommandSender, cmd: Command, cmdstr: String, args: Array<out String>): Boolean {
|
||||
if(!sender.hasPermission(CustomAnvil.commandReloadPermission)) {
|
||||
if (!sender.hasPermission(CustomAnvil.commandReloadPermission)) {
|
||||
sender.sendMessage("§cYou do not have permission to reload the config")
|
||||
return false
|
||||
}
|
||||
sender.sendMessage("§eReloading config...")
|
||||
val hardfail = args.isNotEmpty() && ("hard".equals(args[0],true))
|
||||
val hardfail = args.isNotEmpty() && ("hard".equals(args[0], true))
|
||||
val commandSuccess = commandBody(hardfail)
|
||||
if(commandSuccess){
|
||||
if (commandSuccess) {
|
||||
sender.sendMessage("§aConfig reloaded !")
|
||||
}else{
|
||||
} else {
|
||||
sender.sendMessage("§cConfig was not able to be reloaded...")
|
||||
if(hardfail){
|
||||
if (hardfail) {
|
||||
sender.sendMessage("§4Hard fail, plugin disabled")
|
||||
}
|
||||
}
|
||||
|
|
@ -34,9 +34,9 @@ class ReloadExecutor : CommandExecutor {
|
|||
/**
|
||||
* Execute the command, return true if success or false otherwise
|
||||
*/
|
||||
private fun commandBody(hardfail: Boolean): Boolean{
|
||||
private fun commandBody(hardfail: Boolean): Boolean {
|
||||
try {
|
||||
if(!ConfigHolder.reloadAllFromDisk(hardfail)) return false
|
||||
if (!ConfigHolder.reloadAllFromDisk(hardfail)) return false
|
||||
|
||||
// Then update all global gui containing value from config
|
||||
BasicConfigGui.INSTANCE.updateGuiValues()
|
||||
|
|
@ -48,7 +48,7 @@ class ReloadExecutor : CommandExecutor {
|
|||
MetricsUtil.testIfConfigIsDefault()
|
||||
|
||||
return true
|
||||
}catch (e: Exception){
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import org.bukkit.Material
|
|||
import java.util.*
|
||||
|
||||
abstract class AbstractMaterialGroup(private val name: String) {
|
||||
protected val includedMaterial by lazy {createDefaultSet()}
|
||||
protected val includedMaterial by lazy { createDefaultSet() }
|
||||
|
||||
/**
|
||||
* Get the group default set
|
||||
|
|
@ -14,24 +14,24 @@ abstract class AbstractMaterialGroup(private val name: String) {
|
|||
/**
|
||||
* Get if a material is allowed following the group policy
|
||||
*/
|
||||
open fun contain(mat : Material): Boolean {
|
||||
open fun contain(mat: Material): Boolean {
|
||||
return mat in getMaterials()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if a group is referenced by this:
|
||||
*/
|
||||
abstract fun isReferencing(other : AbstractMaterialGroup): Boolean
|
||||
abstract fun isReferencing(other: AbstractMaterialGroup): Boolean
|
||||
|
||||
/**
|
||||
* Push a material to this group to follow this group policy
|
||||
*/
|
||||
abstract fun addToPolicy(mat : Material)
|
||||
abstract fun addToPolicy(mat: Material)
|
||||
|
||||
/**
|
||||
* Push a group to this group to follow this group policy
|
||||
*/
|
||||
abstract fun addToPolicy(other : AbstractMaterialGroup)
|
||||
abstract fun addToPolicy(other: AbstractMaterialGroup)
|
||||
|
||||
/**
|
||||
* Get the group contained material as a set
|
||||
|
|
@ -44,6 +44,7 @@ abstract class AbstractMaterialGroup(private val name: String) {
|
|||
open fun getNonGroupInheritedMaterials(): EnumSet<Material> {
|
||||
return includedMaterial
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the group non-inherited material as a set
|
||||
*/
|
||||
|
|
@ -69,19 +70,19 @@ abstract class AbstractMaterialGroup(private val name: String) {
|
|||
*/
|
||||
abstract fun getGroups(): MutableSet<AbstractMaterialGroup>
|
||||
|
||||
open fun getRepresentativeMaterial() : Material {
|
||||
open fun getRepresentativeMaterial(): Material {
|
||||
// Test inner material
|
||||
val matIterator = includedMaterial.iterator()
|
||||
while(matIterator.hasNext()){
|
||||
while (matIterator.hasNext()) {
|
||||
val material = matIterator.next()
|
||||
if(material.isAir) continue
|
||||
if (material.isAir) continue
|
||||
return material
|
||||
}
|
||||
// Test included group representative material
|
||||
val groupIterator = getGroups().iterator()
|
||||
while (groupIterator.hasNext()){
|
||||
while (groupIterator.hasNext()) {
|
||||
val groupMat = groupIterator.next().getRepresentativeMaterial()
|
||||
if(groupMat.isAir) continue
|
||||
if (groupMat.isAir) continue
|
||||
return groupMat
|
||||
}
|
||||
return Material.PAPER
|
||||
|
|
|
|||
|
|
@ -7,29 +7,30 @@ import org.bukkit.enchantments.Enchantment
|
|||
class EnchantConflictGroup(
|
||||
val name: String,
|
||||
private val cantConflict: AbstractMaterialGroup,
|
||||
val minBeforeBlock: Int){
|
||||
val minBeforeBlock: Int
|
||||
) {
|
||||
|
||||
private val enchantments = HashSet<Enchantment>()
|
||||
|
||||
fun addEnchantment(enchant: Enchantment){
|
||||
fun addEnchantment(enchant: Enchantment) {
|
||||
enchantments.add(enchant)
|
||||
}
|
||||
|
||||
fun allowed(enchants: Set<Enchantment>, mat: Material) : Boolean{
|
||||
if(enchantments.size < minBeforeBlock){
|
||||
fun allowed(enchants: Set<Enchantment>, mat: Material): Boolean {
|
||||
if (enchantments.size < minBeforeBlock) {
|
||||
return true
|
||||
}
|
||||
|
||||
if(cantConflict.contain(mat)){
|
||||
if (cantConflict.contain(mat)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Count the amount of enchantment that are in the list
|
||||
var enchantAmount = 0
|
||||
for (enchantment in enchants) {
|
||||
if(enchantment !in enchantments) continue
|
||||
if (enchantment !in enchantments) continue
|
||||
CustomAnvil.verboseLog("Enchant ${enchantment.key} is in: ${enchantAmount + 1}/$minBeforeBlock ")
|
||||
if(++enchantAmount > minBeforeBlock){
|
||||
if (++enchantAmount > minBeforeBlock) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -37,8 +38,8 @@ class EnchantConflictGroup(
|
|||
return true
|
||||
}
|
||||
|
||||
fun getCantConflictGroup(): AbstractMaterialGroup{
|
||||
return this.cantConflict;
|
||||
fun getCantConflictGroup(): AbstractMaterialGroup {
|
||||
return this.cantConflict
|
||||
}
|
||||
|
||||
fun getEnchants(): HashSet<Enchantment> {
|
||||
|
|
@ -53,9 +54,9 @@ class EnchantConflictGroup(
|
|||
fun getRepresentativeMaterial(): Material {
|
||||
val groups = getCantConflictGroup().getGroups()
|
||||
val groupIterator = groups.iterator()
|
||||
while (groupIterator.hasNext()){
|
||||
while (groupIterator.hasNext()) {
|
||||
val mat = groupIterator.next().getRepresentativeMaterial()
|
||||
if(mat != Material.ENCHANTED_BOOK) return mat
|
||||
if (mat != Material.ENCHANTED_BOOK) return mat
|
||||
|
||||
}
|
||||
return Material.ENCHANTED_BOOK
|
||||
|
|
|
|||
|
|
@ -11,13 +11,17 @@ 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
|
||||
private const val DEFAULT_GROUP_NAME = "joinedGroup"
|
||||
}
|
||||
|
|
@ -26,64 +30,64 @@ class EnchantConflictManager {
|
|||
lateinit var conflictList: ArrayList<EnchantConflictGroup>
|
||||
|
||||
// Read and prepare all conflict
|
||||
fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager){
|
||||
fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager) {
|
||||
conflictMap = HashMap()
|
||||
conflictList = ArrayList()
|
||||
|
||||
val keys = config.getKeys(false)
|
||||
for (key in keys) {
|
||||
val section = config.getConfigurationSection(key)!!
|
||||
val conflict = createConflict(section,itemManager,key)
|
||||
if(conflict != null){
|
||||
addToMap(conflict)
|
||||
conflictList.add(conflict)
|
||||
}
|
||||
val conflict = createConflict(section, itemManager, key)
|
||||
|
||||
addToMap(conflict)
|
||||
conflictList.add(conflict)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add the conflict to the map
|
||||
private fun addToMap(conflict: EnchantConflictGroup){
|
||||
conflict.getEnchants().forEach{ enchant ->
|
||||
addConflictToConflictMap(enchant, conflict);
|
||||
private fun addToMap(conflict: EnchantConflictGroup) {
|
||||
conflict.getEnchants().forEach { enchant ->
|
||||
addConflictToConflictMap(enchant, conflict)
|
||||
}
|
||||
}
|
||||
|
||||
fun addConflictToConflictMap(enchant: Enchantment, conflict: EnchantConflictGroup){
|
||||
if(!conflictMap.containsKey(enchant)){
|
||||
fun addConflictToConflictMap(enchant: Enchantment, conflict: EnchantConflictGroup) {
|
||||
if (!conflictMap.containsKey(enchant)) {
|
||||
conflictMap[enchant] = ArrayList()
|
||||
}
|
||||
conflictMap[enchant]!!.add(conflict)
|
||||
}
|
||||
|
||||
fun removeConflictFromMap(enchant: Enchantment, conflict: EnchantConflictGroup): Boolean{
|
||||
fun removeConflictFromMap(enchant: Enchantment, conflict: EnchantConflictGroup): Boolean {
|
||||
return conflictMap[enchant]!!.remove(conflict)
|
||||
}
|
||||
|
||||
// create and read a conflict from a yaml section
|
||||
private fun createConflict(section: ConfigurationSection,
|
||||
itemManager: ItemGroupManager,
|
||||
conflictName: String): EnchantConflictGroup? {
|
||||
private fun createConflict(
|
||||
section: ConfigurationSection,
|
||||
itemManager: ItemGroupManager,
|
||||
conflictName: String
|
||||
): EnchantConflictGroup {
|
||||
// Is it planed for the future
|
||||
val futureUse = section.getBoolean(FUTURE_USE_PATH,false)
|
||||
val futureUse = section.getBoolean(FUTURE_USE_PATH, false)
|
||||
// Create conflict
|
||||
val conflict = createConflictObject(section,itemManager,conflictName)
|
||||
val conflict = createConflictObject(section, itemManager, conflictName)
|
||||
// Read and add enchantment to conflict
|
||||
val enchantList = section.getStringList(ENCH_LIST_PATH)
|
||||
for (enchantName in enchantList) {
|
||||
val enchantKey = NamespacedKey.minecraft(enchantName)
|
||||
val enchant = Enchantment.getByKey(enchantKey)
|
||||
if(enchant == null){
|
||||
if(!futureUse){
|
||||
if (enchant == null) {
|
||||
if (!futureUse) {
|
||||
CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName")
|
||||
}
|
||||
continue
|
||||
}
|
||||
conflict.addEnchantment(enchant)
|
||||
}
|
||||
if(conflict.getEnchants().size == 0){
|
||||
if(!futureUse){
|
||||
if (conflict.getEnchants().size == 0) {
|
||||
if (!futureUse) {
|
||||
CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not do anything")
|
||||
}
|
||||
}
|
||||
|
|
@ -91,12 +95,14 @@ class EnchantConflictManager {
|
|||
return conflict
|
||||
}
|
||||
|
||||
private fun createConflictObject(section: ConfigurationSection,
|
||||
itemManager: ItemGroupManager,
|
||||
conflictName: String): EnchantConflictGroup {
|
||||
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){
|
||||
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")
|
||||
|
|
@ -112,9 +118,13 @@ class EnchantConflictManager {
|
|||
return EnchantConflictGroup(conflictName, finalGroup, minBeforeBlock)
|
||||
}
|
||||
|
||||
private fun findGroup(groupName: String, itemManager: ItemGroupManager, conflictName: String): AbstractMaterialGroup {
|
||||
private fun findGroup(
|
||||
groupName: String,
|
||||
itemManager: ItemGroupManager,
|
||||
conflictName: String
|
||||
): AbstractMaterialGroup {
|
||||
val group = itemManager.get(groupName)
|
||||
if(group == null){
|
||||
if (group == null) {
|
||||
CustomAnvil.instance.logger.warning("Group $groupName do not exist but is ask by conflict $conflictName")
|
||||
return IncludeGroup("error_placeholder")
|
||||
}
|
||||
|
|
@ -122,7 +132,7 @@ class EnchantConflictManager {
|
|||
return group
|
||||
}
|
||||
|
||||
fun isConflicting(base: Set<Enchantment>,mat: Material, newEnchant: Enchantment): ConflictType {
|
||||
fun isConflicting(base: Set<Enchantment>, mat: Material, newEnchant: Enchantment): ConflictType {
|
||||
CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${mat.key}")
|
||||
val conflictList = conflictMap[newEnchant] ?: return ConflictType.NO_CONFLICT
|
||||
CustomAnvil.verboseLog("Did not get skipped")
|
||||
|
|
@ -130,13 +140,13 @@ class EnchantConflictManager {
|
|||
var result = ConflictType.NO_CONFLICT
|
||||
for (conflict in conflictList) {
|
||||
CustomAnvil.verboseLog("Is against ${conflict.name}")
|
||||
val conflicting = conflict.allowed(base,mat)
|
||||
val conflicting = conflict.allowed(base, mat)
|
||||
CustomAnvil.verboseLog("Was against ${conflict.name} and conflicting: $conflicting ")
|
||||
if(!conflicting) {
|
||||
if(conflict.getEnchants().size <= 1){
|
||||
if (!conflicting) {
|
||||
if (conflict.getEnchants().size <= 1) {
|
||||
result = ConflictType.SMALL_CONFLICT
|
||||
CustomAnvil.verboseLog("Small conflict, continuing")
|
||||
}else{
|
||||
} else {
|
||||
return ConflictType.BIG_CONFLICT
|
||||
}
|
||||
}
|
||||
|
|
@ -146,7 +156,7 @@ class EnchantConflictManager {
|
|||
|
||||
}
|
||||
|
||||
enum class ConflictType{
|
||||
enum class ConflictType {
|
||||
NO_CONFLICT,
|
||||
SMALL_CONFLICT,
|
||||
BIG_CONFLICT
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@ package xyz.alexcrea.cuanvil.group
|
|||
import org.bukkit.Material
|
||||
import java.util.*
|
||||
|
||||
class ExcludeGroup(name: String): AbstractMaterialGroup(name) {
|
||||
class ExcludeGroup(name: String) : AbstractMaterialGroup(name) {
|
||||
override fun createDefaultSet(): EnumSet<Material> {
|
||||
return EnumSet.allOf(Material::class.java)
|
||||
}
|
||||
|
||||
private var includedGroup: MutableSet<AbstractMaterialGroup> = HashSet()
|
||||
private val groupItems by lazy {createDefaultSet()}
|
||||
private val groupItems by lazy { createDefaultSet() }
|
||||
|
||||
override fun isReferencing(other: AbstractMaterialGroup): Boolean {
|
||||
for (materialGroup in includedGroup.iterator()) {
|
||||
if((materialGroup == other) || (materialGroup.isReferencing(other))){
|
||||
if ((materialGroup == other) || (materialGroup.isReferencing(other))) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ class ExcludeGroup(name: String): AbstractMaterialGroup(name) {
|
|||
|
||||
includedGroup.clear()
|
||||
groups.forEach { group ->
|
||||
if(!group.isReferencing(this)) {
|
||||
if (!group.isReferencing(this)) {
|
||||
includedGroup.add(group)
|
||||
groupItems.removeAll(group.getMaterials())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@ package xyz.alexcrea.cuanvil.group
|
|||
import org.bukkit.Material
|
||||
import java.util.*
|
||||
|
||||
class IncludeGroup(name: String): AbstractMaterialGroup(name) {
|
||||
class IncludeGroup(name: String) : AbstractMaterialGroup(name) {
|
||||
override fun createDefaultSet(): EnumSet<Material> {
|
||||
return EnumSet.noneOf(Material::class.java)
|
||||
}
|
||||
|
||||
private var includedGroup: MutableSet<AbstractMaterialGroup> = HashSet()
|
||||
private val groupItems by lazy {createDefaultSet()}
|
||||
private val groupItems by lazy { createDefaultSet() }
|
||||
|
||||
override fun isReferencing(other: AbstractMaterialGroup): Boolean {
|
||||
for (materialGroup in includedGroup.iterator()) {
|
||||
if((materialGroup == other) || (materialGroup.isReferencing(other))){
|
||||
if ((materialGroup == other) || (materialGroup.isReferencing(other))) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ class IncludeGroup(name: String): AbstractMaterialGroup(name) {
|
|||
|
||||
includedGroup.clear()
|
||||
groups.forEach { group ->
|
||||
if(!group.isReferencing(this)){
|
||||
if (!group.isReferencing(this)) {
|
||||
includedGroup.add(group)
|
||||
groupItems.addAll(group.getMaterials())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,49 +4,53 @@ import io.delilaheve.CustomAnvil
|
|||
import org.bukkit.Material
|
||||
import org.bukkit.configuration.ConfigurationSection
|
||||
import java.util.*
|
||||
import kotlin.collections.LinkedHashMap
|
||||
|
||||
class ItemGroupManager {
|
||||
|
||||
companion object {
|
||||
// Path for group type
|
||||
private const val GROUP_TYPE_PATH = "type"
|
||||
|
||||
// Path for included items list
|
||||
private const val MATERIAL_LIST_PATH = "items"
|
||||
|
||||
// Path for included groups list
|
||||
private const val GROUP_LIST_PATH = "groups"
|
||||
|
||||
// Temporary list of elements in default config that are use in future
|
||||
private val FUTURE_MATERIAL = setOf("PIGLIN_HEAD","BRUSH")
|
||||
private val FUTURE_MATERIAL = setOf("PIGLIN_HEAD", "BRUSH")
|
||||
}
|
||||
|
||||
lateinit var groupMap : LinkedHashMap<String, AbstractMaterialGroup>
|
||||
lateinit var groupMap: LinkedHashMap<String, AbstractMaterialGroup>
|
||||
|
||||
// Read and create material groups
|
||||
fun prepareGroups(config: ConfigurationSection){
|
||||
fun prepareGroups(config: ConfigurationSection) {
|
||||
groupMap = LinkedHashMap()
|
||||
|
||||
val keys = config.getKeys(false)
|
||||
for (key in keys) {
|
||||
if(groupMap.containsKey(key))
|
||||
if (groupMap.containsKey(key))
|
||||
continue
|
||||
createGroup(config, keys, key)
|
||||
}
|
||||
}
|
||||
|
||||
// Create group by key
|
||||
private fun createGroup(config: ConfigurationSection,
|
||||
keys: Set<String>,
|
||||
key: String): AbstractMaterialGroup {
|
||||
private fun createGroup(
|
||||
config: ConfigurationSection,
|
||||
keys: Set<String>,
|
||||
key: String
|
||||
): AbstractMaterialGroup {
|
||||
val groupSection = config.getConfigurationSection(key)!!
|
||||
val groupType = groupSection.getString(GROUP_TYPE_PATH,null)
|
||||
val groupType = groupSection.getString(GROUP_TYPE_PATH, null)
|
||||
|
||||
// Create Material group according to the group type
|
||||
val group: AbstractMaterialGroup
|
||||
if(GroupType.EXCLUDE.equal(groupType)){
|
||||
if (GroupType.EXCLUDE.equal(groupType)) {
|
||||
group = ExcludeGroup(key)
|
||||
}else {
|
||||
} else {
|
||||
group = IncludeGroup(key)
|
||||
if(!GroupType.INCLUDE.equal(groupType)){
|
||||
if (!GroupType.INCLUDE.equal(groupType)) {
|
||||
CustomAnvil.instance.logger.warning("Group $key have an invalid group type. default to Include.")
|
||||
}
|
||||
}
|
||||
|
|
@ -57,20 +61,23 @@ class ItemGroupManager {
|
|||
}
|
||||
|
||||
// Read Group elements
|
||||
private fun readGroup(group: AbstractMaterialGroup,
|
||||
groupSection: ConfigurationSection,
|
||||
config: ConfigurationSection,
|
||||
keys: Set<String>){
|
||||
private fun readGroup(
|
||||
group: AbstractMaterialGroup,
|
||||
groupSection: ConfigurationSection,
|
||||
config: ConfigurationSection,
|
||||
keys: Set<String>
|
||||
) {
|
||||
// Read material to include in this group policy
|
||||
val materialList = groupSection.getStringList(MATERIAL_LIST_PATH)
|
||||
for (materialTemp in materialList) {
|
||||
val materialName = materialTemp.uppercase(Locale.getDefault())
|
||||
val material = Material.getMaterial(materialName)
|
||||
if(material == null){
|
||||
if (material == null) {
|
||||
// Check if we should warn the user
|
||||
if(materialName !in FUTURE_MATERIAL){
|
||||
if (materialName !in FUTURE_MATERIAL) {
|
||||
CustomAnvil.instance.logger.warning(
|
||||
"Unknown material $materialTemp on group ${group.getName()}")
|
||||
"Unknown material $materialTemp on group ${group.getName()}"
|
||||
)
|
||||
|
||||
}
|
||||
continue
|
||||
|
|
@ -82,23 +89,26 @@ class ItemGroupManager {
|
|||
// please note the group name is case-sensitive.
|
||||
val groupList = groupSection.getStringList(GROUP_LIST_PATH)
|
||||
for (groupName in groupList) {
|
||||
if(groupName !in keys){
|
||||
if (groupName !in keys) {
|
||||
CustomAnvil.instance.logger.warning(
|
||||
"Group $groupName do not exist but is included in group ${group.getName()}")
|
||||
"Group $groupName do not exist but is included in group ${group.getName()}"
|
||||
)
|
||||
continue
|
||||
}
|
||||
// Get other group or create it if not yet created
|
||||
val otherGroup = if(!groupMap.containsKey(groupName)){
|
||||
createGroup(config,keys,groupName)
|
||||
}else{
|
||||
val otherGroup = if (!groupMap.containsKey(groupName)) {
|
||||
createGroup(config, keys, groupName)
|
||||
} else {
|
||||
groupMap[groupName]!!
|
||||
}
|
||||
// Avoid self reference or it will create an infinite loop
|
||||
if(otherGroup.isReferencing(group)){
|
||||
if (otherGroup.isReferencing(group)) {
|
||||
CustomAnvil.instance.logger.warning(
|
||||
"Group $groupName is on a reference loop with group ${group.getName()} !")
|
||||
"Group $groupName is on a reference loop with group ${group.getName()} !"
|
||||
)
|
||||
CustomAnvil.instance.logger.warning(
|
||||
"Please fix it in your item_groups config or the plugin will probably not work as expected.")
|
||||
"Please fix it in your item_groups config or the plugin will probably not work as expected."
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -121,10 +131,10 @@ enum class GroupType(private val groupID: String) {
|
|||
;
|
||||
|
||||
// Test if string is equal to the groupID of this enum
|
||||
fun equal(toTest: String?): Boolean{
|
||||
if(toTest == null)
|
||||
fun equal(toTest: String?): Boolean {
|
||||
if (toTest == null)
|
||||
return false
|
||||
return groupID.contentEquals(toTest.lowercase(Locale.getDefault()))
|
||||
return groupID.contentEquals(toTest.lowercase(Locale.getDefault()))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import java.util.*
|
|||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.function.Consumer
|
||||
|
||||
class ChatEventListener : Listener{
|
||||
class ChatEventListener : Listener {
|
||||
|
||||
private val playerListenMap: ConcurrentHashMap<UUID, Consumer<String?>> = ConcurrentHashMap()
|
||||
|
||||
|
|
|
|||
|
|
@ -31,12 +31,11 @@ object MetricsUtil {
|
|||
*/
|
||||
private fun getHashFromKey(section: ConfigurationSection, key: String): Int {
|
||||
// Key is assumend to exist
|
||||
val resultHash: Int
|
||||
if(section.isConfigurationSection(key)){
|
||||
val resultHash = if (section.isConfigurationSection(key)) {
|
||||
val sectionResult = getConfigurationHash(section.getConfigurationSection(key)!!)
|
||||
resultHash = key.hashCode() xor sectionResult
|
||||
}else{
|
||||
resultHash = key.hashCode() xor section.getString(key).hashCode()
|
||||
key.hashCode() xor sectionResult
|
||||
} else {
|
||||
key.hashCode() xor section.getString(key).hashCode()
|
||||
}
|
||||
return resultHash.hashCode()
|
||||
}
|
||||
|
|
@ -47,7 +46,7 @@ object MetricsUtil {
|
|||
private fun getConfigurationHash(section: ConfigurationSection): Int {
|
||||
var resultHash = 0
|
||||
for (key in section.getKeys(false)) {
|
||||
resultHash = resultHash xor getHashFromKey(section,key)
|
||||
resultHash = resultHash xor getHashFromKey(section, key)
|
||||
}
|
||||
return resultHash
|
||||
}
|
||||
|
|
@ -55,10 +54,10 @@ object MetricsUtil {
|
|||
/**
|
||||
* Get hash value of the default config
|
||||
*/
|
||||
private fun testBaseConfig(defaultConfig: ConfigurationSection): Int{
|
||||
private fun testBaseConfig(defaultConfig: ConfigurationSection): Int {
|
||||
var result = 0
|
||||
for (key in ConfigOptions.getBasicConfigKeys()) {
|
||||
result = result xor getHashFromKey(defaultConfig,key)
|
||||
result = result xor getHashFromKey(defaultConfig, key)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -66,7 +65,7 @@ object MetricsUtil {
|
|||
/**
|
||||
* Test if the used configuration is the default config
|
||||
*/
|
||||
fun testIfConfigIsDefault(){
|
||||
fun testIfConfigIsDefault() {
|
||||
// Calculate hash of config
|
||||
val baseConfig = testBaseConfig(ConfigHolder.DEFAULT_CONFIG.config)
|
||||
val limitEnchantConfig = getHashFromKey(ConfigHolder.DEFAULT_CONFIG.config, ConfigOptions.ENCHANT_LIMIT_ROOT)
|
||||
|
|
@ -77,37 +76,49 @@ object MetricsUtil {
|
|||
// Test if default
|
||||
isDefaultBaseConfig = baseConfigHash == baseConfig
|
||||
isDefaultEnchantLimitsConfig = enchantLimitsConfigHash == limitEnchantConfig
|
||||
isDefaultEnchantValuesConfig = enchantValuesConfigHash == enchantValueConfig
|
||||
isDefaultEnchantValuesConfig = enchantValuesConfigHash == enchantValueConfig
|
||||
isDefaultEnchantConflictConfig = enchantConflictConfigHash == enchantConflictConfig
|
||||
isDefaultItemGroupsConfig = itemGroupsConfigHash == itemGroupConfig
|
||||
isDefaultUnitRepairItemConfig = unitRepairItemConfigHash == unitRepairConfig
|
||||
// If not default and debug flag active, print the hash.
|
||||
if(ConfigOptions.debugLog){
|
||||
if(!isDefaultBaseConfig){CustomAnvil.log("baseConfig: $baseConfig")}
|
||||
if(!isDefaultEnchantLimitsConfig){CustomAnvil.log("limitEnchantConfig: $limitEnchantConfig")}
|
||||
if(!isDefaultEnchantValuesConfig){CustomAnvil.log("enchantValueConfig: $enchantValueConfig")}
|
||||
if(!isDefaultEnchantConflictConfig){CustomAnvil.log("enchantConflictConfig: $enchantConflictConfig")}
|
||||
if(!isDefaultItemGroupsConfig){CustomAnvil.log("itemGroupConfig: $itemGroupConfig")}
|
||||
if(!isDefaultUnitRepairItemConfig){CustomAnvil.log("unitRepairConfig: $unitRepairConfig")}
|
||||
if (ConfigOptions.debugLog) {
|
||||
if (!isDefaultBaseConfig) {
|
||||
CustomAnvil.log("baseConfig: $baseConfig")
|
||||
}
|
||||
if (!isDefaultEnchantLimitsConfig) {
|
||||
CustomAnvil.log("limitEnchantConfig: $limitEnchantConfig")
|
||||
}
|
||||
if (!isDefaultEnchantValuesConfig) {
|
||||
CustomAnvil.log("enchantValueConfig: $enchantValueConfig")
|
||||
}
|
||||
if (!isDefaultEnchantConflictConfig) {
|
||||
CustomAnvil.log("enchantConflictConfig: $enchantConflictConfig")
|
||||
}
|
||||
if (!isDefaultItemGroupsConfig) {
|
||||
CustomAnvil.log("itemGroupConfig: $itemGroupConfig")
|
||||
}
|
||||
if (!isDefaultUnitRepairItemConfig) {
|
||||
CustomAnvil.log("unitRepairConfig: $unitRepairConfig")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun notifyChange(holder: ConfigHolder, path: String){
|
||||
if(ConfigHolder.DEFAULT_CONFIG.equals(holder)){
|
||||
if(path.startsWith(ConfigOptions.ENCHANT_LIMIT_ROOT+".")){
|
||||
isDefaultEnchantLimitsConfig = false;
|
||||
}else if(path.startsWith(ConfigOptions.ENCHANT_VALUES_ROOT+".")){
|
||||
isDefaultEnchantValuesConfig = false;
|
||||
}else{
|
||||
isDefaultBaseConfig = false;
|
||||
fun notifyChange(holder: ConfigHolder, path: String) {
|
||||
if (ConfigHolder.DEFAULT_CONFIG.equals(holder)) {
|
||||
if (path.startsWith(ConfigOptions.ENCHANT_LIMIT_ROOT + ".")) {
|
||||
isDefaultEnchantLimitsConfig = false
|
||||
} else if (path.startsWith(ConfigOptions.ENCHANT_VALUES_ROOT + ".")) {
|
||||
isDefaultEnchantValuesConfig = false
|
||||
} else {
|
||||
isDefaultBaseConfig = false
|
||||
}
|
||||
}else if(ConfigHolder.CONFLICT_HOLDER.equals(holder)){
|
||||
isDefaultEnchantConflictConfig = false;
|
||||
}else if(ConfigHolder.ITEM_GROUP_HOLDER.equals(holder)){
|
||||
isDefaultItemGroupsConfig = false;
|
||||
}else if(ConfigHolder.UNIT_REPAIR_HOLDER.equals(holder)){
|
||||
isDefaultUnitRepairItemConfig = false;
|
||||
} else if (ConfigHolder.CONFLICT_HOLDER.equals(holder)) {
|
||||
isDefaultEnchantConflictConfig = false
|
||||
} else if (ConfigHolder.ITEM_GROUP_HOLDER.equals(holder)) {
|
||||
isDefaultItemGroupsConfig = false
|
||||
} else if (ConfigHolder.UNIT_REPAIR_HOLDER.equals(holder)) {
|
||||
isDefaultUnitRepairItemConfig = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ object UnitRepairUtil {
|
|||
|
||||
// Default value for user set default unit repair %
|
||||
private const val DEFAULT_DEFAULT_UNIT_REPAIR = 0.25
|
||||
|
||||
// Path to user default unit repair value
|
||||
private const val UNIT_REPAIR_DEFAULT_PATH = "default_repair_amount"
|
||||
|
||||
|
|
@ -18,23 +19,23 @@ object UnitRepairUtil {
|
|||
fun ItemStack.getRepair(
|
||||
other: ItemStack?
|
||||
): Double? {
|
||||
if(other == null) return null
|
||||
if (other == null) return null
|
||||
val config = ConfigHolder.UNIT_REPAIR_HOLDER.config
|
||||
// Get configuration section if exist
|
||||
val otherName = other.type.name.uppercase()
|
||||
var section = config.getConfigurationSection(otherName)
|
||||
if(section == null){
|
||||
if (section == null) {
|
||||
section = config.getConfigurationSection(otherName.lowercase())
|
||||
if(section == null) return null
|
||||
if (section == null) return null
|
||||
|
||||
}
|
||||
// Get repair amount
|
||||
var userDefault = config.getDouble(UNIT_REPAIR_DEFAULT_PATH, DEFAULT_DEFAULT_UNIT_REPAIR)
|
||||
if(userDefault <= 0){
|
||||
if (userDefault <= 0) {
|
||||
userDefault = DEFAULT_DEFAULT_UNIT_REPAIR
|
||||
}
|
||||
|
||||
return getRepairAmount(this,section,userDefault)
|
||||
return getRepairAmount(this, section, userDefault)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -42,16 +43,16 @@ object UnitRepairUtil {
|
|||
* null if not found.
|
||||
* If value is set to less than or equal to 0 then it will be set to default
|
||||
*/
|
||||
private fun getRepairAmount(item: ItemStack, section: ConfigurationSection, default: Double): Double?{
|
||||
private fun getRepairAmount(item: ItemStack, section: ConfigurationSection, default: Double): Double? {
|
||||
val itemName = item.type.name.uppercase()
|
||||
val repairValue = if(section.isDouble(itemName)){
|
||||
val repairValue = if (section.isDouble(itemName)) {
|
||||
section.getDouble(itemName)
|
||||
}else if(section.isDouble(itemName.lowercase())){
|
||||
} else if (section.isDouble(itemName.lowercase())) {
|
||||
section.getDouble(itemName.lowercase())
|
||||
}else{
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
if(repairValue <= 0)
|
||||
if (repairValue <= 0)
|
||||
return default
|
||||
return repairValue
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue