Skip to content

Commit

Permalink
Merge pull request #17 from iGabyTM/add-custom-requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
iGabyTM authored Feb 1, 2023
2 parents da9e667 + 345f248 commit bca1b68
Show file tree
Hide file tree
Showing 30 changed files with 726 additions and 27 deletions.
10 changes: 10 additions & 0 deletions plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ repositories {
name 'TimeAPI'
url 'https://repo.piggypiglet.me/releases'
}

maven {
url 'https://repo.extendedclip.com/content/repositories/placeholderapi/'
}
}

dependencies {
Expand All @@ -34,6 +38,9 @@ dependencies {
compileOnly 'me.gabytm.util:actions-core:1.0.0-SNAPSHOT'
implementation('me.gabytm.util:actions-spigot:1.0.0-SNAPSHOT') { exclude group: 'com.google.guava' }

// Requirements
implementation 'me.gabytm.minecraft.util:requirements-bukkit:1.0.0-SNAPSHOT'

compileOnly('com.github.MilkBowl:VaultAPI:1.7') { transitive false }

// NBT
Expand Down Expand Up @@ -62,6 +69,9 @@ dependencies {

// Other dependencies that don't have a repository or the release is old
compileOnly fileTree(dir: './libs', includes: ['*.jar'])

// PAPI
compileOnly 'me.clip:placeholderapi:2.10.10'
}

compileKotlin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import me.gabytm.minecraft.arcanevouchers.listeners.VoucherUseListener
import me.gabytm.minecraft.arcanevouchers.message.Lang
import me.gabytm.minecraft.arcanevouchers.other.ResourcesHandler
import me.gabytm.minecraft.arcanevouchers.voucher.VoucherManager
import me.gabytm.minecraft.arcanevouchers.voucher.requirements.ArcaneRequirementProcessor
import net.kyori.adventure.platform.bukkit.BukkitAudiences
import org.bukkit.Bukkit
import org.bukkit.plugin.java.JavaPlugin
Expand All @@ -29,6 +30,7 @@ class ArcaneVouchers : JavaPlugin() {
lateinit var actionManager: ArcaneActionManager private set
lateinit var itemCreator: ItemCreator private set
lateinit var voucherManager: VoucherManager private set
lateinit var requirementProcessor: ArcaneRequirementProcessor private set

private fun sendLogo() {
with (description) {
Expand Down Expand Up @@ -62,6 +64,7 @@ class ArcaneVouchers : JavaPlugin() {
this.actionManager = ArcaneActionManager(this)
this.itemCreator = ItemCreator(this)
this.voucherManager = VoucherManager(this)
this.requirementProcessor = ArcaneRequirementProcessor(actionManager)

reload()
CommandManager(this) // register the commands
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ object Constant {

}

object Requirement {

const val TYPE: String = "type"
const val OPTIONAL: String = "optional"
const val NEGATION: Char = '!'
const val FAIL_ACTIONS: String = "failActions"

}

object Separator {

val COLON = Regex(":")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class MessageAction(meta: ActionMeta<Player>, handler: PermissionHandler) : Arca
private val messageType: MessageType = meta.getProperty("type", MessageType.CHAT) { MessageType.find(it) }
private val broadcast: Broadcast = Broadcast.parse(meta.properties["broadcast"])

@Transient
private val times: Title.Times = Title.Times.times(
parseDuration("fadeIn", Title.DEFAULT_TIMES.fadeIn()),
parseDuration("stay", Title.DEFAULT_TIMES.stay()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import me.gabytm.minecraft.arcanevouchers.ArcaneVouchers
import me.gabytm.minecraft.arcanevouchers.Constant
import me.gabytm.minecraft.arcanevouchers.commands.ArcaneCommand
import me.gabytm.minecraft.arcanevouchers.functions.exception
import me.gabytm.minecraft.arcanevouchers.io.serializers.java.PatternSerializer
import me.gabytm.minecraft.arcanevouchers.io.serializers.adventure.TextComponentSerializer
import me.gabytm.minecraft.arcanevouchers.io.serializers.bukkit.LocationSerializer
import me.gabytm.minecraft.arcanevouchers.message.implementations.ActionBarMessage
import me.gabytm.minecraft.arcanevouchers.message.implementations.ChatMessage
import me.gabytm.minecraft.arcanevouchers.message.implementations.TitleMessage
Expand All @@ -14,8 +17,8 @@ import me.gabytm.minecraft.arcanevouchers.voucher.settings.VoucherSettings
import me.mattstudios.mf.annotations.Permission
import me.mattstudios.mf.annotations.SubCommand
import net.kyori.adventure.text.TextComponent
import net.kyori.adventure.text.minimessage.MiniMessage
import org.bukkit.Bukkit
import org.bukkit.Location
import org.bukkit.command.CommandSender
import java.io.IOException
import java.io.InputStreamReader
Expand All @@ -42,6 +45,7 @@ class DebugCommand(plugin: ArcaneVouchers) : ArcaneCommand(plugin) {
.registerTypeAdapter(TextComponent::class.java, TextComponentSerializer())
.registerTypeAdapter(Voucher::class.java, VoucherSerializer.INSTANCE)
.registerTypeAdapter(Pattern::class.java, PatternSerializer())
.registerTypeAdapter(Location::class.java, LocationSerializer.INSTANCE)
// Messages
.registerTypeAdapter(ActionBarMessage::class.java, ActionBarMessage.Serializer.INSTANCE)
.registerTypeAdapter(ChatMessage::class.java, ChatMessage.Serializer.INSTANCE)
Expand Down Expand Up @@ -156,20 +160,4 @@ class DebugCommand(plugin: ArcaneVouchers) : ArcaneCommand(plugin) {

}

internal class TextComponentSerializer : JsonSerializer<TextComponent> {

override fun serialize(src: TextComponent?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
return if (src == null) JsonNull.INSTANCE else JsonPrimitive(MiniMessage.miniMessage().serialize(src))
}

}

internal class PatternSerializer : JsonSerializer<Pattern> {

override fun serialize(src: Pattern?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
return JsonPrimitive(src?.pattern())
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import java.nio.file.Files

class Config(plugin: ArcaneVouchers, path: String, isResource: Boolean = true) {

@Transient
private val file = File(plugin.dataFolder, path)
var yaml: YamlConfiguration
private set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package me.gabytm.minecraft.arcanevouchers.functions

import com.google.common.base.Enums
import com.google.common.primitives.Ints
import me.clip.placeholderapi.PlaceholderAPI
import me.gabytm.minecraft.arcanevouchers.Constant
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.format.TextDecoration
import net.md_5.bungee.api.ChatColor
import org.apache.commons.lang.StringUtils
import org.bukkit.Bukkit
import org.bukkit.Color
import org.bukkit.OfflinePlayer
import sh.okx.timeapi.TimeAPI
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern
Expand Down Expand Up @@ -36,6 +39,14 @@ fun String.mini(removeItalic: Boolean = false): Component {
}
}

fun String.papi(player: OfflinePlayer?): String {
return if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
PlaceholderAPI.setPlaceholders(player, this)
} else {
this
}
}

fun Array<String>.toArgsMap(): MutableMap<String, String> {
if (isEmpty()) {
return mutableMapOf()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.gabytm.minecraft.arcanevouchers.io.serializers.adventure

import com.google.gson.*
import net.kyori.adventure.text.TextComponent
import net.kyori.adventure.text.minimessage.MiniMessage
import java.lang.reflect.Type

class TextComponentSerializer : JsonSerializer<TextComponent> {

override fun serialize(src: TextComponent?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
return if (src == null) JsonNull.INSTANCE else JsonPrimitive(MiniMessage.miniMessage().serialize(src))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package me.gabytm.minecraft.arcanevouchers.io.serializers.bukkit

import com.google.gson.*
import org.bukkit.Location
import java.lang.reflect.Type

class LocationSerializer : JsonSerializer<Location> {

override fun serialize(src: Location?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
if (src == null) {
return JsonNull.INSTANCE
}

val element = JsonObject()
element.addProperty("world", src.world?.name)
element.addProperty("x", src.x)
element.addProperty("y", src.y)
element.addProperty("z", src.z)
return element
}

companion object {

val INSTANCE = LocationSerializer()

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.gabytm.minecraft.arcanevouchers.io.serializers.java

import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import java.lang.reflect.Type
import java.util.regex.Pattern

class PatternSerializer : JsonSerializer<Pattern> {

override fun serialize(src: Pattern?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
return JsonPrimitive(src?.pattern())
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import me.gabytm.minecraft.arcanevouchers.ServerVersion
import me.gabytm.minecraft.arcanevouchers.functions.*
import me.gabytm.minecraft.arcanevouchers.limit.LimitType
import me.gabytm.minecraft.arcanevouchers.voucher.Voucher
import me.gabytm.minecraft.util.requirements.Arguments
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.entity.Player
Expand Down Expand Up @@ -203,6 +204,10 @@ class VoucherUseListener(private val plugin: ArcaneVouchers) : Listener {
return
}

if (!settings.requirementsList.check(player, Arguments.of(emptyMap()))) {
return
}

val isBulk = settings.bulkOpen.enabled && player.isSneaking

if (settings.confirmationEnabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import me.gabytm.minecraft.arcanevouchers.functions.warning
import net.kyori.adventure.bossbar.BossBar
import net.kyori.adventure.sound.Sound
import org.bukkit.Bukkit
import org.bukkit.DyeColor
import org.bukkit.Material
import org.bukkit.block.banner.PatternType
import org.bukkit.configuration.file.YamlConfiguration
Expand Down Expand Up @@ -47,7 +48,7 @@ class ResourcesHandler(plugin: ArcaneVouchers) {
}

create("DyeColors") {
it["list"] = Constant.NAMED_COLORS.keys.toList().sorted()
it["list"] = DyeColor.values().map { it.name }.sorted()
}

// For some reason, on versions <= 1.12.2, the first value of the array is null (???)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import me.gabytm.minecraft.arcanevouchers.functions.debug
import me.gabytm.minecraft.arcanevouchers.functions.item
import me.gabytm.minecraft.arcanevouchers.items.ItemCreator
import me.gabytm.minecraft.arcanevouchers.limit.LimitType
import me.gabytm.minecraft.arcanevouchers.voucher.requirements.ArcaneRequirementProcessor
import me.gabytm.minecraft.arcanevouchers.voucher.settings.VoucherSettings
import org.bukkit.Material
import org.bukkit.configuration.ConfigurationSection
Expand Down Expand Up @@ -179,9 +180,12 @@ class Voucher private constructor(

companion object {

fun from(config: ConfigurationSection, actionManager: ArcaneActionManager, itemCreator: ItemCreator): Voucher {
fun from(
config: ConfigurationSection, actionManager: ArcaneActionManager,
itemCreator: ItemCreator, requirementProcessor: ArcaneRequirementProcessor
): Voucher {
val id = config.name
val settings = VoucherSettings.from(config.getConfigurationSection("settings"))
val settings = VoucherSettings.from(config.getConfigurationSection("settings"), requirementProcessor)
val item = itemCreator.create(true, config.getConfigurationSection("item"), Material.PAPER).apply {
val nbtItem = NBTItem(this, true)
val compound = nbtItem.getOrCreateCompound(NBT.VOUCHER_COMPOUND)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class VoucherManager(private val plugin: ArcaneVouchers) {
}

val section = vouchersSection.getConfigurationSection(it) ?: continue
this.loadedVouchers[it] = Voucher.from(section, plugin.actionManager, plugin.itemCreator)
this.loadedVouchers[it] = Voucher.from(section, plugin.actionManager, plugin.itemCreator, plugin.requirementProcessor)
}

info("Loaded ${this.loadedVouchers.size} voucher(s): ${this.loadedVouchers.keys.joinToString(", ")}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package me.gabytm.minecraft.arcanevouchers.voucher.requirements

import me.gabytm.minecraft.arcanevouchers.actions.ArcaneAction
import me.gabytm.minecraft.arcanevouchers.actions.ArcaneActionManager
import me.gabytm.minecraft.util.requirements.Requirement
import org.bukkit.entity.Player

abstract class ArcaneRequirement(
name: String,
optional: Boolean,
negated: Boolean,
@Transient private val failActions: List<ArcaneAction>,
@Transient private val actionManager: ArcaneActionManager
// A requirement can not be 'optional' and 'required' at the same time
// So we consider a requirement 'required' if it is not 'optional'
) : Requirement<Player>(name, !optional, optional, negated) {

@Suppress("unused")
protected val requirementType: String = this::class.java.simpleName

override fun onFail(player: Player?) {
if (player != null && failActions.isNotEmpty()) {
actionManager.executeActions(player, failActions)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package me.gabytm.minecraft.arcanevouchers.voucher.requirements

import me.gabytm.minecraft.arcanevouchers.actions.ArcaneActionManager
import me.gabytm.minecraft.util.requirements.RequirementFactory
import org.bukkit.configuration.ConfigurationSection

abstract class ArcaneRequirementFactory<R : ArcaneRequirement> : RequirementFactory<ConfigurationSection, R> {

override fun create(source: ConfigurationSection): R? = null

abstract fun create(source: ConfigurationSection, actionManager: ArcaneActionManager): R?

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package me.gabytm.minecraft.arcanevouchers.voucher.requirements

import me.gabytm.minecraft.arcanevouchers.actions.ArcaneActionManager
import me.gabytm.minecraft.arcanevouchers.voucher.requirements.implementations.location.DistanceRequirementFactory
import me.gabytm.minecraft.arcanevouchers.voucher.requirements.implementations.number.NumberRequirementFactory
import me.gabytm.minecraft.arcanevouchers.voucher.requirements.implementations.string.StringRequirementFactory
import me.gabytm.minecraft.util.requirements.RequirementsList
import me.gabytm.minecraft.util.requirements.bukkit.BukkitRequirementProcessor
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.entity.Player

class ArcaneRequirementProcessor(private val actionManager: ArcaneActionManager) : BukkitRequirementProcessor<Player>() {

private val requirementFactories = mutableSetOf<ArcaneRequirementFactory<out ArcaneRequirement>>()

init {
// Location
registerFactory(DistanceRequirementFactory())

registerFactory(NumberRequirementFactory())
registerFactory(StringRequirementFactory())
}

private fun createRequirement(source: ConfigurationSection): ArcaneRequirement? {
return requirementFactories.firstOrNull { it.matches(source) }?.create(source, actionManager)
}

fun registerFactory(factory: ArcaneRequirementFactory<out ArcaneRequirement>) {
requirementFactories.add(factory)
}

fun processRequirements(root: ConfigurationSection?): RequirementsList<ArcaneRequirement, Player> {
if (root == null) {
return RequirementsList(emptyList())
}

val minimumRequirements = root.getInt("minimumRequirements", RequirementsList.ALL_REQUIREMENTS)
val requirementsSection = root.getConfigurationSection("list") ?: return RequirementsList(emptyList())
val requirements = mutableListOf<ArcaneRequirement>()

for (name in requirementsSection.getKeys(false)) {
val section = requirementsSection.getConfigurationSection(name) ?: continue
val requirement = createRequirement(section) ?: continue
requirements.add(requirement)
}

return RequirementsList(requirements, minimumRequirements)
}

}
Loading

0 comments on commit bca1b68

Please sign in to comment.