Applied kotlin style conventions

This commit is contained in:
bluefireoly
2020-10-18 18:36:49 +02:00
parent e1d4e8bbfc
commit da848728d2
39 changed files with 509 additions and 385 deletions

View File

@@ -37,7 +37,11 @@ class KSpigotComponentBuilder {
this += SelectorComponent(selector).apply(builder) this += SelectorComponent(selector).apply(builder)
} }
inline fun translatable(translatable: String, with: Array<BaseComponent>, builder: TranslatableComponent.() -> Unit = { }) { inline fun translatable(
translatable: String,
with: Array<BaseComponent>,
builder: TranslatableComponent.() -> Unit = { }
) {
this += TranslatableComponent(translatable, with).apply(builder) this += TranslatableComponent(translatable, with).apply(builder)
} }
@@ -47,8 +51,13 @@ class KSpigotComponentBuilder {
this += TextComponent.fromLegacyText(text, color) this += TextComponent.fromLegacyText(text, color)
} }
operator fun plusAssign(baseComponent: BaseComponent) { components += baseComponent } operator fun plusAssign(baseComponent: BaseComponent) {
operator fun plusAssign(baseComponents: Array<out BaseComponent>) { components += baseComponents } components += baseComponent
}
operator fun plusAssign(baseComponents: Array<out BaseComponent>) {
components += baseComponents
}
fun create() = components.toTypedArray() fun create() = components.toTypedArray()

View File

