Improve code style
This commit is contained in:
@@ -6,7 +6,6 @@ import java.awt.*;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class KColors {
|
||||
|
||||
// DEFAULT CODES
|
||||
|
||||
public static final ChatColor MAGIC = ChatColor.MAGIC;
|
||||
@@ -877,5 +876,4 @@ public class KColors {
|
||||
* <div style="border:1px solid black;width:120px;height:120px;background-color:#9ACD32;float:right;margin: 0 10px 0 0"></div>
|
||||
*/
|
||||
public static final ChatColor YELLOWGREEN = ChatColor.of(new Color(0.6039216f, 0.8039216f, 0.19607843f));
|
||||
|
||||
}
|
||||
|
@@ -13,11 +13,8 @@ inline fun chatComponent(builder: KSpigotComponentBuilder.() -> Unit): Array<out
|
||||
}
|
||||
|
||||
class KSpigotComponentBuilder {
|
||||
|
||||
private val components = ArrayList<BaseComponent>()
|
||||
|
||||
// COMPONENTS
|
||||
|
||||
inline fun text(text: String, builder: TextComponent.() -> Unit = { }) {
|
||||
this += TextComponent(text).apply(builder)
|
||||
}
|
||||
@@ -40,13 +37,11 @@ class KSpigotComponentBuilder {
|
||||
inline fun translatable(
|
||||
translatable: String,
|
||||
with: Array<BaseComponent>,
|
||||
builder: TranslatableComponent.() -> Unit = { }
|
||||
builder: TranslatableComponent.() -> Unit = { },
|
||||
) {
|
||||
this += TranslatableComponent(translatable, with).apply(builder)
|
||||
}
|
||||
|
||||
// SPECIAL
|
||||
|
||||
fun legacyText(text: String, color: ChatColor = ChatColor.WHITE, builder: BaseComponent.() -> Unit = { }) {
|
||||
this += TextComponent.fromLegacyText(text, color).onEach { it.apply(builder) }
|
||||
}
|
||||
@@ -60,15 +55,11 @@ class KSpigotComponentBuilder {
|
||||
}
|
||||
|
||||
fun create() = components.toTypedArray()
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* BASE COMPONENT
|
||||
*/
|
||||
|
||||
// extensions
|
||||
|
||||
inline fun BaseComponent.hoverEventText(builder: KSpigotComponentBuilder.() -> Unit) {
|
||||
hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, Text(KSpigotComponentBuilder().apply(builder).create()))
|
||||
}
|
||||
@@ -84,7 +75,6 @@ fun BaseComponent.hoverEventEntity(type: String, id: String, baseComponent: Base
|
||||
fun BaseComponent.clickEvent(action: ClickEvent.Action, value: String) {
|
||||
clickEvent = ClickEvent(action, value)
|
||||
}
|
||||
|
||||
/*
|
||||
* GLOBAL SHORTCUTS
|
||||
*/
|
||||
|
@@ -19,7 +19,7 @@ import org.bukkit.event.Listener
|
||||
fun Player.awaitChatInput(
|
||||
question: String = "Type your input in the chat!",
|
||||
timeoutSeconds: Int = 1 * 60,
|
||||
callback: (PlayerInputResult<String>) -> Unit
|
||||
callback: (PlayerInputResult<String>) -> Unit,
|
||||
) {
|
||||
PlayerInputChat(this, callback, timeoutSeconds, question)
|
||||
}
|
||||
@@ -36,7 +36,7 @@ fun Player.awaitAnvilInput(
|
||||
"submit your input!"
|
||||
),
|
||||
timeoutSeconds: Int = 1 * 60,
|
||||
callback: (PlayerInputResult<String>) -> Unit
|
||||
callback: (PlayerInputResult<String>) -> Unit,
|
||||
) {
|
||||
PlayerInputAnvilInv(this, callback, timeoutSeconds, invTitle, startText, renameItemDescription)
|
||||
}
|
||||
@@ -48,7 +48,7 @@ fun Player.awaitAnvilInput(
|
||||
*/
|
||||
fun Player.awaitBookInputAsString(
|
||||
timeoutSeconds: Int = 1 * 60,
|
||||
callback: (PlayerInputResult<String>) -> Unit
|
||||
callback: (PlayerInputResult<String>) -> Unit,
|
||||
) {
|
||||
PlayerInputBookComprehensive(this, callback, timeoutSeconds)
|
||||
}
|
||||
@@ -61,7 +61,7 @@ fun Player.awaitBookInputAsString(
|
||||
*/
|
||||
fun Player.awaitBookInputAsList(
|
||||
timeoutSeconds: Int = 1 * 60,
|
||||
callback: (PlayerInputResult<List<String>>) -> Unit
|
||||
callback: (PlayerInputResult<List<String>>) -> Unit,
|
||||
) {
|
||||
PlayerInputBookPaged(this, callback, timeoutSeconds)
|
||||
}
|
||||
@@ -70,17 +70,13 @@ fun Player.awaitBookInputAsList(
|
||||
* @param input The input the player gave. Null on timeout or invalid input.
|
||||
*/
|
||||
class PlayerInputResult<T> internal constructor(val input: T?)
|
||||
|
||||
internal abstract class PlayerInput<T>(
|
||||
protected val player: Player,
|
||||
private val callback: (PlayerInputResult<T>) -> Unit,
|
||||
timeoutSeconds: Int
|
||||
timeoutSeconds: Int,
|
||||
) {
|
||||
|
||||
private var received = false
|
||||
|
||||
protected abstract val inputListeners: List<Listener>
|
||||
|
||||
protected fun onReceive(input: T?) {
|
||||
if (!received) {
|
||||
inputListeners.forEach { it.unregister() }
|
||||
@@ -99,5 +95,4 @@ internal abstract class PlayerInput<T>(
|
||||
onReceive(null)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -19,9 +19,8 @@ internal class PlayerInputAnvilInv(
|
||||
timeoutSeconds: Int,
|
||||
invTitle: String,
|
||||
startText: String,
|
||||
renameItemDescription: List<String>
|
||||
renameItemDescription: List<String>,
|
||||
) : PlayerInput<String>(player, callback, timeoutSeconds) {
|
||||
|
||||
private val anvilInv =
|
||||
AnvilGUI.Builder().plugin(KSpigotMainInstance)
|
||||
.onClose { onReceive(null) }
|
||||
@@ -42,7 +41,6 @@ internal class PlayerInputAnvilInv(
|
||||
)
|
||||
.text("${KColors.ORANGERED}$startText")
|
||||
.open(player)
|
||||
|
||||
override val inputListeners = listOf(
|
||||
listen<InventoryClickEvent> {
|
||||
if (it.clickedInventory == anvilInv.inventory)
|
||||
@@ -53,5 +51,4 @@ internal class PlayerInputAnvilInv(
|
||||
override fun onTimeout() {
|
||||
anvilInv.inventory.closeForViewers()
|
||||
}
|
||||
|
||||
}
|
@@ -17,7 +17,7 @@ import org.bukkit.persistence.PersistentDataType
|
||||
internal class PlayerInputBookComprehensive(
|
||||
player: Player,
|
||||
callback: (PlayerInputResult<String>) -> Unit,
|
||||
timeoutSeconds: Int
|
||||
timeoutSeconds: Int,
|
||||
) : PlayerInputBook<String>(player, callback, timeoutSeconds) {
|
||||
override fun loadBookContent(bookMeta: BookMeta) = bookMeta.content
|
||||
}
|
||||
@@ -25,7 +25,7 @@ internal class PlayerInputBookComprehensive(
|
||||
internal class PlayerInputBookPaged(
|
||||
player: Player,
|
||||
callback: (PlayerInputResult<List<String>>) -> Unit,
|
||||
timeoutSeconds: Int
|
||||
timeoutSeconds: Int,
|
||||
) : PlayerInputBook<List<String>>(player, callback, timeoutSeconds) {
|
||||
override fun loadBookContent(bookMeta: BookMeta): List<String> = bookMeta.pages
|
||||
}
|
||||
@@ -33,9 +33,8 @@ internal class PlayerInputBookPaged(
|
||||
internal abstract class PlayerInputBook<T>(
|
||||
player: Player,
|
||||
callback: (PlayerInputResult<T>) -> Unit,
|
||||
timeoutSeconds: Int
|
||||
timeoutSeconds: Int,
|
||||
) : PlayerInput<T>(player, callback, timeoutSeconds) {
|
||||
|
||||
private val id = getID()
|
||||
|
||||
init {
|
||||
@@ -47,7 +46,6 @@ internal abstract class PlayerInputBook<T>(
|
||||
}
|
||||
|
||||
abstract fun loadBookContent(bookMeta: BookMeta): T
|
||||
|
||||
override val inputListeners = listOf(
|
||||
listen<PlayerEditBookEvent> {
|
||||
val meta = it.newBookMeta
|
||||
@@ -64,16 +62,12 @@ internal abstract class PlayerInputBook<T>(
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val idKey = NamespacedKey(KSpigotMainInstance, "kspigot_bookinput_id")
|
||||
|
||||
internal val usedIDs = ArrayList<Int>()
|
||||
fun getID(): Int {
|
||||
var returnID = (0..Int.MAX_VALUE).random()
|
||||
while (usedIDs.contains(returnID)) returnID = (0..Int.MAX_VALUE).random()
|
||||
return returnID
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -12,7 +12,7 @@ internal class PlayerInputChat(
|
||||
player: Player,
|
||||
callback: (PlayerInputResult<String>) -> Unit,
|
||||
timeoutSeconds: Int,
|
||||
question: String
|
||||
question: String,
|
||||
) : PlayerInput<String>(player, callback, timeoutSeconds) {
|
||||
|
||||
init {
|
||||
@@ -27,5 +27,4 @@ internal class PlayerInputChat(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
@@ -43,11 +43,9 @@ class ConfigDelegate<T : Any>(
|
||||
private val configClass: KClass<T>,
|
||||
private val file: File,
|
||||
private val saveAfterLoad: Boolean,
|
||||
private val defaultCallback: (() -> T)?
|
||||
private val defaultCallback: (() -> T)?,
|
||||
) {
|
||||
|
||||
private var internalConfig: T = loadIt()
|
||||
|
||||
var data: T
|
||||
get() = internalConfig
|
||||
set(value) {
|
||||
@@ -55,7 +53,6 @@ class ConfigDelegate<T : Any>(
|
||||
}
|
||||
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>) = internalConfig
|
||||
|
||||
operator fun setValue(thisRef: Any?, property: KProperty<*>, config: T): Boolean {
|
||||
internalConfig = config
|
||||
return true
|
||||
@@ -79,7 +76,6 @@ class ConfigDelegate<T : Any>(
|
||||
}
|
||||
|
||||
private fun loadIt(): T {
|
||||
|
||||
val loaded = if (defaultCallback == null)
|
||||
GsonConfigManager.loadConfig(file, configClass)
|
||||
else
|
||||
@@ -90,13 +86,10 @@ class ConfigDelegate<T : Any>(
|
||||
saveIt(loaded)
|
||||
|
||||
return loaded
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal object GsonConfigManager {
|
||||
|
||||
fun <T : Any> loadConfig(file: File, configClass: KClass<T>): T =
|
||||
FileReader(file).use { reader -> return getGson().fromJson(reader, configClass.java) }
|
||||
|
||||
@@ -111,7 +104,7 @@ internal object GsonConfigManager {
|
||||
file: File,
|
||||
configClass: KClass<T>,
|
||||
pretty: Boolean = true,
|
||||
default: () -> T
|
||||
default: () -> T,
|
||||
): T {
|
||||
try {
|
||||
return loadConfig(file, configClass)
|
||||
@@ -122,5 +115,4 @@ internal object GsonConfigManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -8,7 +8,6 @@ import net.minecraft.server.v1_16_R3.NBTTagCompound
|
||||
|
||||
@NMS_General
|
||||
class NBTData {
|
||||
|
||||
val nbtTagCompound: NBTTagCompound
|
||||
|
||||
constructor(nbtTagCompound: NBTTagCompound?) {
|
||||
@@ -60,9 +59,6 @@ class NBTData {
|
||||
operator fun minusAssign(key: String) = remove(key)
|
||||
|
||||
companion object {
|
||||
|
||||
fun deserialize(nbtString: String) = NBTData(nbtString)
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -5,12 +5,10 @@ import net.minecraft.server.v1_16_R3.*
|
||||
|
||||
@NMS_General
|
||||
interface NBTDataType<T> {
|
||||
|
||||
fun decodeNMS(nbtBase: NBTBase): T?
|
||||
fun writeToCompound(key: String, data: T, compound: NBTTagCompound)
|
||||
|
||||
companion object {
|
||||
|
||||
val COMPOUND = nbtDataType<NBTData, NBTTagCompound>({ NBTData(it) },
|
||||
{ key, data, compound -> compound.set(key, data.nbtTagCompound) })
|
||||
val BYTE =
|
||||
@@ -32,9 +30,7 @@ interface NBTDataType<T> {
|
||||
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) })
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,16 +39,11 @@ interface NBTDataType<T> {
|
||||
*/
|
||||
private inline fun <T, reified E> nbtDataType(
|
||||
crossinline decodeNMS: (E) -> T,
|
||||
crossinline writeToCompound: (key: String, data: T, compound: NBTTagCompound) -> Unit
|
||||
crossinline writeToCompound: (key: String, data: T, compound: NBTTagCompound) -> Unit,
|
||||
): NBTDataType<T> {
|
||||
|
||||
return object : NBTDataType<T> {
|
||||
|
||||
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)
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -28,7 +28,7 @@ fun Listener.unregister() = HandlerList.unregisterAll(this)
|
||||
inline fun <reified T : Event> Listener.register(
|
||||
priority: EventPriority = EventPriority.NORMAL,
|
||||
ignoreCancelled: Boolean = false,
|
||||
noinline executor: (Listener, Event) -> Unit
|
||||
noinline executor: (Listener, Event) -> Unit,
|
||||
) {
|
||||
pluginManager.registerEvent(T::class.java, this, priority, executor, KSpigotMainInstance, ignoreCancelled)
|
||||
}
|
||||
@@ -50,7 +50,7 @@ interface SingleListener<T : Event> : Listener {
|
||||
*/
|
||||
inline fun <reified T : Event> SingleListener<T>.register(
|
||||
priority: EventPriority = EventPriority.NORMAL,
|
||||
ignoreCancelled: Boolean = false
|
||||
ignoreCancelled: Boolean = false,
|
||||
) {
|
||||
register<T>(priority, ignoreCancelled) { _, event ->
|
||||
(event as? T)?.let { this.onEvent(it) }
|
||||
@@ -68,7 +68,7 @@ inline fun <reified T : Event> listen(
|
||||
priority: EventPriority = EventPriority.NORMAL,
|
||||
ignoreCancelled: Boolean = false,
|
||||
register: Boolean = true,
|
||||
crossinline onEvent: (event: T) -> Unit
|
||||
crossinline onEvent: (event: T) -> Unit,
|
||||
): SingleListener<T> {
|
||||
val listener = object : SingleListener<T> {
|
||||
override fun onEvent(event: T) = onEvent.invoke(event)
|
||||
|
@@ -4,7 +4,6 @@ import net.axay.kspigot.main.KSpigotMainInstance
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Entity
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
/**
|
||||
|
@@ -1,7 +1,5 @@
|
||||
package net.axay.kspigot.extensions.bukkit
|
||||
|
||||
// FROM BUNGEE COLOR
|
||||
|
||||
/**
|
||||
* Returns the corresponding Bukkit Color object.
|
||||
*/
|
||||
@@ -14,9 +12,7 @@ val net.md_5.bungee.api.ChatColor.bukkitColor
|
||||
*/
|
||||
val net.md_5.bungee.api.ChatColor.javaAwtColor: java.awt.Color
|
||||
get() = color
|
||||
|
||||
// FROM BUKKIT COLOR
|
||||
|
||||
/**
|
||||
* Returns the corresponding Bungee Color object.
|
||||
*/
|
||||
@@ -28,9 +24,7 @@ val org.bukkit.Color.bungeeColor: net.md_5.bungee.api.ChatColor
|
||||
*/
|
||||
val org.bukkit.Color.javaAwtColor: java.awt.Color
|
||||
get() = java.awt.Color(asRGB())
|
||||
|
||||
// FROM JAVA AWT COLOR
|
||||
|
||||
/**
|
||||
* Returns the corresponding Bukkit Color object.
|
||||
*/
|
||||
@@ -42,9 +36,7 @@ val java.awt.Color.bukkitColor
|
||||
*/
|
||||
val java.awt.Color.bungeeColor: net.md_5.bungee.api.ChatColor
|
||||
get() = net.md_5.bungee.api.ChatColor.of(this)
|
||||
|
||||
// FROM BUKKIT CHAT COLOR
|
||||
|
||||
/**
|
||||
* Returns the corresponding Bukkit Color object.
|
||||
*/
|
||||
|
@@ -133,7 +133,7 @@ fun Player.title(
|
||||
subText: String? = null,
|
||||
fadeIn: Int = 10,
|
||||
stay: Int = 70,
|
||||
fadeOut: Int = 20
|
||||
fadeOut: Int = 20,
|
||||
) {
|
||||
sendTitle(mainText, subText, fadeIn, stay, fadeOut)
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ fun Inventory.closeForViewers() = HashSet(viewers).forEach { it.closeInventory()
|
||||
val InventoryAction.isSimple
|
||||
get() = when (this) {
|
||||
InventoryAction.PLACE_ALL, InventoryAction.PLACE_ONE,
|
||||
InventoryAction.PICKUP_ALL, InventoryAction.PICKUP_HALF, InventoryAction.PICKUP_ONE
|
||||
InventoryAction.PICKUP_ALL, InventoryAction.PICKUP_HALF, InventoryAction.PICKUP_ONE,
|
||||
-> true
|
||||
else -> false
|
||||
}
|
||||
|
@@ -1,13 +1,13 @@
|
||||
package net.axay.kspigot.extensions.bukkit
|
||||
|
||||
import org.bukkit.inventory.meta.BookMeta
|
||||
import java.lang.StringBuilder
|
||||
|
||||
val BookMeta.content get() =
|
||||
StringBuilder().apply {
|
||||
for (it in pages) {
|
||||
if (isNotEmpty())
|
||||
append('\n')
|
||||
append(it)
|
||||
}
|
||||
}.toString()
|
||||
val BookMeta.content
|
||||
get() =
|
||||
StringBuilder().apply {
|
||||
for (it in pages) {
|
||||
if (isNotEmpty())
|
||||
append('\n')
|
||||
append(it)
|
||||
}
|
||||
}.toString()
|
@@ -40,16 +40,12 @@ val PlayerInteractEvent.clickedBlockExceptAir: Block?
|
||||
get() {
|
||||
return clickedBlock ?: kotlin.run {
|
||||
return@run if (this.action == Action.RIGHT_CLICK_AIR) {
|
||||
|
||||
val p: Player = this.player
|
||||
|
||||
// check for sight blocking entities
|
||||
for (nearbyEntity: Entity in p.getNearbyEntities(5.0, 5.0, 5.0))
|
||||
if (p.hasLineOfSight(nearbyEntity)) return@run null
|
||||
|
||||
// get first block in line of sight which is not air
|
||||
p.getLineOfSight(null, 5).find { block -> !block.type.isAir }
|
||||
|
||||
} else null
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ import org.bukkit.util.Vector
|
||||
|
||||
data class SimpleLocation2D(
|
||||
val x: Double,
|
||||
val y: Double
|
||||
val y: Double,
|
||||
) {
|
||||
constructor(x: Number, y: Number)
|
||||
: this(x.toDouble(), y.toDouble())
|
||||
@@ -19,30 +19,23 @@ data class SimpleLocation3D(
|
||||
val x: Double,
|
||||
val y: Double,
|
||||
val z: Double,
|
||||
val direction: Vector = vec(0, 0, 0)
|
||||
val direction: Vector = vec(0, 0, 0),
|
||||
) {
|
||||
|
||||
constructor(x: Number, y: Number, z: Number)
|
||||
: this(x.toDouble(), y.toDouble(), z.toDouble())
|
||||
|
||||
val chunk: SimpleChunkLocation
|
||||
get() = SimpleChunkLocation(x.toInt() shr 4, z.toInt() shr 4)
|
||||
|
||||
}
|
||||
|
||||
data class SimpleChunkLocation(
|
||||
val x: Int,
|
||||
val z: Int
|
||||
val z: Int,
|
||||
)
|
||||
|
||||
// CONVERTER
|
||||
|
||||
fun Location.toSimple() = SimpleLocation3D(x, y, z)
|
||||
fun Chunk.toSimple() = SimpleChunkLocation(x, z)
|
||||
|
||||
fun SimpleLocation3D.withWorld(world: World) = Location(world, x, y, z).apply { direction = this@withWorld.direction }
|
||||
fun SimpleChunkLocation.withWorld(world: World) = world.getChunkAt(x, z)
|
||||
|
||||
fun Vector.toSimpleLoc() = SimpleLocation3D(x, y, z)
|
||||
|
||||
fun SimpleLocation3D.toVector() = Vector(x, y, z)
|
@@ -10,21 +10,17 @@ import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class SimpleLocationPair(loc1: Location, loc2: Location) {
|
||||
|
||||
val world = loc1.worldOrException.let {
|
||||
if (it == loc2.worldOrException) it
|
||||
else throw IllegalArgumentException("The given locations worlds are not the same!")
|
||||
}
|
||||
|
||||
val minSimpleLoc = SimpleLocation3D(min(loc1.x, loc2.x), min(loc1.y, loc2.y), min(loc1.z, loc2.z))
|
||||
val maxSimpleLoc = SimpleLocation3D(max(loc1.x, loc2.x), max(loc1.y, loc2.y), max(loc1.z, loc2.z))
|
||||
|
||||
fun isInArea(
|
||||
loc: Location,
|
||||
check3d: Boolean = true,
|
||||
tolerance: Int = 0
|
||||
tolerance: Int = 0,
|
||||
): Boolean {
|
||||
|
||||
// checking world
|
||||
if (loc.world != world) return false
|
||||
|
||||
@@ -37,11 +33,9 @@ class SimpleLocationPair(loc1: Location, loc2: Location) {
|
||||
// checking y
|
||||
if (check3d) loc.y >= minSimpleLoc.y - tolerance && loc.y <= maxSimpleLoc.y + tolerance else true
|
||||
} else false
|
||||
|
||||
}
|
||||
|
||||
val touchedSimpleChunks: Set<SimpleChunkLocation> by lazy {
|
||||
|
||||
val foundChunks = HashSet<SimpleChunkLocation>()
|
||||
|
||||
(minSimpleLoc.chunk.x until maxSimpleLoc.chunk.x + 1).forEach { curX ->
|
||||
@@ -51,13 +45,10 @@ class SimpleLocationPair(loc1: Location, loc2: Location) {
|
||||
}
|
||||
|
||||
return@lazy foundChunks
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class LocationArea(loc1: Location, loc2: Location) {
|
||||
|
||||
var loc1: Location = loc1
|
||||
set(value) {
|
||||
field = value
|
||||
@@ -68,19 +59,14 @@ class LocationArea(loc1: Location, loc2: Location) {
|
||||
field = value
|
||||
simpleLocationPair = SimpleLocationPair(loc1, value)
|
||||
}
|
||||
|
||||
var simpleLocationPair = SimpleLocationPair(loc1, loc2); private set
|
||||
|
||||
val world: World get() = simpleLocationPair.world
|
||||
val minLoc: Location get() = simpleLocationPair.minSimpleLoc.withWorld(simpleLocationPair.world)
|
||||
val maxLoc: Location get() = simpleLocationPair.maxSimpleLoc.withWorld(simpleLocationPair.world)
|
||||
|
||||
val touchedChunks: Set<Chunk> get() = simpleLocationPair.touchedSimpleChunks.mapTo(HashSet()) { it.withWorld(world) }
|
||||
|
||||
fun isInArea(
|
||||
loc: Location,
|
||||
check3d: Boolean = true,
|
||||
tolerance: Int = 0
|
||||
tolerance: Int = 0,
|
||||
) = simpleLocationPair.isInArea(loc, check3d, tolerance)
|
||||
|
||||
}
|
@@ -36,15 +36,10 @@ infix fun Location.reduceZ(distance: Number) = subtract(0.0, 0.0, distance)
|
||||
infix fun Location.reduceXY(distance: Number) = subtract(distance, distance, 0.0)
|
||||
infix fun Location.reduceYZ(distance: Number) = subtract(0.0, distance, distance)
|
||||
infix fun Location.reduceXZ(distance: Number) = subtract(distance, 0.0, distance)
|
||||
|
||||
// extensions
|
||||
|
||||
fun Location.add(x: Number, y: Number, z: Number) = add(x.toDouble(), y.toDouble(), z.toDouble())
|
||||
|
||||
fun Location.subtract(x: Number, y: Number, z: Number) = subtract(x.toDouble(), y.toDouble(), z.toDouble())
|
||||
|
||||
val Location.blockLoc: Location get() = Location(world, blockX.toDouble(), blockY.toDouble(), blockZ.toDouble())
|
||||
|
||||
infix fun Location.relationTo(loc: Location) = this.subtract(loc).toSimple()
|
||||
|
||||
// operator functions
|
||||
@@ -88,11 +83,9 @@ infix fun Location.increase(loc: Location) = add(loc)
|
||||
infix fun Location.reduce(loc: Location) = subtract(loc)
|
||||
infix fun Location.increase(loc: SimpleLocation3D) = add(loc.x, loc.y, loc.z)
|
||||
infix fun Location.reduce(loc: SimpleLocation3D) = subtract(loc.x, loc.y, loc.z)
|
||||
|
||||
/*
|
||||
* VECTOR
|
||||
*/
|
||||
|
||||
val Vector.isFinite: Boolean get() = x.isFinite() && y.isFinite() && z.isFinite()
|
||||
|
||||
// fast construct
|
||||
|
@@ -18,13 +18,11 @@ fun buildCounterMessageCallback(
|
||||
secondPlural: String = "s",
|
||||
hourSingular: String = hourPlural,
|
||||
minuteSingular: String = minutePlural,
|
||||
secondSingular: String = secondPlural
|
||||
secondSingular: String = secondPlural,
|
||||
): (Long) -> String = { curSeconds ->
|
||||
|
||||
StringBuilder().apply {
|
||||
if (beforeTime != null)
|
||||
append(beforeTime)
|
||||
|
||||
val hourTime = (curSeconds / 3600)
|
||||
val minuteTime = ((curSeconds % 3600) / 60)
|
||||
val secondsTime = (curSeconds % 60)
|
||||
@@ -46,14 +44,13 @@ fun buildCounterMessageCallback(
|
||||
if (afterTime != null)
|
||||
append(afterTime)
|
||||
}.toString()
|
||||
|
||||
}
|
||||
|
||||
class GamePhase(
|
||||
val length: Long,
|
||||
val start: (() -> Unit)?,
|
||||
val end: (() -> Unit)?,
|
||||
val counterMessage: ((secondsLeft: Long) -> String)?
|
||||
val counterMessage: ((secondsLeft: Long) -> String)?,
|
||||
) {
|
||||
fun startIt(phaseQueue: MutableList<GamePhase>) {
|
||||
start?.invoke()
|
||||
@@ -61,21 +58,17 @@ class GamePhase(
|
||||
period = 20,
|
||||
howOften = (length / 20) + 1,
|
||||
endCallback = {
|
||||
|
||||
end?.invoke()
|
||||
|
||||
if (phaseQueue.isNotEmpty())
|
||||
phaseQueue.removeAt(0).startIt(phaseQueue)
|
||||
|
||||
}
|
||||
) {
|
||||
|
||||
if (counterMessage != null) {
|
||||
val currentCounter = it.counterDownToZero
|
||||
if (currentCounter?.isCounterValue == true)
|
||||
broadcast(counterMessage.invoke(currentCounter))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,22 +3,17 @@
|
||||
package net.axay.kspigot.game
|
||||
|
||||
class GamePhaseSystemBuilder {
|
||||
|
||||
private val gamePhases = mutableListOf<GamePhase>()
|
||||
fun build() = GamePhaseSystem(*gamePhases.toTypedArray())
|
||||
|
||||
fun phase(length: Long, builder: GamePhaseBuilder.() -> Unit) {
|
||||
gamePhases += GamePhaseBuilder(length).apply(builder).build()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GamePhaseBuilder(val length: Long) {
|
||||
|
||||
private var start: (() -> Unit)? = null
|
||||
private var end: (() -> Unit)? = null
|
||||
private var counterMessage: ((secondsLeft: Long) -> String)? = null
|
||||
|
||||
fun start(callback: () -> Unit) {
|
||||
start = callback
|
||||
}
|
||||
@@ -36,13 +31,12 @@ class GamePhaseBuilder(val length: Long) {
|
||||
afterTime: String? = null,
|
||||
hours: String = "h",
|
||||
minutes: String = "m",
|
||||
seconds: String = "s"
|
||||
seconds: String = "s",
|
||||
) {
|
||||
counterMessage = buildCounterMessageCallback(beforeTime, afterTime, hours, minutes, seconds)
|
||||
}
|
||||
|
||||
fun build() = GamePhase(length, start, end, counterMessage)
|
||||
|
||||
}
|
||||
|
||||
fun buildGame(builder: GamePhaseSystemBuilder.() -> Unit) = GamePhaseSystemBuilder().apply(builder).build()
|
@@ -9,8 +9,6 @@ import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
import org.bukkit.event.player.PlayerQuitEvent
|
||||
import org.bukkit.inventory.Inventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.*
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
class GUIData<T : ForInventory>(
|
||||
val guiType: GUIType<T>,
|
||||
@@ -19,13 +17,12 @@ class GUIData<T : ForInventory>(
|
||||
val defaultPage: Int,
|
||||
val transitionTo: InventoryChangeEffect?,
|
||||
val transitionFrom: InventoryChangeEffect?,
|
||||
internal val generalOnClick: ((GUIClickEvent<T>) -> Unit)?
|
||||
internal val generalOnClick: ((GUIClickEvent<T>) -> Unit)?,
|
||||
)
|
||||
|
||||
abstract class GUI<T : ForInventory>(
|
||||
val data: GUIData<T>
|
||||
val data: GUIData<T>,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Returns the instance beloning to the given player.
|
||||
* If not existing, a new instance will be created.
|
||||
@@ -42,20 +39,17 @@ abstract class GUI<T : ForInventory>(
|
||||
* all instances.
|
||||
*/
|
||||
abstract fun closeGUI()
|
||||
|
||||
protected fun unregisterAndClose() {
|
||||
getAllInstances().forEach {
|
||||
it.bukkitInventory.closeForViewers()
|
||||
it.unregister()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GUIShared<T : ForInventory>(
|
||||
guiData: GUIData<T>
|
||||
guiData: GUIData<T>,
|
||||
) : GUI<T>(guiData) {
|
||||
|
||||
private var _singleInstance: GUIInstance<T>? = null
|
||||
val singleInstance
|
||||
get() = _singleInstance ?: GUIInstance(this, null).apply {
|
||||
@@ -64,29 +58,23 @@ class GUIShared<T : ForInventory>(
|
||||
}
|
||||
|
||||
override fun getInstance(player: Player) = singleInstance
|
||||
|
||||
override fun getAllInstances() = _singleInstance?.let { listOf(it) } ?: emptyList()
|
||||
|
||||
override fun closeGUI() {
|
||||
unregisterAndClose()
|
||||
_singleInstance = null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GUIIndividual<T : ForInventory>(
|
||||
guiData: GUIData<T>,
|
||||
resetOnClose: Boolean,
|
||||
resetOnQuit: Boolean
|
||||
resetOnQuit: Boolean,
|
||||
) : GUI<T>(guiData) {
|
||||
|
||||
private val playerInstances = HashMap<Player, GUIInstance<T>>()
|
||||
|
||||
override fun getInstance(player: Player) =
|
||||
playerInstances[player] ?: createInstance(player)
|
||||
|
||||
override fun getAllInstances() = playerInstances.values
|
||||
|
||||
private fun createInstance(player: Player) =
|
||||
GUIInstance(this, player).apply {
|
||||
playerInstances[player] = this
|
||||
@@ -94,14 +82,12 @@ class GUIIndividual<T : ForInventory>(
|
||||
}
|
||||
|
||||
fun deleteInstance(player: Player) = playerInstances.remove(player)?.unregister()
|
||||
|
||||
override fun closeGUI() {
|
||||
unregisterAndClose()
|
||||
playerInstances.clear()
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
if (resetOnClose) {
|
||||
listen<InventoryCloseEvent> {
|
||||
deleteInstance(it.player as? Player ?: return@listen)
|
||||
@@ -113,22 +99,16 @@ class GUIIndividual<T : ForInventory>(
|
||||
deleteInstance(it.player)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GUIInstance<T : ForInventory>(
|
||||
val gui: GUI<T>,
|
||||
holder: Player?
|
||||
holder: Player?,
|
||||
) {
|
||||
|
||||
internal val bukkitInventory = gui.data.guiType.createBukkitInv(holder, gui.data.title)
|
||||
|
||||
private val currentElements = HashSet<GUIElement<*>>()
|
||||
|
||||
internal var isInMove: Boolean = false
|
||||
|
||||
var currentPageInt: Int = gui.data.defaultPage; private set
|
||||
val currentPage
|
||||
get() = getPage(currentPageInt)
|
||||
@@ -143,15 +123,12 @@ class GUIInstance<T : ForInventory>(
|
||||
}
|
||||
|
||||
internal fun loadPageUnsafe(page: GUIPage<*>, offsetHorizontally: Int = 0, offsetVertically: Int = 0) {
|
||||
|
||||
val ifOffset = offsetHorizontally != 0 || offsetVertically != 0
|
||||
|
||||
if (!ifOffset) {
|
||||
|
||||
// unregister this inv from all elements on the previous page
|
||||
currentElements.forEach { it.stopUsing(this) }
|
||||
currentElements.clear()
|
||||
|
||||
// register this inv for all new elements
|
||||
HashSet(page.slots.values).forEach {
|
||||
if (it is GUIElement) {
|
||||
@@ -161,23 +138,18 @@ class GUIInstance<T : ForInventory>(
|
||||
}
|
||||
|
||||
currentPageInt = page.number
|
||||
|
||||
}
|
||||
|
||||
loadContent(page.slots, offsetHorizontally, offsetVertically)
|
||||
|
||||
}
|
||||
|
||||
internal fun loadContent(
|
||||
content: Map<Int, GUISlot<*>>,
|
||||
offsetHorizontally: Int = 0,
|
||||
offsetVertically: Int = 0
|
||||
offsetVertically: Int = 0,
|
||||
) {
|
||||
|
||||
val ifOffset = offsetHorizontally != 0 || offsetVertically != 0
|
||||
|
||||
val dimensions = gui.data.guiType.dimensions
|
||||
|
||||
// clear the space which will be redefined
|
||||
if (ifOffset) {
|
||||
dimensions.invSlots.forEach {
|
||||
@@ -185,13 +157,10 @@ class GUIInstance<T : ForInventory>(
|
||||
if (slotToClear != null) bukkitInventory.clear(slotToClear)
|
||||
}
|
||||
} else bukkitInventory.clear()
|
||||
|
||||
// render the given content
|
||||
content.forEach {
|
||||
|
||||
val slot = it.value
|
||||
if (slot is GUIElement) {
|
||||
|
||||
if (ifOffset) {
|
||||
val invSlot = InventorySlot.fromRealSlot(it.key, dimensions)
|
||||
if (invSlot != null) {
|
||||
@@ -199,11 +168,8 @@ class GUIInstance<T : ForInventory>(
|
||||
if (offsetSlot != null) bukkitInventory.setItem(offsetSlot, slot.getItemStack(offsetSlot))
|
||||
}
|
||||
} else bukkitInventory.setItem(it.key, slot.getItemStack(it.key))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,14 +184,11 @@ class GUIInstance<T : ForInventory>(
|
||||
* GUI anymore.
|
||||
*/
|
||||
fun unregister() {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
GUIHolder.unregister(this as GUIInstance<ForInventory>)
|
||||
|
||||
// unregister this inv from all elements
|
||||
currentElements.forEach { it.stopUsing(this) }
|
||||
currentElements.clear()
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,5 +222,4 @@ class GUIInstance<T : ForInventory>(
|
||||
if (!isInMove)
|
||||
loadPage(currentPage)
|
||||
}
|
||||
|
||||
}
|
@@ -14,9 +14,8 @@ fun <T : ForInventory> kSpigotGUI(
|
||||
|
||||
class GUIBuilder<T : ForInventory>(
|
||||
val type: GUIType<T>,
|
||||
private val guiCreator: GUICreator<T>
|
||||
private val guiCreator: GUICreator<T>,
|
||||
) {
|
||||
|
||||
/**
|
||||
* The title of this GUI.
|
||||
* This title will be visible for every page of
|
||||
@@ -42,9 +41,7 @@ class GUIBuilder<T : ForInventory>(
|
||||
* GUI instance.
|
||||
*/
|
||||
var defaultPage = 1
|
||||
|
||||
private val guiSlots = HashMap<Int, GUIPage<T>>()
|
||||
|
||||
private var onClickElement: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
|
||||
/**
|
||||
@@ -67,21 +64,16 @@ class GUIBuilder<T : ForInventory>(
|
||||
internal fun build() = guiCreator.createInstance(
|
||||
GUIData(type, title, guiSlots, defaultPage, transitionTo, transitionFrom, onClickElement)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
class GUIPageBuilder<T : ForInventory>(
|
||||
private val type: GUIType<T>,
|
||||
val page: Int
|
||||
val page: Int,
|
||||
) {
|
||||
|
||||
private val guiSlots = HashMap<Int, GUISlot<T>>()
|
||||
|
||||
var transitionTo: PageChangeEffect? = null
|
||||
var transitionFrom: PageChangeEffect? = null
|
||||
|
||||
internal fun build() = GUIPage(page, guiSlots, transitionTo, transitionFrom)
|
||||
|
||||
private fun defineSlots(slots: InventorySlotCompound<T>, element: GUISlot<T>) =
|
||||
slots.withInvType(type).forEach { curSlot ->
|
||||
curSlot.realSlotIn(type.dimensions)?.let { guiSlots[it] = element }
|
||||
@@ -118,7 +110,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
slots: InventorySlotCompound<T>,
|
||||
icon: ItemStack,
|
||||
toPage: Int,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null,
|
||||
) = pageChanger(slots, icon, toPage, null, onChange)
|
||||
|
||||
/**
|
||||
@@ -130,7 +122,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
icon: ItemStack,
|
||||
toPage: Int,
|
||||
shouldChange: ((GUIClickEvent<T>) -> Boolean)? = null,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null,
|
||||
) = defineSlots(
|
||||
slots, GUIButtonPageChange(
|
||||
icon,
|
||||
@@ -149,7 +141,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
fun previousPage(
|
||||
slots: InventorySlotCompound<T>,
|
||||
icon: ItemStack,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null,
|
||||
) = previousPage(slots, icon, null, onChange)
|
||||
|
||||
/**
|
||||
@@ -161,7 +153,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
slots: InventorySlotCompound<T>,
|
||||
icon: ItemStack,
|
||||
shouldChange: ((GUIClickEvent<T>) -> Boolean)? = null,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null,
|
||||
) = defineSlots(
|
||||
slots, GUIButtonPageChange(
|
||||
icon,
|
||||
@@ -180,7 +172,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
fun nextPage(
|
||||
slots: InventorySlotCompound<T>,
|
||||
icon: ItemStack,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null,
|
||||
) = nextPage(slots, icon, null, onChange)
|
||||
|
||||
/**
|
||||
@@ -192,7 +184,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
slots: InventorySlotCompound<T>,
|
||||
icon: ItemStack,
|
||||
shouldChange: ((GUIClickEvent<T>) -> Boolean)? = null,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null,
|
||||
) = defineSlots(
|
||||
slots, GUIButtonPageChange(
|
||||
icon,
|
||||
@@ -211,7 +203,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
icon: ItemStack,
|
||||
newGUI: () -> GUI<*>,
|
||||
newPage: Int? = null,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)? = null,
|
||||
) = defineSlots(
|
||||
slots, GUIButtonInventoryChange(
|
||||
icon,
|
||||
@@ -235,7 +227,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
*/
|
||||
fun <E> createCompound(
|
||||
iconGenerator: (E) -> ItemStack,
|
||||
onClick: ((clickEvent: GUIClickEvent<T>, element: E) -> Unit)? = null
|
||||
onClick: ((clickEvent: GUIClickEvent<T>, element: E) -> Unit)? = null,
|
||||
) = GUISpaceCompound(type, iconGenerator, onClick)
|
||||
|
||||
/**
|
||||
@@ -244,7 +236,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
*/
|
||||
fun <E> compoundSpace(
|
||||
slots: InventorySlotCompound<T>,
|
||||
compound: GUISpaceCompound<T, E>
|
||||
compound: GUISpaceCompound<T, E>,
|
||||
) {
|
||||
compound.addSlots(slots)
|
||||
defineSlots(
|
||||
@@ -264,14 +256,11 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
*/
|
||||
fun createSimpleRectCompound(
|
||||
fromSlot: SingleInventorySlot<out T>,
|
||||
toSlot: SingleInventorySlot<out T>
|
||||
toSlot: SingleInventorySlot<out T>,
|
||||
) = createRectCompound<GUICompoundElement<T>>(
|
||||
|
||||
fromSlot, toSlot,
|
||||
|
||||
iconGenerator = { it.icon },
|
||||
onClick = { clickEvent, element -> element.onClick?.invoke(clickEvent) }
|
||||
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -283,7 +272,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
fromSlot: SingleInventorySlot<out T>,
|
||||
toSlot: SingleInventorySlot<out T>,
|
||||
iconGenerator: (E) -> ItemStack,
|
||||
onClick: ((clickEvent: GUIClickEvent<T>, element: E) -> Unit)? = null
|
||||
onClick: ((clickEvent: GUIClickEvent<T>, element: E) -> Unit)? = null,
|
||||
): GUIRectSpaceCompound<T, E> {
|
||||
val rectSlotCompound = fromSlot rectTo toSlot
|
||||
return GUIRectSpaceCompound(
|
||||
@@ -310,7 +299,7 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
compound: GUISpaceCompound<T, *>,
|
||||
scrollDistance: Int = 1,
|
||||
scrollTimes: Int = 1,
|
||||
reverse: Boolean = false
|
||||
reverse: Boolean = false,
|
||||
) = defineSlots(
|
||||
slots,
|
||||
GUISpaceCompoundScrollButton(icon, compound, scrollDistance.absoluteValue, scrollTimes, reverse)
|
||||
@@ -325,10 +314,9 @@ class GUIPageBuilder<T : ForInventory>(
|
||||
icon: ItemStack,
|
||||
compound: GUIRectSpaceCompound<T, *>,
|
||||
scrollTimes: Int = 1,
|
||||
reverse: Boolean = false
|
||||
reverse: Boolean = false,
|
||||
) = defineSlots(
|
||||
slots,
|
||||
GUISpaceCompoundScrollButton(icon, compound, scrollTimes, reverse)
|
||||
)
|
||||
|
||||
}
|
||||
|
@@ -6,5 +6,5 @@ import org.bukkit.event.inventory.InventoryClickEvent
|
||||
class GUIClickEvent<T : ForInventory>(
|
||||
val bukkitEvent: InventoryClickEvent,
|
||||
val guiInstance: GUIInstance<T>,
|
||||
val player: Player
|
||||
val player: Player,
|
||||
)
|
@@ -10,7 +10,7 @@ class SharedGUICreator<T : ForInventory> : GUICreator<T>() {
|
||||
|
||||
class IndividualGUICreator<T : ForInventory>(
|
||||
private val resetOnClose: Boolean = true,
|
||||
private val resetOnQuit: Boolean = true
|
||||
private val resetOnQuit: Boolean = true,
|
||||
) : GUICreator<T>() {
|
||||
override fun createInstance(guiData: GUIData<T>) = GUIIndividual(guiData, resetOnClose, resetOnQuit)
|
||||
}
|
@@ -5,21 +5,15 @@ import org.bukkit.inventory.ItemStack
|
||||
abstract class GUISlot<T : ForInventory> {
|
||||
abstract fun onClick(clickEvent: GUIClickEvent<T>)
|
||||
}
|
||||
|
||||
// ELEMENT
|
||||
|
||||
abstract class GUIElement<T : ForInventory> : GUISlot<T>() {
|
||||
|
||||
abstract fun getItemStack(slot: Int): ItemStack
|
||||
|
||||
final override fun onClick(clickEvent: GUIClickEvent<T>) {
|
||||
clickEvent.guiInstance.gui.data.generalOnClick?.invoke(clickEvent)
|
||||
onClickElement(clickEvent)
|
||||
}
|
||||
|
||||
protected abstract fun onClickElement(clickEvent: GUIClickEvent<T>)
|
||||
|
||||
internal open fun startUsing(gui: GUIInstance<*>) {}
|
||||
internal open fun stopUsing(gui: GUIInstance<*>) {}
|
||||
|
||||
}
|
@@ -9,10 +9,8 @@ fun Player.openGUI(gui: GUI<*>, page: Int? = null): InventoryView? {
|
||||
}
|
||||
|
||||
internal fun Player.openGUIInstance(guiInstance: GUIInstance<*>, page: Int? = null): InventoryView? {
|
||||
|
||||
if (page != null)
|
||||
guiInstance.loadPageUnsafe(page)
|
||||
|
||||
return openInventory(guiInstance.bukkitInventory)
|
||||
|
||||
}
|
@@ -7,9 +7,7 @@ import org.bukkit.event.inventory.*
|
||||
import org.bukkit.inventory.Inventory
|
||||
|
||||
object GUIHolder : AutoCloseable {
|
||||
|
||||
private val registered = HashMap<Inventory, GUIInstance<ForInventory>>()
|
||||
|
||||
fun register(guiInstance: GUIInstance<ForInventory>) {
|
||||
registered[guiInstance.bukkitInventory] = guiInstance
|
||||
}
|
||||
@@ -19,13 +17,9 @@ object GUIHolder : AutoCloseable {
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
listen<InventoryClickEvent> {
|
||||
|
||||
val clickedInv = it.clickedInventory ?: return@listen
|
||||
|
||||
val gui = registered[clickedInv] ?: return@listen
|
||||
|
||||
val player = it.playerOrCancel ?: return@listen
|
||||
|
||||
if (gui.isInMove) {
|
||||
@@ -39,26 +33,20 @@ object GUIHolder : AutoCloseable {
|
||||
}
|
||||
else
|
||||
it.isCancelled = true
|
||||
|
||||
}
|
||||
|
||||
listen<InventoryDragEvent> {
|
||||
|
||||
val inv = it.inventory
|
||||
val gui = registered[inv] ?: return@listen
|
||||
|
||||
val player = it.playerOrCancel ?: return@listen
|
||||
|
||||
var ifCancel = false
|
||||
|
||||
for (slotIndex in it.inventorySlots) {
|
||||
|
||||
val slot = gui.currentPage.slots[slotIndex]
|
||||
if (slot == null) {
|
||||
ifCancel = true
|
||||
break
|
||||
}
|
||||
|
||||
val clickEvent = InventoryClickEvent(
|
||||
it.view,
|
||||
it.view.getSlotType(slotIndex),
|
||||
@@ -73,26 +61,21 @@ object GUIHolder : AutoCloseable {
|
||||
ifCancel = true
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ifCancel)
|
||||
it.isCancelled = true
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
registered.keys.forEach { it.closeForViewers() }
|
||||
registered.clear()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val InventoryAction.isGUIClick
|
||||
get() = this == InventoryAction.PICKUP_ALL || this == InventoryAction.PICKUP_HALF
|
||||
|
||||
private val InventoryInteractEvent.playerOrCancel: Player?
|
||||
get() = (whoClicked as? Player) ?: kotlin.run {
|
||||
isCancelled = true
|
||||
|
@@ -4,5 +4,5 @@ class GUIPage<T : ForInventory>(
|
||||
val number: Int,
|
||||
internal val slots: Map<Int, GUISlot<T>>,
|
||||
val transitionTo: PageChangeEffect?,
|
||||
val transitionFrom: PageChangeEffect?
|
||||
val transitionFrom: PageChangeEffect?,
|
||||
)
|
@@ -3,7 +3,6 @@ package net.axay.kspigot.gui
|
||||
import net.axay.kspigot.runnables.task
|
||||
|
||||
abstract class GUIPageChangeCalculator {
|
||||
|
||||
abstract fun calculateNewPage(currentPage: Int, pages: Collection<Int>): Int?
|
||||
|
||||
object GUIPreviousPageCalculator : GUIPageChangeCalculator() {
|
||||
@@ -19,7 +18,6 @@ abstract class GUIPageChangeCalculator {
|
||||
class GUIConsistentPageCalculator(private val toPage: Int) : GUIPageChangeCalculator() {
|
||||
override fun calculateNewPage(currentPage: Int, pages: Collection<Int>) = toPage
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class PageChangeEffect {
|
||||
@@ -31,7 +29,7 @@ enum class PageChangeEffect {
|
||||
}
|
||||
|
||||
enum class InventoryChangeEffect(
|
||||
val effect: PageChangeEffect
|
||||
val effect: PageChangeEffect,
|
||||
) {
|
||||
INSTANT(PageChangeEffect.INSTANT)
|
||||
}
|
||||
@@ -46,18 +44,14 @@ fun GUIInstance<*>.gotoPage(page: Int, overrideEffect: PageChangeEffect? = null)
|
||||
internal fun GUIInstance<*>.changePage(
|
||||
effect: PageChangeEffect,
|
||||
fromPage: GUIPage<*>,
|
||||
toPage: GUIPage<*>
|
||||
toPage: GUIPage<*>,
|
||||
) {
|
||||
|
||||
val fromPageInt = fromPage.number
|
||||
val toPageInt = toPage.number
|
||||
|
||||
when (effect) {
|
||||
|
||||
PageChangeEffect.INSTANT -> loadPageUnsafe(toPage)
|
||||
|
||||
PageChangeEffect.SLIDE_HORIZONTALLY -> {
|
||||
|
||||
val width = gui.data.guiType.dimensions.width
|
||||
|
||||
changePageEffect(fromPageInt, toPageInt, width) { currentOffset, ifInverted ->
|
||||
@@ -69,11 +63,8 @@ internal fun GUIInstance<*>.changePage(
|
||||
loadPageUnsafe(toPage, offsetHorizontally = width - currentOffset)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PageChangeEffect.SLIDE_VERTICALLY -> {
|
||||
|
||||
val height = gui.data.guiType.dimensions.height
|
||||
|
||||
changePageEffect(fromPageInt, toPageInt, height) { currentOffset, ifInverted ->
|
||||
@@ -85,11 +76,8 @@ internal fun GUIInstance<*>.changePage(
|
||||
loadPageUnsafe(toPage, offsetVertically = height - currentOffset)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PageChangeEffect.SWIPE_HORIZONTALLY -> {
|
||||
|
||||
val width = gui.data.guiType.dimensions.width
|
||||
|
||||
changePageEffect(fromPageInt, toPageInt, width) { currentOffset, ifInverted ->
|
||||
@@ -99,11 +87,8 @@ internal fun GUIInstance<*>.changePage(
|
||||
loadPageUnsafe(toPage, offsetHorizontally = width - currentOffset)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PageChangeEffect.SWIPE_VERTICALLY -> {
|
||||
|
||||
val height = gui.data.guiType.dimensions.height
|
||||
|
||||
changePageEffect(fromPageInt, toPageInt, height) { currentOffset, ifInverted ->
|
||||
@@ -113,16 +98,14 @@ internal fun GUIInstance<*>.changePage(
|
||||
loadPageUnsafe(toPage, offsetVertically = height - currentOffset)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal fun GUIInstance<*>.changeGUI(
|
||||
effect: InventoryChangeEffect,
|
||||
fromPage: GUIPage<*>,
|
||||
toPage: GUIPage<*>
|
||||
toPage: GUIPage<*>,
|
||||
) = changePage(effect.effect, fromPage, toPage)
|
||||
|
||||
private inline fun changePageEffect(
|
||||
@@ -131,20 +114,15 @@ private inline fun changePageEffect(
|
||||
doFor: Int,
|
||||
crossinline effect: (currentOffset: Int, ifInverted: Boolean) -> Unit,
|
||||
) {
|
||||
|
||||
val ifInverted = fromPage >= toPage
|
||||
|
||||
var currentOffset = 1
|
||||
task(
|
||||
sync = true,
|
||||
period = 1,
|
||||
howOften = doFor.toLong()
|
||||
) {
|
||||
|
||||
effect.invoke(currentOffset, ifInverted)
|
||||
|
||||
currentOffset++
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,11 +5,8 @@ package net.axay.kspigot.gui
|
||||
import net.axay.kspigot.languageextensions.kotlinextensions.MinMaxPair
|
||||
|
||||
// INVENTORY
|
||||
|
||||
data class InventoryDimensions(val width: Int, val height: Int) {
|
||||
|
||||
val slotAmount = width * height
|
||||
|
||||
val invSlots by lazy {
|
||||
ArrayList<InventorySlot>().apply {
|
||||
(1..height).forEach { row ->
|
||||
@@ -19,7 +16,6 @@ data class InventoryDimensions(val width: Int, val height: Int) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val invSlotsWithRealSlots by lazy {
|
||||
HashMap<InventorySlot, Int>().apply {
|
||||
invSlots.forEach { curSlot ->
|
||||
@@ -27,15 +23,10 @@ data class InventoryDimensions(val width: Int, val height: Int) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val realSlots by lazy { invSlotsWithRealSlots.values }
|
||||
|
||||
}
|
||||
|
||||
// SLOTS
|
||||
|
||||
data class InventorySlot(val row: Int, val slotInRow: Int) : Comparable<InventorySlot> {
|
||||
|
||||
companion object {
|
||||
fun fromRealSlot(realSlot: Int, dimensions: InventoryDimensions) =
|
||||
dimensions.invSlotsWithRealSlots.toList().find { it.second == realSlot }?.first
|
||||
@@ -65,28 +56,21 @@ data class InventorySlot(val row: Int, val slotInRow: Int) : Comparable<Inventor
|
||||
row + offsetVertically,
|
||||
slotInRow + offsetHorizontally
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
interface InventorySlotCompound<out T : ForInventory> {
|
||||
|
||||
fun withInvType(invType: GUIType<T>): Collection<InventorySlot>
|
||||
|
||||
fun realSlotsWithInvType(invType: GUIType<T>) =
|
||||
withInvType(invType).mapNotNull { it.realSlotIn(invType.dimensions) }
|
||||
|
||||
}
|
||||
|
||||
open class SingleInventorySlot<T : ForInventory> internal constructor(
|
||||
val inventorySlot: InventorySlot
|
||||
val inventorySlot: InventorySlot,
|
||||
) : InventorySlotCompound<T> {
|
||||
|
||||
constructor(row: Int, slotInRow: Int) : this(InventorySlot(row, slotInRow))
|
||||
|
||||
private val slotAsList = listOf(inventorySlot)
|
||||
|
||||
override fun withInvType(invType: GUIType<T>) = slotAsList
|
||||
|
||||
}
|
||||
|
||||
internal enum class InventorySlotRangeType {
|
||||
@@ -95,14 +79,10 @@ internal enum class InventorySlotRangeType {
|
||||
}
|
||||
|
||||
class InventorySlotRange<out T : ForInventory> internal constructor(
|
||||
|
||||
startSlot: SingleInventorySlot<out T>,
|
||||
endSlot: SingleInventorySlot<out T>,
|
||||
|
||||
private val type: InventorySlotRangeType
|
||||
|
||||
private val type: InventorySlotRangeType,
|
||||
) : InventorySlotCompound<T>, ClosedRange<InventorySlot> {
|
||||
|
||||
override val start: InventorySlot
|
||||
override val endInclusive: InventorySlot
|
||||
|
||||
@@ -114,7 +94,6 @@ class InventorySlotRange<out T : ForInventory> internal constructor(
|
||||
|
||||
override fun withInvType(invType: GUIType<T>) = LinkedHashSet<InventorySlot>().apply {
|
||||
when (type) {
|
||||
|
||||
InventorySlotRangeType.RECTANGLE -> {
|
||||
// all possible combinations between the two slots
|
||||
// -> form a rectangle
|
||||
@@ -122,7 +101,6 @@ class InventorySlotRange<out T : ForInventory> internal constructor(
|
||||
for (slotInRow in start.slotInRow..endInclusive.slotInRow)
|
||||
this += InventorySlot(row, slotInRow)
|
||||
}
|
||||
|
||||
InventorySlotRangeType.LINEAR -> {
|
||||
if (endInclusive.row > start.row) {
|
||||
// from start --->| to end of row
|
||||
@@ -142,10 +120,8 @@ class InventorySlotRange<out T : ForInventory> internal constructor(
|
||||
this += InventorySlot(start.row, slotInRow)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,33 +139,27 @@ infix fun <T : ForInventory> SingleInventorySlot<out T>.rectTo(slot: SingleInven
|
||||
InventorySlotRange(this, slot, InventorySlotRangeType.RECTANGLE)
|
||||
|
||||
class InventoryRowSlots<T : ForInventory> internal constructor(
|
||||
val row: Int
|
||||
val row: Int,
|
||||
) : InventorySlotCompound<T> {
|
||||
|
||||
override fun withInvType(invType: GUIType<T>) = HashSet<InventorySlot>().apply {
|
||||
for (slotInRow in 1..invType.dimensions.width)
|
||||
this += InventorySlot(row, slotInRow)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InventoryColumnSlots<T : ForInventory> internal constructor(
|
||||
val column: Int
|
||||
val column: Int,
|
||||
) : InventorySlotCompound<T> {
|
||||
|
||||
override fun withInvType(invType: GUIType<T>) = HashSet<InventorySlot>().apply {
|
||||
for (row in 1..invType.dimensions.height)
|
||||
this += InventorySlot(row, column)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InventoryBorderSlots<T : ForInventory> internal constructor(
|
||||
val padding: Int
|
||||
val padding: Int,
|
||||
) : InventorySlotCompound<T> {
|
||||
|
||||
override fun withInvType(invType: GUIType<T>) = HashSet<InventorySlot>().apply {
|
||||
|
||||
val dimensions = invType.dimensions
|
||||
|
||||
for (currentPadding in 0 until padding) {
|
||||
@@ -202,39 +172,30 @@ class InventoryBorderSlots<T : ForInventory> internal constructor(
|
||||
this += InventorySlot(row, dimensions.width)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InventoryCornerSlots<T : ForInventory> internal constructor(
|
||||
val ifBottomLeft: Boolean = false,
|
||||
val ifBottomRight: Boolean = false,
|
||||
val ifTopLeft: Boolean = false,
|
||||
val ifTopRight: Boolean = false
|
||||
val ifTopRight: Boolean = false,
|
||||
) : InventorySlotCompound<T> {
|
||||
|
||||
override fun withInvType(invType: GUIType<T>) = HashSet<InventorySlot>().apply {
|
||||
|
||||
val dimensions = invType.dimensions
|
||||
|
||||
if (ifBottomLeft) this += InventorySlot(1, 1)
|
||||
if (ifBottomRight) this += InventorySlot(1, dimensions.width)
|
||||
if (ifTopLeft) this += InventorySlot(dimensions.height, 1)
|
||||
if (ifTopRight) this += InventorySlot(dimensions.height, dimensions.width)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class InventoryAllSlots<T : ForInventory> : InventorySlotCompound<T> {
|
||||
class InventoryAllSlots<T : ForInventory> : InventorySlotCompound<T> {
|
||||
override fun withInvType(invType: GUIType<T>) = invType.dimensions.invSlots
|
||||
}
|
||||
|
||||
// SLOT TYPE SAFETY
|
||||
|
||||
// COLUMNS
|
||||
|
||||
interface ForColumnOne : ForInventoryWidthThree, ForInventoryWidthFive, ForInventoryWidthNine
|
||||
interface ForColumnTwo : ForInventoryWidthThree, ForInventoryWidthFive, ForInventoryWidthNine
|
||||
interface ForColumnThree : ForInventoryWidthThree, ForInventoryWidthFive, ForInventoryWidthNine
|
||||
@@ -244,9 +205,7 @@ interface ForColumnSix : ForInventoryWidthNine
|
||||
interface ForColumnSeven : ForInventoryWidthNine
|
||||
interface ForColumnEight : ForInventoryWidthNine
|
||||
interface ForColumnNine : ForInventoryWidthNine
|
||||
|
||||
// ROWS
|
||||
|
||||
interface ForRowOne : ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine, ForInventoryFourByNine,
|
||||
ForInventoryFiveByNine, ForInventorySixByNine
|
||||
|
||||
@@ -273,9 +232,7 @@ interface ForRowThreeSlotOneToThree : ForRowThree, ForInventoryThreeByThree
|
||||
interface ForCompleteRowOne : ForRowOne, ForRowOneSlotOneToThree, ForRowOneSlotFourToFive
|
||||
interface ForCompleteRowTwo : ForRowTwo, ForRowTwoSlotOneToThree
|
||||
interface ForCompleteRowThree : ForRowThree, ForRowThreeSlotOneToThree
|
||||
|
||||
object Slots {
|
||||
|
||||
// ROW ONE
|
||||
val RowOneSlotOne = SingleInventorySlot<ForRowOneSlotOneToThree>(1, 1)
|
||||
val RowOneSlotTwo = SingleInventorySlot<ForRowOneSlotOneToThree>(1, 2)
|
||||
@@ -380,5 +337,4 @@ object Slots {
|
||||
|
||||
// ALL
|
||||
val All = InventoryAllSlots<ForEveryInventory>()
|
||||
|
||||
}
|
@@ -9,11 +9,9 @@ import org.bukkit.inventory.InventoryHolder
|
||||
|
||||
class GUIType<in T : ForInventory>(
|
||||
val dimensions: InventoryDimensions,
|
||||
val bukkitType: InventoryType? = null
|
||||
val bukkitType: InventoryType? = null,
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
||||
val ONE_BY_NINE = GUIType<ForInventoryOneByNine>(InventoryDimensions(9, 1))
|
||||
val TWO_BY_NINE = GUIType<ForInventoryTwoByNine>(InventoryDimensions(9, 2))
|
||||
val THREE_BY_NINE = GUIType<ForInventoryThreeByNine>(InventoryDimensions(9, 3))
|
||||
@@ -24,7 +22,6 @@ class GUIType<in T : ForInventory>(
|
||||
GUIType<ForInventoryOneByFive>(InventoryDimensions(5, 1), bukkitType = InventoryType.HOPPER)
|
||||
val THREE_BY_THREE =
|
||||
GUIType<ForInventoryThreeByThree>(InventoryDimensions(3, 3), bukkitType = InventoryType.DROPPER)
|
||||
|
||||
}
|
||||
|
||||
fun createBukkitInv(holder: InventoryHolder? = null, title: String? = null): Inventory {
|
||||
@@ -34,13 +31,9 @@ class GUIType<in T : ForInventory>(
|
||||
else -> Bukkit.createInventory(holder, dimensions.slotAmount, realTitle)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// INVENTORY TYPE SAFETY
|
||||
|
||||
interface ForInventory
|
||||
|
||||
interface ForInventoryThreeByThree : ForInventoryThreeByNine
|
||||
interface ForInventoryOneByFive : ForInventoryOneByNine
|
||||
interface ForInventoryOneByNine : ForInventoryTwoByNine
|
||||
@@ -49,7 +42,6 @@ interface ForInventoryThreeByNine : ForInventoryFourByNine
|
||||
interface ForInventoryFourByNine : ForInventoryFiveByNine
|
||||
interface ForInventoryFiveByNine : ForInventorySixByNine
|
||||
interface ForInventorySixByNine : ForInventory
|
||||
|
||||
interface ForEveryInventory
|
||||
: ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine,
|
||||
ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine,
|
||||
|
@@ -9,12 +9,9 @@ open class GUIButton<T : ForInventory>(
|
||||
private val icon: ItemStack,
|
||||
private val action: (GUIClickEvent<T>) -> Unit,
|
||||
) : GUIElement<T>() {
|
||||
|
||||
final override fun getItemStack(slot: Int) = icon
|
||||
|
||||
override fun onClickElement(clickEvent: GUIClickEvent<T>) {
|
||||
clickEvent.bukkitEvent.isCancelled = true
|
||||
action(clickEvent)
|
||||
}
|
||||
|
||||
}
|
@@ -7,14 +7,11 @@ class GUIButtonInventoryChange<T : ForInventory>(
|
||||
icon: ItemStack,
|
||||
changeToGUICallback: () -> GUI<*>,
|
||||
changeToPageInt: Int?,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)?
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)?,
|
||||
) : GUIButton<T>(icon, {
|
||||
|
||||
val changeToGUI = changeToGUICallback.invoke().getInstance(it.player)
|
||||
|
||||
val effect = (changeToGUI.gui.data.transitionTo ?: it.guiInstance.gui.data.transitionFrom)
|
||||
?: InventoryChangeEffect.INSTANT
|
||||
|
||||
val changeToPage = changeToGUI.getPage(changeToPageInt) ?: changeToGUI.currentPage
|
||||
|
||||
changeToGUI.changeGUI(effect, it.guiInstance.currentPage, changeToPage)
|
||||
@@ -22,5 +19,4 @@ class GUIButtonInventoryChange<T : ForInventory>(
|
||||
it.player.openGUIInstance(changeToGUI)
|
||||
|
||||
onChange?.invoke(it)
|
||||
|
||||
})
|
@@ -7,9 +7,8 @@ class GUIButtonPageChange<T : ForInventory>(
|
||||
icon: ItemStack,
|
||||
calculator: GUIPageChangeCalculator,
|
||||
shouldChange: ((GUIClickEvent<T>) -> Boolean)?,
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)?
|
||||
onChange: ((GUIClickEvent<T>) -> Unit)?,
|
||||
) : GUIButton<T>(icon, {
|
||||
|
||||
val currentPage = it.guiInstance.currentPage
|
||||
val newPage = it.guiInstance.getPage(
|
||||
calculator.calculateNewPage(
|
||||
@@ -18,7 +17,6 @@ class GUIButtonPageChange<T : ForInventory>(
|
||||
)
|
||||
)
|
||||
if (newPage != null) {
|
||||
|
||||
val changePage = shouldChange?.invoke(it) ?: true
|
||||
|
||||
if (changePage) {
|
||||
@@ -29,5 +27,4 @@ class GUIButtonPageChange<T : ForInventory>(
|
||||
onChange?.invoke(it)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
@@ -6,13 +6,10 @@ import net.axay.kspigot.gui.GUIElement
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class GUIPlaceholder<T : ForInventory>(
|
||||
private val icon: ItemStack
|
||||
private val icon: ItemStack,
|
||||
) : GUIElement<T>() {
|
||||
|
||||
override fun getItemStack(slot: Int) = icon
|
||||
|
||||
override fun onClickElement(clickEvent: GUIClickEvent<T>) {
|
||||
clickEvent.bukkitEvent.isCancelled = true
|
||||
}
|
||||
|
||||
}
|
@@ -7,78 +7,58 @@ import org.bukkit.Material
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class GUISpaceCompoundElement<T : ForInventory, E> internal constructor(
|
||||
private val compound: AbstractGUISpaceCompound<T, E>
|
||||
private val compound: AbstractGUISpaceCompound<T, E>,
|
||||
) : GUIElement<T>() {
|
||||
|
||||
override fun getItemStack(slot: Int) = compound.getItemStack(slot)
|
||||
|
||||
override fun onClickElement(clickEvent: GUIClickEvent<T>) {
|
||||
compound.onClickElement(clickEvent)
|
||||
}
|
||||
|
||||
// the following two methods register and unregister the instance
|
||||
// for each compound element, but that is ok because it gets
|
||||
// added/removed to/from a HashSet
|
||||
|
||||
override fun startUsing(gui: GUIInstance<*>) = compound.registerGUI(gui)
|
||||
|
||||
override fun stopUsing(gui: GUIInstance<*>) = compound.unregisterGUI(gui)
|
||||
|
||||
}
|
||||
|
||||
class GUIRectSpaceCompound<T : ForInventory, E>(
|
||||
invType: GUIType<T>,
|
||||
iconGenerator: (E) -> ItemStack,
|
||||
onClick: ((GUIClickEvent<T>, E) -> Unit)?,
|
||||
internal val compoundWidth: Int
|
||||
internal val compoundWidth: Int,
|
||||
) : AbstractGUISpaceCompound<T, E>(invType, iconGenerator, onClick) {
|
||||
|
||||
override fun handleScrollEndReached(newProgress: Int, internalSlotsSize: Int, contentSize: Int) =
|
||||
(internalSlotsSize + newProgress <= contentSize + (compoundWidth - (contentSize % compoundWidth)))
|
||||
|
||||
}
|
||||
|
||||
class GUISpaceCompound<T : ForInventory, E>(
|
||||
invType: GUIType<T>,
|
||||
iconGenerator: (E) -> ItemStack,
|
||||
onClick: ((GUIClickEvent<T>, E) -> Unit)?
|
||||
onClick: ((GUIClickEvent<T>, E) -> Unit)?,
|
||||
) : AbstractGUISpaceCompound<T, E>(invType, iconGenerator, onClick) {
|
||||
|
||||
override fun handleScrollEndReached(newProgress: Int, internalSlotsSize: Int, contentSize: Int) = false
|
||||
|
||||
}
|
||||
|
||||
abstract class AbstractGUISpaceCompound<T : ForInventory, E> internal constructor(
|
||||
val guiType: GUIType<T>,
|
||||
private val iconGenerator: (E) -> ItemStack,
|
||||
private val onClick: ((GUIClickEvent<T>, E) -> Unit)?
|
||||
private val onClick: ((GUIClickEvent<T>, E) -> Unit)?,
|
||||
) {
|
||||
|
||||
private val content = ArrayList<E>()
|
||||
private var currentContent: List<E> = emptyList()
|
||||
|
||||
private val internalSlots: MutableList<Int> = ArrayList()
|
||||
|
||||
private var scrollProgress: Int = 0
|
||||
|
||||
private var contentSort: () -> Unit = { }
|
||||
|
||||
private val registeredGUIs = HashSet<GUIInstance<*>>()
|
||||
|
||||
private fun contentAtSlot(slot: Int) = currentContent.getOrNull(internalSlots.indexOf(slot))
|
||||
|
||||
private fun recalculateCurrentContent() {
|
||||
|
||||
if (scrollProgress > content.size)
|
||||
throw IllegalStateException("The scrollProgress is greater than the content size.")
|
||||
|
||||
// avoid IndexOutOfBoundsException
|
||||
var sliceUntil = internalSlots.size + scrollProgress
|
||||
if (sliceUntil > content.lastIndex)
|
||||
sliceUntil = content.size
|
||||
|
||||
currentContent = content.slice(scrollProgress until sliceUntil)
|
||||
|
||||
}
|
||||
|
||||
private fun updateOpenGUIs() {
|
||||
@@ -88,7 +68,6 @@ abstract class AbstractGUISpaceCompound<T : ForInventory, E> internal constructo
|
||||
internal fun scroll(distance: Int): Boolean {
|
||||
val value = scrollProgress + distance
|
||||
return if (value >= 0) {
|
||||
|
||||
// always scroll if the end of the content is not reached
|
||||
val ifScroll = if (internalSlots.size + value <= content.size) true
|
||||
// scroll further if the width of the compound is defined and the last line can be filled up
|
||||
@@ -100,12 +79,10 @@ abstract class AbstractGUISpaceCompound<T : ForInventory, E> internal constructo
|
||||
updateOpenGUIs()
|
||||
true
|
||||
} else false
|
||||
|
||||
} else false
|
||||
}
|
||||
|
||||
internal abstract fun handleScrollEndReached(newProgress: Int, internalSlotsSize: Int, contentSize: Int): Boolean
|
||||
|
||||
internal fun getItemStack(slot: Int): ItemStack {
|
||||
return contentAtSlot(slot)?.let { return@let iconGenerator.invoke(it) }
|
||||
?: ItemStack(Material.AIR)
|
||||
@@ -191,7 +168,6 @@ abstract class AbstractGUISpaceCompound<T : ForInventory, E> internal constructo
|
||||
recalculateCurrentContent()
|
||||
updateOpenGUIs()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,5 +179,5 @@ abstract class AbstractGUISpaceCompound<T : ForInventory, E> internal constructo
|
||||
*/
|
||||
open class GUICompoundElement<T : ForInventory>(
|
||||
internal val icon: ItemStack,
|
||||
internal val onClick: ((GUIClickEvent<T>) -> Unit)? = null
|
||||
internal val onClick: ((GUIClickEvent<T>) -> Unit)? = null,
|
||||
)
|
@@ -5,16 +5,12 @@ import net.axay.kspigot.runnables.task
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class GUISpaceCompoundScrollButton<T : ForInventory>(
|
||||
|
||||
icon: ItemStack,
|
||||
|
||||
private val compound: AbstractGUISpaceCompound<T, *>,
|
||||
private val scrollDistance: Int,
|
||||
private val scrollTimes: Int,
|
||||
private val reverse: Boolean = false
|
||||
|
||||
private val reverse: Boolean = false,
|
||||
) : GUIButton<T>(icon, {
|
||||
|
||||
if (scrollTimes > 1) {
|
||||
task(
|
||||
period = 1,
|
||||
@@ -25,14 +21,11 @@ class GUISpaceCompoundScrollButton<T : ForInventory>(
|
||||
}
|
||||
} else if (scrollTimes == 1)
|
||||
if (reverse) compound.scroll(-scrollDistance) else compound.scroll(scrollDistance)
|
||||
|
||||
}) {
|
||||
|
||||
constructor(
|
||||
icon: ItemStack,
|
||||
compound: GUIRectSpaceCompound<T, *>,
|
||||
scrollTimes: Int = 1,
|
||||
reverse: Boolean = false
|
||||
reverse: Boolean = false,
|
||||
) : this(icon, compound, compound.compoundWidth, scrollTimes, reverse)
|
||||
|
||||
}
|
@@ -30,7 +30,7 @@ fun Player.hasBadIP(detector: BadIPDetector = BadIPDetector.DEFAULT) =
|
||||
*/
|
||||
fun Player.checkIP(
|
||||
detector: BadIPDetector = BadIPDetector.DEFAULT,
|
||||
breakOnHit: Boolean = true
|
||||
breakOnHit: Boolean = true,
|
||||
): Map<BadIPDetectionService, BadIPDetectionResult> {
|
||||
val ip = address?.hostString ?: return emptyMap()
|
||||
return detector.checkIP(ip, breakOnHit)
|
||||
@@ -47,9 +47,8 @@ fun Player.checkIP(
|
||||
* - [net.axay.kspigot.ipaddress.badipdetectionservices.VPNBlocker]
|
||||
*/
|
||||
class BadIPDetector(
|
||||
val services: List<BadIPDetectionService>
|
||||
val services: List<BadIPDetectionService>,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Alternative constructor.
|
||||
* @see BadIPDetector
|
||||
@@ -65,46 +64,35 @@ class BadIPDetector(
|
||||
fun checkIP(ip: String, breakOnHit: Boolean = true) =
|
||||
HashMap<BadIPDetectionService, BadIPDetectionResult>().apply {
|
||||
for (it in services) {
|
||||
|
||||
val curResult = it.isBad(ip)
|
||||
this[it] = curResult
|
||||
|
||||
if (curResult.isBad && breakOnHit) break
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class BadIPDetectionResult(
|
||||
val isBad: Boolean,
|
||||
val typeName: String
|
||||
val typeName: String,
|
||||
) {
|
||||
|
||||
GENERAL_BAD(true, "bad ip"),
|
||||
|
||||
VPN(true, "vpn"),
|
||||
PROXY(true, "proxy"),
|
||||
TOR(true, "tor network"),
|
||||
HOSTING(true, "hosting"),
|
||||
|
||||
GOOD(false, "valid ip"),
|
||||
ERROR(false, "error"),
|
||||
LIMIT(false, "limit");
|
||||
|
||||
}
|
||||
|
||||
abstract class BadIPDetectionService(
|
||||
val name: String
|
||||
val name: String,
|
||||
) {
|
||||
|
||||
protected abstract fun requestString(ip: String): String
|
||||
protected open fun requestHeaders() = emptyMap<String, String>()
|
||||
|
||||
protected abstract fun interpreteResult(result: JSONObject): BadIPDetectionResult
|
||||
|
||||
fun isBad(ip: String): BadIPDetectionResult {
|
||||
|
||||
val con = URL(requestString(ip)).openConnection() as HttpURLConnection
|
||||
con.requestMethod = "GET"
|
||||
requestHeaders().forEach { (field, value) -> con.setRequestProperty(field, value) }
|
||||
@@ -113,7 +101,6 @@ abstract class BadIPDetectionService(
|
||||
if (con.responseCode == 429)
|
||||
return BadIPDetectionResult.LIMIT
|
||||
else {
|
||||
|
||||
val result = try {
|
||||
con.inputStream.use { JSONObject(it.readAllBytes().decodeToString()) }
|
||||
} catch (exc: JSONException) {
|
||||
@@ -125,9 +112,6 @@ abstract class BadIPDetectionService(
|
||||
} catch (exc: Exception) {
|
||||
return BadIPDetectionResult.ERROR
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -28,11 +28,8 @@ val Player.ipAddressData get() = ipAddressData()
|
||||
* be found out about the IP address of the player.
|
||||
*/
|
||||
fun Player.ipAddressData(language: IPAddressDataLanguage = IPAddressDataLanguage.ENGLISH): IPAddressData? {
|
||||
|
||||
return try {
|
||||
|
||||
val hostString = address?.hostString ?: return null
|
||||
|
||||
val jsonObject = ValueHolder.getGson().fromUrlJson(
|
||||
"$IP_API${hostString}?fields=${IP_API_FIELDS}?lang=${language.code}"
|
||||
) ?: return null
|
||||
@@ -40,11 +37,9 @@ fun Player.ipAddressData(language: IPAddressDataLanguage = IPAddressDataLanguage
|
||||
if (jsonObject["status"].toString() == "fail") return null
|
||||
|
||||
IPAddressData(jsonObject)
|
||||
|
||||
} catch (exc: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class IPAddressDataLanguage(val code: String) {
|
||||
@@ -59,7 +54,6 @@ enum class IPAddressDataLanguage(val code: String) {
|
||||
}
|
||||
|
||||
class IPAddressData(private val json: JsonObject) {
|
||||
|
||||
val ip get() = json.getStringOrNull("query")
|
||||
|
||||
// region
|
||||
@@ -81,5 +75,4 @@ class IPAddressData(private val json: JsonObject) {
|
||||
// information
|
||||
val internetServiceProvider get() = json.getStringOrNull("isp")
|
||||
val organisation get() = json.getStringOrNull("org")
|
||||
|
||||
}
|
@@ -9,15 +9,14 @@ import org.json.JSONObject
|
||||
|
||||
class GetIPIntel(
|
||||
private val intensity: Float = 0.99f,
|
||||
private val contactEmail: String = "foo@bar.com"
|
||||
private val contactEmail: String = "foo@bar.com",
|
||||
) : BadIPDetectionService("getipintel.net") {
|
||||
|
||||
override fun requestString(ip: String) = "http://check.getipintel.net/check.php?ip=$ip&contact=$contactEmail&format=json"
|
||||
override fun requestString(ip: String) =
|
||||
"http://check.getipintel.net/check.php?ip=$ip&contact=$contactEmail&format=json"
|
||||
|
||||
override fun interpreteResult(result: JSONObject): BadIPDetectionResult {
|
||||
val probability = result.getStringOrNull("result")?.toFloatOrNull()
|
||||
?: return BadIPDetectionResult.ERROR
|
||||
return if (probability >= intensity) BadIPDetectionResult.GENERAL_BAD else BadIPDetectionResult.GOOD
|
||||
}
|
||||
|
||||
}
|
@@ -9,15 +9,12 @@ import org.json.JSONObject
|
||||
|
||||
class IPHub(
|
||||
private val apiKey: String,
|
||||
private val ifStrict: Boolean = false
|
||||
private val ifStrict: Boolean = false,
|
||||
) : BadIPDetectionService("iphub.info") {
|
||||
|
||||
override fun requestString(ip: String) = "http://v2.api.iphub.info/ip/$ip"
|
||||
override fun requestHeaders() = mapOf("X-Key" to apiKey)
|
||||
|
||||
override fun interpreteResult(result: JSONObject): BadIPDetectionResult {
|
||||
val ifBlock = result.getStringOrNull("block")?.toInt() ?: return BadIPDetectionResult.ERROR
|
||||
return if (ifBlock == 1 || (ifStrict && ifBlock == 2)) BadIPDetectionResult.GENERAL_BAD else BadIPDetectionResult.GOOD
|
||||
}
|
||||
|
||||
}
|
@@ -6,11 +6,9 @@ import net.axay.kspigot.languageextensions.getStringOrNull
|
||||
import org.json.JSONObject
|
||||
|
||||
class IPInfo(
|
||||
private val token: String
|
||||
private val token: String,
|
||||
) : BadIPDetectionService("ipinfo.io") {
|
||||
|
||||
override fun requestString(ip: String) = "https://ipinfo.io/$ip/privacy?token=$token"
|
||||
|
||||
override fun interpreteResult(result: JSONObject): BadIPDetectionResult {
|
||||
return when {
|
||||
result.getStringOrNull("vpn").toBoolean() -> BadIPDetectionResult.VPN
|
||||
@@ -20,5 +18,4 @@ class IPInfo(
|
||||
else -> BadIPDetectionResult.GOOD
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -6,9 +6,7 @@ import net.axay.kspigot.languageextensions.getStringOrNull
|
||||
import org.json.JSONObject
|
||||
|
||||
class VPNBlocker : BadIPDetectionService("vpnblocker.net") {
|
||||
|
||||
override fun requestString(ip: String) = "http://api.vpnblocker.net/v2/json/$ip"
|
||||
|
||||
override fun interpreteResult(result: JSONObject): BadIPDetectionResult {
|
||||
val isBad = result.getStringOrNull("host-ip")
|
||||
return when {
|
||||
@@ -20,5 +18,4 @@ class VPNBlocker : BadIPDetectionService("vpnblocker.net") {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -15,7 +15,6 @@ import org.bukkit.inventory.meta.ItemMeta
|
||||
* aswell.
|
||||
*/
|
||||
data class CustomItemIdentifier(val customModelData: Int, val placeHolderMaterial: Material) {
|
||||
|
||||
constructor(itemStack: ItemStack) :
|
||||
this(
|
||||
kotlin.run {
|
||||
@@ -38,5 +37,4 @@ data class CustomItemIdentifier(val customModelData: Int, val placeHolderMateria
|
||||
itemStack
|
||||
} else null
|
||||
}
|
||||
|
||||
}
|
@@ -8,20 +8,15 @@ import net.md_5.bungee.api.ChatColor
|
||||
* can be used for minecraft lorelists.
|
||||
*/
|
||||
fun String.toLoreList(vararg lineColors: ChatColor = arrayOf(KColors.RESET), lineLength: Int = 40): List<String> {
|
||||
|
||||
val lineColor = lineColors.joinToString(separator = "")
|
||||
|
||||
val loreList = ArrayList<String>()
|
||||
|
||||
val lineBuilder = StringBuilder()
|
||||
|
||||
fun submitLine() {
|
||||
loreList += "$lineColor$lineBuilder"
|
||||
lineBuilder.clear()
|
||||
}
|
||||
|
||||
fun addWord(word: String) {
|
||||
|
||||
if (lineBuilder.lengthWithoutMinecraftColour + word.lengthWithoutMinecraftColour > lineLength)
|
||||
submitLine()
|
||||
|
||||
@@ -29,7 +24,6 @@ fun String.toLoreList(vararg lineColors: ChatColor = arrayOf(KColors.RESET), lin
|
||||
lineBuilder.append(" ")
|
||||
|
||||
lineBuilder.append(word)
|
||||
|
||||
}
|
||||
|
||||
split(" ").forEach { addWord(it) }
|
||||
@@ -38,38 +32,33 @@ fun String.toLoreList(vararg lineColors: ChatColor = arrayOf(KColors.RESET), lin
|
||||
submitLine()
|
||||
|
||||
return loreList
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of this sequence, ignoring
|
||||
* all minecraft colour codes.
|
||||
*/
|
||||
val CharSequence.lengthWithoutMinecraftColour: Int get() {
|
||||
val CharSequence.lengthWithoutMinecraftColour: Int
|
||||
get() {
|
||||
var count = 0
|
||||
var isPreviousColourCode = false
|
||||
|
||||
var count = 0
|
||||
this.forEachIndexed { index, char ->
|
||||
if (isPreviousColourCode) {
|
||||
isPreviousColourCode = false
|
||||
return@forEachIndexed
|
||||
}
|
||||
|
||||
var isPreviousColourCode = false
|
||||
|
||||
this.forEachIndexed { index, char ->
|
||||
|
||||
if (isPreviousColourCode) {
|
||||
isPreviousColourCode = false
|
||||
return@forEachIndexed
|
||||
if (char == '§') {
|
||||
if (lastIndex >= index + 1) {
|
||||
val nextChar = this[index + 1]
|
||||
if (nextChar.isLetter() || nextChar.isDigit())
|
||||
isPreviousColourCode = true
|
||||
else
|
||||
count++
|
||||
}
|
||||
} else count++
|
||||
}
|
||||
|
||||
if (char == '§') {
|
||||
if (lastIndex >= index + 1) {
|
||||
val nextChar = this[index + 1]
|
||||
if (nextChar.isLetter() || nextChar.isDigit())
|
||||
isPreviousColourCode = true
|
||||
else
|
||||
count++
|
||||
}
|
||||
} else count++
|
||||
|
||||
}
|
||||
|
||||
return count
|
||||
|
||||
}
|
||||
return count
|
||||
}
|
@@ -9,16 +9,12 @@ import org.bukkit.inventory.meta.ItemMeta
|
||||
/*
|
||||
ITEM STACK
|
||||
*/
|
||||
|
||||
// creation
|
||||
|
||||
/**
|
||||
* Creates a new [ItemStack] and opens a builder for it.
|
||||
*/
|
||||
inline fun itemStack(material: Material, builder: ItemStack.() -> Unit) = ItemStack(material).apply(builder)
|
||||
|
||||
// extensions
|
||||
|
||||
/**
|
||||
* Opens a builder with the current meta.
|
||||
* @param T the specific type of the meta
|
||||
@@ -48,13 +44,10 @@ inline fun <reified T : ItemMeta> ItemStack.setMeta(builder: T.() -> Unit) {
|
||||
/** @see setMeta */
|
||||
@JvmName("simpleSetMeta")
|
||||
inline fun ItemStack.setMeta(builder: ItemMeta.() -> Unit) = setMeta<ItemMeta>(builder)
|
||||
|
||||
/*
|
||||
ITEM META
|
||||
*/
|
||||
|
||||
// creation
|
||||
|
||||
/**
|
||||
* Creates new a [ItemMeta] instance of the given material and opens a builder for it.
|
||||
* @param T the specific type of the meta
|
||||
@@ -67,9 +60,7 @@ inline fun <reified T : ItemMeta> itemMeta(material: Material, builder: T.() ->
|
||||
/** @see itemMeta */
|
||||
@JvmName("simpleItemMeta")
|
||||
inline fun itemMeta(material: Material, builder: ItemMeta.() -> Unit) = itemMeta<ItemMeta>(material, builder)
|
||||
|
||||
// extensions
|
||||
|
||||
/**
|
||||
* Sets the lore (description) of the item.
|
||||
*/
|
||||
|
@@ -1,7 +1,5 @@
|
||||
package net.axay.kspigot.languageextensions.kotlinextensions
|
||||
|
||||
internal inline fun <T, R> Lazy<T>.ifInitialized(block: (T) -> R) = if (isInitialized()) block(value) else null
|
||||
|
||||
internal val <T> Lazy<T>.valueIfInitialized get() = ifInitialized { value }
|
||||
|
||||
internal fun Lazy<AutoCloseable>.closeIfInitialized() = ifInitialized { value.close() }
|
@@ -3,7 +3,6 @@
|
||||
package net.axay.kspigot.languageextensions.kotlinextensions
|
||||
|
||||
internal class MinMaxPair<T : Comparable<T>>(a: T, b: T) {
|
||||
|
||||
val min: T;
|
||||
val max: T
|
||||
|
||||
@@ -14,5 +13,4 @@ internal class MinMaxPair<T : Comparable<T>>(a: T, b: T) {
|
||||
min = a; max = b
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,17 +1,12 @@
|
||||
package net.axay.kspigot.languageextensions.kotlinextensions
|
||||
|
||||
internal fun stringBuilder(builder: StringBuilder.() -> Unit) = StringBuilder().apply(builder).toString()
|
||||
|
||||
inline fun multiLine(builder: MultiLineBuilder.() -> Unit) = MultiLineBuilder().apply(builder).build()
|
||||
|
||||
class MultiLineBuilder {
|
||||
|
||||
private val stringBuilder = StringBuilder()
|
||||
|
||||
operator fun String.unaryPlus() {
|
||||
stringBuilder.appendLine(this)
|
||||
}
|
||||
|
||||
fun build() = stringBuilder.toString()
|
||||
|
||||
}
|
@@ -5,7 +5,6 @@ import org.bukkit.entity.Player
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
/**
|
||||
* Handles localization of strings using java [ResourceBundle]s.
|
||||
@@ -23,7 +22,6 @@ object Localization {
|
||||
* is advisable in many cases.
|
||||
*/
|
||||
var localeProvider: (Player) -> Locale = { Locale.US }
|
||||
|
||||
private val bundles: MutableMap<Locale, ResourceBundle> = HashMap()
|
||||
|
||||
/**
|
||||
|
@@ -19,11 +19,9 @@ import org.bukkit.plugin.java.JavaPlugin
|
||||
* - [shutdown()] (called in the "end")
|
||||
*/
|
||||
abstract class KSpigot : JavaPlugin() {
|
||||
|
||||
// lazy properties
|
||||
private val kRunnableHolderProperty = lazy { KRunnableHolder }
|
||||
private val guiHolderProperty = lazy { GUIHolder }
|
||||
|
||||
internal val kRunnableHolder by kRunnableHolderProperty
|
||||
internal val guiHolder by guiHolderProperty
|
||||
|
||||
@@ -41,7 +39,6 @@ abstract class KSpigot : JavaPlugin() {
|
||||
* Called when the plugin gets disabled
|
||||
*/
|
||||
open fun shutdown() {}
|
||||
|
||||
final override fun onLoad() {
|
||||
KSpigotMainInstance = this
|
||||
load()
|
||||
@@ -52,15 +49,11 @@ abstract class KSpigot : JavaPlugin() {
|
||||
}
|
||||
|
||||
final override fun onDisable() {
|
||||
|
||||
shutdown()
|
||||
|
||||
// avoid unnecessary load of lazy properties
|
||||
kRunnableHolderProperty.closeIfInitialized()
|
||||
guiHolderProperty.closeIfInitialized()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lateinit var KSpigotMainInstance: KSpigot private set
|
@@ -4,14 +4,10 @@ import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
|
||||
object ValueHolder {
|
||||
|
||||
private val gsonBuilder by lazy {
|
||||
GsonBuilder()
|
||||
}
|
||||
|
||||
private val gson: Gson by lazy { gsonBuilder.create() }
|
||||
private val gsonPretty: Gson by lazy { gsonBuilder.setPrettyPrinting().create() }
|
||||
|
||||
fun getGson(pretty: Boolean = false) = if (pretty) gsonPretty else gson
|
||||
|
||||
}
|
@@ -21,9 +21,8 @@ data class KSpigotParticle(
|
||||
var offset: Vector? = null,
|
||||
var extra: Number = 1.0,
|
||||
var data: Any? = null,
|
||||
var force: Boolean = false
|
||||
var force: Boolean = false,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Spawns the particle at the location. It
|
||||
* will be visible for everyone near it.
|
||||
@@ -58,7 +57,6 @@ data class KSpigotParticle(
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -9,40 +9,29 @@ import java.io.DataInputStream
|
||||
internal class BungeePluginMessageResponseCallback(
|
||||
val subChannel: String,
|
||||
val timeoutSeconds: Int,
|
||||
val onResponse: (message: DataInputStream) -> Unit
|
||||
val onResponse: (message: DataInputStream) -> Unit,
|
||||
) {
|
||||
|
||||
init {
|
||||
|
||||
BungeePluginMessageReceiver.registered += this
|
||||
|
||||
taskRunLater(20L * timeoutSeconds) {
|
||||
BungeePluginMessageReceiver.registered -= this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private object BungeePluginMessageReceiver : PluginMessageListener {
|
||||
|
||||
val registered = ArrayList<BungeePluginMessageResponseCallback>()
|
||||
|
||||
override fun onPluginMessageReceived(channel: String, player: Player, message: ByteArray) {
|
||||
|
||||
if (channel != "BungeeCord") return
|
||||
|
||||
val msgbytes = ByteArrayInputStream(message)
|
||||
val msgin = DataInputStream(msgbytes)
|
||||
|
||||
val subChannel = msgin.readUTF()
|
||||
|
||||
val callback = registered.find { it.subChannel == subChannel }
|
||||
if (callback != null) {
|
||||
registered -= callback
|
||||
callback.onResponse.invoke(msgin)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -8,7 +8,7 @@ import org.bukkit.entity.Player
|
||||
* Sends the sending player to the given server
|
||||
*/
|
||||
class PluginMessageConnect(
|
||||
val servername: String
|
||||
val servername: String,
|
||||
) : BungeePluginMessagePlayerSpecific {
|
||||
override fun sendWithPlayer(player: Player) = sendPluginMessageToBungeeCord(
|
||||
player, "Connect", listOf(servername)
|
||||
@@ -21,7 +21,7 @@ class PluginMessageConnect(
|
||||
*/
|
||||
class PluginMessagePlayerCount(
|
||||
val servername: String,
|
||||
private val response: (Int) -> Unit
|
||||
private val response: (Int) -> Unit,
|
||||
) : BungeePluginMessageRandomPlayer {
|
||||
override fun send() = sendPluginMessageToBungeeCordRandomPlayer(
|
||||
"PlayerCount", listOf(servername)
|
||||
@@ -35,7 +35,7 @@ class PluginMessagePlayerCount(
|
||||
* on all servers.
|
||||
*/
|
||||
class PluginMessagePlayerCountAllServers(
|
||||
private val response: (Int) -> Unit
|
||||
private val response: (Int) -> Unit,
|
||||
) : BungeePluginMessageRandomPlayer {
|
||||
override fun send() = sendPluginMessageToBungeeCordRandomPlayer(
|
||||
"PlayerCount", listOf("ALL")
|
||||
@@ -50,7 +50,7 @@ class PluginMessagePlayerCountAllServers(
|
||||
*/
|
||||
class PluginMessagePlayerList(
|
||||
val servername: String,
|
||||
private val response: (List<String>) -> Unit
|
||||
private val response: (List<String>) -> Unit,
|
||||
) : BungeePluginMessageRandomPlayer {
|
||||
override fun send() = sendPluginMessageToBungeeCordRandomPlayer(
|
||||
"PlayerList", listOf(servername)
|
||||
@@ -65,7 +65,7 @@ class PluginMessagePlayerList(
|
||||
*/
|
||||
class PluginMessagePlayerListAllServers(
|
||||
val servername: String,
|
||||
private val response: (List<String>) -> Unit
|
||||
private val response: (List<String>) -> Unit,
|
||||
) : BungeePluginMessageRandomPlayer {
|
||||
override fun send() = sendPluginMessageToBungeeCordRandomPlayer(
|
||||
"PlayerList", listOf("ALL")
|
||||
@@ -79,7 +79,7 @@ class PluginMessagePlayerListAllServers(
|
||||
* BungeeCord network.
|
||||
*/
|
||||
class PluginMessageGetServers(
|
||||
private val response: (List<String>) -> Unit
|
||||
private val response: (List<String>) -> Unit,
|
||||
) : BungeePluginMessageRandomPlayer {
|
||||
override fun send() = sendPluginMessageToBungeeCordRandomPlayer(
|
||||
"GetServers"
|
||||
|
@@ -19,7 +19,7 @@ fun sendPluginMessageToBungeeCordRandomPlayer(
|
||||
subChannel: String,
|
||||
content: List<String>? = null,
|
||||
responseTimeout: Int = 20,
|
||||
onResponse: ((message: DataInputStream) -> Unit)? = null
|
||||
onResponse: ((message: DataInputStream) -> Unit)? = null,
|
||||
): Boolean {
|
||||
val randomPlayer = onlinePlayers.randomOrNull()
|
||||
return if (randomPlayer != null) {
|
||||
@@ -43,20 +43,17 @@ fun sendPluginMessageToBungeeCord(
|
||||
subChannel: String,
|
||||
content: List<String>? = null,
|
||||
responseTimeout: Int = 20,
|
||||
onResponse: ((message: DataInputStream) -> Unit)? = null
|
||||
onResponse: ((message: DataInputStream) -> Unit)? = null,
|
||||
) {
|
||||
|
||||
val msgbytes = ByteArrayOutputStream()
|
||||
val msgout = DataOutputStream(msgbytes)
|
||||
|
||||
try {
|
||||
|
||||
msgout.writeUTF(subChannel)
|
||||
|
||||
if (content != null)
|
||||
for (messagePart in content)
|
||||
msgout.writeUTF(messagePart)
|
||||
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
@@ -65,5 +62,4 @@ fun sendPluginMessageToBungeeCord(
|
||||
BungeePluginMessageResponseCallback(subChannel, responseTimeout, onResponse)
|
||||
|
||||
player.sendPluginMessage(KSpigotMainInstance, "BungeeCord", msgbytes.toByteArray())
|
||||
|
||||
}
|
@@ -5,11 +5,9 @@ package net.axay.kspigot.runnables
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
abstract class ChainedRunnablePart<T, R>(
|
||||
val sync: Boolean
|
||||
val sync: Boolean,
|
||||
) {
|
||||
|
||||
var next: ChainedRunnablePart<R, *>? = null
|
||||
|
||||
protected abstract fun invoke(data: T): R
|
||||
|
||||
/**
|
||||
@@ -27,7 +25,7 @@ abstract class ChainedRunnablePart<T, R>(
|
||||
*/
|
||||
inline fun <reified E : Exception> executeCatching(
|
||||
exceptionSync: Boolean = true,
|
||||
noinline exceptionHandler: ((E) -> Unit)? = null
|
||||
noinline exceptionHandler: ((E) -> Unit)? = null,
|
||||
) {
|
||||
executeCatchingImpl(E::class, exceptionSync, exceptionHandler)
|
||||
}
|
||||
@@ -74,42 +72,35 @@ abstract class ChainedRunnablePart<T, R>(
|
||||
next?.startCatching(result, exceptionClass, exceptionSync, exceptionHandler)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ChainedRunnablePartFirst<R>(
|
||||
val runnable: () -> R,
|
||||
sync: Boolean
|
||||
sync: Boolean,
|
||||
) : ChainedRunnablePart<Unit, R>(sync) {
|
||||
|
||||
override fun execute() = start(Unit)
|
||||
|
||||
override fun <E : Exception> executeCatchingImpl(
|
||||
exceptionClass: KClass<E>,
|
||||
exceptionSync: Boolean,
|
||||
exceptionHandler: ((E) -> Unit)?
|
||||
exceptionHandler: ((E) -> Unit)?,
|
||||
) = startCatching(Unit, exceptionClass, exceptionSync, exceptionHandler)
|
||||
|
||||
override fun invoke(data: Unit) = runnable.invoke()
|
||||
|
||||
}
|
||||
|
||||
class ChainedRunnablePartThen<T, R>(
|
||||
val runnable: (T) -> R,
|
||||
sync: Boolean,
|
||||
val previous: ChainedRunnablePart<*, T>
|
||||
val previous: ChainedRunnablePart<*, T>,
|
||||
) : ChainedRunnablePart<T, R>(sync) {
|
||||
|
||||
override fun execute() = previous.execute()
|
||||
|
||||
override fun <E : Exception> executeCatchingImpl(
|
||||
exceptionClass: KClass<E>,
|
||||
exceptionSync: Boolean,
|
||||
exceptionHandler: ((E) -> Unit)?
|
||||
exceptionHandler: ((E) -> Unit)?,
|
||||
) = previous.executeCatchingImpl(exceptionClass, exceptionSync, exceptionHandler)
|
||||
|
||||
override fun invoke(data: T) = runnable.invoke(data)
|
||||
|
||||
}
|
||||
|
||||
// FIRST
|
||||
|
@@ -7,7 +7,6 @@ import org.bukkit.Bukkit
|
||||
import org.bukkit.scheduler.BukkitRunnable
|
||||
|
||||
internal object KRunnableHolder : AutoCloseable {
|
||||
|
||||
/**
|
||||
* [BukkitRunnable] for tracking the responsible runnable.
|
||||
* [Pair] of callback for the endCallback code and [Boolean]
|
||||
@@ -15,7 +14,6 @@ internal object KRunnableHolder : AutoCloseable {
|
||||
* or not.
|
||||
*/
|
||||
private val runnableEndCallbacks = HashMap<BukkitRunnable, Pair<() -> Unit, Boolean>>()
|
||||
|
||||
override fun close() {
|
||||
runnableEndCallbacks.values.forEach { if (it.second) it.first.invoke() }
|
||||
runnableEndCallbacks.clear()
|
||||
@@ -26,13 +24,12 @@ internal object KRunnableHolder : AutoCloseable {
|
||||
|
||||
fun remove(runnable: BukkitRunnable) = runnableEndCallbacks.remove(runnable)
|
||||
fun activate(runnable: BukkitRunnable) = runnableEndCallbacks.remove(runnable)?.first?.invoke()
|
||||
|
||||
}
|
||||
|
||||
abstract class KSpigotRunnable(
|
||||
var counterUp: Long? = null,
|
||||
var counterDownToOne: Long? = null,
|
||||
var counterDownToZero: Long? = null
|
||||
var counterDownToZero: Long? = null,
|
||||
) : BukkitRunnable()
|
||||
|
||||
/**
|
||||
@@ -56,20 +53,14 @@ fun task(
|
||||
howOften: Long? = null,
|
||||
safe: Boolean = false,
|
||||
endCallback: (() -> Unit)? = null,
|
||||
runnable: ((KSpigotRunnable) -> Unit)? = null
|
||||
runnable: ((KSpigotRunnable) -> Unit)? = null,
|
||||
): KSpigotRunnable? {
|
||||
|
||||
if (howOften != null && howOften == 0L) return null
|
||||
|
||||
val bukkitRunnable = object : KSpigotRunnable() {
|
||||
|
||||
private var curCounter = 0L
|
||||
|
||||
override fun run() {
|
||||
|
||||
var ranOut = false
|
||||
if (howOften != null) {
|
||||
|
||||
counterDownToOne = howOften - curCounter
|
||||
counterDownToZero = counterDownToOne?.minus(1)
|
||||
|
||||
@@ -78,7 +69,6 @@ fun task(
|
||||
ranOut = true
|
||||
|
||||
counterUp = curCounter
|
||||
|
||||
}
|
||||
|
||||
runnable?.invoke(this)
|
||||
@@ -91,9 +81,7 @@ fun task(
|
||||
else
|
||||
KRunnableHolder.remove(this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (endCallback != null) KRunnableHolder.add(bukkitRunnable, endCallback, safe)
|
||||
@@ -106,7 +94,6 @@ fun task(
|
||||
else bukkitRunnable.runTaskLaterAsynchronously(KSpigotMainInstance, delay)
|
||||
|
||||
return bukkitRunnable
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -24,13 +24,10 @@ object ItemMetaSerializer : KSerializerForBukkit<ItemMeta>(ItemMeta::class)
|
||||
object ItemStackSerializer : KSerializerForBukkit<ItemStack>(ItemStack::class)
|
||||
object LocationSerializer : KSerializerForBukkit<Location>(Location::class)
|
||||
object VectorSerializer : KSerializerForBukkit<Vector>(Vector::class)
|
||||
|
||||
open class KSerializerForBukkit<T : ConfigurationSerializable>(
|
||||
private val kClass: KClass<T>
|
||||
private val kClass: KClass<T>,
|
||||
) : KSerializer<T> {
|
||||
|
||||
override val descriptor = ByteArraySerializer().descriptor
|
||||
|
||||
override fun serialize(encoder: Encoder, value: T) {
|
||||
val bytes = ByteArrayOutputStream()
|
||||
BukkitObjectOutputStream(bytes).use {
|
||||
@@ -48,5 +45,4 @@ open class KSerializerForBukkit<T : ConfigurationSerializable>(
|
||||
?: throw IllegalStateException("The object can not be deserialized to an object of the type ${kClass.simpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -11,14 +11,16 @@ data class SerializableLocation(
|
||||
val x: Double,
|
||||
val y: Double,
|
||||
val z: Double,
|
||||
val direction: SerializableVector
|
||||
val direction: SerializableVector,
|
||||
) : SpigotSerializable<Location> {
|
||||
|
||||
companion object : SpigotSerializableCompanion<SerializableLocation>
|
||||
|
||||
constructor(loc: Location) : this(loc.world?.let { SerializableWorld(it) }, loc.x, loc.y, loc.z, SerializableVector(loc.direction))
|
||||
constructor(loc: Location) : this(loc.world?.let { SerializableWorld(it) },
|
||||
loc.x,
|
||||
loc.y,
|
||||
loc.z,
|
||||
SerializableVector(loc.direction))
|
||||
|
||||
override fun toSpigot() = Location(world?.toSpigot(), x, y, z)
|
||||
.apply { direction = this@SerializableLocation.direction.toSpigot() }
|
||||
|
||||
}
|
@@ -9,13 +9,11 @@ import org.bukkit.util.Vector
|
||||
data class SerializableVector(
|
||||
val x: Double,
|
||||
val y: Double,
|
||||
val z: Double
|
||||
val z: Double,
|
||||
) : SpigotSerializable<Vector> {
|
||||
|
||||
companion object : SpigotSerializableCompanion<SerializableVector>
|
||||
|
||||
constructor(vec: Vector) : this(vec.x, vec.y, vec.z)
|
||||
|
||||
override fun toSpigot() = Vector(x, y, z)
|
||||
|
||||
}
|
@@ -8,14 +8,12 @@ import org.bukkit.Bukkit
|
||||
import org.bukkit.World
|
||||
|
||||
class SerializableWorld(
|
||||
val name: String
|
||||
val name: String,
|
||||
) : SpigotSerializable<World> {
|
||||
|
||||
companion object : SpigotSerializableCompanion<World>
|
||||
|
||||
constructor(world: World) : this(world.name)
|
||||
|
||||
override fun toSpigot() = Bukkit.getWorld(name)
|
||||
?: throw NullPointerException("The world \"$name\" does not exist")
|
||||
|
||||
}
|
@@ -11,9 +11,8 @@ data class KSpigotSound(
|
||||
val sound: Sound,
|
||||
var volume: Float = 1f,
|
||||
var pitch: Float = 1f,
|
||||
var category: SoundCategory? = null
|
||||
var category: SoundCategory? = null,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Plays the sound at the location. It
|
||||
* will be audible for everyone near it.
|
||||
@@ -37,7 +36,6 @@ data class KSpigotSound(
|
||||
else
|
||||
player.playSound(player.location, sound, volume, pitch)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -9,15 +9,12 @@ import org.bukkit.Material
|
||||
import org.bukkit.entity.EntityType
|
||||
|
||||
private fun circleEdgeLocations(radius: Number) = HashSet<SimpleLocation2D>().apply {
|
||||
|
||||
val currentRadius = radius.toDouble()
|
||||
|
||||
var d = -currentRadius
|
||||
var x = currentRadius
|
||||
var y = 0
|
||||
|
||||
while (y <= x) {
|
||||
|
||||
addSimpleLoc2D(x, y)
|
||||
addSimpleLoc2D(x, -y)
|
||||
addSimpleLoc2D(-x, y)
|
||||
@@ -34,9 +31,7 @@ private fun circleEdgeLocations(radius: Number) = HashSet<SimpleLocation2D>().ap
|
||||
d += -2 * x + 2
|
||||
x--
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun MutableSet<SimpleLocation2D>.addSimpleLoc2D(first: Number, second: Number) {
|
||||
@@ -44,11 +39,8 @@ private fun MutableSet<SimpleLocation2D>.addSimpleLoc2D(first: Number, second: N
|
||||
}
|
||||
|
||||
abstract class Circle(val radius: Number) {
|
||||
|
||||
protected abstract val data: StructureData
|
||||
|
||||
val fillLocations by lazy {
|
||||
|
||||
var currentRadius = radius.toDouble()
|
||||
|
||||
HashSet<SimpleLocation2D>().apply {
|
||||
@@ -70,17 +62,12 @@ abstract class Circle(val radius: Number) {
|
||||
currentRadius--
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val edgeLocations by lazy {
|
||||
circleEdgeLocations(radius)
|
||||
}
|
||||
|
||||
val filledStructure by lazy { structure(true) }
|
||||
|
||||
val edgeStructure by lazy { structure(false) }
|
||||
|
||||
fun structure(filled: Boolean) = Structure(
|
||||
HashSet<SingleStructureData>().apply {
|
||||
val locations = if (filled) fillLocations else edgeLocations
|
||||
@@ -88,7 +75,6 @@ abstract class Circle(val radius: Number) {
|
||||
this += SingleStructureData(SimpleLocation3D(it.x, 0, it.y), data)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
class MaterialCircle(radius: Number, material: Material) : Circle(radius) {
|
||||
|
@@ -19,35 +19,31 @@ interface StructureData {
|
||||
|
||||
class SingleStructureData(
|
||||
val location: SimpleLocation3D,
|
||||
val structureData: StructureData
|
||||
val structureData: StructureData,
|
||||
)
|
||||
|
||||
data class Structure(
|
||||
val structureData: Set<SingleStructureData>
|
||||
val structureData: Set<SingleStructureData>,
|
||||
) {
|
||||
constructor(vararg structureDataSets: Set<SingleStructureData>)
|
||||
: this(structureDataSets.flatMapTo(HashSet()) { it })
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure data implementations.
|
||||
*/
|
||||
|
||||
data class StructureDataMaterial(
|
||||
val material: Material
|
||||
val material: Material,
|
||||
) : StructureData {
|
||||
|
||||
override fun createAt(loc: Location) {
|
||||
loc.block.type = material
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class StructureDataBlock(
|
||||
val material: Material,
|
||||
val blockData: BlockData
|
||||
val blockData: BlockData,
|
||||
) : StructureData {
|
||||
|
||||
constructor(block: Block) : this(block.type, block.blockData)
|
||||
|
||||
override fun createAt(loc: Location) {
|
||||
@@ -56,30 +52,25 @@ data class StructureDataBlock(
|
||||
it.blockData = blockData
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@NMS_General
|
||||
data class StructureDataEntity(
|
||||
val entityType: EntityType,
|
||||
val nbtData: NBTData
|
||||
val nbtData: NBTData,
|
||||
) : StructureData {
|
||||
|
||||
constructor(entity: Entity) : this(entity.type, entity.nbtData)
|
||||
constructor(entityType: EntityType) : this(entityType, NBTData())
|
||||
|
||||
override fun createAt(loc: Location) {
|
||||
loc.spawnCleanEntity(entityType)?.nbtData = nbtData
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class StructureDataParticle(
|
||||
val particle: KSpigotParticle
|
||||
val particle: KSpigotParticle,
|
||||
) : StructureData {
|
||||
|
||||
override fun createAt(loc: Location) {
|
||||
particle.spawnAt(loc)
|
||||
}
|
||||
|
||||
}
|
@@ -9,14 +9,12 @@ import org.bukkit.block.BlockFace
|
||||
* vertical directions (pitch).
|
||||
*/
|
||||
enum class VerticalDirection {
|
||||
|
||||
UP, DOWN, STRAIGHT;
|
||||
|
||||
val facing: BlockFace?
|
||||
get() = Enums.getIfPresent(BlockFace::class.java, this.name).orNull()
|
||||
|
||||
companion object {
|
||||
|
||||
fun fromLocation(location: Location): VerticalDirection {
|
||||
val pitch: Float = location.pitch
|
||||
return when {
|
||||
@@ -25,9 +23,7 @@ enum class VerticalDirection {
|
||||
else -> STRAIGHT
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,14 +31,12 @@ enum class VerticalDirection {
|
||||
* cardinal directions (yaw).
|
||||
*/
|
||||
enum class CardinalDirection {
|
||||
|
||||
NORTH, EAST, SOUTH, WEST;
|
||||
|
||||
val facing: BlockFace?
|
||||
get() = Enums.getIfPresent(BlockFace::class.java, this.name).orNull()
|
||||
|
||||
companion object {
|
||||
|
||||
fun fromLocation(location: Location): CardinalDirection {
|
||||
var yaw: Float = location.yaw
|
||||
if (yaw < 0) yaw += 360f
|
||||
@@ -54,7 +48,5 @@ enum class CardinalDirection {
|
||||
else -> NORTH
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -7,44 +7,34 @@ import org.bukkit.FireworkEffect
|
||||
import org.bukkit.inventory.meta.FireworkMeta
|
||||
|
||||
object KSpigotFirework {
|
||||
|
||||
inline fun buildFireworkMeta(fireworkMeta: FireworkMeta, builder: KSpigotFireworkBuilder.() -> Unit): FireworkMeta {
|
||||
return KSpigotFireworkBuilder().apply(builder).applyTo(fireworkMeta)
|
||||
}
|
||||
|
||||
fun FireworkMeta.build(builder: KSpigotFireworkBuilder.() -> Unit) = buildFireworkMeta(this, builder)
|
||||
|
||||
}
|
||||
|
||||
class KSpigotFireworkBuilder {
|
||||
|
||||
val effects = ArrayList<FireworkEffect>()
|
||||
|
||||
var power: Int? = null
|
||||
|
||||
inline fun effect(builder: FireworkEffectBuilder.() -> Unit) {
|
||||
effects += FireworkEffectBuilder().apply(builder).fireworkEffect
|
||||
}
|
||||
|
||||
fun applyTo(fireworkMeta: FireworkMeta): FireworkMeta {
|
||||
|
||||
fireworkMeta.addEffects(effects)
|
||||
|
||||
power?.let { fireworkMeta.power = it }
|
||||
|
||||
return fireworkMeta
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FireworkEffectBuilder {
|
||||
|
||||
private val fireworkBuilder = FireworkEffect.builder()
|
||||
|
||||
var type: FireworkEffect.Type? = null
|
||||
var trail: Boolean? = null
|
||||
var flicker: Boolean? = null
|
||||
|
||||
fun fade(vararg colors: Color) {
|
||||
fireworkBuilder.withFade(*colors)
|
||||
}
|
||||
@@ -55,13 +45,10 @@ class FireworkEffectBuilder {
|
||||
|
||||
val fireworkEffect: FireworkEffect
|
||||
get() {
|
||||
|
||||
type?.let { fireworkBuilder.with(it) }
|
||||
trail?.let { fireworkBuilder.trail(it) }
|
||||
flicker?.let { fireworkBuilder.flicker(it) }
|
||||
|
||||
return fireworkBuilder.build()
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -33,9 +33,7 @@ fun PersistentDataHolder.unmark(key: String) {
|
||||
* this objects' markings.
|
||||
*/
|
||||
fun PersistentDataHolder.hasMark(key: String) = persistentDataContainer.has(markerKey(key), PersistentDataType.BYTE)
|
||||
|
||||
// quick access for ItemStacks
|
||||
|
||||
/** @see PersistentDataHolder.mark */
|
||||
fun ItemStack.mark(key: String) = meta { mark(key) }
|
||||
|
||||
|
Reference in New Issue
Block a user