Documentation Index
Fetch the complete documentation index at: https://mintlify.com/qualk/take-care/llms.txt
Use this file to discover all available pages before exploring further.
Meteor modules are the toggleable features that appear in the module list (accessed with the Right Shift key by default). Each module extends meteordevelopment.meteorclient.systems.modules.Module, declares its settings through a builder pattern on SettingGroup objects, and subscribes to game events using @EventHandler-annotated methods. Take Care ships two modules — Asset Protection and Parrot Deadener — which serve as real-world examples of the pattern described below.
Creating a module
Create a class extending Module
Add a new Java class inside the modules/ package (kpn.qualk.takecare.modules). The class must extend meteordevelopment.meteorclient.systems.modules.Module:package kpn.qualk.takecare.modules;
import kpn.qualk.takecare.TakeCare;
import meteordevelopment.meteorclient.systems.modules.Module;
public class YourModule extends Module {
public YourModule() {
super(TakeCare.CATEGORY, "your-module", "A short description.");
}
}
Call super() with the category, name, and description
The Module constructor takes three arguments:| Argument | Value |
|---|
category | TakeCare.CATEGORY — the shared “Take Care” category declared in TakeCare.java |
name | A kebab-case string, e.g. "asset-protection" |
description | A plain-text sentence shown in the module list tooltip |
The name parameter in super(...) must be in kebab-case (e.g. "asset-protection", not "AssetProtection" or "asset_protection"). Meteor uses this string as the module’s unique identifier and display name.
Define settings with SettingGroup and the builder pattern
Settings are declared as private final fields on the class. Retrieve the default group from settings.getDefaultGroup() or create a named group with settings.createGroup("GroupName"). Each setting is added via the add() method on the group, using a typed builder.The following example from AssetProtection.java shows three BoolSetting entries:modules/AssetProtection.java
private final SettingGroup sgGeneral = settings.getDefaultGroup();
public final Setting<Boolean> protectTamed = sgGeneral.add(new BoolSetting.Builder()
.name("protect-tamed")
.description("Protects your tamed animals from your attacks.")
.defaultValue(true)
.build()
);
public final Setting<Boolean> protectVillagers = sgGeneral.add(new BoolSetting.Builder()
.name("protect-villagers")
.description("Protects villagers from your attacks.")
.defaultValue(true)
.build()
);
public final Setting<Boolean> mimicInvulnerability = sgGeneral.add(new BoolSetting.Builder()
.name("mimic-invulnerability")
.description("Plays the invulnerable hit sound when you try to attack a protected entity.")
.defaultValue(true)
.build()
);
Read the current value of a setting at runtime with setting.get(). React to game events with @EventHandler
Annotate private methods with @EventHandler (from meteordevelopment.orbit) to subscribe to Meteor’s event bus. The method parameter type determines which event is delivered.AssetProtection listens to AttackEntityEvent to intercept player attacks:modules/AssetProtection.java
@EventHandler
private void onAttackEntity(AttackEntityEvent event) {
boolean protect = false;
if (protectTamed.get() && event.entity instanceof OwnableEntity owned) {
EntityReference<LivingEntity> ownerRef = owned.getOwnerReference();
if (ownerRef != null && ownerRef.getUUID().equals(mc.player.getUUID())) {
protect = true;
}
}
if (!protect && protectVillagers.get() && event.entity instanceof AbstractVillager) {
protect = true;
}
if (protect) {
if (mimicInvulnerability.get()) {
mc.player.playSound(SoundEvents.PLAYER_ATTACK_NODAMAGE, 1.0F, 1.0F);
}
event.cancel();
}
}
Event handlers are only active while the module is enabled. Meteor handles subscription and unsubscription automatically when the module is toggled. Register the module in TakeCare.onInitialize()
Open TakeCare.java and call Modules.get().add(new YourModule()) inside onInitialize(). The onRegisterCategories() override in the same file ensures TakeCare.CATEGORY is registered with Meteor before modules are added.@Override
public void onInitialize() {
LOG.info("Initialising Meteor addon: " + getPackage());
Modules.get().add(new AssetProtection());
Modules.get().add(new ParrotDeadener());
// Modules.get().add(new YourModule());
}
Full working example
Below is the complete AssetProtection module as it appears in the Take Care source:
modules/AssetProtection.java
package kpn.qualk.takecare.modules;
import kpn.qualk.takecare.TakeCare;
import meteordevelopment.meteorclient.events.entity.player.AttackEntityEvent;
import meteordevelopment.meteorclient.settings.BoolSetting;
import meteordevelopment.meteorclient.settings.Setting;
import meteordevelopment.meteorclient.settings.SettingGroup;
import meteordevelopment.meteorclient.systems.modules.Module;
import meteordevelopment.orbit.EventHandler;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.EntityReference;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.OwnableEntity;
import net.minecraft.world.entity.npc.villager.AbstractVillager;
public class AssetProtection extends Module {
private final SettingGroup sgGeneral = settings.getDefaultGroup();
public final Setting<Boolean> protectTamed = sgGeneral.add(new BoolSetting.Builder()
.name("protect-tamed")
.description("Protects your tamed animals from your attacks.")
.defaultValue(true)
.build()
);
public final Setting<Boolean> protectVillagers = sgGeneral.add(new BoolSetting.Builder()
.name("protect-villagers")
.description("Protects villagers from your attacks.")
.defaultValue(true)
.build()
);
public final Setting<Boolean> mimicInvulnerability = sgGeneral.add(new BoolSetting.Builder()
.name("mimic-invulnerability")
.description("Plays the invulnerable hit sound when you try to attack a protected entity.")
.defaultValue(true)
.build()
);
public AssetProtection() {
super(TakeCare.CATEGORY, "asset-protection",
"Protects your tamed animals and villagers from your attacks.");
}
@EventHandler
private void onAttackEntity(AttackEntityEvent event) {
boolean protect = false;
if (protectTamed.get() && event.entity instanceof OwnableEntity owned) {
EntityReference<LivingEntity> ownerRef = owned.getOwnerReference();
if (ownerRef != null && ownerRef.getUUID().equals(mc.player.getUUID())) {
protect = true;
}
}
if (!protect && protectVillagers.get() && event.entity instanceof AbstractVillager) {
protect = true;
}
if (protect) {
if (mimicInvulnerability.get()) {
mc.player.playSound(SoundEvents.PLAYER_ATTACK_NODAMAGE, 1.0F, 1.0F);
}
event.cancel();
}
}
}