@@ -28,24 +28,26 @@ import kotlin.reflect.KProperty
* exist and no default config is specified. * exist and no default config is specified.
*/ */
inline fun <reified T : Any> kSpigotJsonConfig( inline fun <reified T : Any> kSpigotJsonConfig(
file: File, file: File,
noinline default: (() -> T)? = null, noinline default: (() -> T)? = null,
) = ConfigDelegate(T::class, file, default) ) = ConfigDelegate(T::class, file, default)
/** /**
* @see kSpigotJsonConfig * @see kSpigotJsonConfig
*/ */
class ConfigDelegate<T : Any> ( class ConfigDelegate<T : Any>(
private val configClass: KClass<T>, private val configClass: KClass<T>,
private val file: File, private val file: File,
private val defaultCallback: (() -> T)? private val defaultCallback: (() -> T)?
) { ) {
private var internalConfig: T = loadIt() private var internalConfig: T = loadIt()
var data: T var data: T
get() = internalConfig get() = internalConfig
set(value) { internalConfig = value } set(value) {
internalConfig = value
}
operator fun getValue(thisRef: Any?, property: KProperty<*>) = internalConfig operator fun getValue(thisRef: Any?, property: KProperty<*>) = internalConfig
@@ -62,25 +64,26 @@ class ConfigDelegate<T : Any> (
/** /**
* Loads the current state of the config on disk to the config object. * Loads the current state of the config on disk to the config object.
*/ */
fun reload() { loadIt() } fun reload() {
loadIt()
}
private fun saveIt(toSave: T) { private fun saveIt(toSave: T) {
GsonConfigManager.saveConfig(file, toSave, true) GsonConfigManager.saveConfig(file, toSave, true)
internalConfig = toSave internalConfig = toSave
} }
private fun loadIt() private fun loadIt() = if (defaultCallback == null)
= if (defaultCallback == null) GsonConfigManager.loadConfig(file, configClass)
GsonConfigManager.loadConfig(file, configClass) else
else GsonConfigManager.loadOrCreateDefault(file, configClass, true, defaultCallback)
GsonConfigManager.loadOrCreateDefault(file, configClass, true, defaultCallback)
} }
internal object GsonConfigManager { internal object GsonConfigManager {
fun <T : Any> loadConfig(file: File, configClass: KClass<T>): T fun <T : Any> loadConfig(file: File, configClass: KClass<T>): T =
= FileReader(file).use { reader -> return getGson(false).fromJson(reader, configClass.java) } FileReader(file).use { reader -> return getGson(false).fromJson(reader, configClass.java) }
fun <T : Any> saveConfig(file: File, config: T, pretty: Boolean = true) { fun <T : Any> saveConfig(file: File, config: T, pretty: Boolean = true) {
file.createIfNotExists() file.createIfNotExists()

View File

@@ -3,10 +3,9 @@ package net.axay.kspigot.config
import net.axay.kspigot.main.KSpigotMainInstance import net.axay.kspigot.main.KSpigotMainInstance
import java.io.File import java.io.File
class PluginFile(path: String, child: String? = null) class PluginFile(path: String, child: String? = null) : File(
: File( "${KSpigotMainInstance.dataFolder}",
"${KSpigotMainInstance.dataFolder}", run {
run { if (child == null) path else File(path, child).path
if (child == null) path else File(path, child).path }
} )
)

View File

@@ -19,8 +19,9 @@ var Entity.nbtData: NBTData
} }
@NMS_General @NMS_General
val ItemStack.nbtData: NBTData get() { val ItemStack.nbtData: NBTData
CraftItemStack.asNMSCopy(this).let { get() {
return if (it.hasTag()) NBTData(it.tag) else NBTData() CraftItemStack.asNMSCopy(this).let {
return if (it.hasTag()) NBTData(it.tag) else NBTData()
}
} }
}

View File

@@ -11,17 +11,27 @@ interface NBTDataType<T> {
companion object { companion object {
val COMPOUND = nbtDataType<NBTData, NBTTagCompound>({ NBTData(it) }, { key, data, compound -> compound.set(key, data.nbtTagCompound) }) val COMPOUND = nbtDataType<NBTData, NBTTagCompound>({ NBTData(it) },
val BYTE = nbtDataType<Byte, NBTTagByte>({ it.asByte() }, { key, data, compound -> compound.setByte(key, data) }) { key, data, compound -> compound.set(key, data.nbtTagCompound) })
val BYTE_ARRAY = nbtDataType<ByteArray, NBTTagByteArray>({ it.bytes }, { key, data, compound -> compound.setByteArray(key, data) }) val BYTE =
val DOUBLE = nbtDataType<Double, NBTTagDouble>({ it.asDouble() }, { key, data, compound -> compound.setDouble(key, data) }) nbtDataType<Byte, NBTTagByte>({ it.asByte() }, { key, data, compound -> compound.setByte(key, data) })
val FLOAT = nbtDataType<Float, NBTTagFloat>({ it.asFloat() }, { key, data, compound -> compound.setFloat(key, data) }) val BYTE_ARRAY = nbtDataType<ByteArray, NBTTagByteArray>({ it.bytes },
{ key, data, compound -> compound.setByteArray(key, data) })
val DOUBLE = nbtDataType<Double, NBTTagDouble>({ it.asDouble() },
{ key, data, compound -> compound.setDouble(key, data) })
val FLOAT =
nbtDataType<Float, NBTTagFloat>({ it.asFloat() }, { key, data, compound -> compound.setFloat(key, data) })
val INT = nbtDataType<Int, NBTTagInt>({ it.asInt() }, { key, data, compound -> compound.setInt(key, data) }) val INT = nbtDataType<Int, NBTTagInt>({ it.asInt() }, { key, data, compound -> compound.setInt(key, data) })
val INT_ARRAY = nbtDataType<IntArray, NBTTagIntArray>({ it.ints }, { key, data, compound -> compound.setIntArray(key, data) }) val INT_ARRAY = nbtDataType<IntArray, NBTTagIntArray>({ it.ints },
val LONG = nbtDataType<Long, NBTTagLong>({ it.asLong() }, { key, data, compound -> compound.setLong(key, data) }) { key, data, compound -> compound.setIntArray(key, data) })
val LONG_ARRAY = nbtDataType<LongArray, NBTTagLongArray>({ it.longs }, { key, data, compound -> compound.set(key, NBTTagLongArray(data)) }) val LONG =
val SHORT = nbtDataType<Short, NBTTagShort>({ it.asShort() }, { key, data, compound -> compound.setShort(key, data) }) nbtDataType<Long, NBTTagLong>({ it.asLong() }, { key, data, compound -> compound.setLong(key, data) })
val STRING = nbtDataType<String, NBTTagString>({ it.asString() }, { key, data, compound -> compound.setString(key, data) }) val LONG_ARRAY = nbtDataType<LongArray, NBTTagLongArray>({ it.longs },
{ key, data, compound -> compound.set(key, NBTTagLongArray(data)) })
val SHORT =
nbtDataType<Short, NBTTagShort>({ it.asShort() }, { key, data, compound -> compound.setShort(key, data) })
val STRING = nbtDataType<String, NBTTagString>({ it.asString() },
{ key, data, compound -> compound.setString(key, data) })
} }
@@ -32,15 +42,16 @@ interface NBTDataType<T> {
* @property E the NBT data type * @property E the NBT data type
*/ */
private inline fun <T, reified E> nbtDataType( private inline fun <T, reified E> nbtDataType(
crossinline decodeNMS: (E) -> T, crossinline decodeNMS: (E) -> T,
crossinline writeToCompound: (key: String, data: T, compound: NBTTagCompound) -> Unit crossinline writeToCompound: (key: String, data: T, compound: NBTTagCompound) -> Unit
): NBTDataType<T> { ): NBTDataType<T> {
return object : NBTDataType<T> { return object : NBTDataType<T> {
override fun decodeNMS(nbtBase: NBTBase) = if (nbtBase is E) decodeNMS.invoke(nbtBase) else null override fun decodeNMS(nbtBase: NBTBase) = if (nbtBase is E) decodeNMS.invoke(nbtBase) else null
override fun writeToCompound(key: String, data: T, compound: NBTTagCompound) = writeToCompound.invoke(key, data, compound) override fun writeToCompound(key: String, data: T, compound: NBTTagCompound) =
writeToCompound.invoke(key, data, compound)
} }

View File

@@ -26,9 +26,9 @@ fun Listener.unregister() = HandlerList.unregisterAll(this)
* @param executor handles incoming events * @param executor handles incoming events
*/ */
inline fun <reified T : Event> Listener.register( inline fun <reified T : Event> Listener.register(
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false, ignoreCancelled: Boolean = false,
noinline executor: (Listener, Event) -> Unit noinline executor: (Listener, Event) -> Unit
) { ) {
pluginManager.registerEvent(T::class.java, this, priority, executor, KSpigotMainInstance, ignoreCancelled) pluginManager.registerEvent(T::class.java, this, priority, executor, KSpigotMainInstance, ignoreCancelled)
} }
@@ -49,8 +49,8 @@ interface SingleListener<T : Event> : Listener {
* @param ignoreCancelled if manual cancellation should be ignored * @param ignoreCancelled if manual cancellation should be ignored
*/ */
inline fun <reified T : Event> SingleListener<T>.register( inline fun <reified T : Event> SingleListener<T>.register(
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false ignoreCancelled: Boolean = false
) { ) {
register<T>(priority, ignoreCancelled) { _, event -> register<T>(priority, ignoreCancelled) { _, event ->
(event as? T)?.let { this.onEvent(it) } (event as? T)?.let { this.onEvent(it) }
@@ -64,9 +64,9 @@ inline fun <reified T : Event> SingleListener<T>.register(
* @param onEvent the event callback * @param onEvent the event callback
*/ */
inline fun <reified T : Event> listen( inline fun <reified T : Event> listen(
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false, ignoreCancelled: Boolean = false,
crossinline onEvent: (T) -> Unit crossinline onEvent: (T) -> Unit
): SingleListener<T> { ): SingleListener<T> {
val listener = object : SingleListener<T> { val listener = object : SingleListener<T> {
override fun onEvent(event: T) = onEvent.invoke(event) override fun onEvent(event: T) = onEvent.invoke(event)

View File

@@ -6,27 +6,27 @@ import org.bukkit.command.CommandSender
import org.bukkit.plugin.Plugin import org.bukkit.plugin.Plugin
/** @see printColoredPrefix */ /** @see printColoredPrefix */
fun CommandSender.print(text: String, plugin: Plugin? = KSpigotMainInstance) fun CommandSender.print(text: String, plugin: Plugin? = KSpigotMainInstance) =
= printColoredPrefix(text, ChatColor.RESET, plugin?.name ?: "INFO", ChatColor.GRAY) printColoredPrefix(text, ChatColor.RESET, plugin?.name ?: "INFO", ChatColor.GRAY)
/** @see printColoredPrefix */ /** @see printColoredPrefix */
fun CommandSender.info(text: String, plugin: Plugin? = KSpigotMainInstance) fun CommandSender.info(text: String, plugin: Plugin? = KSpigotMainInstance) =
= printColoredPrefix(text, ChatColor.WHITE, plugin?.name ?: "INFO", ChatColor.DARK_AQUA) printColoredPrefix(text, ChatColor.WHITE, plugin?.name ?: "INFO", ChatColor.DARK_AQUA)
/** @see printColoredPrefix */ /** @see printColoredPrefix */
fun CommandSender.success(text: String, plugin: Plugin? = KSpigotMainInstance) fun CommandSender.success(text: String, plugin: Plugin? = KSpigotMainInstance) =
= printColoredPrefix(text, ChatColor.GREEN, plugin?.name ?: "SUCCESS", ChatColor.DARK_AQUA) printColoredPrefix(text, ChatColor.GREEN, plugin?.name ?: "SUCCESS", ChatColor.DARK_AQUA)
/** @see printColoredPrefix */ /** @see printColoredPrefix */
fun CommandSender.warn(text: String, plugin: Plugin? = KSpigotMainInstance) fun CommandSender.warn(text: String, plugin: Plugin? = KSpigotMainInstance) =
= printColoredPrefix(text, ChatColor.WHITE, plugin?.name?.plus(" - WARN") ?: "WARN", ChatColor.YELLOW) printColoredPrefix(text, ChatColor.WHITE, plugin?.name?.plus(" - WARN") ?: "WARN", ChatColor.YELLOW)
/** @see printColoredPrefix */ /** @see printColoredPrefix */
fun CommandSender.error(text: String, plugin: Plugin? = KSpigotMainInstance) fun CommandSender.error(text: String, plugin: Plugin? = KSpigotMainInstance) =
= printColoredPrefix(text, ChatColor.RED, plugin?.name?.plus(" - ERROR") ?: "ERROR", ChatColor.DARK_RED) printColoredPrefix(text, ChatColor.RED, plugin?.name?.plus(" - ERROR") ?: "ERROR", ChatColor.DARK_RED)
/** /**
* Sends the given message and adds the given prefix with the given color to it. * Sends the given message and adds the given prefix with the given color to it.
*/ */
fun CommandSender.printColoredPrefix(text: String, textColor: ChatColor, prefix: String, prefixColor: ChatColor) fun CommandSender.printColoredPrefix(text: String, textColor: ChatColor, prefix: String, prefixColor: ChatColor) =
= sendMessage("${prefixColor}[${prefix}]${textColor} $text") sendMessage("${prefixColor}[${prefix}]${textColor} $text")

View File

@@ -43,7 +43,7 @@ fun Damageable.kill() {
*/ */
fun LivingEntity.heal() { fun LivingEntity.heal() {
health = getAttribute(Attribute.GENERIC_MAX_HEALTH)?.value health = getAttribute(Attribute.GENERIC_MAX_HEALTH)?.value
?: throw NullPointerException("The entity does not have a max health value!") ?: throw NullPointerException("The entity does not have a max health value!")
} }
/** /**
@@ -110,7 +110,13 @@ fun Location.spawnCleanEntity(entityType: EntityType): Entity? {
* @param stay time in ticks for titles to stay * @param stay time in ticks for titles to stay
* @param fadeOut time in ticks for titles to fade out * @param fadeOut time in ticks for titles to fade out
*/ */
fun Player.title(mainText: String? = null, subText: String? = null, fadeIn: Int = 10, stay: Int = 70, fadeOut: Int = 20) { fun Player.title(
mainText: String? = null,
subText: String? = null,
fadeIn: Int = 10,
stay: Int = 70,
fadeOut: Int = 20
) {
sendTitle(mainText, subText, fadeIn, stay, fadeOut) sendTitle(mainText, subText, fadeIn, stay, fadeOut)
} }

View File

@@ -7,5 +7,6 @@ import org.bukkit.World
* Assumes that this Location has world data. * Assumes that this Location has world data.
* If not, an exception will be thrown. * If not, an exception will be thrown.
*/ */
val Location.worldOrException: World get() = world val Location.worldOrException: World
?: throw NullPointerException("The world of the location is null!") get() = world
?: throw NullPointerException("The world of the location is null!")

View File

@@ -10,10 +10,12 @@ import org.bukkit.inventory.ItemStack
* the result is equal to [Material.AIR]. * the result is equal to [Material.AIR].
*/ */
val PrepareItemCraftEvent.isCancelled: Boolean val PrepareItemCraftEvent.isCancelled: Boolean
get() = this.inventory.result?.type == Material.AIR get() = this.inventory.result?.type == Material.AIR
/** /**
* "Cancels" this event by * "Cancels" this event by
* setting the result to [Material.AIR]. * setting the result to [Material.AIR].
*/ */
fun PrepareItemCraftEvent.cancel() { this.inventory.result = ItemStack(Material.AIR) } fun PrepareItemCraftEvent.cancel() {
this.inventory.result = ItemStack(Material.AIR)
}

View File

@@ -20,16 +20,16 @@ class SimpleLocationPair(loc1: Location, loc2: Location) {
val maxSimpleLoc = SimpleLocation3D(max(loc1.x, loc2.x), max(loc1.y, loc2.y), max(loc1.z, loc2.z)) val maxSimpleLoc = SimpleLocation3D(max(loc1.x, loc2.x), max(loc1.y, loc2.y), max(loc1.z, loc2.z))
fun isInArea( fun isInArea(
loc: Location, loc: Location,
check3d: Boolean = true, check3d: Boolean = true,
tolerance: Int = 0 tolerance: Int = 0
): Boolean { ): Boolean {
// checking world // checking world
if (loc.world != world) return false if (loc.world != world) return false
return if ( return if (
// checking x // checking x
loc.x >= minSimpleLoc.x - tolerance && loc.x <= maxSimpleLoc.x + tolerance && loc.x >= minSimpleLoc.x - tolerance && loc.x <= maxSimpleLoc.x + tolerance &&
// checking z // checking z
loc.z >= minSimpleLoc.z - tolerance && loc.z <= maxSimpleLoc.z + tolerance loc.z >= minSimpleLoc.z - tolerance && loc.z <= maxSimpleLoc.z + tolerance
@@ -45,9 +45,10 @@ class SimpleLocationPair(loc1: Location, loc2: Location) {
val foundChunks = HashSet<SimpleChunkLocation>() val foundChunks = HashSet<SimpleChunkLocation>()
(minSimpleLoc.chunk.x until maxSimpleLoc.chunk.x + 1).forEach { curX -> (minSimpleLoc.chunk.x until maxSimpleLoc.chunk.x + 1).forEach { curX ->
(minSimpleLoc.chunk.z until maxSimpleLoc.chunk.z + 1).forEach { curZ -> (minSimpleLoc.chunk.z until maxSimpleLoc.chunk.z + 1).forEach { curZ ->
foundChunks += SimpleChunkLocation(curX, curZ) foundChunks += SimpleChunkLocation(curX, curZ)
} } }
}
return@lazy foundChunks return@lazy foundChunks
@@ -77,9 +78,9 @@ class LocationArea(loc1: Location, loc2: Location) {
val touchedChunks: Set<Chunk> get() = simpleLocationPair.touchedSimpleChunks.mapTo(HashSet()) { it.withWorld(world) } val touchedChunks: Set<Chunk> get() = simpleLocationPair.touchedSimpleChunks.mapTo(HashSet()) { it.withWorld(world) }
fun isInArea( fun isInArea(
loc: Location, loc: Location,
check3d: Boolean = true, check3d: Boolean = true,
tolerance: Int = 0 tolerance: Int = 0
) = simpleLocationPair.isInArea(loc, check3d, tolerance) ) = simpleLocationPair.isInArea(loc, check3d, tolerance)
} }

View File

@@ -12,10 +12,12 @@ import org.bukkit.util.Vector
// INCREASE // INCREASE
// all // all
infix fun Location.increase(distance: Number) = add(distance, distance, distance) infix fun Location.increase(distance: Number) = add(distance, distance, distance)
// single // single
infix fun Location.increaseX(distance: Number) = add(distance, 0.0, 0.0) infix fun Location.increaseX(distance: Number) = add(distance, 0.0, 0.0)
infix fun Location.increaseY(distance: Number) = add(0.0, distance, 0.0) infix fun Location.increaseY(distance: Number) = add(0.0, distance, 0.0)
infix fun Location.increaseZ(distance: Number) = add(0.0, 0.0, distance) infix fun Location.increaseZ(distance: Number) = add(0.0, 0.0, distance)
// pair // pair
infix fun Location.increaseXY(distance: Number) = add(distance, distance, 0.0) infix fun Location.increaseXY(distance: Number) = add(distance, distance, 0.0)
infix fun Location.increaseYZ(distance: Number) = add(0.0, distance, distance) infix fun Location.increaseYZ(distance: Number) = add(0.0, distance, distance)
@@ -24,10 +26,12 @@ infix fun Location.increaseXZ(distance: Number) = add(distance, 0.0, distance)
// REDUCE // REDUCE
// all // all
infix fun Location.reduce(distance: Number) = substract(distance, distance, distance) infix fun Location.reduce(distance: Number) = substract(distance, distance, distance)
// single // single
infix fun Location.reduceX(distance: Number) = substract(distance, 0.0, 0.0) infix fun Location.reduceX(distance: Number) = substract(distance, 0.0, 0.0)
infix fun Location.reduceY(distance: Number) = substract(0.0, distance, 0.0) infix fun Location.reduceY(distance: Number) = substract(0.0, distance, 0.0)
infix fun Location.reduceZ(distance: Number) = substract(0.0, 0.0, distance) infix fun Location.reduceZ(distance: Number) = substract(0.0, 0.0, distance)
// pair // pair
infix fun Location.reduceXY(distance: Number) = substract(distance, distance, 0.0) infix fun Location.reduceXY(distance: Number) = substract(distance, distance, 0.0)
infix fun Location.reduceYZ(distance: Number) = substract(0.0, distance, distance) infix fun Location.reduceYZ(distance: Number) = substract(0.0, distance, distance)
@@ -50,13 +54,32 @@ operator fun Location.plus(loc: Location) = clone().add(loc)
operator fun Location.minus(loc: Location) = clone().subtract(loc) operator fun Location.minus(loc: Location) = clone().subtract(loc)
operator fun Location.plus(loc: SimpleLocation3D) = clone().add(loc.x, loc.y, loc.z) operator fun Location.plus(loc: SimpleLocation3D) = clone().add(loc.x, loc.y, loc.z)
operator fun Location.minus(loc: SimpleLocation3D) = clone().subtract(loc.x, loc.y, loc.z) operator fun Location.minus(loc: SimpleLocation3D) = clone().subtract(loc.x, loc.y, loc.z)
// mutable // mutable
operator fun Location.plusAssign(vec: Vector) { add(vec) } operator fun Location.plusAssign(vec: Vector) {
operator fun Location.minusAssign(vec: Vector) { subtract(vec) } add(vec)
operator fun Location.plusAssign(loc: Location) { add(loc) } }
operator fun Location.minusAssign(loc: Location) { subtract(loc) }
operator fun Location.plusAssign(loc: SimpleLocation3D) { add(loc.x, loc.y, loc.z) } operator fun Location.minusAssign(vec: Vector) {
operator fun Location.minusAssign(loc: SimpleLocation3D) { subtract(loc.x, loc.y, loc.z) } subtract(vec)
}
operator fun Location.plusAssign(loc: Location) {
add(loc)
}
operator fun Location.minusAssign(loc: Location) {
subtract(loc)
}
operator fun Location.plusAssign(loc: SimpleLocation3D) {
add(loc.x, loc.y, loc.z)
}
operator fun Location.minusAssign(loc: SimpleLocation3D) {
subtract(loc.x, loc.y, loc.z)
}
// mutable with return // mutable with return
infix fun Location.increase(vec: Vector) = add(vec) infix fun Location.increase(vec: Vector) = add(vec)
infix fun Location.reduce(vec: Vector) = subtract(vec) infix fun Location.reduce(vec: Vector) = subtract(vec)
@@ -86,11 +109,24 @@ operator fun Vector.plus(vec: Vector) = clone().add(vec)
operator fun Vector.minus(vec: Vector) = clone().subtract(vec) operator fun Vector.minus(vec: Vector) = clone().subtract(vec)
operator fun Vector.times(vec: Vector) = clone().multiply(vec) operator fun Vector.times(vec: Vector) = clone().multiply(vec)
operator fun Vector.times(num: Number) = clone().multiply(num.toDouble()) operator fun Vector.times(num: Number) = clone().multiply(num.toDouble())
// mutable // mutable
operator fun Vector.plusAssign(vec: Vector) { add(vec) } operator fun Vector.plusAssign(vec: Vector) {
operator fun Vector.minusAssign(vec: Vector) { subtract(vec) } add(vec)
operator fun Vector.timesAssign(vec: Vector) { multiply(vec) } }
operator fun Vector.timesAssign(num: Number) { multiply(num.toDouble()) }
operator fun Vector.minusAssign(vec: Vector) {
subtract(vec)
}
operator fun Vector.timesAssign(vec: Vector) {
multiply(vec)
}
operator fun Vector.timesAssign(num: Number) {
multiply(num.toDouble())
}
// mutable with return // mutable with return
infix fun Vector.increase(vec: Vector) = add(vec) infix fun Vector.increase(vec: Vector) = add(vec)
infix fun Vector.reduce(vec: Vector) = subtract(vec) infix fun Vector.reduce(vec: Vector) = subtract(vec)

View File

@@ -11,14 +11,14 @@ class GamePhaseSystem(vararg gamePhases: GamePhase) {
} }
fun buildCounterMessageCallback( fun buildCounterMessageCallback(
beforeTime: String? = null, beforeTime: String? = null,
afterTime: String? = null, afterTime: String? = null,
hourPlural: String = "h", hourPlural: String = "h",
minutePlural: String = "m", minutePlural: String = "m",
secondPlural: String = "s", secondPlural: String = "s",
hourSingular: String = hourPlural, hourSingular: String = hourPlural,
minuteSingular: String = minutePlural, minuteSingular: String = minutePlural,
secondSingular: String = secondPlural secondSingular: String = secondPlural
): (Long) -> String = { curSeconds -> ): (Long) -> String = { curSeconds ->
StringBuilder().apply { StringBuilder().apply {
@@ -50,24 +50,24 @@ fun buildCounterMessageCallback(
} }
class GamePhase( class GamePhase(
val length: Long, val length: Long,
val start: (() -> Unit)?, val start: (() -> Unit)?,
val end: (() -> Unit)?, val end: (() -> Unit)?,
val counterMessage: ((secondsLeft: Long) -> String)? val counterMessage: ((secondsLeft: Long) -> String)?
) { ) {
fun startIt(phaseQueue: MutableList<GamePhase>) { fun startIt(phaseQueue: MutableList<GamePhase>) {
start?.invoke() start?.invoke()
task( task(
period = 20, period = 20,
howOften = (length / 20) + 1, howOften = (length / 20) + 1,
endCallback = { endCallback = {
end?.invoke() end?.invoke()
if (phaseQueue.isNotEmpty()) if (phaseQueue.isNotEmpty())
phaseQueue.removeAt(0).startIt(phaseQueue) phaseQueue.removeAt(0).startIt(phaseQueue)
} }
) { ) {
if (counterMessage != null) { if (counterMessage != null) {
@@ -80,8 +80,9 @@ class GamePhase(
} }
} }
private val Long.isCounterValue: Boolean get() = when (this) { private val Long.isCounterValue: Boolean
1L, 2L, 3L, 4L, 5L, 10L, 15L, 20L, 30L -> true get() = when (this) {
0L -> false 1L, 2L, 3L, 4L, 5L, 10L, 15L, 20L, 30L -> true
else -> this % 60 == 0L 0L -> false
} else -> this % 60 == 0L
}

View File

@@ -64,8 +64,8 @@ object InventoryGUIHolder : AutoCloseable {
// EVENT // EVENT
class InventoryGUIClickEvent<T : ForInventory>( class InventoryGUIClickEvent<T : ForInventory>(
val bukkitEvent: InventoryClickEvent, val bukkitEvent: InventoryClickEvent,
val gui: InventoryGUI<T> val gui: InventoryGUI<T>
) )
/* /*
@@ -84,16 +84,22 @@ class InventoryGUIData<T : ForInventory>(
) )
abstract class InventoryGUI<T : ForInventory>( abstract class InventoryGUI<T : ForInventory>(
val data: InventoryGUIData<T> val data: InventoryGUIData<T>
) { ) {
var currentPageInt: Int = DEFAULT_PAGE; protected set var currentPageInt: Int = DEFAULT_PAGE; protected set
val currentPage get() = getPage(currentPageInt) val currentPage
get() = getPage(currentPageInt)
?: throw IllegalStateException("The currentPageInt has no associated page!") ?: throw IllegalStateException("The currentPageInt has no associated page!")
internal abstract val bukkitInventory: Inventory internal abstract val bukkitInventory: Inventory
internal abstract fun loadPageUnsafe(page: InventoryGUIPage<*>, offsetHorizontally: Int = 0, offsetVertically: Int = 0) internal abstract fun loadPageUnsafe(
page: InventoryGUIPage<*>,
offsetHorizontally: Int = 0,
offsetVertically: Int = 0
)
internal abstract fun loadPageUnsafe(page: Int, offsetHorizontally: Int = 0, offsetVertically: Int = 0) internal abstract fun loadPageUnsafe(page: Int, offsetHorizontally: Int = 0, offsetVertically: Int = 0)
/** /**
@@ -135,12 +141,14 @@ abstract class InventoryGUI<T : ForInventory>(
// Inventory GUI implementations // Inventory GUI implementations
class InventoryGUIShared<T : ForInventory>( class InventoryGUIShared<T : ForInventory>(
inventoryGUIData: InventoryGUIData<T> inventoryGUIData: InventoryGUIData<T>
) : InventoryGUI<T>(inventoryGUIData) { ) : InventoryGUI<T>(inventoryGUIData) {
override val bukkitInventory = data.inventoryType.createBukkitInv(null, data.title) override val bukkitInventory = data.inventoryType.createBukkitInv(null, data.title)
init { loadPageUnsafe(DEFAULT_PAGE) } init {
loadPageUnsafe(DEFAULT_PAGE)
}
override fun isThisInv(inventory: Inventory) = inventory == bukkitInventory override fun isThisInv(inventory: Inventory) = inventory == bukkitInventory

View File

@@ -6,12 +6,12 @@ import net.axay.kspigot.inventory.elements.*
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
fun <T : ForInventory> inventoryGUI( fun <T : ForInventory> inventoryGUI(
type: InventoryType<T>, type: InventoryType<T>,
builder: InventoryGUIBuilder<T>.() -> Unit, builder: InventoryGUIBuilder<T>.() -> Unit,
) = InventoryGUIBuilder(type).apply(builder).build() ) = InventoryGUIBuilder(type).apply(builder).build()
class InventoryGUIBuilder<T : ForInventory>( class InventoryGUIBuilder<T : ForInventory>(
val type: InventoryType<T> val type: InventoryType<T>
) { ) {
var title: String = "" var title: String = ""
@@ -37,14 +37,14 @@ class InventoryGUIBuilder<T : ForInventory>(
} }
internal fun build() = InventoryGUIShared( internal fun build() = InventoryGUIShared(
InventoryGUIData(type, title, guiSlots, transitionTo, transitionFrom, onClickElement) InventoryGUIData(type, title, guiSlots, transitionTo, transitionFrom, onClickElement)
).apply { register() } ).apply { register() }
} }
class InventoryGUIPageBuilder<T : ForInventory>( class InventoryGUIPageBuilder<T : ForInventory>(
val type: InventoryType<T>, val type: InventoryType<T>,
val page: Int val page: Int
) { ) {
private val guiSlots = HashMap<Int, InventoryGUISlot<T>>() private val guiSlots = HashMap<Int, InventoryGUISlot<T>>()
@@ -59,74 +59,96 @@ class InventoryGUIPageBuilder<T : ForInventory>(
* actions. If clicked, the specified [onClick] * actions. If clicked, the specified [onClick]
* function is invoked. * function is invoked.
*/ */
fun button(slots: InventorySlotCompound<T>, itemStack: ItemStack, onClick: (InventoryGUIClickEvent<T>) -> Unit) fun button(slots: InventorySlotCompound<T>, itemStack: ItemStack, onClick: (InventoryGUIClickEvent<T>) -> Unit) =
= defineSlots(slots, InventoryGUIButton(InventoryGUIElementData(itemStack), onClick)) defineSlots(slots, InventoryGUIButton(InventoryGUIElementData(itemStack), onClick))
/** /**
* An item protected from any player actions. * An item protected from any player actions.
* This is not a button. * This is not a button.
*/ */
fun placeholder(slots: InventorySlotCompound<T>, itemStack: ItemStack) fun placeholder(slots: InventorySlotCompound<T>, itemStack: ItemStack) =
= defineSlots(slots, InventoryGUIPlaceholder(InventoryGUIElementData(itemStack))) defineSlots(slots, InventoryGUIPlaceholder(InventoryGUIElementData(itemStack)))
/** /**
* A free slot does not block any player actions. * A free slot does not block any player actions.
* The player can put items in this slot or take * The player can put items in this slot or take
* items out of it. * items out of it.
*/ */
fun freeSlot(slots: InventorySlotCompound<T>) fun freeSlot(slots: InventorySlotCompound<T>) = defineSlots(slots, InventoryGUIFreeSlot())
= defineSlots(slots, InventoryGUIFreeSlot())
/** /**
* This is a button which loads the specified * This is a button which loads the specified
* [toPage] if clicked. * [toPage] if clicked.
*/ */
fun pageChanger(slots: InventorySlotCompound<T>, itemStack: ItemStack, toPage: Int, onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null) fun pageChanger(
= defineSlots(slots, InventoryGUIButtonPageChange( slots: InventorySlotCompound<T>,
itemStack: ItemStack,
toPage: Int,
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null
) = defineSlots(
slots, InventoryGUIButtonPageChange(
InventoryGUIElementData(itemStack), InventoryGUIElementData(itemStack),
InventoryGUIPageChangeCalculator.InventoryGUIConsistentPageCalculator(toPage), InventoryGUIPageChangeCalculator.InventoryGUIConsistentPageCalculator(toPage),
onChange onChange
)) )
)
/** /**
* This button always tries to find the previous * This button always tries to find the previous
* page if clicked, and if a previous page * page if clicked, and if a previous page
* exists it is loaded. * exists it is loaded.
*/ */
fun previousPage(slots: InventorySlotCompound<T>, itemStack: ItemStack, onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null) fun previousPage(
= defineSlots(slots, InventoryGUIButtonPageChange( slots: InventorySlotCompound<T>,
itemStack: ItemStack,
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null
) = defineSlots(
slots, InventoryGUIButtonPageChange(
InventoryGUIElementData(itemStack), InventoryGUIElementData(itemStack),
InventoryGUIPageChangeCalculator.InventoryGUIPreviousPageCalculator, InventoryGUIPageChangeCalculator.InventoryGUIPreviousPageCalculator,
onChange onChange
)) )
)
/** /**
* This button always tries to find the next * This button always tries to find the next
* page if clicked, and if a next page * page if clicked, and if a next page
* exists it is loaded. * exists it is loaded.
*/ */
fun nextPage(slots: InventorySlotCompound<T>, itemStack: ItemStack, onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null) fun nextPage(
= defineSlots(slots, InventoryGUIButtonPageChange( slots: InventorySlotCompound<T>,
itemStack: ItemStack,
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null
) = defineSlots(
slots, InventoryGUIButtonPageChange(
InventoryGUIElementData(itemStack), InventoryGUIElementData(itemStack),
InventoryGUIPageChangeCalculator.InventoryGUINextPageCalculator, InventoryGUIPageChangeCalculator.InventoryGUINextPageCalculator,
onChange onChange
)) )
)
/** /**
* By pressing this button, the player switches to another * By pressing this button, the player switches to another
* InventoryGUI. The transition effect is applied. * InventoryGUI. The transition effect is applied.
*/ */
fun changeGUI(slots: InventorySlotCompound<T>, itemStack: ItemStack, newGUI: () -> InventoryGUI<*>, newPage: Int? = null, onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null) fun changeGUI(
= defineSlots(slots, InventoryGUIButtonInventoryChange( slots: InventorySlotCompound<T>,
itemStack: ItemStack,
newGUI: () -> InventoryGUI<*>,
newPage: Int? = null,
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null
) = defineSlots(
slots, InventoryGUIButtonInventoryChange(
InventoryGUIElementData(itemStack), InventoryGUIElementData(itemStack),
newGUI, newGUI,
newPage, newPage,
onChange onChange
)) )
)
private fun defineSlots(slots: InventorySlotCompound<T>, element: InventoryGUISlot<T>) private fun defineSlots(slots: InventorySlotCompound<T>, element: InventoryGUISlot<T>) =
= slots.withInvType(type).forEach { curSlot -> slots.withInvType(type).forEach { curSlot ->
curSlot.realSlotIn(type.dimensions)?.let { guiSlots[it] = element } curSlot.realSlotIn(type.dimensions)?.let { guiSlots[it] = element }
} }
} }

View File

@@ -9,11 +9,11 @@ abstract class InventoryGUISlot<T : ForInventory> {
// ELEMENT // ELEMENT
class InventoryGUIElementData( class InventoryGUIElementData(
val itemStack: ItemStack val itemStack: ItemStack
) )
abstract class InventoryGUIElement<T : ForInventory>( abstract class InventoryGUIElement<T : ForInventory>(
val inventoryGUIElementData: InventoryGUIElementData val inventoryGUIElementData: InventoryGUIElementData
) : InventoryGUISlot<T>() { ) : InventoryGUISlot<T>() {
final override fun onClick(clickEvent: InventoryGUIClickEvent<T>) { final override fun onClick(clickEvent: InventoryGUIClickEvent<T>) {

View File

@@ -7,13 +7,13 @@ abstract class InventoryGUIPageChangeCalculator {
abstract fun calculateNewPage(currentPage: Int, pages: Collection<Int>): Int? abstract fun calculateNewPage(currentPage: Int, pages: Collection<Int>): Int?
object InventoryGUIPreviousPageCalculator : InventoryGUIPageChangeCalculator() { object InventoryGUIPreviousPageCalculator : InventoryGUIPageChangeCalculator() {
override fun calculateNewPage(currentPage: Int, pages: Collection<Int>) override fun calculateNewPage(currentPage: Int, pages: Collection<Int>) =
= pages.sortedDescending().find { it < currentPage } pages.sortedDescending().find { it < currentPage }
} }
object InventoryGUINextPageCalculator : InventoryGUIPageChangeCalculator() { object InventoryGUINextPageCalculator : InventoryGUIPageChangeCalculator() {
override fun calculateNewPage(currentPage: Int, pages: Collection<Int>) override fun calculateNewPage(currentPage: Int, pages: Collection<Int>) =
= pages.sorted().find { it > currentPage } pages.sorted().find { it > currentPage }
} }
class InventoryGUIConsistentPageCalculator(private val toPage: Int) : InventoryGUIPageChangeCalculator() { class InventoryGUIConsistentPageCalculator(private val toPage: Int) : InventoryGUIPageChangeCalculator() {
@@ -119,19 +119,19 @@ internal fun InventoryGUI<*>.changeGUI(
) = changePage(effect.effect, fromPage, toPage) ) = changePage(effect.effect, fromPage, toPage)
private inline fun changePageEffect( private inline fun changePageEffect(
fromPage: Int, fromPage: Int,
toPage: Int, toPage: Int,
doFor: Int, doFor: Int,
crossinline effect: (currentOffset: Int, ifInverted: Boolean) -> Unit, crossinline effect: (currentOffset: Int, ifInverted: Boolean) -> Unit,
) { ) {
val ifInverted = fromPage >= toPage val ifInverted = fromPage >= toPage
var currentOffset = 1 var currentOffset = 1
task( task(
sync = true, sync = true,
period = 1, period = 1,
howOften = doFor.toLong() howOften = doFor.toLong()
) { ) {
effect.invoke(currentOffset, ifInverted) effect.invoke(currentOffset, ifInverted)

View File

@@ -10,10 +10,11 @@ data class InventoryDimensions(val width: Int, val heigth: Int) {
val invSlots by lazy { val invSlots by lazy {
ArrayList<InventorySlot>().apply { ArrayList<InventorySlot>().apply {
(1 .. heigth).forEach { row -> (1..heigth).forEach { row ->
(1 .. width).forEach { slotInRow -> (1..width).forEach { slotInRow ->
this += InventorySlot(row, slotInRow) this += InventorySlot(row, slotInRow)
} } }
}
} }
} }
@@ -40,8 +41,8 @@ data class InventoryDimensions(val width: Int, val heigth: Int) {
data class InventorySlot(val row: Int, val slotInRow: Int) : Comparable<InventorySlot> { data class InventorySlot(val row: Int, val slotInRow: Int) : Comparable<InventorySlot> {
companion object { companion object {
fun fromRealSlot(realSlot: Int, dimensions: InventoryDimensions) fun fromRealSlot(realSlot: Int, dimensions: InventoryDimensions) =
= dimensions.invSlotsWithRealSlots.toList().find { it.second == realSlot }?.first dimensions.invSlotsWithRealSlots.toList().find { it.second == realSlot }?.first
} }
override fun compareTo(other: InventorySlot) = when { override fun compareTo(other: InventorySlot) = when {
@@ -61,12 +62,12 @@ data class InventorySlot(val row: Int, val slotInRow: Int) : Comparable<Inventor
return ((rowsUnder * inventoryDimensions.width) + slotInRow) - 1 return ((rowsUnder * inventoryDimensions.width) + slotInRow) - 1
} }
fun isInDimension(inventoryDimensions: InventoryDimensions) fun isInDimension(inventoryDimensions: InventoryDimensions) =
= (1 .. inventoryDimensions.width).contains(slotInRow) && (1 .. inventoryDimensions.heigth).contains(row) (1..inventoryDimensions.width).contains(slotInRow) && (1..inventoryDimensions.heigth).contains(row)
fun add(offsetHorizontally: Int, offsetVertically: Int) = InventorySlot( fun add(offsetHorizontally: Int, offsetVertically: Int) = InventorySlot(
row + offsetVertically, row + offsetVertically,
slotInRow + offsetHorizontally slotInRow + offsetHorizontally
) )
} }
@@ -75,13 +76,13 @@ interface InventorySlotCompound<out T : ForInventory> {
fun withInvType(invType: InventoryType<T>): Collection<InventorySlot> fun withInvType(invType: InventoryType<T>): Collection<InventorySlot>
fun realSlotsWithInvType(invType: InventoryType<T>) fun realSlotsWithInvType(invType: InventoryType<T>) =
= withInvType(invType).mapNotNull { it.realSlotIn(invType.dimensions) } withInvType(invType).mapNotNull { it.realSlotIn(invType.dimensions) }
} }
open class SingleInventorySlot<T : ForInventory> internal constructor( open class SingleInventorySlot<T : ForInventory> internal constructor(
val inventorySlot: InventorySlot val inventorySlot: InventorySlot
) : InventorySlotCompound<T> { ) : InventorySlotCompound<T> {
constructor(row: Int, slotInRow: Int) : this(InventorySlot(row, slotInRow)) constructor(row: Int, slotInRow: Int) : this(InventorySlot(row, slotInRow))
@@ -99,10 +100,10 @@ internal enum class InventorySlotRangeType {
class InventorySlotRange<out T : ForInventory> internal constructor( class InventorySlotRange<out T : ForInventory> internal constructor(
startSlot: SingleInventorySlot<out T>, startSlot: SingleInventorySlot<out T>,
endSlot: SingleInventorySlot<out T>, endSlot: SingleInventorySlot<out T>,
private val type: InventorySlotRangeType private val type: InventorySlotRangeType
) : InventorySlotCompound<T>, ClosedRange<InventorySlot> { ) : InventorySlotCompound<T>, ClosedRange<InventorySlot> {
@@ -115,40 +116,39 @@ class InventorySlotRange<out T : ForInventory> internal constructor(
endInclusive = minMaxPair.max endInclusive = minMaxPair.max
} }
override fun withInvType(invType: InventoryType<T>) override fun withInvType(invType: InventoryType<T>) = LinkedHashSet<InventorySlot>().apply {
= LinkedHashSet<InventorySlot>().apply { when (type) {
when (type) {
InventorySlotRangeType.RECTANGLE -> {
// all possible combinations between the two slots
// -> form a rectangle
for (row in start.row .. endInclusive.row)
for (slotInRow in start.slotInRow .. endInclusive.slotInRow)
this += InventorySlot(row, slotInRow)
}
InventorySlotRangeType.LINEAR -> {
if (endInclusive.row > start.row) {
// from start --->| to end of row
for (slotInRow in start.slotInRow .. invType.dimensions.width)
this += InventorySlot(start.row, slotInRow)
// all rows in between
if (endInclusive.row > start.row + 1)
for (row in start.row + 1 until endInclusive.row)
for (slotInRow in 1 .. invType.dimensions.width)
this += InventorySlot(row, slotInRow)
// from start of row |----> to endInclusive
for (slotInRow in 1 .. endInclusive.slotInRow)
this += InventorySlot(endInclusive.row, slotInRow)
} else if (endInclusive.row == start.row) {
// from start ---> to endInclusive in the same row
for (slotInRow in start.slotInRow .. endInclusive.slotInRow)
this += InventorySlot(start.row, slotInRow)
}
}
InventorySlotRangeType.RECTANGLE -> {
// all possible combinations between the two slots
// -> form a rectangle
for (row in start.row..endInclusive.row)
for (slotInRow in start.slotInRow..endInclusive.slotInRow)
this += InventorySlot(row, slotInRow)
} }
InventorySlotRangeType.LINEAR -> {
if (endInclusive.row > start.row) {
// from start --->| to end of row
for (slotInRow in start.slotInRow..invType.dimensions.width)
this += InventorySlot(start.row, slotInRow)
// all rows in between
if (endInclusive.row > start.row + 1)
for (row in start.row + 1 until endInclusive.row)
for (slotInRow in 1..invType.dimensions.width)
this += InventorySlot(row, slotInRow)
// from start of row |----> to endInclusive
for (slotInRow in 1..endInclusive.slotInRow)
this += InventorySlot(endInclusive.row, slotInRow)
} else if (endInclusive.row == start.row) {
// from start ---> to endInclusive in the same row
for (slotInRow in start.slotInRow..endInclusive.slotInRow)
this += InventorySlot(start.row, slotInRow)
}
}
} }
}
} }
@@ -156,40 +156,40 @@ class InventorySlotRange<out T : ForInventory> internal constructor(
* This range contains all slots having an index between * This range contains all slots having an index between
* the indeces of the two given slots. * the indeces of the two given slots.
*/ */
infix fun <T : ForInventory> SingleInventorySlot<out T>.linTo(slot: SingleInventorySlot<out T>) infix fun <T : ForInventory> SingleInventorySlot<out T>.linTo(slot: SingleInventorySlot<out T>) =
= InventorySlotRange(this, slot, InventorySlotRangeType.LINEAR) InventorySlotRange(this, slot, InventorySlotRangeType.LINEAR)
/** /**
* This range contains all slots inside of a thought rectangle * This range contains all slots inside of a thought rectangle
* with the two given slots as two opposite corners of the rectangle. * with the two given slots as two opposite corners of the rectangle.
*/ */
infix fun <T : ForInventory> SingleInventorySlot<out T>.rectTo(slot: SingleInventorySlot<out T>) infix fun <T : ForInventory> SingleInventorySlot<out T>.rectTo(slot: SingleInventorySlot<out T>) =
= InventorySlotRange(this, slot, InventorySlotRangeType.RECTANGLE) InventorySlotRange(this, slot, InventorySlotRangeType.RECTANGLE)
class InventoryRowSlots<T : ForInventory> internal constructor( class InventoryRowSlots<T : ForInventory> internal constructor(
val row: Int val row: Int
) : InventorySlotCompound<T> { ) : InventorySlotCompound<T> {
override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().apply { override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().apply {
for (slotInRow in 1 .. invType.dimensions.width) for (slotInRow in 1..invType.dimensions.width)
this += InventorySlot(row, slotInRow) this += InventorySlot(row, slotInRow)
} }
} }
class InventoryColumnSlots<T : ForInventory> internal constructor( class InventoryColumnSlots<T : ForInventory> internal constructor(
val column: Int val column: Int
) : InventorySlotCompound<T> { ) : InventorySlotCompound<T> {
override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().apply { override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().apply {
for (row in 1 .. invType.dimensions.heigth) for (row in 1..invType.dimensions.heigth)
this += InventorySlot(row, column) this += InventorySlot(row, column)
} }
} }
class InventoryBorderSlots<T : ForInventory> internal constructor( class InventoryBorderSlots<T : ForInventory> internal constructor(
val padding: Int val padding: Int
) : InventorySlotCompound<T> { ) : InventorySlotCompound<T> {
override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().apply { override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().apply {
@@ -197,7 +197,7 @@ class InventoryBorderSlots<T : ForInventory> internal constructor(
val dimensions = invType.dimensions val dimensions = invType.dimensions
for (currentPadding in 0 until padding) { for (currentPadding in 0 until padding) {
for (slotInRow in 1 + currentPadding .. dimensions.width - currentPadding) { for (slotInRow in 1 + currentPadding..dimensions.width - currentPadding) {
this += InventorySlot(1, slotInRow) this += InventorySlot(1, slotInRow)
this += InventorySlot(dimensions.heigth, slotInRow) this += InventorySlot(dimensions.heigth, slotInRow)
} }
@@ -212,11 +212,11 @@ class InventoryBorderSlots<T : ForInventory> internal constructor(
} }
class InventoryCornerSlots<T : ForInventory> internal constructor( class InventoryCornerSlots<T : ForInventory> internal constructor(
val ifBottomLeft: Boolean = false, val ifBottomLeft: Boolean = false,
val ifBottomRight: Boolean = false, val ifBottomRight: Boolean = false,
val ifTopLeft: Boolean = false, val ifTopLeft: Boolean = false,
val ifTopRight: Boolean = false val ifTopRight: Boolean = false
) : InventorySlotCompound<T> { ) : InventorySlotCompound<T> {
override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().apply { override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().apply {
@@ -247,20 +247,28 @@ interface ForColumnNine : ForInventoryWidthNine
// ROWS // ROWS
interface ForRowOne : ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine interface ForRowOne : ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine, ForInventoryFourByNine,
interface ForRowTwo : ForInventoryTwoByNine, ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine ForInventoryFiveByNine, ForInventorySixByNine
interface ForRowTwo : ForInventoryTwoByNine, ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine,
ForInventorySixByNine
interface ForRowThree : ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine interface ForRowThree : ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine
interface ForRowFour : ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine interface ForRowFour : ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine
interface ForRowFive : ForInventoryFiveByNine, ForInventorySixByNine interface ForRowFive : ForInventoryFiveByNine, ForInventorySixByNine
interface ForRowSix : ForInventorySixByNine interface ForRowSix : ForInventorySixByNine
// EDGE CASES: // EDGE CASES:
// ROW ONE // ROW ONE
interface ForRowOneSlotOneToThree : ForRowOne, ForInventoryOneByFive, ForInventoryThreeByThree interface ForRowOneSlotOneToThree : ForRowOne, ForInventoryOneByFive, ForInventoryThreeByThree
interface ForRowOneSlotFourToFive : ForRowOne, ForInventoryOneByFive interface ForRowOneSlotFourToFive : ForRowOne, ForInventoryOneByFive
// ROW TWO // ROW TWO
interface ForRowTwoSlotOneToThree : ForRowTwo, ForInventoryThreeByThree interface ForRowTwoSlotOneToThree : ForRowTwo, ForInventoryThreeByThree
// ROW THREE // ROW THREE
interface ForRowThreeSlotOneToThree : ForRowThree, ForInventoryThreeByThree interface ForRowThreeSlotOneToThree : ForRowThree, ForInventoryThreeByThree
// COMPLETE ROWS (including the edge cases) // COMPLETE ROWS (including the edge cases)
interface ForCompleteRowOne : ForRowOne, ForRowOneSlotOneToThree, ForRowOneSlotFourToFive interface ForCompleteRowOne : ForRowOne, ForRowOneSlotOneToThree, ForRowOneSlotFourToFive
interface ForCompleteRowTwo : ForRowTwo, ForRowTwoSlotOneToThree interface ForCompleteRowTwo : ForRowTwo, ForRowTwoSlotOneToThree
@@ -278,6 +286,7 @@ object Slots {
val RowOneSlotSeven = SingleInventorySlot<ForRowOne>(1, 7) val RowOneSlotSeven = SingleInventorySlot<ForRowOne>(1, 7)
val RowOneSlotEight = SingleInventorySlot<ForRowOne>(1, 8) val RowOneSlotEight = SingleInventorySlot<ForRowOne>(1, 8)
val RowOneSlotNine = SingleInventorySlot<ForRowOne>(1, 9) val RowOneSlotNine = SingleInventorySlot<ForRowOne>(1, 9)
// ROW TWO // ROW TWO
val RowTwoSlotOne = SingleInventorySlot<ForRowTwoSlotOneToThree>(2, 1) val RowTwoSlotOne = SingleInventorySlot<ForRowTwoSlotOneToThree>(2, 1)
val RowTwoSlotTwo = SingleInventorySlot<ForRowTwoSlotOneToThree>(2, 2) val RowTwoSlotTwo = SingleInventorySlot<ForRowTwoSlotOneToThree>(2, 2)
@@ -288,6 +297,7 @@ object Slots {
val RowTwoSlotSeven = SingleInventorySlot<ForRowTwo>(2, 7) val RowTwoSlotSeven = SingleInventorySlot<ForRowTwo>(2, 7)
val RowTwoSlotEight = SingleInventorySlot<ForRowTwo>(2, 8) val RowTwoSlotEight = SingleInventorySlot<ForRowTwo>(2, 8)
val RowTwoSlotNine = SingleInventorySlot<ForRowTwo>(2, 9) val RowTwoSlotNine = SingleInventorySlot<ForRowTwo>(2, 9)
// ROW THREE // ROW THREE
val RowThreeSlotOne = SingleInventorySlot<ForRowThreeSlotOneToThree>(3, 1) val RowThreeSlotOne = SingleInventorySlot<ForRowThreeSlotOneToThree>(3, 1)
val RowThreeSlotTwo = SingleInventorySlot<ForRowThreeSlotOneToThree>(3, 2) val RowThreeSlotTwo = SingleInventorySlot<ForRowThreeSlotOneToThree>(3, 2)
@@ -298,6 +308,7 @@ object Slots {
val RowThreeSlotSeven = SingleInventorySlot<ForRowThree>(3, 7) val RowThreeSlotSeven = SingleInventorySlot<ForRowThree>(3, 7)
val RowThreeSlotEight = SingleInventorySlot<ForRowThree>(3, 8) val RowThreeSlotEight = SingleInventorySlot<ForRowThree>(3, 8)
val RowThreeSlotNine = SingleInventorySlot<ForRowThree>(3, 9) val RowThreeSlotNine = SingleInventorySlot<ForRowThree>(3, 9)
// ROW FOUR // ROW FOUR
val RowFourSlotOne = SingleInventorySlot<ForRowFour>(4, 1) val RowFourSlotOne = SingleInventorySlot<ForRowFour>(4, 1)
val RowFourSlotTwo = SingleInventorySlot<ForRowFour>(4, 2) val RowFourSlotTwo = SingleInventorySlot<ForRowFour>(4, 2)
@@ -308,6 +319,7 @@ object Slots {
val RowFourSlotSeven = SingleInventorySlot<ForRowFour>(4, 7) val RowFourSlotSeven = SingleInventorySlot<ForRowFour>(4, 7)
val RowFourSlotEight = SingleInventorySlot<ForRowFour>(4, 8) val RowFourSlotEight = SingleInventorySlot<ForRowFour>(4, 8)
val RowFourSlotNine = SingleInventorySlot<ForRowFour>(4, 9) val RowFourSlotNine = SingleInventorySlot<ForRowFour>(4, 9)
// ROW FIVE // ROW FIVE
val RowFiveSlotOne = SingleInventorySlot<ForRowFive>(5, 1) val RowFiveSlotOne = SingleInventorySlot<ForRowFive>(5, 1)
val RowFiveSlotTwo = SingleInventorySlot<ForRowFive>(5, 2) val RowFiveSlotTwo = SingleInventorySlot<ForRowFive>(5, 2)
@@ -318,6 +330,7 @@ object Slots {
val RowFiveSlotSeven = SingleInventorySlot<ForRowFive>(5, 7) val RowFiveSlotSeven = SingleInventorySlot<ForRowFive>(5, 7)
val RowFiveSlotEight = SingleInventorySlot<ForRowFive>(5, 8) val RowFiveSlotEight = SingleInventorySlot<ForRowFive>(5, 8)
val RowFiveSlotNine = SingleInventorySlot<ForRowFive>(5, 9) val RowFiveSlotNine = SingleInventorySlot<ForRowFive>(5, 9)
// ROW SIX // ROW SIX
val RowSixSlotOne = SingleInventorySlot<ForRowSix>(6, 1) val RowSixSlotOne = SingleInventorySlot<ForRowSix>(6, 1)
val RowSixSlotTwo = SingleInventorySlot<ForRowSix>(6, 2) val RowSixSlotTwo = SingleInventorySlot<ForRowSix>(6, 2)

View File

@@ -8,8 +8,8 @@ import org.bukkit.inventory.Inventory
import org.bukkit.inventory.InventoryHolder import org.bukkit.inventory.InventoryHolder
class InventoryType<in T : ForInventory>( class InventoryType<in T : ForInventory>(
val dimensions: InventoryDimensions, val dimensions: InventoryDimensions,
val bukkitType: InventoryType? = null val bukkitType: InventoryType? = null
) { ) {
private val size = dimensions.width * dimensions.heigth private val size = dimensions.width * dimensions.heigth
@@ -22,8 +22,10 @@ class InventoryType<in T : ForInventory>(
val FOUR_BY_NINE = InventoryType<ForInventoryFourByNine>(InventoryDimensions(9, 4)) val FOUR_BY_NINE = InventoryType<ForInventoryFourByNine>(InventoryDimensions(9, 4))
val FIVE_BY_NINE = InventoryType<ForInventoryFiveByNine>(InventoryDimensions(9, 5)) val FIVE_BY_NINE = InventoryType<ForInventoryFiveByNine>(InventoryDimensions(9, 5))
val SIX_BY_NINE = InventoryType<ForInventorySixByNine>(InventoryDimensions(9, 6)) val SIX_BY_NINE = InventoryType<ForInventorySixByNine>(InventoryDimensions(9, 6))
val ONE_BY_FIVE = InventoryType<ForInventoryOneByFive>(InventoryDimensions(5, 1), bukkitType = InventoryType.HOPPER) val ONE_BY_FIVE =
val THREE_BY_THREE = InventoryType<ForInventoryThreeByThree>(InventoryDimensions(3, 3), bukkitType = InventoryType.DROPPER) InventoryType<ForInventoryOneByFive>(InventoryDimensions(5, 1), bukkitType = InventoryType.HOPPER)
val THREE_BY_THREE =
InventoryType<ForInventoryThreeByThree>(InventoryDimensions(3, 3), bukkitType = InventoryType.DROPPER)
} }
@@ -52,9 +54,10 @@ interface ForInventorySixByNine : ForInventory
interface ForEveryInventory interface ForEveryInventory
: ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine, : ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine,
ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine,
ForInventoryThreeByThree, ForInventoryOneByFive ForInventoryThreeByThree, ForInventoryOneByFive
interface ForInventoryWidthThree : ForInventoryThreeByThree interface ForInventoryWidthThree : ForInventoryThreeByThree
interface ForInventoryWidthFive : ForInventoryOneByFive interface ForInventoryWidthFive : ForInventoryOneByFive
interface ForInventoryWidthNine : ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine interface ForInventoryWidthNine : ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine,
ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine

View File

@@ -6,8 +6,8 @@ import net.axay.kspigot.inventory.InventoryGUIElement
import net.axay.kspigot.inventory.InventoryGUIElementData import net.axay.kspigot.inventory.InventoryGUIElementData
open class InventoryGUIButton<T : ForInventory>( open class InventoryGUIButton<T : ForInventory>(
inventoryGUIElementData: InventoryGUIElementData, inventoryGUIElementData: InventoryGUIElementData,
val action: (InventoryGUIClickEvent<T>) -> Unit, val action: (InventoryGUIClickEvent<T>) -> Unit,
) : InventoryGUIElement<T>(inventoryGUIElementData) { ) : InventoryGUIElement<T>(inventoryGUIElementData) {
override fun onClickElement(clickEvent: InventoryGUIClickEvent<T>) { override fun onClickElement(clickEvent: InventoryGUIClickEvent<T>) {

View File

@@ -3,17 +3,16 @@ package net.axay.kspigot.inventory.elements
import net.axay.kspigot.inventory.* import net.axay.kspigot.inventory.*
class InventoryGUIButtonInventoryChange<T : ForInventory>( class InventoryGUIButtonInventoryChange<T : ForInventory>(
inventoryGUIElementData: InventoryGUIElementData, inventoryGUIElementData: InventoryGUIElementData,
changeToGUICallback: () -> InventoryGUI<*>, changeToGUICallback: () -> InventoryGUI<*>,
changeToPageInt: Int?, changeToPageInt: Int?,
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? onChange: ((InventoryGUIClickEvent<T>) -> Unit)?
) ) : InventoryGUIButton<T>(inventoryGUIElementData, {
: InventoryGUIButton<T>(inventoryGUIElementData, {
val changeToGUI = changeToGUICallback.invoke() val changeToGUI = changeToGUICallback.invoke()
val effect = (changeToGUI.data.transitionTo ?: it.gui.data.transitionFrom) val effect = (changeToGUI.data.transitionTo ?: it.gui.data.transitionFrom)
?: InventoryChangeEffect.INSTANT ?: InventoryChangeEffect.INSTANT
val changeToPage = changeToGUI.getPage(changeToPageInt) ?: changeToGUI.currentPage val changeToPage = changeToGUI.getPage(changeToPageInt) ?: changeToGUI.currentPage

View File

@@ -3,18 +3,17 @@ package net.axay.kspigot.inventory.elements
import net.axay.kspigot.inventory.* import net.axay.kspigot.inventory.*
class InventoryGUIButtonPageChange<T : ForInventory>( class InventoryGUIButtonPageChange<T : ForInventory>(
inventoryGUIElementData: InventoryGUIElementData, inventoryGUIElementData: InventoryGUIElementData,
calculator: InventoryGUIPageChangeCalculator, calculator: InventoryGUIPageChangeCalculator,
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? onChange: ((InventoryGUIClickEvent<T>) -> Unit)?
) ) : InventoryGUIButton<T>(inventoryGUIElementData, {
: InventoryGUIButton<T>(inventoryGUIElementData, {
val currentPage = it.gui.currentPage val currentPage = it.gui.currentPage
val newPage = it.gui.getPage(calculator.calculateNewPage(it.gui.currentPageInt, it.gui.data.pages.keys)) val newPage = it.gui.getPage(calculator.calculateNewPage(it.gui.currentPageInt, it.gui.data.pages.keys))
if (newPage != null) { if (newPage != null) {
val effect = (newPage.transitionTo ?: currentPage.transitionFrom) val effect = (newPage.transitionTo ?: currentPage.transitionFrom)
?: PageChangeEffect.INSTANT ?: PageChangeEffect.INSTANT
it.gui.changePage(effect, currentPage, newPage) it.gui.changePage(effect, currentPage, newPage)

View File

@@ -5,5 +5,7 @@ import net.axay.kspigot.inventory.InventoryGUIClickEvent
import net.axay.kspigot.inventory.InventoryGUISlot import net.axay.kspigot.inventory.InventoryGUISlot
class InventoryGUIFreeSlot<T : ForInventory> : InventoryGUISlot<T>() { class InventoryGUIFreeSlot<T : ForInventory> : InventoryGUISlot<T>() {
override fun onClick(clickEvent: InventoryGUIClickEvent<T>) { /* do nothing */ } override fun onClick(clickEvent: InventoryGUIClickEvent<T>) {
/* do nothing */
}
} }

View File

@@ -6,7 +6,7 @@ import net.axay.kspigot.inventory.InventoryGUIElement
import net.axay.kspigot.inventory.InventoryGUIElementData import net.axay.kspigot.inventory.InventoryGUIElementData
class InventoryGUIPlaceholder<T : ForInventory>( class InventoryGUIPlaceholder<T : ForInventory>(
inventoryGUIElementData: InventoryGUIElementData inventoryGUIElementData: InventoryGUIElementData
) : InventoryGUIElement<T>(inventoryGUIElementData) { ) : InventoryGUIElement<T>(inventoryGUIElementData) {
override fun onClickElement(clickEvent: InventoryGUIClickEvent<T>) { override fun onClickElement(clickEvent: InventoryGUIClickEvent<T>) {

View File

@@ -8,7 +8,8 @@ import org.bukkit.entity.Player
import java.net.URL import java.net.URL
private const val IP_API = "http://ip-api.com/json/" private const val IP_API = "http://ip-api.com/json/"
private const val IP_API_FIELDS = "status,message,continent,continentCode,country,countryCode,region,regionName,city,district,zip,lat,lon,timezone,currency,isp,org,query" private const val IP_API_FIELDS =
"status,message,continent,continentCode,country,countryCode,region,regionName,city,district,zip,lat,lon,timezone,currency,isp,org,query"
/** /**
* @see ipAddressData * @see ipAddressData
@@ -27,8 +28,8 @@ fun Player.ipAddressData(language: IPAddressDataLanguage = IPAddressDataLanguage
val hostString = address?.hostString ?: return null val hostString = address?.hostString ?: return null
val jsonObject = ValueHolder.getGson(false).fromJson( val jsonObject = ValueHolder.getGson(false).fromJson(
URL("$IP_API${hostString}?fields=${IP_API_FIELDS}?lang=${language.code}").readText(), URL("$IP_API${hostString}?fields=${IP_API_FIELDS}?lang=${language.code}").readText(),
JsonObject::class.java JsonObject::class.java
) ?: return null ) ?: return null
if (jsonObject["status"].toString() == "fail") return null if (jsonObject["status"].toString() == "fail") return null

View File

@@ -17,16 +17,16 @@ import org.bukkit.inventory.meta.ItemMeta
data class CustomItemIdentifier(val customModelData: Int, val placeHolderMaterial: Material) { data class CustomItemIdentifier(val customModelData: Int, val placeHolderMaterial: Material) {
constructor(itemStack: ItemStack) : constructor(itemStack: ItemStack) :
this( this(
kotlin.run { kotlin.run {
val itemMeta = itemStack.itemMeta val itemMeta = itemStack.itemMeta
if (itemMeta != null && itemMeta.hasCustomModelData()) { if (itemMeta != null && itemMeta.hasCustomModelData()) {
return@run itemMeta.customModelData return@run itemMeta.customModelData
} }
return@run 0 return@run 0
}, },
itemStack.type itemStack.type
) )
val itemStack: ItemStack? val itemStack: ItemStack?
get() { get() {

View File

@@ -9,10 +9,15 @@ internal val <T> Lazy<T>.valueIfInitialized get() = ifInitialized { value }
internal fun Lazy<AutoCloseable>.closeIfInitialized() = ifInitialized { value.close() } internal fun Lazy<AutoCloseable>.closeIfInitialized() = ifInitialized { value.close() }
internal class MinMaxPair<T : Comparable<T>>(a: T, b: T) { internal class MinMaxPair<T : Comparable<T>>(a: T, b: T) {
val min: T; val max: T val min: T;
val max: T
init { init {
if (a >= b) { min = b; max = a } if (a >= b) {
else { min = a; max = b } min = b; max = a
} else {
min = a; max = b
}
} }
} }

View File

@@ -30,17 +30,17 @@ abstract class KSpigot : JavaPlugin() {
/** /**
* Called when the plugin was loaded * Called when the plugin was loaded
*/ */
open fun load() { } open fun load() {}
/** /**
* Called when the plugin was enabled * Called when the plugin was enabled
*/ */
open fun startup() { } open fun startup() {}
/** /**
* Called when the plugin gets disabled * Called when the plugin gets disabled
*/ */
open fun shutdown() { } open fun shutdown() {}
final override fun onLoad() { final override fun onLoad() {
KSpigotMainInstance = this KSpigotMainInstance = this

View File

@@ -16,12 +16,12 @@ import org.bukkit.util.Vector
* @param force Determines whether the client should be encouraged to display the particles. * @param force Determines whether the client should be encouraged to display the particles.
*/ */
data class KSpigotParticle( data class KSpigotParticle(
val particle: Particle, val particle: Particle,
var amount: Int = 1, var amount: Int = 1,
var offset: Vector? = null, var offset: Vector? = null,
var extra: Number = 1.0, var extra: Number = 1.0,
var data: Any? = null, var data: Any? = null,
var force: Boolean = false var force: Boolean = false
) { ) {
/** /**
@@ -30,15 +30,15 @@ data class KSpigotParticle(
*/ */
fun spawnAt(loc: Location) { fun spawnAt(loc: Location) {
loc.worldOrException.spawnParticle( loc.worldOrException.spawnParticle(
particle, particle,
loc, loc,
amount, amount,
offset?.x ?: 0.0, offset?.x ?: 0.0,
offset?.y ?: 0.0, offset?.y ?: 0.0,
offset?.z ?: 0.0, offset?.z ?: 0.0,
extra.toDouble(), extra.toDouble(),
data, data,
force force
) )
} }
@@ -48,14 +48,14 @@ data class KSpigotParticle(
*/ */
fun spawnFor(player: Player) { fun spawnFor(player: Player) {
player.spawnParticle( player.spawnParticle(
particle, particle,
player.location, player.location,
amount, amount,
offset?.x ?: 0.0, offset?.x ?: 0.0,
offset?.y ?: 0.0, offset?.y ?: 0.0,
offset?.z ?: 0.0, offset?.z ?: 0.0,
extra.toDouble(), extra.toDouble(),
data data
) )
} }
@@ -65,21 +65,20 @@ data class KSpigotParticle(
* Accesses the particle builder. * Accesses the particle builder.
* @see KSpigotParticle * @see KSpigotParticle
*/ */
fun particle(particle: Particle, builder: KSpigotParticle.() -> Unit) fun particle(particle: Particle, builder: KSpigotParticle.() -> Unit) = KSpigotParticle(particle).apply(builder)
= KSpigotParticle(particle).apply(builder)
/** /**
* Accesses the particle builder and then immediately * Accesses the particle builder and then immediately
* spawns the particle at the given location. * spawns the particle at the given location.
* @see KSpigotParticle * @see KSpigotParticle
*/ */
fun Location.particle(particle: Particle, builder: (KSpigotParticle.() -> Unit)? = null) fun Location.particle(particle: Particle, builder: (KSpigotParticle.() -> Unit)? = null) =
= KSpigotParticle(particle).applyIfNotNull(builder).spawnAt(this) KSpigotParticle(particle).applyIfNotNull(builder).spawnAt(this)
/** /**
* Accesses the particle builder and then immediately * Accesses the particle builder and then immediately
* spawns the particle for the player. * spawns the particle for the player.
* @see KSpigotParticle * @see KSpigotParticle
*/ */
fun Player.particle(particle: Particle, builder: (KSpigotParticle.() -> Unit)? = null) fun Player.particle(particle: Particle, builder: (KSpigotParticle.() -> Unit)? = null) =
= KSpigotParticle(particle).applyIfNotNull(builder).spawnFor(this) KSpigotParticle(particle).applyIfNotNull(builder).spawnFor(this)

View File

@@ -82,8 +82,7 @@ class ChainedRunnablePartFirst<R>(
sync: Boolean sync: Boolean
) : ChainedRunnablePart<Unit, R>(sync) { ) : ChainedRunnablePart<Unit, R>(sync) {
override fun execute() override fun execute() = start(Unit)
= start(Unit)
override fun <E : Exception> executeCatchingImpl( override fun <E : Exception> executeCatchingImpl(
exceptionClass: KClass<E>, exceptionClass: KClass<E>,
@@ -101,8 +100,7 @@ class ChainedRunnablePartThen<T, R>(
val previous: ChainedRunnablePart<*, T> val previous: ChainedRunnablePart<*, T>
) : ChainedRunnablePart<T, R>(sync) { ) : ChainedRunnablePart<T, R>(sync) {
override fun execute() override fun execute() = previous.execute()
= previous.execute()
override fun <E : Exception> executeCatchingImpl( override fun <E : Exception> executeCatchingImpl(
exceptionClass: KClass<E>, exceptionClass: KClass<E>,
@@ -115,13 +113,13 @@ class ChainedRunnablePartThen<T, R>(
} }
// FIRST // FIRST
fun <R> firstDo(sync: Boolean, runnable: () -> R) fun <R> firstDo(sync: Boolean, runnable: () -> R) = ChainedRunnablePartFirst(runnable, sync)
= ChainedRunnablePartFirst(runnable, sync)
fun <R> firstSync(runnable: () -> R) = firstDo(true, runnable) fun <R> firstSync(runnable: () -> R) = firstDo(true, runnable)
fun <R> firstAsync(runnable: () -> R) = firstDo(false, runnable) fun <R> firstAsync(runnable: () -> R) = firstDo(false, runnable)
// THEN // THEN
fun <T, R, U> ChainedRunnablePart<T, R>.thenDo(sync: Boolean, runnable: (R) -> U) fun <T, R, U> ChainedRunnablePart<T, R>.thenDo(sync: Boolean, runnable: (R) -> U) =
= ChainedRunnablePartThen(runnable, sync, this).apply { previous.next = this } ChainedRunnablePartThen(runnable, sync, this).apply { previous.next = this }
fun <T, R, U> ChainedRunnablePart<T, R>.thenSync(runnable: (R) -> U) = thenDo(true, runnable) fun <T, R, U> ChainedRunnablePart<T, R>.thenSync(runnable: (R) -> U) = thenDo(true, runnable)
fun <T, R, U> ChainedRunnablePart<T, R>.thenAsync(runnable: (R) -> U) = thenDo(false, runnable) fun <T, R, U> ChainedRunnablePart<T, R>.thenAsync(runnable: (R) -> U) = thenDo(false, runnable)

View File

@@ -21,19 +21,18 @@ internal object KRunnableHolder : AutoCloseable {
runnableEndCallbacks.clear() runnableEndCallbacks.clear()
} }
fun add(runnable: BukkitRunnable, callback: () -> Unit, safe: Boolean) fun add(runnable: BukkitRunnable, callback: () -> Unit, safe: Boolean) =
= runnableEndCallbacks.put(runnable, Pair(callback, safe)) runnableEndCallbacks.put(runnable, Pair(callback, safe))
fun remove(runnable: BukkitRunnable)
= runnableEndCallbacks.remove(runnable) fun remove(runnable: BukkitRunnable) = runnableEndCallbacks.remove(runnable)
fun activate(runnable: BukkitRunnable) fun activate(runnable: BukkitRunnable) = runnableEndCallbacks.remove(runnable)?.first?.invoke()
= runnableEndCallbacks.remove(runnable)?.first?.invoke()
} }
abstract class KSpigotRunnable( abstract class KSpigotRunnable(
var counterUp: Long? = null, var counterUp: Long? = null,
var counterDownToOne: Long? = null, var counterDownToOne: Long? = null,
var counterDownToZero: Long? = null var counterDownToZero: Long? = null
) : BukkitRunnable() ) : BukkitRunnable()
/** /**
@@ -49,13 +48,13 @@ abstract class KSpigotRunnable(
* @param runnable the runnable which should be executed each repetition * @param runnable the runnable which should be executed each repetition
*/ */
fun task( fun task(
sync: Boolean = true, sync: Boolean = true,
delay: Long = 0, delay: Long = 0,
period: Long? = null, period: Long? = null,
howOften: Long? = null, howOften: Long? = null,
safe: Boolean = false, safe: Boolean = false,
endCallback: (() -> Unit)? = null, endCallback: (() -> Unit)? = null,
runnable: ((KSpigotRunnable) -> Unit)? = null runnable: ((KSpigotRunnable) -> Unit)? = null
) { ) {
if (howOften != null && howOften == 0L) return if (howOften != null && howOften == 0L) return
@@ -119,11 +118,9 @@ fun bukkitRun(sync: Boolean, runnable: () -> Unit) {
/** /**
* Starts a synchronous task. * Starts a synchronous task.
*/ */
fun sync(runnable: () -> Unit) fun sync(runnable: () -> Unit) = Bukkit.getScheduler().runTask(KSpigotMainInstance, runnable)
= Bukkit.getScheduler().runTask(KSpigotMainInstance, runnable)
/** /**
* Starts an asynchronous task. * Starts an asynchronous task.
*/ */
fun async(runnable: () -> Unit) fun async(runnable: () -> Unit) = Bukkit.getScheduler().runTaskAsynchronously(KSpigotMainInstance, runnable)
= Bukkit.getScheduler().runTaskAsynchronously(KSpigotMainInstance, runnable)

View File

@@ -15,13 +15,12 @@ interface SpigotSerialzableCompanion<T>
/** /**
* @return A json string. * @return A json string.
*/ */
fun SpigotSerializable<*>.serialize(pretty: Boolean = true): String fun SpigotSerializable<*>.serialize(pretty: Boolean = true): String = ValueHolder.getGson(pretty).toJson(this)
= ValueHolder.getGson(pretty).toJson(this)
/** /**
* Deserializes the given json string and * Deserializes the given json string and
* returns the deserialized object. * returns the deserialized object.
*/ */
@Suppress("unused") @Suppress("unused")
inline fun <reified T> SpigotSerialzableCompanion<T>.deserialize(json: String): T inline fun <reified T> SpigotSerialzableCompanion<T>.deserialize(json: String): T =
= ValueHolder.getGson(false).fromJson(json, T::class.java) ValueHolder.getGson(false).fromJson(json, T::class.java)

View File

@@ -19,8 +19,7 @@ class SerializableLocation(
constructor(loc: Location) : this(loc.world?.name, loc.x, loc.y, loc.z, SerializableVector(loc.direction)) constructor(loc: Location) : this(loc.world?.name, loc.x, loc.y, loc.z, SerializableVector(loc.direction))
override fun toSpigot() override fun toSpigot() = Location(world?.let { Bukkit.getWorld(world) }, x, y, z)
= Location(world?.let { Bukkit.getWorld(world) }, x, y, z) .apply { direction = this@SerializableLocation.direction.toSpigot() }
.apply { direction = this@SerializableLocation.direction.toSpigot() }
} }

View File

@@ -44,21 +44,20 @@ data class KSpigotSound(
* Accesses the sound builder. * Accesses the sound builder.
* @see KSpigotSound * @see KSpigotSound
*/ */
fun sound(sound: Sound, builder: KSpigotSound.() -> Unit) fun sound(sound: Sound, builder: KSpigotSound.() -> Unit) = KSpigotSound(sound).apply(builder)
= KSpigotSound(sound).apply(builder)
/** /**
* Accesses the sound builder and then immediately * Accesses the sound builder and then immediately
* plays the sound at the given location. * plays the sound at the given location.
* @see KSpigotSound * @see KSpigotSound
*/ */
fun Location.sound(sound: Sound, builder: (KSpigotSound.() -> Unit)? = null) fun Location.sound(sound: Sound, builder: (KSpigotSound.() -> Unit)? = null) =
= KSpigotSound(sound).applyIfNotNull(builder).playAt(this) KSpigotSound(sound).applyIfNotNull(builder).playAt(this)
/** /**
* Accesses the sound builder and then immediately * Accesses the sound builder and then immediately
* plays the sound for the player. * plays the sound for the player.
* @see KSpigotSound * @see KSpigotSound
*/ */
fun Player.sound(sound: Sound, builder: (KSpigotSound.() -> Unit)? = null) fun Player.sound(sound: Sound, builder: (KSpigotSound.() -> Unit)? = null) =
= KSpigotSound(sound).applyIfNotNull(builder).playFor(this) KSpigotSound(sound).applyIfNotNull(builder).playFor(this)

View File

@@ -55,8 +55,16 @@ abstract class Circle(val radius: Number) {
while (currentRadius >= 0) { while (currentRadius >= 0) {
this += circleEdgeLocations(currentRadius).mapTo(HashSet()) { this += circleEdgeLocations(currentRadius).mapTo(HashSet()) {
mutableSetOf(it).apply { mutableSetOf(it).apply {
this += SimpleLocation2D(it.x + when { it.x >= 1 -> -1; it.x <= -1 -> 1; else -> 0 }, it.y) this += SimpleLocation2D(
this += SimpleLocation2D(it.x, it.y + when { it.y >= 1 -> -1; it.y <= -1 -> 1; else -> 0 }) it.x + when {
it.x >= 1 -> -1; it.x <= -1 -> 1; else -> 0
}, it.y
)
this += SimpleLocation2D(
it.x, it.y + when {
it.y >= 1 -> -1; it.y <= -1 -> 1; else -> 0
}
)
} }
}.flatten() }.flatten()
currentRadius-- currentRadius--

View File

@@ -18,12 +18,12 @@ interface StructureData {
} }
class SingleStructureData( class SingleStructureData(
val location: SimpleLocation3D, val location: SimpleLocation3D,
val structureData: StructureData val structureData: StructureData
) )
data class Structure( data class Structure(
val structureData: Set<SingleStructureData> val structureData: Set<SingleStructureData>
) { ) {
constructor(vararg structureDataSets: Set<SingleStructureData>) constructor(vararg structureDataSets: Set<SingleStructureData>)
: this(structureDataSets.flatMapTo(HashSet()) { it }) : this(structureDataSets.flatMapTo(HashSet()) { it })
@@ -34,7 +34,7 @@ data class Structure(
*/ */
data class StructureDataMaterial( data class StructureDataMaterial(
val material: Material val material: Material
) : StructureData { ) : StructureData {
override fun createAt(loc: Location) { override fun createAt(loc: Location) {
@@ -44,8 +44,8 @@ data class StructureDataMaterial(
} }
data class StructureDataBlock( data class StructureDataBlock(
val material: Material, val material: Material,
val blockData: BlockData val blockData: BlockData
) : StructureData { ) : StructureData {
constructor(block: Block) : this(block.type, block.blockData) constructor(block: Block) : this(block.type, block.blockData)
@@ -61,8 +61,8 @@ data class StructureDataBlock(
@NMS_General @NMS_General
data class StructureDataEntity( data class StructureDataEntity(
val entityType: EntityType, val entityType: EntityType,
val nbtData: NBTData val nbtData: NBTData
) : StructureData { ) : StructureData {
constructor(entity: Entity) : this(entity.type, entity.nbtData) constructor(entity: Entity) : this(entity.type, entity.nbtData)
@@ -75,7 +75,7 @@ data class StructureDataEntity(
} }
data class StructureDataParticle( data class StructureDataParticle(
val particle: KSpigotParticle val particle: KSpigotParticle
) : StructureData { ) : StructureData {
override fun createAt(loc: Location) { override fun createAt(loc: Location) {

View File

@@ -15,26 +15,22 @@ fun Structure.buildAt(loc: Location) {
} }
/** @see Structure.rotate */ /** @see Structure.rotate */
fun Structure.rotateAroundX(angle: Number) fun Structure.rotateAroundX(angle: Number) = rotate(angle) { it, rad -> it.rotateAroundZ(rad) }
= rotate(angle) { it, rad -> it.rotateAroundZ(rad) }
/** @see Structure.rotate */ /** @see Structure.rotate */
fun Structure.rotateAroundY(angle: Number) fun Structure.rotateAroundY(angle: Number) = rotate(angle) { it, rad -> it.rotateAroundY(rad) }
= rotate(angle) { it, rad -> it.rotateAroundY(rad) }
/** @see Structure.rotate */ /** @see Structure.rotate */
fun Structure.rotateAroundZ(angle: Number) fun Structure.rotateAroundZ(angle: Number) = rotate(angle) { it, rad -> it.rotateAroundZ(rad) }
= rotate(angle) { it, rad -> it.rotateAroundZ(rad) }
/** @param angle The angle of rotation in degrees.*/ /** @param angle The angle of rotation in degrees.*/
inline fun Structure.rotate(angle: Number, vectorRotation: (Vector, Double) -> Vector) inline fun Structure.rotate(angle: Number, vectorRotation: (Vector, Double) -> Vector) = Structure(
= Structure( HashSet<SingleStructureData>().apply {
HashSet<SingleStructureData>().apply { structureData.forEach {
structureData.forEach { this += SingleStructureData(
this += SingleStructureData( vectorRotation.invoke(it.location.toVector(), Math.toRadians(angle.toDouble())).toSimpleLoc(),
vectorRotation.invoke(it.location.toVector(), Math.toRadians(angle.toDouble())).toSimpleLoc(), it.structureData
it.structureData )
)
}
} }
) }
)

View File

@@ -12,38 +12,45 @@ import org.bukkit.entity.Entity
/** /**
* @return A [Structure] containing all data of the given [LocationArea]. * @return A [Structure] containing all data of the given [LocationArea].
*/ */
fun LocationArea.loadStructure(includeBlocks: Boolean = true, includeEntities: Boolean = false) fun LocationArea.loadStructure(includeBlocks: Boolean = true, includeEntities: Boolean = false) = Structure(
= Structure( if (includeBlocks)
if (includeBlocks) fillBlocks.mapTo(HashSet()) {
fillBlocks.mapTo(HashSet()) { SingleStructureData(it.location relationTo minLoc.blockLoc, StructureDataBlock(it))
SingleStructureData(it.location relationTo minLoc.blockLoc, StructureDataBlock(it)) } }
else emptySet(), else emptySet(),
if (includeEntities) if (includeEntities)
entities.mapTo(HashSet()) { entities.mapTo(HashSet()) {
SingleStructureData(it.location relationTo minLoc.blockLoc, StructureDataEntity(it)) } SingleStructureData(it.location relationTo minLoc.blockLoc, StructureDataEntity(it))
else emptySet() }
) else emptySet()
)
/** /**
* @return All blocks in the given [LocationArea]. * @return All blocks in the given [LocationArea].
* Sorted by their coordinates. * Sorted by their coordinates.
*/ */
val LocationArea.fillBlocks: Set<Block> get() val LocationArea.fillBlocks: Set<Block>
get()
= LinkedHashSet<Block>().apply { = LinkedHashSet<Block>().apply {
(minLoc.blockX until maxLoc.blockX + 1).forEach { x -> (minLoc.blockX until maxLoc.blockX + 1).forEach { x ->
(minLoc.blockY until maxLoc.blockY + 1).forEach { y -> (minLoc.blockY until maxLoc.blockY + 1).forEach { y ->
(minLoc.blockZ until maxLoc.blockZ + 1).forEach { z -> (minLoc.blockZ until maxLoc.blockZ + 1).forEach { z ->
this += Location(world, x.toDouble(), y.toDouble(), z.toDouble()).block this += Location(world, x.toDouble(), y.toDouble(), z.toDouble()).block
} } } }
}
}
} }
/** /**
* @return All entities in the given [LocationArea]. * @return All entities in the given [LocationArea].
*/ */
val LocationArea.entities: Set<Entity> get() val LocationArea.entities: Set<Entity>
get()
= HashSet<Entity>().apply { = HashSet<Entity>().apply {
touchedChunks.forEach { it.entities.forEach { en -> touchedChunks.forEach {
if (simpleLocationPair.isInArea(en.location)) it.entities.forEach { en ->
this += en if (simpleLocationPair.isInArea(en.location))
} } this += en
}
}
} }