All Projects → hazae41 → Mc Kutils

hazae41 / Mc Kutils

Licence: mit
The ultimate Kotlin library for Minecraft plugin development

Programming Languages

kotlin
9241 projects

Labels

Projects that are alternatives of or similar to Mc Kutils

Fruitphone
An immersive Waila-compatible information mod. Maintained by Falkreon.
Stars: ✭ 10 (-69.7%)
Mutual labels:  minecraft
Factory Rise
Factory Rise is a 2D sandbox game, focused on building, developing industries and handling resources. The game is based on Oxygen Not Included, Terraria, Factorio and some Minecraft mods (EnderIO, Industrial Craft, BuildCraft, GregTech and Thermal Expansion), it also have a game progress similar to StarBound.
Stars: ✭ 21 (-36.36%)
Mutual labels:  minecraft
Unifiedmetrics
Fully-featured metrics collection agent for Minecraft servers. Supports Prometheus and InfluxDB. Dashboard included out-of-box.
Stars: ✭ 29 (-12.12%)
Mutual labels:  minecraft
Nbt
An NBT library for Minecraft.
Stars: ✭ 12 (-63.64%)
Mutual labels:  minecraft
Zenscript Highlighter
Sublime Text highlighting for ZenScript used in MineTweaker, CraftTweaker and ModTweaker
Stars: ✭ 15 (-54.55%)
Mutual labels:  minecraft
Transport Pipes
Buildcraft without mods!
Stars: ✭ 21 (-36.36%)
Mutual labels:  minecraft
Ratchetandclankmod
Stars: ✭ 8 (-75.76%)
Mutual labels:  minecraft
Essentials
The essential plugin suite for Minecraft servers.
Stars: ✭ 957 (+2800%)
Mutual labels:  minecraft
Realistictorches
A Minecraft mod that increases the difficulty of the early game by adding realism mechanics to torches.
Stars: ✭ 15 (-54.55%)
Mutual labels:  minecraft
Powernbt
Minecraft PowerNBT plugin
Stars: ✭ 29 (-12.12%)
Mutual labels:  minecraft
Craftstudioapi
The official CraftStudio API for Minecraft
Stars: ✭ 12 (-63.64%)
Mutual labels:  minecraft
Railcraft Api
An API for interacting with Railcraft.
Stars: ✭ 14 (-57.58%)
Mutual labels:  minecraft
Blur
Minecraft Game Engine written in Java & Kotlin
Stars: ✭ 21 (-36.36%)
Mutual labels:  minecraft
Mwt
A basic set of web-based tools for Minecraft and things related to it.
Stars: ✭ 11 (-66.67%)
Mutual labels:  minecraft
Pocket Minecraft Protocol
[En][de]code Minecraft packets
Stars: ✭ 30 (-9.09%)
Mutual labels:  minecraft
Chameleoncreepersmod
Minecraft Mod that makes creepers harder to see by tinting their color based on their surroundings - over 120k downloads!
Stars: ✭ 9 (-72.73%)
Mutual labels:  minecraft
Emc
The EMC Framework (Easy Minecraft Client) - An easy to use Minecraft modding framework
Stars: ✭ 21 (-36.36%)
Mutual labels:  minecraft
Mineflayer Statemachine
A state machine plugin for Mineflayer to aid in designing more complex behavior trees.
Stars: ✭ 32 (-3.03%)
Mutual labels:  minecraft
Holovid
Stream videos from websites, all in-game!
Stars: ✭ 31 (-6.06%)
Mutual labels:  minecraft
Feedthebeast Docker Servers
FTB Minecraft servers dockerized
Stars: ✭ 27 (-18.18%)
Mutual labels:  minecraft





Go to Spigot

Go to JitPack

Usage

Simplified componentization

You can componentize and colorize any message

With Kotlin4MC
textOf("&bHello world!")
Without Kotlin4MC
TextComponent(*fromLegacyText(ChatColor.translateAlternateColorCodes("&", "&bHello world")))

Simplified messages sending

Let's send a message to a player (any Player, ProxiedPlayer, CommandSender is supported)

With Kotlin4MC
player.msg("&bHello world!")
Without Kotlin4MC (not deprecated)
player.sendMessage(TextComponent(*fromLegacyText(ChatColor.translateAlternateColorCodes("&", "&bHello world"))))

