KSpigot
Dependency
Gradle (Kotlin-Script)
The repository:
jcenter()
The dependency:
implementation("net.axay", "KSpigot", "VERSION_HERE")
Gradle (Groovy)
The repository:
jcenter()
The dependency:
implementation 'net.axay:KSpigot:VERSION_HERE'
Maven
The repository:
<repository>
<id>jcenter</id>
<name>jcenter</name>
<url>https://jcenter.bintray.com</url>
</repository>
The dependency:
<dependency>
<groupId>net.axay</groupId>
<artifactId>KSpigot</artifactId>
<version>VERSION_HERE</version>
</dependency>
About
KSpigot is a kotlin extension for the popular spigot server software for minecraft. KSpigot adds functionality missing in spigot and partly makes it possible to do it the kotlin way. Most of KSpigot's extensions are stable.
IMPORTANT:
Extensions marked with NMS annotations like @NMS_GENERAL
or @NMS_"VERSIONSTRING"
are unstable.
Extensions marked with the @UnsafeImplementaion
annotation do not promise to always give the correct result, but are still useful and therefore included in the project. This readme DOES NOT contain any unsafe parts of KSpigot.
First of all
Inherit from KSpigot
instead of JavaPlugin
in your main class
class MyPluginMain : KSpigot()
Replaced methods: (override these instead)
onLoad() with load()
onEnable() with startup()
onDisable() with shutdown()
Examples
Simple runnables and schedulers:
plugin.async { /* short form for async tasks */ }
plugin.sync { /* sync some code to bukkits main thread */ }
kSpigot.task(
sync = false,
delay = 25,
period = 20,
howOften = 5
) {
// runnable code...
// you can access the following counter variables in here
println(counterUp) // starting from zero
println(counterDownToOne) // starting from howOften
println(counterDownToZero) // starting from howOften - 1
}
NOTE: The counters are nullable, because howOften is (when null) infinite.
Safe runnables
With the kSpigot.task() { }
method you have the possibility to set the parameter safe = true
. When doing this, the defined endCallback
will be executed under any circumstances (except a major server crash). If you define endCallback
, but do not set safe = true
the endCallback
will only be executed when the task ends, because the limit of howOften
was reached.
Chainable runnables
This makes it possible to do resource intensive tasks asynchronous and then doing something with the result synchronous (e.g. because Spigot forces you) in a simple way.
kSpigot.firstAsync {
// do a resource intensive task
ArrayList<Block>() // -> this will be forwarded to the next part of the chain as "it"
}.thenSync {
// do something with the result
it?.forEach { }
}.thenAsync {
// and so on...
}
Inventory GUI API
Tutorial coming soon...
Powerful builders
For items
val wand = itemStack(Material.GOLD_BLOCK) {
amount = 3
addEnchantment(Enchantment.KNOCKBACK, 2)
meta {
name = "${ChatColor.GOLD}Magic wand"
isUnbreakable = true
addLore {
+ "This wand is truly special."
+ "Try it!"
}
customModel = 1001
flag(ItemFlag.HIDE_UNBREAKABLE)
}
}
For complex chat components
val component = chatComponent {
text("You got a friend request! ") {
color = col("#4FEA40")
isBold = true
}
text("[Accept]") {
color = ChatColor.WHITE
clickEvent(ClickEvent.Action.RUN_COMMAND, "friend accept Foo")
hoverEventText {
text("Click here to accept the friend request!") { color = ChatColor.RED }
}
}
}
You can also access the builder by calling
commandSender.sendMessage { /* same in here as above */ }
And more
A lot of additional things are also suitable for builders. Just like fireworks etc...
NBTData support
Typesafe and consistent
// load nbt
val nbt = entity.nbtData
// retrieve data via keys
val health = nbt["hearts", NBTDataType.INT]
// set data for a given key
nbt["custom", NBTDataType.DOUBLE] = 3.3
// save data to the entity
entity.nbtData = nbt
// serialization support
val serializedString = nbt.serialize()
val deserializeMethod1 = NBTData(serializedString)
val deserializeMethod2 = NBTData.deserialize(serializedString)
Simple extension methods / values (with kotlin getters)
livingEntity.isInWater // checks if both feet and head are in water
livingEntity.isHeadInWater // checks if the head (eye location) is in water
entity.isFeetInWater // checks if the feet are in water
entity.isGroundSolid // checks if the entity stands on a solid material
damageable.kill() // instantly kills the damageable
livingEntity.heal() // sets the health to the maximum health (if given - else throws Exception)
player.feed() // sets the players food level to 20
player.saturate() // sets the players saturation level to the current max value
player.feedSaturate() // sets the players food and saturation level to 20
player.disappear(plugin) // all other players won't be able to see the player anymore
player.appear(plugin) // show the player to every other player
vector.isFinite // checks if x, y and z of the vector are all finite
playerInteractEntityEvent.interactItem // gets the item the player interacted with
prepareItemCraftEvent.isCancelled // checks if the event isCancelled
prepareItemCraftEvent.cancel() // cancels the PrepareItemCraftEvent
Direction API
Handles the hassle of struggling with direction angles for you.
val cardinal = CardinalDirection.fromLocation(loc) // NORTH, EAST, SOUTH, WEST
val vertical = VerticalDirection.fromLocation(loc) // UP, DOWN, STRAIGHT
// convert to BlockFace
val blockFace = cardinal.facing
CustomItemIdentifiers
You want to mess with resourcepacks and extend your possibilities?
Spigot is lacking a representation of custom items (via custom model data). This is what the data class CustomItemIdentifier
is for!
val identifier = CustomItemIdentifier(itemStack)
// or
val identifier = CustomItemIdentifier(1001, Material.IRON_NUGGET)
// get an itemstack with the custom model data applied
val stack = identifier.itemStack
Flexible and chainable geometry syntax
Makes complex modification of locations and vectors more intuitive. Also, you can use any type of number (Short
, Int
, Long
, Float
, Double
) you want. You do not have to mess with different data types.
loc increaseX 3 reduce vec(3.0, 1.5f, 3) increaseYZ 5.7
loc + vecXY(3, 7f) - vecZ(3)
loc - vec(x = 3, z = 5.6f) * 3 * vecXZ(7, 3.1)
Listeners made easy
Kotlins' language design allows you to create listeners in a very short way.
kSpigot.listen<PlayerMoveEvent> {
it.player.kick("Do not move!")
}
NOTE:
- This method automatically registers the listener.
- The
listen<Event>
method returns the listener instance.
The following extension methods can be used on any listener:
listener.register(plugin)
listener.unregister()
Structures
Tutorial coming soon...
IP Address API
Tutorial coming soon...
Particles
Tutorial coming soon...
GamePhase API
Tutorial coming soon...
Any questions? Feel free to contact me!