diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b18ad38d..3c2519ad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,6 +52,32 @@ jobs: - name: Build with Gradle run: ./gradlew clean assemble publishToMavenLocal + upload: + runs-on: ubuntu-latest + needs: build + timeout-minutes: 30 + + name: Create Artifacts + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + cache: 'gradle' + - name: Change Permissions + run: chmod +x ./gradlew + - name: Build with Gradle + run: ./gradlew clean assemble + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: battlecards + path: | + plugin/build/libs/*.jar + api/build/libs/*.jar + analyze: runs-on: ubuntu-latest needs: build diff --git a/README.md b/README.md index 6a76669c..f6b46546 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,19 @@ This plugin is built in Kotlin. While the plugin will automatically download the ## 📓Changelog +📖 **v1.1.0** - January 2, 2024 | Generation II +- 3 new Generation II Cards +- New Card Equipment +- Turkish Translation +- **Card & Equipment Catalogue** + - View useful information & crafting recipes about all cards & card equipment +- Release of the [official guide](https://guide.battlecards.gamercoder215.me) +- Equipment Drops from Normal Entities +- Piglin Bartering for Equipment & Card Shards (1.16+) +- Decrease BASIC and COMMON Max Experience Requirements +- Minor Bug Fixes + - Added Missing Translations + 🛠️ v1.0.2 - December 2, 2023 - Dependency Updates - 10+ New Card Equipments diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/CardAnnotations.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/CardAnnotations.kt index d01ae92f..4b2e133f 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/CardAnnotations.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/CardAnnotations.kt @@ -44,7 +44,7 @@ enum class CardAttribute( MAX_HEALTH(25_000_000.0), ATTACK_DAMAGE(3_500_000.0), DEFENSE(2_000_000.0), - SPEED(0.45), + SPEED(1.05), KNOCKBACK_RESISTANCE, FOLLOW_RANGE(1024.0) diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/ICard.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/ICard.kt index 24c9fd24..179115ef 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/ICard.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/ICard.kt @@ -57,6 +57,9 @@ class ICard( override fun spawnCard(owner: Player): IBattleCard<*> = spawnCard(owner, itemStack) + override val isRideable: Boolean + get() = entityCardClass.isAnnotationPresent(Rideable::class.java) + fun spawnCard(owner: Player, itemUsed: ItemStack): IBattleCard<*> { if (owner.spawnedCards.size >= BattleConfig.config.maxCardsSpawned) throw IllegalStateException("Player already has ${BattleConfig.config.maxCardsSpawned} spawned cards") @@ -131,8 +134,9 @@ class ICard( private const val serialVersionUID: Long = 193409138419023815L - @JvmStatic - fun fromByteArray(array: ByteArray): ICard { + fun fromByteArray(array: ByteArray): ICard? { + if (array.isEmpty()) return null + val bIs = ByteArrayInputStream(array) val iS = BukkitObjectInputStream(BufferedInputStream(bIs)) val card = iS.readObject() as ICard @@ -141,7 +145,6 @@ class ICard( return card } - @JvmStatic fun deserialize(map: Map): ICard { val clazz = Class.forName(map["clazz"] as String).asSubclass(BattleCard::class.java) val type = BattleCardType.valueOf((map["type"] as String).uppercase()) diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBattleCard.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBattleCard.kt index e008b3ce..e5eae059 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBattleCard.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBattleCard.kt @@ -4,7 +4,10 @@ import me.gamercoder215.battlecards.api.BattleConfig import me.gamercoder215.battlecards.api.card.BattleCard import me.gamercoder215.battlecards.api.card.item.CardEquipment.Potion import me.gamercoder215.battlecards.api.events.entity.CardUseAbilityEvent -import me.gamercoder215.battlecards.impl.* +import me.gamercoder215.battlecards.impl.IBattleStatistics +import me.gamercoder215.battlecards.impl.ICard +import me.gamercoder215.battlecards.impl.Passive +import me.gamercoder215.battlecards.impl.UnlockedAt import me.gamercoder215.battlecards.util.* import me.gamercoder215.battlecards.wrapper.Wrapper.Companion.w import me.gamercoder215.battlecards.wrapper.commands.CommandWrapper.Companion.getError @@ -28,13 +31,10 @@ abstract class IBattleCard( ) : BattleCard { companion object { - @JvmStatic val spawned: MutableMap> = mutableMapOf() - @JvmStatic fun byEntity(entity: Creature): IBattleCard<*>? = spawned[entity.uniqueId] - @JvmStatic fun byMinion(minion: LivingEntity): IBattleCard<*>? { spawned.forEach { (_, card) -> if (card.minions.any { it.uniqueId == minion.uniqueId }) @@ -276,7 +276,10 @@ abstract class IBattleCard( get() = data.statistics final override val isRideable: Boolean - get() = this::class.java.isAnnotationPresent(Rideable::class.java) + get() = this.data.isRideable + + final override val owner: Player + get() = p // Utilities diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBattleCardListener.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBattleCardListener.kt index 1d132a24..786fd986 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBattleCardListener.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBattleCardListener.kt @@ -13,7 +13,7 @@ class IBattleCardListener(plugin: Plugin) : org.bukkit.event.Listener { init { Bukkit.getPluginManager().registerEvents(this, plugin) - val reg = RegisteredListener(this, { _, e -> onEvent(e) }, EventPriority.NORMAL, plugin, false) + val reg = RegisteredListener(this, { _, e -> onEvent(e) }, EventPriority.HIGHEST, plugin, false) HandlerList.getHandlerLists().forEach { it.register(reg) } } diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IWitherKing.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IWitherKing.kt index f31d66eb..93fce491 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IWitherKing.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IWitherKing.kt @@ -65,7 +65,6 @@ class IWitherKing(data: ICard) : IBattleCard(data) { } private companion object { - @JvmStatic private val types: List = listOf( EntityType.BLAZE, EntityType.SKELETON, diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IWitherman.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IWitherman.kt index 9ba13378..0dc23514 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IWitherman.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IWitherman.kt @@ -12,10 +12,10 @@ import org.bukkit.potion.PotionEffectType @Type(BattleCardType.WITHERMAN) @Attributes(650.0, 16.5, 25.5, 0.25, 0.15) -@AttributesModifier(CardAttribute.MAX_HEALTH, CardOperation.ADD, 8.0) +@AttributesModifier(CardAttribute.MAX_HEALTH, CardOperation.ADD, 7.6) @AttributesModifier(CardAttribute.ATTACK_DAMAGE, CardOperation.ADD, 5.75) @AttributesModifier(CardAttribute.DEFENSE, CardOperation.ADD, 4.5) -@AttributesModifier(CardAttribute.SPEED, CardOperation.MULTIPLY, 1.01) +@AttributesModifier(CardAttribute.SPEED, CardOperation.MULTIPLY, 1.015) class IWitherman(data: ICard) : IBattleCard(data) { @CardAbility("card.witherman.ability.wither", ChatColor.DARK_GRAY) diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/CardUtils.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/CardUtils.kt index 86b6f6f7..edeb755d 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/CardUtils.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/CardUtils.kt @@ -21,12 +21,10 @@ import kotlin.math.pow object CardUtils { - @JvmStatic val BLOCK_DATA: MutableMap = mutableMapOf() // Entity Utils - @JvmStatic fun createAttachments(card: IBattleCard<*>) { val attachments = card.javaClass.getAnnotationsByType(BlockAttachment::class.java) if (attachments.isEmpty()) return @@ -73,7 +71,6 @@ object CardUtils { } } - @JvmStatic fun createMinionAttachments(minion: LivingEntity, card: IBattleCard<*>) { val attachments = card.javaClass.getAnnotationsByType(MinionBlockAttachment::class.java).filter { it.type == minion.type } if (attachments.isEmpty()) return @@ -124,12 +121,10 @@ object CardUtils { // String Utils / Extensions - @JvmStatic fun format(string: String, vararg args: Any): String { return String.format(BattleConfig.config.locale, string, *args) } - @JvmStatic fun color(s: String): String { val array = s.trim().split("\\s".toRegex()).toTypedArray() @@ -159,7 +154,6 @@ object CardUtils { return list.joinToString(" ") } - @JvmStatic fun dateFormat(date: Date?, time: Boolean = false): String? { if (date == null || date.time == 0L) return null @@ -169,7 +163,6 @@ object CardUtils { // Other - @JvmStatic fun local(reference: Location, local: Vector): Location { val base = Vector(0, 0, 1) val left: Vector = base.clone().rotateAroundY(Math.toRadians(-reference.yaw + 90.0)) @@ -185,7 +178,6 @@ object CardUtils { return loc } - @JvmStatic fun createLine(card: Card): String { val builder = StringBuilder() @@ -205,11 +197,10 @@ object CardUtils { val Card.power: Long get() = (level.toDouble().pow(rarity.experienceModifier) * rarity.ordinal.plus(1)).toLong() - @JvmStatic fun getCardPower(cards: Iterable) - = cards.map { it to it.card!! }.sumOf { it.second.power * it.first.amount } + = cards.filter { it.isCard }.map { it to it.card!! }.sumOf { it.second.power * it.first.amount } + + cards.filter { it.id == "card_shard" }.sumOf { 3.0.pow(Rarity.valueOf(it.nbt.getString("rarity")).ordinal) * it.amount } - @JvmStatic private val intervalCardChances = listOf( 250, 1250, @@ -218,7 +209,6 @@ object CardUtils { 31475 ) - @JvmStatic fun calculateCardChances(cards: Iterable): Map { val power = getCardPower(cards) if (power < 50) return emptyMap() diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/_Util.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/_Util.kt index 70470d33..58aad453 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/_Util.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/_Util.kt @@ -171,6 +171,16 @@ enum class BattleMaterial( { ItemStack(Material.matchMaterial("red_wool")) } ), + STONE_BRICKS( + { ItemStack(Material.matchMaterial("smooth_brick")) }, + { ItemStack(Material.matchMaterial("stone_bricks")) } + ), + + SPIDER_SPAWN_EGG( + { ItemStack(Material.matchMaterial("monster_egg"), 1, 52) }, + { ItemStack(Material.matchMaterial("spider_spawn_egg")) } + ), + ; fun findStack(): ItemStack = if (Wrapper.legacy) onLegacy() else onModern() diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/extensions.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/extensions.kt index f2df3de4..911fe967 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/extensions.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/extensions.kt @@ -1,6 +1,7 @@ package me.gamercoder215.battlecards.util import me.gamercoder215.battlecards.api.BattleConfig +import me.gamercoder215.battlecards.api.card.BattleCardType import me.gamercoder215.battlecards.api.card.item.CardEquipment import me.gamercoder215.battlecards.impl.* import me.gamercoder215.battlecards.impl.cards.IBattleCard @@ -234,6 +235,9 @@ inline val Player.attackable: Boolean inline val Player.gameName: String get() = displayName ?: name +inline val BattleCardType.isDisabled: Boolean + get() = BattleConfig.config.disabledCards.contains(this) + fun Event.call() { Bukkit.getPluginManager().callEvent(this) } @@ -279,6 +283,9 @@ inline val Chunk.blocks: Set return blocks } +inline val Material?.airOrNull: Boolean + get() = this == null || this == Material.AIR + val PotionEffectType.prefix: String get() = when (this.name.lowercase()) { "absorption", "fire_resistance" -> ChatColor.GOLD @@ -292,7 +299,7 @@ val PotionEffectType.prefix: String "dolphins_grace" -> "a5d1d3" "harm", "increase_damage" -> ChatColor.DARK_RED "hunger" -> "8b4513" - "levitation", "slow_digging" -> ChatColor.WHITE + "levitation", "slow_digging", "slow_falling" -> ChatColor.WHITE "luck", "poison" -> ChatColor.DARK_GREEN "night_vision" -> ChatColor.DARK_BLUE "speed", "water_breathing" -> ChatColor.AQUA @@ -533,4 +540,10 @@ fun String.replace(replacements: Map): String = fun String.capitalizeFully(): String = split(" ").joinToString(" ") { s -> s.lowercase(BattleConfig.config.locale).replaceFirstChar { it.uppercase(BattleConfig.config.locale) } - } \ No newline at end of file + } + +infix fun Iterable.except(other: Iterable): List = + filter { !other.contains(it) } + +infix fun Iterable.except(other: T): List = + filter { it != other } \ No newline at end of file diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/CardGenerator.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/CardGenerator.kt index 96c2b45c..2fae1477 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/CardGenerator.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/CardGenerator.kt @@ -19,7 +19,6 @@ import org.bukkit.util.ChatPaginator object CardGenerator { - @JvmStatic fun toItem(card: Card): ItemStack { val config = BattleConfig.configuration @@ -49,17 +48,17 @@ object CardGenerator { }.nbt { nbt -> nbt["card"] = card.toByteArray() } } - @JvmStatic fun createBasicCard(entity: Creature): ItemStack { if (!BattleConfig.getValidBasicCards().contains(entity.type)) throw IllegalArgumentException("Invalid Entity Type: ${entity.type}") - val card = BattleCardType.BASIC.createCardData() as ICard + val card = BattleCardType.BASIC() as ICard card.storedEntityType = entity.type return toItem(card) } - private val generationColors = listOf( - ChatColor.GREEN, + internal val generationColors = arrayOf( + ChatColor.RESET, // Generation 0 ChatColor.AQUA, + ChatColor.GREEN, ChatColor.DARK_BLUE, ChatColor.YELLOW, ChatColor.DARK_PURPLE, @@ -67,7 +66,6 @@ object CardGenerator { ChatColor.LIGHT_PURPLE ) - @JvmStatic fun generateCardInfo(card: Card): ItemStack { val config = BattleConfig.configuration @@ -159,7 +157,6 @@ object CardGenerator { } } - @JvmStatic fun generateCardStatistics(card: Card): ItemStack? { if (!BattleConfig.configuration.getBoolean("Cards.Display.Info.ShowStatistics")) return null diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/Generator.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/Generator.kt index 82cbf6b1..a91689ff 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/Generator.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/Generator.kt @@ -1,6 +1,7 @@ package me.gamercoder215.battlecards.util.inventory import me.gamercoder215.battlecards.api.BattleConfig +import me.gamercoder215.battlecards.api.card.BattleCardType import me.gamercoder215.battlecards.api.card.Card import me.gamercoder215.battlecards.api.card.CardQuest import me.gamercoder215.battlecards.api.card.item.CardEquipment @@ -9,6 +10,7 @@ import me.gamercoder215.battlecards.impl.CardAttribute import me.gamercoder215.battlecards.impl.ICard import me.gamercoder215.battlecards.util.* import me.gamercoder215.battlecards.util.CardUtils.format +import me.gamercoder215.battlecards.util.inventory.CardGenerator.generationColors import me.gamercoder215.battlecards.wrapper.BattleInventory import me.gamercoder215.battlecards.wrapper.Wrapper.Companion.get import me.gamercoder215.battlecards.wrapper.Wrapper.Companion.w @@ -21,21 +23,21 @@ import org.bukkit.inventory.ItemFlag import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.SkullMeta import org.bukkit.potion.PotionEffectType +import org.bukkit.util.ChatPaginator import java.util.concurrent.atomic.AtomicBoolean import java.util.function.BiConsumer import java.util.function.Consumer import kotlin.math.ceil import kotlin.math.floor +import kotlin.math.pow @Suppress("unchecked_cast") object Generator { - @JvmStatic fun genGUI(size: Int, name: String?): BattleInventory { return genGUI("", size, name) } - @JvmStatic fun genGUI(key: String, size: Int, name: String?): BattleInventory { if (size < 9 || size > 54) throw IllegalArgumentException("Size must be between 9 and 54") if (size % 9 > 0) throw IllegalArgumentException("Size must be a multiple of 9") @@ -57,7 +59,6 @@ object Generator { return inv } - @JvmStatic fun generatePluginInfo(): BattleInventory { val inv = genGUI(27, get("menu.plugin_info")) @@ -92,7 +93,6 @@ object Generator { return inv } - @JvmStatic fun generateCardInfo(card: Card): BattleInventory { val inv = genGUI(27, get("menu.card.info")) inv.isCancelled = true @@ -135,7 +135,15 @@ object Generator { } else Items.locked(floor(card.maxCardLevel / 2.0).toInt()) - inv[23] = Items.COMING_SOON + if (card.type != BattleCardType.BASIC) + inv[23] = ItemStack(Material.BOOK).apply { + itemMeta = itemMeta.apply { + displayName = "${ChatColor.YELLOW}${get("menu.card_catalogue.view_in_catalogue")}" + } + }.nbt { nbt -> + nbt.id = "card:info_item" + nbt["type"] = "catalogue" + } while (inv.firstEmpty() != -1) inv[inv.firstEmpty()] = Items.GUI_BACKGROUND @@ -143,36 +151,6 @@ object Generator { return inv } - @JvmStatic - fun generateCardTable(): BattleInventory { - val inv = genGUI("card_table", 45, get("menu.card_table")) - - inv["on_close"] = BiConsumer { p: Player, inventory: BattleInventory -> - val items = listOfNotNull( - inventory[10], inventory[11], inventory[12], - inventory[19], inventory[20], inventory[21], - inventory[28], inventory[29], inventory[30] - ).toTypedArray() - - items.withIndex().forEach { (i, item) -> - if (p.inventory.firstEmpty() == -1) - p.world.dropItemNaturally(p.location, item) - else - p.inventory.addItem(item) - - inventory[i] = null - } - } - - for (i in 4..7) - for (j in 1..3) inv[i + j.times(9)] = Items.GUI_BACKGROUND - - inv[24] = null - - return inv - } - - @JvmStatic fun generateCardQuests(card: Card, quest: CardQuest? = null): BattleInventory { val inv: BattleInventory @@ -281,7 +259,6 @@ object Generator { return inv } - @JvmStatic private val progressString: List = listOf( 10 nineTo 37, 37..39, @@ -309,7 +286,6 @@ object Generator { return (start..end).filter { (it % 9) - remainder == 0 }.run { if (reverse) reversed() else this } } - @JvmStatic fun generateCardEquipment(card: Card): BattleInventory { val equipment = (card as ICard).cardEquipment val slots = card.statistics.equipmentSlots @@ -383,7 +359,7 @@ object Generator { } } - inv[8] = generateEffectiveModifiers(equipment) + inv[8] = generateEffectiveModifiers(equipment.values) inv[9..17] = Items.GUI_BACKGROUND inv[13] = Items.back() @@ -391,13 +367,12 @@ object Generator { return inv } - @JvmStatic - fun generateEffectiveModifiers(equipment: Map) = ItemStack(BattleMaterial.MAP.find()).apply { + fun generateEffectiveModifiers(equipment: Iterable) = ItemStack(BattleMaterial.MAP.find()).apply { itemMeta = itemMeta.apply { displayName = "${ChatColor.BLUE}${get("constants.effective_modifiers")}" val lore = mutableListOf() - val modifiers = equipment.values.map { it.mods }.run { + val modifiers = equipment.map { it.mods }.run { val map = mutableMapOf() for (mods in this) @@ -434,7 +409,7 @@ object Generator { lore.add(format(get(str), modS)) } - val effects = equipment.values.map { it.effects }.flatten().run { + val effects = equipment.map { it.effects }.flatten().run { val effects = mutableSetOf() for (type in PotionEffectType.values()) { @@ -461,35 +436,103 @@ object Generator { nbt.addTag("_cancel") } - @JvmStatic - fun generateCardCombiner(): BattleInventory { - val inv = genGUI("card_combiner", 54, get("menu.card_combiner")) - - inv["on_close"] = BiConsumer { p: Player, inventory: BattleInventory -> - listOf( - inventory[28..34], inventory[37..43], inventory[13] - ).map { - when (it) { - is Iterable<*> -> it.filterIsInstance().filterNotNull() - is ItemStack? -> listOf(it) - else -> emptyList() + fun generateCatalogue(original: Card, type: BattleCardType = original.type): BattleInventory { + val card = type().apply { experience = maxCardExperience } as ICard + val inv = genGUI(45, format(get("menu.catalogue"), card.name)) + inv.isCancelled = true + inv["card"] = card + + inv[4] = card.icon + + val rideable = card.isRideable + inv[12] = ItemStack(Material.ARMOR_STAND).apply { + itemMeta = itemMeta.apply { + displayName = "${generationColors[type.generation]}${format(get("constants.card.generation"), type.generation.toRoman())}" + lore = listOf( + "${ChatColor.GOLD}${get("constants.card.rideable")} ${if (rideable) "${ChatColor.GREEN}${get("constants.yes")}" else "${ChatColor.RED}${get("constants.no")}" }" + ) + } + } + + val attributes = mapOf( + "health" to (ChatColor.RED to card.statistics.maxHealth), + "damage" to (ChatColor.DARK_RED to card.statistics.attackDamage * 2), + "defense" to (ChatColor.GREEN to card.statistics.defense * 1.75), + "speed" to (ChatColor.DARK_AQUA to card.statistics.speed.pow(500.0)), + "knockback_resistance" to (ChatColor.BLUE to card.statistics.knockbackResistance) + ) + val best = attributes.maxBy { it.value.second } + inv[13] = ItemStack(Material.IRON_HELMET).apply { + itemMeta = itemMeta.apply { + displayName = "${ChatColor.YELLOW}${get("constants.card.attr.best")}" + lore = mutableListOf( + "${best.value.first}${get("constants.card.attr.${best.key}")}", + " " + ).apply { + addAll(ChatPaginator.wordWrap(get("constants.card.attr.${best.key}.desc"), 30).map { "${ChatColor.GRAY}$it" }) } - }.forEach { items -> - for (item in items.filterNotNull()) - if (p.inventory.firstEmpty() == -1) - p.world.dropItemNaturally(p.location, item) - else - p.inventory.addItem(item) + + addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1, true) + addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_ENCHANTS) + } + } + + fun formatCount(count: Double): String { + val long = ceil(count).toLong().coerceAtLeast(1) + val str = long.formatInt() + return if (long == Long.MAX_VALUE) "$str+" + else str + } + + val maxCardExperience = card.maxCardExperience + val zombies = formatCount(maxCardExperience / 20.0) + val endermen = formatCount(maxCardExperience / 40.0) + val withers = formatCount(maxCardExperience / 300.0) + val wardens = formatCount(maxCardExperience / 500.0) + val passive = formatCount(maxCardExperience / BattleConfig.config.growthPassiveAmount) + val smallBook = formatCount(maxCardExperience / Items.SMALL_EXPERIENCE_BOOK.nbt.getDouble("amount")) + val largeBook = formatCount(maxCardExperience / Items.LARGE_EXPERIENCE_BOOK.nbt.getDouble("amount")) + val hugeBook = formatCount(maxCardExperience / Items.HUGE_EXPERIENCE_BOOK.nbt.getDouble("amount")) + + inv[14] = ItemStack(Material.BOOK).apply { + itemMeta = itemMeta.apply { + displayName = "${ChatColor.LIGHT_PURPLE}${get("constants.card.to_max")}" + lore = listOf( + "${ChatColor.DARK_GREEN}-> ${maxCardExperience.withSuffix()} XP", + " ", + "${ChatColor.DARK_GREEN}${format(get("constants.card.to_max.zombies"), zombies)}", + "${ChatColor.DARK_PURPLE}${format(get("constants.card.to_max.endermen"), endermen)}", + "${ChatColor.DARK_GRAY}${format(get("constants.card.to_max.withers"), withers)}", + "${ChatColor.BLUE}${format(get("constants.card.to_max.wardens"), wardens)}", + "${ChatColor.RED}${format(get("constants.card.to_max.passive"), passive)}", + " ", + "${ChatColor.GOLD}${format(get("constants.card.to_max.small_experience_books"), smallBook)}", + "${ChatColor.GOLD}${format(get("constants.card.to_max.large_experience_books"), largeBook)}", + "${ChatColor.GOLD}${format(get("constants.card.to_max.huge_experience_books"), hugeBook)}" + ) } } - inv[10..25] = Items.GUI_BACKGROUND - inv[13] = null - inv[22] = BattleMaterial.YELLOW_STAINED_GLASS_PANE.findStack().apply { + inv[31] = ItemStack(BattleMaterial.CRAFTING_TABLE.find()).apply { itemMeta = itemMeta.apply { - displayName = "${ChatColor.YELLOW}${get("constants.place_items")}" + displayName = "${ChatColor.GOLD}${get("menu.card_catalogue.view_crafting_recipe")}" } - }.nbt { nbt -> nbt.addTag("_cancel") } + }.nbt { nbt -> + nbt.id = "card_catalogue:crafting_recipe" + nbt["type"] = type.name + } + + inv["back"] = Consumer { p: Player -> p.openInventory(generateCardInfo(original)) } + inv[37] = Items.back("action") + + return inv + } + + fun generateCatalogue(equipment: CardEquipment): BattleInventory { + val inv = genGUI(27, format(get("menu.catalogue"), equipment.name.replace("_", " ").capitalizeFully())) + inv.isCancelled = true + inv[12] = equipment.itemStack + inv[14] = generateEffectiveModifiers(listOf(equipment)) return inv } diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/Items.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/Items.kt index 597fca3a..8d073d9a 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/Items.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/Items.kt @@ -25,25 +25,21 @@ import java.util.* object Items { - @JvmStatic val GUI_BACKGROUND: ItemStack = builder(BattleMaterial.BLACK_STAINED_GLASS_PANE, { displayName = " " }, { nbt -> nbt.id = "gui_background" } ) - @JvmStatic val LOCKED: ItemStack = builder(Material.BEDROCK, { displayName = "${ChatColor.DARK_PURPLE}${get("constants.locked")}" }, { nbt -> nbt.addTag("_cancel") } ) - @JvmStatic val COMING_SOON: ItemStack = builder(Material.BEDROCK, { displayName = "${ChatColor.YELLOW}${get("constants.coming_soon")}" }, { nbt -> nbt.addTag("_cancel") } ) - @JvmStatic fun locked(unlockedAt: Int): ItemStack = LOCKED.clone().apply { itemMeta = itemMeta.apply { lore = listOf( @@ -54,7 +50,6 @@ object Items { // Card Items - @JvmStatic val CARD_TABLE: ItemStack = builder(BattleMaterial.CRAFTING_TABLE, { displayName = "${ChatColor.RESET}Card Table" }, { nbt -> nbt["card_block"] = true; nbt.id = "card_table" @@ -66,7 +61,6 @@ object Items { } ) - @JvmStatic val CARD_COMBINER = builder(BattleMaterial.CAULDRON, { displayName = "${ChatColor.RESET}Card Combiner" }, { nbt -> nbt["card_block"] = true; nbt.id = "card_combiner" @@ -78,37 +72,31 @@ object Items { } ) - @JvmStatic val TINY_EXPERIENCE_BOOK: ItemStack = builder(Material.BOOK, { displayName = "${ChatColor.WHITE}Tiny Card Experience Book"; addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1, true); addItemFlags(ItemFlag.HIDE_ENCHANTS) }, { nbt -> nbt["exp_book"] = true; nbt["amount"] = 100.0 } ) - @JvmStatic val SMALL_EXPERIENCE_BOOK: ItemStack = builder(Material.BOOK, { displayName = "${ChatColor.GREEN}Small Card Experience Book"; addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1, true); addItemFlags(ItemFlag.HIDE_ENCHANTS) }, { nbt -> nbt["exp_book"] = true; nbt["amount"] = 2500.0 } ) - @JvmStatic val MEDIUM_EXPERIENCE_BOOK: ItemStack = builder(Material.BOOK, { displayName = "${ChatColor.BLUE}Medium Card Experience Book"; addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1, true); addItemFlags(ItemFlag.HIDE_ENCHANTS) }, { nbt -> nbt["exp_book"] = true; nbt["amount"] = 10000.0 } ) - @JvmStatic val LARGE_EXPERIENCE_BOOK: ItemStack = builder(Material.BOOK, { displayName = "${ChatColor.DARK_PURPLE}Large Card Experience Book"; addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1, true); addItemFlags(ItemFlag.HIDE_ENCHANTS) }, { nbt -> nbt["exp_book"] = true; nbt["amount"] = 500000.0 } ) - @JvmStatic val HUGE_EXPERIENCE_BOOK: ItemStack = builder(Material.BOOK, { displayName = "${ChatColor.GOLD}Huge Card Experience Book"; addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1, true); addItemFlags(ItemFlag.HIDE_ENCHANTS) }, - { nbt -> nbt["exp_book"] = true; nbt["amount"] = 2000000.0 } + { nbt -> nbt["exp_book"] = true; nbt["amount"] = 4000000.0 } ) - @JvmStatic fun cardShard(rarity: Rarity): ItemStack { if (rarity == Rarity.BASIC) throw UnsupportedOperationException("Cannot Use Basic Rarity") @@ -120,7 +108,6 @@ object Items { // Static Util - @JvmStatic fun builder(material: Material, action: ItemMeta.() -> Unit): ItemStack { return ItemStack(material).apply { itemMeta = itemMeta.apply { @@ -129,7 +116,6 @@ object Items { } } - @JvmStatic fun next(key: String = "stored"): ItemStack = head("arrow_right") { itemMeta = itemMeta.apply { @@ -137,7 +123,6 @@ object Items { } }.nbt { nbt -> nbt.id = "scroll:$key"; nbt["operation"] = 1 } - @JvmStatic fun prev(key: String = "stored"): ItemStack = head("arrow_left") { itemMeta = itemMeta.apply { @@ -145,7 +130,6 @@ object Items { } }.nbt { nbt -> nbt.id = "scroll:$key"; nbt["operation"] = -1 } - @JvmStatic fun back(key: String = "action"): ItemStack = head("arrow_left_log") { itemMeta = itemMeta.apply { @@ -153,14 +137,13 @@ object Items { } }.nbt { nbt -> nbt.id = "back:$key" } - @JvmStatic fun head(key: String, action: ItemStack.() -> Unit = {}): ItemStack { val p = Properties().apply { load(Items::class.java.getResourceAsStream("/util/heads.properties")) } val value = p.getProperty(key) ?: throw IllegalArgumentException("Head not found: $key") return (if (Wrapper.legacy) ItemStack(matchMaterial("SKULL_ITEM"), 1, 3.toShort()) else ItemStack(matchMaterial("PLAYER_HEAD"))).apply { itemMeta = (itemMeta as SkullMeta).apply { - val profile = GameProfile(UUID.randomUUID(), null).apply { + val profile = GameProfile(UUID.randomUUID(), key).apply { properties.put("textures", Property("textures", value)) } @@ -171,7 +154,6 @@ object Items { } } - @JvmStatic fun createShapedRecipe(key: String, result: ItemStack): ShapedRecipe { return try { val namespacedKey = Class.forName("org.bukkit.NamespacedKey").run { @@ -188,7 +170,6 @@ object Items { // Recipes & Public Items - @JvmStatic val RECIPES: List = mutableListOf( createShapedRecipe("card_table", CARD_TABLE).apply { shape(" W ", "WPW", " W ") @@ -239,7 +220,6 @@ object Items { } } - @JvmStatic val CARD_TABLE_RECIPES: List = listOf( CardWorkbenchRecipe( { matrix -> @@ -288,7 +268,6 @@ object Items { ) ) - @JvmStatic val PUBLIC_ITEMS = mutableMapOf( "card_table" to CARD_TABLE, "card_combiner" to CARD_COMBINER, @@ -301,7 +280,6 @@ object Items { putAll(Rarity.entries.filter { it != Rarity.BASIC }.map { "${it.name.lowercase()}_card_shard" to cardShard(it) }) } - @JvmStatic private val GENERATED_ITEMS: Map = mapOf( "tiny_experience_book" to 0.04, "small_experience_book" to 0.001, @@ -317,13 +295,14 @@ object Items { "ultimate_card_shard" to 0.0000025 ) - @JvmStatic val EFFECTIVE_GENERATED_ITEMS = { GENERATED_ITEMS.mapNotNull { val item = PUBLIC_ITEMS[it.key] ?: return@mapNotNull null item to (it.value / GENERATED_ITEMS.values.sum()) }.toMap() } - fun Map.randomCumulative(reroll: Int = 0): T { + fun Map.randomCumulative(reroll: Int = 0): T? { + if (isEmpty()) return null + val distribution = DoubleArray(size) var cumulative = 0.0 diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/containers.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/containers.kt index f316d644..7d98ba4f 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/containers.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/util/inventory/containers.kt @@ -1,8 +1,78 @@ package me.gamercoder215.battlecards.util.inventory +import me.gamercoder215.battlecards.util.BattleMaterial +import me.gamercoder215.battlecards.util.get +import me.gamercoder215.battlecards.util.inventory.Generator.genGUI +import me.gamercoder215.battlecards.util.nbt +import me.gamercoder215.battlecards.util.set import me.gamercoder215.battlecards.wrapper.BattleInventory +import me.gamercoder215.battlecards.wrapper.Wrapper +import org.bukkit.ChatColor +import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack +import java.util.function.BiConsumer val CONTAINERS_CARD_BLOCKS: Map BattleInventory> = mapOf( - "card_table" to { Generator.generateCardTable() }, - "card_combiner" to { Generator.generateCardCombiner() } -) \ No newline at end of file + "card_table" to { generateCardTable() }, + "card_combiner" to { generateCardCombiner() } +) + +fun generateCardTable(): BattleInventory { + val inv = genGUI("card_table", 45, Wrapper.get("menu.card_table")) + + inv["on_close"] = BiConsumer { p: Player, inventory: BattleInventory -> + val items = listOfNotNull( + inventory[10], inventory[11], inventory[12], + inventory[19], inventory[20], inventory[21], + inventory[28], inventory[29], inventory[30] + ).toTypedArray() + + items.withIndex().forEach { (i, item) -> + if (p.inventory.firstEmpty() == -1) + p.world.dropItemNaturally(p.location, item) + else + p.inventory.addItem(item) + + inventory[i] = null + } + } + + for (i in 4..7) + for (j in 1..3) inv[i + j.times(9)] = Items.GUI_BACKGROUND + + inv[24] = null + + return inv +} + +fun generateCardCombiner(): BattleInventory { + val inv = genGUI("card_combiner", 54, Wrapper.get("menu.card_combiner")) + + inv["on_close"] = BiConsumer { p: Player, inventory: BattleInventory -> + listOf( + inventory[28..34], inventory[37..43], inventory[13] + ).map { + when (it) { + is Iterable<*> -> it.filterIsInstance().filterNotNull() + is ItemStack? -> listOf(it) + else -> emptyList() + } + }.forEach { items -> + for (item in items.filterNotNull()) + if (p.inventory.firstEmpty() == -1) + p.world.dropItemNaturally(p.location, item) + else + p.inventory.addItem(item) + } + } + + inv[10..25] = Items.GUI_BACKGROUND + inv[13] = null + inv[22] = BattleMaterial.YELLOW_STAINED_GLASS_PANE.findStack().apply { + itemMeta = itemMeta.apply { + displayName = "${ChatColor.YELLOW}${Wrapper.get("constants.place_items")}" + } + }.nbt { nbt -> nbt.addTag("_cancel") } + + return inv +} \ No newline at end of file diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/NBTWrapper.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/NBTWrapper.kt index d0e53a40..542a5a3d 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/NBTWrapper.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/NBTWrapper.kt @@ -18,23 +18,18 @@ abstract class NBTWrapper( @JvmStatic protected val TAGS_KEY = "tags" - @JvmStatic fun of(item: ItemStack) = w.getNBTWrapper(item) - @JvmStatic fun builder(item: ItemStack, action: (NBTWrapper) -> Unit): ItemStack { return of(item.clone()).apply { action(this) }.item } - @JvmStatic fun builder(material: Material, action: (NBTWrapper) -> Unit): ItemStack = builder(ItemStack(material), action) - @JvmStatic fun builder(material: BattleMaterial, action: (NBTWrapper) -> Unit): ItemStack = builder(ItemStack(material.findStack()), action) - @JvmStatic fun builder(item: ItemStack, meta: ItemMeta.() -> Unit, nbt: (NBTWrapper) -> Unit): ItemStack { val item0 = item.clone() item0.itemMeta = item0.itemMeta.apply { meta(this) } @@ -42,10 +37,8 @@ abstract class NBTWrapper( return of(item0).apply { nbt(this) }.item } - @JvmStatic fun builder(material: Material, meta: ItemMeta.() -> Unit, nbt: (NBTWrapper) -> Unit): ItemStack = builder(ItemStack(material), meta, nbt) - @JvmStatic fun builder(material: BattleMaterial, meta: ItemMeta.() -> Unit, nbt: (NBTWrapper) -> Unit): ItemStack = builder(ItemStack(material.findStack()), meta, nbt) } diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/Wrapper.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/Wrapper.kt index 716f4de7..66b8478c 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/Wrapper.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/Wrapper.kt @@ -54,15 +54,12 @@ interface Wrapper { fun addFollowGoal(entity: LivingEntity, ownerCard: IBattleCard<*>) companion object { - @JvmStatic val w = getWrapper() const val PACKET_INJECTOR_ID = "battlecards:packet_injector" - @JvmStatic val r = SecureRandom() - @JvmStatic val versions = listOf( "1_8_R1", "1_8_R2", @@ -90,7 +87,6 @@ interface Wrapper { "1_20_R3" ) - @JvmStatic fun getWrapper(): Wrapper { val constr = Class.forName("${Wrapper::class.java.`package`.name}.v${getServerVersion()}.Wrapper${getServerVersion()}") .asSubclass(Wrapper::class.java) @@ -100,7 +96,6 @@ interface Wrapper { return constr.newInstance() } - @JvmStatic fun getCommandWrapper(): CommandWrapper { val cmdV: Int = when (BattleConfig.configuration.getString("Functionality.CommandVersion", "auto")) { "1" -> 1 @@ -117,7 +112,6 @@ interface Wrapper { return constr.newInstance(BattleConfig.plugin) } - @JvmStatic fun loadCards() { val current = getServerVersion() val cards: MutableList>> = mutableListOf( @@ -156,26 +150,29 @@ interface Wrapper { } catch (ignored: ClassNotFoundException) {} } - cards.forEach(BattleConfig.config::registerCard) + cards.forEach { + try { + BattleConfig.config.registerCard(it) + } catch (e: IllegalStateException) { + BattleConfig.logger.warning("Failed to register card '${it.name}'") + BattleConfig.print(e) + } + } equipment.forEach(BattleConfig.config::registerEquipment) } - @JvmStatic fun getServerVersion(): String { return Bukkit.getServer().javaClass.`package`.name.split(".")[3].substring(1) } - @JvmStatic fun get(key: String): String { return BattleConfig.config.get(key) } - @JvmStatic fun getMessage(key: String): String { return BattleConfig.config.getMessage(key) } - @JvmStatic val legacy: Boolean get() = w.getCommandVersion() == 1 diff --git a/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapper.kt b/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapper.kt index 594a971d..0334d406 100644 --- a/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapper.kt +++ b/abstract/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapper.kt @@ -20,38 +20,32 @@ import java.util.* interface CommandWrapper { companion object { - @JvmStatic val COMMANDS: Map> = ImmutableMap.builder>() .put("bcard", listOf("card", "battlecard")) .put("cardreload", listOf("creload")) .put("bquery", listOf("cardquery", "battlequery")) .build() - @JvmStatic val COMMAND_PERMISSION: Map = ImmutableMap.builder() .put("bcard", "battlecards.user.card") .put("cardreload", "battlecards.admin.reload") .put("bquery", "battlecards.user.query") .build() - @JvmStatic val COMMAND_DESCRIPTION: Map = ImmutableMap.builder() .put("bcard", "Main BattleCards Card Command") .put("cardreload", "Reloads the BattleCards Plugin") .put("bquery", "Command for Querying BattleCards Cards") .build() - @JvmStatic val COMMAND_USAGE: Map = ImmutableMap.builder() .put("bcard", "/bcard") .put("cardreload", "/cardreload") .put("bquery", "/bquery ") .build() - @JvmStatic fun getError(key: String): String = "${get("plugin.prefix")} ${ChatColor.RED}${get(key)}" - @JvmStatic fun getSuccess(key: String): String = "${get("plugin.prefix")} ${ChatColor.GREEN}${get(key)}" private val COOLDOWN: MutableMap> = mutableMapOf() @@ -65,7 +59,6 @@ interface CommandWrapper { plugin.reloadConfig() BattleConfig.loadConfig() Wrapper.getCommandWrapper() - sender.sendMessage(getSuccess("command.reload.reloaded")) } @@ -88,6 +81,9 @@ interface CommandWrapper { if (!p.hasPermission("battlecards.admin.card.create")) return p.sendMessage(getError("error.permission.argument")) + if (type.isDisabled) + return p.sendMessage(getError("error.card.disabled")) + if (p.inventory.firstEmpty() == -1) return p.sendMessage(getError("error.inventory.full")) @@ -95,7 +91,7 @@ interface CommandWrapper { if (basicType == null || !BattleConfig.getValidBasicCards().contains(basicType)) return p.sendMessage(getError("error.argument.basic_type")) - p.inventory.addItem(CardGenerator.toItem(type.createCardData().apply { this as ICard; storedEntityType = basicType } )) + p.inventory.addItem(CardGenerator.toItem(type().apply { this as ICard; storedEntityType = basicType } )) p.sendMessage(format(getSuccess("success.card.created"), type.formatName())) p.playSuccess() } @@ -104,7 +100,10 @@ interface CommandWrapper { if (!p.hasPermission("battlecards.user.query")) return p.sendMessage(getError("error.permission.argument")) - p.openInventory(Generator.generateCardInfo(type.createCardData())) + if (type.isDisabled) + return p.sendMessage(getError("error.card.disabled")) + + p.openInventory(Generator.generateCardInfo(type())) p.playSuccess() } @@ -120,6 +119,31 @@ interface CommandWrapper { p.playSuccess() } + fun catalogue(p: Player, input: String) { + if (!p.hasPermission("battlecards.user.query")) + return p.sendMessage(getError("error.permission.argument")) + + if (BattleCardType.entries.map { it.name.lowercase() }.contains(input.lowercase())) { + val type = BattleCardType.valueOf(input.uppercase()) + + if (type.isDisabled) + return p.sendMessage(getError("error.card.disabled")) + + if (type == BattleCardType.BASIC) + return p.sendMessage(getError("error.argument.basic_type")) + + p.openInventory(Generator.generateCatalogue(type())) + } + + if (BattleConfig.config.registeredEquipment.any { it.name.lowercase() == input.lowercase() }) { + val equipment = BattleConfig.config.registeredEquipment.first { it.name.lowercase() == input.lowercase() } + + p.openInventory(Generator.generateCatalogue(equipment)) + } + + p.playSuccess() + } + fun giveItem(p: Player, id: String) { if (!p.hasPermission("battlecards.admin.items")) return p.sendMessage(getError("error.permission.argument")) diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 799f0819..dddf5d20 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { compileOnly("org.spigotmc:spigot-api:1.8-R0.1-SNAPSHOT") + testImplementation("org.spigotmc:spigot-api:1.8-R0.1-SNAPSHOT") } description = "API for the Plugin BattleCards" diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/BattleConfig.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/BattleConfig.kt index aa789611..cee4613e 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/BattleConfig.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/BattleConfig.kt @@ -270,6 +270,18 @@ interface BattleConfig { plugin.saveConfig() } + var disabledCards: Set + /** + * Gets all disabled BattleCards. + * @return Set of disabled BattleCards + */ + get() = configuration.getStringList("Cards.Disabled").mapNotNull { try { BattleCardType.valueOf(it.uppercase()) } catch (ignored: IllegalArgumentException) { null } }.toSet() + /** + * Sets the currently disabled BattleCards. + * @param value Set of disabled BattleCards + */ + set(value) = setConfig("Cards.Disabled", value.map { it.name.lowercase() }) + var isBasicDropsEnabled: Boolean /** * Fetches whether cards of the [Rarity.BASIC] rarity can be dropped by mobs. diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/BattleCard.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/BattleCard.kt index d8f5850f..ae3b85bb 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/BattleCard.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/BattleCard.kt @@ -3,6 +3,7 @@ package me.gamercoder215.battlecards.api.card import me.gamercoder215.battlecards.api.card.item.CardEquipment import org.bukkit.OfflinePlayer import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import java.util.* @@ -27,6 +28,12 @@ interface BattleCard { */ get() = entity != null + /** + * Fetches the Player that owns this BattleCard. + * @return Owner + */ + val owner: Player + /** * Fetches the Entity that this BattleCard is spawned as, or null if not spawned. * @return Spawned Entity diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/BattleCardType.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/BattleCardType.kt index 73572e1c..eaccf6cc 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/BattleCardType.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/BattleCardType.kt @@ -209,7 +209,7 @@ enum class BattleCardType { /** * Represents a Skeleton BattleCard. */ - GOAT_GLADIATOR(1, Skeleton::class, Rarity.RARE, Material.matchMaterial("GOAT_HORN")), + GOAT_GLADIATOR(1, Skeleton::class, Rarity.RARE, Material.matchMaterial("GOAT_HORN") ?: Material.matchMaterial("HORN_CORAL_BLOCK")), /** * Represents a Piglin BattleCard. @@ -219,14 +219,29 @@ enum class BattleCardType { /** * Represents a Piglin Brute BattleCard. */ - PIGLIN_TITAN(1, "PiglinBrute", Rarity.ULTIMATE, Material.matchMaterial("PIGLIN_HEAD") ?: Material.matchMaterial("NETHERITE_BLOCK"), Material.matchMaterial("NETHERITE_BLOCK")) + PIGLIN_TITAN(1, "PiglinBrute", Rarity.ULTIMATE, Material.matchMaterial("PIGLIN_HEAD") ?: Material.matchMaterial("NETHERITE_BLOCK"), Material.matchMaterial("NETHERITE_BLOCK")), + + /** + * Represents a Husk BattleCard. + */ + SAND_TRAVELER(2, "Husk", Rarity.EPIC, Material.SAND), + + /** + * Represents a Wither Skeleton BattleCard. + */ + THE_IMMORTAL(2, "WitherSkeleton", Rarity.ULTIMATE, Material.matchMaterial("END_CRYSTAL")), + + /** + * Represents a Snowman BattleCard. + */ + BLIZZARD(2, "Snowman", Rarity.LEGEND, Material.SNOW_BLOCK), ; constructor(generation: Int, entityClass: String, rarity: Rarity, material: Material? = null, crafting: Material? = material) : this( generation, try { Class.forName("org.bukkit.entity.${entityClass}") as Class - } catch (e: ClassNotFoundException) { + } catch (e: ReflectiveOperationException) { null }, rarity, @@ -287,6 +302,13 @@ enum class BattleCardType { */ fun createCardData(): Card = BattleConfig.config.createCardData(this) + /** + * Creates a new card data object. + * @return New Card Data + * @see [createCardData] + */ + operator fun invoke(): Card = createCardData() + companion object { /** diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/Card.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/Card.kt index f6e01b90..e87d5c74 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/Card.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/Card.kt @@ -245,6 +245,11 @@ interface Card : ConfigurationSerializable { */ get() = statistics.equipmentSlots + /** + * Gets whether or not this card can be ridden. + */ + val isRideable: Boolean + // Serialization /** diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/Rarity.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/Rarity.kt index 17401a9f..d1e7d311 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/Rarity.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/Rarity.kt @@ -13,11 +13,11 @@ enum class Rarity( /** * Represents the Basic rarity */ - BASIC(ChatColor.WHITE, 1.05), + BASIC(ChatColor.WHITE, 1.025), /** * Represents the Common rarity */ - COMMON(ChatColor.GREEN, 1.075), + COMMON(ChatColor.GREEN, 1.05), /** * Represents the Uncommon rarity */ diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/item/CardEquipment.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/item/CardEquipment.kt index c3ce62de..88af2002 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/item/CardEquipment.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/card/item/CardEquipment.kt @@ -178,7 +178,6 @@ interface CardEquipment : Serializable { ) { private companion object { - @JvmStatic private val r = SecureRandom() } diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardEvent.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardEvent.kt index 54fa7010..b9d40d13 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardEvent.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardEvent.kt @@ -7,20 +7,17 @@ import org.bukkit.event.HandlerList /** * Represents an event involving a [Card]. */ -abstract class CardEvent(card: Card, async: Boolean = false) : Event(async) { - - companion object { - @JvmStatic - val handlerList = HandlerList() - } - +abstract class CardEvent( /** * The [Card] involved in this event. */ - val card: Card + val card: Card, + async: Boolean = false +) : Event(async) { - init { - this.card = card + companion object { + @JvmStatic + val handlerList = HandlerList() } override fun getHandlers() = handlerList diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardExperienceChangeEvent.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardExperienceChangeEvent.kt index bae9e463..9003c8e1 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardExperienceChangeEvent.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardExperienceChangeEvent.kt @@ -13,17 +13,12 @@ open class CardExperienceChangeEvent(card: Card, old: Double, new: Double) : Car /** * The old experience amount of the [Card]. */ - val oldExperience: Double + val oldExperience: Double = old /** * The new experience amount of the [Card]. */ - var newExperience: Double - - init { - this.oldExperience = old - this.newExperience = new - } + var newExperience: Double = new override fun isCancelled(): Boolean = cancelled override fun setCancelled(cancel: Boolean) { cancelled = cancel } diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardQuestLevelUpEvent.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardQuestLevelUpEvent.kt index 1ce97a97..d4fd5e63 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardQuestLevelUpEvent.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/CardQuestLevelUpEvent.kt @@ -8,37 +8,20 @@ import me.gamercoder215.battlecards.api.card.CardQuest */ open class CardQuestLevelUpEvent( card: Card, - quest: CardQuest, - oldLevel: Int, - newLevel: Int, - experienceAdded: Double -) : CardEvent(card) { - /** * The Quest involved in this Event */ - val quest: CardQuest - + val quest: CardQuest, /** * The old Level of the Quest */ - val oldLevel: Int - + val oldLevel: Int, /** * The new Level of the Quest */ - val newLevel: Int - + val newLevel: Int, /** * The amount of Card Experience added to the Card as a reward */ var experienceAdded: Double - - init { - this.quest = quest - this.oldLevel = oldLevel - this.newLevel = newLevel - this.experienceAdded = experienceAdded - } - -} \ No newline at end of file +) : CardEvent(card) \ No newline at end of file diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/PrepareCardCombineEvent.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/PrepareCardCombineEvent.kt new file mode 100644 index 00000000..9068862a --- /dev/null +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/PrepareCardCombineEvent.kt @@ -0,0 +1,33 @@ +package me.gamercoder215.battlecards.api.events + +import org.bukkit.entity.Player +import org.bukkit.event.Cancellable +import org.bukkit.event.HandlerList +import org.bukkit.event.player.PlayerEvent +import org.bukkit.inventory.ItemStack + +open class PrepareCardCombineEvent( + player: Player, + /** + * The matrix of items used to combine the cards. + */ + val matrix: Array, + /** + * The result of the combining. + */ + var result: ItemStack +) : PlayerEvent(player), Cancellable { + + private var cancelled = false + + companion object { + @JvmStatic + val handlerList = HandlerList() + } + + override fun getHandlers() = handlerList + override fun isCancelled() = cancelled + override fun setCancelled(cancel: Boolean) { cancelled = cancel } + + +} \ No newline at end of file diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/PrepareCardCraftEvent.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/PrepareCardCraftEvent.kt index 9bc43d6e..5ded2a4f 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/PrepareCardCraftEvent.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/PrepareCardCraftEvent.kt @@ -9,24 +9,19 @@ import org.bukkit.inventory.ItemStack /** * Called before an item is crafted in the Card Workbench. */ -open class PrepareCardCraftEvent(player: Player, matrix: Array, result: ItemStack?) : PlayerEvent(player), Cancellable { - - private var cancelled = false - +open class PrepareCardCraftEvent( + player: Player, /** - * The matrix of items used to craft the item. - */ - val matrix: Array - + * The matrix of items used to craft the item. + */ + val matrix: Array, /** - * The result of the crafting. - */ + * The result of the crafting. + */ var result: ItemStack? +) : PlayerEvent(player), Cancellable { - init { - this.matrix = matrix - this.result = result - } + private var cancelled = false companion object { @JvmStatic diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/entity/CardUseAbilityEvent.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/entity/CardUseAbilityEvent.kt index e587c864..0fa89d8f 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/entity/CardUseAbilityEvent.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/entity/CardUseAbilityEvent.kt @@ -13,11 +13,7 @@ open class CardUseAbilityEvent(card: BattleCard<*>, type: AbilityType) : EntityC /** * The [AbilityType] of the ability used. */ - val abilityType: AbilityType - - init { - this.abilityType = type - } + val abilityType: AbilityType = type override fun isCancelled(): Boolean = cancelled override fun setCancelled(cancel: Boolean) { cancelled = cancel } diff --git a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/entity/EntityCardEvent.kt b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/entity/EntityCardEvent.kt index 9f7326dd..7b89b92d 100644 --- a/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/entity/EntityCardEvent.kt +++ b/api/src/main/kotlin/me/gamercoder215/battlecards/api/events/entity/EntityCardEvent.kt @@ -1,27 +1,22 @@ package me.gamercoder215.battlecards.api.events.entity import me.gamercoder215.battlecards.api.card.BattleCard -import me.gamercoder215.battlecards.api.events.CardEvent import org.bukkit.event.HandlerList import org.bukkit.event.entity.EntityEvent /** * Represents an event involving a [BattleCard] entity. */ -abstract class EntityCardEvent(card: BattleCard<*>) : EntityEvent(card.entity) { - - companion object { - @JvmStatic - val handlerList: HandlerList = HandlerList() - } - +abstract class EntityCardEvent( /** * The [BattleCard] involved in this event. */ val card: BattleCard<*> +) : EntityEvent(card.entity) { - init { - this.card = card + companion object { + @JvmStatic + val handlerList: HandlerList = HandlerList() } override fun getHandlers(): HandlerList = handlerList diff --git a/api/src/main/resources/lang/battlecards.properties b/api/src/main/resources/lang/battlecards.properties index d3f1c967..8ff906bd 100644 --- a/api/src/main/resources/lang/battlecards.properties +++ b/api/src/main/resources/lang/battlecards.properties @@ -345,4 +345,60 @@ card.piglin_titan.ability.leap=Leap card.piglin_titan.ability.leap.desc=Every %bcint, will leap towards its target. If close enough, deals an extra 2% damage. constants.card_equipment.ability.chainmail=&7Chainmail constants.card_equipment.ability.chainmail.desc=-35% Projectile Damage Taken +error.card.disabled=This card is currently disabled. +constants.card.attr.defense=Defense +constants.card.attr.speed=Speed +constants.card.attr.defense.desc=This is a very tanky card that is useful for defending you or your other cards. It may not be able to defeat an enemy by itself, through! +constants.card.attr.speed.desc=A very swift Card that can be hard to hit, especially by ranged foes. Maybe it's also rideable! +constants.card.attr.damage=Attack Damage +constants.card.attr.damage.desc=This card is very useful when cutting down on weaker cards. It may not live long, but it'll die trying! +constants.card.attr.knockback_resistance=Knockback Resistance +constants.card.attr.knockback_resistance.desc=This card knows how to stand its ground. Depending on how hard it hits back, this can be one formidable foe! +constants.card.attr.health=Health +constants.card.attr.health.desc=A very healthy card that can be around for awhile. The other attributes can be a hit or miss. +constants.card.attr.best=Best Attribute: +constants.card.rideable=Rideable: +constants.yes=Yes +constants.no=No +constants.card.to_max=To Max: +constants.card.to_max.zombies=%s Zombies to Kill +constants.card.to_max.endermen=%s Endermen to Kill +constants.card.to_max.withers=%s Withers to Slay +constants.card.to_max.passive=%s Hours inside an Inventory +constants.card.to_max.small_experience_books=%s Small Experience Books +constants.card.to_max.large_experience_books=%s Large Experience Books +constants.card.to_max.wardens=%s Wardens to Kill +menu.catalogue=Catalogue | "%s" +menu.card_catalogue.view_crafting_recipe=View Crafting Recipe +menu.card_catalogue.crafting=Recipe for "%s" +menu.card_catalogue.view_in_catalogue=View in Card Catalogue +card.goat_gladiator=USHAAAAAAA! +card.goat_gladiator.desc=The soldier picked the worst sounding goat to go with him into the Wither War. He now has to live with it even after death. +constants.card_equipment.ability.deflect=&aDeflect +constants.card_equipment.ability.deflect.desc=40% Chance to Deflect Projectiles. +card.sand_traveler.ability.blazing_hot=Blazing Hot +card.sand_traveler.ability.blazing_hot.desc=Both the card and the card owner gain immunity to all heat. +card.sand_traveler=50 days to Egypt! +card.sand_traveler.desc=He traveled on his trusty camel for so long that he gained immunity to all heat. He runs ultra marathons in his free time. +card.sand_traveler.ability.firecracker=Firecracker +card.sand_traveler.ability.firecracker.desc=Shoots exploside fireballs out of its mouth every 7s. +card.the_immortal=WE TRUSTED YOU!! +card.the_immortal.desc=An ancient warrior, surviving a great betrayal and literally too angry to die. +card.the_immortal.ability.immortality=Immortality +card.the_immortal.ability.immortality.desc=Holds 1 totem and gains 1 for every 10 levels. +card.the_immortal.ability.hardening=Hardening +card.the_immortal.ability.hardening.desc=%bch chance to block incoming damage. +card.the_immortal.ability.soft_landing=Soft Landing +card.the_immortal.ability.soft_landing.desc=Player & Card gain immunity to fall damage. +card.blizzard.ability.iceball=Iceball +card.blizzard.ability.iceball.desc=Shoots snowballs that deal 50% of its attack damage. +card.blizzard=Don't sing it. +card.blizzard.desc=A simple Ice Wizard tired of Disney songs. +card.blizzard.ability.storm=Storm +card.blizzard.ability.blue_flame=Blue Flame +card.blizzard.ability.blue_flame.desc=Owner can inflict 2s of Ice Damage. +constants.card.to_max.huge_experience_books=%s Huge Experience Books + + + diff --git a/api/src/main/resources/lang/battlecards_es.properties b/api/src/main/resources/lang/battlecards_es.properties index 9243911b..59e55e28 100644 --- a/api/src/main/resources/lang/battlecards_es.properties +++ b/api/src/main/resources/lang/battlecards_es.properties @@ -345,3 +345,56 @@ card.piglin_titan.ability.leap=Salto card.piglin_titan.ability.leap.desc=Cada %bcint saltar\u00E1 hacia su objetivo. Si est\u00E1 lo suficientemente cerca, inflige un 2% de da\u00F1o adicional. constants.card_equipment.ability.chainmail=&7Cota de Malla constants.card_equipment.ability.chainmail.desc=-35% de Da\u00F1o de Proyectil Recibido +error.card.disabled=Esta tarjeta est\u00E1 actualmente deshabilitada. +constants.card.attr.damage=Da\u00F1o de Ataque +constants.card.attr.damage.desc=Esta carta es muy \u00FAtil para reducir las cartas m\u00E1s d\u00E9biles. Puede que no viva mucho, \u00A1pero morir\u00E1 en el intento! +constants.card.attr.defense=Defensa +constants.card.attr.defense.desc=Esta es una carta muy resistente que es \u00FAtil para defenderte a ti o a tus otras cartas. Es posible que no pueda derrotar a un enemigo por s\u00ED solo! +constants.card.attr.health=Salud +constants.card.attr.health.desc=Una tarjeta muy saludable que puede durar un tiempo. Los otros atributos pueden ser impredecibles. +constants.card.attr.knockback_resistance=Resistencia al retroceso +constants.card.attr.knockback_resistance.desc=Esta carta sabe c\u00F3mo mantenerse firme. Dependiendo de lo fuerte que devuelva el golpe, \u00A1este puede ser un enemigo formidable! +constants.card.attr.speed=Velocidad +constants.card.attr.speed.desc=Una carta muy r\u00E1pida que puede ser dif\u00EDcil de golpear, especialmente para enemigos a distancia. Quiz\u00E1s tambi\u00E9n sea manejable! +constants.card.attr.best=Mejor Atributo: +constants.card.rideable=Montable: +constants.no=No +constants.yes=S\u00ED +constants.card.to_max=A M\u00E1ximo: +constants.card.to_max.endermen=%s Endermen de Matar +constants.card.to_max.large_experience_books=%s Libros de Experiencias Grandes +constants.card.to_max.passive=%s Horas Dentro de un Inventario +constants.card.to_max.small_experience_books=%s Libros de Experiencias Peque\u00F1as +constants.card.to_max.wardens=%s Guardianes a Los que Matar +constants.card.to_max.withers=%s se Marchita de Matar +constants.card.to_max.zombies=%s Zombis de Matar +menu.catalogue=Cat\u00E1logo | "%s" +menu.card_catalogue.view_crafting_recipe=Ver Receta de Elaboraci\u00F3n +menu.card_catalogue.crafting=Receta para "%s" +menu.card_catalogue.view_in_catalogue=Ver en Cat\u00E1logo de Tarjetas +card.goat_gladiator=USHAAAAAAA! +card.goat_gladiator.desc=El soldado eligi\u00F3 la cabra que sonaba peor para ir con \u00E9l a la Guerra Marchita. Ahora tiene que vivir con ello incluso despu\u00E9s de la muerte. +constants.card_equipment.ability.deflect=&aDesviar +constants.card_equipment.ability.deflect.desc=40% de probabilidad de desviar proyectiles. +card.sand_traveler=50 d\u00EDas a Egipto! +card.sand_traveler.ability.blazing_hot=Ardientemente Caliente +card.sand_traveler.ability.blazing_hot.desc=Tanto la tarjeta como el propietario de la tarjeta obtienen inmunidad a todo calor. +card.sand_traveler.ability.firecracker=Petardo +card.sand_traveler.ability.firecracker.desc=Dispara que explotan bolas de fuego fuera de su boca cada 7s. +card.the_immortal=CONFIAMOS EN TI!! +card.the_immortal.desc=Un antiguo guerrero que sobrevivi\u00F3 a una gran traici\u00F3n y, literalmente, demasiado enojado para morir. +card.the_immortal.ability.immortality=Inmortalidad +card.the_immortal.ability.immortality.desc=Tiene 1 t\u00F3tem y gana 1 por cada 10 niveles. +card.the_immortal.ability.hardening=Endurecimiento +card.the_immortal.ability.hardening.desc=%bch probabilidad de bloquear el da\u00F1o entrante. +card.the_immortal.ability.soft_landing=Aterrizaje Suave +card.the_immortal.ability.soft_landing.desc=El jugador y la carta obtienen inmunidad al da\u00F1o por ca\u00EDda. +card.blizzard=No lo cantes. +card.blizzard.desc=Un sencillo Mago de Hielo cansado de las canciones de Disney. +card.blizzard.ability.blue_flame=Llama Azul +card.blizzard.ability.blue_flame.desc=El propietario puede infligir 2s de da\u00F1o por hielo. +card.blizzard.ability.iceball=Bola de Hielo +card.blizzard.ability.iceball.desc=Dispara bolas de nieve que causan el 50% de su da\u00F1o de ataque. +card.blizzard.ability.storm=Tormenta +constants.card.to_max.huge_experience_books=%s Libros de Enormes Experiencias + diff --git a/api/src/main/resources/lang/battlecards_fr.properties b/api/src/main/resources/lang/battlecards_fr.properties index 27d3165d..92e8e1e9 100644 --- a/api/src/main/resources/lang/battlecards_fr.properties +++ b/api/src/main/resources/lang/battlecards_fr.properties @@ -345,3 +345,56 @@ card.piglin_titan.ability.leap=Saut card.piglin_titan.ability.leap.desc=Chaque %bcint bondira vers sa cible. S'il est suffisamment proche, inflige 2% de d\u00E9g\u00E2ts suppl\u00E9mentaires. constants.card_equipment.ability.chainmail=&7Cotte de Mailles constants.card_equipment.ability.chainmail.desc=-35% de D\u00E9g\u00E2ts de Projectile Subis +error.card.disabled=Cette carte est actuellement d\u00E9sactiv\u00E9e. +constants.card.attr.damage=D\u00E9g\u00E2ts d'attaque +constants.card.attr.damage.desc=Cette carte est tr\u00E8s utile pour r\u00E9duire les cartes les plus faibles. Il ne vivra peut-\u00EAtre pas longtemps, mais il mourra en essayant! +constants.card.attr.defense=D\u00E9fense +constants.card.attr.defense.desc=C'est une carte tr\u00E8s tanky qui est utile pour vous d\u00E9fendre ou d\u00E9fendre vos autres cartes. Il ne sera peut-\u00EAtre pas capable de vaincre un ennemi par lui-m\u00EAme, \u00E0 travers ! +constants.card.attr.health=Sant\u00E9 +constants.card.attr.health.desc=Une carte tr\u00E8s saine qui peut durer un moment. Les autres attributs peuvent \u00EAtre al\u00E9atoires. +constants.card.attr.knockback_resistance=R\u00E9sistance au recul +constants.card.attr.knockback_resistance.desc=Cette carte sait tenir bon. Selon la force avec laquelle il riposte, cela peut \u00EAtre un ennemi redoutable ! +constants.card.attr.speed=Vitesse +constants.card.attr.speed.desc=Une carte tr\u00E8s rapide qui peut \u00EAtre difficile \u00E0 toucher, surtout par les ennemis \u00E0 distance. Peut-\u00EAtre que c'est aussi roulable! +constants.card.attr.best=Meilleur Attribut: +constants.card.rideable=Utilisable: +constants.no=Non +constants.yes=Oui +constants.card.to_max=Au Maximum: +constants.card.to_max.endermen=%s Endermen \u00E0 tuer +constants.card.to_max.large_experience_books=%s Grands Livres D'exp\u00E9rience +constants.card.to_max.passive=%s Heures dans un Inventaire +constants.card.to_max.small_experience_books=%s Petits livres D'Exp\u00E9rience +constants.card.to_max.wardens=%s Gardiens \u00E0 Tuer +constants.card.to_max.withers=%s Withers \u00E0 Tuer +constants.card.to_max.zombies=%s Zombies \u00E0 Tuer +menu.catalogue=Catalogue | "%s" +menu.card_catalogue.view_crafting_recipe=Voir la Recette de Fabrication +menu.card_catalogue.crafting=Recette pour "%s" +menu.card_catalogue.view_in_catalogue=Afficher dans le Catalogue de Cartes +card.goat_gladiator=USHAAAAAAA! +card.goat_gladiator.desc=Le soldat a choisi la ch\u00E8vre la plus mauvaise pour l'accompagner dans la guerre du Wither. Il doit d\u00E9sormais vivre avec, m\u00EAme apr\u00E8s sa mort. +constants.card_equipment.ability.deflect=&aD\u00E9vier +constants.card_equipment.ability.deflect.desc=40% de chances de d\u00E9vier les projectiles. +card.sand_traveler=50 jours en Egypte! +card.sand_traveler.desc=Il a voyag\u00E9 si longtemps sur son fid\u00E8le chameau qu\u2019il a acquis une immunit\u00E9 contre toutes les chaleurs. Il court des ultra marathons pendant son temps libre. +card.sand_traveler.ability.blazing_hot=Flamboyant +card.sand_traveler.ability.blazing_hot.desc=La carte et son propri\u00E9taire sont tous deux immunis\u00E9s contre toute chaleur. +card.sand_traveler.ability.firecracker=P\u00E9tard +card.sand_traveler.ability.firecracker.desc=Tire des boules de feu explosives hors de sa bouche toutes les 7s. +card.the_immortal=ON VOUS A CONFI\u00C9!! +card.the_immortal.desc=Un ancien guerrier, survivant \u00E0 une grande trahison et litt\u00E9ralement trop en col\u00E8re pour mourir. +card.the_immortal.ability.immortality=Immortalit\u00E9 +card.the_immortal.ability.immortality.desc=Contient 1 totem et en gagne 1 tous les 10 niveaux. +card.the_immortal.ability.hardening=Durcissement +card.the_immortal.ability.hardening.desc=%bch chance de bloquer les d\u00E9g\u00E2ts entrants. +card.the_immortal.ability.soft_landing=Atterrissage en Douceur +card.the_immortal.ability.soft_landing.desc=Le joueur et la carte gagnent l\u2019immunit\u00E9 contre les d\u00E9g\u00E2ts de chute. +card.blizzard=Ne le chante pas. +card.blizzard.desc=Un simple magicien de glace fatigu\u00E9 des chansons de Disney. +card.blizzard.ability.blue_flame=Flamme Bleue +card.blizzard.ability.blue_flame.desc=Le propri\u00E9taire peut infliger 2s de d\u00E9g\u00E2ts de glace. +card.blizzard.ability.iceball=Boule de Glace +card.blizzard.ability.iceball.desc=Tire des boules de neige qui infligent 50 % de ses d\u00E9g\u00E2ts d'attaque. +card.blizzard.ability.storm=Temp\u00EAte +constants.card.to_max.huge_experience_books=%s Livres d'exp\u00E9rience \u00E9normes diff --git a/api/src/main/resources/lang/battlecards_tr.properties b/api/src/main/resources/lang/battlecards_tr.properties new file mode 100644 index 00000000..461db6e3 --- /dev/null +++ b/api/src/main/resources/lang/battlecards_tr.properties @@ -0,0 +1,380 @@ +card.wither_king.ability.poison_thorns=Zehirli Dikenler +card.diamond_golem.ability.launch=F\u0131rlat +card.diamond_golem.ability.launch.desc=%bch \u015Fans\u0131yla hedefin, her seviyede h\u0131z\u0131 %5 artarak ve \u015Fans\u0131 her seviyede %2.5 artarak, artan bir h\u0131zla. +card.diamond_golem.ability.thorns=Dikenler +card.diamond_golem.ability.thorns.desc=%bch \u015Fans\u0131yla sald\u0131ran\u0131n sald\u0131r\u0131 hasar\u0131n\u0131n %20'siyle vurulma \u015Fans\u0131. +card.wither_king.ability.lightning_thorns=Y\u0131ld\u0131r\u0131m Dikenleri +command.reload.reloaded=Yeniden Y\u00FCklendi BattleCards! G\u00FCncellemeleri g\u00F6rmek i\u00E7in JAR'\u0131n\u0131z\u0131 yeniden y\u00FCklemeniz/g\u00FCncellemeniz gerekebilir. +command.reload.reloading=Yeniden Y\u00FCkleniyor BattleCards... +constants.card=%s Kart +constants.card.creation_date=Olu\u015Fturulma Tarihi: %s +constants.card.deploy=%ss Yerle\u015Ftir +constants.card.generation=Nesil %s +constants.card.last_used_by=Son Kullanan: %s +constants.card.last_used_on=Son Kullan\u0131lan Tarih: %s +constants.card.left_click_view=G\u00F6r\u00FCnt\u00FClemek i\u00E7in Sol T\u0131kla +constants.card.next_level=Bir Sonraki Seviyeye %s +constants.card.right_click_deploy=Yerle\u015Ftirmek i\u00E7in Sa\u011F T\u0131kla +constants.card.statistics.attack_damage=Sald\u0131r\u0131 Hasar\u0131: %s +constants.card.statistics.card_experience=Kart Deneyimi: %s +constants.card.statistics.card_kills=Kart \u00D6ld\u00FCrmeleri: %s +constants.card.statistics.card_level=Kart Seviyesi: %s +constants.card.statistics.defense=Savunma: %s +constants.card.statistics.entity_kills=Varl\u0131k \u00D6ld\u00FCrmeleri: %s +constants.card.statistics.knockback_resistance=\u0130tme Direnci: %s +constants.card.statistics.max_card_experience=Maksimum Kart Deneyimi: %s +constants.card.statistics.max_card_level=Maksimum Kart Seviyesi: %s +constants.card.statistics.max_health=Maksimum Can: %s +constants.card.statistics.movement_speed=Hareket H\u0131z\u0131: %s +constants.card.statistics.player_kills=Oyuncu \u00D6ld\u00FCrmeleri: %s +constants.card.statistics.total_damage_dealt=Toplam Verilen Hasar: %s +constants.card.statistics.total_damage_received=Toplam Al\u0131nan Hasar: %s +constants.card.statistics.total_deaths=\u00D6l\u00FCmler: %s +constants.card.statistics.total_kills=Toplam \u00D6ld\u00FCrmeler: %s +constants.created_by=GamerCoder Taraf\u0131ndan Olu\u015Fturuldu +constants.level=Seviye %s +constants.maxed=MAKS\u0130MUM +constants.statistics=\u0130statistikler ve \u00D6zellikler +error.argument=L\u00FCtfen ge\u00E7erli arg\u00FCmanlar sa\u011Flay\u0131n. +error.argument.basic_type=Bir Temel Kart olu\u015Fturmak i\u00E7in varl\u0131k t\u00FCr\u00FCn\u00FC belirtmeniz gerekir! +error.argument.card=L\u00FCtfen ge\u00E7erli Bir Kart T\u00FCr\u00FC sa\u011Flay\u0131n. +error.argument.card.experience=L\u00FCtfen bu Kart i\u00E7in ge\u00E7erli bir deneyim miktar\u0131 sa\u011Flay\u0131n. +error.argument.card.level=L\u00FCtfen bu Kart i\u00E7in ge\u00E7erli bir seviye sa\u011Flay\u0131n. +error.argument.entity_type=L\u00FCtfen ge\u00E7erli bir Varl\u0131k T\u00FCr\u00FC sa\u011Flay\u0131n. +error.argument.int=L\u00FCtfen ge\u00E7erli bir tamsay\u0131 sa\u011Flay\u0131n. +error.argument.item=L\u00FCtfen ge\u00E7erli bir \u00F6\u011Fe sa\u011Flay\u0131n. +error.argument.item.held=L\u00FCtfen ge\u00E7erli bir \u00F6\u011Fe tutun. +error.argument.item.held.card=L\u00FCtfen ge\u00E7erli Bir Kart tutun. +error.argument.number=L\u00FCtfen ge\u00E7erli bir say\u0131 sa\u011Flay\u0131n. +error.card.cooldown=Bu kart kullan\u0131lm\u0131\u015F ve yeniden kullan\u0131ma haz\u0131r de\u011Fil. L\u00FCtfen %ss bekleyin. +error.card.use_limit=%ss i\u00E7inde %s Kart kullan\u0131m s\u0131n\u0131r\u0131na ula\u015Ft\u0131n\u0131z! L\u00FCtfen kartlar\u0131 tekrar kullanmak i\u00E7in bekleyin. +error.inventory.full=Envanteriniz Dolu! +error.permission=Bu komutu kullanma izniniz yok! +error.permission.argument=Bu alt komutu kullanma izniniz yok! +menu.card.info=Kart Bilgisi +menu.plugin_info=BattleCards Bilgisi +plugin.prefix=&d[&bBattleCards&d]&r +success.card.created=%s Kart ba\u015Far\u0131yla olu\u015Fturuldu! +card.wither_king.ability.user.wither_offensive=Wither Sald\u0131r\u0131s\u0131 +card.wither_king.ability.decree=Ferman +card.wither_king.ability.decay=\u00C7\u00FCr\u00FCme +card.wither_king.ability.decay.desc=Sald\u0131ran\u0131n, kart\u0131n \u00FCzerine %100 \u015Fans ve sahibine %bcu \u015Fansla 6 saniye boyunca Wither Etkisi almas\u0131. +card.wither_king.ability.decree.desc=Her %bcint, belirli bir yar\u0131\u00E7ap i\u00E7indeki t\u00FCm nether d\u00FC\u015Fman\u0131 varl\u0131klar art\u0131k kart\u0131n hedefini hedef al\u0131r. Yar\u0131\u00E7ap ba\u015Flang\u0131\u00E7ta 25.0'dir ve her seviyede 2.0 artarak maksimumda 60.0'a ula\u015F\u0131r. +card.wither_king.ability.lightning_thorns.desc=%bch \u015Fans\u0131yla sald\u0131ran\u0131n y\u0131ld\u0131r\u0131m ile vurulma \u015Fans\u0131. +card.wither_king.ability.poison_thorns.desc=%bch \u015Fansla sald\u0131ran\u0131n 5 saniye boyunca Zehir Etkisi almas\u0131, her seviyede 2 saniye artarak ve maksimumda 60 saniyeye ula\u015Farak. +card.wither_king.ability.user.wither_offensive.desc=%bch \u015Fansla kart sahibinin 60 saniye boyunca Wither Etkisi II vermesi. +card.mercenary.ability.rage=Rage +card.mercenary.ability.rage.desc=Her %bcint, 20 saniye boyunca G\u00FC\u00E7 III kazan\u0131r ve 15 saniye boyunca H\u0131z II kazan\u0131r. +card.eye_of_enderman.ability.beam=Beam +card.eye_of_enderman.ability.end_aspect=End Aspect +card.eye_of_enderman.ability.beam.desc=Kart Hedefi, End Kristal I\u015F\u0131n\u0131 ile her %bcint hasar g\u00F6r\u00FCr. +card.eye_of_enderman.ability.end_aspect.desc=Kart Sahibi, End Boyutlar\u0131nda 2x Hasar verir. +card.frost_bear.ability.frostbite=Frostbite +card.frost_bear.ability.ice_defense=Ice Defense +card.frost_bear.ability.ice_aspect=Ice Aspect +card.frost_bear.ability.frostbite.desc=%bch \u015Fansla kart hedefine 3 saniye donma etkisi ekler. +card.frost_bear.ability.ice_aspect.desc=%bch \u015Fansla kart sahibi, 0.75 saniye donma etkisi verir. +card.frost_bear.ability.ice_defense.desc=Belirli karl\u0131/buzlu biyomlarda kart kar\u015F\u0131s\u0131nda %bch \u015Fans\u0131 ve sahibe kar\u015F\u0131 %bcu \u015Fans\u0131 ile -25% hasar alma \u015Fans\u0131. +card.bomberman.ability.exploding=Exploding +card.bomberman.ability.exploding.desc=%bch \u015Fansla kart\u0131n hedefinde blok k\u0131rmayan bir patlama olu\u015Fturur. +card.bomberman.ability.primed=Primed +card.bomberman.ability.primed.desc=Vuruldu\u011Funda, %bch \u015Fansla patlam\u0131\u015F bir TNT'nin herkesi incitece\u011Fi bir patlama olu\u015Fur. +card.bomberman.ability.tntlings=TNTLings +card.bomberman.ability.tntlings.desc=Her %bcint, hedefi hasar verebilen, 6 saniye sonra patlayan en fazla 6 zombi \u00E7a\u011F\u0131r\u0131r. +card.bomberman.ability.meteor=Meteor +card.bomberman.ability.meteor.desc=Her %bcint, Kart Hedefinin \u00FCzerinde b\u00FCy\u00FCk, patlayan bir ate\u015F topu \u00E7a\u011Fr\u0131l\u0131r. +card.bomberman=Bay Bombasic, Bomba Fantastik +card.bomberman.desc=Elit creepers taraf\u0131ndan d\u00F6v\u00FClen, patlama sanat\u0131nda e\u011Fitilen bu patlay\u0131c\u0131 kart. +card.diamond_golem=G\u00F6r\u00FCn\u00FC\u015Fe g\u00F6re g\u00F6lge boyunca gidiyorsun, Jimbo. +card.diamond_golem.desc=Bu sert kafal\u0131 kart, \u00E7e\u015Fitli k\u00E2hinlerin demiri elmasla de\u011Fi\u015Ftirme denemesiydi. +card.eye_of_enderman=Hatta arama ge\u00E7mi\u015Finizi bile g\u00F6rebilirim. +card.eye_of_enderman.desc=Bir havu\u00E7 ve koro meyvesi diyetine tak\u0131nt\u0131l\u0131 yan\u0131t olarak ba\u015F\u0131ndaki ender kristali b\u00FCy\u00FCd\u00FC. +card.frost_bear=Hay\u0131r, da\u011Flara t\u0131rmanmay\u0131 sevmem. +card.frost_bear.desc=100 y\u0131l boyunca da\u011Flarda e\u011Fitim g\u00F6rd\u00FCkten sonra, bu ak\u0131ll\u0131 ay\u0131 daha da g\u00FC\u00E7lendi. +card.wither_king=Kral olmak g\u00FCzeldir. +card.wither_king.desc=Kaynakl\u0131 ve g\u00FC\u00E7l\u00FC bir kart, kemiklerinin \u00E7o\u011Fu nether'da kayboldu. +card.mercenary=San\u0131r\u0131m bu, G\u00FCm\u00FC\u015F Araba'n\u0131n ayn\u0131 t\u00FCrdeki kart\u0131. +card.mercenary.desc=Ya\u011Fmalay\u0131c\u0131lar aras\u0131nda dola\u015Fan bir s\u00F6ylenti, crossbow sanat\u0131n\u0131 reddediyor ve daha \u00E7ok saplay\u0131c\u0131 bir meslek se\u00E7iyor. +menu.card_table=Kart At\u00F6lyesi +success.item.given=\u00D6\u011Fe ba\u015Far\u0131yla al\u0131nd\u0131! +card.pitbull.ability.bite=Bite +card.pitbull=HAF! +card.pitbull.desc=Bu sad\u0131k k\u00F6pek bir\u00E7ok \u015Fey ya\u015Fad\u0131, hala sahibini korumaya haz\u0131r. +card.pitbull.ability.bite.desc=%bch \u015Fansla hedefe verilen hasar\u0131 %5 art\u0131rma \u015Fans\u0131. +card.redstone_zombie=Sadece basit bir redstone. +card.redstone_zombie.desc=Mob'lar\u0131 k\u00F6t\u00FC niyetli bir \u015Fekilde \u00F6ld\u00FCren mekanik bir canavar. +card.silverfish_hive.ability.hivemind=Hivemind +card.silverfish_hive=Bunlardan binlerce var. +card.silverfish_hive.desc=Bir \u00E7\u00F6k\u00FC\u015F ma\u011Faras\u0131nda binlerce silverfish yumurtas\u0131yla d\u00F6v\u00FClen yeni bir hanedanl\u0131k. +card.silverfish_hive.ability.hivemind.desc=Her %bcint, 4-10 adet silverfish \u00E7a\u011F\u0131r\u0131r. +card.skeleton_soldier=Her zaman emirlere uyun, \u00F6zellikle de sizi \u00F6ld\u00FCren emirlere. +card.skeleton_soldier.desc, \u00F6l\u00FCmden sonra bile sad\u0131k, bu asker Wither Sava\u015F\u0131'nda sava\u015Ft\u0131. +card.sniper.ability.triple_shot=Triple Shot +card.sniper=D\u00F6rt nala isabet. +card.sniper.desc=Overworld'\u00FCn en iyi \u00F6l\u00FC at\u0131c\u0131lardan biri, belirsiz bir kafa say\u0131s\u0131na sahip. +card.sniper.ability.triple_shot.desc=\u00DC\u00E7 ok atma \u015Fans\u0131 %20, her seviyede %5 artar. +card.spider_hive.ability.colony=Colony +card.spider_hive.ability.colony.desc=Her %bcint, kart\u0131n sa\u011Fl\u0131\u011F\u0131n\u0131n %60'\u0131yla 3-7 adet ma\u011Fara \u00F6r\u00FCmce\u011Fi \u00E7a\u011F\u0131r\u0131r. +card.spider_hive=Bippity Boppity, kan\u0131n art\u0131k benim mal\u0131m. +card.spider_hive.desc=Binlerce y\u0131l s\u00FCren klonlama, binlerce \u00F6r\u00FCmcek hanedanl\u0131\u011F\u0131 yaratt\u0131. +card.spider_queen.ability.poisoning=Poisoning +card.spider_queen.ability.webbing=Webbing +card.spider_queen.ability.matriarchy=Matriarchy +card.spider_queen.ability.spiderlings=Spiderlings +card.spider_queen.ability.fangs=Fangs +card.spider_queen.ability.fangs.desc=Kart Sahibi, 4 saniye boyunca Zehir verir. +card.spider_queen.ability.matriarchy.desc=En b\u00FCy\u00FCk o\u011Flunu \u00F6ld\u00FCrme, o\u011Ful ona s\u0131k\u0131 s\u0131k\u0131ya ba\u011Fl\u0131. +card.spider_queen.ability.poisoning.desc=2 saniye boyunca Zehir verir, her 5 seviyede bir 1 saniye artar ve her 25 seviyede bir g\u00FC\u00E7lenir. +card.spider_queen.ability.spiderlings.desc=Vuruldu\u011Funda, %bch \u015Fansla bir minion ma\u011Fara \u00F6r\u00FCmce\u011Fi \u00E7a\u011F\u0131rmak. +card.spider_queen.ability.webbing.desc=%bch \u015Fansla hedefe \u00F6r\u00FCmcek a\u011F\u0131 yerle\u015Ftirme ve 1 saniye boyunca yava\u015Fl\u0131k verme, her 5 seviyede bir 1 saniye artar ve her 30 seviyede bir g\u00FC\u00E7lenir. +card.spider_queen=Orijinal \u00D6r\u00FCmcek. +card.spider_queen.desc="Spider Supreme" olarak bilinen, Wither Sava\u015F\u0131'n\u0131 hayatta kalan son \u00F6r\u00FCmcek, demir yumru\u011Fuyla krall\u0131\u011F\u0131n\u0131 olu\u015Fturdu. +card.stone_archer=Pling. +card.stone_archer.desc=Bir ta\u015F blo\u011Fu ba\u015F\u0131na d\u00FC\u015Fen sakar bir ok\u00E7u \u00F6ld\u00FC. +card.thunder_revenant.ability.heat_resistance=Heat Resistance +card.thunder_revenant.ability.electricity=Electricity +card.thunder_revenant.ability.thunderbolt=Thunderbolt +card.thunder_revenant.ability.paralysis=Paralysis +card.thunder_revenant=Zeus gizlice orta seviyede. +card.thunder_revenant.desc=\u015Eim\u015Fir tanr\u0131lar\u0131yla yar\u0131\u015Fan ve hava kadar eski olan bir kart. +card.thunder_revenant.ability.electricity.desc=%bch \u015Fansla +%10 hasar ve +%2 saniye ate\u015F hasar\u0131. +card.thunder_revenant.ability.heat_resistance.desc=Ate\u015F ve \u015Eim\u015Fir Hasar\u0131 etkisi yok. +card.thunder_revenant.ability.paralysis.desc=%bch \u015Fansla hedefe 4 saniye boyunca Yava\u015Fl\u0131k X ve 12 saniye boyunca Zay\u0131fl\u0131k V verme \u015Fans\u0131. +card.thunder_revenant.ability.thunderbolt.desc=%bch \u015Fansla (kart kar\u015F\u0131s\u0131nda) ve %bcu \u015Fansla (sahibe kar\u015F\u0131) hedefe \u015Fim\u015Firle vurma \u015Fans\u0131. Kart +%15 hasara sahiptir ve sahip 5 ile 20 aras\u0131nda hasar ekler. +card.undead_lumberjack.ability.bleeding=Bleeding +card.undead_lumberjack=Ben sadece bir oduncuydum, odun i\u015Flerini yap\u0131yordum. +card.undead_lumberjack.desc=Bir ma\u011Fara \u00E7\u00F6kmesi, bu talihsiz ki\u015Finin \u00F6l\u00FCm\u00FCne neden oldu. Hala en sevdi\u011Fi ormanda tak\u0131l\u0131yor... +card.undead_lumberjack.ability.bleeding.desc=%bch \u015Fansla her 3.25 saniyede iki kez sald\u0131r\u0131 hasar\u0131n\u0131n %10'unu vermeye \u015Fans\u0131, miktar her 8 seviyede bir artar. +card.witherman.ability.wither=Wither +card.witherman=NETHER'da Yap\u0131ld\u0131! +card.witherman.desc=Bu h\u0131zl\u0131 kart, Wither Krall\u0131\u011F\u0131'ndaki y\u00FCksek sesli bir tart\u0131\u015Fma gecesinde ke\u015Ffedildi. +card.witherman.ability.wither.desc=%bch \u015Fansla (kart kar\u015F\u0131s\u0131nda) ve %bcu \u015Fansla (sahibe kar\u015F\u0131) 5 saniye boyunca Wither Etkisi verme \u015Fans\u0131. +card.witherman.ability.wither_immune=Wither Immune +card.witherman.ability.wither_immune.desc=T\u00FCm Wither Hasarlar\u0131na Kar\u015F\u0131 Ba\u011F\u0131\u015F\u0131kt\u0131r. +card.bandit.ability.bullet=Bullet +card.bandit=H\u0131zla \u00E7al\u0131yor... +card.bandit.desc=Bu amat\u00F6r ok\u00E7u, efendisi onu unuttuktan sonra kendi ba\u015F\u0131na savunmak zorunda kald\u0131. +card.bandit.ability.bullet.desc=+%50 Projeksiyon H\u0131z\u0131 +card.emerald_husk=Tanklar en k\u00F6t\u00FCs\u00FC de\u011Fil! +card.emerald_husk.desc=Ore yanl\u0131\u015F se\u00E7en tank hayranlar\u0131. +card.gold_skeleton=Nether Prens'in En \u0130yi Dostu. +card.gold_skeleton.desc=Nether Krall\u0131\u011F\u0131 alt\u0131nda bir elit sava\u015F\u00E7\u0131, \u00F6l\u00FCms\u00FCzl\u00FCk g\u00FCc\u00FC ile \u00F6d\u00FCllendirildi (herkes gibi.) +card.mesa_zombie.ability.fire_aspect=Fire Aspect +card.mesa_zombie=Evet! Ben buraday\u0131m! +card.mesa_zombie.desc=Y\u00FCz y\u0131l s\u00FCren bir kum \u00E7\u0131\u011F\u0131n\u0131n ard\u0131ndan uyanan bu yan\u0131c\u0131-zombi. +card.mesa_zombie.ability.fire_aspect.desc=%bch \u015Fansla ate\u015F hasar\u0131 verme \u015Fans\u0131. +card.phantom_rider.ability.phantom_bow=Phantom Bow +card.phantom_rider=G\u00F6ky\u00FCz\u00FCne do\u011Fru! +card.phantom_rider.desc=Bu asi s\u00FCvari ne yapabilirse yapar, pet phantom'unu korur. +card.phantom_rider.ability.phantom_bow.desc=Kart Hedefleri 5 saniye - 10 saniye boyunca havada as\u0131l\u0131 kal\u0131r. +card.miner=Sadece kazmaya devam et, sadece kazmaya devam et... +card.miner.ability.haste=Haste +card.miner.ability.haste.desc=Kart Sahibi aktifken H\u0131z II kazan\u0131r. +card.miner.desc=Ma\u011Faras\u0131 \u00E7\u00F6kt\u00FC\u011F\u00FCnde \u00E7\u0131k\u0131\u015F\u0131n\u0131 engelleyen ma\u011Fara adam\u0131, g\u00F6r\u00FCn\u00FC\u015Fte k\u0131r\u0131lmaz kazma ile maden \u00E7al\u0131\u015Fmaya devam etti, hatta \u00F6l\u00FCm\u00FCnden sonra bile. +card.prince_husk=Senin burada hi\u00E7 g\u00FCc\u00FCn yok. +card.prince_husk.desc=Kontrol\u00FCn\u00FC s\u00FCrd\u00FCrmeye \u00E7al\u0131\u015Fan m\u00FCcadele eden bir +card.prince_husk.ability.royal_guard.desc=Kraliyet Muhaf\u0131z\u0131 +card.suspicious_zombie.desc=Woololoo! +card.suspicious_zombie.ability.fangs.desc=Her %bcint, etraf\u0131nda di\u015Fler \u00E7a\u011F\u0131r\u0131r. +card.suspicious_zombie.ability.effect.desc=4 saniye ile 11 saniye aras\u0131nda rastgele bir olumsuz etkiyi ve amplifikat\u00F6r\u00FC verir. +card.suspicious_zombie.ability.lightning.desc=%bch \u015Fans (kart kar\u015F\u0131s\u0131nda) ve %bcu \u015Fans (sahip kar\u015F\u0131) hasar verene y\u0131ld\u0131r\u0131m \u00E7arpmas\u0131. +card.warrior_husk=WAAAAAAARRRHHH! +card.warrior_husk.desc=Prens i\u00E7in bir koz kart\u0131 olarak kullan\u0131lan g\u00FCvenilir ve sad\u0131k bir ruh. +card.inferno_blaze.ability.fire_thorns.desc=Alevli Dikenler +card.inferno_blaze.desc=Nether Sava\u015F\u0131'nda kaybolan karde\u015Flerini intikam almak i\u00E7in haz\u0131r, enerji dolu bir kart. +card.inferno_blaze.ability.heat_aspect.desc=Nether'da, kart kar\u015F\u0131s\u0131nda %bch \u015Fans (kart kar\u015F\u0131) ve %bcu \u015Fans (sahip kar\u015F\u0131) i\u00E7in +%25 hasar. +card.inferno_blaze.ability.heat_protection.desc=Nether'da, %bch \u015Fans (kart kar\u015F\u0131) ve %bcu \u015Fans (sahip kar\u015F\u0131) ile varl\u0131klardan al\u0131nan hasarda -%15 \u015Fans. +card.inferno_blaze.ability.heat_shield.desc=Nether'da, varl\u0131klardan gelecek hasar\u0131 engellemek i\u00E7in %bch \u015Fans. +card.inferno_blaze.ability.ghast.desc=Her %bcint, patlay\u0131c\u0131 bir alev topu ate\u015Fler. +card.knight=En k\u0131sa yol, dolamba\u00E7l\u0131 yoldur. +card.knight.desc=Wither Sava\u015F\u0131'n\u0131 sona erdirmeye katk\u0131da bulunan \u00E7al\u0131\u015Fkan bir ruh. +card.lapis_drowned.ability.disenchantment.desc=Smite Hasar\u0131'na kar\u015F\u0131 ba\u011F\u0131\u015F\u0131k. +card.lapis_drowned=Smite kullanabilece\u011Fini d\u00FC\u015F\u00FCnd\u00FCn, ama benim, Lapis Drowned'um! +card.lapis_drowned.desc=Hen\u00FCz ke\u015Ffedilmemi\u015F bir ge\u00E7mi\u015Fi olan sihirli bir yarat\u0131k. +card.raider.ability.raid_golems.desc=Her %bcint, sava\u015Fta raider'a yard\u0131m eden Demir Golemleri \u00E7a\u011F\u0131r\u0131r. +card.raider=GIMMEE! +card.raider.desc=Basit bir soyguncu, "basit" soyguncu \u015Feylerini yap\u0131yor. +card.raider.ability.bombs.desc=Kart hedeflerinde y\u0131k\u0131c\u0131 bir patlama yarat\u0131r. +card.raider.ability.illusioner.desc=Her %bcint, sava\u015Fa bir Illusioner \u00E7a\u011F\u0131r\u0131r. +card.nether_prince.ability.firepower=Ate\u015F G\u00FCc\u00FC +card.nether_prince.ability.nether_aspect.desc=Kart Sahibi +%10 ate\u015F hasar\u0131 uygular. +card.nether_prince.ability.firepower.desc=30 HP'lik bir Blaze \u00E7a\u011F\u0131r\u0131r, HP'si Kart Seviyesi ba\u015F\u0131na 0.5 ile azal\u0131r. +card.nether_prince=Ben de kendi k\u0131sm\u0131ma d\u00FC\u015Feni yap\u0131yorum! +card.nether_prince.desc=Bir Wither Kral\u0131'ndan liderli\u011Fi devralmaya hevesli, tutkulu bir bar\u0131\u015Fsever lider. +card.nether_prince.ability.decree.desc=Her %bcint, belirli bir yar\u0131\u00E7ap i\u00E7indeki \u00E7o\u011Fu Nether d\u00FC\u015Fman\u0131 \u015Fimdi kart\u0131n hedefini hedef al\u0131r. Yar\u0131\u00E7ap, 20.0'de ba\u015Flar ve seviye ba\u015F\u0131na 2.0 artar, maksimum 40.0'de sona erer. +card.golden_wizard.ability.channeling.desc=Kanal +card.golden_wizard=Alt\u0131n Bilim d\u00FCnyan\u0131n en iyisidir! +card.golden_wizard.desc=Hardcore Illager Savunucusu ve aktif bir b\u00FCy\u00FCc\u00FC. +card.netherite_piglin.ability.netherite_rage.desc=Her %bcint, %15 seviye ba\u015F\u0131na 1 artacak \u015Fekilde 5 saniye boyunca G\u00FC\u00E7 III kazan\u0131r. +card.netherite_piglin.ability.hoglin.desc=%bch \u015Fans\u0131 ile Hoglin'lerinden birini \u00E7a\u011F\u0131rmak i\u00E7in. +card.netherite_piglin.ability.heat_shield.desc=Lava Hasar\u0131na kar\u015F\u0131 ba\u011F\u0131\u015F\u0131kt\u0131r. +card.netherite_piglin=Ben yaln\u0131z \u00E7al\u0131\u015F\u0131yorum. +card.netherite_piglin.desc=Yar\u0131 zamanl\u0131 bir suikast\u00E7\u0131, yaln\u0131z \u00E7al\u0131\u015F\u0131yor. Hen\u00FCz bir ili\u015Fkiye giremedi. +card.sealord.ability.sea_military=Deniz Askeri +card.sealord=Poseidon'u tan\u0131masam da, d\u00FCnyan\u0131n en k\u00F6t\u00FC varl\u0131klar\u0131ndan biri oldu\u011Funu s\u00F6yleyebilirim. +card.sealord.desc=Sular\u0131n efendisi, Poseidon bile kendisini rakip olarak adland\u0131ramazd\u0131. +card.sealord.ability.sea_military.desc=Kart\u0131n sava\u015Fta yard\u0131ma gelmesi i\u00E7in 2-5 Drowned ve Zombi \u00E7a\u011F\u0131r\u0131r. +card.sealord.ability.channeling=Kanal +card.sealord.ability.channeling.desc=%bch \u015Fans\u0131yla hedefe y\u0131ld\u0131r\u0131m \u00E7arpmas\u0131, ek hasar verir. +card.sealord.ability.wet=Nemli +card.sealord.ability.wet.desc=Kart ve Sahip, t\u00FCm Ate\u015F ve Lava hasarlar\u0131ndan ba\u011F\u0131\u015F\u0131kt\u0131r. +card.sealord.ability.thundering=G\u00F6k g\u00FCr\u00FClt\u00FCs\u00FC +card.sealord.ability.thundering.desc=Her %bcint, d\u00FCnyay\u0131 g\u00F6k g\u00FCr\u00FClt\u00FCl\u00FC yapar ve 10 metre yar\u0131\u00E7ap\u0131ndaki t\u00FCm d\u00FC\u015Fmanlara y\u0131ld\u0131r\u0131m \u00E7arpar. +error.card.max_spawned=\u00C7ok fazla kart \u00E7a\u011F\u0131rd\u0131n! Maksimum: %s +time.seconds=%s Saniye +time.years=%s Y\u0131l +time.months=%s Ay +time.weeks=%s Hafta +time.minutes=%s Dakika +time.hours=%s Saat +time.days=%s G\u00FCn +error.inventory.full.card_dropped=Envanterin dolu! Bir Kart konumuna b\u0131rak\u0131ld\u0131. +error.cooldown=Bu eylem \u015Fu anda beklemede. L\u00FCtfen %s bekleyin. +menu.card_quests=Kart G\u00F6revleri +constants.completed=%s Tamamland\u0131 +menu.card_quests.card_hunter=Kart Avc\u0131s\u0131 +menu.card_quests.entity_hunter=Varl\u0131k Avc\u0131s\u0131 +menu.card_quests.damager=Hasar Verici +menu.card_quests.tank=Z\u0131rhl\u0131 +menu.card_quests.reviver=Canland\u0131r\u0131c\u0131 +menu.card_quests.card_hunter.completion=%s Kart \u00D6ld\u00FCrme +menu.card_quests.damager.completion=%s Hasar Verme +menu.card_quests.entity_hunter.completion=%s Varl\u0131k/Oyuncu \u00D6ld\u00FCrme +menu.card_quests.reviver.completion=%s Kez \u00D6lme +menu.card_quests.tank.completion=%s Hasar Alma +constants.next=\u0130leri +constants.prev=Geri +constants.back=Geri +constants.total_experience_reward=%s Deneyim \u00D6d\u00FCl\u00FC +constants.locked=Kilitli! +constants.unlocks_at_level=Seviye %s'de A\u00E7\u0131l\u0131r +card.necromancer=Kalk, hizmetk\u00E2rlar\u0131m! +card.necromancer.desc=Arkada\u015Fl\u0131k i\u00E7in \u00E7aresizce ihtiya\u00E7 duyan ya\u015Fl\u0131 bir ruh. Belki biraz fazla arkada\u015F... +card.necromancer.ability.bullet=Mermi +card.necromancer.ability.bullet.desc=Her %bcint, hedefine do\u011Fru ate\u015Flenen bir Shulker Mermisi. +card.necromancer.ability.rise_of_the_undead=\u00D6l\u00FClerin Y\u00FCkseli\u015Fi +card.necromancer.ability.rise_of_the_undead.desc=Her %bcint, sava\u015Fmas\u0131 i\u00E7in bir iskelet \u00E7a\u011F\u0131r\u0131r. +card.necromancer.ability.lightning=Y\u0131ld\u0131r\u0131m +card.necromancer.ability.lightning.desc=%bch \u015Fans\u0131yla hedefin y\u0131ld\u0131r\u0131mla vurulmas\u0131. +card.necromancer.ability.undead_monster=\u00D6l\u00FC Canavar +card.necromancer.ability.undead_monster.desc=Her %bcint, daha g\u00FC\u00E7l\u00FC bir hizmetkar \u00E7a\u011F\u0131r\u0131r. +card.eternal_husk=\u00D6l\u00FCm oldum, d\u00FCnyalar\u0131n yok edeni. +card.eternal_husk.desc=Sessiz ve \u00F6l\u00FCmc\u00FCl bir kart tipi, b\u00FCt\u00FCn \u00F6l\u00FClerin itaat etmek zorunda oldu\u011Fu bir liderlik. +card.eternal_husk.ability.deathly_healing=\u00D6l\u00FCmc\u00FCl \u0130yile\u015Fme +card.eternal_husk.ability.deathly_healing.desc=Sahip, Zehir Hasar\u0131'ndan ve Kart en az Seviye 20 ise Wither Hasar\u0131'ndan sa\u011Fl\u0131k kazan\u0131r. +card.eternal_husk.ability.charge=Sald\u0131r\u0131 +card.eternal_husk.ability.charge.desc=%bch \u015Fans\u0131yla al\u0131nan hasar\u0131n yar\u0131s\u0131n\u0131n \u015Earj Hasar\u0131'na eklenmesi ve bir hedefi vurdu\u011Funda al\u0131nan t\u00FCm hasar\u0131n serbest b\u0131rak\u0131lma \u015Fans\u0131 %10. +card.eternal_husk.ability.advisors=Dan\u0131\u015Fmanlar +card.eternal_husk.ability.advisors.desc=En fazla 4 \u00E7ok g\u00FC\u00E7l\u00FC hizmetkar h\u00FCk\u00FCmleri \u00E7a\u011F\u0131r\u0131r. +card.eternal_husk.ability.undead_supreme=\u00DCst\u00FCn \u00D6l\u00FC +card.eternal_husk.ability.undead_supreme.desc=Her %bcint, 15.0 metre yar\u0131\u00E7ap\u0131ndaki kart\u0131n hedefini hedef alan t\u00FCm \u00F6l\u00FC olmayan kart ve hizmetk\u00E2r. Yar\u0131\u00E7ap seviye ba\u015F\u0131na 2.25 artar ve 50.0 metreye kadar s\u0131n\u0131rl\u0131d\u0131r. +menu.card_equipment=Kart Ekipman\u0131 +constants.card_equipment.damage=%s Sald\u0131r\u0131 Hasar\u0131 +constants.card_equipment.defense=%s Savunma +constants.card_equipment.speed=%s H\u0131z +constants.card_equipment.knockback_resistance=%s Geri \u0130tme Direnci +constants.card_equipment.health=%s Sa\u011Fl\u0131k +constants.effective_modifiers=Etkili Modifikat\u00F6rler: +constants.none=Hi\u00E7biri +constants.card_equipment.ability.flame=&6Alev +constants.card_equipment.ability.flame.desc=3 saniye Alev Hasar\u0131 verir. +constants.card_equipment.ability.freezing=&bDondurma +constants.card_equipment.ability.freezing.desc=2.25 saniye Dondurma Hasar\u0131 verir. +constants.card_equipment.ability.lightning=Y\u0131ld\u0131r\u0131m +constants.card_equipment.ability.lightning.desc=\u015Eim\u015Fek Hasar\u0131 verme olas\u0131l\u0131\u011F\u0131 %50. Olas\u0131l\u0131k, Kart Seviyesi ba\u015F\u0131na %5 artar. +constants.card_equipment.ability.pricking=&2Dikenli +constants.card_equipment.ability.pricking.desc=Vuruldu\u011Funda %75 \u015Fansla 1.5 hasar verir. +constants.card_equipment.ability.flame_thorns=&6Alev Dikenleri +constants.card_equipment.ability.flame_thorns.desc=Vuruldu\u011Funda %80 \u015Fansla 1.5 saniye Alev Hasar\u0131 verir. +constants.card_equipment.ability.slowing=&8Yava\u015Flatma +constants.card_equipment.ability.slowing.desc=%75 \u015Fansla 2 saniye Yava\u015Flatma ekler ve +1.5 Hasar verir. +error.card.equipment.input_1=Kart Ekipman\u0131 yaln\u0131zca yuva ba\u015F\u0131na 1 \u00F6\u011Fe miktar\u0131n\u0131 destekler. Ekstralar dolu bir envanterden dolay\u0131 b\u0131rak\u0131ld\u0131. +error.card.equipment.one_special=Kartlar yaln\u0131zca bir \u00F6zel t\u00FCrde kart ekipman\u0131 takabilir. +constants.card_equipment.potion_status.both=Kart ve Kullan\u0131c\u0131 +constants.card_equipment.potion_status.user_only=Yaln\u0131zca Kullan\u0131c\u0131 +constants.card_equipment.potion_status.card_only=Yaln\u0131zca Kart +constants.coming_soon=Yak\u0131nda! +constants.place_items=\u00D6\u011Feleri Yerle\u015Ftir +constants.confirm=Onayla +constants.cancel=\u0130ptal +constants.chance=%s \u015Eans +constants.card_chances=Kart \u015Eanslar\u0131 +constants.card_power=%s Kart G\u00FCc\u00FC +card.aquatic_assassin.ability.super_conduit=S\u00FCper Kond\u00FCkt\u00F6r +card.aquatic_assassin.ability.super_conduit.desc=Kart\u0131n spawnlanan t\u00FCm m\u00FCttefikleri (sahip ve m\u00FCttefik kartlar dahil) Kond\u00FCkt\u00F6r G\u00FCc\u00FC II kazan\u0131r. +card.aquatic_assassin=Sen \u00E7ok yaramaz bir Koruyucu oldun. +card.aquatic_assassin.desc=Sadece evcil Guardian'\u0131na g\u00FCvenen gizemli bir birey. +card.aquatic_assassin.ability.paralysis=Fel\u00E7 +card.aquatic_assassin.ability.paralysis.desc=Guardian'\u0131n vuru\u015Flar\u0131 Blindness II ve Weakness III verir. +card.aquatic_assassin.ability.airbending=Hava B\u00FCkme +card.aquatic_assassin.ability.airbending.desc=Su i\u00E7inde hedef, kart kar\u015F\u0131s\u0131nda %bch \u015Fans\u0131 (kart kar\u015F\u0131s\u0131nda) ve %bcu \u015Fans\u0131 (sahip kar\u015F\u0131s\u0131nda) ile kalan havas\u0131n\u0131 kaybeder. +card.magma_jockey.ability.nether_magic=Nether B\u00FCy\u00FCs\u00FC +card.magma_jockey.ability.nether_magic.desc=Pi\u011Flin taraf\u0131ndan ate\u015Flenen cisimler, hedefine y\u00F6nlendirilir. +card.magma_jockey=Boing! Boing! Boing! +card.magma_jockey.desc=Sihirli crossbow'un g\u00FCc\u00FCn\u00FC kullanarak yaln\u0131z bir birey. +menu.card_combiner=Kart Birle\u015Ftirici +menu.card_combiner.not_enough_power=En az 50 Kart G\u00FCc\u00FCne ihtiya\u00E7 var! +card.piglin_titan=BURAYA GEL! +card.piglin_titan.desc=S\u00FCper d\u00F6v\u00FC\u015F becerileri ve g\u00FCc\u00FC ile piglinler aras\u0131nda bir efsane, bir\u00E7ok e\u011Fitimli h\u00FCk\u00FCml\u00FC i\u00E7in bir kahraman. +card.piglin_titan.ability.lava_walker=Lava Y\u00FCr\u00FCy\u00FCc\u00FC +card.piglin_titan.ability.lava_walker.desc=3 metre yar\u0131\u00E7ap\u0131ndaki t\u00FCm su ge\u00E7ici olarak magma haline gelir. +card.piglin_titan.ability.landing=\u0130ni\u015F +card.piglin_titan.ability.landing.desc=Kullan\u0131c\u0131 d\u00FC\u015Fme hasar\u0131ndan muaf tutulur. +card.piglin_titan.ability.leap=Z\u0131plama +card.piglin_titan.ability.leap.desc=Her %bcint, hedefine z\u0131plar. Yeterince yak\u0131nsa, ekstra %2 hasar verir. +constants.card_equipment.ability.chainmail=&7Zincir Z\u0131rh +constants.card_equipment.ability.chainmail.desc=-35% Mermi Hasar\u0131 Al\u0131n\u0131r +constants.card.attr.damage=Sald\u0131r\u0131 hasar\u0131 +constants.card.attr.damage.desc=Bu kart, zay\u0131f kartlar\u0131n azalt\u0131lmas\u0131nda \u00E7ok kullan\u0131\u015Fl\u0131d\u0131r. Uzun ya\u015Famayabilir ama denerken \u00F6lecek! +constants.card.attr.defense=Savunma +constants.card.attr.defense.desc=Bu, sizi veya di\u011Fer kartlar\u0131n\u0131z\u0131 savunmak i\u00E7in yararl\u0131 olan \u00E7ok dayan\u0131kl\u0131 bir kartt\u0131r. Bir d\u00FC\u015Fman\u0131 tek ba\u015F\u0131na yenemeyebilir! +constants.card.attr.health=Sa\u011Fl\u0131k +constants.card.attr.health.desc=Bir s\u00FCre ortal\u0131kta dola\u015Fabilecek \u00E7ok sa\u011Fl\u0131kl\u0131 bir kart. Di\u011Fer \u00F6zellikler isabetli veya ka\u00E7\u0131r\u0131lm\u0131\u015F olabilir. +constants.card.attr.knockback_resistance=Geri Tepme Direnci +constants.card.attr.knockback_resistance.desc=Bu kart kendi ayaklar\u0131 \u00FCzerinde durmay\u0131 biliyor. Ne kadar sert kar\u015F\u0131l\u0131k verdi\u011Fine ba\u011Fl\u0131 olarak bu zorlu bir d\u00FC\u015Fman olabilir! +constants.card.attr.speed=H\u0131z +constants.card.attr.speed.desc=\u00D6zellikle menzilli d\u00FC\u015Fmanlar taraf\u0131ndan vurulmas\u0131 zor olabilecek \u00E7ok h\u0131zl\u0131 bir Kart. Belki de s\u00FCr\u00FClebilir! +constants.card.attr.best=En \u0130yi \u00D6zellik: +constants.card.rideable=S\u00FCr\u00FClebilir: +constants.no=Hay\u0131r +constants.yes=Evet +constants.card.to_max=Maksimuma: +constants.card.to_max.endermen=%s \u00D6ld\u00FCr\u00FClecek Endermen +constants.card.to_max.large_experience_books=%s B\u00FCy\u00FCk Deneyim Kitaplar\u0131 +constants.card.to_max.passive=Envanterdeki %s Saat +constants.card.to_max.small_experience_books=%s K\u00FC\u00E7\u00FCk Deneyim Kitaplar\u0131 +constants.card.to_max.wardens=%s \u00D6ld\u00FCr\u00FClecek Muhaf\u0131zlar +constants.card.to_max.withers=%s \u00D6ld\u00FCrmek \u0130\u00E7in Soldu +constants.card.to_max.zombies=%s \u00D6ld\u00FCr\u00FClecek Zombi +menu.catalogue=Katalo\u011Fu | "%S" +menu.card_catalogue.view_crafting_recipe=\u00DCretim Tarifini G\u00F6r\u00FCnt\u00FCle +menu.card_catalogue.crafting="%s" Tarifi +menu.card_catalogue.view_in_catalogue=Kart Katalo\u011Funda G\u00F6r\u00FCnt\u00FCle +card.goat_gladiator=USHAAAAAAA! +card.goat_gladiator.desc=Asker, Solma Sava\u015F\u0131'na gitmek i\u00E7in sesi en k\u00F6t\u00FC olan ke\u00E7iyi se\u00E7ti. Art\u0131k \u00F6ld\u00FCkten sonra bile bununla ya\u015Famak zorunda. +constants.card_equipment.ability.deflect=&aSapt\u0131rma +constants.card_equipment.ability.deflect.desc=Mermileri Sapt\u0131rma \u015Eans\u0131 40%. +card.sand_traveler=M\u0131s\u0131r'a 50 g\u00FCn! +card.sand_traveler.desc=G\u00FCvenilir devesinin \u00FCzerinde o kadar uzun s\u00FCre seyahat etti ki, her t\u00FCrl\u00FC s\u0131ca\u011Fa kar\u015F\u0131 ba\u011F\u0131\u015F\u0131kl\u0131k kazand\u0131. Bo\u015F zamanlar\u0131nda ultra maraton ko\u015Fuyor. +card.sand_traveler.ability.blazing_hot=\u00C7ok S\u0131cak +card.sand_traveler.ability.blazing_hot.desc=Hem kart hem de kart sahibi t\u00FCm \u0131s\u0131ya kar\u015F\u0131 ba\u011F\u0131\u015F\u0131kl\u0131k kazan\u0131r. +card.sand_traveler.ability.firecracker=Havai Fi\u015Fek +card.sand_traveler.ability.firecracker.desc=Her 7s bir a\u011Fz\u0131ndan patlay\u0131c\u0131 ate\u015F toplar\u0131 f\u0131rlat\u0131r. +card.the_immortal=S\u0130ZE G\u00DCVEND\u0130K!! +card.the_immortal.desc=B\u00FCy\u00FCk bir ihanetten sa\u011F kurtulan ve \u00F6lmek i\u00E7in fazlas\u0131yla \u00F6fkeli olan eski bir sava\u015F\u00E7\u0131. +card.the_immortal.ability.immortality=\u00D6l\u00FCms\u00FCzl\u00FCk +card.the_immortal.ability.immortality.desc=1 totem tutar ve her 10 seviye i\u00E7in 1 totem kazan\u0131r. +card.the_immortal.ability.hardening=Sertle\u015Fme +card.the_immortal.ability.hardening.desc=Gelen hasar\u0131 engelleme \u015Fans\u0131 %bch. +card.the_immortal.ability.soft_landing=Yumu\u015Fak Ini\u015F +card.the_immortal.ability.soft_landing.desc=Oyuncu ve Kart, d\u00FC\u015Fme hasar\u0131na kar\u015F\u0131 ba\u011F\u0131\u015F\u0131kl\u0131k kazan\u0131r. +card.blizzard=\u015Eark\u0131 s\u00F6yleme. +card.blizzard.desc=Disney \u015Fark\u0131lar\u0131ndan b\u0131km\u0131\u015F basit bir Buz B\u00FCy\u00FCc\u00FCs\u00FC. +card.blizzard.ability.blue_flame=Mavi Alev +card.blizzard.ability.blue_flame.desc=Sahibi 2s Buz Hasar\u0131 verebilir. +card.blizzard.ability.iceball=Buz Topu +card.blizzard.ability.iceball.desc=Sald\u0131r\u0131 hasar\u0131n\u0131n %50'sini veren kartoplar\u0131n\u0131 f\u0131rlat\u0131r. +card.blizzard.ability.storm=F\u0131rt\u0131na +constants.card.to_max.huge_experience_books=%s Devasa Deneyim Kitaplar\u0131 + + diff --git a/build.gradle.kts b/build.gradle.kts index 74a893f6..d1ef41b0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ plugins { } val pGroup = "me.gamercoder215.battlecards" -val pVersion = "1.0.2-SNAPSHOT" +val pVersion = "1.1.0-SNAPSHOT" val pAuthor = "GamerCoder" sonarqube { @@ -43,6 +43,7 @@ allprojects { maven("https://oss.sonatype.org/content/repositories/central") maven("https://repo.codemc.org/repository/nms/") + maven("https://repo.codemc.io/repository/maven-releases/") maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") maven("https://repo.papermc.io/repository/maven-public/") maven("https://hub.jeff-media.com/nexus/repository/jeff-media-public/") @@ -69,7 +70,7 @@ subprojects { testImplementation("org.mockito:mockito-core:5.8.0") testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") - testImplementation("org.spigotmc:spigot-api:1.8-R0.1-SNAPSHOT") + testImplementation(kotlin("test")) } java { diff --git a/nms/1_10_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_10_R1/PacketHandler1_10_R1.kt b/nms/1_10_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_10_R1/PacketHandler1_10_R1.kt index 5601144c..96e26338 100644 --- a/nms/1_10_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_10_R1/PacketHandler1_10_R1.kt +++ b/nms/1_10_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_10_R1/PacketHandler1_10_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_10_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_11_R1/build.gradle.kts b/nms/1_11_R1/build.gradle.kts index e1e6dd2b..02c07f99 100644 --- a/nms/1_11_R1/build.gradle.kts +++ b/nms/1_11_R1/build.gradle.kts @@ -4,4 +4,5 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") } \ No newline at end of file diff --git a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_11_R1.kt b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_11_R1.kt index 12f828f8..7acc6ed6 100644 --- a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_11_R1.kt +++ b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_11_R1.kt @@ -14,7 +14,8 @@ internal class CardLoader1_11_R1 : CardLoader { ISuspiciousZombie::class.java, IEmeraldHusk::class.java, IEternalHusk::class.java, - IWarriorHusk::class.java + IWarriorHusk::class.java, + IImmortal::class.java, ) override fun loadedEquipment(): Collection = CardEquipments1_11_R1.entries diff --git a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IEmeraldHusk.kt b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IEmeraldHusk.kt index 91ebcccc..b96c8788 100644 --- a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IEmeraldHusk.kt +++ b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IEmeraldHusk.kt @@ -12,7 +12,7 @@ import org.bukkit.inventory.meta.LeatherArmorMeta @Attributes(100.0, 5.5, 10.0, 0.2, 100.0, 128.0) @AttributesModifier(CardAttribute.MAX_HEALTH, CardOperation.ADD, 0.55) @AttributesModifier(CardAttribute.ATTACK_DAMAGE, CardOperation.ADD, 2.72) -@AttributesModifier(CardAttribute.DEFENSE, CardOperation.ADD, 2.385) +@AttributesModifier(CardAttribute.DEFENSE, CardOperation.ADD, 3.175) class IEmeraldHusk(data: ICard) : IBattleCard(data) { override fun init() { diff --git a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IEternalHusk.kt b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IEternalHusk.kt index 3169e8e1..f64f1e9d 100644 --- a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IEternalHusk.kt +++ b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IEternalHusk.kt @@ -135,7 +135,6 @@ class IEternalHusk(data: ICard) : IBattleCard(data) { } private companion object { - @JvmStatic private val undeadTypes: List = listOf( EntityType.ZOMBIE, EntityType.SKELETON, diff --git a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IImmortal.kt b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IImmortal.kt new file mode 100644 index 00000000..203f7492 --- /dev/null +++ b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IImmortal.kt @@ -0,0 +1,100 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.api.card.BattleCardType +import me.gamercoder215.battlecards.impl.* +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.Sound +import org.bukkit.enchantments.Enchantment +import org.bukkit.entity.WitherSkeleton +import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType + +@Type(BattleCardType.THE_IMMORTAL) +@Attributes(1400.0, 29.5, 85.5, 0.38, 50.0) +@AttributesModifier(CardAttribute.MAX_HEALTH, CardOperation.ADD, 5.92, 6150.0) +@AttributesModifier(CardAttribute.ATTACK_DAMAGE, CardOperation.ADD, 3.72) +@AttributesModifier(CardAttribute.DEFENSE, CardOperation.ADD, 2.17) +@CardAbility("card.the_immortal.ability.immortality", ChatColor.YELLOW) +class IImmortal(data: ICard) : IBattleCard(data) { + + override fun init() { + super.init() + + val regen = PotionEffect(PotionEffectType.REGENERATION, deployTime * 20, 0, false, false) + entity.addPotionEffect(regen) + p.addPotionEffect(regen) + + entity.equipment.apply { + itemInOffHand = ItemStack(Material.matchMaterial("TOTEM_OF_UNDYING") ?: Material.matchMaterial("TOTEM")).apply { + amount = 1 + (level / 10).coerceAtMost(2) + } + + if (level > 10) + helmet = ItemStack(Material.DIAMOND_HELMET).apply { + itemMeta = itemMeta.apply { + isUnbreakable = true + + if (level > 15) + addEnchant(Enchantment.THORNS, 3, true) + + addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, (level / 3).coerceAtMost(10), true) + } + } + + chestplate = ItemStack(Material.DIAMOND_CHESTPLATE).apply { + itemMeta = itemMeta.apply { + isUnbreakable = true + + if (level > 5) + addEnchant(Enchantment.THORNS, 2, true) + + if (level > 10) + addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, (level / 5).coerceAtMost(10), true) + } + } + + leggings = ItemStack(Material.DIAMOND_LEGGINGS).apply { + itemMeta = itemMeta.apply { + isUnbreakable = true + + if (level > 10) + addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, (level / 4).coerceAtMost(10), true) + } + } + + boots = ItemStack(Material.DIAMOND_BOOTS).apply { + itemMeta = itemMeta.apply { + isUnbreakable = true + + if (level > 5) + addEnchant(Enchantment.PROTECTION_FALL, 3, true) + + if (level > 10) + addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, (level / 4).coerceAtMost(10), true) + } + } + } + } + + @CardAbility("card.the_immortal.ability.hardening", ChatColor.GREEN) + @UnlockedAt(5) + @Defensive(0.05, CardOperation.ADD, 0.01, 0.15) + private fun hardening(event: EntityDamageByEntityEvent) { + event.isCancelled = true + entity.world.playSound(entity.location, Sound.ITEM_SHIELD_BLOCK, 1F, 1F) + } + + @CardAbility("card.the_immortal.ability.soft_landing", ChatColor.WHITE) + @UnlockedAt(10) + @UserDamage + @Damage + private fun softLanding(event: EntityDamageEvent) { + if (event.cause == EntityDamageEvent.DamageCause.FALL || event.cause == EntityDamageEvent.DamageCause.FLY_INTO_WALL) + event.isCancelled = true + } + +} \ No newline at end of file diff --git a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_11_R1/PacketHandler1_11_R1.kt b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_11_R1/PacketHandler1_11_R1.kt index f1a73cdd..9325f9bc 100644 --- a/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_11_R1/PacketHandler1_11_R1.kt +++ b/nms/1_11_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_11_R1/PacketHandler1_11_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_11_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_11_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_11_R1.kt b/nms/1_11_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_11_R1.kt new file mode 100644 index 00000000..e139aef7 --- /dev/null +++ b/nms/1_11_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_11_R1.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_11_R1 { + + companion object { + internal val cardLoader = CardLoader1_11_R1() + } + + @Test + @DisplayName("Test 1.11.2 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_12_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_12_R1/PacketHandler1_12_R1.kt b/nms/1_12_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_12_R1/PacketHandler1_12_R1.kt index f9107d10..46d45f1e 100644 --- a/nms/1_12_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_12_R1/PacketHandler1_12_R1.kt +++ b/nms/1_12_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_12_R1/PacketHandler1_12_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_12_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_13_R1/build.gradle.kts b/nms/1_13_R1/build.gradle.kts index fe7c1e9c..fe0c603d 100644 --- a/nms/1_13_R1/build.gradle.kts +++ b/nms/1_13_R1/build.gradle.kts @@ -4,4 +4,5 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") } \ No newline at end of file diff --git a/nms/1_13_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/INecromancer.kt b/nms/1_13_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/INecromancer.kt index 9c24d531..46d14660 100644 --- a/nms/1_13_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/INecromancer.kt +++ b/nms/1_13_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/INecromancer.kt @@ -29,7 +29,6 @@ import org.bukkit.inventory.meta.LeatherArmorMeta class INecromancer(data: ICard) : IBattleCard(data) { private companion object { - @JvmStatic val capePattern = listOf( Pattern(DyeColor.BLACK, PatternType.GRADIENT_UP), Pattern(DyeColor.WHITE, PatternType.SKULL) diff --git a/nms/1_13_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_13_R1/PacketHandler1_13_R1.kt b/nms/1_13_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_13_R1/PacketHandler1_13_R1.kt index 20f279d3..43c3404b 100644 --- a/nms/1_13_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_13_R1/PacketHandler1_13_R1.kt +++ b/nms/1_13_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_13_R1/PacketHandler1_13_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_13_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_13_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_13_R1.kt b/nms/1_13_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_13_R1.kt new file mode 100644 index 00000000..f42a0f6c --- /dev/null +++ b/nms/1_13_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_13_R1.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_13_R1 { + + companion object { + internal val cardLoader = CardLoader1_13_R1() + } + + @Test + @DisplayName("Test 1.13 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_13_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapperV2.kt b/nms/1_13_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapperV2.kt index 12a88e7e..5c6fd850 100644 --- a/nms/1_13_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapperV2.kt +++ b/nms/1_13_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapperV2.kt @@ -5,6 +5,7 @@ import me.gamercoder215.battlecards.api.card.BattleCardType import me.gamercoder215.battlecards.api.card.Card import me.gamercoder215.battlecards.util.cardInHand import me.gamercoder215.battlecards.util.inventory.Items +import me.gamercoder215.battlecards.util.isDisabled import me.gamercoder215.battlecards.wrapper.commands.CommandWrapper.Companion.getError import org.bukkit.command.CommandSender import org.bukkit.entity.EntityType @@ -20,7 +21,6 @@ internal class CommandWrapperV2(private val plugin: Plugin) : CommandWrapper { companion object { private lateinit var handler: BukkitCommandHandler - @JvmStatic fun hasHandler(): Boolean = ::handler.isInitialized } @@ -30,9 +30,13 @@ internal class CommandWrapperV2(private val plugin: Plugin) : CommandWrapper { handler = BukkitCommandHandler.create(plugin) handler.autoCompleter - .registerParameterSuggestions(BattleCardType::class.java, SuggestionProvider.of { BattleCardType.entries.filter { it != BattleCardType.BASIC }.map { it.name.lowercase() } }) + .registerParameterSuggestions(BattleCardType::class.java, SuggestionProvider.of { BattleCardType.entries.filter { it != BattleCardType.BASIC && !it.isDisabled }.map { it.name.lowercase() } }) .registerParameterSuggestions(EntityType::class.java, SuggestionProvider.of { EntityType.entries.map { it.name.lowercase() } }) .registerSuggestion("items", SuggestionProvider.of { Items.PUBLIC_ITEMS.keys }) + .registerSuggestion("catalogue", SuggestionProvider.of { + BattleCardType.entries.filter { it != BattleCardType.BASIC && !it.isDisabled }.map { it.name.lowercase() } + + BattleConfig.config.registeredEquipment.map { it.name.lowercase() } + }) handler.register(this) handler.register(CardCommands(this)) @@ -137,6 +141,11 @@ internal class CommandWrapperV2(private val plugin: Plugin) : CommandWrapper { @CommandPermission("battlecards.user.despawn") fun despawnCards(p: Player) = wrapper.despawnCards(p) + @Subcommand("catalogue") + @CommandPermission("battlecards.user.query") + @AutoComplete("@catalogue") + fun cardCatalogue(p: Player, input: String) = wrapper.catalogue(p, input) + } } \ No newline at end of file diff --git a/nms/1_13_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_13_R2/PacketHandler1_13_R2.kt b/nms/1_13_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_13_R2/PacketHandler1_13_R2.kt index d6916a47..42d08946 100644 --- a/nms/1_13_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_13_R2/PacketHandler1_13_R2.kt +++ b/nms/1_13_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_13_R2/PacketHandler1_13_R2.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_13_R2(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_14_R1/build.gradle.kts b/nms/1_14_R1/build.gradle.kts index d75f59fc..685d103e 100644 --- a/nms/1_14_R1/build.gradle.kts +++ b/nms/1_14_R1/build.gradle.kts @@ -4,4 +4,5 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") } \ No newline at end of file diff --git a/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_14_R1.kt b/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_14_R1.kt index 8e628ca1..319693fc 100644 --- a/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_14_R1.kt +++ b/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_14_R1.kt @@ -2,6 +2,7 @@ package me.gamercoder215.battlecards.impl.cards import me.gamercoder215.battlecards.api.BattleConfig import me.gamercoder215.battlecards.api.card.BattleCardType +import me.gamercoder215.battlecards.api.card.Rarity import me.gamercoder215.battlecards.api.card.item.CardEquipment import me.gamercoder215.battlecards.api.card.item.CardEquipment.Rarity.* import me.gamercoder215.battlecards.util.inventory.CardGenerator @@ -34,7 +35,6 @@ internal class CardLoader1_14_R1 : CardLoader, Listener { override fun loadedEquipment(): Collection = CardEquipments1_14_R1.entries private companion object { - @JvmStatic private val equipmentToPrice = mutableMapOf( AVERAGE to 26..48, FREQUENT to 39..61, @@ -42,7 +42,6 @@ internal class CardLoader1_14_R1 : CardLoader, Listener { MYTHOLOGICAL to 65..128 ) - @JvmStatic private fun recipe(equipment: CardEquipment): MerchantRecipe { val count = equipmentToPrice[equipment.rarity]!!.random() return MerchantRecipe(equipment.itemStack, 5).apply { @@ -57,12 +56,11 @@ internal class CardLoader1_14_R1 : CardLoader, Listener { } } - @JvmStatic private fun recipe(card: BattleCardType): MerchantRecipe? { if (card.entityClass == null) return null val shards = (5..8).random() - return MerchantRecipe(CardGenerator.toItem(card.createCardData()), 3).apply { + return MerchantRecipe(CardGenerator.toItem(card()), 3).apply { setExperienceReward(true) villagerExperience = 15 @@ -72,7 +70,10 @@ internal class CardLoader1_14_R1 : CardLoader, Listener { } } - @JvmStatic + private fun equipment(filter: (CardEquipment) -> Boolean): MerchantRecipe = recipe(BattleConfig.config.registeredEquipment + .filter(filter) + .filter { it.rarity in equipmentToPrice.keys }.random()) + private val villagerTrades: Map MerchantRecipe?>>> = mapOf( Villager.Profession.CLERIC to setOf( 2 to { @@ -86,12 +87,12 @@ internal class CardLoader1_14_R1 : CardLoader, Listener { } }, 2 to { - recipe(BattleConfig.config.registeredEquipment.filter { it.healthModifier in 1.0..1.1 && it.rarity in equipmentToPrice.keys }.random()) + equipment { it.healthModifier in 1.0..1.1 } }, 3 to { - recipe(BattleConfig.config.registeredEquipment.filter { it.healthModifier in 1.0..1.3 && it.rarity in equipmentToPrice.keys }.random()) + equipment { it.healthModifier in 1.0..1.3 } }, - 4 to { + 3 to { MerchantRecipe(Items.SMALL_EXPERIENCE_BOOK, 5).apply { setExperienceReward(true) villagerExperience = 15 @@ -102,17 +103,52 @@ internal class CardLoader1_14_R1 : CardLoader, Listener { ) } }, + 3 to { + recipe(listOf( + BattleCardType.REDSTONE_ZOMBIE, + BattleCardType.LAPIS_DROWNED, + ).random()) + }, + 4 to { + MerchantRecipe(Items.MEDIUM_EXPERIENCE_BOOK, 3).apply { + setExperienceReward(true) + villagerExperience = 35 + + ingredients = listOf( + ItemStack(Material.EMERALD, 64), + ItemStack(Material.EMERALD, 64) + ) + } + }, + 4 to { + recipe(BattleCardType.SILVERFISH_HIVE) + }, + 4 to { + MerchantRecipe(Items.LARGE_EXPERIENCE_BOOK, 2).apply { + setExperienceReward(true) + villagerExperience = 50 + + ingredients = listOf( + ItemStack(Material.EMERALD_BLOCK, r.nextInt(18, 24)) + ) + } + } ), Villager.Profession.ARMORER to setOf( 2 to { - recipe(BattleConfig.config.registeredEquipment.filter { it.defenseModifier in 1.0..1.1 && it.rarity in equipmentToPrice.keys }.random()) + equipment { it.defenseModifier in 1.0..1.1 } }, 3 to { - recipe(BattleConfig.config.registeredEquipment.filter { it.defenseModifier in 1.0..1.3 && it.rarity in equipmentToPrice.keys }.random()) + equipment { it.defenseModifier in 1.0..1.3 } }, - 4 to { + 3 to { recipe(listOf( BattleCardType.STONE_ARCHER, + BattleCardType.SKELETON_SOLDIER, + ).random()) + }, + 4 to { + recipe(listOf( BattleCardType.GOLD_SKELETON, BattleCardType.DIAMOND_GOLEM, ).random()) @@ -120,28 +156,35 @@ internal class CardLoader1_14_R1 : CardLoader, Listener { ), Villager.Profession.WEAPONSMITH to setOf( 2 to { - recipe(BattleConfig.config.registeredEquipment.filter { it.damageModifier in 1.0..1.1 && it.rarity in equipmentToPrice.keys }.random()) + equipment { it.damageModifier in 1.0..1.1 } + }, + 3 to { + recipe(listOf( + BattleCardType.SKELETON_SOLDIER, + BattleCardType.STONE_ARCHER, + BattleCardType.BANDIT + ).random()) }, 4 to { - recipe(BattleConfig.config.registeredEquipment.filter { it.damageModifier in 1.0..1.4 && it.ability != null && it.rarity in equipmentToPrice.keys }.random()) + equipment { it.damageModifier in 1.0..1.4 && it.ability != null } }, 4 to { recipe(listOf( - BattleCardType.SKELETON_SOLDIER, - BattleCardType.STONE_ARCHER, BattleCardType.LAPIS_DROWNED, - BattleCardType.KNIGHT + BattleCardType.KNIGHT, + BattleCardType.UNDEAD_LUMBERJACK, + BattleCardType.MERCENARY ).random()) } ), Villager.Profession.TOOLSMITH to setOf( 2 to { - recipe(BattleConfig.config.registeredEquipment.filter { (it.speedModifier in 1.0..1.1 || it.knockbackResistanceModifier in 1.0..1.2) && it.rarity in equipmentToPrice.keys }.random()) + equipment { (it.speedModifier in 1.0..1.1 || it.knockbackResistanceModifier in 1.0..1.2) } }, 3 to { - recipe(BattleConfig.config.registeredEquipment.filter { (it.speedModifier in 1.0..1.3 || it.knockbackResistanceModifier in 1.0..1.5) && it.rarity in equipmentToPrice.keys }.random()) + equipment { (it.speedModifier in 1.0..1.3 || it.knockbackResistanceModifier in 1.0..1.5) } }, - 4 to { + 3 to { recipe(listOf( BattleCardType.KNIGHT, BattleCardType.MERCENARY, @@ -150,9 +193,85 @@ internal class CardLoader1_14_R1 : CardLoader, Listener { } ), Villager.Profession.BUTCHER to setOf( - 4 to { + 3 to { recipe(BattleCardType.PITBULL) } + ), + Villager.Profession.MASON to setOf( + 3 to { + recipe(BattleCardType.MESA_ZOMBIE) + } + ), + Villager.Profession.FLETCHER to setOf( + 3 to { + recipe(BattleCardType.SNIPER) + } + ), + Villager.Profession.LIBRARIAN to setOf( + 1 to { + MerchantRecipe(Items.cardShard(Rarity.COMMON), 8).apply { + setExperienceReward(true) + villagerExperience = 5 + + ingredients = listOf( + ItemStack(Material.EMERALD, r.nextInt(31, 47)) + ) + } + }, + 2 to { + MerchantRecipe(Items.cardShard(Rarity.UNCOMMON), 8).apply { + setExperienceReward(true) + villagerExperience = 10 + + ingredients = listOf( + Items.cardShard(Rarity.COMMON).apply { amount = r.nextInt(3, 6) }, + ItemStack(Material.EMERALD, r.nextInt(28, 51)) + ) + } + }, + 3 to { + MerchantRecipe(Items.cardShard(Rarity.RARE), 8).apply { + setExperienceReward(true) + villagerExperience = 25 + + ingredients = listOf( + Items.cardShard(Rarity.UNCOMMON).apply { amount = r.nextInt(3, 6) }, + ItemStack(Material.EMERALD, r.nextInt(38, 65)) + ) + } + }, + 3 to { + MerchantRecipe(Items.TINY_EXPERIENCE_BOOK, 5).apply { + setExperienceReward(true) + villagerExperience = 5 + + ingredients = listOf( + ItemStack(Material.EMERALD, r.nextInt(35, 53)) + ) + } + }, + 4 to { + MerchantRecipe(Items.cardShard(Rarity.EPIC), 8).apply { + setExperienceReward(true) + villagerExperience = 40 + + ingredients = listOf( + Items.cardShard(Rarity.RARE).apply { amount = r.nextInt(3, 6) }, + ItemStack(Material.EMERALD, r.nextInt(49, 65)) + ) + } + }, + 4 to { + MerchantRecipe(Items.SMALL_EXPERIENCE_BOOK, 10).apply { + setExperienceReward(true) + villagerExperience = 10 + + ingredients = listOf( + ItemStack(Material.EMERALD, 64), + ItemStack(Material.EMERALD, r.nextInt(31, 54)) + ) + } + } ) ) } diff --git a/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IRaider.kt b/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IRaider.kt index a12af760..c1e4fa97 100644 --- a/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IRaider.kt +++ b/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IRaider.kt @@ -27,7 +27,6 @@ class IRaider(data: ICard) : IBattleCard(data) { private lateinit var ravager: Ravager private companion object { - @JvmStatic val bannerPattern = listOf( Pattern(DyeColor.ORANGE, PatternType.DIAGONAL_RIGHT_MIRROR), Pattern(DyeColor.YELLOW, PatternType.CROSS), diff --git a/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_14_R1/PacketHandler1_14_R1.kt b/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_14_R1/PacketHandler1_14_R1.kt index c906e8af..61772c7f 100644 --- a/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_14_R1/PacketHandler1_14_R1.kt +++ b/nms/1_14_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_14_R1/PacketHandler1_14_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_14_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_14_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_14_R1.kt b/nms/1_14_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_14_R1.kt new file mode 100644 index 00000000..1671adf3 --- /dev/null +++ b/nms/1_14_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_14_R1.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_14_R1 { + + companion object { + internal val cardLoader = CardLoader1_14_R1() + } + + @Test + @DisplayName("Test 1.14.4 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_15_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_15_R1/PacketHandler1_15_R1.kt b/nms/1_15_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_15_R1/PacketHandler1_15_R1.kt index 350ea2a1..9b47f820 100644 --- a/nms/1_15_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_15_R1/PacketHandler1_15_R1.kt +++ b/nms/1_15_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_15_R1/PacketHandler1_15_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_15_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_16_R1/build.gradle.kts b/nms/1_16_R1/build.gradle.kts index 92d869c2..b73eb78d 100644 --- a/nms/1_16_R1/build.gradle.kts +++ b/nms/1_16_R1/build.gradle.kts @@ -4,4 +4,5 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") } \ No newline at end of file diff --git a/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_16_R1.kt b/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_16_R1.kt index 334e5164..2653220d 100644 --- a/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_16_R1.kt +++ b/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_16_R1.kt @@ -29,7 +29,7 @@ internal class CardLoader1_16_R1 : CardLoader, Listener { if (event.inventoryHolder?.inventory == null) return val luck = event.lootContext.luck - if (r.nextDouble() < 0.3) return + if (r.nextDouble() > 0.3) return val limit = (luck / 0.5F).toInt().coerceAtMost(3) diff --git a/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/INetherPrince.kt b/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/INetherPrince.kt index 9cc263b0..7702c8fa 100644 --- a/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/INetherPrince.kt +++ b/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/INetherPrince.kt @@ -81,7 +81,6 @@ class INetherPrince(data: ICard) : IBattleCard(data) { } private companion object { - @JvmStatic private val netherTypes: List = listOf( EntityType.WITHER_SKELETON, EntityType.BLAZE, diff --git a/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R1/PacketHandler1_16_R1.kt b/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R1/PacketHandler1_16_R1.kt index 77e57782..a0c3d673 100644 --- a/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R1/PacketHandler1_16_R1.kt +++ b/nms/1_16_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R1/PacketHandler1_16_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_16_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_16_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_16_R1.kt b/nms/1_16_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_16_R1.kt new file mode 100644 index 00000000..bb94f3c8 --- /dev/null +++ b/nms/1_16_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_16_R1.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_16_R1 { + + companion object { + internal val cardLoader = CardLoader1_16_R1() + } + + @Test + @DisplayName("Test 1.16.1 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_16_R2/build.gradle.kts b/nms/1_16_R2/build.gradle.kts index 7d339973..d2a7fd26 100644 --- a/nms/1_16_R2/build.gradle.kts +++ b/nms/1_16_R2/build.gradle.kts @@ -4,4 +4,5 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") } \ No newline at end of file diff --git a/nms/1_16_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R2/PacketHandler1_16_R2.kt b/nms/1_16_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R2/PacketHandler1_16_R2.kt index db0a1c52..86494d41 100644 --- a/nms/1_16_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R2/PacketHandler1_16_R2.kt +++ b/nms/1_16_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R2/PacketHandler1_16_R2.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_16_R2(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_16_R2/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_16_R2.kt b/nms/1_16_R2/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_16_R2.kt new file mode 100644 index 00000000..b74d8432 --- /dev/null +++ b/nms/1_16_R2/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_16_R2.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_16_R2 { + + companion object { + internal val cardLoader = CardLoader1_16_R2() + } + + @Test + @DisplayName("Test 1.16.2 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_16_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R3/PacketHandler1_16_R3.kt b/nms/1_16_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R3/PacketHandler1_16_R3.kt index 03171951..018e2b44 100644 --- a/nms/1_16_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R3/PacketHandler1_16_R3.kt +++ b/nms/1_16_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_16_R3/PacketHandler1_16_R3.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_16_R3(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_17_R1/build.gradle.kts b/nms/1_17_R1/build.gradle.kts index 22217c1f..d6972aa0 100644 --- a/nms/1_17_R1/build.gradle.kts +++ b/nms/1_17_R1/build.gradle.kts @@ -5,6 +5,7 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") } java { diff --git a/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_17_R1.kt b/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_17_R1.kt index 0bdd1044..bb5c86d9 100644 --- a/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_17_R1.kt +++ b/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_17_R1.kt @@ -1,15 +1,39 @@ package me.gamercoder215.battlecards.impl.cards +import me.gamercoder215.battlecards.api.BattleConfig import me.gamercoder215.battlecards.api.card.item.CardEquipment +import me.gamercoder215.battlecards.util.inventory.Items.randomCumulative +import me.gamercoder215.battlecards.util.itemStack import me.gamercoder215.battlecards.wrapper.CardLoader +import me.gamercoder215.battlecards.wrapper.Wrapper.Companion.r +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.PiglinBarterEvent -internal class CardLoader1_17_R1 : CardLoader { +internal class CardLoader1_17_R1 : CardLoader, Listener { override fun loadedCards(): Collection>> = listOf( IFrostBear::class.java, - IGoatGladiator::class.java + IGoatGladiator::class.java, + IBlizzard::class.java, ) override fun loadedEquipment(): Collection = CardEquipments1_17_R1.entries + @EventHandler + fun onBarter(event: PiglinBarterEvent) { + if (r.nextDouble() > 0.1) return + + val equipment: Map = BattleConfig.config.registeredEquipment + .filter { it.damageModifier > 1.0 || it.defenseModifier > 1.0 } + .associateWith { 1.0 / (it.damageModifier + it.defenseModifier).times(it.rarity.ordinal + 1) } + + event.outcome.clear() + for (i in 0 until r.nextInt(1, 3)) + equipment.randomCumulative(r.nextInt(2)).let { + if (it == null) return@let + event.outcome.add(it.itemStack) + } + } + } \ No newline at end of file diff --git a/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBlizzard.kt b/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBlizzard.kt new file mode 100644 index 00000000..cdbd395e --- /dev/null +++ b/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/IBlizzard.kt @@ -0,0 +1,96 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.api.BattleConfig +import me.gamercoder215.battlecards.api.card.BattleCardType +import me.gamercoder215.battlecards.impl.* +import me.gamercoder215.battlecards.util.cardByMinion +import me.gamercoder215.battlecards.util.sync +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.Particle +import org.bukkit.World +import org.bukkit.entity.* +import org.bukkit.event.EventHandler +import org.bukkit.event.block.EntityBlockFormEvent +import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.entity.EntityDamageEvent.DamageCause +import org.bukkit.event.entity.ProjectileHitEvent + +@Type(BattleCardType.BLIZZARD) +@Attributes(50.0, 6.5, 60.0, 0.2, 100.0) +@AttributesModifier(CardAttribute.MAX_HEALTH, CardOperation.ADD, 3.42) +@AttributesModifier(CardAttribute.DEFENSE, CardOperation.ADD, 4.38) +@AttributesModifier(CardAttribute.ATTACK_DAMAGE, CardOperation.ADD, 2.26) +@AttributesModifier(CardAttribute.KNOCKBACK_RESISTANCE, CardOperation.ADD, 4.55) +@BlockAttachment(Material.BLUE_ICE, 0.0, -0.05, 0.0, local = false) +class IBlizzard(data: ICard) : IBattleCard(data) { + + override fun init() { + super.init() + + entity.isDerp = true + } + + @CardAbility("card.blizzard.ability.iceball", ChatColor.WHITE) + @EventHandler + private fun onShoot(event: ProjectileHitEvent) { + val proj = event.entity as? Snowball ?: return + if (proj.shooter != entity) return + + val target = event.hitEntity as? LivingEntity ?: return + if (target == p || target.cardByMinion == this) return + + target.damage(statistics.attackDamage / 2.0, entity) + target.freezeTicks += 20 * r.nextInt(3, 6) + } + + @CardAbility("card.blizzard.ability.storm", ChatColor.DARK_AQUA) + @Passive(20) + @UnlockedAt(10) + private fun storm() { + if (entity.world.environment == World.Environment.NETHER) return + + val targets = entity.getNearbyEntities(3.5, 0.5, 3.5) + .asSequence() + .filterIsInstance() + .filter { it !is ArmorStand } + .filter { it.cardByMinion != this } + .filter { if (BattleConfig.config.cardAttackPlayers) it !is Player else true } + .filter { it.fireTicks <= 0 } + .toList() + + targets.forEach { + it.freezeTicks += 20 * r.nextInt(1, 5) + it.world.spawnParticle(Particle.SNOWFLAKE, it.eyeLocation, r.nextInt(3, 5), 0.0, 0.0, 0.0, 0.01) + } + } + + @CardAbility("card.blizzard.ability.blue_flame", ChatColor.AQUA) + @UserOffensive + @UnlockedAt(15) + private fun blueFlame(event: EntityDamageByEntityEvent) { + val target = event.entity as? LivingEntity ?: return + + target.freezeTicks += 40 + } + + @Damage + private fun damage(event: EntityDamageEvent) { + if (event.cause == DamageCause.DRYOUT || event.cause == DamageCause.DROWNING) + event.isCancelled = true + } + + @EventHandler + private fun onCreateTrail(event: EntityBlockFormEvent) { + if (event.entity != entity) return + if (event.newState.type != Material.SNOW) return + + event.isCancelled = true + val oldData = event.block.blockData + sync({ + event.block.blockData = oldData + }, 1) + } + +} \ No newline at end of file diff --git a/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_17_R1/PacketHandler1_17_R1.kt b/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_17_R1/PacketHandler1_17_R1.kt index 4c90fdaf..d573382e 100644 --- a/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_17_R1/PacketHandler1_17_R1.kt +++ b/nms/1_17_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_17_R1/PacketHandler1_17_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_17_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_17_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_17_R1.kt b/nms/1_17_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_17_R1.kt new file mode 100644 index 00000000..5d01baec --- /dev/null +++ b/nms/1_17_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_17_R1.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_17_R1 { + + companion object { + internal val cardLoader = CardLoader1_17_R1() + } + + @Test + @DisplayName("Test 1.17.1 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_18_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_18_R1/PacketHandler1_18_R1.kt b/nms/1_18_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_18_R1/PacketHandler1_18_R1.kt index 63e9ec4c..db15bbe5 100644 --- a/nms/1_18_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_18_R1/PacketHandler1_18_R1.kt +++ b/nms/1_18_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_18_R1/PacketHandler1_18_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_18_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_18_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_18_R2/PacketHandler1_18_R2.kt b/nms/1_18_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_18_R2/PacketHandler1_18_R2.kt index 38bc151d..7d31f787 100644 --- a/nms/1_18_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_18_R2/PacketHandler1_18_R2.kt +++ b/nms/1_18_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_18_R2/PacketHandler1_18_R2.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_18_R2(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_19_R1/build.gradle.kts b/nms/1_19_R1/build.gradle.kts index f65f9e7e..0fafbc10 100644 --- a/nms/1_19_R1/build.gradle.kts +++ b/nms/1_19_R1/build.gradle.kts @@ -11,6 +11,7 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT:remapped-mojang") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT:remapped-mojang") } java { diff --git a/nms/1_19_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R1/PacketHandler1_19_R1.kt b/nms/1_19_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R1/PacketHandler1_19_R1.kt index 98ce4dc8..d60367dd 100644 --- a/nms/1_19_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R1/PacketHandler1_19_R1.kt +++ b/nms/1_19_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R1/PacketHandler1_19_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_19_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_19_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_19_R1.kt b/nms/1_19_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_19_R1.kt new file mode 100644 index 00000000..ed4890ec --- /dev/null +++ b/nms/1_19_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_19_R1.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_19_R1 { + + companion object { + internal val cardLoader = CardLoader1_19_R1() + } + + @Test + @DisplayName("Test 1.19.2 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_19_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R2/PacketHandler1_19_R2.kt b/nms/1_19_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R2/PacketHandler1_19_R2.kt index fdb7c2af..d4360b1d 100644 --- a/nms/1_19_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R2/PacketHandler1_19_R2.kt +++ b/nms/1_19_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R2/PacketHandler1_19_R2.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_19_R2(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_19_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R3/PacketHandler1_19_R3.kt b/nms/1_19_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R3/PacketHandler1_19_R3.kt index 60b7577e..1fa59a19 100644 --- a/nms/1_19_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R3/PacketHandler1_19_R3.kt +++ b/nms/1_19_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_19_R3/PacketHandler1_19_R3.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_19_R3(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_20_R1/build.gradle.kts b/nms/1_20_R1/build.gradle.kts index 682f3bc4..fc988fb9 100644 --- a/nms/1_20_R1/build.gradle.kts +++ b/nms/1_20_R1/build.gradle.kts @@ -11,6 +11,7 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT:remapped-mojang") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT:remapped-mojang") } java { diff --git a/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_20_R1.kt b/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_20_R1.kt index af3ba26f..3fc7c304 100644 --- a/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_20_R1.kt +++ b/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/CardLoader1_20_R1.kt @@ -11,7 +11,8 @@ internal class CardLoader1_20_R1 : CardLoader, Listener { override fun loadedCards(): Collection>> = listOf( ISeaLord::class.java, - IPurpleParasite::class.java + IPurpleParasite::class.java, + ISandTraveler::class.java, ) override fun loadedEquipment(): Collection = CardEquipments1_20_R1.entries diff --git a/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/ISandTraveler.kt b/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/ISandTraveler.kt new file mode 100644 index 00000000..bd3af05e --- /dev/null +++ b/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/ISandTraveler.kt @@ -0,0 +1,84 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.api.card.BattleCardType +import me.gamercoder215.battlecards.impl.* +import org.bukkit.ChatColor +import org.bukkit.Material +import org.bukkit.Sound +import org.bukkit.attribute.Attribute +import org.bukkit.enchantments.Enchantment +import org.bukkit.entity.Camel +import org.bukkit.entity.Husk +import org.bukkit.entity.LargeFireball +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType + +@Type(BattleCardType.SAND_TRAVELER) +@Attributes(155.0, 13.7, 31.7, 0.29, 25.0) +@AttributesModifier(CardAttribute.MAX_HEALTH, CardOperation.ADD, 3.81) +@AttributesModifier(CardAttribute.ATTACK_DAMAGE, CardOperation.ADD, 3.15) +@AttributesModifier(CardAttribute.DEFENSE, CardOperation.ADD, 2.545) + +@CardAbility("card.sand_traveler.ability.blazing_hot", ChatColor.GOLD) +class ISandTraveler(data: ICard) : IBattleCard(data) { + + private lateinit var camel: Camel + + override fun init() { + super.init() + + val fireResistance = PotionEffect(PotionEffectType.FIRE_RESISTANCE, deployTime * 20, 0, true, false) + entity.addPotionEffect(fireResistance) + p.addPotionEffect(fireResistance) + + camel = entity.world.spawn(entity.location, Camel::class.java).apply { + addPassenger(entity) + minions.add(this) + + isTamed = true + + addPotionEffect(fireResistance) + + val health = statistics.maxHealth * 0.75 + getAttribute(Attribute.GENERIC_MAX_HEALTH)!!.baseValue = health + this.health = health + + getAttribute(Attribute.GENERIC_MOVEMENT_SPEED)!!.baseValue = statistics.speed + } + + entity.equipment!!.apply { + helmet = ItemStack(Material.GOLDEN_HELMET).apply { + itemMeta = itemMeta!!.apply { + isUnbreakable = true + + addEnchant(Enchantment.PROTECTION_PROJECTILE, 1 + (level / 5).coerceAtMost(6), true) + } + } + + if (level > 15) + chestplate = ItemStack(Material.GOLDEN_CHESTPLATE).apply { + itemMeta = itemMeta!!.apply { + isUnbreakable = true + + addEnchant(Enchantment.PROTECTION_PROJECTILE, 1 + (level.minus(15) / 5).coerceAtMost(8), true) + addEnchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1 + (level.minus(15) / 7).coerceAtMost(6), true) + } + } + } + } + + @UnlockedAt(3) + @CardAbility("card.sand_traveler.ability.firecracker", ChatColor.RED) + @Passive(7 * 20) + private fun firecracker() { + entity.world.spawn(entity.eyeLocation, LargeFireball::class.java).apply { + direction = entity.eyeLocation.direction + yield = 0.75F + setIsIncendiary(true) + shooter = entity + } + entity.world.playSound(entity.eyeLocation, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 3.0F, 0.5F) + } + +} \ No newline at end of file diff --git a/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/ISeaLord.kt b/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/ISeaLord.kt index f1bc7d93..fa9841b1 100644 --- a/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/ISeaLord.kt +++ b/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/impl/cards/ISeaLord.kt @@ -34,7 +34,6 @@ import org.bukkit.scheduler.BukkitRunnable class ISeaLord(data: ICard) : IBattleCard(data) { private companion object { - @JvmStatic val dolphinKey = NamespacedKey(BattleConfig.plugin, "sealord_dolphin") } diff --git a/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R1/PacketHandler1_20_R1.kt b/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R1/PacketHandler1_20_R1.kt index 54f16789..48aaa428 100644 --- a/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R1/PacketHandler1_20_R1.kt +++ b/nms/1_20_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R1/PacketHandler1_20_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_20_R1(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_20_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_20_R1.kt b/nms/1_20_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_20_R1.kt new file mode 100644 index 00000000..6bfaa364 --- /dev/null +++ b/nms/1_20_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_20_R1.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_20_R1 { + + companion object { + internal val cardLoader = CardLoader1_20_R1() + } + + @Test + @DisplayName("Test 1.20.1 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_20_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R2/PacketHandler1_20_R2.kt b/nms/1_20_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R2/PacketHandler1_20_R2.kt index 7b44e56f..656508e4 100644 --- a/nms/1_20_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R2/PacketHandler1_20_R2.kt +++ b/nms/1_20_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R2/PacketHandler1_20_R2.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_20_R2(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_20_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R3/PacketHandler1_20_R3.kt b/nms/1_20_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R3/PacketHandler1_20_R3.kt index ee3dba00..9d64a54a 100644 --- a/nms/1_20_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R3/PacketHandler1_20_R3.kt +++ b/nms/1_20_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_20_R3/PacketHandler1_20_R3.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_20_R3(private val p: Player) : ChannelDuplexHandle } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_8_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapperV1.kt b/nms/1_8_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapperV1.kt index e173a89e..9ae7af29 100644 --- a/nms/1_8_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapperV1.kt +++ b/nms/1_8_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/commands/CommandWrapperV1.kt @@ -197,6 +197,17 @@ internal class CommandWrapperV1(private val plugin: Plugin) : CommandWrapper, Co despawnCards(sender) true } + "catalogue" -> { + if (args.size < 2) + return sender.sendMessage(getError("error.argument.card"), false) + + return try { + catalogue(sender, args[1].uppercase()) + true + } catch (ignored: IllegalArgumentException) { + sender.sendMessage(getError("error.argument.card"), false) + } + } else -> { sender.sendMessage(getError("error.argument")) false diff --git a/nms/1_8_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R1/PacketHandler1_8_R1.kt b/nms/1_8_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R1/PacketHandler1_8_R1.kt index f955f1a3..11eb9d58 100644 --- a/nms/1_8_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R1/PacketHandler1_8_R1.kt +++ b/nms/1_8_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R1/PacketHandler1_8_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_8_R1(private val p: Player) : ChannelDuplexHandler } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_8_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R2/PacketHandler1_8_R2.kt b/nms/1_8_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R2/PacketHandler1_8_R2.kt index 4f831f21..36f1dab0 100644 --- a/nms/1_8_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R2/PacketHandler1_8_R2.kt +++ b/nms/1_8_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R2/PacketHandler1_8_R2.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_8_R2(private val p: Player) : ChannelDuplexHandler } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_8_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R3/PacketHandler1_8_R3.kt b/nms/1_8_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R3/PacketHandler1_8_R3.kt index bbc6ff41..e3267afb 100644 --- a/nms/1_8_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R3/PacketHandler1_8_R3.kt +++ b/nms/1_8_R3/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_8_R3/PacketHandler1_8_R3.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_8_R3(private val p: Player) : ChannelDuplexHandler } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_9_R1/build.gradle.kts b/nms/1_9_R1/build.gradle.kts index 6ab33b0a..11e176f6 100644 --- a/nms/1_9_R1/build.gradle.kts +++ b/nms/1_9_R1/build.gradle.kts @@ -4,4 +4,5 @@ dependencies { api(project(":battlecards-abstract")) compileOnly("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") + testImplementation("org.spigotmc:spigot:$mcVersion-R0.1-SNAPSHOT") } \ No newline at end of file diff --git a/nms/1_9_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_9_R1/PacketHandler1_9_R1.kt b/nms/1_9_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_9_R1/PacketHandler1_9_R1.kt index 9080d7ab..fa70b1e0 100644 --- a/nms/1_9_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_9_R1/PacketHandler1_9_R1.kt +++ b/nms/1_9_R1/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_9_R1/PacketHandler1_9_R1.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_9_R1(private val p: Player) : ChannelDuplexHandler } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/nms/1_9_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_9_R1.kt b/nms/1_9_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_9_R1.kt new file mode 100644 index 00000000..d06afc40 --- /dev/null +++ b/nms/1_9_R1/src/test/kotlin/me/gamercoder215/battlecards/impl/cards/TestCardLoader1_9_R1.kt @@ -0,0 +1,26 @@ +package me.gamercoder215.battlecards.impl.cards + +import me.gamercoder215.battlecards.impl.Type +import me.gamercoder215.battlecards.util.airOrNull +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse + +class TestCardLoader1_9_R1 { + + companion object { + internal val cardLoader = CardLoader1_9_R1() + } + + @Test + @DisplayName("Test 1.9 CardLoader") + fun testCardLoader() { + for (clazz in cardLoader.loadedCards()) { + val type = clazz.getAnnotation(Type::class.java).type + assertFalse { type.craftingMaterial.airOrNull } + } + + cardLoader.loadedEquipment() + } + +} \ No newline at end of file diff --git a/nms/1_9_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_9_R2/PacketHandler1_9_R2.kt b/nms/1_9_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_9_R2/PacketHandler1_9_R2.kt index faf9d318..b3abb02d 100644 --- a/nms/1_9_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_9_R2/PacketHandler1_9_R2.kt +++ b/nms/1_9_R2/src/main/kotlin/me/gamercoder215/battlecards/wrapper/v1_9_R2/PacketHandler1_9_R2.kt @@ -23,7 +23,6 @@ internal class PacketHandler1_9_R2(private val p: Player) : ChannelDuplexHandler } companion object { - @JvmStatic val PACKET_HANDLERS: MutableMap) -> Unit> = mutableMapOf() } } \ No newline at end of file diff --git a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleCardListener.kt b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleCardListener.kt index 33b13ec8..5ce4c3ed 100644 --- a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleCardListener.kt +++ b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleCardListener.kt @@ -83,10 +83,8 @@ internal class BattleCardListener(private val plugin: BattleCards) : Listener { } private companion object { - @JvmStatic private val uses = mutableMapOf() - @JvmStatic private val basicCardDrops: List = listOf( "ENTITY_ATTACK", "ENTITY_SWEEP_ATTACK", @@ -645,9 +643,9 @@ internal class BattleCardListener(private val plugin: BattleCards) : Listener { if (!block.isCardBlock) return if (block["container"]?.toString()?.isNotEmpty() == true) { - event.setUseInteractedBlock(Event.Result.DENY) - if (p.isSneaking && p.itemInHand != null) return + if (p.isSneaking && p.itemInHand?.type.airOrNull) return + event.setUseInteractedBlock(Event.Result.DENY) p.openInventory(CONTAINERS_CARD_BLOCKS[block["container"].toString()].let { if (it == null) return else it() }) if (block["success"] as? Boolean == true) p.playSuccess() diff --git a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleCards.kt b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleCards.kt index 7f5e6e05..b928bb92 100644 --- a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleCards.kt +++ b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleCards.kt @@ -29,7 +29,6 @@ import org.bstats.charts.SingleLineChart import org.bukkit.Bukkit import org.bukkit.ChatColor import org.bukkit.Location -import org.bukkit.Material import org.bukkit.inventory.ShapedRecipe import org.bukkit.metadata.FixedMetadataValue import org.bukkit.plugin.java.JavaPlugin @@ -56,6 +55,7 @@ class BattleCards : JavaPlugin(), BattleConfig { fun loadListeners() { BattleCardListener(this) BattleGUIManager(this) + BattleSpawner(this) IBattleCardListener(this) } @@ -240,7 +240,6 @@ class BattleCards : JavaPlugin(), BattleConfig { companion object { - @JvmStatic val cardRecipes: MutableMap = mutableMapOf() } @@ -258,12 +257,12 @@ class BattleCards : JavaPlugin(), BattleConfig { if (cards.contains(card)) throw IllegalArgumentException("Card ${card.simpleName} already registered") val type = card.getAnnotation(Type::class.java).type - if (type != BattleCardType.BASIC && type.craftingMaterial == Material.AIR) throw IllegalStateException("$type is not available on this Minecraft Version") + if (type != BattleCardType.BASIC && type.craftingMaterial.airOrNull) throw IllegalStateException("$type is not available on this Minecraft Version: Crafting Material is AIR") cards.add(card) if (type != BattleCardType.BASIC) - Bukkit.addRecipe(createShapedRecipe("card_${card.simpleName.lowercase()}", CardGenerator.toItem(type.createCardData())).apply { + Bukkit.addRecipe(createShapedRecipe("card_${card.simpleName.lowercase()}", CardGenerator.toItem(type())).apply { shape("SSS", "SMS", "SSS") setIngredient('M', type.craftingMaterial) @@ -308,7 +307,9 @@ class BattleCards : JavaPlugin(), BattleConfig { registeredCards.firstOrNull { it.getAnnotation(Type::class.java).type == type } != null || type == BattleCardType.BASIC override fun createCardData(type: BattleCardType): Card { - val clazz = registeredCards.firstOrNull { it.getAnnotation(Type::class.java).type == type } ?: throw IllegalStateException("$type is not available on this Minecraft Version") + if (disabledCards.contains(type)) throw IllegalStateException("$type is not available on this Minecraft Version: Disabled") + + val clazz = registeredCards.firstOrNull { it.getAnnotation(Type::class.java).type == type } ?: throw IllegalStateException("$type is not available on this Minecraft Version: Unregistered") return ICard( clazz, type, diff --git a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleGUIManager.kt b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleGUIManager.kt index bad4021f..9f7c7810 100644 --- a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleGUIManager.kt +++ b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleGUIManager.kt @@ -5,12 +5,15 @@ import me.gamercoder215.battlecards.api.BattleConfig import me.gamercoder215.battlecards.api.card.BattleCardType import me.gamercoder215.battlecards.api.card.Card import me.gamercoder215.battlecards.api.card.CardQuest +import me.gamercoder215.battlecards.api.card.Rarity import me.gamercoder215.battlecards.api.card.item.CardEquipment +import me.gamercoder215.battlecards.api.events.PrepareCardCombineEvent import me.gamercoder215.battlecards.api.events.PrepareCardCraftEvent import me.gamercoder215.battlecards.util.* import me.gamercoder215.battlecards.util.CardUtils.format import me.gamercoder215.battlecards.util.inventory.CardGenerator import me.gamercoder215.battlecards.util.inventory.Generator +import me.gamercoder215.battlecards.util.inventory.Generator.genGUI import me.gamercoder215.battlecards.util.inventory.Items import me.gamercoder215.battlecards.util.inventory.Items.GUI_BACKGROUND import me.gamercoder215.battlecards.util.inventory.Items.randomCumulative @@ -40,12 +43,10 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { companion object { - @JvmStatic private val cardTableSlots = listOf( 10, 11, 12, 19, 20, 21, 24, 28, 29, 30 ) - @JvmStatic private val CLICK_ITEMS = ImmutableMap.builder Unit>() .put("card:info_item") { e, inv -> val p = e.whoClicked as Player @@ -55,6 +56,7 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { when (item.nbt.getString("type")) { "quests" -> p.openInventory(Generator.generateCardQuests(card)) "equipment" -> p.openInventory(Generator.generateCardEquipment(card)) + "catalogue" -> p.openInventory(Generator.generateCatalogue(card)) } } .put("scroll:stored") { e, inv -> @@ -102,7 +104,10 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { fun stopped() = inv["stopped", Boolean::class.java, false] fun matrix() = listOf( inv[28..34], inv[37..43] - ).flatten().filterNotNull().filter { it.type != Material.AIR } + ).flatten() + .filterNotNull() + .filter { !it.type.airOrNull } + .filter { it.isCard || it.id == "card_shard" } if (matrix().isEmpty()) return@put p.playFailure() if (inv["running", Boolean::class.java, false]) return@put e.setCancelled(true) @@ -120,16 +125,9 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { sync( { if (stopped()) return@sync cancel(); BattleSound.ENTITY_ARROW_HIT_PLAYER.play(p.location, 1F, 1F); inv[23]?.amount = 1 }, 60) sync({ if (stopped()) return@sync cancel() - val matrix = matrix() - inv[28..34] = null - inv[37..43] = null - - inv["running"] = false - - val chosen = CardUtils.calculateCardChances(matrix).randomCumulative() - - val card = BattleCardType.entries.filter { it.rarity == chosen }.random().createCardData().apply { + val chosen = CardUtils.calculateCardChances(matrix).randomCumulative() ?: Rarity.COMMON + val card = CardGenerator.toItem(BattleCardType.entries.filter { it.rarity == chosen && !it.isDisabled }.random()().apply { var total = 0.0 for ((amount, card) in matrix.map { it.amount to it.card }) { @@ -145,9 +143,16 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { } experience = total.coerceAtMost(maxCardExperience) - } + }) + + val event = PrepareCardCombineEvent(p, matrix.toTypedArray(), card).apply { call() } + if (event.isCancelled) return@sync cancel() - inv[13] = CardGenerator.toItem(card) + inv[28..34] = null + inv[37..43] = null + + inv["running"] = false + inv[13] = card BattleSound.ENTITY_PLAYER_LEVELUP.play(p.location, 1F, 0F) inv[22] = BattleMaterial.YELLOW_STAINED_GLASS_PANE.findStack().apply { @@ -160,10 +165,7 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { } .put("card_combiner:stop") { e, inv -> val p = e.whoClicked as Player - - inv["stopped"] = true - inv["running"] = false - + inv["stopped"] = true; inv["running"] = false p.playFailure() inv[22] = BattleMaterial.YELLOW_STAINED_GLASS_PANE.findStack().apply { @@ -173,9 +175,28 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { }.nbt { nbt -> nbt.addTag("_cancel") } inv[23] = GUI_BACKGROUND } + .put("card_catalogue:crafting_recipe") { e, inv -> + val p = e.whoClicked as Player + val item = e.currentItem + val type = BattleCardType.valueOf(item.nbt.getString("type")) + + val gui = genGUI(45, format(get("menu.card_catalogue.crafting"), type.name.lowercase())) + gui.isCancelled = true + gui["back"] = Consumer { pl: Player -> pl.openInventory(inv) } + gui[10..34 except (cardTableSlots + 24)] = GUI_BACKGROUND + + val rarityShard = Items.cardShard(type.rarity) + gui[10..12] = rarityShard; gui[listOf(19, 21)] = rarityShard; gui[28..30] = rarityShard + gui[20] = ItemStack(type.craftingMaterial) + gui[24] = CardGenerator.toItem(type()) + + gui[37] = Items.back("action") + + p.openInventory(gui) + p.playSuccess() + } .build() - @JvmStatic private val CLICK_INVENTORIES = ImmutableMap.builder Unit>() .put("card_table") { e, inv -> val p = e.whoClicked as Player @@ -246,7 +267,7 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { e.newItems.values.toList() } else -> listOf() - }.filterNotNull().filter { it.type != Material.AIR } + }.filterNotNull().filter { !it.type.airOrNull } if (items.isNotEmpty()) { if (items.any { it.nbt.id != "card_equipment" }) { @@ -278,10 +299,32 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { } ?: return@mapNotNull null) }.toMap() - inv[8] = Generator.generateEffectiveModifiers(equipment) + inv[8] = Generator.generateEffectiveModifiers(equipment.values) } } .put("card_combiner") { e, inv -> + val p = e.whoClicked as Player + if (inv["running", Boolean::class.java, false]) { + if (e is InventoryClickEvent && e.currentItem?.type.airOrNull) return@put + if (e is InventoryDragEvent && e.newItems.values.all { it.type.airOrNull }) return@put + + inv["stopped"] = true; inv["running"] = false + p.playFailure() + + inv[22] = BattleMaterial.YELLOW_STAINED_GLASS_PANE.findStack().apply { + itemMeta = itemMeta.apply { + displayName = "${ChatColor.YELLOW}${get("constants.place_items")}" + } + }.nbt { nbt -> nbt.addTag("_cancel") } + inv[23] = GUI_BACKGROUND + return@put + } + + val filter = { item: ItemStack? -> item != null && !item.type.airOrNull && (item.isCard || item.id == "card_shard") } + fun matrix() = listOf( + inv[28..34], inv[37..43] + ).flatten().filterNotNull().filter { !it.type.airOrNull } + if (e is InventoryClickEvent) { if (when (e.action) { InventoryAction.MOVE_TO_OTHER_INVENTORY -> inv.firstEmpty() @@ -289,16 +332,17 @@ internal class BattleGUIManager(private val plugin: BattleCards) : Listener { } == 13 ) return@put e.setCancelled(true) - if (if (e.action == InventoryAction.MOVE_TO_OTHER_INVENTORY) !e.currentItem.isCard else !e.cursor.isCard && e.clickedInventory is BattleInventory) + if (if (e.action == InventoryAction.MOVE_TO_OTHER_INVENTORY) !filter(e.currentItem) else !filter(e.cursor) && e.clickedInventory is BattleInventory) return@put e.setCancelled(true) } - if (e is InventoryDragEvent && (13 in e.rawSlots || e.newItems.values.any { !it.isCard })) - return@put e.setCancelled(true) + if (e is InventoryDragEvent) { + if (e.rawSlots.any { it < 54 } && inv["running", Boolean::class.java, false]) + return@put e.setCancelled(true) - fun matrix() = listOf( - inv[28..34], inv[37..43] - ).flatten().filterNotNull().filter { it.type != Material.AIR } + if (13 in e.rawSlots || e.newItems.values.any { !filter(it) }) + return@put e.setCancelled(true) + } sync { val matrix = matrix() diff --git a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleGenerator.kt b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleGenerator.kt index 6c8cde35..dd20c264 100644 --- a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleGenerator.kt +++ b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleGenerator.kt @@ -35,7 +35,6 @@ internal class BattleGenerator(private val plugin: BattleCards) : Listener { private companion object { - @JvmStatic private val rarityChances = Rarity.entries.filter { it != Rarity.BASIC }.associateWith { (2.0 / 10.0.pow(it.ordinal)) } @@ -51,8 +50,8 @@ internal class BattleGenerator(private val plugin: BattleCards) : Listener { if (p.itemInHand.containsEnchantment(Enchantment.LOOT_BONUS_BLOCKS)) luck += p.itemInHand.getEnchantmentLevel(Enchantment.LOOT_BONUS_BLOCKS) - if (block.world.environment == World.Environment.NORMAL && block.x < 48) + if (block.world.environment == World.Environment.NORMAL && block.y < 48) if (r.nextDouble() < 0.08.plus(luck / 100.0).coerceAtMost(0.5)) - block.world.dropItemNaturally(block.location, Items.cardShard(rarityChances.randomCumulative())) + block.world.dropItemNaturally(block.location, Items.cardShard(rarityChances.randomCumulative()!!)) } } \ No newline at end of file diff --git a/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleSpawner.kt b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleSpawner.kt new file mode 100644 index 00000000..7582cad4 --- /dev/null +++ b/plugin/src/main/kotlin/me/gamercoder215/battlecards/BattleSpawner.kt @@ -0,0 +1,89 @@ +package me.gamercoder215.battlecards + +import com.google.common.collect.ImmutableMap +import me.gamercoder215.battlecards.api.card.item.CardEquipment +import me.gamercoder215.battlecards.util.inventory.Items.randomCumulative +import me.gamercoder215.battlecards.util.isCard +import me.gamercoder215.battlecards.util.isMinion +import me.gamercoder215.battlecards.util.itemStack +import me.gamercoder215.battlecards.wrapper.Wrapper.Companion.r +import org.bukkit.enchantments.Enchantment +import org.bukkit.entity.* +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.entity.EntityDamageEvent +import kotlin.math.pow + +internal class BattleSpawner(private val plugin: BattleCards) : Listener { + + init { + plugin.server.pluginManager.registerEvents(this, plugin) + } + + val NO_SPECIAL: (CardEquipment) -> Boolean = { eq -> eq.rarity != CardEquipment.Rarity.SPECIAL } + val CLASSES_TO_EQUIMENT = ImmutableMap.builder<(LivingEntity) -> Boolean, (CardEquipment) -> Boolean>() + .put( + { en -> en is Monster }, + { eq -> eq.damageModifier > 1 && NO_SPECIAL(eq) } + ) + .put( + { en -> en !is Monster && en !is Animals }, + { eq -> eq.healthModifier > 1 && NO_SPECIAL(eq) } + ) + .put( + { en -> en.type == EntityType.ENDERMAN }, + { eq -> eq.speedModifier > 1 && NO_SPECIAL(eq) } + ) + .put( + { en -> en is Animals }, + { eq -> eq.defenseModifier > 1 && NO_SPECIAL(eq) } + ) + .put( + { en -> en is Golem }, + { eq -> eq.defenseModifier > 1 && eq.rarity.ordinal > 0 && NO_SPECIAL(eq) } + ) + .put( + { en -> en is WaterMob }, + { eq -> eq.defenseModifier > 1 && eq.healthModifier > 1 && NO_SPECIAL(eq) } + ) + .put( + { en -> en.type == EntityType.WITHER || en.type == EntityType.ENDER_DRAGON }, + { eq -> eq.rarity.ordinal > 2 } // Mythological & Special + ) + .build()!! + + val EQUIPMENT_RARITY_CHANCES = (CardEquipment.Rarity.entries - CardEquipment.Rarity.SPECIAL) + .associateWith { rarity -> 10.0.pow(rarity.ordinal) } + + @EventHandler + fun onDeath(event: EntityDamageEvent) { + val entity = event.entity as? LivingEntity ?: return + if (entity is Player) return + if (entity.isCard || entity.isMinion) return + + if (entity.health - event.finalDamage > 0) return + + if (r.nextDouble() > 0.1) return + + var rerolls = 0 + var count = 1 + if (event is EntityDamageByEntityEvent && event.damager is Player) { + val p = event.damager as Player + rerolls += p.itemInHand.getEnchantmentLevel(Enchantment.LOOT_BONUS_MOBS).coerceAtMost(7) + count += (p.activePotionEffects + .filter { effect -> effect.type.name == "LUCK" } + .sumOf { effect -> effect.amplifier + 1 } / 2) + .coerceAtMost(3) + } + + val predicates = CLASSES_TO_EQUIMENT.filter { entry -> entry.key(entity) }.entries + val equipments = plugin.registeredEquipment + .filter { eq -> predicates.any { entry -> entry.value(eq) } } + .associateWith { eq -> EQUIPMENT_RARITY_CHANCES[eq.rarity]!! } + + for (i in 1..count) + entity.world.dropItemNaturally(entity.location, equipments.randomCumulative(rerolls)?.itemStack ?: continue) + } + +} \ No newline at end of file diff --git a/plugin/src/main/kotlin/me/gamercoder215/battlecards/placeholderapi/BattlePlaceholders.kt b/plugin/src/main/kotlin/me/gamercoder215/battlecards/placeholderapi/BattlePlaceholders.kt index 155be3f5..fa41eebd 100644 --- a/plugin/src/main/kotlin/me/gamercoder215/battlecards/placeholderapi/BattlePlaceholders.kt +++ b/plugin/src/main/kotlin/me/gamercoder215/battlecards/placeholderapi/BattlePlaceholders.kt @@ -18,7 +18,6 @@ internal class BattlePlaceholders(private val plugin: BattleCards) : Placeholder companion object { - @JvmStatic private val PLACEHOLDERS = ImmutableMap.builder Any>() .put("card_count") { p -> if (p !is Player) return@put 0 diff --git a/plugin/src/main/kotlin/me/gamercoder215/battlecards/vault/VaultChat.kt b/plugin/src/main/kotlin/me/gamercoder215/battlecards/vault/VaultChat.kt index f379416d..46bc8338 100644 --- a/plugin/src/main/kotlin/me/gamercoder215/battlecards/vault/VaultChat.kt +++ b/plugin/src/main/kotlin/me/gamercoder215/battlecards/vault/VaultChat.kt @@ -7,10 +7,8 @@ import java.util.concurrent.atomic.AtomicBoolean internal object VaultChat { - @JvmStatic private lateinit var chat: Chat - @JvmStatic fun loadChat() { if (this::chat.isInitialized) return @@ -18,7 +16,6 @@ internal object VaultChat { if (rsp.provider != null) chat = rsp.provider } - @JvmStatic fun isInGroup(player: Player, vararg groups: String): Boolean { if (!this::chat.isInitialized) return false diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml index 6e68387d..426647be 100644 --- a/plugin/src/main/resources/config.yml +++ b/plugin/src/main/resources/config.yml @@ -10,6 +10,7 @@ # en - English # es - Spanish / Español # fr - French / Français +# tr - Turkish / Türkçe Language: en # Plugin Functionality Configuration