Simplified event listening

You can use listen() to easily listen to events

With Kotlin4MC
listen<PlayerJoinEvent>{
  it.player.msg("Hello world!")
}
Without Kotlin4MC
server.pluginManager.registerEvent(object: Listener{
  @EventHandler
  fun onPlayerJoin(e: PlayerJoinEvent){
      e.player.sendMessage("Hello world!")
  }
}, this)
In Java
getServer().getPluginManager().registerEvents(new Listener() {
  @EventHandler
  public void onPlayerJoin(PlayerJoinEvent e){
      e.getPlayer().sendMessage("Hello world!");
  }
}, this);

You can also use priorities

listen<PlayerJoinEvent>(HIGHEST){
  it.player.msg("This will be the first")
}

Simplified scheduling

schedule(delay = 10){
    // this will be executed after 10 seconds
}

schedule(delay = 10, period = 20){
    // this will be executed after 10 seconds then each 20 seconds
}

schedule(async = true){
    // this will be executed asynchronously now
}

schedule(true, delay = 20){
    // this will be executed asynchronously after 20 seconds
}

schedule(true, period = 3, unit = TimeUnit.MINUTES){
    // this will be executed asynchronously each 3 minutes
}

// Tasks can cancel themselves
schedule(period = ...) {
    if(...) cancel()
}

Fast access to files of a directory

You can easily access a file or a subfolder with the get() operator applied to a File

With Kotlin4MC
val config = dataFolder["config.yml"]
val lang = dataFolder["langs"]["en_US.yml"]
Without Kotlin4MC
val config = File(dataFolder, "config.yml")
val lang = File(File(dataFolder, "langs"), "en_US.yml")

Type aliases for multi-platform plugins

If you want to specify the platform of any type, just add "Bungee" or "Bukkit" before its name

With Kotlin4MC: both platforms on the same file
class MyPluginOnBungee: BungeePlugin(){
    override fun onEnable() = info("Hello Bungee!")
}

class MyPluginOnBukkit: BukkitPlugin(){
    override fun onEnable() = info("Hello Bukkit!")
}
Without Kotlin4MC: two separated files for each platform

Simple configuration loading

Load the config from the data folder, otherwise, copy it from the resource "config.yml".

If there is an error, do not continue.

val configFile = dataFolder["config.yml"]
val config = loadConfig(configFile, "configs/config.yml")
// Will load resource configs/config.yml

You can ommit the resource argument, it will copy the resource of the same name as the file

val configFile = dataFolder["config.yml"]
val config = loadConfig(configFile) // Will load resource "config.yml"

Delegated configuration

You can use delegated configuration to manage big configurations

class MyPlugin: BukkitPlugin(){

    object MyConfig: ConfigFile("config"){
        var debug by boolean("debug")
        var alertMessage by string("alert-message")
        var enabledWorlds by stringList("enabled-worlds")
    }

    override fun onEnable(){
        // Initialize the object with the current file
        init(MyConfig) // (it will copy the resource config.yml to the data folder)
        // We can access properties dynamically
        info("debug: " + MyConfig.debug)
        // Change them (if "var" is used)
        MyConfig.debug = false
        // Save them (if auto-saving is disabled)
        MyConfig.save()
        // Reload the config from the file
        MyConfig.reload()
    }
}

You have to init the configuration only if you're using a resource

ConfigFile(file: File)
// This will load the config from the file
// No init() required

ConfigFile(path: String)
// This will copy the resource located at path to a file of the same path in the data folder
// Needs to be initialized with init(plugin) or plugin.init(config)
// You can ommit the .yml in the path
// You can specify the resource to copy with init(plugin, resourcePath)

You can pass multiple ConfigFile to the init() like

init(Options, Players, Worlds, ...)

By default, the configuration is saved every time a property is changed

You can disable auto-saving by doing

MyConfig.autoSave = false

or changing the constructor

object MyConfig: ConfigFile("config", false){
    ...
}

You can also use sections

object MySection: ConfigSection(MyConfig, "mysection"){
    val host by string("host")
    val port by int("port")
}

And parameters

inner class PlayerInfo(uuid: UUID): ConfigFile(dataFolder["$uuid.yml"]){
    val friends by stringList("friends")
    // ...
}

val Player.info get() = PlayerInfo(uniqueId)
val Player.friends get() = info.friends
class SocketConfig(id: String): ConfigSection(MyConfig, "sockets.$id"){
    val host by string("host")
    val port by int("port")
}

fun address(id: String){
    val config = SocketConfig(id)
    return config.host + ":" + config.port
}

Fast logging

You can use info(), warning() and severe() with String or Exception to log them in the console

You can also use logToFile() to write to a file named "log.txt" in your plugin's data folder

With Kotlin4MC
info("Hello world!")
Without Kotlin4MC
logger.info("Hello world!")
In Java
getLogger().info("Hello world!");

Simplified commands

With Kotlin4MC
// Example on Bukkit
command("hello"){ sender, args ->
    if(args.isEmpty())
        sender.msg("&cWrong arguments, usage: $usage")
    else sender.msg("&bHello!")
}

// You can apply the executor directly to the sender
command("test") { 
    args -> msg("&bYou said $args") 
}
Without Kotlin4MC
// Bungee
proxy.pluginManager.registerCommand(this,
    object: Command("hello"){
        override fun execute(sender: CommandSender, args: Array<String>){
            sender.sendMessage("§bHello!")
        }
    }
)

// Bukkit
getCommand("hello").executor = CommandExecutor {
    sender, command, label, args ->
    sender.sendMessage("§bHello!")
    true
}

Plugin updates checker

You can check for updates of your plugin using Spiget

Just use update() with your Spigot resource ID

update(15938)

You can specify the color

update(15938, LIGHT_PURPLE)

and the permission (the default permission is "rhaz.update")

update(15938, LIGHT_PURPLE, "myplugin.updates")

Advanced exception catching

Exceptions can be catched with a beautiful syntax

With Kotlin4MC
// This will catch any exception and log it as a warning
catch<Exception>(::warning){
    // ex() is a short replacement of Exception()
    throw ex("An error occured")
}
Without Kotlin4MC
try{
    throw Exception("An error occured")
} catch(ex: Exception){
    warning(ex)
}
Catch only specific exceptions
// The callback can be ommited, the default one is ::printStackTrace
catch<CommandException>{
    throw Exception("This won't be catched")
}
Catch and redirect to the sender
val sender: CommandSender = ...
catch<Exception>(sender::msg){
    if(sender !is Player)
        throw ex("&cYou're not a player!")
    sender.gamemode = GameMode.CREATIVE
    sender.msg("&bYou're now in creative mode :)")
}
Custom callbacks
// Tell the admins about the exception
val admins = server.onlinePlayers.filter{it.hasPermission("test.admin")}
fun tellToAdmins(ex: Exception) = admins.forEach{it.msg(ex)}

catch<Exception>(::tellToAdmins){
    throw ex("Alert!")
}


// Anonymous callback that prepend the warning with "An error occured"
catch<Exception>({ warning("An error occured: ${it.message}")}){
    throw ex(...)
}
Custom exceptions
class RedException(message: String): Exception(){
    override val message = "&c$message"
}

fun test(){
    catch<RedException>(::warning){
        throw RedException("This message will be red")
    }    
}
Catching with result, callback and default value
fun default(ex: Exception) =
    {warning(ex); "This is the default message"}()

val msg = catch(::default){
    val line1 = read() ?: throw ex("Could not read first line")
    val line2 = read() ?: throw ex("Could not read second line")
    val line3 = read() ?: throw ex("Could not read third line")
    info("Sucessfully read three lines")
    "$line1, $line2, $line3"
    // Return the three lines separated by "," 
}

// Will print "This is the default message"
// if one of the three lines could not be read
info("The message is: $msg")

Short inequality checks

You can use .not() to check inequality of any object

"object.not(other)":

  • returns null if object == other
  • returns object if object != other
With Kotlin4MC
val delay = config.getLong("delay").not(0) // Assignment + Check
    ?: return warning("Delay should not be 0")
Without Kotlin4MC
val delay = config.getLong("delay")  // Assignment
if(delay == 0) return warning("Delay should not be 0") // Check
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].