mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 16:16:17 +02:00
1.6.3 (#35)
- Support for [ExcellentEnchants](https://www.spigotmc.org/resources/excellentenchants-⭐-75-vanilla-like-enchantments.61693/) - Add enchantment merge level limit (& config gui for to configure it) - Use namespace for enchantment instead of name (still use name as backup) - Deprecated API method using enchantment name and replaced them with namespace methods - Improved main logic code readability (but may break thing) Multiplies changes (improved logic, namespace...) make this version likely to have something broken. Next version(s) may be fix
This commit is contained in:
commit
7266d4b0c4
52 changed files with 2048 additions and 1463 deletions
|
|
@ -14,7 +14,7 @@ plugins {
|
|||
}
|
||||
|
||||
group = "xyz.alexcrea"
|
||||
version = "1.6.2"
|
||||
version = "1.6.3"
|
||||
|
||||
repositories {
|
||||
// EcoEnchants
|
||||
|
|
@ -36,6 +36,10 @@ dependencies {
|
|||
compileOnly("com.willfp:EcoEnchants:12.5.1")
|
||||
compileOnly("com.willfp:eco:6.70.1")
|
||||
|
||||
// ExcellentEnchants
|
||||
compileOnly(files("libs/nightcore-2.6.4.jar"))
|
||||
compileOnly(files("libs/ExcellentEnchants-4.2.2.jar"))
|
||||
|
||||
// Disenchantment
|
||||
compileOnly("cz.kominekjan:Disenchantment:v5.4.0")
|
||||
|
||||
|
|
|
|||
|
|
@ -97,49 +97,46 @@ default_limit: 5
|
|||
#
|
||||
# Valid range of 1 - 255 for each enchantment
|
||||
enchant_limits:
|
||||
aqua_affinity: 1
|
||||
binding_curse: 1
|
||||
channeling: 1
|
||||
flame: 1
|
||||
infinity: 1
|
||||
mending: 1
|
||||
multishot: 1
|
||||
silk_touch: 1
|
||||
vanishing_curse: 1
|
||||
depth_strider: 3 # anything more than 3 is treated as 3 by the game
|
||||
protection: 4
|
||||
fire_protection: 4
|
||||
blast_protection: 4
|
||||
projectile_protection: 4
|
||||
feather_falling: 4
|
||||
thorns: 3
|
||||
respiration: 3
|
||||
sharpness: 5
|
||||
smite: 5
|
||||
bane_of_arthropods: 5
|
||||
knockback: 2
|
||||
fire_aspect: 2
|
||||
looting: 3
|
||||
sweeping: 3
|
||||
sweeping_edge: 3
|
||||
efficiency: 5
|
||||
unbreaking: 3
|
||||
fortune: 3
|
||||
power: 5
|
||||
punch: 2
|
||||
luck_of_the_sea: 3
|
||||
lure: 3
|
||||
frost_walker: 2
|
||||
impaling: 5
|
||||
riptide: 3
|
||||
loyalty: 3
|
||||
piercing: 4
|
||||
quick_charge: 3
|
||||
soul_speed: 3
|
||||
swift_sneak: 3
|
||||
density: 5
|
||||
breach: 4
|
||||
wind_burst: 3
|
||||
minecraft:aqua_affinity: 1
|
||||
minecraft:binding_curse: 1
|
||||
minecraft:channeling: 1
|
||||
minecraft:flame: 1
|
||||
minecraft:infinity: 1
|
||||
minecraft:mending: 1
|
||||
minecraft:multishot: 1
|
||||
minecraft:silk_touch: 1
|
||||
minecraft:vanishing_curse: 1
|
||||
minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game
|
||||
minecraft:protection: 4
|
||||
minecraft:fire_protection: 4
|
||||
minecraft:blast_protection: 4
|
||||
minecraft:projectile_protection: 4
|
||||
minecraft:feather_falling: 4
|
||||
minecraft:thorns: 3
|
||||
minecraft:respiration: 3
|
||||
minecraft:sharpness: 5
|
||||
minecraft:smite: 5
|
||||
minecraft:bane_of_arthropods: 5
|
||||
minecraft:knockback: 2
|
||||
minecraft:fire_aspect: 2
|
||||
minecraft:looting: 3
|
||||
minecraft:sweeping: 3
|
||||
minecraft:sweeping_edge: 3
|
||||
minecraft:efficiency: 5
|
||||
minecraft:unbreaking: 3
|
||||
minecraft:fortune: 3
|
||||
minecraft:power: 5
|
||||
minecraft:punch: 2
|
||||
minecraft:luck_of_the_sea: 3
|
||||
minecraft:lure: 3
|
||||
minecraft:frost_walker: 2
|
||||
minecraft:impaling: 5
|
||||
minecraft:riptide: 3
|
||||
minecraft:loyalty: 3
|
||||
minecraft:piercing: 4
|
||||
minecraft:quick_charge: 3
|
||||
minecraft:soul_speed: 3
|
||||
minecraft:swift_sneak: 3
|
||||
|
||||
# Multipliers used to calculate the enchantment's value in repair/combining
|
||||
#
|
||||
|
|
@ -153,135 +150,137 @@ enchant_limits:
|
|||
# With default values protection 4 would have a value of 4 when
|
||||
# coming from either a book (4 * 1) or an item (4 * 1)
|
||||
enchant_values:
|
||||
aqua_affinity:
|
||||
minecraft:aqua_affinity:
|
||||
item: 4
|
||||
book: 2
|
||||
bane_of_arthropods:
|
||||
minecraft:bane_of_arthropods:
|
||||
item: 2
|
||||
book: 1
|
||||
binding_curse:
|
||||
minecraft:binding_curse:
|
||||
item: 8
|
||||
book: 4
|
||||
blast_protection:
|
||||
minecraft:blast_protection:
|
||||
item: 4
|
||||
book: 2
|
||||
channeling:
|
||||
minecraft:channeling:
|
||||
item: 8
|
||||
book: 4
|
||||
depth_strider:
|
||||
minecraft:depth_strider:
|
||||
item: 4
|
||||
book: 2
|
||||
efficiency:
|
||||
minecraft:efficiency:
|
||||
item: 1
|
||||
book: 1
|
||||
flame:
|
||||
minecraft:flame:
|
||||
item: 4
|
||||
book: 2
|
||||
feather_falling:
|
||||
minecraft:feather_falling:
|
||||
item: 2
|
||||
book: 1
|
||||
fire_aspect:
|
||||
minecraft:fire_aspect:
|
||||
item: 4
|
||||
book: 2
|
||||
fire_protection:
|
||||
minecraft:fire_protection:
|
||||
item: 2
|
||||
book: 1
|
||||
fortune:
|
||||
minecraft:fortune:
|
||||
item: 4
|
||||
book: 2
|
||||
frost_walker:
|
||||
minecraft:frost_walker:
|
||||
item: 4
|
||||
book: 2
|
||||
impaling:
|
||||
minecraft:impaling:
|
||||
item: 4
|
||||
book: 2
|
||||
infinity:
|
||||
minecraft:infinity:
|
||||
item: 8
|
||||
book: 4
|
||||
knockback:
|
||||
minecraft:knockback:
|
||||
item: 2
|
||||
book: 1
|
||||
looting:
|
||||
minecraft:looting:
|
||||
item: 4
|
||||
book: 2
|
||||
loyalty:
|
||||
minecraft:loyalty:
|
||||
item: 1
|
||||
book: 1
|
||||
luck_of_the_sea:
|
||||
minecraft:luck_of_the_sea:
|
||||
item: 4
|
||||
book: 2
|
||||
lure:
|
||||
minecraft:lure:
|
||||
item: 4
|
||||
book: 2
|
||||
mending:
|
||||
minecraft:mending:
|
||||
item: 4
|
||||
book: 2
|
||||
multishot:
|
||||
minecraft:multishot:
|
||||
item: 4
|
||||
book: 2
|
||||
piercing:
|
||||
minecraft:piercing:
|
||||
item: 1
|
||||
book: 1
|
||||
power:
|
||||
minecraft:power:
|
||||
item: 1
|
||||
book: 1
|
||||
projectile_protection:
|
||||
minecraft:projectile_protection:
|
||||
item: 2
|
||||
book: 1
|
||||
protection:
|
||||
minecraft:protection:
|
||||
item: 1
|
||||
book: 1
|
||||
punch:
|
||||
minecraft:punch:
|
||||
item: 4
|
||||
book: 2
|
||||
quick_charge:
|
||||
minecraft:quick_charge:
|
||||
item: 2
|
||||
book: 1
|
||||
respiration:
|
||||
minecraft:respiration:
|
||||
item: 4
|
||||
book: 2
|
||||
riptide:
|
||||
minecraft:riptide:
|
||||
item: 4
|
||||
book: 2
|
||||
silk_touch:
|
||||
minecraft:silk_touch:
|
||||
item: 8
|
||||
book: 4
|
||||
sharpness:
|
||||
minecraft:sharpness:
|
||||
item: 1
|
||||
book: 1
|
||||
smite:
|
||||
minecraft:smite:
|
||||
item: 2
|
||||
book: 1
|
||||
soul_speed:
|
||||
minecraft:soul_speed:
|
||||
item: 8
|
||||
book: 4
|
||||
swift_sneak:
|
||||
minecraft:swift_sneak:
|
||||
item: 8
|
||||
book: 4
|
||||
sweeping:
|
||||
minecraft:sweeping:
|
||||
item: 4
|
||||
book: 2
|
||||
sweeping_edge:
|
||||
minecraft:sweeping_edge:
|
||||
item: 4
|
||||
book: 2
|
||||
thorns:
|
||||
minecraft:thorns:
|
||||
item: 8
|
||||
book: 4
|
||||
unbreaking:
|
||||
minecraft:unbreaking:
|
||||
item: 2
|
||||
book: 1
|
||||
vanishing_curse:
|
||||
minecraft:vanishing_curse:
|
||||
item: 8
|
||||
book: 4
|
||||
density:
|
||||
item: 1
|
||||
book: 1
|
||||
breach:
|
||||
item: 4
|
||||
book: 2
|
||||
wind_burst:
|
||||
item: 4
|
||||
book: 2
|
||||
|
||||
# Disable enchantment merging for level above the set value
|
||||
# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III
|
||||
# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword
|
||||
# Even if disable-merge-over of unbreaking is set to 2
|
||||
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
|
||||
disable-merge-over:
|
||||
# Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla)
|
||||
minecraft:sharpness: -1
|
||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||
#minecraft:unbreaking: 2
|
||||
|
||||
# Whether to show debug logging
|
||||
debug_log: false
|
||||
|
|
@ -296,4 +295,3 @@ debug_log_verbose: false
|
|||
force_protocolib: false
|
||||
|
||||
configVersion: 1.6.2
|
||||
lowMinecraftVersion: '1.21'
|
||||
|
|
|
|||
|
|
@ -17,158 +17,158 @@
|
|||
# ----------------------------------------------------
|
||||
|
||||
restriction_aqua_affinity:
|
||||
enchantments: [ aqua_affinity ]
|
||||
enchantments: [ minecraft:aqua_affinity ]
|
||||
notAffectedGroups: [ enchanted_book, helmets ]
|
||||
|
||||
restriction_bane_of_arthropods:
|
||||
enchantments: [ bane_of_arthropods ]
|
||||
enchantments: [ minecraft:bane_of_arthropods ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_blast_protection:
|
||||
enchantments: [ blast_protection ]
|
||||
enchantments: [ minecraft:blast_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_channeling:
|
||||
enchantments: [ channeling ]
|
||||
enchantments: [ minecraft:channeling ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_binding_curse:
|
||||
enchantments: [ binding_curse ]
|
||||
enchantments: [ minecraft:binding_curse ]
|
||||
notAffectedGroups: [ enchanted_book, wearable ]
|
||||
|
||||
restriction_vanishing_curse:
|
||||
enchantments: [ vanishing_curse ]
|
||||
enchantments: [ minecraft:vanishing_curse ]
|
||||
notAffectedGroups: [ enchanted_book, can_vanish ]
|
||||
|
||||
restriction_depth_strider:
|
||||
enchantments: [ depth_strider ]
|
||||
enchantments: [ minecraft:depth_strider ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_efficiency:
|
||||
enchantments: [ efficiency ]
|
||||
enchantments: [ minecraft:efficiency ]
|
||||
notAffectedGroups: [ enchanted_book, tools, shears ]
|
||||
|
||||
restriction_feather_falling:
|
||||
enchantments: [ feather_falling ]
|
||||
enchantments: [ minecraft:feather_falling ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_fire_aspect:
|
||||
enchantments: [ fire_aspect ]
|
||||
enchantments: [ minecraft:fire_aspect ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_fire_protection:
|
||||
enchantments: [ fire_protection ]
|
||||
enchantments: [ minecraft:fire_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_flame:
|
||||
enchantments: [ flame ]
|
||||
enchantments: [ minecraft:flame ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_fortune:
|
||||
enchantments: [ fortune ]
|
||||
enchantments: [ minecraft:fortune ]
|
||||
notAffectedGroups: [ enchanted_book, tools ]
|
||||
|
||||
restriction_frost_walker:
|
||||
enchantments: [ frost_walker ]
|
||||
enchantments: [ minecraft:frost_walker ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_impaling:
|
||||
enchantments: [ impaling ]
|
||||
enchantments: [ minecraft:impaling ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_infinity:
|
||||
enchantments: [ infinity ]
|
||||
enchantments: [ minecraft:infinity ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_knockback:
|
||||
enchantments: [ knockback ]
|
||||
enchantments: [ minecraft:knockback ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_looting:
|
||||
enchantments: [ looting ]
|
||||
enchantments: [ minecraft:looting ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_loyalty:
|
||||
enchantments: [ loyalty ]
|
||||
enchantments: [ minecraft:loyalty ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_lure:
|
||||
enchantments: [ lure ]
|
||||
enchantments: [ minecraft:lure ]
|
||||
notAffectedGroups: [ enchanted_book, fishing_rod ]
|
||||
|
||||
restriction_mending:
|
||||
enchantments: [ mending ]
|
||||
enchantments: [ minecraft:mending ]
|
||||
notAffectedGroups: [ enchanted_book, can_unbreak ]
|
||||
|
||||
restriction_multishot:
|
||||
enchantments: [ multishot ]
|
||||
restriction_minecraft_multishot:
|
||||
enchantments: [ minecraft:multishot ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_piercing:
|
||||
enchantments: [ piercing ]
|
||||
enchantments: [ minecraft:piercing ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_power:
|
||||
enchantments: [ power ]
|
||||
enchantments: [ minecraft:power ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_projectile_protection:
|
||||
enchantments: [ projectile_protection ]
|
||||
enchantments: [ minecraft:projectile_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_protection:
|
||||
enchantments: [ protection ]
|
||||
enchantments: [ minecraft:protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_punch:
|
||||
enchantments: [ punch ]
|
||||
enchantments: [ minecraft:punch ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_quick_charge:
|
||||
enchantments: [ quick_charge ]
|
||||
enchantments: [ minecraft:quick_charge ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_respiration:
|
||||
enchantments: [ respiration ]
|
||||
enchantments: [ minecraft:respiration ]
|
||||
notAffectedGroups: [ enchanted_book, helmets ]
|
||||
|
||||
restriction_riptide:
|
||||
enchantments: [ riptide ]
|
||||
enchantments: [ minecraft:riptide ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_sharpness:
|
||||
enchantments: [ sharpness ]
|
||||
enchantments: [ minecraft:sharpness ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_silk_touch:
|
||||
enchantments: [ silk_touch ]
|
||||
restriction__silk_touch:
|
||||
enchantments: [ minecraft:silk_touch ]
|
||||
notAffectedGroups: [ enchanted_book, tools ]
|
||||
|
||||
restriction_smite:
|
||||
enchantments: [ smite ]
|
||||
enchantments: [ minecraft:smite ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_soul_speed:
|
||||
enchantments: [ soul_speed ]
|
||||
enchantments: [ minecraft:soul_speed ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_sweeping_edge:
|
||||
enchantments: [ sweeping, sweeping_edge ]
|
||||
enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
# Do not exist in 1.18, that mean useInFuture will be set to true
|
||||
# useInFuture set to true also mean it will not warn if there is an issue
|
||||
restriction_swift_sneak:
|
||||
useInFuture: true
|
||||
enchantments: [ swift_sneak ]
|
||||
enchantments: [ minecraft:swift_sneak ]
|
||||
notAffectedGroups: [ enchanted_book, leggings ]
|
||||
|
||||
restriction_thorns:
|
||||
enchantments: [ thorns ]
|
||||
enchantments: [ minecraft:thorns ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_unbreaking:
|
||||
enchantments: [ unbreaking ]
|
||||
restriction__unbreaking:
|
||||
enchantments: [ minecraft:unbreaking ]
|
||||
notAffectedGroups: [ enchanted_book, can_unbreak ]
|
||||
|
||||
# ----------------------------------------------------
|
||||
|
|
@ -180,60 +180,60 @@ restriction_unbreaking:
|
|||
|
||||
sword_enchant_conflict:
|
||||
enchantments:
|
||||
- bane_of_arthropods
|
||||
- smite
|
||||
- sharpness
|
||||
- minecraft:bane_of_arthropods
|
||||
- minecraft:smite
|
||||
- minecraft:sharpness
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
protection_enchant_conflict:
|
||||
enchantments:
|
||||
- blast_protection
|
||||
- fire_protection
|
||||
- projectile_protection
|
||||
- protection
|
||||
- minecraft:blast_protection
|
||||
- minecraft:fire_protection
|
||||
- minecraft:projectile_protection
|
||||
- minecraft:protection
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
trident_conflict1:
|
||||
enchantments:
|
||||
- channeling
|
||||
- riptide
|
||||
- minecraft:channeling
|
||||
- minecraft:riptide
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
trident_conflict2:
|
||||
enchantments:
|
||||
- loyalty
|
||||
- riptide
|
||||
- minecraft:loyalty
|
||||
- minecraft:riptide
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
boot_conflict:
|
||||
enchantments:
|
||||
- depth_strider
|
||||
- frost_walker
|
||||
- minecraft:depth_strider
|
||||
- minecraft:frost_walker
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
tool_conflict:
|
||||
enchantments:
|
||||
- fortune
|
||||
- silk_touch
|
||||
- minecraft:fortune
|
||||
- minecraft:silk_touch
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
bow_conflict:
|
||||
enchantments:
|
||||
- mending
|
||||
- infinity
|
||||
- minecraft:mending
|
||||
- minecraft:infinity
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
crossbow_conflict:
|
||||
enchantments:
|
||||
- multishot
|
||||
- piercing
|
||||
- minecraft:multishot
|
||||
- minecraft:piercing
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
|
|
|
|||
|
|
@ -97,49 +97,46 @@ default_limit: 5
|
|||
#
|
||||
# Valid range of 1 - 255 for each enchantment
|
||||
enchant_limits:
|
||||
aqua_affinity: 1
|
||||
binding_curse: 1
|
||||
channeling: 1
|
||||
flame: 1
|
||||
infinity: 1
|
||||
mending: 1
|
||||
multishot: 1
|
||||
silk_touch: 1
|
||||
vanishing_curse: 1
|
||||
depth_strider: 3 # anything more than 3 is treated as 3 by the game
|
||||
protection: 4
|
||||
fire_protection: 4
|
||||
blast_protection: 4
|
||||
projectile_protection: 4
|
||||
feather_falling: 4
|
||||
thorns: 3
|
||||
respiration: 3
|
||||
sharpness: 5
|
||||
smite: 5
|
||||
bane_of_arthropods: 5
|
||||
knockback: 2
|
||||
fire_aspect: 2
|
||||
looting: 3
|
||||
sweeping: 3
|
||||
sweeping_edge: 3
|
||||
efficiency: 5
|
||||
unbreaking: 3
|
||||
fortune: 3
|
||||
power: 5
|
||||
punch: 2
|
||||
luck_of_the_sea: 3
|
||||
lure: 3
|
||||
frost_walker: 2
|
||||
impaling: 5
|
||||
riptide: 3
|
||||
loyalty: 3
|
||||
piercing: 4
|
||||
quick_charge: 3
|
||||
soul_speed: 3
|
||||
swift_sneak: 3
|
||||
density: 5
|
||||
breach: 4
|
||||
wind_burst: 3
|
||||
minecraft:aqua_affinity: 1
|
||||
minecraft:binding_curse: 1
|
||||
minecraft:channeling: 1
|
||||
minecraft:flame: 1
|
||||
minecraft:infinity: 1
|
||||
minecraft:mending: 1
|
||||
minecraft:multishot: 1
|
||||
minecraft:silk_touch: 1
|
||||
minecraft:vanishing_curse: 1
|
||||
minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game
|
||||
minecraft:protection: 4
|
||||
minecraft:fire_protection: 4
|
||||
minecraft:blast_protection: 4
|
||||
minecraft:projectile_protection: 4
|
||||
minecraft:feather_falling: 4
|
||||
minecraft:thorns: 3
|
||||
minecraft:respiration: 3
|
||||
minecraft:sharpness: 5
|
||||
minecraft:smite: 5
|
||||
minecraft:bane_of_arthropods: 5
|
||||
minecraft:knockback: 2
|
||||
minecraft:fire_aspect: 2
|
||||
minecraft:looting: 3
|
||||
minecraft:sweeping: 3
|
||||
minecraft:sweeping_edge: 3
|
||||
minecraft:efficiency: 5
|
||||
minecraft:unbreaking: 3
|
||||
minecraft:fortune: 3
|
||||
minecraft:power: 5
|
||||
minecraft:punch: 2
|
||||
minecraft:luck_of_the_sea: 3
|
||||
minecraft:lure: 3
|
||||
minecraft:frost_walker: 2
|
||||
minecraft:impaling: 5
|
||||
minecraft:riptide: 3
|
||||
minecraft:loyalty: 3
|
||||
minecraft:piercing: 4
|
||||
minecraft:quick_charge: 3
|
||||
minecraft:soul_speed: 3
|
||||
minecraft:swift_sneak: 3
|
||||
|
||||
# Multipliers used to calculate the enchantment's value in repair/combining
|
||||
#
|
||||
|
|
@ -153,135 +150,137 @@ enchant_limits:
|
|||
# With default values protection 4 would have a value of 4 when
|
||||
# coming from either a book (4 * 1) or an item (4 * 1)
|
||||
enchant_values:
|
||||
aqua_affinity:
|
||||
minecraft:aqua_affinity:
|
||||
item: 4
|
||||
book: 2
|
||||
bane_of_arthropods:
|
||||
minecraft:bane_of_arthropods:
|
||||
item: 2
|
||||
book: 1
|
||||
binding_curse:
|
||||
minecraft:binding_curse:
|
||||
item: 8
|
||||
book: 4
|
||||
blast_protection:
|
||||
minecraft:blast_protection:
|
||||
item: 4
|
||||
book: 2
|
||||
channeling:
|
||||
minecraft:channeling:
|
||||
item: 8
|
||||
book: 4
|
||||
depth_strider:
|
||||
minecraft:depth_strider:
|
||||
item: 4
|
||||
book: 2
|
||||
efficiency:
|
||||
minecraft:efficiency:
|
||||
item: 1
|
||||
book: 1
|
||||
flame:
|
||||
minecraft:flame:
|
||||
item: 4
|
||||
book: 2
|
||||
feather_falling:
|
||||
minecraft:feather_falling:
|
||||
item: 2
|
||||
book: 1
|
||||
fire_aspect:
|
||||
minecraft:fire_aspect:
|
||||
item: 4
|
||||
book: 2
|
||||
fire_protection:
|
||||
minecraft:fire_protection:
|
||||
item: 2
|
||||
book: 1
|
||||
fortune:
|
||||
minecraft:fortune:
|
||||
item: 4
|
||||
book: 2
|
||||
frost_walker:
|
||||
minecraft:frost_walker:
|
||||
item: 4
|
||||
book: 2
|
||||
impaling:
|
||||
minecraft:impaling:
|
||||
item: 4
|
||||
book: 2
|
||||
infinity:
|
||||
minecraft:infinity:
|
||||
item: 8
|
||||
book: 4
|
||||
knockback:
|
||||
minecraft:knockback:
|
||||
item: 2
|
||||
book: 1
|
||||
looting:
|
||||
minecraft:looting:
|
||||
item: 4
|
||||
book: 2
|
||||
loyalty:
|
||||
minecraft:loyalty:
|
||||
item: 1
|
||||
book: 1
|
||||
luck_of_the_sea:
|
||||
minecraft:luck_of_the_sea:
|
||||
item: 4
|
||||
book: 2
|
||||
lure:
|
||||
minecraft:lure:
|
||||
item: 4
|
||||
book: 2
|
||||
mending:
|
||||
minecraft:mending:
|
||||
item: 4
|
||||
book: 2
|
||||
multishot:
|
||||
minecraft:multishot:
|
||||
item: 4
|
||||
book: 2
|
||||
piercing:
|
||||
minecraft:piercing:
|
||||
item: 1
|
||||
book: 1
|
||||
power:
|
||||
minecraft:power:
|
||||
item: 1
|
||||
book: 1
|
||||
projectile_protection:
|
||||
minecraft:projectile_protection:
|
||||
item: 2
|
||||
book: 1
|
||||
protection:
|
||||
minecraft:protection:
|
||||
item: 1
|
||||
book: 1
|
||||
punch:
|
||||
minecraft:punch:
|
||||
item: 4
|
||||
book: 2
|
||||
quick_charge:
|
||||
minecraft:quick_charge:
|
||||
item: 2
|
||||
book: 1
|
||||
respiration:
|
||||
minecraft:respiration:
|
||||
item: 4
|
||||
book: 2
|
||||
riptide:
|
||||
minecraft:riptide:
|
||||
item: 4
|
||||
book: 2
|
||||
silk_touch:
|
||||
minecraft:silk_touch:
|
||||
item: 8
|
||||
book: 4
|
||||
sharpness:
|
||||
minecraft:sharpness:
|
||||
item: 1
|
||||
book: 1
|
||||
smite:
|
||||
minecraft:smite:
|
||||
item: 2
|
||||
book: 1
|
||||
soul_speed:
|
||||
minecraft:soul_speed:
|
||||
item: 8
|
||||
book: 4
|
||||
swift_sneak:
|
||||
minecraft:swift_sneak:
|
||||
item: 8
|
||||
book: 4
|
||||
sweeping:
|
||||
minecraft:sweeping:
|
||||
item: 4
|
||||
book: 2
|
||||
sweeping_edge:
|
||||
minecraft:sweeping_edge:
|
||||
item: 4
|
||||
book: 2
|
||||
thorns:
|
||||
minecraft:thorns:
|
||||
item: 8
|
||||
book: 4
|
||||
unbreaking:
|
||||
minecraft:unbreaking:
|
||||
item: 2
|
||||
book: 1
|
||||
vanishing_curse:
|
||||
minecraft:vanishing_curse:
|
||||
item: 8
|
||||
book: 4
|
||||
density:
|
||||
item: 1
|
||||
book: 1
|
||||
breach:
|
||||
item: 4
|
||||
book: 2
|
||||
wind_burst:
|
||||
item: 4
|
||||
book: 2
|
||||
|
||||
# Disable enchantment merging for level above the set value
|
||||
# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III
|
||||
# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword
|
||||
# Even if disable-merge-over of unbreaking is set to 2
|
||||
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
|
||||
disable-merge-over:
|
||||
# Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla)
|
||||
minecraft:sharpness: -1
|
||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||
#minecraft:unbreaking: 2
|
||||
|
||||
# Whether to show debug logging
|
||||
debug_log: false
|
||||
|
|
@ -296,4 +295,3 @@ debug_log_verbose: false
|
|||
force_protocolib: false
|
||||
|
||||
configVersion: 1.6.2
|
||||
lowMinecraftVersion: '1.21'
|
||||
|
|
|
|||
|
|
@ -17,278 +17,159 @@
|
|||
# ----------------------------------------------------
|
||||
|
||||
restriction_aqua_affinity:
|
||||
enchantments:
|
||||
- aqua_affinity
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- helmets
|
||||
enchantments: [ minecraft:aqua_affinity ]
|
||||
notAffectedGroups: [ enchanted_book, helmets ]
|
||||
|
||||
restriction_bane_of_arthropods:
|
||||
enchantments:
|
||||
- bane_of_arthropods
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- melee_weapons
|
||||
- mace
|
||||
enchantments: [ minecraft:bane_of_arthropods ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_blast_protection:
|
||||
enchantments:
|
||||
- blast_protection
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- armors
|
||||
enchantments: [ minecraft:blast_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_channeling:
|
||||
enchantments:
|
||||
- channeling
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- trident
|
||||
enchantments: [ minecraft:channeling ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_binding_curse:
|
||||
enchantments:
|
||||
- binding_curse
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- wearable
|
||||
enchantments: [ minecraft:binding_curse ]
|
||||
notAffectedGroups: [ enchanted_book, wearable ]
|
||||
|
||||
restriction_vanishing_curse:
|
||||
enchantments:
|
||||
- vanishing_curse
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- can_vanish
|
||||
enchantments: [ minecraft:vanishing_curse ]
|
||||
notAffectedGroups: [ enchanted_book, can_vanish ]
|
||||
|
||||
restriction_depth_strider:
|
||||
enchantments:
|
||||
- depth_strider
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- boots
|
||||
enchantments: [ minecraft:depth_strider ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_efficiency:
|
||||
enchantments:
|
||||
- efficiency
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- tools
|
||||
- shears
|
||||
enchantments: [ minecraft:efficiency ]
|
||||
notAffectedGroups: [ enchanted_book, tools, shears ]
|
||||
|
||||
restriction_feather_falling:
|
||||
enchantments:
|
||||
- feather_falling
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- boots
|
||||
enchantments: [ minecraft:feather_falling ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_fire_aspect:
|
||||
enchantments:
|
||||
- fire_aspect
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- swords
|
||||
- mace
|
||||
enchantments: [ minecraft:fire_aspect ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_fire_protection:
|
||||
enchantments:
|
||||
- fire_protection
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- armors
|
||||
enchantments: [ minecraft:fire_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_flame:
|
||||
enchantments:
|
||||
- flame
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- bow
|
||||
enchantments: [ minecraft:flame ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_fortune:
|
||||
enchantments:
|
||||
- fortune
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- tools
|
||||
enchantments: [ minecraft:fortune ]
|
||||
notAffectedGroups: [ enchanted_book, tools ]
|
||||
|
||||
restriction_frost_walker:
|
||||
enchantments:
|
||||
- frost_walker
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- boots
|
||||
enchantments: [ minecraft:frost_walker ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_impaling:
|
||||
enchantments:
|
||||
- impaling
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- trident
|
||||
enchantments: [ minecraft:impaling ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_infinity:
|
||||
enchantments:
|
||||
- infinity
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- bow
|
||||
enchantments: [ minecraft:infinity ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_knockback:
|
||||
enchantments:
|
||||
- knockback
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- swords
|
||||
enchantments: [ minecraft:knockback ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_looting:
|
||||
enchantments:
|
||||
- looting
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- swords
|
||||
enchantments: [ minecraft:looting ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_loyalty:
|
||||
enchantments:
|
||||
- loyalty
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- trident
|
||||
enchantments: [ minecraft:loyalty ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_lure:
|
||||
enchantments:
|
||||
- lure
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- fishing_rod
|
||||
enchantments: [ minecraft:lure ]
|
||||
notAffectedGroups: [ enchanted_book, fishing_rod ]
|
||||
|
||||
restriction_mending:
|
||||
enchantments:
|
||||
- mending
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- can_unbreak
|
||||
enchantments: [ minecraft:mending ]
|
||||
notAffectedGroups: [ enchanted_book, can_unbreak ]
|
||||
|
||||
restriction_multishot:
|
||||
enchantments:
|
||||
- multishot
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- crossbow
|
||||
restriction_minecraft_multishot:
|
||||
enchantments: [ minecraft:multishot ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_piercing:
|
||||
enchantments:
|
||||
- piercing
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- crossbow
|
||||
enchantments: [ minecraft:piercing ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_power:
|
||||
enchantments:
|
||||
- power
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- bow
|
||||
enchantments: [ minecraft:power ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_projectile_protection:
|
||||
enchantments:
|
||||
- projectile_protection
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- armors
|
||||
enchantments: [ minecraft:projectile_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_protection:
|
||||
enchantments:
|
||||
- protection
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- armors
|
||||
enchantments: [ minecraft:protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_punch:
|
||||
enchantments:
|
||||
- punch
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- bow
|
||||
enchantments: [ minecraft:punch ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_quick_charge:
|
||||
enchantments:
|
||||
- quick_charge
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- crossbow
|
||||
enchantments: [ minecraft:quick_charge ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_respiration:
|
||||
enchantments:
|
||||
- respiration
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- helmets
|
||||
enchantments: [ minecraft:respiration ]
|
||||
notAffectedGroups: [ enchanted_book, helmets ]
|
||||
|
||||
restriction_riptide:
|
||||
enchantments:
|
||||
- riptide
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- trident
|
||||
enchantments: [ minecraft:riptide ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_sharpness:
|
||||
enchantments:
|
||||
- sharpness
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- melee_weapons
|
||||
enchantments: [ minecraft:sharpness ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_silk_touch:
|
||||
enchantments:
|
||||
- silk_touch
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- tools
|
||||
restriction__silk_touch:
|
||||
enchantments: [ minecraft:silk_touch ]
|
||||
notAffectedGroups: [ enchanted_book, tools ]
|
||||
|
||||
restriction_smite:
|
||||
enchantments:
|
||||
- smite
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- melee_weapons
|
||||
- mace
|
||||
enchantments: [ minecraft:smite ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_soul_speed:
|
||||
enchantments:
|
||||
- soul_speed
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- boots
|
||||
enchantments: [ minecraft:soul_speed ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_sweeping_edge:
|
||||
enchantments:
|
||||
- sweeping
|
||||
- sweeping_edge
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- swords
|
||||
enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
# Do not exist in 1.18, that mean useInFuture will be set to true
|
||||
# useInFuture set to true also mean it will not warn if there is an issue
|
||||
restriction_swift_sneak:
|
||||
useInFuture: true
|
||||
enchantments:
|
||||
- swift_sneak
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- leggings
|
||||
enchantments: [ minecraft:swift_sneak ]
|
||||
notAffectedGroups: [ enchanted_book, leggings ]
|
||||
|
||||
restriction_thorns:
|
||||
enchantments:
|
||||
- thorns
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- armors
|
||||
enchantments: [ minecraft:thorns ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_unbreaking:
|
||||
enchantments:
|
||||
- unbreaking
|
||||
notAffectedGroups:
|
||||
- enchanted_book
|
||||
- can_unbreak
|
||||
restriction__unbreaking:
|
||||
enchantments: [ minecraft:unbreaking ]
|
||||
notAffectedGroups: [ enchanted_book, can_unbreak ]
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Now we have conflicts about enchantment Incompatibility
|
||||
|
|
@ -299,87 +180,62 @@ restriction_unbreaking:
|
|||
|
||||
sword_enchant_conflict:
|
||||
enchantments:
|
||||
- bane_of_arthropods
|
||||
- smite
|
||||
- sharpness
|
||||
- minecraft:bane_of_arthropods
|
||||
- minecraft:smite
|
||||
- minecraft:sharpness
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
protection_enchant_conflict:
|
||||
enchantments:
|
||||
- blast_protection
|
||||
- fire_protection
|
||||
- projectile_protection
|
||||
- protection
|
||||
- minecraft:blast_protection
|
||||
- minecraft:fire_protection
|
||||
- minecraft:projectile_protection
|
||||
- minecraft:protection
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
trident_conflict1:
|
||||
enchantments:
|
||||
- channeling
|
||||
- riptide
|
||||
- minecraft:channeling
|
||||
- minecraft:riptide
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
trident_conflict2:
|
||||
enchantments:
|
||||
- loyalty
|
||||
- riptide
|
||||
- minecraft:loyalty
|
||||
- minecraft:riptide
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
boot_conflict:
|
||||
enchantments:
|
||||
- depth_strider
|
||||
- frost_walker
|
||||
- minecraft:depth_strider
|
||||
- minecraft:frost_walker
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
tool_conflict:
|
||||
enchantments:
|
||||
- fortune
|
||||
- silk_touch
|
||||
- minecraft:fortune
|
||||
- minecraft:silk_touch
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
bow_conflict:
|
||||
enchantments:
|
||||
- mending
|
||||
- infinity
|
||||
- minecraft:mending
|
||||
- minecraft:infinity
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
crossbow_conflict:
|
||||
enchantments:
|
||||
- multishot
|
||||
- piercing
|
||||
- minecraft:multishot
|
||||
- minecraft:piercing
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
restriction_density:
|
||||
enchantments:
|
||||
- density
|
||||
notAffectedGroups:
|
||||
- mace
|
||||
- enchanted_book
|
||||
restriction_breach:
|
||||
enchantments:
|
||||
- breach
|
||||
notAffectedGroups:
|
||||
- mace
|
||||
- enchanted_book
|
||||
restriction_wind_burst:
|
||||
enchantments:
|
||||
- wind_burst
|
||||
notAffectedGroups:
|
||||
- mace
|
||||
- enchanted_book
|
||||
mace_enchant_conflict:
|
||||
enchantments:
|
||||
- density
|
||||
- breach
|
||||
- smite
|
||||
- bane_of_arthropods
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Bellow is for custom conflicts.
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ wearable:
|
|||
- player_head
|
||||
- creeper_head
|
||||
- dragon_head
|
||||
# do not exist in 1.18 but exist in future update
|
||||
- piglin_head
|
||||
groups:
|
||||
- armors
|
||||
|
|
@ -187,6 +188,7 @@ can_unbreak:
|
|||
- shield
|
||||
- carrot_on_a_stick
|
||||
- warped_fungus_on_a_stick
|
||||
# do not exist in 1.18 but exist in future update
|
||||
- brush
|
||||
groups:
|
||||
- melee_weapons
|
||||
|
|
@ -197,7 +199,6 @@ can_unbreak:
|
|||
- crossbow
|
||||
- fishing_rod
|
||||
- shears
|
||||
- mace
|
||||
|
||||
can_vanish:
|
||||
type: include
|
||||
|
|
@ -206,8 +207,4 @@ can_vanish:
|
|||
groups:
|
||||
- wearable
|
||||
- can_unbreak
|
||||
mace:
|
||||
type: include
|
||||
items:
|
||||
- mace
|
||||
|
||||
|
|
|
|||
|
|
@ -188,5 +188,3 @@ warped_planks:
|
|||
wooden_shovel: 0.25
|
||||
wooden_hoe: 0.25
|
||||
shield: 0.25
|
||||
breeze_rod:
|
||||
mace: 0.25
|
||||
|
|
|
|||
BIN
libs/ExcellentEnchants-4.2.2.jar
Normal file
BIN
libs/ExcellentEnchants-4.2.2.jar
Normal file
Binary file not shown.
BIN
libs/nightcore-2.6.4.jar
Normal file
BIN
libs/nightcore-2.6.4.jar
Normal file
Binary file not shown.
|
|
@ -0,0 +1,24 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui
|
||||
|
||||
import org.bukkit.inventory.InventoryView
|
||||
|
||||
interface ExternGuiTester {
|
||||
|
||||
val wesjdAnvilGuiName: String?
|
||||
|
||||
fun getContainerClass(inventory: InventoryView): Class<Any>?
|
||||
|
||||
fun testIfGui(inventory: InventoryView): Boolean {
|
||||
val clazz = getContainerClass(inventory)
|
||||
if(clazz == null) return false
|
||||
|
||||
val expectedWesjdGuiPath = "anvilgui.version.$wesjdAnvilGuiName"
|
||||
|
||||
val clazzName = clazz.name
|
||||
val isWejdsGui = clazzName.contains(expectedWesjdGuiPath)
|
||||
|
||||
return isWejdsGui
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
|
||||
class v1_17R1_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_17_R1"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
|
||||
class v1_18R1_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_18_R1"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
|
||||
class v1_18R2_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_18_R2"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
|
||||
class v1_19R1_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_19_R1"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
|
||||
class v1_19R2_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_19_R2"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
|
||||
class v1_19R3_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_19_R3"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
|
||||
class v1_20R1_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_20_R1"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
import kotlin.jvm.javaClass
|
||||
|
||||
class v1_20R2_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_20_R2"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
import kotlin.jvm.javaClass
|
||||
|
||||
class v1_20R3_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_20_R3"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
import kotlin.jvm.javaClass
|
||||
|
||||
class v1_20R4_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_20_R4"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if (view !is CraftInventoryView) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui.version
|
||||
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryView
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
|
||||
class v1_21R1_ExternGuiTester: ExternGuiTester {
|
||||
override val wesjdAnvilGuiName = "Wrapper1_21_R1"
|
||||
|
||||
override fun getContainerClass(view: InventoryView): Class<Any>? {
|
||||
if(view !is CraftInventoryView<*>) return null
|
||||
val container = view.handle
|
||||
|
||||
return container.javaClass
|
||||
}
|
||||
}
|
||||
|
|
@ -119,7 +119,7 @@ public class ConflictAPI {
|
|||
private static List<String> extractEnchantments(@NotNull ConflictBuilder builder){
|
||||
List<String> result = new ArrayList<>(builder.getEnchantmentNames());
|
||||
for (NamespacedKey enchantmentKey : builder.getEnchantmentKeys()) {
|
||||
result.add(enchantmentKey.getKey());
|
||||
result.add(enchantmentKey.toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
|||
import xyz.alexcrea.cuanvil.group.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
|
@ -372,7 +373,7 @@ public class ConflictBuilder {
|
|||
*/
|
||||
protected void appendEnchantments(@NotNull EnchantConflictGroup conflict){
|
||||
for (String enchantmentName : getEnchantmentNames()){
|
||||
if(appendEnchantment(conflict, EnchantmentApi.getByName(enchantmentName))){
|
||||
if(appendEnchantments(conflict, EnchantmentApi.getListByName(enchantmentName)) == 0){
|
||||
CustomAnvil.instance.getLogger().warning("Could not find enchantment " + enchantmentName + " for conflict " + getName());
|
||||
ConflictAPI.logConflictOrigin(this);
|
||||
}
|
||||
|
|
@ -399,6 +400,24 @@ public class ConflictBuilder {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a list of enchantments.
|
||||
*
|
||||
* @param conflict The conflict target
|
||||
* @param enchantments List of enchantment to add
|
||||
* @return Number of enchantment added
|
||||
*/
|
||||
protected static int appendEnchantments(@NotNull EnchantConflictGroup conflict, @NotNull List<CAEnchantment> enchantments){
|
||||
int numberValid = 0;
|
||||
for (CAEnchantment enchantment : enchantments) {
|
||||
if(appendEnchantment(conflict, enchantment)){
|
||||
numberValid++;
|
||||
}
|
||||
}
|
||||
|
||||
return numberValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract group abstract material group.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import xyz.alexcrea.cuanvil.gui.config.global.EnchantCostConfigGui;
|
|||
import xyz.alexcrea.cuanvil.gui.config.global.EnchantLimitConfigGui;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
|
@ -104,7 +105,7 @@ public class EnchantmentApi {
|
|||
* @return True if successful.
|
||||
*/
|
||||
public static boolean unregisterEnchantment(@NotNull NamespacedKey key){
|
||||
CAEnchantment enchantment = CAEnchantmentRegistry.getInstance().getByKey(key);
|
||||
CAEnchantment enchantment = CAEnchantment.getByKey(key);
|
||||
return unregisterEnchantment(enchantment);
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +127,7 @@ public class EnchantmentApi {
|
|||
*/
|
||||
@Nullable
|
||||
public static CAEnchantment getByKey(@NotNull NamespacedKey key){
|
||||
return CAEnchantmentRegistry.getInstance().getByKey(key);
|
||||
return CAEnchantment.getByKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -134,10 +135,22 @@ public class EnchantmentApi {
|
|||
*
|
||||
* @param name The name used to fetch
|
||||
* @return The custom anvil enchantment of this name. null if not found.
|
||||
* @deprecated use {@link #getListByName(String)}
|
||||
*/
|
||||
@Deprecated(since = "1.6.3")
|
||||
@Nullable
|
||||
public static CAEnchantment getByName(@NotNull String name){
|
||||
return CAEnchantmentRegistry.getInstance().getByName(name);
|
||||
return CAEnchantment.getByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of enchantment using the provided name.
|
||||
*
|
||||
* @param name The name used to fetch
|
||||
* @return List of custom anvil enchantments of this name. May be empty if not found.
|
||||
*/
|
||||
public static List<CAEnchantment> getListByName(@NotNull String name){
|
||||
return CAEnchantment.getListByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -167,9 +180,9 @@ public class EnchantmentApi {
|
|||
|
||||
|
||||
private static void writeDefaultConfig(FileConfiguration defaultConfig, CAEnchantment enchantment) {
|
||||
defaultConfig.set("enchant_limits." + enchantment.getKey().getKey(), enchantment.defaultMaxLevel());
|
||||
defaultConfig.set("enchant_limits." + enchantment.getKey(), enchantment.defaultMaxLevel());
|
||||
|
||||
String basePath = "enchant_values." + enchantment.getKey().getKey();
|
||||
String basePath = "enchant_values." + enchantment.getKey();
|
||||
EnchantmentRarity rarity = enchantment.defaultRarity();
|
||||
|
||||
defaultConfig.set(basePath + ".item", rarity.getItemValue());
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
|
@ -226,12 +227,24 @@ public interface CAEnchantment {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all the unoptimised enchantments.
|
||||
* @param name The enchantment name
|
||||
* @return List of enchantment.
|
||||
* Gets the enchantment by the provided name.
|
||||
* @param name Name to fetch.
|
||||
* @return Registered enchantment. null if absent.
|
||||
*
|
||||
* @deprecated use {@link #getListByName(String)}
|
||||
*/
|
||||
@Deprecated(since = "1.6.3")
|
||||
static @Nullable CAEnchantment getByName(@NotNull String name){
|
||||
return CAEnchantmentRegistry.getInstance().getByName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets list of enchantment using the provided name.
|
||||
* @param name Name to fetch.
|
||||
* @return List of registered enchantment.
|
||||
*/
|
||||
static List<CAEnchantment> getListByName(@NotNull String name){
|
||||
return CAEnchantmentRegistry.getInstance().getListByName(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public class CAEnchantmentRegistry {
|
|||
|
||||
// Register enchantment functions
|
||||
private final HashMap<NamespacedKey, CAEnchantment> byKeyMap;
|
||||
private final HashMap<String, CAEnchantment> byNameMap;
|
||||
private final HashMap<String, List<CAEnchantment>> byNameMap;
|
||||
|
||||
private final SortedSet<CAEnchantment> nameSortedEnchantments;
|
||||
|
||||
|
|
@ -62,6 +62,8 @@ public class CAEnchantmentRegistry {
|
|||
|
||||
}
|
||||
|
||||
private static boolean hasWarnedRegistering = false;
|
||||
|
||||
/**
|
||||
* Can be used to register new enchantment.
|
||||
* <p>
|
||||
|
|
@ -73,19 +75,25 @@ public class CAEnchantmentRegistry {
|
|||
public boolean register(@NotNull CAEnchantment enchantment){
|
||||
if(byKeyMap.containsKey(enchantment.getKey())){
|
||||
CustomAnvil.instance.getLogger().log(Level.WARNING,
|
||||
"Duplicate registered enchantment. This should NOT happen.",
|
||||
"Duplicate 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. " +
|
||||
"maybe remove enchantment with the same key before registering yours",
|
||||
new IllegalStateException(enchantment.getKey()+" enchantment was already registered"));
|
||||
return false;
|
||||
}
|
||||
if(byNameMap.containsKey(enchantment.getName())){
|
||||
|
||||
if((!hasWarnedRegistering) && byNameMap.containsKey(enchantment.getName())){
|
||||
hasWarnedRegistering = true;
|
||||
|
||||
CustomAnvil.instance.getLogger().log(Level.WARNING,
|
||||
"Duplicate registered enchantment name. There will have issue. " +
|
||||
"\nI hope this do not happen to you on a production server. If it do, there is probably a plugin trying to register an enchantment with the same name than another one",
|
||||
new IllegalStateException(enchantment.getKey()+" enchantment name was already registered"));
|
||||
"Duplicate registered enchantment name. Please check that configuration is using namespace.");
|
||||
}
|
||||
|
||||
byKeyMap.put(enchantment.getKey(), enchantment);
|
||||
byNameMap.put(enchantment.getName(), enchantment);
|
||||
|
||||
byNameMap.putIfAbsent(enchantment.getName(), new ArrayList<>());
|
||||
byNameMap.get(enchantment.getName()).add(enchantment);
|
||||
|
||||
nameSortedEnchantments.add(enchantment);
|
||||
|
||||
if(!enchantment.isGetOptimised()){
|
||||
|
|
@ -112,7 +120,7 @@ public class CAEnchantmentRegistry {
|
|||
public boolean unregister(@Nullable CAEnchantment enchantment){
|
||||
if(enchantment == null) return false;
|
||||
byKeyMap.remove(enchantment.getKey());
|
||||
byNameMap.remove(enchantment.getName());
|
||||
byNameMap.get(enchantment.getName()).remove(enchantment);
|
||||
|
||||
nameSortedEnchantments.remove(enchantment);
|
||||
|
||||
|
|
@ -135,10 +143,26 @@ public class CAEnchantmentRegistry {
|
|||
* Gets the enchantment by the provided name.
|
||||
* @param name Name to fetch.
|
||||
* @return Registered enchantment. null if absent.
|
||||
*
|
||||
* @deprecated use {@link #getListByName(String)}
|
||||
*/
|
||||
@Deprecated(since = "1.6.3")
|
||||
@Nullable
|
||||
public CAEnchantment getByName(@NotNull String name){
|
||||
return byNameMap.get(name);
|
||||
List<CAEnchantment> enchantments = getListByName(name);
|
||||
if(enchantments.isEmpty()) return null;
|
||||
|
||||
return enchantments.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets list of enchantment using the provided name.
|
||||
* @param name Name to fetch.
|
||||
* @return List of registered enchantment.
|
||||
*/
|
||||
@NotNull
|
||||
public List<CAEnchantment> getListByName(@NotNull String name){
|
||||
return byNameMap.getOrDefault(name, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package xyz.alexcrea.cuanvil.enchant.wrapped;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import su.nightexpress.excellentenchants.api.enchantment.CustomEnchantment;
|
||||
import su.nightexpress.excellentenchants.api.enchantment.Definition;
|
||||
import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment;
|
||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
||||
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CAEEEnchantment extends CABukkitEnchantment implements AdditionalTestEnchantment {
|
||||
|
||||
@NotNull CustomEnchantment eeenchantment;
|
||||
@NotNull Definition definition;
|
||||
|
||||
public CAEEEnchantment(@NotNull CustomEnchantment enchantment) {
|
||||
super(enchantment.getBukkitEnchantment(), EnchantmentRarity.getRarity(enchantment.getDefinition().getAnvilCost()));
|
||||
this.eeenchantment = enchantment;
|
||||
this.definition = enchantment.getDefinition();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnchantConflict(@NotNull Map<CAEnchantment, Integer> enchantments, @NotNull Material itemMat) {
|
||||
if(!definition.hasConflicts()) return false;
|
||||
|
||||
Set<String> conflicts = definition.getConflicts();
|
||||
|
||||
for (CAEnchantment caEnchantment : enchantments.keySet()) {
|
||||
if(conflicts.contains(caEnchantment.getName())) 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;
|
||||
|
||||
return !definition.getSupportedItems().is(item);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ public class MainConfigGui extends ChestGui {
|
|||
public void init(PacketManager packetManager) {
|
||||
Pattern pattern = new Pattern(
|
||||
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
|
||||
"012304567",
|
||||
"012345678",
|
||||
"Q00000000"
|
||||
);
|
||||
PatternPane pane = new PatternPane(0, 0, 9, 3, pattern);
|
||||
|
|
@ -62,6 +62,18 @@ public class MainConfigGui extends ChestGui {
|
|||
GuiItem enchantLimitItem = GuiGlobalItems.goToGuiItem(enchantLimitItemstack, new EnchantLimitConfigGui());
|
||||
pane.bindItem('2', enchantLimitItem);
|
||||
|
||||
// enchant level limit item
|
||||
ItemStack enchantMergeLimitItemstack = new ItemStack(Material.ENCHANTED_BOOK);
|
||||
ItemMeta enchantMergeLimitMeta = enchantMergeLimitItemstack.getItemMeta();
|
||||
assert enchantMergeLimitMeta != null;
|
||||
|
||||
enchantMergeLimitMeta.setDisplayName("§aEnchantment Merge Limit");
|
||||
enchantMergeLimitMeta.setLore(Collections.singletonList("§7Click here to open enchantment merge limit menu"));
|
||||
enchantMergeLimitItemstack.setItemMeta(enchantMergeLimitMeta);
|
||||
|
||||
GuiItem enchantMergeLimitItem = GuiGlobalItems.goToGuiItem(enchantMergeLimitItemstack, new EnchantMergeLimitConfigGui());
|
||||
pane.bindItem('3', enchantMergeLimitItem);
|
||||
|
||||
// enchant cost item
|
||||
ItemStack enchantCostItemstack = new ItemStack(Material.EXPERIENCE_BOTTLE);
|
||||
ItemMeta enchantCostMeta = enchantCostItemstack.getItemMeta();
|
||||
|
|
@ -72,7 +84,7 @@ public class MainConfigGui extends ChestGui {
|
|||
enchantCostItemstack.setItemMeta(enchantCostMeta);
|
||||
|
||||
GuiItem enchantCostItem = GuiGlobalItems.goToGuiItem(enchantCostItemstack, new EnchantCostConfigGui());
|
||||
pane.bindItem('3', enchantCostItem);
|
||||
pane.bindItem('4', enchantCostItem);
|
||||
|
||||
// Enchantment Conflicts item
|
||||
ItemStack enchantConflictItemstack = new ItemStack(Material.OAK_FENCE);
|
||||
|
|
@ -84,7 +96,7 @@ public class MainConfigGui extends ChestGui {
|
|||
enchantConflictItemstack.setItemMeta(enchantConflictMeta);
|
||||
|
||||
GuiItem enchantConflictItem = GuiGlobalItems.goToGuiItem(enchantConflictItemstack, EnchantConflictGui.getInstance());
|
||||
pane.bindItem('4', enchantConflictItem);
|
||||
pane.bindItem('5', enchantConflictItem);
|
||||
|
||||
// Group config items
|
||||
ItemStack groupItemstack = new ItemStack(Material.CHEST);
|
||||
|
|
@ -97,7 +109,7 @@ public class MainConfigGui extends ChestGui {
|
|||
|
||||
GuiItem groupConfigItem = GuiGlobalItems.goToGuiItem(groupItemstack, GroupConfigGui.getInstance());
|
||||
|
||||
pane.bindItem('5', groupConfigItem);
|
||||
pane.bindItem('6', groupConfigItem);
|
||||
|
||||
// Unit repair item
|
||||
ItemStack unirRepairItemstack = new ItemStack(Material.DIAMOND);
|
||||
|
|
@ -109,7 +121,7 @@ public class MainConfigGui extends ChestGui {
|
|||
unirRepairItemstack.setItemMeta(unitRepairMeta);
|
||||
|
||||
GuiItem unitRepairItem = GuiGlobalItems.goToGuiItem(unirRepairItemstack, UnitRepairConfigGui.getInstance());
|
||||
pane.bindItem('6', unitRepairItem);
|
||||
pane.bindItem('7', unitRepairItem);
|
||||
|
||||
// Custom recipe item
|
||||
ItemStack customRecipeItemstack = new ItemStack(Material.CRAFTING_TABLE);
|
||||
|
|
@ -121,7 +133,7 @@ public class MainConfigGui extends ChestGui {
|
|||
customRecipeItemstack.setItemMeta(customRecipeMeta);
|
||||
|
||||
GuiItem customRecipeItem = GuiGlobalItems.goToGuiItem(customRecipeItemstack, CustomRecipeConfigGui.getInstance());
|
||||
pane.bindItem('7', customRecipeItem);
|
||||
pane.bindItem('8', customRecipeItem);
|
||||
|
||||
// quit item
|
||||
ItemStack quitItemstack = new ItemStack(Material.BARRIER);
|
||||
|
|
|
|||
|
|
@ -44,24 +44,16 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
|
|||
|
||||
@Override
|
||||
public EnchantCostSettingsGui.EnchantCostSettingFactory createFactory(CAEnchantment enchant) {
|
||||
String key = enchant.getKey().getKey().toLowerCase(Locale.ENGLISH);
|
||||
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key);
|
||||
String key = enchant.getKey().toString().toLowerCase(Locale.ENGLISH);
|
||||
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
|
||||
|
||||
// try to find rarity. default to 0 if not found
|
||||
EnchantmentRarity rarity = enchant.defaultRarity();
|
||||
try {
|
||||
rarity = EnchantmentProperties.valueOf(key.toUpperCase(Locale.ENGLISH)).getRarity();
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
|
||||
return EnchantCostSettingsGui.enchantCostFactory(prettyKey + " Level Cost", this,
|
||||
ConfigHolder.DEFAULT_CONFIG, SECTION_NAME + '.' + key,
|
||||
return new EnchantCostSettingsGui.EnchantCostSettingFactory(prettyKey + " Cost", this,
|
||||
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
|
||||
Arrays.asList(
|
||||
"§7How many level should " + prettyKey,
|
||||
"§7cost when applied by book or by another item."
|
||||
),
|
||||
0, 255,
|
||||
rarity.getItemValue(), rarity.getBookValue(),
|
||||
enchant, 0, 255,
|
||||
1, 10, 50);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package xyz.alexcrea.cuanvil.gui.config.global;
|
||||
|
||||
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
|
||||
import io.delilaheve.util.ConfigOptions;
|
||||
import org.bukkit.Material;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||
|
|
@ -37,17 +38,23 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
|
|||
|
||||
@Override
|
||||
public IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant) {
|
||||
String key = enchant.getKey().getKey().toLowerCase(Locale.ROOT);
|
||||
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key);
|
||||
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
|
||||
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
|
||||
|
||||
return new IntSettingsGui.IntSettingFactory(prettyKey + " Level Limit", this,
|
||||
return new IntSettingsGui.IntSettingFactory(prettyKey + " Limit", this,
|
||||
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
|
||||
Collections.singletonList(
|
||||
"§7Maximum applied level of " + prettyKey
|
||||
),
|
||||
0, 255,
|
||||
enchant.defaultMaxLevel(),
|
||||
1, 5, 10, 50, 100);
|
||||
1, 5, 10, 50, 100){
|
||||
|
||||
@Override
|
||||
public int getConfiguredValue() {
|
||||
return ConfigOptions.INSTANCE.enchantLimit(enchant);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
package xyz.alexcrea.cuanvil.gui.config.global;
|
||||
|
||||
import com.github.stefvanschie.inventoryframework.gui.GuiItem;
|
||||
import io.delilaheve.util.ConfigOptions;
|
||||
import org.bukkit.Material;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
||||
import xyz.alexcrea.cuanvil.gui.config.settings.IntSettingsGui;
|
||||
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
public class EnchantMergeLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsGui.IntSettingFactory> {
|
||||
|
||||
private static final String SECTION_NAME = "disable-merge-over";
|
||||
|
||||
private static EnchantMergeLimitConfigGui INSTANCE = null;
|
||||
|
||||
@Nullable
|
||||
public static EnchantMergeLimitConfigGui getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor of this Global gui for enchantment level limit settings.
|
||||
*/
|
||||
public EnchantMergeLimitConfigGui() {
|
||||
super("§8Enchantment Maximum Merge Level");
|
||||
if(INSTANCE == null) INSTANCE = this;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntSettingsGui.IntSettingFactory createFactory(CAEnchantment enchant) {
|
||||
String key = enchant.getKey().toString().toLowerCase(Locale.ROOT);
|
||||
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key.replace(":", "_"));
|
||||
|
||||
return new IntSettingsGui.IntSettingFactory(prettyKey + " Merge Limit", this,
|
||||
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG,
|
||||
Arrays.asList(
|
||||
"§7Maximum merge level for for " + prettyKey,
|
||||
"",
|
||||
"§7For example, if set to §e2§7, §alvl1 §7+ §alvl1 §7of will give a §alvl2",
|
||||
"§7But §alvl2 §7+ §alvl2 §7will not give a §clv3§7.",
|
||||
"§7Will still not merge above max enchantment level",
|
||||
"§e-1 §7(default) will set the merge limit to enchantment's maximum level"
|
||||
),
|
||||
-1, 255, -1,
|
||||
1, 5, 10, 50, 100){
|
||||
|
||||
@Override
|
||||
public int getConfiguredValue() {
|
||||
return ConfigOptions.INSTANCE.maxBeforeMergeDisabled(enchant);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiItem itemFromFactory(CAEnchantment enchantment, IntSettingsGui.IntSettingFactory inventoryFactory) {
|
||||
return inventoryFactory.getItem(
|
||||
Material.ENCHANTED_BOOK,
|
||||
inventoryFactory.getTitle());
|
||||
}
|
||||
}
|
||||
|
|
@ -258,7 +258,7 @@ public class EnchantConflictSubSettingGui extends MappedToListSubSettingGui impl
|
|||
String[] enchantKeys = new String[enchantments.size()];
|
||||
int index = 0;
|
||||
for (CAEnchantment enchantment : enchantments) {
|
||||
enchantKeys[index++] = enchantment.getKey().getKey();
|
||||
enchantKeys[index++] = enchantment.getKey().toString();
|
||||
}
|
||||
ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict + ".enchantments", enchantKeys);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.github.stefvanschie.inventoryframework.gui.type.util.Gui;
|
|||
import com.github.stefvanschie.inventoryframework.pane.PatternPane;
|
||||
import com.github.stefvanschie.inventoryframework.pane.util.Pattern;
|
||||
import io.delilaheve.CustomAnvil;
|
||||
import io.delilaheve.util.ConfigOptions;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
|
|
@ -13,6 +14,7 @@ import org.bukkit.inventory.meta.ItemMeta;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
||||
import xyz.alexcrea.cuanvil.gui.ValueUpdatableGui;
|
||||
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions;
|
||||
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems;
|
||||
|
|
@ -237,43 +239,13 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
|
|||
return super.hadChange() || nowBook != beforeBook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an int setting factory from setting's parameters.
|
||||
*
|
||||
* @param title The title of the gui.
|
||||
* @param parent Parent gui to go back when completed.
|
||||
* @param config Configuration holder of this setting.
|
||||
* @param configPath Configuration path of this setting.
|
||||
* @param displayLore Gui display item lore.
|
||||
* @param min Minimum value of this setting.
|
||||
* @param max Maximum value of this setting.
|
||||
* @param defaultItemVal Default item value if not found on the config.
|
||||
* @param defaultBookVal Default book value if not found on the config.
|
||||
* @param steps List of step the value can increment/decrement.
|
||||
* List's size should be between 1 (included) and 3 (included).
|
||||
* it is visually preferable to have an odd number of step.
|
||||
* If step only contain 1 value, no step item should be displayed.
|
||||
* @return A factory for an enchant cost setting gui.
|
||||
*/
|
||||
public static EnchantCostSettingFactory enchantCostFactory(
|
||||
@NotNull String title, @NotNull ValueUpdatableGui parent,
|
||||
@NotNull ConfigHolder config, @NotNull String configPath,
|
||||
@Nullable List<String> displayLore,
|
||||
int min, int max, int defaultItemVal, int defaultBookVal,
|
||||
int... steps) {
|
||||
return new EnchantCostSettingFactory(
|
||||
title, parent,
|
||||
configPath, config,
|
||||
displayLore,
|
||||
min, max, defaultItemVal, defaultBookVal, steps);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory for an enchantment cost setting gui that hold setting's information.
|
||||
*/
|
||||
public static class EnchantCostSettingFactory extends IntSettingsGui.IntSettingFactory {
|
||||
|
||||
int defaultBookVal;
|
||||
@NotNull CAEnchantment enchantment;
|
||||
|
||||
/**
|
||||
* Constructor for an enchantment cost setting gui factory.
|
||||
|
|
@ -285,25 +257,27 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
|
|||
* @param displayLore Gui display item lore.
|
||||
* @param min Minimum value of this setting.
|
||||
* @param max Maximum value of this setting.
|
||||
* @param defaultItemVal Default item value if not found on the config.
|
||||
* @param defaultBookVal Default book value if not found on the config.
|
||||
* @param enchantment Enchantment to change the cost to
|
||||
* @param steps List of step the value can increment/decrement.
|
||||
* List's size should be between 1 (included) and 3 (included).
|
||||
* it is visually preferable to have an odd number of step.
|
||||
* If step only contain 1 value, no step item should be displayed.
|
||||
*/
|
||||
protected EnchantCostSettingFactory(
|
||||
public EnchantCostSettingFactory(
|
||||
@NotNull String title, ValueUpdatableGui parent,
|
||||
@NotNull String configPath, @NotNull ConfigHolder config,
|
||||
@Nullable List<String> displayLore,
|
||||
int min, int max, int defaultItemVal, int defaultBookVal,
|
||||
int... steps) {
|
||||
@NotNull CAEnchantment enchantment,
|
||||
int min, int max, int... steps) {
|
||||
|
||||
super(title, parent,
|
||||
configPath, config,
|
||||
displayLore,
|
||||
min, max, defaultItemVal, steps);
|
||||
this.defaultBookVal = defaultBookVal;
|
||||
min, max, enchantment.defaultRarity().getItemValue(),
|
||||
steps);
|
||||
|
||||
this.defaultBookVal = enchantment.defaultRarity().getBookValue();
|
||||
this.enchantment = enchantment;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -311,14 +285,14 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
|
|||
*/
|
||||
@Override
|
||||
public int getConfiguredValue() {
|
||||
return this.config.getConfig().getInt(this.configPath + ITEM_PATH, this.defaultVal);
|
||||
return ConfigOptions.INSTANCE.enchantmentValue(enchantment, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The configured value for the enchant setting book value.
|
||||
*/
|
||||
public int getConfiguredBookValue() {
|
||||
return this.config.getConfig().getInt(this.configPath + BOOK_PATH, this.defaultBookVal);
|
||||
return ConfigOptions.INSTANCE.enchantmentValue(enchantment, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -45,13 +45,13 @@ public class Update_1_21 {
|
|||
addToStringList(groupConfig, "can_unbreak.groups", "mace");
|
||||
|
||||
// Add new enchant conflicts
|
||||
addToStringList(conflictConfig, "restriction_density.enchantments", "density");
|
||||
addToStringList(conflictConfig, "restriction_density.enchantments", "minecraft:density");
|
||||
addToStringList(conflictConfig, "restriction_density.notAffectedGroups", "mace", "enchanted_book");
|
||||
|
||||
addToStringList(conflictConfig, "restriction_breach.enchantments", "breach");
|
||||
addToStringList(conflictConfig, "restriction_breach.enchantments", "minecraft:breach");
|
||||
addToStringList(conflictConfig, "restriction_breach.notAffectedGroups", "mace", "enchanted_book");
|
||||
|
||||
addToStringList(conflictConfig, "restriction_wind_burst.enchantments", "wind_burst");
|
||||
addToStringList(conflictConfig, "restriction_wind_burst.enchantments", "minecraft:wind_burst");
|
||||
addToStringList(conflictConfig, "restriction_wind_burst.notAffectedGroups", "mace", "enchanted_book");
|
||||
|
||||
// Add mace to conflicts
|
||||
|
|
@ -59,13 +59,14 @@ public class Update_1_21 {
|
|||
addToStringList(conflictConfig, "restriction_smite.notAffectedGroups", "mace");
|
||||
addToStringList(conflictConfig, "restriction_bane_of_arthropods.notAffectedGroups", "mace");
|
||||
|
||||
addToStringList(conflictConfig, "mace_enchant_conflict.enchantments", "density", "breach", "smite", "bane_of_arthropods");
|
||||
addToStringList(conflictConfig, "mace_enchant_conflict.enchantments",
|
||||
"minecraft:density", "minecraft:breach", "minecraft:smite", "minecraft:bane_of_arthropods");
|
||||
conflictConfig.set("mace_enchant_conflict.maxEnchantmentBeforeConflict", 1);
|
||||
|
||||
// Add level limit
|
||||
baseConfig.set("enchant_limits.density", 5);
|
||||
baseConfig.set("enchant_limits.breach", 4);
|
||||
baseConfig.set("enchant_limits.wind_burst", 3);
|
||||
baseConfig.set("enchant_limits.minecraft:density", 5);
|
||||
baseConfig.set("enchant_limits.minecraft:breach", 4);
|
||||
baseConfig.set("enchant_limits.minecraft:wind_burst", 3);
|
||||
|
||||
// Add enchant values
|
||||
baseConfig.set("enchant_values.density.item", 1);
|
||||
|
|
|
|||
|
|
@ -1,580 +0,0 @@
|
|||
package io.delilaheve
|
||||
|
||||
import io.delilaheve.util.ConfigOptions
|
||||
import io.delilaheve.util.EnchantmentUtil.combineWith
|
||||
import io.delilaheve.util.ItemUtil.canMergeWith
|
||||
import io.delilaheve.util.ItemUtil.findEnchantments
|
||||
import io.delilaheve.util.ItemUtil.isEnchantedBook
|
||||
import io.delilaheve.util.ItemUtil.repairFrom
|
||||
import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe
|
||||
import io.delilaheve.util.ItemUtil.unitRepair
|
||||
import org.bukkit.ChatColor
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.entity.HumanEntity
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.Event
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.EventPriority.HIGHEST
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.ClickType
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
|
||||
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil.calculatePenalty
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil.getRightValues
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil.setAnvilInvXp
|
||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
/**
|
||||
* Listener for anvil events
|
||||
*/
|
||||
class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
||||
|
||||
companion object {
|
||||
// Anvil's output slot
|
||||
const val ANVIL_INPUT_LEFT = 0
|
||||
const val ANVIL_INPUT_RIGHT = 1
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler logic for when an anvil contains items to be combined
|
||||
*/
|
||||
@EventHandler(priority = HIGHEST)
|
||||
fun anvilCombineCheck(event: PrepareAnvilEvent) {
|
||||
// Test if the event should bypass custom anvil.
|
||||
if(DependencyManager.tryEventPreAnvilBypass(event)) return
|
||||
|
||||
val inventory = event.inventory
|
||||
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||
val second = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||
|
||||
// Should find player
|
||||
val player = event.view.player
|
||||
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
|
||||
// Test custom recipe
|
||||
val recipe = getCustomRecipe(first, second)
|
||||
CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}")
|
||||
if(recipe != null){
|
||||
val amount = getCustomRecipeAmount(recipe, first, second)
|
||||
|
||||
val resultItem: ItemStack = recipe.resultItem!!.clone()
|
||||
resultItem.amount *= amount
|
||||
|
||||
event.result = resultItem
|
||||
setAnvilInvXp(inventory, event.view, recipe.xpCostPerCraft * amount, true)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Test rename lonely item
|
||||
if (second == null) {
|
||||
val resultItem = first.clone()
|
||||
var anvilCost = handleRename(resultItem, inventory, player)
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
if (first == resultItem) {
|
||||
CustomAnvil.log("no right item, But input is same as output")
|
||||
event.result = null
|
||||
return
|
||||
}
|
||||
|
||||
event.result = resultItem
|
||||
|
||||
anvilCost += calculatePenalty(first, null, resultItem)
|
||||
|
||||
setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
return
|
||||
}
|
||||
|
||||
// Test for merge
|
||||
if (first.canMergeWith(second)) {
|
||||
val newEnchants = first.findEnchantments()
|
||||
.combineWith(second.findEnchantments(), first, player)
|
||||
val resultItem = first.clone()
|
||||
resultItem.setEnchantmentsUnsafe(newEnchants)
|
||||
|
||||
// Calculate enchantment cost
|
||||
var anvilCost = getRightValues(second, resultItem)
|
||||
// Calculate repair cost
|
||||
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
|
||||
}
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
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)
|
||||
// Calculate rename cost
|
||||
anvilCost += handleRename(resultItem, inventory, player)
|
||||
|
||||
// Finally, we set result
|
||||
event.result = resultItem
|
||||
|
||||
setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
return
|
||||
}
|
||||
|
||||
// Test for unit repair
|
||||
val unitRepairAmount = first.getRepair(second)
|
||||
if (unitRepairAmount != null) {
|
||||
val resultItem = first.clone()
|
||||
var anvilCost = handleRename(resultItem, inventory, player)
|
||||
|
||||
val repairAmount = resultItem.unitRepair(second.amount, unitRepairAmount)
|
||||
if (repairAmount > 0) {
|
||||
anvilCost += repairAmount * ConfigOptions.unitRepairCost
|
||||
}
|
||||
// We do not care about right item penalty for unit repair
|
||||
anvilCost += calculatePenalty(first, null, resultItem, true)
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
if (first == resultItem) {
|
||||
CustomAnvil.log("unit repair, But input is same as output")
|
||||
event.result = null
|
||||
return
|
||||
}
|
||||
event.result = resultItem
|
||||
|
||||
setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
} else {
|
||||
CustomAnvil.log("no anvil fuse type found")
|
||||
event.result = null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory, player: HumanEntity): Int {
|
||||
// Rename item and add renaming cost
|
||||
resultItem.itemMeta?.let {
|
||||
val displayName = ChatColor.stripColor(it.displayName)
|
||||
var inventoryName = ChatColor.stripColor(inventory.renameText)
|
||||
|
||||
var sumCost = 0
|
||||
|
||||
var useColor = false
|
||||
if(ConfigOptions.renameColorPossible){
|
||||
val resultString = StringBuilder(inventoryName)
|
||||
|
||||
useColor = handleRenamingColor(resultString, player)
|
||||
|
||||
if(useColor) {
|
||||
inventoryName = resultString.toString()
|
||||
|
||||
sumCost+= ConfigOptions.useOfColorCost
|
||||
}
|
||||
}
|
||||
|
||||
if ((!useColor && (!displayName.contentEquals(inventoryName))) || (useColor && !(it.displayName).contentEquals(inventoryName))) {
|
||||
it.setDisplayName(inventoryName)
|
||||
resultItem.itemMeta = it
|
||||
|
||||
sumCost+= ConfigOptions.itemRenameCost
|
||||
}
|
||||
|
||||
return sumCost
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun handleRenamingColor(textToColor: StringBuilder, player: HumanEntity): Boolean {
|
||||
val usePermission = ConfigOptions.permissionNeededForColor
|
||||
val canUseColorCode = ConfigOptions.allowColorCode && (!usePermission || player.hasPermission("ca.color.code"))
|
||||
val canUseHexColor = ConfigOptions.allowHexadecimalColor && (!usePermission || player.hasPermission("ca.color.hex"))
|
||||
|
||||
if((!canUseColorCode) && (!canUseHexColor)) return false
|
||||
|
||||
var useColor = false
|
||||
// Handle color code
|
||||
if(canUseColorCode){
|
||||
var nbReplacement = replaceAll(textToColor, "&", "§", 2)
|
||||
nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2)
|
||||
|
||||
if(nbReplacement > 0) useColor = true
|
||||
}
|
||||
|
||||
if(canUseHexColor){
|
||||
val nbReplacement = replaceHexToColor(textToColor, 7)
|
||||
|
||||
if(nbReplacement > 0) useColor = true
|
||||
}
|
||||
|
||||
return useColor
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace every instance of "from" to "to".
|
||||
* @param builder The builder to replace the string from.
|
||||
* @param from The source that should be replaced.
|
||||
* @param to The string that should replace.
|
||||
* @param endOffset Amount of character that should be ignored at the end.
|
||||
* @return The number of replacement was that was done.
|
||||
*/
|
||||
private fun replaceAll(builder: java.lang.StringBuilder, from: String, to: String, endOffset: Int): Int {
|
||||
var index = builder.indexOf(from)
|
||||
var numberOfChanges = 0
|
||||
|
||||
while (index != -1 && index < builder.length - endOffset) {
|
||||
builder.replace(index, index + from.length, to)
|
||||
index += to.length
|
||||
index = builder.indexOf(from, index)
|
||||
|
||||
numberOfChanges+=1
|
||||
}
|
||||
|
||||
return numberOfChanges
|
||||
}
|
||||
|
||||
val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string
|
||||
/**
|
||||
* Replace every hex color formatted like #000000 to the minecraft format
|
||||
* @param builder The builder to replace the hex color from.
|
||||
* @param endOffset Amount of character that should be ignored at the end.
|
||||
* @return The number of replacement was that was done.
|
||||
*/
|
||||
private fun replaceHexToColor(builder: StringBuilder, endOffset: Int): Int {
|
||||
val matcher: Matcher = HEX_PATTERN.matcher(builder)
|
||||
|
||||
var numberOfChanges = 0
|
||||
var startIndex = 0
|
||||
|
||||
while(matcher.find(startIndex)){
|
||||
startIndex = matcher.start()
|
||||
if(startIndex >= builder.length - endOffset) break
|
||||
|
||||
builder.replace(startIndex, startIndex + 1, "§x")
|
||||
startIndex+=2
|
||||
for (i in 0..5) {
|
||||
builder.insert(startIndex, '§')
|
||||
startIndex+=2
|
||||
}
|
||||
|
||||
numberOfChanges+=1
|
||||
}
|
||||
|
||||
return numberOfChanges
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler logic for when a player is trying to pull an item out of the anvil
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
fun anvilExtractionCheck(event: InventoryClickEvent) {
|
||||
val player = event.whoClicked as? Player ?: return
|
||||
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
val inventory = event.inventory as? AnvilInventory ?: return
|
||||
|
||||
if (event.rawSlot != ANVIL_OUTPUT_SLOT) {
|
||||
return
|
||||
}
|
||||
// Test if the event should bypass custom anvil.
|
||||
if(DependencyManager.tryClickAnvilResultBypass(event, inventory)) return
|
||||
|
||||
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
|
||||
val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||
val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||
|
||||
// Test custom recipe
|
||||
val recipe = getCustomRecipe(leftItem, rightItem)
|
||||
if(recipe != null){
|
||||
event.result = Event.Result.ALLOW
|
||||
onCustomCraft(
|
||||
event, recipe, player,
|
||||
leftItem, rightItem, output, inventory)
|
||||
return
|
||||
}
|
||||
|
||||
val canMerge = leftItem.canMergeWith(rightItem)
|
||||
val unitRepairResult = leftItem.getRepair(rightItem)
|
||||
val allowed = (rightItem == null)
|
||||
|| (canMerge)
|
||||
|| (unitRepairResult != null)
|
||||
|
||||
// True if there was no change or not allowed
|
||||
if ((output == inventory.getItem(ANVIL_INPUT_LEFT))
|
||||
|| !allowed
|
||||
) {
|
||||
event.result = Event.Result.DENY
|
||||
return
|
||||
}
|
||||
if (rightItem == null) {
|
||||
event.result = Event.Result.ALLOW
|
||||
return
|
||||
}
|
||||
if (canMerge) {
|
||||
event.result = Event.Result.ALLOW
|
||||
} else if (unitRepairResult != null) {
|
||||
onUnitRepairExtract(
|
||||
leftItem, rightItem, output,
|
||||
unitRepairResult, event, player, inventory
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCustomCraft(event: InventoryClickEvent,
|
||||
recipe: AnvilCustomRecipe,
|
||||
player: Player,
|
||||
leftItem: ItemStack,
|
||||
rightItem: ItemStack?,
|
||||
output: ItemStack,
|
||||
inventory: AnvilInventory) {
|
||||
event.result = Event.Result.DENY
|
||||
|
||||
if(recipe.leftItem == null) return // in case it changed
|
||||
|
||||
val amount = getCustomRecipeAmount(recipe, leftItem, rightItem)
|
||||
val xpCost = amount * recipe.xpCostPerCraft
|
||||
|
||||
if ((player.gameMode != GameMode.CREATIVE) && (player.level < xpCost)) return
|
||||
|
||||
// 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
|
||||
|
||||
// If not creative middle click...
|
||||
if (event.click != ClickType.MIDDLE) {
|
||||
// We remove what should be removed
|
||||
leftItem.amount -= amount * recipe.leftItem!!.amount
|
||||
inventory.setItem(ANVIL_INPUT_LEFT, leftItem)
|
||||
|
||||
if(rightItem != null){
|
||||
if(recipe.rightItem == null) return // in case it changed
|
||||
|
||||
rightItem.amount -= amount * recipe.rightItem!!.amount
|
||||
inventory.setItem(ANVIL_INPUT_RIGHT, rightItem)
|
||||
}
|
||||
|
||||
if(player.gameMode != GameMode.CREATIVE){
|
||||
player.level -= xpCost
|
||||
}
|
||||
|
||||
// Then we try to find the new values for the anvil
|
||||
val newAmount = getCustomRecipeAmount(recipe, leftItem, rightItem)
|
||||
|
||||
CustomAnvil.verboseLog("new amount is $newAmount")
|
||||
if(newAmount <= 0 || recipe.exactCount){
|
||||
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
||||
}else{
|
||||
val resultItem: ItemStack = recipe.resultItem!!.clone()
|
||||
resultItem.amount *= newAmount
|
||||
|
||||
val newXp = newAmount * newAmount
|
||||
|
||||
inventory.repairCost = newXp
|
||||
event.view.setProperty(REPAIR_COST, newXp)
|
||||
|
||||
inventory.setItem(ANVIL_OUTPUT_SLOT, resultItem)
|
||||
|
||||
player.updateInventory()
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, we add the item to the player
|
||||
if (slotDestination.type == SlotType.CURSOR) {
|
||||
player.setItemOnCursor(output)
|
||||
} else {// We assume SlotType == SlotType.INVENTORY
|
||||
player.inventory.setItem(slotDestination.slot, output)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
// Test repair cost
|
||||
var repairCost = 0
|
||||
if (player.gameMode != GameMode.CREATIVE) {
|
||||
// Get repairCost
|
||||
leftItem.itemMeta?.let { leftMeta ->
|
||||
val leftName = leftMeta.displayName
|
||||
output.itemMeta?.let {
|
||||
// Rename cost
|
||||
if (!leftName.contentEquals(it.displayName)) {
|
||||
repairCost += ConfigOptions.itemRenameCost
|
||||
|
||||
// Color cost
|
||||
if(it.displayName.contains('§')){
|
||||
repairCost += ConfigOptions.useOfColorCost
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repairCost += calculatePenalty(leftItem, null, resultCopy)
|
||||
repairCost += resultAmount * ConfigOptions.unitRepairCost
|
||||
|
||||
if (
|
||||
!ConfigOptions.doRemoveCostLimit &&
|
||||
ConfigOptions.doCapCost) {
|
||||
|
||||
repairCost = min(repairCost, ConfigOptions.maxAnvilCost)
|
||||
}
|
||||
|
||||
if ((inventory.maximumRepairCost <= repairCost)
|
||||
|| (player.level < repairCost)
|
||||
) return
|
||||
}
|
||||
// If not creative middle click...
|
||||
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_OUTPUT_SLOT, null)
|
||||
player.level -= repairCost
|
||||
}
|
||||
|
||||
// Finally, we add the item to the player
|
||||
if (slotDestination.type == SlotType.CURSOR) {
|
||||
player.setItemOnCursor(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) {
|
||||
val inventory = player.inventory
|
||||
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)) {
|
||||
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)) {
|
||||
slotIndex--
|
||||
}
|
||||
if (slotIndex < 9) {
|
||||
return NO_SLOT
|
||||
}
|
||||
return SlotContainer(SlotType.INVENTORY, slotIndex)
|
||||
} else {
|
||||
if (player.itemOnCursor.type != Material.AIR) {
|
||||
return NO_SLOT
|
||||
}
|
||||
return CURSOR_SLOT
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCustomRecipe (
|
||||
leftItem: ItemStack,
|
||||
rightItem: ItemStack?) : AnvilCustomRecipe? {
|
||||
|
||||
val recipeList = ConfigHolder.CUSTOM_RECIPE_HOLDER.recipeManager.recipeByMat[leftItem.type] ?: return null
|
||||
|
||||
CustomAnvil.verboseLog("Testing " + recipeList.size+" recipe...")
|
||||
for (recipe in recipeList) {
|
||||
if(recipe.testItem(leftItem, rightItem)){
|
||||
return recipe
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getCustomRecipeAmount(
|
||||
recipe: AnvilCustomRecipe,
|
||||
leftItem: ItemStack,
|
||||
rightItem: ItemStack?
|
||||
): Int{
|
||||
return if(recipe.exactCount) {
|
||||
if(leftItem.amount != recipe.leftItem!!.amount){
|
||||
0
|
||||
}else if(rightItem != null && rightItem.amount != recipe.rightItem!!.amount){
|
||||
0
|
||||
}else{
|
||||
1
|
||||
}
|
||||
}
|
||||
else {
|
||||
// test amount
|
||||
val resultItem = recipe.resultItem!! // we know exist as the recipe was returned to us
|
||||
val maxResultAmount = resultItem.type.maxStackSize/resultItem.amount
|
||||
val maxLeftAmount = leftItem.amount/recipe.leftItem!!.amount
|
||||
val maxRightAmount = if(rightItem == null){ maxLeftAmount } else{ rightItem.amount/recipe.rightItem!!.amount }
|
||||
|
||||
CustomAnvil.verboseLog("resultItem: $resultItem, maxResultAmount: $maxResultAmount, maxLeftAmount: $maxLeftAmount, maxRightAmount: $maxRightAmount")
|
||||
|
||||
min(min(maxResultAmount, maxLeftAmount), maxRightAmount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
fun onAnvilClose(event: InventoryCloseEvent){
|
||||
val player = event.player
|
||||
if(event.inventory !is AnvilInventory) return
|
||||
if(player is Player && GameMode.CREATIVE != player.gameMode){
|
||||
packetManager.setInstantBuild(player, false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private class SlotContainer(val type: SlotType, val slot: Int)
|
||||
private enum class SlotType {
|
||||
CURSOR,
|
||||
INVENTORY,
|
||||
NO_SLOT
|
||||
|
||||
}
|
||||
|
|
@ -13,7 +13,10 @@ import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
|||
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry
|
||||
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
|
||||
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant
|
||||
import xyz.alexcrea.cuanvil.listener.AnvilCloseListener
|
||||
import xyz.alexcrea.cuanvil.listener.AnvilResultListener
|
||||
import xyz.alexcrea.cuanvil.listener.ChatEventListener
|
||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener
|
||||
import xyz.alexcrea.cuanvil.update.PluginSetDefault
|
||||
import xyz.alexcrea.cuanvil.update.Update_1_21
|
||||
import xyz.alexcrea.cuanvil.update.plugin.PluginUpdates
|
||||
|
|
@ -110,7 +113,9 @@ class CustomAnvil : JavaPlugin() {
|
|||
DependencyManager.loadDependency()
|
||||
|
||||
// Register anvil events
|
||||
server.pluginManager.registerEvents(AnvilEventListener(DependencyManager.packetManager), this)
|
||||
server.pluginManager.registerEvents(PrepareAnvilListener(), this)
|
||||
server.pluginManager.registerEvents(AnvilResultListener(), this)
|
||||
server.pluginManager.registerEvents(AnvilCloseListener(DependencyManager.packetManager), this)
|
||||
|
||||
// Load metrics
|
||||
Metrics(this, bstatsPluginId)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ object ConfigOptions {
|
|||
const val ENCHANT_LIMIT_ROOT = "enchant_limits"
|
||||
const val ENCHANT_VALUES_ROOT = "enchant_values"
|
||||
|
||||
const val DISABLE_MERGE_OVER_ROOT = "disable-merge-over"
|
||||
|
||||
// Keys for specific enchantment values
|
||||
private const val KEY_BOOK = "book"
|
||||
private const val KEY_ITEM = "item"
|
||||
|
|
@ -110,6 +112,9 @@ object ConfigOptions {
|
|||
// Default value for an enchantment multiplier
|
||||
private const val DEFAULT_ENCHANT_VALUE = 0
|
||||
|
||||
// Default max before merge disabled (negative mean enabled)
|
||||
const val DEFAULT_MAX_BEFORE_MERGE_DISABLED = -1;
|
||||
|
||||
// -------------
|
||||
// Get methods
|
||||
// -------------
|
||||
|
|
@ -296,21 +301,28 @@ object ConfigOptions {
|
|||
* Get the given [enchantment]'s limit
|
||||
*/
|
||||
fun enchantLimit(enchantment: CAEnchantment): Int {
|
||||
return enchantLimit(enchantment.enchantmentName)
|
||||
// Test namespace
|
||||
var limit = enchantLimit(enchantment.key.toString())
|
||||
if(limit != null) return limit;
|
||||
|
||||
// Test legacy (name only)
|
||||
limit = enchantLimit(enchantment.enchantmentName)
|
||||
if(limit != null) return limit;
|
||||
|
||||
// get default (and test old legacy if present)
|
||||
return getDefaultLevel(enchantment.enchantmentName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the given [enchantmentName]'s limit
|
||||
*/
|
||||
private fun enchantLimit(enchantmentName: String): Int {
|
||||
val default = getDefaultLevel(enchantmentName)
|
||||
private fun enchantLimit(enchantmentName: String): Int? {
|
||||
|
||||
val path = "${ENCHANT_LIMIT_ROOT}.$enchantmentName"
|
||||
return CustomAnvil.instance
|
||||
.config
|
||||
.getInt(path, default)
|
||||
.getInt(path, ENCHANT_LIMIT_RANGE.first-1)
|
||||
.takeIf { it in ENCHANT_LIMIT_RANGE }
|
||||
?: default
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -319,7 +331,9 @@ object ConfigOptions {
|
|||
private fun getDefaultLevel(enchantmentName: String, // compatibility with 1.20.5. TODO better update system
|
||||
) : Int {
|
||||
if(enchantmentName == "sweeping_edge"){
|
||||
return enchantLimit("sweeping")
|
||||
val limit = enchantLimit("sweeping")
|
||||
if(limit != null) return limit
|
||||
|
||||
}
|
||||
return defaultEnchantLimit
|
||||
}
|
||||
|
|
@ -332,7 +346,17 @@ object ConfigOptions {
|
|||
enchantment: CAEnchantment,
|
||||
isFromBook: Boolean
|
||||
): Int {
|
||||
return enchantmentValue(enchantment.enchantmentName, isFromBook)
|
||||
// Test namespace
|
||||
var limit = enchantmentValue(enchantment.key.toString(), isFromBook)
|
||||
if(limit != null) return limit;
|
||||
|
||||
// Test legacy (name only)
|
||||
limit = enchantmentValue(enchantment.enchantmentName, isFromBook)
|
||||
if(limit != null) return limit;
|
||||
|
||||
// get default (and test old legacy if present)
|
||||
return getDefaultValue(enchantment, isFromBook)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -342,36 +366,76 @@ object ConfigOptions {
|
|||
private fun enchantmentValue(
|
||||
enchantmentName: String,
|
||||
isFromBook: Boolean
|
||||
): Int {
|
||||
val default = getDefaultValue(enchantmentName, isFromBook)
|
||||
|
||||
): Int? {
|
||||
val typeKey = if (isFromBook) KEY_BOOK else KEY_ITEM
|
||||
val path = "${ENCHANT_VALUES_ROOT}.${enchantmentName}.$typeKey"
|
||||
return CustomAnvil.instance
|
||||
.config
|
||||
.getInt(path, default)
|
||||
.getInt(path, DEFAULT_ENCHANT_VALUE - 1)
|
||||
.takeIf { it >= DEFAULT_ENCHANT_VALUE }
|
||||
?: DEFAULT_ENCHANT_VALUE
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default value if enchantment do not exist on config
|
||||
*/
|
||||
private fun getDefaultValue(enchantmentName: String, // compatibility with 1.20.5. TODO better update system
|
||||
private fun getDefaultValue(enchantment: CAEnchantment, // compatibility with 1.20.5. TODO better update system
|
||||
isFromBook: Boolean) : Int {
|
||||
if(enchantmentName == "sweeping_edge"){
|
||||
return enchantmentValue("sweeping", isFromBook)
|
||||
|
||||
val enchantmentName = enchantment.key.toString()
|
||||
if(enchantmentName == "minecraft:sweeping_edge"){
|
||||
var limit = enchantmentValue("minecraft:sweeping", isFromBook)
|
||||
if(limit != null) return limit
|
||||
|
||||
// legacy name
|
||||
limit = enchantmentValue("sweeping", isFromBook)
|
||||
if(limit != null) return limit
|
||||
}
|
||||
|
||||
val enchantment = CAEnchantment.getByName(enchantmentName)
|
||||
if(enchantment != null){
|
||||
val rarity = enchantment.defaultRarity()
|
||||
|
||||
return if(isFromBook) rarity.bookValue
|
||||
else rarity.itemValue
|
||||
return if(isFromBook)
|
||||
rarity.bookValue
|
||||
else
|
||||
rarity.itemValue
|
||||
}
|
||||
|
||||
return DEFAULT_ENCHANT_VALUE
|
||||
/**
|
||||
* Get the given [enchantmentName]'s level before merge is disabled
|
||||
* a negative value would mean never disabled
|
||||
*/
|
||||
fun maxBeforeMergeDisabled(enchantment: CAEnchantment): Int {
|
||||
val key = enchantment.key.toString()
|
||||
var value = maxBeforeMergeDisabled(key)
|
||||
if(value != null) return value
|
||||
|
||||
// Legacy name
|
||||
val legacy = enchantment.enchantmentName
|
||||
value = maxBeforeMergeDisabled(legacy)
|
||||
if(value != null) return value
|
||||
|
||||
if(key == "minecraft:sweeping_edge"){
|
||||
value = maxBeforeMergeDisabled("minecraft:sweeping")
|
||||
if(value != null) return value
|
||||
|
||||
// legacy name of legacy enchantment name
|
||||
value = maxBeforeMergeDisabled("sweeping")
|
||||
if(value != null) return value
|
||||
}
|
||||
|
||||
return DEFAULT_MAX_BEFORE_MERGE_DISABLED
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the given [enchantmentName]'s level before merge is disabled
|
||||
* a negative value would mean never disabled
|
||||
*/
|
||||
private fun maxBeforeMergeDisabled(enchantmentName: String) : Int? {
|
||||
// find if set
|
||||
val path = "${DISABLE_MERGE_OVER_ROOT}.$enchantmentName"
|
||||
|
||||
return CustomAnvil.instance
|
||||
.config
|
||||
.getInt(path, ENCHANT_LIMIT_RANGE.min() - 1)
|
||||
.takeIf { it in ENCHANT_LIMIT_RANGE }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,11 @@ object EnchantmentUtil {
|
|||
}
|
||||
// ... and they're the same level
|
||||
else {
|
||||
// try to increase the enchantment level by 1
|
||||
// We test if it is allowed to merge at this level
|
||||
val maxBeforeDisabled = ConfigOptions.maxBeforeMergeDisabled(enchantment)
|
||||
if((maxBeforeDisabled > 0) && (oldLevel >= maxBeforeDisabled)) return@forEach
|
||||
|
||||
// Now we increase the enchantment level by 1
|
||||
var newLevel = oldLevel + 1
|
||||
newLevel = max(min(newLevel, maxLevel), oldLevel)
|
||||
this[enchantment] = newLevel
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import org.bukkit.event.inventory.InventoryClickEvent
|
|||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.ExternGuiTester
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.GuiTesterSelector
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerSelector
|
||||
import xyz.alexcrea.cuanvil.dependency.scheduler.BukkitScheduler
|
||||
|
|
@ -17,8 +19,12 @@ object DependencyManager {
|
|||
var isFolia: Boolean = false
|
||||
lateinit var scheduler: TaskScheduler
|
||||
lateinit var packetManager: PacketManager
|
||||
var externGuiTester: ExternGuiTester? = null
|
||||
|
||||
var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null
|
||||
var ecoEnchantCompatibility: EcoEnchantDependency? = null
|
||||
var excellentEnchantsCompatibility: ExcellentEnchantsDependency? = null
|
||||
|
||||
var disenchantmentCompatibility: DisenchantmentDependency? = null
|
||||
|
||||
fun loadDependency(){
|
||||
|
|
@ -35,6 +41,7 @@ object DependencyManager {
|
|||
// Packet Manager
|
||||
val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.config.getBoolean("force_protocolib", false)
|
||||
packetManager = PacketManagerSelector.selectPacketManager(forceProtocolib)
|
||||
externGuiTester = GuiTesterSelector.selectGuiTester
|
||||
|
||||
// Enchantment Squared dependency
|
||||
if(pluginManager.isPluginEnabled("EnchantsSquared")){
|
||||
|
|
@ -48,6 +55,12 @@ object DependencyManager {
|
|||
ecoEnchantCompatibility!!.disableAnvilListener()
|
||||
}
|
||||
|
||||
// Excellent Enchants dependency
|
||||
if(pluginManager.isPluginEnabled("ExcellentEnchants")){
|
||||
excellentEnchantsCompatibility = ExcellentEnchantsDependency()
|
||||
excellentEnchantsCompatibility!!.redirectListeners()
|
||||
}
|
||||
|
||||
// Disenchantment dependency
|
||||
if(pluginManager.isPluginEnabled("Disenchantment")){
|
||||
disenchantmentCompatibility = DisenchantmentDependency()
|
||||
|
|
@ -64,6 +77,7 @@ object DependencyManager {
|
|||
fun registerEnchantments() {
|
||||
enchantmentSquaredCompatibility?.registerEnchantments()
|
||||
ecoEnchantCompatibility?.registerEnchantments()
|
||||
excellentEnchantsCompatibility?.registerEnchantments()
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -79,16 +93,30 @@ object DependencyManager {
|
|||
fun tryEventPreAnvilBypass(event: PrepareAnvilEvent): Boolean {
|
||||
var bypass = false
|
||||
|
||||
// Test if disenchantment used special prepare anvil
|
||||
if(disenchantmentCompatibility?.testPrepareAnvil(event) == true) bypass = true
|
||||
|
||||
// Test excellent enchantments used special prepare anvil
|
||||
if(!bypass && (excellentEnchantsCompatibility?.testPrepareAnvil(event) == true)) bypass = true
|
||||
|
||||
// Test if the inventory is a gui(version specific)
|
||||
if(!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true
|
||||
|
||||
return bypass
|
||||
}
|
||||
|
||||
fun tryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean {
|
||||
var bypass = false
|
||||
|
||||
// Test if disenchantment used special event click
|
||||
if(disenchantmentCompatibility?.testAnvilResult(event, inventory) == true) bypass = true
|
||||
|
||||
// Test if disenchantment used special event click
|
||||
if(!bypass && (excellentEnchantsCompatibility?.testAnvilResult(event) == true)) bypass = true
|
||||
|
||||
// Test if the inventory is a gui(version specific)
|
||||
if(!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true
|
||||
|
||||
return bypass
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import cz.kominekjan.disenchantment.events.DisenchantClickEvent
|
|||
import cz.kominekjan.disenchantment.events.DisenchantEvent
|
||||
import cz.kominekjan.disenchantment.events.ShatterClickEvent
|
||||
import cz.kominekjan.disenchantment.events.ShatterEvent
|
||||
import io.delilaheve.AnvilEventListener
|
||||
import io.delilaheve.CustomAnvil
|
||||
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 xyz.alexcrea.cuanvil.listener.PrepareAnvilListener
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
|
||||
|
||||
class DisenchantmentDependency {
|
||||
|
|
@ -26,7 +26,6 @@ class DisenchantmentDependency {
|
|||
private lateinit var itemClickEvent: DisenchantClickEvent
|
||||
|
||||
fun redirectListeners() {
|
||||
|
||||
val toUnregister = ArrayList<RegisteredListener>()
|
||||
// get required PrepareAnvilEvent listener
|
||||
for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) {
|
||||
|
|
@ -96,7 +95,7 @@ class DisenchantmentDependency {
|
|||
}
|
||||
|
||||
fun testAnvilResult(event: InventoryClickEvent, inventory: AnvilInventory): Boolean {
|
||||
val previousResultSlot = inventory.getItem(AnvilEventListener.ANVIL_OUTPUT_SLOT)?.clone()
|
||||
val previousResultSlot = inventory.getItem(PrepareAnvilListener.ANVIL_OUTPUT_SLOT)?.clone()
|
||||
|
||||
// Test event if change the result
|
||||
itemClickEvent.onDisenchantmentClickEvent(event)
|
||||
|
|
@ -115,7 +114,7 @@ class DisenchantmentDependency {
|
|||
}
|
||||
|
||||
private fun testAnvilInventoryChange(inventory: AnvilInventory, previous: ItemStack?): Boolean {
|
||||
val currentResult = inventory.getItem(AnvilEventListener.ANVIL_OUTPUT_SLOT)
|
||||
val currentResult = inventory.getItem(PrepareAnvilListener.ANVIL_OUTPUT_SLOT)
|
||||
|
||||
return currentResult == previous
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
package xyz.alexcrea.cuanvil.dependency
|
||||
|
||||
import io.delilaheve.CustomAnvil
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.plugin.RegisteredListener
|
||||
import su.nightexpress.excellentenchants.enchantment.impl.universal.CurseOfFragilityEnchant
|
||||
import su.nightexpress.excellentenchants.enchantment.listener.AnvilListener
|
||||
import su.nightexpress.excellentenchants.registry.EnchantRegistry
|
||||
import xyz.alexcrea.cuanvil.api.EnchantmentApi
|
||||
import xyz.alexcrea.cuanvil.enchant.wrapped.CAEEEnchantment
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class ExcellentEnchantsDependency {
|
||||
|
||||
init {
|
||||
CustomAnvil.instance.logger.info("Excellent Enchants Detected !")
|
||||
}
|
||||
|
||||
fun registerEnchantments() {
|
||||
CustomAnvil.instance.logger.info("Preparing Excellent Enchants compatibility...")
|
||||
|
||||
for (enchantment in EnchantRegistry.getRegistered()) {
|
||||
EnchantmentApi.unregisterEnchantment(enchantment.bukkitEnchantment.key) // As excellent enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant.
|
||||
EnchantmentApi.registerEnchantment(CAEEEnchantment(enchantment))
|
||||
}
|
||||
|
||||
CustomAnvil.instance.logger.info("Excellent Enchants should now work as expected !")
|
||||
}
|
||||
|
||||
private lateinit var fragilityCurse: CurseOfFragilityEnchant
|
||||
|
||||
private lateinit var anvilListener: AnvilListener
|
||||
private lateinit var handleRechargeMethod: Method
|
||||
private lateinit var handleCombineMethod: Method
|
||||
|
||||
fun redirectListeners() {
|
||||
val toUnregister = ArrayList<RegisteredListener>()
|
||||
// get required PrepareAnvilEvent listener
|
||||
for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) {
|
||||
val listener = registeredListener.listener
|
||||
|
||||
if(listener is CurseOfFragilityEnchant){
|
||||
this.fragilityCurse = listener
|
||||
toUnregister.add(registeredListener)
|
||||
}
|
||||
|
||||
if(listener is AnvilListener){
|
||||
this.anvilListener = listener;
|
||||
toUnregister.add(registeredListener)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (listener in toUnregister) {
|
||||
PrepareAnvilEvent.getHandlerList().unregister(listener)
|
||||
|
||||
}
|
||||
|
||||
// Unregister inventory click event
|
||||
InventoryClickEvent.getHandlerList().unregister(this.anvilListener)
|
||||
|
||||
findAnvilFunctions()
|
||||
}
|
||||
|
||||
private fun findAnvilFunctions() {
|
||||
this.handleRechargeMethod = AnvilListener::class.java.getDeclaredMethod("handleRecharge",
|
||||
PrepareAnvilEvent::class.java, ItemStack::class.java, ItemStack::class.java)
|
||||
this.handleRechargeMethod.setAccessible(true)
|
||||
|
||||
this.handleCombineMethod = AnvilListener::class.java.getDeclaredMethod("handleCombine",
|
||||
PrepareAnvilEvent::class.java, ItemStack::class.java, ItemStack::class.java, ItemStack::class.java)
|
||||
this.handleCombineMethod.setAccessible(true)
|
||||
|
||||
}
|
||||
|
||||
fun testPrepareAnvil(event: PrepareAnvilEvent): Boolean {
|
||||
if(event.result != null){
|
||||
this.fragilityCurse.onItemAnvil(event)
|
||||
if(event.result == null) return true
|
||||
}
|
||||
|
||||
var first: ItemStack? = event.inventory.getItem(0)
|
||||
var second: ItemStack? = event.inventory.getItem(1)
|
||||
var result = event.result
|
||||
|
||||
if (first == null) first = ItemStack(Material.AIR)
|
||||
if (second == null) second = ItemStack(Material.AIR)
|
||||
if (result == null) result = ItemStack(Material.AIR)
|
||||
|
||||
if(handleRechargeMethod.invoke(this.anvilListener, event, first, second) as Boolean) return true
|
||||
return handleCombineMethod.invoke(this.anvilListener, event, first, second, result) as Boolean
|
||||
}
|
||||
|
||||
fun testAnvilResult(event: InventoryClickEvent): Any {
|
||||
if(event.inventory.getItem(2) != null){
|
||||
this.anvilListener.onClickAnvil(event)
|
||||
return event.inventory.getItem(2) == null
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package xyz.alexcrea.cuanvil.dependency.gui
|
||||
|
||||
import xyz.alexcrea.cuanvil.dependency.gui.version.*;
|
||||
import xyz.alexcrea.cuanvil.update.UpdateUtils
|
||||
|
||||
object GuiTesterSelector {
|
||||
|
||||
val selectGuiTester: ExternGuiTester?
|
||||
get() {
|
||||
val versionParts = UpdateUtils.currentMinecraftVersionArray()
|
||||
if (versionParts[0] != 1) return null
|
||||
|
||||
return when (versionParts[1]) {
|
||||
// Can't support 1.16.5 bc 1.16.5 paper userdev do not exist
|
||||
|
||||
17 -> when (versionParts[2]) {
|
||||
0, 1 -> v1_17R1_ExternGuiTester()
|
||||
else -> null
|
||||
}
|
||||
|
||||
18 -> when (versionParts[2]) {
|
||||
0, 1 -> v1_18R1_ExternGuiTester()
|
||||
2 -> v1_18R2_ExternGuiTester()
|
||||
else -> null
|
||||
}
|
||||
|
||||
19 -> when (versionParts[2]) {
|
||||
0, 1, 2 -> v1_19R1_ExternGuiTester()
|
||||
3 -> v1_19R2_ExternGuiTester()
|
||||
4 -> v1_19R3_ExternGuiTester()
|
||||
else -> null
|
||||
}
|
||||
|
||||
20 -> when (versionParts[2]) {
|
||||
0, 1 -> v1_20R1_ExternGuiTester()
|
||||
2 -> v1_20R2_ExternGuiTester()
|
||||
3, 4 -> v1_20R3_ExternGuiTester()
|
||||
5, 6 -> v1_20R4_ExternGuiTester()
|
||||
else -> null
|
||||
}
|
||||
|
||||
21 -> when (versionParts[2]) {
|
||||
0, 1 -> v1_21R1_ExternGuiTester()
|
||||
else -> null
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -15,6 +15,9 @@ class EnchantConflictGroup(
|
|||
fun addEnchantment(enchant: CAEnchantment) {
|
||||
enchantments.add(enchant)
|
||||
}
|
||||
fun addEnchantments(enchants: List<CAEnchantment>) {
|
||||
enchantments.addAll(enchants)
|
||||
}
|
||||
|
||||
fun allowed(enchants: Set<CAEnchantment>, mat: Material): Boolean {
|
||||
if (enchantments.size < minBeforeBlock) {
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ class EnchantConflictManager {
|
|||
const val DEFAULT_GROUP_NAME = "joinedGroup"
|
||||
|
||||
// 1.20.5 compatibility TODO better update system
|
||||
private val SWEEPING_EDGE_ENCHANT =
|
||||
private val SWEEPING_EDGE_ENCHANT = Collections.singletonList<CAEnchantment>(
|
||||
CAEnchantment.getByKey(NamespacedKey.minecraft("sweeping_edge")) ?:
|
||||
CAEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key)
|
||||
CAEnchantment.getByKey(Enchantment.SWEEPING_EDGE.key))
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -94,14 +94,14 @@ class EnchantConflictManager {
|
|||
// Read and add enchantment to conflict
|
||||
val enchantList = section.getStringList(ENCH_LIST_PATH)
|
||||
for (enchantName in enchantList) {
|
||||
val enchant = getEnchantByName(enchantName)
|
||||
if (enchant == null) {
|
||||
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.addEnchantment(enchant)
|
||||
conflict.addEnchantments(enchants)
|
||||
}
|
||||
if (conflict.getEnchants().isEmpty()) {
|
||||
if (!futureUse) { //TODO future use will be deprecated once the new update system is finished
|
||||
|
|
@ -112,16 +112,23 @@ class EnchantConflictManager {
|
|||
return conflict
|
||||
}
|
||||
|
||||
private fun getEnchantByName(enchantName: String): CAEnchantment? {
|
||||
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){
|
||||
"sweeping", "sweeping_edge" -> {
|
||||
"minecraft:sweeping", "sweeping",
|
||||
"minecraft:sweeping_edge", "sweeping_edge" -> {
|
||||
return SWEEPING_EDGE_ENCHANT
|
||||
}
|
||||
}
|
||||
|
||||
return CAEnchantment.getByName(enchantName)
|
||||
return CAEnchantment.getListByName(enchantName)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package xyz.alexcrea.cuanvil.listener
|
||||
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
|
||||
|
||||
class AnvilCloseListener(private val packetManager: PacketManager) : Listener {
|
||||
|
||||
@EventHandler
|
||||
fun onAnvilClose(event: InventoryCloseEvent){
|
||||
val player = event.player
|
||||
if(event.inventory !is AnvilInventory) return
|
||||
if(player is Player && GameMode.CREATIVE != player.gameMode){
|
||||
packetManager.setInstantBuild(player, false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
package xyz.alexcrea.cuanvil.listener
|
||||
|
||||
import io.delilaheve.CustomAnvil
|
||||
import io.delilaheve.util.ConfigOptions
|
||||
import io.delilaheve.util.ItemUtil.canMergeWith
|
||||
import io.delilaheve.util.ItemUtil.unitRepair
|
||||
import org.bukkit.GameMode
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.Event
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.ClickType
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT
|
||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT
|
||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
|
||||
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
|
||||
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
|
||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||
import kotlin.math.min
|
||||
|
||||
class AnvilResultListener: Listener {
|
||||
|
||||
companion object {
|
||||
// static slot container
|
||||
private val NO_SLOT = SlotContainer(SlotType.NO_SLOT, 0)
|
||||
private val CURSOR_SLOT = SlotContainer(SlotType.CURSOR, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler logic for when a player is trying to pull an item out of the anvil
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
fun anvilExtractionCheck(event: InventoryClickEvent) {
|
||||
val player = event.whoClicked as? Player ?: return
|
||||
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
val inventory = event.inventory as? AnvilInventory ?: return
|
||||
|
||||
if (event.rawSlot != ANVIL_OUTPUT_SLOT) {
|
||||
return
|
||||
}
|
||||
// Test if the event should bypass custom anvil.
|
||||
if(DependencyManager.tryClickAnvilResultBypass(event, inventory)) return
|
||||
|
||||
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
|
||||
val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||
val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||
|
||||
// Test custom recipe
|
||||
val recipe = CustomRecipeUtil.getCustomRecipe(leftItem, rightItem)
|
||||
if(recipe != null){
|
||||
event.result = Event.Result.ALLOW
|
||||
onCustomCraft(
|
||||
event, recipe, player,
|
||||
leftItem, rightItem, output, inventory)
|
||||
return
|
||||
}
|
||||
|
||||
val canMerge = leftItem.canMergeWith(rightItem)
|
||||
val unitRepairResult = leftItem.getRepair(rightItem)
|
||||
val allowed = (rightItem == null)
|
||||
|| (canMerge)
|
||||
|| (unitRepairResult != null)
|
||||
|
||||
// True if there was no change or not allowed
|
||||
if ((output == inventory.getItem(ANVIL_INPUT_LEFT))
|
||||
|| !allowed
|
||||
) {
|
||||
event.result = Event.Result.DENY
|
||||
return
|
||||
}
|
||||
if (rightItem == null) {
|
||||
event.result = Event.Result.ALLOW
|
||||
return
|
||||
}
|
||||
if (canMerge) {
|
||||
event.result = Event.Result.ALLOW
|
||||
} else if (unitRepairResult != null) {
|
||||
onUnitRepairExtract(
|
||||
leftItem, rightItem, output,
|
||||
unitRepairResult, event, player, inventory
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun onCustomCraft(event: InventoryClickEvent,
|
||||
recipe: AnvilCustomRecipe,
|
||||
player: Player,
|
||||
leftItem: ItemStack,
|
||||
rightItem: ItemStack?,
|
||||
output: ItemStack,
|
||||
inventory: AnvilInventory
|
||||
) {
|
||||
event.result = Event.Result.DENY
|
||||
|
||||
if(recipe.leftItem == null) return // in case it changed
|
||||
|
||||
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem)
|
||||
val xpCost = amount * recipe.xpCostPerCraft
|
||||
|
||||
if ((player.gameMode != GameMode.CREATIVE) && (player.level < xpCost)) return
|
||||
|
||||
// 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
|
||||
|
||||
// Handle not creative middle click...
|
||||
if (event.click != ClickType.MIDDLE &&
|
||||
!handleCustomCraftClick(event, recipe, inventory, player, leftItem, rightItem, amount, xpCost)) return;
|
||||
|
||||
// Finally, we add the item to the player
|
||||
if (slotDestination.type == SlotType.CURSOR) {
|
||||
player.setItemOnCursor(output)
|
||||
} else {// We assume SlotType == SlotType.INVENTORY
|
||||
player.inventory.setItem(slotDestination.slot, output)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCustomCraftClick(event: InventoryClickEvent, recipe: AnvilCustomRecipe,
|
||||
inventory: AnvilInventory, player: Player,
|
||||
leftItem: ItemStack, rightItem: ItemStack?,
|
||||
amount: Int, xpCost: Int): Boolean {
|
||||
// We remove what should be removed
|
||||
if(rightItem != null){
|
||||
if(recipe.rightItem == null) return false// in case it changed
|
||||
|
||||
rightItem.amount -= amount * recipe.rightItem!!.amount
|
||||
inventory.setItem(ANVIL_INPUT_RIGHT, rightItem)
|
||||
}
|
||||
|
||||
leftItem.amount -= amount * recipe.leftItem!!.amount
|
||||
inventory.setItem(ANVIL_INPUT_LEFT, leftItem)
|
||||
|
||||
if(player.gameMode != GameMode.CREATIVE){
|
||||
player.level -= xpCost
|
||||
}
|
||||
|
||||
// Then we try to find the new values for the anvil
|
||||
val newAmount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem)
|
||||
|
||||
CustomAnvil.verboseLog("new amount is $newAmount")
|
||||
if(newAmount <= 0 || recipe.exactCount){
|
||||
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
||||
}else{
|
||||
val resultItem: ItemStack = recipe.resultItem!!.clone()
|
||||
resultItem.amount *= newAmount
|
||||
|
||||
val newXp = newAmount * newAmount
|
||||
|
||||
inventory.repairCost = newXp
|
||||
event.view.setProperty(InventoryView.Property.REPAIR_COST, newXp)
|
||||
|
||||
inventory.setItem(ANVIL_OUTPUT_SLOT, resultItem)
|
||||
|
||||
player.updateInventory()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
// Test repair cost
|
||||
val repairCost = getUnitRepairCost(inventory, player, leftItem, output, resultCopy, resultAmount)
|
||||
if(repairCost == Int.MIN_VALUE) return
|
||||
|
||||
// If not creative middle click...
|
||||
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_OUTPUT_SLOT, null)
|
||||
player.level -= repairCost
|
||||
}
|
||||
|
||||
// Finally, we add the item to the player
|
||||
if (slotDestination.type == SlotType.CURSOR) {
|
||||
player.setItemOnCursor(output)
|
||||
} else {// We assume SlotType == SlotType.INVENTORY
|
||||
player.inventory.setItem(slotDestination.slot, output)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUnitRepairCost(inventory: AnvilInventory, player: Player,
|
||||
leftItem: ItemStack, output: ItemStack,
|
||||
resultCopy: ItemStack, resultAmount: Int): Int {
|
||||
if (player.gameMode == GameMode.CREATIVE) return 0
|
||||
|
||||
var repairCost = 0;
|
||||
// Get repairCost
|
||||
leftItem.itemMeta?.let { leftMeta ->
|
||||
val leftName = leftMeta.displayName
|
||||
output.itemMeta?.let {
|
||||
// Rename cost
|
||||
if (!leftName.contentEquals(it.displayName)) {
|
||||
repairCost += ConfigOptions.itemRenameCost
|
||||
|
||||
// Color cost
|
||||
if(it.displayName.contains('§')){
|
||||
repairCost += ConfigOptions.useOfColorCost
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repairCost += AnvilXpUtil.calculatePenalty(leftItem, null, resultCopy)
|
||||
repairCost += resultAmount * ConfigOptions.unitRepairCost
|
||||
|
||||
if (
|
||||
!ConfigOptions.doRemoveCostLimit &&
|
||||
ConfigOptions.doCapCost
|
||||
) {
|
||||
repairCost = min(repairCost, ConfigOptions.maxAnvilCost)
|
||||
}
|
||||
|
||||
if ((inventory.maximumRepairCost <= repairCost)
|
||||
|| (player.level < repairCost)
|
||||
) return Int.MIN_VALUE
|
||||
|
||||
return repairCost
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
val inventory = player.inventory
|
||||
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)) {
|
||||
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)) {
|
||||
slotIndex--
|
||||
}
|
||||
if (slotIndex < 9) {
|
||||
return NO_SLOT
|
||||
}
|
||||
return SlotContainer(SlotType.INVENTORY, slotIndex)
|
||||
}
|
||||
else if (player.itemOnCursor.type != Material.AIR) return NO_SLOT
|
||||
return CURSOR_SLOT
|
||||
}
|
||||
|
||||
private class SlotContainer(val type: SlotType, val slot: Int)
|
||||
private enum class SlotType {
|
||||
CURSOR,
|
||||
INVENTORY,
|
||||
NO_SLOT
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
package xyz.alexcrea.cuanvil.listener
|
||||
|
||||
import io.delilaheve.CustomAnvil
|
||||
import io.delilaheve.util.ConfigOptions
|
||||
import io.delilaheve.util.EnchantmentUtil.combineWith
|
||||
import io.delilaheve.util.ItemUtil.canMergeWith
|
||||
import io.delilaheve.util.ItemUtil.findEnchantments
|
||||
import io.delilaheve.util.ItemUtil.isEnchantedBook
|
||||
import io.delilaheve.util.ItemUtil.repairFrom
|
||||
import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe
|
||||
import io.delilaheve.util.ItemUtil.unitRepair
|
||||
import org.bukkit.ChatColor
|
||||
import org.bukkit.entity.HumanEntity
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.EventPriority
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||
import xyz.alexcrea.cuanvil.util.AnvilColorUtil
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
|
||||
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
|
||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||
|
||||
/**
|
||||
* Listener for anvil events
|
||||
*/
|
||||
class PrepareAnvilListener : Listener {
|
||||
|
||||
companion object {
|
||||
|
||||
// Anvil's output slot
|
||||
const val ANVIL_INPUT_LEFT = 0
|
||||
const val ANVIL_INPUT_RIGHT = 1
|
||||
const val ANVIL_OUTPUT_SLOT = 2
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler logic for when an anvil contains items to be combined
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
fun anvilCombineCheck(event: PrepareAnvilEvent) {
|
||||
// Test if the event should bypass custom anvil.
|
||||
if(DependencyManager.tryEventPreAnvilBypass(event)) return
|
||||
|
||||
val inventory = event.inventory
|
||||
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||
val second = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||
|
||||
// Should find player
|
||||
val player = event.view.player
|
||||
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
|
||||
// Test custom recipe
|
||||
if(testCustomRecipe(event, inventory, first, second)) return
|
||||
|
||||
// Test rename lonely item
|
||||
if(second == null) {
|
||||
doRenaming(event, inventory, player, first)
|
||||
return
|
||||
}
|
||||
|
||||
// Test for merge
|
||||
if (first.canMergeWith(second)) {
|
||||
doMerge(event, inventory, player, first, second)
|
||||
return
|
||||
}
|
||||
|
||||
// Test for unit repair
|
||||
if(testUnitRepair(event, inventory, player, first, second)) return
|
||||
|
||||
CustomAnvil.log("no anvil fuse type found")
|
||||
event.result = null
|
||||
|
||||
}
|
||||
|
||||
private fun testCustomRecipe(event: PrepareAnvilEvent, inventory: AnvilInventory, first: ItemStack, second: ItemStack?): Boolean {
|
||||
val recipe = CustomRecipeUtil.getCustomRecipe(first, second)
|
||||
CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}")
|
||||
if(recipe == null) return false
|
||||
|
||||
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, first, second)
|
||||
|
||||
val resultItem: ItemStack = recipe.resultItem!!.clone()
|
||||
resultItem.amount *= amount
|
||||
|
||||
event.result = resultItem
|
||||
AnvilXpUtil.setAnvilInvXp(inventory, event.view, recipe.xpCostPerCraft * amount, true)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun doRenaming(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||
player: HumanEntity, first: ItemStack) {
|
||||
val resultItem = first.clone()
|
||||
var anvilCost = handleRename(resultItem, inventory, player)
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
if (first == resultItem) {
|
||||
CustomAnvil.log("no right item, But input is same as output")
|
||||
event.result = null
|
||||
return
|
||||
}
|
||||
|
||||
event.result = resultItem
|
||||
|
||||
anvilCost += AnvilXpUtil.calculatePenalty(first, null, resultItem)
|
||||
|
||||
AnvilXpUtil.setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
}
|
||||
|
||||
private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory, player: HumanEntity): Int {
|
||||
// Rename item and add renaming cost
|
||||
resultItem.itemMeta?.let {
|
||||
val displayName = ChatColor.stripColor(it.displayName)
|
||||
var inventoryName = ChatColor.stripColor(inventory.renameText)
|
||||
|
||||
var sumCost = 0
|
||||
|
||||
var useColor = false
|
||||
if(ConfigOptions.renameColorPossible){
|
||||
val resultString = StringBuilder(inventoryName)
|
||||
|
||||
useColor = AnvilColorUtil.handleRenamingColor(resultString, player)
|
||||
|
||||
if(useColor) {
|
||||
inventoryName = resultString.toString()
|
||||
|
||||
sumCost+= ConfigOptions.useOfColorCost
|
||||
}
|
||||
}
|
||||
|
||||
if ((!useColor && (!displayName.contentEquals(inventoryName))) || (useColor && !(it.displayName).contentEquals(inventoryName))) {
|
||||
it.setDisplayName(inventoryName)
|
||||
resultItem.itemMeta = it
|
||||
|
||||
sumCost+= ConfigOptions.itemRenameCost
|
||||
}
|
||||
|
||||
return sumCost
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun doMerge(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||
player: HumanEntity,
|
||||
first: ItemStack, second: ItemStack) {
|
||||
val newEnchants = first.findEnchantments()
|
||||
.combineWith(second.findEnchantments(), first, player)
|
||||
val resultItem = first.clone()
|
||||
resultItem.setEnchantmentsUnsafe(newEnchants)
|
||||
|
||||
// Calculate enchantment cost
|
||||
var anvilCost = AnvilXpUtil.getRightValues(second, resultItem)
|
||||
// Calculate repair cost
|
||||
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
|
||||
}
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
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 += AnvilXpUtil.calculatePenalty(first, second, resultItem)
|
||||
// Calculate rename cost
|
||||
anvilCost += handleRename(resultItem, inventory, player)
|
||||
|
||||
// Finally, we set result
|
||||
event.result = resultItem
|
||||
|
||||
AnvilXpUtil.setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
}
|
||||
|
||||
private fun testUnitRepair(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
||||
first: ItemStack, second: ItemStack): Boolean {
|
||||
val unitRepairAmount = first.getRepair(second) ?: return false
|
||||
|
||||
val resultItem = first.clone()
|
||||
var anvilCost = handleRename(resultItem, inventory, player)
|
||||
|
||||
val repairAmount = resultItem.unitRepair(second.amount, unitRepairAmount)
|
||||
if (repairAmount > 0) {
|
||||
anvilCost += repairAmount * ConfigOptions.unitRepairCost
|
||||
}
|
||||
// We do not care about right item penalty for unit repair
|
||||
anvilCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, true)
|
||||
|
||||
// Test/stop if nothing changed.
|
||||
if (first == resultItem) {
|
||||
CustomAnvil.log("unit repair, But input is same as output")
|
||||
event.result = null
|
||||
return true
|
||||
}
|
||||
event.result = resultItem
|
||||
|
||||
AnvilXpUtil.setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
88
src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt
Normal file
88
src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package xyz.alexcrea.cuanvil.util
|
||||
|
||||
import io.delilaheve.util.ConfigOptions
|
||||
import org.bukkit.entity.HumanEntity
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
object AnvilColorUtil {
|
||||
private val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string
|
||||
|
||||
fun handleRenamingColor(textToColor: StringBuilder, player: HumanEntity): Boolean {
|
||||
val usePermission = ConfigOptions.permissionNeededForColor
|
||||
val canUseColorCode = ConfigOptions.allowColorCode && (!usePermission || player.hasPermission("ca.color.code"))
|
||||
val canUseHexColor = ConfigOptions.allowHexadecimalColor && (!usePermission || player.hasPermission("ca.color.hex"))
|
||||
|
||||
if((!canUseColorCode) && (!canUseHexColor)) return false
|
||||
|
||||
var useColor = false
|
||||
// Handle color code
|
||||
if(canUseColorCode){
|
||||
var nbReplacement = replaceAll(textToColor, "&", "§", 2)
|
||||
nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2)
|
||||
|
||||
if(nbReplacement > 0) useColor = true
|
||||
}
|
||||
|
||||
if(canUseHexColor){
|
||||
val nbReplacement = replaceHexToColor(textToColor, 7)
|
||||
|
||||
if(nbReplacement > 0) useColor = true
|
||||
}
|
||||
|
||||
return useColor
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace every instance of "from" to "to".
|
||||
* @param builder The builder to replace the string from.
|
||||
* @param from The source that should be replaced.
|
||||
* @param to The string that should replace.
|
||||
* @param endOffset Amount of character that should be ignored at the end.
|
||||
* @return The number of replacement was that was done.
|
||||
*/
|
||||
private fun replaceAll(builder: java.lang.StringBuilder, from: String, to: String, endOffset: Int): Int {
|
||||
var index = builder.indexOf(from)
|
||||
var numberOfChanges = 0
|
||||
|
||||
while (index != -1 && index < builder.length - endOffset) {
|
||||
builder.replace(index, index + from.length, to)
|
||||
index += to.length
|
||||
index = builder.indexOf(from, index)
|
||||
|
||||
numberOfChanges+=1
|
||||
}
|
||||
|
||||
return numberOfChanges
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace every hex color formatted like #000000 to the minecraft format
|
||||
* @param builder The builder to replace the hex color from.
|
||||
* @param endOffset Amount of character that should be ignored at the end.
|
||||
* @return The number of replacement was that was done.
|
||||
*/
|
||||
private fun replaceHexToColor(builder: StringBuilder, endOffset: Int): Int {
|
||||
val matcher: Matcher = HEX_PATTERN.matcher(builder)
|
||||
|
||||
var numberOfChanges = 0
|
||||
var startIndex = 0
|
||||
|
||||
while(matcher.find(startIndex)){
|
||||
startIndex = matcher.start()
|
||||
if(startIndex >= builder.length - endOffset) break
|
||||
|
||||
builder.replace(startIndex, startIndex + 1, "§x")
|
||||
startIndex+=2
|
||||
for (i in 0..5) {
|
||||
builder.insert(startIndex, '§')
|
||||
startIndex+=2
|
||||
}
|
||||
|
||||
numberOfChanges+=1
|
||||
}
|
||||
|
||||
return numberOfChanges
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package xyz.alexcrea.cuanvil.util
|
||||
|
||||
import io.delilaheve.CustomAnvil
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
|
||||
import kotlin.math.min
|
||||
|
||||
object CustomRecipeUtil {
|
||||
|
||||
fun getCustomRecipe (
|
||||
leftItem: ItemStack,
|
||||
rightItem: ItemStack?) : AnvilCustomRecipe? {
|
||||
|
||||
val recipeList = ConfigHolder.CUSTOM_RECIPE_HOLDER.recipeManager.recipeByMat[leftItem.type] ?: return null
|
||||
|
||||
CustomAnvil.verboseLog("Testing " + recipeList.size + " recipe...")
|
||||
for (recipe in recipeList) {
|
||||
if(recipe.testItem(leftItem, rightItem)){
|
||||
return recipe
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun getCustomRecipeAmount(
|
||||
recipe: AnvilCustomRecipe,
|
||||
leftItem: ItemStack,
|
||||
rightItem: ItemStack?
|
||||
): Int{
|
||||
return if(recipe.exactCount) {
|
||||
if(leftItem.amount != recipe.leftItem!!.amount){
|
||||
0
|
||||
}else if(rightItem != null && rightItem.amount != recipe.rightItem!!.amount){
|
||||
0
|
||||
}else{
|
||||
1
|
||||
}
|
||||
}
|
||||
else {
|
||||
// test amount
|
||||
val resultItem = recipe.resultItem!! // we know exist as the recipe was returned to us
|
||||
val maxResultAmount = resultItem.type.maxStackSize/resultItem.amount
|
||||
val maxLeftAmount = leftItem.amount/recipe.leftItem!!.amount
|
||||
val maxRightAmount = if(rightItem == null){ maxLeftAmount } else{ rightItem.amount/recipe.rightItem!!.amount }
|
||||
|
||||
CustomAnvil.verboseLog("resultItem: $resultItem, maxResultAmount: $maxResultAmount, maxLeftAmount: $maxLeftAmount, maxRightAmount: $maxRightAmount")
|
||||
|
||||
min(min(maxResultAmount, maxLeftAmount), maxRightAmount)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -97,46 +97,46 @@ default_limit: 5
|
|||
#
|
||||
# Valid range of 1 - 255 for each enchantment
|
||||
enchant_limits:
|
||||
aqua_affinity: 1
|
||||
binding_curse: 1
|
||||
channeling: 1
|
||||
flame: 1
|
||||
infinity: 1
|
||||
mending: 1
|
||||
multishot: 1
|
||||
silk_touch: 1
|
||||
vanishing_curse: 1
|
||||
depth_strider: 3 # anything more than 3 is treated as 3 by the game
|
||||
protection: 4
|
||||
fire_protection: 4
|
||||
blast_protection: 4
|
||||
projectile_protection: 4
|
||||
feather_falling: 4
|
||||
thorns: 3
|
||||
respiration: 3
|
||||
sharpness: 5
|
||||
smite: 5
|
||||
bane_of_arthropods: 5
|
||||
knockback: 2
|
||||
fire_aspect: 2
|
||||
looting: 3
|
||||
sweeping: 3
|
||||
sweeping_edge: 3
|
||||
efficiency: 5
|
||||
unbreaking: 3
|
||||
fortune: 3
|
||||
power: 5
|
||||
punch: 2
|
||||
luck_of_the_sea: 3
|
||||
lure: 3
|
||||
frost_walker: 2
|
||||
impaling: 5
|
||||
riptide: 3
|
||||
loyalty: 3
|
||||
piercing: 4
|
||||
quick_charge: 3
|
||||
soul_speed: 3
|
||||
swift_sneak: 3
|
||||
minecraft:aqua_affinity: 1
|
||||
minecraft:binding_curse: 1
|
||||
minecraft:channeling: 1
|
||||
minecraft:flame: 1
|
||||
minecraft:infinity: 1
|
||||
minecraft:mending: 1
|
||||
minecraft:multishot: 1
|
||||
minecraft:silk_touch: 1
|
||||
minecraft:vanishing_curse: 1
|
||||
minecraft:depth_strider: 3 # anything more than 3 is treated as 3 by the game
|
||||
minecraft:protection: 4
|
||||
minecraft:fire_protection: 4
|
||||
minecraft:blast_protection: 4
|
||||
minecraft:projectile_protection: 4
|
||||
minecraft:feather_falling: 4
|
||||
minecraft:thorns: 3
|
||||
minecraft:respiration: 3
|
||||
minecraft:sharpness: 5
|
||||
minecraft:smite: 5
|
||||
minecraft:bane_of_arthropods: 5
|
||||
minecraft:knockback: 2
|
||||
minecraft:fire_aspect: 2
|
||||
minecraft:looting: 3
|
||||
minecraft:sweeping: 3
|
||||
minecraft:sweeping_edge: 3
|
||||
minecraft:efficiency: 5
|
||||
minecraft:unbreaking: 3
|
||||
minecraft:fortune: 3
|
||||
minecraft:power: 5
|
||||
minecraft:punch: 2
|
||||
minecraft:luck_of_the_sea: 3
|
||||
minecraft:lure: 3
|
||||
minecraft:frost_walker: 2
|
||||
minecraft:impaling: 5
|
||||
minecraft:riptide: 3
|
||||
minecraft:loyalty: 3
|
||||
minecraft:piercing: 4
|
||||
minecraft:quick_charge: 3
|
||||
minecraft:soul_speed: 3
|
||||
minecraft:swift_sneak: 3
|
||||
|
||||
# Multipliers used to calculate the enchantment's value in repair/combining
|
||||
#
|
||||
|
|
@ -150,127 +150,138 @@ enchant_limits:
|
|||
# With default values protection 4 would have a value of 4 when
|
||||
# coming from either a book (4 * 1) or an item (4 * 1)
|
||||
enchant_values:
|
||||
aqua_affinity:
|
||||
minecraft:aqua_affinity:
|
||||
item: 4
|
||||
book: 2
|
||||
bane_of_arthropods:
|
||||
minecraft:bane_of_arthropods:
|
||||
item: 2
|
||||
book: 1
|
||||
binding_curse:
|
||||
minecraft:binding_curse:
|
||||
item: 8
|
||||
book: 4
|
||||
blast_protection:
|
||||
minecraft:blast_protection:
|
||||
item: 4
|
||||
book: 2
|
||||
channeling:
|
||||
minecraft:channeling:
|
||||
item: 8
|
||||
book: 4
|
||||
depth_strider:
|
||||
minecraft:depth_strider:
|
||||
item: 4
|
||||
book: 2
|
||||
efficiency:
|
||||
minecraft:efficiency:
|
||||
item: 1
|
||||
book: 1
|
||||
flame:
|
||||
minecraft:flame:
|
||||
item: 4
|
||||
book: 2
|
||||
feather_falling:
|
||||
minecraft:feather_falling:
|
||||
item: 2
|
||||
book: 1
|
||||
fire_aspect:
|
||||
minecraft:fire_aspect:
|
||||
item: 4
|
||||
book: 2
|
||||
fire_protection:
|
||||
minecraft:fire_protection:
|
||||
item: 2
|
||||
book: 1
|
||||
fortune:
|
||||
minecraft:fortune:
|
||||
item: 4
|
||||
book: 2
|
||||
frost_walker:
|
||||
minecraft:frost_walker:
|
||||
item: 4
|
||||
book: 2
|
||||
impaling:
|
||||
minecraft:impaling:
|
||||
item: 4
|
||||
book: 2
|
||||
infinity:
|
||||
minecraft:infinity:
|
||||
item: 8
|
||||
book: 4
|
||||
knockback:
|
||||
minecraft:knockback:
|
||||
item: 2
|
||||
book: 1
|
||||
looting:
|
||||
minecraft:looting:
|
||||
item: 4
|
||||
book: 2
|
||||
loyalty:
|
||||
minecraft:loyalty:
|
||||
item: 1
|
||||
book: 1
|
||||
luck_of_the_sea:
|
||||
minecraft:luck_of_the_sea:
|
||||
item: 4
|
||||
book: 2
|
||||
lure:
|
||||
minecraft:lure:
|
||||
item: 4
|
||||
book: 2
|
||||
mending:
|
||||
minecraft:mending:
|
||||
item: 4
|
||||
book: 2
|
||||
multishot:
|
||||
minecraft:multishot:
|
||||
item: 4
|
||||
book: 2
|
||||
piercing:
|
||||
minecraft:piercing:
|
||||
item: 1
|
||||
book: 1
|
||||
power:
|
||||
minecraft:power:
|
||||
item: 1
|
||||
book: 1
|
||||
projectile_protection:
|
||||
minecraft:projectile_protection:
|
||||
item: 2
|
||||
book: 1
|
||||
protection:
|
||||
minecraft:protection:
|
||||
item: 1
|
||||
book: 1
|
||||
punch:
|
||||
minecraft:punch:
|
||||
item: 4
|
||||
book: 2
|
||||
quick_charge:
|
||||
minecraft:quick_charge:
|
||||
item: 2
|
||||
book: 1
|
||||
respiration:
|
||||
minecraft:respiration:
|
||||
item: 4
|
||||
book: 2
|
||||
riptide:
|
||||
minecraft:riptide:
|
||||
item: 4
|
||||
book: 2
|
||||
silk_touch:
|
||||
minecraft:silk_touch:
|
||||
item: 8
|
||||
book: 4
|
||||
sharpness:
|
||||
minecraft:sharpness:
|
||||
item: 1
|
||||
book: 1
|
||||
smite:
|
||||
minecraft:smite:
|
||||
item: 2
|
||||
book: 1
|
||||
soul_speed:
|
||||
minecraft:soul_speed:
|
||||
item: 8
|
||||
book: 4
|
||||
swift_sneak:
|
||||
minecraft:swift_sneak:
|
||||
item: 8
|
||||
book: 4
|
||||
sweeping:
|
||||
minecraft:sweeping:
|
||||
item: 4
|
||||
book: 2
|
||||
sweeping_edge:
|
||||
minecraft:sweeping_edge:
|
||||
item: 4
|
||||
book: 2
|
||||
thorns:
|
||||
minecraft:thorns:
|
||||
item: 8
|
||||
book: 4
|
||||
unbreaking:
|
||||
minecraft:unbreaking:
|
||||
item: 2
|
||||
book: 1
|
||||
vanishing_curse:
|
||||
minecraft:vanishing_curse:
|
||||
item: 8
|
||||
book: 4
|
||||
|
||||
# Disable enchantment merging for level above the set value
|
||||
# Enchantment merging is when, for example, 2 unbreaking II book combine to give sharpness III
|
||||
# But Enchantment above this value can still be applied. following the previous example, we could still apply a unbreaking III book to a sword
|
||||
# Even if disable-merge-over of unbreaking is set to 2
|
||||
# -1 mean enchantment merge for this enchantment is not disabled. default to -1 if absent.
|
||||
disable-merge-over:
|
||||
# Sharpness is set to -1. it equivalent to it not being set to anything (and work as vanilla)
|
||||
minecraft:sharpness: -1
|
||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||
#minecraft:unbreaking: 2
|
||||
|
||||
# Whether to show debug logging
|
||||
debug_log: false
|
||||
|
||||
|
|
|
|||
|
|
@ -17,158 +17,158 @@
|
|||
# ----------------------------------------------------
|
||||
|
||||
restriction_aqua_affinity:
|
||||
enchantments: [ aqua_affinity ]
|
||||
enchantments: [ minecraft:aqua_affinity ]
|
||||
notAffectedGroups: [ enchanted_book, helmets ]
|
||||
|
||||
restriction_bane_of_arthropods:
|
||||
enchantments: [ bane_of_arthropods ]
|
||||
enchantments: [ minecraft:bane_of_arthropods ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_blast_protection:
|
||||
enchantments: [ blast_protection ]
|
||||
enchantments: [ minecraft:blast_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_channeling:
|
||||
enchantments: [ channeling ]
|
||||
enchantments: [ minecraft:channeling ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_binding_curse:
|
||||
enchantments: [ binding_curse ]
|
||||
enchantments: [ minecraft:binding_curse ]
|
||||
notAffectedGroups: [ enchanted_book, wearable ]
|
||||
|
||||
restriction_vanishing_curse:
|
||||
enchantments: [ vanishing_curse ]
|
||||
enchantments: [ minecraft:vanishing_curse ]
|
||||
notAffectedGroups: [ enchanted_book, can_vanish ]
|
||||
|
||||
restriction_depth_strider:
|
||||
enchantments: [ depth_strider ]
|
||||
enchantments: [ minecraft:depth_strider ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_efficiency:
|
||||
enchantments: [ efficiency ]
|
||||
enchantments: [ minecraft:efficiency ]
|
||||
notAffectedGroups: [ enchanted_book, tools, shears ]
|
||||
|
||||
restriction_feather_falling:
|
||||
enchantments: [ feather_falling ]
|
||||
enchantments: [ minecraft:feather_falling ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_fire_aspect:
|
||||
enchantments: [ fire_aspect ]
|
||||
enchantments: [ minecraft:fire_aspect ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_fire_protection:
|
||||
enchantments: [ fire_protection ]
|
||||
enchantments: [ minecraft:fire_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_flame:
|
||||
enchantments: [ flame ]
|
||||
enchantments: [ minecraft:flame ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_fortune:
|
||||
enchantments: [ fortune ]
|
||||
enchantments: [ minecraft:fortune ]
|
||||
notAffectedGroups: [ enchanted_book, tools ]
|
||||
|
||||
restriction_frost_walker:
|
||||
enchantments: [ frost_walker ]
|
||||
enchantments: [ minecraft:frost_walker ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_impaling:
|
||||
enchantments: [ impaling ]
|
||||
enchantments: [ minecraft:impaling ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_infinity:
|
||||
enchantments: [ infinity ]
|
||||
enchantments: [ minecraft:infinity ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_knockback:
|
||||
enchantments: [ knockback ]
|
||||
enchantments: [ minecraft:knockback ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_looting:
|
||||
enchantments: [ looting ]
|
||||
enchantments: [ minecraft:looting ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
restriction_loyalty:
|
||||
enchantments: [ loyalty ]
|
||||
enchantments: [ minecraft:loyalty ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_lure:
|
||||
enchantments: [ lure ]
|
||||
enchantments: [ minecraft:lure ]
|
||||
notAffectedGroups: [ enchanted_book, fishing_rod ]
|
||||
|
||||
restriction_mending:
|
||||
enchantments: [ mending ]
|
||||
enchantments: [ minecraft:mending ]
|
||||
notAffectedGroups: [ enchanted_book, can_unbreak ]
|
||||
|
||||
restriction_multishot:
|
||||
enchantments: [ multishot ]
|
||||
restriction_minecraft_multishot:
|
||||
enchantments: [ minecraft:multishot ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_piercing:
|
||||
enchantments: [ piercing ]
|
||||
enchantments: [ minecraft:piercing ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_power:
|
||||
enchantments: [ power ]
|
||||
enchantments: [ minecraft:power ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_projectile_protection:
|
||||
enchantments: [ projectile_protection ]
|
||||
enchantments: [ minecraft:projectile_protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_protection:
|
||||
enchantments: [ protection ]
|
||||
enchantments: [ minecraft:protection ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_punch:
|
||||
enchantments: [ punch ]
|
||||
enchantments: [ minecraft:punch ]
|
||||
notAffectedGroups: [ enchanted_book, bow ]
|
||||
|
||||
restriction_quick_charge:
|
||||
enchantments: [ quick_charge ]
|
||||
enchantments: [ minecraft:quick_charge ]
|
||||
notAffectedGroups: [ enchanted_book, crossbow ]
|
||||
|
||||
restriction_respiration:
|
||||
enchantments: [ respiration ]
|
||||
enchantments: [ minecraft:respiration ]
|
||||
notAffectedGroups: [ enchanted_book, helmets ]
|
||||
|
||||
restriction_riptide:
|
||||
enchantments: [ riptide ]
|
||||
enchantments: [ minecraft:riptide ]
|
||||
notAffectedGroups: [ enchanted_book, trident ]
|
||||
|
||||
restriction_sharpness:
|
||||
enchantments: [ sharpness ]
|
||||
enchantments: [ minecraft:sharpness ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_silk_touch:
|
||||
enchantments: [ silk_touch ]
|
||||
restriction__silk_touch:
|
||||
enchantments: [ minecraft:silk_touch ]
|
||||
notAffectedGroups: [ enchanted_book, tools ]
|
||||
|
||||
restriction_smite:
|
||||
enchantments: [ smite ]
|
||||
enchantments: [ minecraft:smite ]
|
||||
notAffectedGroups: [ enchanted_book, melee_weapons ]
|
||||
|
||||
restriction_soul_speed:
|
||||
enchantments: [ soul_speed ]
|
||||
enchantments: [ minecraft:soul_speed ]
|
||||
notAffectedGroups: [ enchanted_book, boots ]
|
||||
|
||||
restriction_sweeping_edge:
|
||||
enchantments: [ sweeping, sweeping_edge ]
|
||||
enchantments: [ minecraft:sweeping, minecraft:sweeping_edge ]
|
||||
notAffectedGroups: [ enchanted_book, swords ]
|
||||
|
||||
# Do not exist in 1.18, that mean useInFuture will be set to true
|
||||
# useInFuture set to true also mean it will not warn if there is an issue
|
||||
restriction_swift_sneak:
|
||||
useInFuture: true
|
||||
enchantments: [ swift_sneak ]
|
||||
enchantments: [ minecraft:swift_sneak ]
|
||||
notAffectedGroups: [ enchanted_book, leggings ]
|
||||
|
||||
restriction_thorns:
|
||||
enchantments: [ thorns ]
|
||||
enchantments: [ minecraft:thorns ]
|
||||
notAffectedGroups: [ enchanted_book, armors ]
|
||||
|
||||
restriction_unbreaking:
|
||||
enchantments: [ unbreaking ]
|
||||
restriction__unbreaking:
|
||||
enchantments: [ minecraft:unbreaking ]
|
||||
notAffectedGroups: [ enchanted_book, can_unbreak ]
|
||||
|
||||
# ----------------------------------------------------
|
||||
|
|
@ -180,60 +180,60 @@ restriction_unbreaking:
|
|||
|
||||
sword_enchant_conflict:
|
||||
enchantments:
|
||||
- bane_of_arthropods
|
||||
- smite
|
||||
- sharpness
|
||||
- minecraft:bane_of_arthropods
|
||||
- minecraft:smite
|
||||
- minecraft:sharpness
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
protection_enchant_conflict:
|
||||
enchantments:
|
||||
- blast_protection
|
||||
- fire_protection
|
||||
- projectile_protection
|
||||
- protection
|
||||
- minecraft:blast_protection
|
||||
- minecraft:fire_protection
|
||||
- minecraft:projectile_protection
|
||||
- minecraft:protection
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
trident_conflict1:
|
||||
enchantments:
|
||||
- channeling
|
||||
- riptide
|
||||
- minecraft:channeling
|
||||
- minecraft:riptide
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
trident_conflict2:
|
||||
enchantments:
|
||||
- loyalty
|
||||
- riptide
|
||||
- minecraft:loyalty
|
||||
- minecraft:riptide
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
boot_conflict:
|
||||
enchantments:
|
||||
- depth_strider
|
||||
- frost_walker
|
||||
- minecraft:depth_strider
|
||||
- minecraft:frost_walker
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
tool_conflict:
|
||||
enchantments:
|
||||
- fortune
|
||||
- silk_touch
|
||||
- minecraft:fortune
|
||||
- minecraft:silk_touch
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
bow_conflict:
|
||||
enchantments:
|
||||
- mending
|
||||
- infinity
|
||||
- minecraft:mending
|
||||
- minecraft:infinity
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
crossbow_conflict:
|
||||
enchantments:
|
||||
- multishot
|
||||
- piercing
|
||||
- minecraft:multishot
|
||||
- minecraft:piercing
|
||||
notAffectedGroups: [ ]
|
||||
maxEnchantmentBeforeConflict: 1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
main: io.delilaheve.CustomAnvil
|
||||
name: CustomAnvil
|
||||
prefix: "Custom Anvil"
|
||||
version: 1.6.2
|
||||
version: 1.6.3
|
||||
folia-supported: true
|
||||
description: Allow to customise anvil mechanics
|
||||
api-version: 1.16
|
||||
|
|
@ -49,8 +49,8 @@ permissions:
|
|||
description: Allow player to use hexadecimal color if permission is required (toggleable)
|
||||
|
||||
|
||||
# soft depend on old name, so I can disable it if it is on the same server
|
||||
# as it is the old name for this plugin
|
||||
# soft depend on old name (UnsafeEnchantsPlus), so I can disable it if it is on the same server (old name for this plugin)
|
||||
# Also depend to other plugin for compatibility
|
||||
softdepend:
|
||||
- UnsafeEnchantsPlus
|
||||
- ProtocolLib
|
||||
|
|
@ -58,3 +58,4 @@ softdepend:
|
|||
- EnchantsSquared
|
||||
- EcoEnchants
|
||||
- eco
|
||||
- ExcellentEnchants
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue