Merge branch 'master' into develop

This commit is contained in:
_OfTeN_ 2023-12-03 03:23:23 +03:00
commit 652fc1ad1f
19 changed files with 175 additions and 119 deletions

View File

@ -0,0 +1,6 @@
group = "com.willfp"
version = rootProject.version
dependencies {
compileOnly("org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT")
}

View File

@ -0,0 +1,26 @@
package com.willfp.ecoenchants.proxy.v1_20_R2
import com.willfp.ecoenchants.enchants.EcoEnchant
import com.willfp.ecoenchants.enchants.EcoEnchants
import com.willfp.ecoenchants.vanilla.VanillaEnchantmentData
import net.minecraft.world.item.enchantment.Enchantment
import org.bukkit.craftbukkit.v1_20_R2.enchantments.CraftEnchantment
class EcoCraftEnchantment(
target: Enchantment,
private val data: VanillaEnchantmentData
) : CraftEnchantment(target) {
override fun getMaxLevel(): Int = data.maxLevel ?: super.getMaxLevel()
override fun conflictsWith(other: org.bukkit.enchantments.Enchantment): Boolean {
if (other is EcoEnchant) {
return other.conflictsWith(this)
}
return data.conflicts?.contains(other.key) ?: super.conflictsWith(other)
}
fun register() {
EcoEnchants.register(this)
}
}

View File

@ -0,0 +1,23 @@
package com.willfp.ecoenchants.proxy.v1_20_R2
import com.willfp.ecoenchants.proxy.proxies.EcoCraftEnchantmentManagerProxy
import com.willfp.ecoenchants.vanilla.VanillaEnchantmentData
import net.minecraft.core.registries.BuiltInRegistries
import org.bukkit.enchantments.Enchantment
class EcoCraftEnchantmentManager : EcoCraftEnchantmentManagerProxy {
override fun registerNewCraftEnchantment(
enchantment: Enchantment,
data: VanillaEnchantmentData
) {
for (enchant in BuiltInRegistries.g) {
val key = org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey.fromMinecraft(
BuiltInRegistries.g.b(enchant)
)
if (key.key != enchantment.key.key) {
continue
}
EcoCraftEnchantment(enchant, data).register()
}
}
}

View File

@ -0,0 +1,11 @@
package com.willfp.ecoenchants.proxy.v1_20_R2
import com.willfp.ecoenchants.proxy.proxies.OpenInventoryProxy
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer
import org.bukkit.entity.Player
class OpenInventory : OpenInventoryProxy {
override fun getOpenInventory(player: Player): Any {
return (player as CraftPlayer).handle.bS
}
}

View File

