17 Commits
1.1.0 ... 1.3.0

Author SHA1 Message Date
Auxilor
b969c3e054 libreforge-updater 2024-07-21 12:19:28 +01:00
Auxilor
140eab592e Added scroll tag 2024-07-21 11:15:53 +01:00
Auxilor
0c24d6be21 libreforge-updater 2024-07-19 20:28:49 +01:00
Auxilor
281e605ce1 libreforge-updater 2024-07-18 13:24:24 +01:00
Will FP
95438d151f Added resource ID 2024-07-18 11:38:47 +01:00
Auxilor
d2a00f3c2d Added customItem 2024-07-17 19:01:57 +01:00
Auxilor
18c7635232 Added per-target scroll limits 2024-07-17 18:16:33 +01:00
Auxilor
a17c412a5c Changed placeholder format, improved hot potato books 2024-07-17 18:04:52 +01:00
Auxilor
5c62b3b467 Added hot potato book example 2024-07-17 17:46:49 +01:00
Auxilor
bef67355a6 Fixed inscribe_item 2024-07-17 17:08:14 +01:00
Auxilor
8f8036a518 Minor codestyle improvements 2024-07-17 16:58:58 +01:00
Auxilor
3fe0a8071d Fixed several effect bugs 2024-07-17 16:09:39 +01:00
Auxilor
de7339ac84 Improved _example.yml 2024-07-17 15:02:05 +01:00
Auxilor
e902c65dd0 Added /ecoscrolls inscribe 2024-07-08 18:59:52 +01:00
Auxilor
9207babde5 Minor codestyle 2024-07-08 18:46:48 +01:00
Auxilor
8919ab0d2a Rewrote how scroll uses are tracked 2024-07-08 18:45:58 +01:00
Will FP
776abef5e2 Update gradle.properties 2024-07-08 15:59:33 +01:00
20 changed files with 313 additions and 75 deletions

View File

