Dominion Addon Development Skill
You are an expert developer for Dominion addon plugins (Minecraft Paper/Spigot). Dominion is a land-claim protection plugin; addons extend it using the DominionAPI.
Key References
- JavaDoc: https://lunadeermc.github.io/DominionAPI/
- Documentation: https://github.com/LunaDeerMC/DominionDocs
- API Reference: Load
references/dominion-api-reference.mdfor complete API details.
Project Setup
Gradle (Kotlin DSL) — Recommended
repositories {
mavenLocal()
mavenCentral()
maven("https://oss.sonatype.org/content/groups/public")
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://jitpack.io")
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.20.1-R0.1-SNAPSHOT")
compileOnly("cn.lunadeer:DominionAPI:4.7.3")
}
Gradle (Groovy)
dependencies {
compileOnly 'cn.lunadeer:DominionAPI:4.7.3'
}
Maven
<dependency>
<groupId>cn.lunadeer</groupId>
<artifactId>DominionAPI</artifactId>
<version>4.7.3</version>
<scope>provided</scope>
</dependency>
plugin.yml Requirements
The addon's plugin.yml MUST include Dominion in the depend list:
name: YourAddonPlugin
version: '1.0.0'
main: com.example.yourplugin.YourPlugin
api-version: '1.20'
depend:
- Dominion
Set folia-supported: true if your addon supports Folia.
Getting the API Instance
Always obtain DominionAPI in onEnable() after verifying the Dominion plugin is loaded:
import cn.lunadeer.dominion.api.DominionAPI;
public final class YourPlugin extends JavaPlugin {
private DominionAPI dominionAPI;
@Override
public void onEnable() {
if (Bukkit.getPluginManager().isPluginEnabled("Dominion")) {
dominionAPI = DominionAPI.getInstance();
getLogger().info("DominionAPI loaded successfully");
} else {
throw new IllegalStateException("Dominion plugin is not enabled.");
}
getServer().getPluginManager().registerEvents(this, this);
}
}
Core API Patterns
1. Query Dominion Data (Read-Only)
Use DominionAPI methods for all read operations — they read from cache and are safe on any thread.
// Get dominion at a location
DominionDTO dom = dominionAPI.getDominion(player.getLocation());
// Get dominion by name or ID
DominionDTO dom = dominionAPI.getDominion("myDominion");
DominionDTO dom = dominionAPI.getDominion(42);
// Get player's current dominion
DominionDTO current = dominionAPI.getPlayerCurrentDominion(player);
// Get all dominions owned by a player
List<DominionDTO> owned = dominionAPI.getAllDominionsOfPlayer(player.getUniqueId());
// Get player info
PlayerDTO playerDTO = dominionAPI.getPlayer(player.getUniqueId());
// Get member in a dominion
MemberDTO member = dominionAPI.getMember(dom, player);
// Get group of a member
GroupDTO group = dominionAPI.getGroup(member);
2. Check Flags
// Check privilege flag (with player notification on denial)
boolean canBuild = dominionAPI.checkPrivilegeFlag(location, priFlag, player);
// Check privilege flag silently (no notification)
boolean canBuild = dominionAPI.checkPrivilegeFlagSilence(location, priFlag, player);
// Check environment flag
boolean hasFire = dominionAPI.checkEnvironmentFlag(location, envFlag);
Important (since 4.5.0): Always prefer the Location-based overloads over DominionDTO-based overloads. The Location-based methods also check world-wide flags.
3. Modify Data via Providers
All data modifications MUST go through Providers to ensure consistency and trigger events.
Provider methods are asynchronous and return CompletableFuture.
The operator parameter controls permission checks:
- Pass a
Playerto enforce permission checks - Pass
Bukkit.getConsoleSender()to bypass permission checks (console-level access)
// DominionProvider — create, delete, rename, resize, transfer dominions
DominionProvider domProvider = dominionAPI.getDominionProvider();
CompletableFuture<DominionDTO> future = domProvider.createDominion(
Bukkit.getConsoleSender(), // operator
"newDominion", // name
playerUUID, // owner
world, // world
new CuboidDTO(x1,y1,z1, x2,y2,z2), // boundaries
null, // parent (null = top-level)
false // skipEconomy
);
DominionDTO created = future.get(); // null means failure
// GroupProvider — create, delete, rename groups; manage group members and flags
GroupProvider groupProvider = dominionAPI.getGroupProvider();
// MemberProvider — add, remove members; set member flags
MemberProvider memberProvider = dominionAPI.getMemberProvider();
4. Listen to Dominion Events
Register listeners the standard Bukkit way. All events extend CallableEvent.
import cn.lunadeer.dominion.events.dominion.DominionCreateEvent;
import cn.lunadeer.dominion.events.member.MemberAddedEvent;
public class MyListener implements Listener {
@EventHandler
public void onDominionCreate(DominionCreateEvent event) {
if (event.isCancelled()) return;
// React to dominion creation
}
@EventHandler
public void onMemberAdded(MemberAddedEvent event) {
if (event.isCancelled()) return;
// Use callback to get the result after data is processed
event.afterAdded(memberDTO -> {
if (memberDTO == null) return; // addition failed
DominionDTO dominion = event.getDominion();
Player player = Bukkit.getPlayer(memberDTO.getPlayerUUID());
if (player != null) {
player.teleportAsync(dominion.getTpLocation());
}
});
}
}
Key event categories:
| Package | Events |
|---|---|
cn.lunadeer.dominion.events |
PlayerMoveInDominionEvent, PlayerMoveOutDominionEvent, PlayerCrossDominionBorderEvent, FlagRegisterEvent |
cn.lunadeer.dominion.events.dominion |
DominionCreateEvent, DominionDeleteEvent |
cn.lunadeer.dominion.events.dominion.modify |
DominionRenameEvent, DominionSizeChangeEvent, DominionSetEnvFlagEvent, DominionSetGuestFlagEvent, DominionSetMapColorEvent, DominionSetMessageEvent, DominionSetTpLocationEvent, DominionTransferEvent |
cn.lunadeer.dominion.events.group |
GroupCreateEvent, GroupDeleteEvent, GroupRenamedEvent, GroupSetFlagEvent, GroupAddMemberEvent, GroupRemoveMemberEvent |
cn.lunadeer.dominion.events.member |
MemberAddedEvent, MemberRemovedEvent, MemberSetFlagEvent |
Data operation events (like DominionCreateEvent, MemberAddedEvent) process the actual data after all listeners run. Use provided callback methods (e.g., event.afterAdded(...)) to access results.
5. Register Custom Flags (since 4.7.0)
Two flag types exist:
EnvFlag— environment flags (not player-specific, e.g., weather control)PriFlag— privilege flags (player-specific, e.g., can-build)
import cn.lunadeer.dominion.api.dtos.flag.EnvFlag;
import cn.lunadeer.dominion.api.dtos.flag.PriFlag;
import cn.lunadeer.dominion.api.dtos.flag.Flags;
// Define custom flags
public static EnvFlag NO_RAIN = new EnvFlag(
"no_rain", // unique flag_name (no spaces)
"No Rain", // display_name
"Prevents rain in this dominion.", // description
false, // default_value
true, // enabled
Material.SUNFLOWER // CUI material icon
);
public static PriFlag CUSTOM_ACTION = new PriFlag(
"custom_action", // unique flag_name (no spaces)
"Custom Action", // display_name
"Allows custom action in dominion.", // description
false, // default_value
true, // enabled
Material.RED_BED // CUI material icon
);
// Register and apply in onEnable()
Flags.registerEnvFlag(NO_RAIN);
Flags.registerPriFlag(CUSTOM_ACTION);
Flags.applyNewCustomFlags(); // Must call after registration
DTO Quick Reference
| DTO | Key Methods |
|---|---|
DominionDTO |
getId(), getName(), getOwner(), getWorld(), getCuboid(), getTpLocation(), getEnvFlagValue(flag), getGuestFlagValue(flag), getGroups(), getMembers(), getParentDomId(), getJoinMessage(), getLeaveMessage() |
PlayerDTO |
getId(), getUuid(), getLastKnownName(), getSkinUrl(), getUiPreference() |
MemberDTO |
getId(), getPlayerUUID(), getDomID(), getGroupId(), getFlagValue(flag), getPlayer() |
GroupDTO |
getId(), getDomID(), getNamePlain(), getNameRaw(), getFlagValue(flag), getMembers() |
CuboidDTO |
getPos1(), getPos2(), x1()..z2(), xLength(), yLength(), zLength(), getSquare(), getVolume(), contain(...), intersectWith(...) |
Rules
- DominionAPI is a
compileOnly/provideddependency — never shade it into your jar. - Always verify
Dominionis enabled before callingDominionAPI.getInstance(). - Use
Location-based flag checks overDominionDTO-based ones (since 4.5.0) to include world-wide flags. - All Provider operations are async (
CompletableFuture) — handle appropriately. - Event callbacks (e.g.,
afterAdded) run after actual data processing — use them for post-operation logic. - Custom flag names must be unique and contain no spaces.
- Call
Flags.applyNewCustomFlags()after registering all custom flags. - Never modify DTO data directly — always use Providers for writes.
- Paper API 1.20.1+ is the minimum supported version.
- The plugin must declare
depend: [Dominion]inplugin.yml.
Source: LunaDeerMC/Dominion — distributed by TomeVault.