@ -29,16 +29,13 @@ import com.willfp.ecoenchants.mechanics.GrindstoneSupport
import com.willfp.ecoenchants.mechanics.LootSupport
import com.willfp.ecoenchants.mechanics.VillagerSupport
import com.willfp.ecoenchants.target.EnchantLookup.clearEnchantCache
import com.willfp.ecoenchants.target.EnchantLookup.getActiveEnchantLevel
import com.willfp.ecoenchants.target.EnchantLookup.heldEnchantLevels
import com.willfp.libreforge.EmptyProvidedHolder.holder
import com.willfp.libreforge.NamedValue
import com.willfp.libreforge.ProvidedHolder
import com.willfp.libreforge.loader.LibreforgePlugin
import com.willfp.libreforge.loader.configs.ConfigCategory
import com.willfp.libreforge.registerHolderPlaceholderProvider
import com.willfp.libreforge.registerHolderProvider
import com.willfp.libreforge.registerPlayerRefreshFunction
import com.willfp.libreforge.registerSpecificHolderProvider
import com.willfp.libreforge.registerSpecificRefreshFunction
import org.bukkit.entity.Player
import org.bukkit.event.Listener
@ -61,14 +58,26 @@ class EcoEnchantsPlugin : LibreforgePlugin() {
}
override fun handleEnable() {
registerHolderProvider { it.heldEnchantLevels }
registerPlayerRefreshFunction { it.clearEnchantCache() }
registerSpecificHolderProvider<Player> {
it.heldEnchantLevels
}
registerSpecificRefreshFunction<Player> {
it.clearEnchantCache()
}
registerHolderPlaceholderProvider<FoundEcoEnchantLevel> { it, _ ->
listOf(
NamedValue("level", it.level.level),
NamedValue("active_level", it.activeLevel)
)
}
registerHolderPlaceholderProvider<EcoEnchantLevel> { it, _ ->
listOf(
NamedValue("level", it.level),
)
}
}
override fun handleAfterLoad() {

View File

@ -78,10 +78,10 @@ class EnchantDisplay(private val plugin: EcoEnchantsPlugin) : DisplayModule(plug
val enchantLevel = enchant.getLevel(level)
val holder = ItemProvidedHolder(enchantLevel, itemStack)
val enchantNotMetLines = enchantLevel.conditions.getNotMetLines(player, holder).map { Display.PREFIX + it }
val enchantNotMetLines = holder.getNotMetLines(player).map { Display.PREFIX + it }
notMetLines.addAll(enchantNotMetLines)
if (enchantNotMetLines.isNotEmpty() || enchantLevel.conditions.isShowingAnyNotMet(player, holder)) {
if (enchantNotMetLines.isNotEmpty() || holder.isShowingAnyNotMet(player)) {
showNotMet = true
}
}

View File

@ -26,7 +26,8 @@ object DisplayCache {
data class DisplayableEnchant(
val enchant: EcoEnchantLike,
val level: Int
val level: Int,
val showNotMet: Boolean = false
)
@JvmOverloads
@ -36,7 +37,7 @@ fun EcoEnchantLike.getFormattedName(
): String {
val plugin = EcoEnchantsPlugin.instance
return DisplayCache.nameCache.get(DisplayableEnchant(this, level)) {
return DisplayCache.nameCache.get(DisplayableEnchant(this, level, showNotMet)) {
val numerals = plugin.configYml.getBool("display.numerals.enabled") &&
level <= plugin.configYml.getInt("display.numerals.threshold")
@ -52,15 +53,15 @@ fun EcoEnchantLike.getFormattedName(
val levelOnly = plugin.configYml.getBool("display.above-max-level.level-only")
if (levelOnly) {
StringUtils.format("$notMetFormat$typeFormat$name $format$number")
StringUtils.format("$typeFormat$notMetFormat$name $format$number")
} else {
StringUtils.format("$notMetFormat$format$name $number")
StringUtils.format("$format$notMetFormat$name $number")
}
} else {
if (dontShowNumber) {
StringUtils.format("$notMetFormat$typeFormat$name")
StringUtils.format("$typeFormat$notMetFormat$name")
} else {
StringUtils.format("$notMetFormat$typeFormat$name $number")
StringUtils.format("$typeFormat$notMetFormat$name $number")
}
}
}

View File

@ -1,13 +1,11 @@
package com.willfp.ecoenchants.enchants
import com.github.benmanes.caffeine.cache.Caffeine
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.ConfigType
import com.willfp.eco.core.config.config
import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.config.readConfig
import com.willfp.eco.core.fast.fast
import com.willfp.eco.core.placeholder.PlayerStaticPlaceholder
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder
import com.willfp.eco.core.placeholder.context.PlaceholderContext
import com.willfp.eco.core.placeholder.templates.SimpleInjectablePlaceholder
@ -17,17 +15,14 @@ import com.willfp.ecoenchants.EcoEnchantsPlugin
import com.willfp.ecoenchants.display.getFormattedName
import com.willfp.ecoenchants.mechanics.infiniteIfNegative
import com.willfp.ecoenchants.rarity.EnchantmentRarities
import com.willfp.ecoenchants.target.EnchantLookup.getEnchantLevel
import com.willfp.ecoenchants.target.EnchantmentTargets
import com.willfp.ecoenchants.target.TargetSlot
import com.willfp.ecoenchants.type.EnchantmentTypes
import com.willfp.libreforge.SilentViolationContext
import com.willfp.libreforge.ViolationContext
import com.willfp.libreforge.conditions.ConditionList
import com.willfp.libreforge.conditions.Conditions
import com.willfp.libreforge.conditions.emptyConditionList
import com.willfp.libreforge.effects.EffectList
import com.willfp.libreforge.effects.emptyEffectList
import com.willfp.libreforge.slot.SlotType
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
import org.bukkit.Material
@ -64,7 +59,7 @@ abstract class EcoEnchant(
val targets = config.getStrings("targets")
.mapNotNull { EnchantmentTargets[it] }
val slots: Set<TargetSlot>
val slots: Set<SlotType>
get() = targets.map { it.slot }.toSet()
override val type = EnchantmentTypes[config.getString("type")] ?: EnchantmentTypes.values().first()

View File

@ -5,7 +5,7 @@ import com.willfp.ecoenchants.EcoEnchantsPlugin
import com.willfp.ecoenchants.enchants.EcoEnchant
import com.willfp.ecoenchants.target.EnchantLookup.getActiveEnchantLevelInSlot
import com.willfp.ecoenchants.target.EnchantLookup.hasEnchantActive
import com.willfp.ecoenchants.target.TargetSlot
import com.willfp.libreforge.slot.impl.SlotTypeHands
import org.bukkit.Bukkit
class EnchantmentRepairing(
@ -35,7 +35,7 @@ class EnchantmentRepairing(
continue
}
if (notWhileHolding && slot in TargetSlot.HANDS.getItemSlots(player)) {
if (notWhileHolding && slot in SlotTypeHands.getItemSlots(player)) {
continue
}

View File

@ -1,6 +1,7 @@
package com.willfp.ecoenchants.enchants.impl
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.Prerequisite
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.core.data.keys.PersistentDataKeyType
import com.willfp.eco.core.data.profile
@ -80,6 +81,12 @@ class EnchantmentSoulbound(
event.drops.removeAll(items)
// Use native paper method
if (Prerequisite.HAS_PAPER.isMet) {
event.itemsToKeep += items
return
}
for (item in items) {
item.fast().persistentDataContainer.set(soulboundKey, PersistentDataType.INTEGER, 1)
@ -131,7 +138,9 @@ class EnchantmentSoulbound(
ignoreCancelled = true
)
fun preventDroppingSoulboundItems(event: PlayerDeathEvent) {
event.drops.removeIf { it.fast().persistentDataContainer.has(soulboundKey, PersistentDataType.INTEGER) }
event.drops.removeIf { it.fast().persistentDataContainer.has(soulboundKey, PersistentDataType.INTEGER)
&& it.itemMeta.hasEnchant(enchant)
}
}
}
}

View File

@ -2,9 +2,9 @@ package com.willfp.ecoenchants.libreforge
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.fast.fast
import com.willfp.ecoenchants.enchants.EcoEnchant
import com.willfp.ecoenchants.enchants.wrap
import com.willfp.ecoenchants.type.EnchantmentType
import com.willfp.libreforge.toDispatcher
import com.willfp.libreforge.triggers.Trigger
import com.willfp.libreforge.triggers.TriggerData
import com.willfp.libreforge.triggers.TriggerParameter
@ -35,7 +35,7 @@ class TriggerEnchantType(
.any { it.type == type }
) {
this.dispatch(
player,
player.toDispatcher(),
TriggerData(
player = player,
location = player.location,

View File

@ -3,12 +3,14 @@ package com.willfp.ecoenchants.target
import com.github.benmanes.caffeine.cache.Caffeine
import com.willfp.eco.core.fast.fast
import com.willfp.eco.core.items.HashedItem
import com.willfp.ecoenchants.EcoEnchantsPlugin
import com.willfp.ecoenchants.enchants.EcoEnchant
import com.willfp.ecoenchants.enchants.EcoEnchantLevel
import com.willfp.ecoenchants.enchants.FoundEcoEnchantLevel
import com.willfp.ecoenchants.target.EnchantLookup.getEnchantLevel
import com.willfp.libreforge.ItemProvidedHolder
import com.willfp.libreforge.ProvidedHolder
import com.willfp.libreforge.slot.SlotType
import com.willfp.libreforge.slot.SlotTypes
import com.willfp.libreforge.toDispatcher
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import java.util.concurrent.TimeUnit
@ -17,18 +19,15 @@ import java.util.concurrent.TimeUnit
typealias SlotProvider = (Player) -> Map<ItemInNumericSlot, ItemInSlot>
data class ItemInSlot internal constructor(
val item: ItemStack,
val slot: Collection<TargetSlot>
val item: ItemStack, val slot: Collection<SlotType>
) {
constructor(
item: ItemStack,
slot: TargetSlot
item: ItemStack, slot: SlotType
) : this(item, listOf(slot))
}
data class ItemInNumericSlot internal constructor(
val item: ItemStack,
val slot: Int
val item: ItemStack, val slot: Int
) {
override fun hashCode(): Int {
return HashedItem.of(item).hash * (slot + 1)
@ -36,24 +35,20 @@ data class ItemInNumericSlot internal constructor(
}
private data class HeldEnchant(
val enchant: EcoEnchant,
val level: Int
val enchant: EcoEnchant, val level: Int
)
object EnchantLookup {
private val slotProviders = mutableSetOf<SlotProvider>()
private val itemCache = Caffeine.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build<Player, Map<ItemInNumericSlot, ItemInSlot>>()
private val itemCache =
Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS).build<Player, Map<ItemInNumericSlot, ItemInSlot>>()
private val enchantCache = Caffeine.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
private val enchantCache = Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.SECONDS)
.build<Player, Map<ItemInNumericSlot, Collection<HeldEnchant>>>()
// Higher frequency cache as less intensive
private val enchantLevelCache = Caffeine.newBuilder()
.expireAfterWrite(200, TimeUnit.MILLISECONDS)
private val enchantLevelCache = Caffeine.newBuilder().expireAfterWrite(200, TimeUnit.MILLISECONDS)
.build<Player, Map<ItemInNumericSlot, Map<EcoEnchant, Int>>>()
@JvmStatic
@ -119,8 +114,8 @@ object EnchantLookup {
}
// Basically a multimap
found[slotID] = (found.getOrDefault(slotID, mutableListOf())
+ HeldEnchant(enchant, level)).toMutableList()
found[slotID] =
(found.getOrDefault(slotID, mutableListOf()) + HeldEnchant(enchant, level)).toMutableList()
}
}
@ -182,7 +177,7 @@ object EnchantLookup {
for ((enchant, level) in enchants) {
val enchantLevel = enchant.getLevel(level)
val providedHolder = ItemProvidedHolder(enchantLevel, slot.item)
if (enchantLevel.conditions.areMet(this, providedHolder)) {
if (enchantLevel.conditions.areMet(this.toDispatcher(), providedHolder)) {
inSlot[enchant] = level
}
}
@ -252,7 +247,7 @@ object EnchantLookup {
val item = this.inventory.getItem(slot) ?: return 0
val providedHolder = ItemProvidedHolder(enchantLevel, item)
if (!enchantLevel.conditions.areMet(this, providedHolder)) {
if (!enchantLevel.conditions.areMet(this.toDispatcher(), providedHolder)) {
return 0
}
@ -307,13 +302,16 @@ object EnchantLookup {
// This is such a fucking disgusting way of implementing %active_level%,
// and it's probably quite slow too.
return found.map {
val level = it.holder as EcoEnchantLevel
return if (EcoEnchantsPlugin.instance.configYml.getBool("extra-placeholders.active-level")) {
found.map {
val level = it.holder as EcoEnchantLevel
ItemProvidedHolder(
FoundEcoEnchantLevel(level, this.getActiveEnchantLevel(level.enchant)),
it.provider
)
ItemProvidedHolder(
FoundEcoEnchantLevel(level, this.getActiveEnchantLevel(level.enchant)), it.provider
)
}
} else {
found
}
}
@ -327,22 +325,20 @@ object EnchantLookup {
}
init {
fun createProvider(slot: TargetSlot): SlotProvider {
fun createProvider(slot: SlotType): SlotProvider {
return { player: Player ->
val found = mutableMapOf<ItemInNumericSlot, ItemInSlot>()
for (slotID in slot.getItemSlots(player)) {
val item = player.inventory.getItem(slotID) ?: continue
found[
ItemInNumericSlot(item, slotID)
] = ItemInSlot(item, slot)
found[ItemInNumericSlot(item, slotID)] = ItemInSlot(item, slot)
}
found
}
}
for (slot in TargetSlot.values()) {
for (slot in SlotTypes.values()) {
registerProvider(createProvider(slot))
}
}

View File

@ -6,14 +6,18 @@ import com.willfp.eco.core.items.TestableItem
import com.willfp.eco.core.recipe.parts.EmptyTestableItem
import com.willfp.eco.core.registry.Registrable
import com.willfp.ecoenchants.EcoEnchantsPlugin
import com.willfp.libreforge.slot.SlotType
import com.willfp.libreforge.slot.SlotTypes
import com.willfp.libreforge.slot.impl.SlotTypeAny
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import java.lang.IllegalArgumentException
import java.util.Objects
interface EnchantmentTarget : Registrable {
val id: String
val displayName: String
val slot: TargetSlot
val slot: SlotType
val items: List<TestableItem>
fun matches(itemStack: ItemStack): Boolean {
@ -36,7 +40,8 @@ class ConfiguredEnchantmentTarget(
override val id = config.getString("id")
override val displayName = config.getFormattedString("display-name")
override val slot = TargetSlot.valueOf(config.getString("slot").uppercase())
override val slot = SlotTypes[config.getString("slot")] ?:
throw IllegalArgumentException("Invalid slot type: ${config.getString("slot")}, options are ${SlotTypes.values().map { it.id }}")
override val items = config.getStrings("items")
.map { Items.lookup(it) }
@ -58,7 +63,7 @@ class ConfiguredEnchantmentTarget(
internal object AllEnchantmentTarget : EnchantmentTarget {
override val id = "all"
override val displayName = EcoEnchantsPlugin.instance.langYml.getFormattedString("all")
override val slot = TargetSlot.ANY
override val slot = SlotTypeAny
override var items = emptyList<TestableItem>()
private set
@ -72,36 +77,3 @@ internal object AllEnchantmentTarget : EnchantmentTarget {
return other is AllEnchantmentTarget
}
}
enum class TargetSlot(
private val itemSlotGetter: (Player) -> Collection<Int>
) {
HAND({
listOf(
it.inventory.heldItemSlot
)
}),
OFFHAND({
listOf(
40 // Offhand slot.
)
}),
HANDS({
listOf(
it.inventory.heldItemSlot,
40
)
}),
ARMOR({
(36..39).toList()
}),
ANY({
(0..45).toList()
});
fun getItemSlots(player: Player): Collection<Int> = itemSlotGetter(player)
}

View File

@ -72,7 +72,7 @@ display:
enabled: true # If enchantments should be collapsed in lore
threshold: 9 # Above this amount, enchantments will be collapsed
per-line: 2 # The amount of enchantments to put in each line
delimiter: ", " # The delimiter between enchantments
delimiter: ",&r " # The delimiter between enchantments
descriptions:
enabled: true # If enchantment descriptions should be shown in lore
@ -166,3 +166,9 @@ enchant-gui:
lore-conversion:
enabled: false # If lore conversion should be enabled
aggressive: false # Will convert all items in all inventories when opened, likely to use a lot of performance
# Extra placeholders for enchantment configs
extra-placeholders:
# Enable or disable %active_level% placeholder.
# It's disabled by default to save CPU time, enable if you want to use it.
active-level: false

View File

@ -21,6 +21,6 @@ effects:
triggers:
- bow_attack
filters:
only_bosses: true
is_boss: true
conditions: [ ]

View File

@ -41,6 +41,6 @@ effects:
cooldown: 60
send_cooldown_message: true
triggers:
- alt_click
- click_block
conditions: []

View File

@ -10,18 +10,19 @@ extra-enchantable-items:
- "*player_head"
# A target consists of items and a slot.
# The slot is either hands, hand, offhand, armor, or any.
# hands: Enchant will activate in both hands
# hand: Enchant will activate only in main hand
# offhand: Enchant will activate only in off hand
# armor: Enchant will activate only on armor
# any: Enchant will activate whenever it's in your inventory
# The options for slot are mainhand, offhand, hands, helmet, chestplate,
# leggings, boots, armor, any, a number from 0-40 (to specify an exact slot),
# or a list of slots like "9, 10, 11, mainhand"
# The slot defines when the enchantment will activate, for example if you have
# a target with slot "mainhand", the enchantment will activate whenever the item is
# in your mainhand.
targets:
- id: pickaxe
display-name: "Pickaxes"
slot: hand
slot: mainhand
items:
- "*wooden_pickaxe"
- "*stone_pickaxe"
@ -32,7 +33,7 @@ targets:
- id: axe
display-name: "Axes"
slot: hand
slot: mainhand
items:
- "*wooden_axe"
- "*stone_axe"
@ -43,7 +44,7 @@ targets:
- id: hoe
display-name: "Hoes"
slot: hand
slot: mainhand
items:
- "*wooden_hoe"
- "*stone_hoe"
@ -54,7 +55,7 @@ targets:
- id: shovel
display-name: "Shovels"
slot: hand
slot: mainhand
items:
- "*wooden_shovel"
- "*stone_shovel"
@ -65,7 +66,7 @@ targets:
- id: sword
display-name: "Swords"
slot: hand
slot: mainhand
items:
- "*wooden_sword"
- "*stone_sword"
@ -151,25 +152,25 @@ targets:
- id: trident
display-name: "Tridents"
slot: hand
slot: mainhand
items:
- "*trident"
- id: bow
display-name: "Bows"
slot: hand
slot: mainhand
items:
- "*bow"
- id: crossbow
display-name: "Crossbows"
slot: hand
slot: mainhand
items:
- "*crossbow"
- id: shears
display-name: "Shears"
slot: hand
slot: mainhand
items:
- "*shears"
@ -181,19 +182,19 @@ targets:
- id: fishing_rod
display-name: "Fishing Rods"
slot: hand
slot: mainhand
items:
- "*fishing_rod"
- id: flint_and_steel
display-name: "Flint and Steels"
slot: hand
slot: mainhand
items:
- "*flint_and_steel"
- id: carrot_on_a_stick
display-name: "Carrots on Sticks"
slot: hand
slot: mainhand
items:
- "*carrot_on_a_stick"

View File

@ -1,5 +1,5 @@
#libreforge-updater
#Wed Jul 12 13:08:18 BST 2023
#Thu Nov 30 14:28:00 GMT 2023
kotlin.code.style=official
libreforge-version=4.22.1
version=10.23.1
libreforge-version=4.47.0
version=10.49.0

View File

@ -20,3 +20,4 @@ include(":eco-core:core-nms:v1_19_R1")
include(":eco-core:core-nms:v1_19_R2")
include(":eco-core:core-nms:v1_19_R3")
include(":eco-core:core-nms:v1_20_R1")
include(":eco-core:core-nms:v1_20_R2")