A template to create your own MChallenge addon. This addon is developed in Kotlin and as a PaperMC plugin. You can create MChallenge addons for all platforms as long as MChallenge supports them too (Paper & Fabric).
More information - MUtils Website
IMPORTANT
MChallenge addons must be published under the same licence as MUtils (AGPL v3) and must comply with the MUtils TOS
If you already know how to clone and access repositories, skip to step 3.
Just make sure to add themutils-addon
tag
Clone this repository to create your new addon and add the tag mutils-addon
by clicking on the cogwheel in the about section.
Create a new IntelliJ project and click on Project from Version Control
and enter your repository URL. Finally, wait for Gradle to load your new project.
Images - Click to unfold
Clone this template repository---
Copy your new repository link into IntelliJ
If you plan to publish your addon, you should rename the de.miraculixx
namespace to your own namespace. If you own a domain you can use this (e.g. mutils.net
-> net.mutils
).
To rename a file or package press shift
+ F6
, enter your new name and refactor.
Additionally, you need to apply your changes in the plugin.yml
file in the resources
folder by changing the main
attribute.
Add a new mod enum in the utils/AddonMod
enum class:
enum class AddonMod(val uuid: UUID) {
MOD_ONE(UUID.randomUUID()),
MOD_TWO(UUID.randomUUID()),
;
}
Additionally, each mod/challenge needs a default configuration (settings) and mod data (icon, name, ...).
You can add a default configuration by extending the getDefaultSetting()
function:
fun getDefaultSetting(): ChallengeData {
return when (this) {
MOD_ONE -> ChallengeData(emptyMap(), emptyMap()) // No settings
MOD_TWO -> ChallengeData( // One integer setting with id 'damage'
mapOf("damage" to ChallengeIntSetting("BEETROOT", 2, "hp", min = 1, max = 20)), // Setting data
mapOf("damage" to IconNaming(cmp("Setting Name"), listOf(cmp("Setting Lore")))), // Setting display
)
}
}
You can add mod data by extending the getModData()
function:
fun getModData(): CustomChallengeData {
return when (this) {
MOD_ONE -> CustomChallengeData(
uuid,
ModOneClass(),
AddonManager.getSettings(this),
Icon("CHEST", naming = IconNaming(cmp("Mod Name"), listOf(cmp("Mod Description")))),
setOf(ChallengeTags.FUN)
)
}
}
Finally, you have to add the core of your new mod, the logic! Create a new class inside the mods
package (e.g. ModOneClass
) and extend the Challenge
interface from MChallenge API.
You must override at least the register()
and unregister()
functions. A detailed description can be viewed by hovering over all API classes and functions or entering them with strg
+ left-click
.
A full example for a Mod that damage you on chest interactions:
class DamageOnChest : Challenge {
private var damage: Int = 2
override fun start(): Boolean {
// Refresh all mod settings and apply them
val settings = AddonManager.getSettings(AddonMod.DAMAGE_ON_CHEST_CLICK).settings
damage = settings["damage"]?.toInt()?.getValue() ?: 2
return true
}
override fun register() {
// Register our listener
onChestClick.register()
}
override fun unregister() {
// Unregister our listener
onChestClick.unregister()
}
/**
* We use KSpigot to easily implement our listeners.
*
* IMPORTANT
* - Set the listen state "register" to false, to prevent preloading the listener!
* - If you not use KSpigot for any reason, use a local state variable that toggles on and off in [register] and [unregister] and check the state at the start of your listener
*/
private val onChestClick = listen<PlayerInteractEvent>(register = false) {
val block = it.clickedBlock ?: return@listen
if (block.type != Material.CHEST) return@listen
it.player.damage(damage.toDouble())
}
}