@@ -39,7 +39,7 @@ allprojects {
dependencies { dependencies {
implementation("com.willfp:ecomponent:1.4.1") implementation("com.willfp:ecomponent:1.4.1")
compileOnly("com.willfp:eco:6.71.0") compileOnly("com.willfp:eco:6.73.0")
compileOnly("org.jetbrains:annotations:23.0.0") compileOnly("org.jetbrains:annotations:23.0.0")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.20") compileOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.20")
compileOnly("com.github.ben-manes.caffeine:caffeine:3.1.5") compileOnly("com.github.ben-manes.caffeine:caffeine:3.1.5")

View File

@@ -3,6 +3,7 @@ package com.willfp.ecoscrolls
import com.willfp.eco.core.command.impl.PluginCommand import com.willfp.eco.core.command.impl.PluginCommand
import com.willfp.eco.core.display.DisplayModule import com.willfp.eco.core.display.DisplayModule
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.items.Items
import com.willfp.eco.core.placeholder.context.PlaceholderContext import com.willfp.eco.core.placeholder.context.PlaceholderContext
import com.willfp.eco.core.placeholder.templates.DynamicPlaceholder import com.willfp.eco.core.placeholder.templates.DynamicPlaceholder
import com.willfp.ecoscrolls.commands.CommandEcoScrolls import com.willfp.ecoscrolls.commands.CommandEcoScrolls
@@ -17,6 +18,7 @@ import com.willfp.ecoscrolls.libreforge.TriggerInscribe
import com.willfp.ecoscrolls.libreforge.TriggerTryInscribe import com.willfp.ecoscrolls.libreforge.TriggerTryInscribe
import com.willfp.ecoscrolls.scrolls.InscriptionHandler import com.willfp.ecoscrolls.scrolls.InscriptionHandler
import com.willfp.ecoscrolls.scrolls.ScrollLevel import com.willfp.ecoscrolls.scrolls.ScrollLevel
import com.willfp.ecoscrolls.scrolls.ScrollTag
import com.willfp.ecoscrolls.scrolls.Scrolls import com.willfp.ecoscrolls.scrolls.Scrolls
import com.willfp.ecoscrolls.target.ScrollFinder import com.willfp.ecoscrolls.target.ScrollFinder
import com.willfp.ecoscrolls.target.Targets import com.willfp.ecoscrolls.target.Targets
@@ -54,6 +56,8 @@ class EcoScrollsPlugin : LibreforgePlugin() {
Triggers.register(TriggerInscribe) Triggers.register(TriggerInscribe)
Triggers.register(TriggerTryInscribe) Triggers.register(TriggerTryInscribe)
Items.registerTag(ScrollTag(this))
registerHolderProvider(ScrollFinder.toHolderProvider()) registerHolderProvider(ScrollFinder.toHolderProvider())
registerHolderPlaceholderProvider<ScrollLevel> { it, _ -> registerHolderPlaceholderProvider<ScrollLevel> { it, _ ->
@@ -63,7 +67,7 @@ class EcoScrollsPlugin : LibreforgePlugin() {
} }
PlaceholderManager.registerPlaceholder( PlaceholderManager.registerPlaceholder(
object : DynamicPlaceholder(plugin, Pattern.compile("scroll_([a-z]+)_([a-zA-Z0-9_]+)")) { object : DynamicPlaceholder(plugin, Pattern.compile("scroll_([a-z0-9_]+):([a-zA-Z0-9_]+)")) {
override fun getValue(args: String, context: PlaceholderContext): String? { override fun getValue(args: String, context: PlaceholderContext): String? {
val matcher = pattern.matcher(args) val matcher = pattern.matcher(args)

View File

@@ -13,6 +13,7 @@ class CommandEcoScrolls(plugin: EcoPlugin) : PluginCommand(
init { init {
this.addSubcommand(CommandReload(plugin)) this.addSubcommand(CommandReload(plugin))
.addSubcommand(CommandGive(plugin)) .addSubcommand(CommandGive(plugin))
.addSubcommand(CommandInscribeDirect(plugin))
} }
override fun onExecute(sender: CommandSender, args: List<String>) { override fun onExecute(sender: CommandSender, args: List<String>) {

View File

@@ -5,6 +5,7 @@ import com.willfp.eco.core.command.impl.Subcommand
import com.willfp.eco.core.drops.DropQueue import com.willfp.eco.core.drops.DropQueue
import com.willfp.eco.core.items.Items.toSNBT import com.willfp.eco.core.items.Items.toSNBT
import com.willfp.eco.core.items.toSNBT import com.willfp.eco.core.items.toSNBT
import com.willfp.eco.util.StringUtils
import com.willfp.ecoscrolls.scrolls.Scrolls import com.willfp.ecoscrolls.scrolls.Scrolls
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.command.CommandSender import org.bukkit.command.CommandSender
@@ -65,9 +66,9 @@ class CommandGive(
.forceTelekinesis() .forceTelekinesis()
.push() .push()
val message = plugin.langYml.getMessage("give-success") val message = plugin.langYml.getMessage("give-success", StringUtils.FormatOption.WITHOUT_PLACEHOLDERS)
.replace("%scroll%", scroll.name) .replace("%scroll%", scroll.name)
.replace("%recipient%", reciever.name) .replace("%player%", reciever.name)
sender.sendMessage(message) sender.sendMessage(message)
} }

View File

@@ -0,0 +1,92 @@
package com.willfp.ecoscrolls.commands
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.command.impl.Subcommand
import com.willfp.eco.util.StringUtils
import com.willfp.eco.util.savedDisplayName
import com.willfp.ecoscrolls.scrolls.Scrolls
import com.willfp.ecoscrolls.scrolls.getScrollLevel
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.util.StringUtil
class CommandInscribeDirect(
plugin: EcoPlugin
) : Subcommand(
plugin,
"inscribe",
"ecoscrolls.command.incscribedirect",
false
) {
override fun onExecute(sender: CommandSender, rawArgs: List<String>) {
var args = rawArgs
var player = sender as? Player
if (sender !is Player) {
player = notifyPlayerRequired(args.getOrNull(0), "invalid-player")
args = rawArgs.subList(1, rawArgs.size)
}
if (player == null) {
return
}
val scroll = notifyNull(
args.getOrNull(0)?.lowercase()?.let { Scrolls[it] },
"invalid-scroll"
)
val item = player.inventory.itemInMainHand
val level = args.getOrNull(1)?.toIntOrNull() ?: 1
val currentLevel = item.getScrollLevel(scroll)?.level ?: 0
val levelsToAdd = level - currentLevel
repeat(levelsToAdd) {
scroll.inscribe(item)
}
sender.sendMessage(
plugin.langYml.getMessage("inscribed-item", StringUtils.FormatOption.WITHOUT_PLACEHOLDERS)
.replace("%scroll%", scroll.name)
.replace("%player%", player.savedDisplayName)
)
}
override fun tabComplete(sender: CommandSender, rawArgs: List<String>): List<String> {
val completions = mutableListOf<String>()
var args = rawArgs
if (sender !is Player) {
args = rawArgs.subList(1, rawArgs.size)
}
if (args.size == 1) {
StringUtil.copyPartialMatches(
args[0],
Scrolls.values().map { it.id },
completions
)
}
if (args.size == 2) {
val scroll = Scrolls[args[0].lowercase()]
val levels = if (scroll != null) {
val maxLevel = scroll.maxLevel
(0..maxLevel).toList()
} else {
(0..5).toList()
}
StringUtil.copyPartialMatches(
args[1],
levels.map { it.toString() },
completions
)
}
return completions
}
}

View File

@@ -58,12 +58,12 @@ internal fun updateInscribeMenu(plugin: EcoScrollsPlugin) {
val violationContext = ViolationContext(plugin, "Inscription Table") val violationContext = ViolationContext(plugin, "Inscription Table")
val openEffects = Effects.compile( val openEffects = Effects.compileChain(
plugin.configYml.getSubsections("gui.open-effects"), plugin.configYml.getSubsections("gui.open-effects"),
violationContext.with("Open Effects") violationContext.with("Open Effects")
) )
val closeEffects = Effects.compile( val closeEffects = Effects.compileChain(
plugin.configYml.getSubsections("gui.close-effects"), plugin.configYml.getSubsections("gui.close-effects"),
violationContext.with("Close Effects") violationContext.with("Close Effects")
) )
@@ -139,13 +139,13 @@ internal fun updateInscribeMenu(plugin: EcoScrollsPlugin) {
} }
onOpen { player, _ -> onOpen { player, _ ->
openEffects.trigger(TriggerData(player = player).dispatch(player.toDispatcher())) openEffects?.trigger(player.toDispatcher(), TriggerData(player = player))
} }
onClose { event, menu -> onClose { event, menu ->
val player = event.player as Player val player = event.player as Player
closeEffects.trigger(TriggerData(player = player).dispatch(player.toDispatcher())) closeEffects?.trigger(player.toDispatcher(), TriggerData(player = player))
DropQueue(player) DropQueue(player)
.addItems(menu.getCaptiveItems(player)) .addItems(menu.getCaptiveItems(player))
@@ -299,10 +299,5 @@ private class AllowSlot(plugin: EcoScrollsPlugin) : MenuSlot(plugin, Inscription
} }
} }
private class DenySlot(plugin: EcoScrollsPlugin) : MenuSlot(plugin, InscriptionStatus.DENY) { private class DenySlot(plugin: EcoScrollsPlugin) : MenuSlot(plugin, InscriptionStatus.DENY)
private class EmptySlot(plugin: EcoScrollsPlugin) : MenuSlot(plugin, InscriptionStatus.EMPTY)
}
private class EmptySlot(plugin: EcoScrollsPlugin) : MenuSlot(plugin, InscriptionStatus.EMPTY) {
}

View File

@@ -15,16 +15,14 @@ import com.willfp.libreforge.triggers.TriggerData
import com.willfp.libreforge.triggers.TriggerParameter import com.willfp.libreforge.triggers.TriggerParameter
object EffectInscribeItem : Effect<NoCompileData>("inscribe_item") { object EffectInscribeItem : Effect<NoCompileData>("inscribe_item") {
override val parameters = setOf( override val isPermanent = false
TriggerParameter.ITEM
)
override val arguments = arguments { override val arguments = arguments {
require("scroll", "You must specify the scroll!") require("scroll", "You must specify the scroll!")
} }
override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean { override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean {
val item = data.item ?: return false val item = data.foundItem ?: return false
val scroll = Scrolls[config.getString("scroll")] ?: return false val scroll = Scrolls[config.getString("scroll")] ?: return false

View File

@@ -3,34 +3,37 @@ package com.willfp.ecoscrolls.scrolls
import com.willfp.ecoscrolls.EcoScrollsPlugin import com.willfp.ecoscrolls.EcoScrollsPlugin
import com.willfp.ecoscrolls.scrolls.event.ScrollInscribeEvent import com.willfp.ecoscrolls.scrolls.event.ScrollInscribeEvent
import com.willfp.ecoscrolls.scrolls.event.ScrollTryInscribeEvent import com.willfp.ecoscrolls.scrolls.event.ScrollTryInscribeEvent
import com.willfp.ecoscrolls.target.Targets.targets
import com.willfp.libreforge.NamedValue import com.willfp.libreforge.NamedValue
import com.willfp.libreforge.ViolationContext import com.willfp.libreforge.ViolationContext
import com.willfp.libreforge.effects.EffectList import com.willfp.libreforge.effects.Chain
import com.willfp.libreforge.effects.Effects import com.willfp.libreforge.effects.Effects
import com.willfp.libreforge.toDispatcher import com.willfp.libreforge.toDispatcher
import com.willfp.libreforge.triggers.TriggerData import com.willfp.libreforge.triggers.TriggerData
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.Optional
import kotlin.math.min
class InscriptionHandler(private val plugin: EcoScrollsPlugin) { class InscriptionHandler(private val plugin: EcoScrollsPlugin) {
private lateinit var applyEffects: EffectList private lateinit var applyEffects: Optional<Chain>
private lateinit var denyEffects: EffectList private lateinit var denyEffects: Optional<Chain>
val scrollLimit = plugin.configYml.getInt("inscription.scroll-limit") private val globalScrollLimit = plugin.configYml.getInt("inscription.scroll-limit")
.let { if (it <= 0) Int.MAX_VALUE else it } .let { if (it <= 0) Int.MAX_VALUE else it }
internal fun reload() { internal fun reload() {
val context = ViolationContext(plugin, "Inscriptions") val context = ViolationContext(plugin, "Inscriptions")
applyEffects = Effects.compile( applyEffects = Optional.ofNullable(Effects.compileChain(
plugin.configYml.getSubsections("inscription.apply-effects"), plugin.configYml.getSubsections("inscription.apply-effects"),
context.with("Apply Effects") context.with("Apply Effects")
) ))
denyEffects = Effects.compile( denyEffects = Optional.ofNullable(Effects.compileChain(
plugin.configYml.getSubsections("inscription.deny-effects"), plugin.configYml.getSubsections("inscription.deny-effects"),
context.with("Deny Effects") context.with("Deny Effects")
) ))
} }
private fun inscriptionTrigger(item: ItemStack, scroll: Scroll, player: Player) = private fun inscriptionTrigger(item: ItemStack, scroll: Scroll, player: Player) =
@@ -72,14 +75,33 @@ class InscriptionHandler(private val plugin: EcoScrollsPlugin) {
val didInscribe = scroll.inscribe(item, player) val didInscribe = scroll.inscribe(item, player)
if (didInscribe) { if (didInscribe) {
applyEffects.trigger(inscriptionTrigger(item, scroll, player)) applyEffects.ifPresent {
it.trigger(inscriptionTrigger(item, scroll, player))
}
val event = ScrollInscribeEvent(player, scroll, item) val event = ScrollInscribeEvent(player, scroll, item)
plugin.server.pluginManager.callEvent(event) plugin.server.pluginManager.callEvent(event)
} else { } else {
denyEffects.trigger(inscriptionTrigger(item, scroll, player)) denyEffects.ifPresent {
it.trigger(inscriptionTrigger(item, scroll, player))
}
} }
return didInscribe return didInscribe
} }
fun getScrollLimit(item: ItemStack): Int {
val targets = item.targets
var highest = Int.MAX_VALUE
for (target in targets) {
val limit = target.scrollLimit ?: continue
if (limit < highest) {
highest = limit
}
}
return min(highest, globalScrollLimit)
}
} }

View File

@@ -9,7 +9,7 @@ import org.bukkit.persistence.PersistentDataContainer
import org.bukkit.persistence.PersistentDataType import org.bukkit.persistence.PersistentDataType
private val SCROLL_KEY = plugin.createNamespacedKey("scroll") private val SCROLL_KEY = plugin.createNamespacedKey("scroll")
private val SCROLL_USES_KEY = plugin.createNamespacedKey("scroll_uses") private val SCROLL_USES_LEFT_KEY = plugin.createNamespacedKey("scroll_uses_left")
private val SCROLLS_KEY = plugin.createNamespacedKey("scrolls") private val SCROLLS_KEY = plugin.createNamespacedKey("scrolls")
private val SCROLL_ID_KEY = plugin.createNamespacedKey("scroll") private val SCROLL_ID_KEY = plugin.createNamespacedKey("scroll")
private val SCROLL_LEVEL_KEY = plugin.createNamespacedKey("level") private val SCROLL_LEVEL_KEY = plugin.createNamespacedKey("level")
@@ -40,37 +40,39 @@ var PersistentDataContainer.scroll: Scroll?
this.set(SCROLL_KEY, PersistentDataType.STRING, value.id) this.set(SCROLL_KEY, PersistentDataType.STRING, value.id)
} }
var ItemStack.scrollUses: Int var ItemStack.scrollUsesLeft: Int
get() = this.fast().scrollUses get() = this.fast().scrollUsesLeft
set(value) { set(value) {
this.fast().scrollUses = value this.fast().scrollUsesLeft = value
} }
var FastItemStack.scrollUses: Int var FastItemStack.scrollUsesLeft: Int
get() = this.persistentDataContainer.scrollUses get() = this.persistentDataContainer.scrollUsesLeft
set(value) { set(value) {
this.persistentDataContainer.scrollUses = value this.persistentDataContainer.scrollUsesLeft = value
} }
var PersistentDataContainer.scrollUses: Int var PersistentDataContainer.scrollUsesLeft: Int
get() { get() {
return this.get(SCROLL_USES_KEY, PersistentDataType.INTEGER) ?: 0 return this.get(SCROLL_USES_LEFT_KEY, PersistentDataType.INTEGER) ?: 0
} }
set(value) { set(value) {
if (value == 0) { if (value == 0) {
this.remove(SCROLL_USES_KEY) this.remove(SCROLL_USES_LEFT_KEY)
return return
} }
this.set(SCROLL_USES_KEY, PersistentDataType.INTEGER, value) this.set(SCROLL_USES_LEFT_KEY, PersistentDataType.INTEGER, value)
} }
fun ItemStack.useScroll() { fun ItemStack.useScroll() {
val scroll = this.scroll ?: return if (this.scroll == null) {
return
}
this.scrollUses++ this.scrollUsesLeft--
if (this.scrollUses >= scroll.maxUses) { if (this.scrollUsesLeft <= 0) {
this.amount-- this.amount--
} }
} }

View File

@@ -4,6 +4,7 @@ import com.willfp.eco.core.config.interfaces.Config
import com.willfp.eco.core.display.Display import com.willfp.eco.core.display.Display
import com.willfp.eco.core.fast.FastItemStack import com.willfp.eco.core.fast.FastItemStack
import com.willfp.eco.core.fast.fast import com.willfp.eco.core.fast.fast
import com.willfp.eco.core.items.CustomItem
import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.Items
import com.willfp.eco.core.placeholder.InjectablePlaceholder import com.willfp.eco.core.placeholder.InjectablePlaceholder
import com.willfp.eco.core.placeholder.PlaceholderInjectable import com.willfp.eco.core.placeholder.PlaceholderInjectable
@@ -13,7 +14,6 @@ import com.willfp.eco.core.placeholder.templates.DynamicInjectablePlaceholder
import com.willfp.eco.core.price.ConfiguredPrice import com.willfp.eco.core.price.ConfiguredPrice
import com.willfp.eco.core.recipe.Recipes import com.willfp.eco.core.recipe.Recipes
import com.willfp.eco.core.registry.KRegistrable import com.willfp.eco.core.registry.KRegistrable
import com.willfp.eco.util.evaluateExpression
import com.willfp.eco.util.evaluateExpressionOrNull import com.willfp.eco.util.evaluateExpressionOrNull
import com.willfp.eco.util.formatEco import com.willfp.eco.util.formatEco
import com.willfp.eco.util.toNumeral import com.willfp.eco.util.toNumeral
@@ -29,7 +29,6 @@ import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.Objects import java.util.Objects
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.math.max
class Scroll( class Scroll(
plugin: EcoScrollsPlugin, plugin: EcoScrollsPlugin,
@@ -65,12 +64,19 @@ class Scroll(
fis.scroll = this fis.scroll = this
fis.displayName = itemName.formatEco() fis.displayName = itemName.formatEco()
fis.lore = itemLore.formatEco().map { Display.PREFIX + it } + fis.lore fis.lore = itemLore.formatEco().map { Display.PREFIX + it } + fis.lore
fis.scrollUsesLeft = maxUses
fis.unwrap() fis.unwrap()
} }
val item: ItemStack val item: ItemStack
get() = _item.clone() get() = _item.clone()
val customItem = CustomItem(
plugin.createNamespacedKey("scroll_$id"),
{ it.scroll == this },
_item
).apply { register() }
val recipe = if (config.getBool("item.craftable")) Recipes.createAndRegisterRecipe( val recipe = if (config.getBool("item.craftable")) Recipes.createAndRegisterRecipe(
plugin, plugin,
id, id,
@@ -98,7 +104,7 @@ class Scroll(
context.with("inscription conditions") context.with("inscription conditions")
) )
private val inscriptionEffects = Effects.compile( private val inscriptionEffects = Effects.compileChain(
config.getSubsections("inscription.effects"), config.getSubsections("inscription.effects"),
context.with("inscription effects") context.with("inscription effects")
) )
@@ -131,15 +137,15 @@ class Scroll(
private val usesLeftPlaceholder = object : DynamicInjectablePlaceholder(Pattern.compile("uses_left")) { private val usesLeftPlaceholder = object : DynamicInjectablePlaceholder(Pattern.compile("uses_left")) {
override fun getValue(p0: String, p1: PlaceholderContext): String? { override fun getValue(p0: String, p1: PlaceholderContext): String? {
val item = p1.itemStack ?: return null val item = p1.itemStack ?: return null
val scroll = item.scroll ?: return null return item.scrollUsesLeft.toString()
return (scroll.maxUses - item.scrollUses).toString()
} }
} }
private val usesPlaceholder = object : DynamicInjectablePlaceholder(Pattern.compile("uses")) { private val usesPlaceholder = object : DynamicInjectablePlaceholder(Pattern.compile("uses")) {
override fun getValue(p0: String, p1: PlaceholderContext): String? { override fun getValue(p0: String, p1: PlaceholderContext): String? {
val item = p1.itemStack ?: return null val item = p1.itemStack ?: return null
return item.scrollUses.toString() val scroll = item.scroll ?: return null
return (scroll.maxUses - item.scrollUsesLeft).toString()
} }
} }
@@ -187,7 +193,7 @@ class Scroll(
val currentScrolls = itemStack.scrolls val currentScrolls = itemStack.scrolls
if (currentScrolls.size >= plugin.inscriptionHandler.scrollLimit) { if (currentScrolls.size >= plugin.inscriptionHandler.getScrollLimit(itemStack)) {
return false return false
} }
@@ -231,12 +237,13 @@ class Scroll(
inscribe(itemStack) inscribe(itemStack)
inscriptionEffects.trigger( inscriptionEffects?.trigger(
player.toDispatcher(),
TriggerData( TriggerData(
player = player, player = player,
item = itemStack, item = itemStack,
value = itemStack.getScrollLevel(this)?.level?.toDouble() ?: 1.0 value = itemStack.getScrollLevel(this)?.level?.toDouble() ?: 1.0
).dispatch(player.toDispatcher()) )
) )
return true return true

View File

@@ -0,0 +1,15 @@
package com.willfp.ecoscrolls.scrolls
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.items.tag.CustomItemTag
import org.bukkit.inventory.ItemStack
class ScrollTag(plugin: EcoPlugin) : CustomItemTag(plugin.createNamespacedKey("scroll")) {
override fun matches(p0: ItemStack): Boolean {
return p0.scroll != null
}
override fun getExampleItem(): ItemStack? {
return Scrolls.values().randomOrNull()?.item
}
}

View File

@@ -17,6 +17,7 @@ interface Target : Registrable {
val displayName: String val displayName: String
val slot: SlotType val slot: SlotType
val items: List<TestableItem> val items: List<TestableItem>
val scrollLimit: Int?
fun matches(itemStack: ItemStack): Boolean { fun matches(itemStack: ItemStack): Boolean {
for (item in items) { for (item in items) {
@@ -45,6 +46,8 @@ class ConfiguredTarget(
.map { Items.lookup(it) } .map { Items.lookup(it) }
.filterNot { it is EmptyTestableItem } .filterNot { it is EmptyTestableItem }
override val scrollLimit = config.getIntOrNull("scroll-limit")
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is Target) { if (other !is Target) {
return false return false
@@ -64,6 +67,7 @@ internal object AllTarget : Target {
override val slot = SlotTypeAny override val slot = SlotTypeAny
override var items = emptyList<TestableItem>() override var items = emptyList<TestableItem>()
private set private set
override val scrollLimit = null
fun updateItems() { fun updateItems() {
items = Targets.values() items = Targets.values()

View File

@@ -5,9 +5,6 @@ import com.willfp.eco.core.items.HashedItem
import com.willfp.eco.core.registry.Registry import com.willfp.eco.core.registry.Registry
import com.willfp.ecoscrolls.EcoScrollsPlugin import com.willfp.ecoscrolls.EcoScrollsPlugin
import com.willfp.ecoscrolls.plugin import com.willfp.ecoscrolls.plugin
import com.willfp.ecoscrolls.scrolls.Scroll
import com.willfp.ecoscrolls.scrolls.Scrolls
import org.bukkit.Material
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@@ -23,14 +20,9 @@ object Targets : Registry<Target>() {
.filter { it.matches(item) } .filter { it.matches(item) }
} }
val ItemStack.isModifiable: Boolean val ItemStack.targets: List<Target>
get() = modifiableCache.get(HashedItem.of(this)) { get() = targetsCache.get(HashedItem.of(this)) {
getForItem(this).isNotEmpty() || this.type == Material.BOOK || this.type == Material.ENCHANTED_BOOK getForItem(this)
}
val ItemStack.applicableScrolls: List<Scroll>
get() = canModifyCache.get(HashedItem.of(this)) {
Scrolls.values().filter { it.canInscribe(this) }
} }
internal fun update(plugin: EcoScrollsPlugin) { internal fun update(plugin: EcoScrollsPlugin) {
@@ -49,10 +41,6 @@ object Targets : Registry<Target>() {
} }
} }
private val modifiableCache = Caffeine.newBuilder() private val targetsCache = Caffeine.newBuilder()
.expireAfterAccess(5, TimeUnit.SECONDS) .expireAfterAccess(5, TimeUnit.SECONDS)
.build<HashedItem, Boolean>() .build<HashedItem, List<Target>>()
private val canModifyCache = Caffeine.newBuilder()
.expireAfterAccess(5, TimeUnit.SECONDS)
.build<HashedItem, List<Scroll>>()

View File

@@ -3,6 +3,6 @@ environment:
value: ${libreforgeVersion} value: ${libreforgeVersion}
options: options:
resource-id: 0 resource-id: 6131
bstats-id: 22538 bstats-id: 22538
color: "&#1e3c72" color: "&#1e3c72"

View File

@@ -10,4 +10,4 @@ messages:
needs-scroll: "&cYou must specify a scroll!" needs-scroll: "&cYou must specify a scroll!"
invalid-player: "&cYou must specify a player!" invalid-player: "&cYou must specify a player!"
invalid-scroll: "&cYou must specify a scroll!" invalid-scroll: "&cYou must specify a scroll!"
give-success: "Gave %scroll%&r to %recipient%&r!" give-success: "Gave %scroll%&r to %player%&r!"

View File

@@ -32,6 +32,7 @@ permissions:
ecoscrolls.command.reload: true ecoscrolls.command.reload: true
ecoscrolls.command.inscribe: true ecoscrolls.command.inscribe: true
ecoscrolls.command.give: true ecoscrolls.command.give: true
ecoscrolls.command.inscribedirect: true
ecoscrolls.command.reload: ecoscrolls.command.reload:
description: Allows reloading the config description: Allows reloading the config
@@ -44,3 +45,7 @@ permissions:
ecoscrolls.command.inscribe: ecoscrolls.command.inscribe:
description: Allows opening the inscription table with /inscribe description: Allows opening the inscription table with /inscribe
default: true default: true
ecoscrolls.command.inscribedirect:
description: Allows directly inscribing an item with /ecoscrolls inscribe
default: op

View File

@@ -22,6 +22,8 @@ item:
lore: lore:
- "&7This is an example scroll." - "&7This is an example scroll."
- "&7It does nothing." - "&7It does nothing."
# Options for crafting, read here: https://plugins.auxilor.io/all-plugins/the-item-lookup-system#crafting-recipes
craftable: false craftable: false
recipe: [ ] recipe: [ ]
@@ -32,6 +34,8 @@ inscription:
conditions: [ ] conditions: [ ]
# The effects that will be run when the item is inscribed # The effects that will be run when the item is inscribed
# If your scroll works by modifying the item (e.g. adding enchantments, changing durability),
# then put those effects here.
effects: [ ] effects: [ ]
# Read https://plugins.auxilor.io/all-plugins/prices # Read https://plugins.auxilor.io/all-plugins/prices
@@ -73,7 +77,8 @@ lore:
- "&6Example Scroll" - "&6Example Scroll"
# Item placeholders for dynamic lore in plugins like EcoItems # Item placeholders for dynamic lore in plugins like EcoItems
# The placeholder is %ecoscrolls_scroll_<scroll>_<placeholder>% # The placeholder is %ecoscrolls_scroll_<scroll>:<placeholder>%, e.g.
# %ecoscrolls_scroll_example:bonus%
placeholders: placeholders:
bonus: "%level% * 2" bonus: "%level% * 2"

View File

@@ -0,0 +1,94 @@
# The ID of the scroll is the name of the .yml file,
# for example coins_on_kill.yml has the ID of coins_on_kill
# You can place scrolls anywhere in this folder,
# including in subfolders if you want to organize your scroll configs
# _example.yml is not loaded.
# The name of the scroll
name: "&cHot Potato Book"
max-level: 10
max-uses: 1
item:
item: book unbreaking:1 hide_enchants
name: "&cHot Potato Book"
lore:
- "&7When inscribed on armor, grants"
- "&f+2 %ecoskills_defense_name% &7and &f+1 %ecoskills_health_name%&7."
- ""
- "&7When inscribed to weapons, grants"
- "&f+2 %ecoskills_strength_name% &7and &f+4 %ecoskills_crit_damage_name%&7."
- ""
- "&7This can be inscribed up to &a10 &7times"
- "&7on an item!"
craftable: false
recipe: [ ]
inscription:
conditions: [ ]
effects: [ ]
price:
value: 100
type: coins
display: "&e%value% coins"
price-level-multiplier: "1 + %level% * 0.5"
drag-and-drop: false
inscription-table: true
targets:
- sword
- axe
- armor
placeholders:
# For EcoItems items, use %ecoscrolls_scroll_hot_potato_book:defense% in lore
defense: "&8(&e+{^{%level% * 2}}&8)"
# Same as above, but for health / strength / crit_damage
health: "&8(&e+{^{%level%}}&8)"
strength: "&8(&e+{^{%level% * 2}}&8)"
crit_damage: "&8(&e+{^{%level% * 4}}&8)"
effects:
# Armor effects
- id: add_stat
args:
stat: defense
amount: "%level% * 2"
conditions:
- id: in_slot
args:
slot: armor
- id: add_stat
args:
stat: health
amount: "%level%"
conditions:
- id: in_slot
args:
slot: armor
# Weapon effects
- id: add_stat
args:
stat: strength
amount: "%level% * 2"
conditions:
- id: in_slot
args:
slot: mainhand
- id: add_stat
args:
stat: crit_damage
amount: "%level% * 4"
conditions:
- id: in_slot
args:
slot: mainhand
conditions: [ ]

View File

@@ -8,10 +8,15 @@
# a target with slot "mainhand", the scroll will activate whenever the item is # a target with slot "mainhand", the scroll will activate whenever the item is
# in your mainhand. # in your mainhand.
# You can also specify a scroll limit for a target, for example you can limit
# pickaxes to only have 3 scrolls inscribed on them.
# If an item has multiple targets, the lowest limit will be used.
targets: targets:
- id: pickaxe - id: pickaxe
display-name: "Pickaxes" display-name: "Pickaxes"
slot: mainhand slot: mainhand
# scroll-limit: 10 # Example of a scroll limit
items: items:
- "*wooden_pickaxe" - "*wooden_pickaxe"
- "*stone_pickaxe" - "*stone_pickaxe"

View File

@@ -1,5 +1,5 @@
#libreforge-updater #libreforge-updater
#Mon Jul 08 15:58:38 BST 2024 #Sun Jul 21 12:19:28 BST 2024
kotlin.code.style=official kotlin.code.style=official
libreforge-version=4.65.0 libreforge-version=4.69.0
version=1.1.0 version=1.3.0