Added extensions module

This commit is contained in:
redtea committed 2023-08-21 13:00:30 +03:00
1 parent 4de4f7bf53
commit baff0de0ba
17 files changed
+1191

No files matched your search

@@ -0,0 +1,33 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.Material
import org.bukkit.block.Block
import org.bukkit.entity.Player
import org.bukkit.material.MaterialData
public infix fun Block.eqType(block: Block): Boolean = type == block.type && data == block.data
public infix fun Block.eqType(data: MaterialData): Boolean = type == data.itemType && this.data == data.data
public infix fun Block.eqType(material: Material): Boolean = type == material
public fun Block.sendBlockChange(
materialData: MaterialData,
players: List<Player>,
): Unit = sendBlockChange(materialData.itemType, materialData.data, players)
public fun Block.sendBlockChange(
material: Material,
data: Byte = 0,
players: List<Player>,
) {
players.filter { it.world.name == world.name }.forEach {
it.sendBlockChange(location, material, data)
}
}
@@ -0,0 +1,72 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import net.md_5.bungee.api.chat.BaseComponent
import net.md_5.bungee.api.chat.TextComponent
import org.bukkit.Bukkit
import org.bukkit.Server
import org.bukkit.command.ConsoleCommandSender
import org.bukkit.entity.Player
public val server: Server get() = Bukkit.getServer()
public object Console : ConsoleCommandSender by Bukkit.getConsoleSender() {
public fun command(command: String): Boolean = Bukkit.dispatchCommand(this, command)
}
// logger
// todo: remove and use standard logging library, maybe extensions for it
public object Log {
public fun info(message: String): Unit = Bukkit.getLogger().info(message)
public fun warn(message: String): Unit = Bukkit.getLogger().warning(message)
public fun severe(message: String): Unit = Bukkit.getLogger().severe(message)
public fun fine(message: String): Unit = Bukkit.getLogger().fine(message)
}
public fun broadcast(message: String) {
Bukkit.broadcastMessage(message)
}
public inline fun broadcast(
players: Iterable<Player> = Bukkit.getOnlinePlayers(),
message: Player.() -> String,
) {
for (player in players)
player.msg(message.invoke(player))
}
public fun Collection<Player>.broadcast(
message: Player.() -> String,
): Unit = broadcast(this, message)
public fun Array<Player>.broadcast(
message: Player.() -> String,
): Unit = broadcast(this.toList(), message)
// BaseComponent
public fun broadcast(message: BaseComponent) {
broadcastComponent { arrayOf(message) }
Bukkit.getConsoleSender().msg(TextComponent.toLegacyText(message))
}
public fun broadcast(message: Array<BaseComponent>) {
broadcastComponent { message }
Bukkit.getConsoleSender().msg(TextComponent.toLegacyText(*message))
}
public inline fun broadcastComponent(
players: Iterable<Player> = Bukkit.getOnlinePlayers(),
message: Player.() -> Array<BaseComponent>,
) {
for (player in players) {
player.msg(message.invoke(player))
}
}
@@ -0,0 +1,49 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.Bukkit
import org.bukkit.command.Command
import org.bukkit.command.SimpleCommandMap
import org.bukkit.plugin.Plugin
import java.lang.reflect.Field
private val serverCommands: SimpleCommandMap by lazy {
val server = Bukkit.getServer()
server::class.java.getDeclaredField("commandMap").apply {
isAccessible = true
}.get(server) as SimpleCommandMap
}
private val knownCommandsField: Field by lazy {
SimpleCommandMap::class.java.getDeclaredField("knownCommands").apply {
isAccessible = true
}
}
public fun Command.register(plugin: Plugin) {
serverCommands.register(plugin.name, this)
}
public fun Command.unregister() {
try {
val knownCommands = knownCommandsField.get(serverCommands) as MutableMap<String, Command>
val toRemove = ArrayList<String>()
for ((key, value) in knownCommands) {
if (value === this) {
toRemove.add(key)
}
}
for (str in toRemove) {
knownCommands.remove(str)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
@@ -0,0 +1,47 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.configuration.ConfigurationSection
public fun ConfigurationSection.putAll(map: Map<String, Any?>) {
for ((key, value) in map) {
if (value is Map<*, *>) {
set(key, null)
(getConfigurationSection(key) ?: createSection(key)).putAll(value as Map<String, Any?>)
} else {
set(key, value)
}
}
}
/**
* @returns the count of absent values that was set, if returns 0, no values was set to the Configuration
*/
public fun ConfigurationSection.putAllIfAbsent(map: Map<String, Any?>): Int {
var missing = 0
for ((key, value) in map) {
if (value is Map<*, *>) {
missing += (getConfigurationSection(key) ?: createSection(key)).putAllIfAbsent(value as Map<String, Any?>)
} else if (!contains(key)) {
missing++
}
}
return missing
}
public fun ConfigurationSection.toMap(): Map<String, Any?> {
return getValues(false).apply {
forEach { k, v ->
if (v is ConfigurationSection) {
set(k, v.toMap())
}
}
}
}
@@ -0,0 +1,41 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.Location
import org.bukkit.entity.Entity
import org.bukkit.entity.EntityType
import org.bukkit.entity.Firework
import org.bukkit.entity.Player
import org.bukkit.entity.Projectile
import org.bukkit.inventory.meta.FireworkMeta
import org.bukkit.projectiles.ProjectileSource
import org.bukkit.util.Vector
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
@OptIn(ExperimentalContracts::class)
public fun Entity.isPlayer(): Boolean {
contract { returns(true) implies (this@isPlayer is Player) }
return type == EntityType.PLAYER
}
// firework
public inline fun firework(location: Location, block: FireworkMeta.() -> Unit): Firework {
return location.spawn<Firework>().apply { meta(block) }
}
public inline fun Firework.meta(block: FireworkMeta.() -> Unit): Firework = apply {
fireworkMeta = fireworkMeta.apply(block)
}
public inline fun <reified T : Projectile> ProjectileSource.launchProjectile(): T = launchProjectile(T::class.java)
public inline fun <reified T : Projectile> ProjectileSource.launchProjectile(vector: Vector): T = launchProjectile(T::class.java, vector)
@@ -0,0 +1,79 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import me.redtea.kotlinbukkitkit.architecture.extensions.WithPlugin
import org.bukkit.Bukkit
import org.bukkit.event.Event
import org.bukkit.event.EventPriority
import org.bukkit.event.HandlerList
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerMoveEvent
import org.bukkit.plugin.Plugin
import kotlin.reflect.KClass
public inline fun <reified T : Event> KListener<*>.event(
priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false,
noinline block: T.() -> Unit,
): Unit = event(plugin, priority, ignoreCancelled, block)
public fun <T : Event> KListener<*>.event(
type: KClass<T>,
priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false,
block: T.() -> Unit,
): Unit = event(plugin, type, priority, ignoreCancelled, block)
public inline fun <reified T : Event> Listener.event(
plugin: Plugin,
priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false,
noinline block: T.() -> Unit,
) {
event<T>(plugin, T::class, priority, ignoreCancelled, block)
}
public fun <T : Event> Listener.event(
plugin: Plugin,
type: KClass<T>,
priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false,
block: T.() -> Unit,
) {
Bukkit.getServer().pluginManager.registerEvent(
type.java,
this,
priority,
{ _, event ->
if (type.isInstance(event)) {
(event as? T)?.block()
}
},
plugin,
ignoreCancelled,
)
}
public inline fun WithPlugin<*>.events(block: KListener<*>.() -> Unit): SimpleKListener = plugin.events(block)
public inline fun Plugin.events(block: KListener<*>.() -> Unit): SimpleKListener = SimpleKListener(this).apply(block)
public fun Listener.registerEvents(plugin: Plugin): Unit = plugin.server.pluginManager.registerEvents(this, plugin)
public fun Listener.unregisterListener(): Unit = HandlerList.unregisterAll(this)
public fun Event.callEvent(): Unit = Bukkit.getServer().pluginManager.callEvent(this)
public val PlayerMoveEvent.displaced: Boolean
get() = this.from.x != this.to?.x || this.from.y != this.to?.y || this.from.z != this.to?.z
// TODO: remove KListener and move to Context Receivers
public interface KListener<T : Plugin> : Listener, WithPlugin<T>
public class SimpleKListener(override val plugin: Plugin) : KListener<Plugin>
@@ -0,0 +1,33 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.Material
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack
public val Inventory.hasSpace: Boolean
get() = contents.any { it == null || it.type == Material.AIR }
public fun Inventory.hasSpace(
item: ItemStack,
amount: Int = item.amount,
): Boolean = spaceOf(item) >= amount
public fun Inventory.spaceOf(
item: ItemStack,
): Int {
return contents.filterNotNull().map {
if (it.amount < it.maxStackSize && it.isSimilar(item)) {
it.maxStackSize - it.amount
} else {
0
}
}.count()
}
@@ -0,0 +1,95 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import com.google.common.collect.Multimap
import org.bukkit.Material
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import org.bukkit.inventory.meta.SkullMeta
import org.bukkit.material.MaterialData
import java.util.*
public inline fun item(
material: Material,
amount: Int = 1,
data: Short = 0,
meta: ItemMeta.() -> Unit = {},
): ItemStack = ItemStack(material, amount, data).meta(meta)
public inline fun <reified T : ItemMeta> metadataItem(
material: Material,
amount: Int = 1,
data: Short = 0,
meta: T.() -> Unit,
): ItemStack = ItemStack(material, amount, data).meta(meta)
public inline fun <reified T : ItemMeta> ItemStack.meta(
block: T.() -> Unit,
): ItemStack = apply {
itemMeta = (itemMeta as? T)?.apply(block) ?: itemMeta
}
public fun ItemStack.displayName(displayName: String?): ItemStack = meta<ItemMeta> {
this.setDisplayName(displayName)
}
public fun ItemStack.lore(lore: List<String>): ItemStack = meta<ItemMeta> {
this.lore = lore
}
public inline fun Material.asItemStack(
amount: Int = 1,
data: Short = 0,
meta: ItemMeta.() -> Unit = {},
): ItemStack = item(this, amount, data, meta)
public fun Material.asMaterialData(
data: Byte = 0,
): MaterialData = MaterialData(this, data)
public fun MaterialData.toItemStack(
amount: Int = 1,
meta: ItemMeta.() -> Unit = {},
): ItemStack = toItemStack(amount).meta(meta)
/**
* get head from base64
*/
private val gameProfileClass by lazy { Class.forName("com.mojang.authlib.GameProfile") }
private val propertyClass by lazy { Class.forName("com.mojang.authlib.properties.Property") }
private val getPropertiesMethod by lazy { gameProfileClass.getMethod("getProperties") }
private val gameProfileConstructor by lazy { gameProfileClass.getConstructor(UUID::class.java, String::class.java) }
private val propertyConstructor by lazy { propertyClass.getConstructor(String::class.java, String::class.java) }
public fun headFromBase64(base64: String): ItemStack {
val item = ItemStack(Material.LEGACY_SKULL_ITEM, 1, 3)
val meta = item.itemMeta as SkullMeta
val profile = gameProfileConstructor.newInstance(UUID.randomUUID(), null as String?)
val properties = getPropertiesMethod.invoke(profile) as Multimap<Any, Any>
properties.put("textures", propertyConstructor.newInstance("textures", base64))
val profileField = meta.javaClass.getDeclaredField("profile").apply { isAccessible = true }
profileField.set(meta, profile)
return item.apply { itemMeta = meta }
}
public inline val Material.isPickaxe: Boolean get() = name.endsWith("PICKAXE")
public inline val Material.isSword: Boolean get() = name.endsWith("SWORD")
public inline val Material.isAxe: Boolean get() = name.endsWith("_AXE")
public inline val Material.isSpade: Boolean get() = name.endsWith("SPADE")
public inline val Material.isHoe: Boolean get() = name.endsWith("HOE")
public inline val Material.isOre: Boolean get() = name.endsWith("ORE")
public inline val Material.isIngot: Boolean get() = name.endsWith("INGOT")
public inline val Material.isDoor: Boolean get() = name.endsWith("DOOR")
public inline val Material.isMinecart: Boolean get() = name.endsWith("MINECART")
public inline val Material.isWater: Boolean get() = this == Material.WATER || this == Material.LEGACY_STATIONARY_WATER
public inline val Material.isLava: Boolean get() = this == Material.LAVA || this == Material.LEGACY_STATIONARY_LAVA
@@ -0,0 +1,57 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.BlockChangeDelegate
import org.bukkit.Effect
import org.bukkit.Location
import org.bukkit.Sound
import org.bukkit.TreeType
import org.bukkit.block.Block
import org.bukkit.entity.Arrow
import org.bukkit.entity.Entity
import org.bukkit.entity.Item
import org.bukkit.entity.LightningStrike
import org.bukkit.inventory.ItemStack
import org.bukkit.util.Vector
public operator fun Location.component1(): Double = x
public operator fun Location.component2(): Double = y
public operator fun Location.component3(): Double = z
public operator fun Location.component4(): Float = yaw
public operator fun Location.component5(): Float = pitch
public operator fun Block.component1(): Int = x
public operator fun Block.component2(): Int = y
public operator fun Block.component3(): Int = z
public fun Location.dropItem(item: ItemStack): Item = world!!.dropItem(this, item)
public fun Location.dropItemNaturally(item: ItemStack): Item = world!!.dropItemNaturally(this, item)
public fun Location.spawnArrow(direction: Vector, speed: Float, spread: Float): Arrow = world!!.spawnArrow(this, direction, speed, spread)
public fun Location.generateTree(type: TreeType): Boolean = world!!.generateTree(this, type)
public fun Location.generateTree(type: TreeType, delegate: BlockChangeDelegate): Boolean = world!!.generateTree(this, type, delegate)
public fun Location.strikeLightning(): LightningStrike = world!!.strikeLightning(this)
public fun Location.strikeLightningEffect(): LightningStrike = world!!.strikeLightningEffect(this)
public fun Location.getNearbyEntities(x: Double, y: Double, z: Double): MutableCollection<Entity> = world!!.getNearbyEntities(this, x, y, z)
public fun Location.createExplosion(power: Float): Boolean = world!!.createExplosion(this, power)
public fun Location.createExplosion(power: Float, setFire: Boolean): Boolean = world!!.createExplosion(this, power, setFire)
public inline fun <reified T : Entity> Location.spawn(): T = world!!.spawn<T>(this)
public fun Location.playEffect(effect: Effect, data: Int): Unit = world!!.playEffect(this, effect, data)
public fun Location.playEffect(effect: Effect, data: Int, radius: Int): Unit = world!!.playEffect(this, effect, data, radius)
public fun <T> Location.playEffect(effect: Effect, data: T): Unit = world!!.playEffect(this, effect, data)
public fun <T> Location.playEffect(effect: Effect, data: T, radius: Int): Unit = world!!.playEffect(this, effect, data, radius)
public fun Location.playSound(sound: Sound, volume: Float, pitch: Float): Unit = world!!.playSound(this, sound, volume, pitch)
@@ -0,0 +1,17 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.permissions.Permissible
public fun Permissible.anyPermission(vararg permissions: String): Boolean = permissions.any { hasPermission(it) }
public fun Permissible.allPermission(vararg permissions: String): Boolean = permissions.all { hasPermission(it) }
public fun Permissible.hasPermissionOrStar(permission: String): Boolean = hasPermission(permission) || hasPermission(permission.replaceAfterLast('.', "*"))
@@ -0,0 +1,44 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.Effect
import org.bukkit.Instrument
import org.bukkit.Material
import org.bukkit.Note
import org.bukkit.Sound
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.PlayerInventory
public fun PlayerInventory.clearArmor() {
setArmorContents(arrayOf<ItemStack?>(null, null, null, null))
}
public fun PlayerInventory.clearAll() {
clear()
clearArmor()
}
public val Player.hasItemInHand: Boolean get() = itemInHand != null && itemInHand.type != Material.AIR
public fun Player.playSound(sound: Sound, volume: Float, pitch: Float): Unit = playSound(location, sound, volume, pitch)
public fun Player.playNote(instrument: Instrument, note: Note): Unit = playNote(location, instrument, note)
public fun <T> Player.playEffect(effect: Effect, data: T? = null): Unit = playEffect(location, effect, data)
public fun CommandSender.msg(message: List<String>): Unit = message.forEach { msg(it) }
public fun Player.resetWalkSpeed() {
walkSpeed = 0.2f
}
public fun Player.resetFlySpeed() {
flySpeed = 0.1f
}
@@ -0,0 +1,34 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import me.redtea.kotlinbukkitkit.architecture.extensions.WithPlugin
import org.bukkit.event.Listener
import org.bukkit.plugin.Plugin
public fun Plugin.registerEvents(
vararg listeners: Listener,
): Unit = listeners.forEach { server.pluginManager.registerEvents(it, this) }
public fun WithPlugin<*>.registerEvents(
vararg listeners: Listener,
): Unit = plugin.registerEvents(*listeners)
// logger
public fun Plugin.info(message: String): Unit = logger.info(message)
public fun Plugin.warn(message: String): Unit = logger.warning(message)
public fun Plugin.severe(message: String): Unit = logger.severe(message)
public fun Plugin.debug(message: String): Unit = logger.config(message)
public fun Plugin.fine(message: String): Unit = logger.fine(message)
public fun WithPlugin<*>.info(message: String): Unit = plugin.info(message)
public fun WithPlugin<*>.warn(message: String): Unit = plugin.warn(message)
public fun WithPlugin<*>.severe(message: String): Unit = plugin.severe(message)
public fun WithPlugin<*>.debug(message: String): Unit = plugin.debug(message)
public fun WithPlugin<*>.fine(message: String): Unit = plugin.fine(message)
@@ -0,0 +1,70 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import me.redtea.kotlinbukkitkit.architecture.extensions.WithPlugin
import org.bukkit.plugin.Plugin
import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.scheduler.BukkitTask
public inline fun task(
delayToRun: Long = 0,
repeatDelay: Long = -1,
plugin: Plugin,
crossinline runnable: BukkitRunnable.() -> Unit,
): BukkitTask = task(delayToRun, repeatDelay, false, plugin, runnable)
public inline fun Plugin.task(
delayToRun: Long = 0,
repeatDelay: Long = -1,
crossinline runnable: BukkitRunnable.() -> Unit,
): BukkitTask = task(delayToRun, repeatDelay, this, runnable)
public inline fun WithPlugin<*>.task(
delayToRun: Long = 0,
repeatDelay: Long = -1,
crossinline runnable: BukkitRunnable.() -> Unit,
): BukkitTask = plugin.task(delayToRun, repeatDelay, runnable)
public inline fun taskAsync(
delayToRun: Long = 0,
repeatDelay: Long = -1,
plugin: Plugin,
crossinline runnable: BukkitRunnable.() -> Unit,
): BukkitTask = task(delayToRun, repeatDelay, true, plugin, runnable)
public inline fun Plugin.taskAsync(
delayToRun: Long = 0,
repeatDelay: Long = -1,
crossinline runnable: BukkitRunnable.() -> Unit,
): BukkitTask = taskAsync(delayToRun, repeatDelay, this, runnable)
public inline fun WithPlugin<*>.taskAsync(
delayToRun: Long = 0,
repeatDelay: Long = -1,
crossinline runnable: BukkitRunnable.() -> Unit,
): BukkitTask = plugin.taskAsync(delayToRun, repeatDelay, runnable)
public inline fun task(
delayToRun: Long,
repeatDelay: Long = -1,
async: Boolean,
plugin: Plugin,
crossinline runnable: BukkitRunnable.() -> Unit,
): BukkitTask = scheduler(runnable).run {
if (repeatDelay > -1) if (async) runTaskTimerAsynchronously(plugin, delayToRun, repeatDelay) else runTaskTimer(plugin, delayToRun, repeatDelay)
else if (delayToRun > 0) if (async) runTaskLaterAsynchronously(plugin, delayToRun) else runTaskLater(plugin, delayToRun)
else if (async) runTaskAsynchronously(plugin) else runTask(plugin)
}
public inline fun scheduler(crossinline runnable: BukkitRunnable.() -> Unit): BukkitRunnable = object : BukkitRunnable() {
override fun run() {
this.runnable()
}
}
@@ -0,0 +1,90 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.GameMode
import org.bukkit.OfflinePlayer
import org.bukkit.World
import org.bukkit.WorldCreator
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.Recipe
import org.bukkit.plugin.PluginManager
import org.bukkit.plugin.ServicesManager
import org.bukkit.plugin.messaging.Messenger
import org.bukkit.scheduler.BukkitScheduler
import org.bukkit.scoreboard.ScoreboardManager
import java.io.File
import java.util.*
public val isPrimaryThread: Boolean get() = server.isPrimaryThread
public fun offlinePlayer(uuid: UUID): OfflinePlayer = server.getOfflinePlayer(uuid)
public fun offlinePlayer(name: String): OfflinePlayer = server.getOfflinePlayer(name)
public fun player(uuid: UUID): Player? = server.getPlayer(uuid)
public fun player(name: String): Player? = server.getPlayer(name)
public fun playerExact(name: String): Player? = server.getPlayerExact(name)
public fun matchPlayer(name: String): List<Player> = server.matchPlayer(name)
public fun onlinePlayer(uuid: UUID): Player? = server.getPlayer(uuid)
public fun onlinePlayer(name: String): Player? = server.getPlayerExact(name)
public val onlinePlayers: Collection<Player> get() = server.onlinePlayers
public val worldType: String get() = server.worldType
public val generateStructures: Boolean get() = server.generateStructures
public val allowEnd: Boolean get() = server.allowEnd
public val allowNether: Boolean get() = server.allowNether
public val allowFlight: Boolean get() = server.allowFlight
public val whitelistedPlayers: MutableSet<OfflinePlayer> get() = server.whitelistedPlayers
public val updateFolder: String get() = server.updateFolder
public val updateFolderFile: File get() = server.updateFolderFile
public val connectionThrottle: Long get() = server.connectionThrottle
public val recipes: Iterator<Recipe> get() = server.recipeIterator()
public val ticksPerAnimalSpawns: Int get() = server.ticksPerAnimalSpawns
public val ticksPerMonsterSpawns: Int get() = server.ticksPerMonsterSpawns
public val pluginManager: PluginManager get() = server.pluginManager
public val scheduler: BukkitScheduler get() = server.scheduler
public val servicesManager: ServicesManager get() = server.servicesManager
public val worlds: List<World> get() = server.worlds
public val onlineMode: Boolean get() = server.onlineMode
public val isHardcore: Boolean get() = server.isHardcore
public val bannedPlayers: Set<OfflinePlayer> get() = server.bannedPlayers
public val ipBans: Set<String> get() = server.ipBans
public val operators: Set<OfflinePlayer> get() = server.operators
public val worldContainer: File get() = server.worldContainer
public val messenger: Messenger get() = server.messenger
public val monsterSpawnLimit: Int get() = server.monsterSpawnLimit
public val animalSpawnLimit: Int get() = server.animalSpawnLimit
public val ambientSpawnLimit: Int get() = server.ambientSpawnLimit
public val scoreboardManager: ScoreboardManager? get() = server.scoreboardManager
public var idleTimeout: Int
get() = server.idleTimeout
set(value) { server.idleTimeout = value }
public var defaultGameMode: GameMode
get() = server.defaultGameMode
set(value) { server.defaultGameMode = value }
public var spawnRadius: Int
get() = server.spawnRadius
set(value) { server.spawnRadius = value }
public var whitelist: Boolean
get() = server.hasWhitelist()
set(value) { server.setWhitelist(value) }
public fun reloadWhitelist(): Unit = server.reloadWhitelist()
public fun world(name: String): World? = server.getWorld(name)
public fun addRecipe(recipe: Recipe): Boolean = server.addRecipe(recipe)
public fun recipesFor(item: ItemStack): List<Recipe> = server.getRecipesFor(item)
public fun WorldCreator.create(): World? = server.createWorld(this)
@@ -0,0 +1,374 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import net.md_5.bungee.api.chat.BaseComponent
import net.md_5.bungee.api.chat.ClickEvent
import net.md_5.bungee.api.chat.HoverEvent
import net.md_5.bungee.api.chat.TextComponent
import net.md_5.bungee.chat.ComponentSerializer
import org.bukkit.ChatColor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import kotlin.reflect.KProperty
import net.md_5.bungee.api.ChatColor as BungeeColor
public fun CommandSender.msg(message: String): Unit = sendMessage(message)
public fun CommandSender.msg(message: Array<String>): Unit = sendMessage(message)
/**
* ONLY WITH SPIGOT
*/
public fun textOf(text: String): TextComponent = text.asText()
public fun String.translateColor(code: Char = '&'): String = ChatColor.translateAlternateColorCodes(code, this)
public fun Collection<String>.translateColor(code: Char = '&'): List<String> = map { it.translateColor(code) }
public fun <V> Map<String, V>.translateColorKeys(code: Char = '&'): Map<String, V> = mapKeys { it.key.translateColor(code) }
public fun <K> Map<K, String>.translateColorValues(code: Char = '&'): Map<K, String> = mapValues { it.value.translateColor(code) }
public fun String.reverseTranslateColor(code: Char = '&'): String = replace('§', code)
public fun Collection<String>.reverseTranslateColor(code: Char = '&'): List<String> = map { it.reverseTranslateColor(code) }
public fun <V> Map<String, V>.reverseTranslateColorKeys(code: Char = '&'): Map<String, V> = mapKeys { it.key.reverseTranslateColor(code) }
public fun <K> Map<K, String>.reverseTranslateColorValues(code: Char = '&'): Map<K, String> = mapValues { it.value.reverseTranslateColor(code) }
public operator fun ChatColor.plus(text: String): String = toString() + text
public operator fun ChatColor.plus(other: ChatColor): String = toString() + other.toString()
public fun translateColor(default: String, colorChar: Char = '&'): TranslateChatColorDelegate = TranslateChatColorDelegate(default, colorChar)
public class TranslateChatColorDelegate(public val realValue: String, public val colorChar: Char = '&') {
private var _value: String = ChatColor.translateAlternateColorCodes(colorChar, realValue)
public operator fun getValue(thisRef: Any?, property: KProperty<*>): String = _value
public operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
_value = ChatColor.translateAlternateColorCodes(colorChar, value)
}
}
public fun Player.sendMessage(text: BaseComponent): Unit = spigot().sendMessage(text)
public fun Player.sendMessage(text: Array<BaseComponent>): Unit = spigot().sendMessage(TextComponent(*text))
public fun Player.sendMessage(text: List<BaseComponent>): Unit = sendMessage(text.toTypedArray())
public fun CommandSender.sendMessage(text: BaseComponent): Unit = (this as? Player)?.let { it.sendMessage(text) } ?: sendMessage(TextComponent.toLegacyText(text))
public fun CommandSender.sendMessage(text: Array<BaseComponent>): Unit = (this as? Player)?.let { it.sendMessage(text) } ?: sendMessage(TextComponent.toLegacyText(*text))
public fun CommandSender.sendMessage(text: List<BaseComponent>): Unit = sendMessage(text.toTypedArray())
public fun Player.msg(text: BaseComponent): Unit = sendMessage(text)
public fun Player.msg(text: Array<BaseComponent>): Unit = sendMessage(text)
public fun Player.msg(text: List<BaseComponent>): Unit = sendMessage(text)
public fun CommandSender.msg(text: BaseComponent): Unit = sendMessage(text)
public fun CommandSender.msg(text: Array<BaseComponent>): Unit = sendMessage(text)
public fun CommandSender.msg(text: List<BaseComponent>): Unit = sendMessage(text)
public fun String.asText(): TextComponent = TextComponent(*TextComponent.fromLegacyText(this))
public fun List<String>.asText(): TextComponent = TextComponent(*map { it.asText() }.toTypedArray())
// fun String.asText() = TextComponent(this)
public fun BaseComponent.toJson(): String = ComponentSerializer.toString(this)
public fun Array<BaseComponent>.toJson(): String = ComponentSerializer.toString(*this)
public operator fun <T : BaseComponent> T.plus(component: BaseComponent): T = apply { addExtra(component) }
public operator fun <T : BaseComponent> T.plus(text: String): T = apply { addExtra(text) }
public fun String.color(color: BungeeColor): TextComponent = asText().color(color)
public fun String.color(color: ChatColor): TextComponent = asText().color(BungeeColor.getByChar(color.char))
public fun String.bold(): TextComponent = asText().bold()
public fun String.italic(): TextComponent = asText().italic()
public fun String.underline(): TextComponent = asText().underline()
public fun String.strikethrough(): TextComponent = asText().strikethrough()
public fun String.obfuscated(): TextComponent = asText().obfuscated()
public fun String.click(clickEvent: ClickEvent): TextComponent = asText().click(clickEvent)
public fun String.openUrl(url: String): TextComponent = click(ClickEvent(ClickEvent.Action.OPEN_URL, url))
public fun String.runCommand(command: String): TextComponent = click(ClickEvent(ClickEvent.Action.RUN_COMMAND, command))
public fun String.suggestCommand(command: String): TextComponent = click(ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command))
public fun String.hover(hoverEvent: HoverEvent): TextComponent = asText().hover(hoverEvent)
public fun String.showText(component: BaseComponent): TextComponent = hover(HoverEvent(HoverEvent.Action.SHOW_TEXT, arrayOf(component)))
public fun String.showText(vararg components: BaseComponent): TextComponent = hover(HoverEvent(HoverEvent.Action.SHOW_TEXT, components))
/**
* Chaining methods for TextComponent and BaseComponent
*/
public fun TextComponent.append(text: String): TextComponent = apply { addExtra(text) }
public fun TextComponent.append(text: BaseComponent): TextComponent = apply { addExtra(text) }
public fun TextComponent.breakLine(): TextComponent = apply { addExtra("\\n") }
public fun <T : BaseComponent> T.color(color: BungeeColor): T = apply { this.color = color }
public fun <T : BaseComponent> T.color(color: ChatColor): T = apply { this.color = BungeeColor.getByChar(color.char) }
public fun <T : BaseComponent> T.bold(): T = apply { isBold = true }
public fun <T : BaseComponent> T.italic(): T = apply { isItalic = true }
public fun <T : BaseComponent> T.underline(): T = apply { isUnderlined = true }
public fun <T : BaseComponent> T.strikethrough(): T = apply { isStrikethrough = true }
public fun <T : BaseComponent> T.obfuscated(): T = apply { isObfuscated = true }
public fun <T : BaseComponent> T.click(clickEvent: ClickEvent): T = apply { this.clickEvent = clickEvent }
public fun <T : BaseComponent> T.openUrl(url: String): T = click(ClickEvent(ClickEvent.Action.OPEN_URL, url))
public fun <T : BaseComponent> T.runCommand(command: String): T = click(ClickEvent(ClickEvent.Action.RUN_COMMAND, command))
public fun <T : BaseComponent> T.suggestCommand(command: String): T = click(ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command))
public fun <T : BaseComponent> T.hover(hoverEvent: HoverEvent): T = apply { this.hoverEvent = hoverEvent }
public fun <T : BaseComponent> T.showText(component: BaseComponent): T = hover(HoverEvent(HoverEvent.Action.SHOW_TEXT, arrayOf(component)))
public fun <T : BaseComponent> T.showText(vararg components: BaseComponent): T = hover(HoverEvent(HoverEvent.Action.SHOW_TEXT, components))
/**
* Replaces
*/
/**
* Replace current [TextComponent.text], [BaseComponent.hover] text
* and [BaseComponent.click] text using [String.replace].
*/
public fun <T : BaseComponent> T.replace(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
replaceOnHover(oldValue, newValue, ignoreCase)
replaceOnClick(oldValue, newValue, ignoreCase)
(this as? TextComponent)?.replaceOnText(oldValue, newValue, ignoreCase)
}
/**
* Replace the current [BaseComponent] text, hover and click and all the [BaseComponent.extra]
*
* See [BaseComponent.replace].
*/
public fun <T : BaseComponent> T.replaceAll(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
replaceOnAllHovers(oldValue, newValue, ignoreCase)
replaceOnAllClick(oldValue, newValue, ignoreCase)
(this as? TextComponent)?.replaceOnAllTexts(oldValue, newValue, ignoreCase)
}
/**
* Replace the current [BaseComponent] hover [oldValue] to [newValue] with [String.replace]
*/
public fun <T : BaseComponent> T.replaceOnHover(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
if (hoverEvent != null) {
for (component in hoverEvent.value)
if (component is TextComponent) component.replaceOnAllTexts(oldValue, newValue, ignoreCase)
}
}
/**
* Replace the current [BaseComponent] hover and all the [BaseComponent.extra]
*
* See [BaseComponent.replaceOnHover]
*/
public fun <T : BaseComponent> T.replaceOnAllHovers(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T {
return apply {
replaceOnHover(oldValue, newValue, ignoreCase)
if (extra != null) {
for (component in extra)
component.replaceOnAllHovers(oldValue, newValue, ignoreCase)
}
}
}
public fun <T : BaseComponent> T.replaceOnShowText(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
if (hoverEvent != null) {
if (hoverEvent.action == HoverEvent.Action.SHOW_TEXT) {
for (component in hoverEvent.value)
if (component is TextComponent) {
component.replaceOnAllTexts(oldValue, newValue, ignoreCase)
}
}
}
}
public fun <T : BaseComponent> T.replaceOnAllShowText(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
replaceOnShowText(oldValue, newValue, ignoreCase)
if (extra != null) {
for (component in extra) component.replaceOnAllShowText(oldValue, newValue, ignoreCase)
}
}
/**
* Replace the current [BaseComponent] click [oldValue] to [newValue] with [String.replace]
*/
public fun <T : BaseComponent> T.replaceOnClick(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
if (clickEvent != null) {
click(ClickEvent(clickEvent.action, clickEvent.value.replace(oldValue, newValue, ignoreCase)))
}
}
/**
* Replace the current [BaseComponent] click and all [BaseComponent.extra]
*
* See [BaseComponent.replaceOnClick]
*/
public fun <T : BaseComponent> T.replaceOnAllClick(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
replaceOnClick(oldValue, newValue, ignoreCase)
if (extra != null) {
for (component in extra)
component.replaceOnAllClick(oldValue, newValue, ignoreCase)
}
}
public fun <T : BaseComponent> T.replaceOnRunCommand(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
if (clickEvent != null && clickEvent.action == ClickEvent.Action.RUN_COMMAND) {
runCommand(clickEvent.value.replace(oldValue, newValue, ignoreCase))
}
}
public fun <T : BaseComponent> T.replaceOnAllRunCommand(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): T = apply {
replaceOnRunCommand(oldValue, newValue, ignoreCase)
if (extra != null) {
for (component in extra)
component.replaceOnRunCommand(oldValue, newValue, ignoreCase)
}
}
/**
* Replace the [TextComponent.text] with [String.replace]
*/
public fun TextComponent.replaceOnText(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): TextComponent = apply {
this.text = text.replace(oldValue, newValue, ignoreCase)
}
/**
* Replace the current [TextComponent.text] and all the [TextComponent.extra].
*
* See [TextComponent.replaceOnText]
*/
public fun TextComponent.replaceOnAllTexts(
oldValue: String,
newValue: String,
ignoreCase: Boolean = false,
): TextComponent = apply {
replaceOnText(oldValue, newValue, ignoreCase)
if (extra != null) {
for (component in extra)
if (component is TextComponent) {
component.replaceOnAllTexts(oldValue, newValue, ignoreCase)
}
}
}
/**
* Replace the current [TextComponent.text] [oldValue] to [newValue].
*/
public fun TextComponent.replace(
oldValue: String,
newValue: TextComponent,
ignoreCase: Boolean = false,
): TextComponent = split(oldValue, ignoreCase = ignoreCase, limit = 0).joinToText(newValue)
/**
* Replace the current [TextComponent.text] and all the [TextComponent.extra] [oldValue] to [newValue].
*/
public fun TextComponent.replaceAll(
oldValue: String,
newValue: TextComponent,
ignoreCase: Boolean = false,
): TextComponent = replace(oldValue, newValue, ignoreCase).apply {
if (extra != null) {
extra = extra.map {
if (it is TextComponent) {
it.replaceAll(oldValue, newValue, ignoreCase)
} else {
it
}
}.toMutableList()
}
}
/**
* Splits this [TextComponent.text] into a list of [TextComponent] around occurrences of the specified [delimiters].
*
* @param delimiters One or more characters to be used as delimiters.
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
* @param limit The maximum number of substrings to return.
*/
public fun TextComponent.split(
vararg delimiters: String,
ignoreCase: Boolean = false,
limit: Int = 0,
): List<TextComponent> {
val copy = duplicate().apply { extra?.clear() }
val list = text.split(*delimiters, ignoreCase = ignoreCase, limit = limit).map {
(copy.duplicate() as TextComponent).apply {
text = it
}
}
if (list.isNotEmpty()) {
duplicate().also { if (it.extra != null) list.last().extra = it.extra }
}
return list
}
/**
* Creates a [TextComponent] from all the elements separated using [separator] (none by default)
* and using the given [prefix] (none by default) and [postfix] (none by default).
*
* If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit]
* elements will be appended.
*/
public fun List<TextComponent>.joinToText(
separator: TextComponent? = null,
prefix: TextComponent? = null,
suffix: TextComponent? = null,
limit: Int = -1,
): TextComponent {
if (isEmpty()) return TextComponent("")
var component = prefix?.append(get(0)) ?: get(0)
var count = 0
for (element in this) {
if (++count > 1 && separator != null) component.append(separator)
if (limit < 0 || count <= limit) {
if (count > 1) component.append(element)
} else {
break
}
}
if (suffix != null) component.append(suffix)
return component
}
@@ -0,0 +1,55 @@
/*
ORIGINAL PACKAGE: package br.com.devsrsouza.kotlinbukkitapi.extensions
ORIGINAL REPOSITORY: https://github.com/DevSrSouza/KotlinBukkitAPI
AUTHOR: https://github.com/DevSrSouza
Thanks DevSrSouza for KotlinBukkitAPI
*/
package me.redtea.kotlinbukkitkit.extensions
import org.bukkit.Bukkit
import org.bukkit.Chunk
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.World
import org.bukkit.block.Block
import org.bukkit.entity.Entity
import org.bukkit.entity.Item
import org.bukkit.material.MaterialData
public fun mainWorld(): World = Bukkit.getWorlds()[0]
public fun chunk(world: World, x: Int, y: Int): Chunk = world.getChunkAt(x, y)
public fun chunk(block: Block): Chunk = chunk(block.world, block.x shr 4, block.z shr 4)
public inline fun <reified T : Entity> World.spawn(location: Location): T {
return spawn(location, T::class.java)
}
public inline fun <reified T : Entity> World.getEntitiesByClass(): Collection<T> {
return getEntitiesByClass(T::class.java)
}
public fun World.dropItem(location: Location, material: Material, data: Byte = 0): Item {
return dropItem(location, material.asMaterialData(data))
}
public fun World.dropItem(location: Location, materialData: MaterialData): Item {
return dropItem(location, materialData.toItemStack(1))
}
public fun World.dropItemNaturally(location: Location, material: Material, data: Byte = 0): Item {
return dropItemNaturally(location, material.asMaterialData(data))
}
public fun World.dropItemNaturally(location: Location, materialData: MaterialData): Item {
return dropItemNaturally(location, materialData.toItemStack(1))
}
public fun World.setSpawnLocation(location: Location): Boolean {
return setSpawnLocation(location.blockX, location.blockY, location.blockZ)
}
public fun World.setSpawnLocation(block: Block): Boolean {
return setSpawnLocation(block.x, block.y, block.z)
}
+1
View File
@@ -2,3 +2,4 @@
rootProject.name = "kotlinbukkitkit" rootProject.name = "kotlinbukkitkit"
include("architecture") include("architecture")
include("messages") include("messages")
include("extensions")