KtSkript - Endless customizations for your server

KtSkript is a plugin which allows you to write scripts for your server. It is ideal for very custom modifications for your server.

Kt means Kotlin, the programming language used for scripts.

Skript, well the old Bukkit plugin, I just wanted people to know what this plugin does.

Download (not on Ore yet, plugin jar is too large)

Wiki (a must read)

------- Example scripts -------

===> Get quick help on my Discord server <===

7 Likes

New release: v1.1

Download

Changes:

  • Fixed a bug which stopped the monitoring for script file changes when a script failed to execute
  • Fixed a bug which prevented script specific .imports file from being actually used
  • As of now, by default the default.imports file is ignored; changes will be respected and not overwritten only if the config option is enabled
  • Added config option for more log verbosity

New release: v1.1.1

Download

Changes:

  • Fixed a bug on Windows

New release: v1.1.2

Download

Changes:

  • Fixed a bug which prevented the automatic script reloading

New release: v1.1.3

Download

Changes:

  • Fixed a bug with the spawning event
  • Fixed warnings on Windows

Can you write an example of adding commands and permissions?

If you have any questions, let me know. I think discord is a better place to discuss individual things.

New release: v1.1.4

Download

Changes:

  • Fixed a bug which caused empty hands not being recognized correctly, this was due to a recent change in Sponge

I realized I may get more people to use this plugin if I add more helpful example scripts. All those scripts are ready to use, but I encourage you to edit them to get the best results for your desired server experience.

I plan on adding more scripts somewhat regularly. This is the first one.


Custom join messages for staff members

Have a look at this very simple script.

val staffMembers = listOf(
  "KitCrafty",
  "Notch"
)

onPlayerJoin {
  if (player.name in staffMembers) {
    setMessage("&2The legendary ${player.name} has joined the server!".t)
  }
}

You can change the message as you like, with all the normal Minecraft color codes. Adding new players in the list should be self-explanatory.


That’s it for today, I appreciate suggestions from you guys.

1 Like

This is a pretty cool use for Kotlin! Have you done any testing to see how well a KtScript performs when compared to the same thing implemented in a compiled plugin, or does this work in a similar way to Kotlin itself under normal conditions?

Thanks!

I haven’t done any benchmarking yet. I guess the only performance hit is the compiling itself, it is done at startup, at reload and when scripts are modified/deleted/created. The Kotlin compiler is under steady improvement.

Once compiled, it is just another loaded JVM class. Ofc the kotlin runtime and stdlib is another added layer, but this “issue” is present in any other real compiled Kotlin plugin/program/app. The Kotlin compiler itself and the JVM runtime inline many things.

I think I could simplify more things with Kotlin’s DSL, like scheduling tasks. But I don’t want to cover the SpongeAPI completly lol.

Btw: One thing I am not very happy with is NMS code. I haven’t been able to find the correct classloader and import them properly at runtime. So NMS stuff isn’t possible yet. Maybe that will change once I migrate from FastClasspathLoader to ClassGraph.

1 Like

Simple roleplay chat

Script on GitHub

val SHOUTING_PREFIX = "!"

registerListener<MessageChannelEvent.Chat> {

  val isShouting = rawMessage.toPlain().startsWith(SHOUTING_PREFIX)

  val range = if (isShouting) 100 else 50
  val playerLoc = causingPlayer.location
  val targetedPlayers = playerLoc.extent
    .getNearbyEntities(playerLoc.position, range.toDouble())
    .mapNotNull { it as? Player }
  setChannel(MessageChannel.fixed(targetedPlayers))

  formatter.setBody(rawMessage.toPlain().removePrefix(SHOUTING_PREFIX).toText())
  
  val prefix = if (isShouting) "&7[&aShout&7] ".t else "&7[&aLocal&7] ".t
  formatter.setHeader(prefix + formatter.header.toText())
}

This is a roleplay chat system which limits the range players can “understand” each other. This was suggested by @Louie_Beltran here.

By default players can chat with each other as in vanilla Minecraft within 50 blocks. To extend that range to 100 a ! has to be appending before the message.
Modify the script as you like, change the shouting prefix, the range or anything else. Let me know if you have any questions.

wheres the permission to be able to use this?

Insert this at the top of the listener:

if (!causingPlayer.hasPermission("bla.bla")) return

Hey RandomByte, how to just target certain region of foxguard?

example, player break a block in foxguard region or in a location pos1 and location pos2. execute command.

FoxGuard doesn’t seem to have a public API, but other plugins (or a script) can still interact with FoxGuard nevertheless. Though you would have to dig through the code and find the respective methods for getting a region and then checking if it is inside that. There’s no built-in shortcut for that in KtSkript.
So I advise you to get familiar with FoxGuard’s code and how to get a region/all regions and then checking if some position is inside a region. Maybe you will get help from the developer.

It may be easier for you to just check if some position is inside a hard coded area, if that would work for you.

It would look like this:

val pos = v3(3, 1, 3)
val area = v3(0, 0, 0)..v3(10, 10, 10)
if (pos in area) {
  println("pos really is in area!")
}

oh okay cool XD I’ll try it out.

Replacements for block break drops

Script on GitHub

val replacements = mapOf(

  "minecraft:log" to "minecraft:diamond",
  "minecraft:stone" to "minecraft:gold_ingot"

).mapValues { (_, itemTypeId) ->
  ItemStack.of(Sponge.getRegistry().getType(ItemType::class.java, itemTypeId).get(), 1).createSnapshot()
}

registerListener<SpawnEntityEvent> {
  entities
    .filter { it is Item }
    .forEach { item ->
      if (context.get(EventContextKeys.SPAWN_TYPE).orNull() == SpawnTypes.DROPPED_ITEM) {
        val brokenBlockSnapshot = context.get(EventContextKeys.BLOCK_HIT).orNull() ?: return@forEach
        val replacement = replacements[brokenBlockSnapshot.state.type.id] ?: return@forEach
        item.tryOffer(Keys.REPRESENTED_ITEM, replacement)
      }
    }
}

This script can replace block drops with other items. The replacements can be defined at the top.

The script can definitely be worked on to support custom data, other variants of item drops or even add more requirements (like having to have a special item in the inventory to produce a different drop).

Hey can someone help me out? I need a sckript that disables all of my mod messages that my mods bring in, when they join all that junk pops up in chat, PLEASE HELP