Methods
The Mythic Dungeons developer API is exposed through the MythicDungeonsService interface. See Introduction to API for how to install the dependency and grab the service.
Service FQN:
net.playavalon.mythicdungeons.api.MythicDungeonsService
Dungeon Methods
isPlayerInDungeon
boolean isPlayerInDungeon(Player player)
Returns true if the player is currently inside any dungeon instance (play or edit mode). Returns false if the player is offline or in the regular server world.
getDungeonInstance (by player)
AbstractInstance getDungeonInstance(Player player)
Returns the instance the player is currently in, or null if they aren't in one.
Unlike isPlayerInDungeon, this getter does not self-heal a stale reference. It hands back whatever instance is recorded on the player's MythicPlayer, even if that instance no longer lists them. If you need certainty, check instance.getPlayers().contains(mythicPlayer) yourself, or call isPlayerInDungeon first, which validates the reference and clears it when it is stale.
getDungeonInstance (by world name)
AbstractInstance getDungeonInstance(String worldName)
Returns the first active instance whose world is named worldName, or null if none matches.
Two caveats:
- In One-World mode many instances share a single Bukkit world, so the world name does not identify an instance. The match is taken from a
ConcurrentHashMapwhose iteration order is unspecified, meaning you can get a different instance from one call to the next. - To resolve a
Locationto an instance, iterate the active instances and useAbstractInstance.isLocationInInstance(Location)instead. That is bounds-aware and correct in every dungeon mode.
initiateDungeonForPlayer
boolean initiateDungeonForPlayer(Player player, String dungeonName)
Queues the player (and their party, if any) for the dungeon identified by dungeonName.
Warning: this method returns
falseon every path, including success. It hands off to the internal queue and then returns a hard-codedfalse, discarding the queue call's own result. Do not branch on it. The failure paths (dungeon not found, player already in a different dungeon, missing thedungeons.playpermission) message the player themselves before returning. If you need a result you can act on, useforceInitiateDungeonForPlayer.
Re-calling it because the first call "failed" makes things worse: the player is already queued, so the second call rejects them with the commands.play.already-in-queue message.
forceInitiateDungeonForPlayer (v2.0.1+)
boolean forceInitiateDungeonForPlayer(Player player, String dungeonName, boolean bypassReqs, boolean withParty)
Force-initiate a dungeon for a player, skipping the queue and the ready-check.
bypassReqs: iftrue, party-size / permission / key / cost checks are all skipped. Iffalse, requirements are still enforced (and cost/keys are consumed); only the queue/ready-check is bypassed.withParty: iftruethe player's party comes along; iffalsethe player enters solo. There is no leader check on this path. The flag is applied by marking the player for solo entry, and the party is then gathered for anyone who is not marked solo, leader or not. (The leader-only restriction,LeaderOnlyQueue, only applies to the normal queue path.)
Returns true once the instance load has been scheduled. This is not a completion signal: the load itself continues asynchronously, so a true means "accepted", not "the player is standing in the dungeon". The false cases are the dungeon not being found, the player being busy (already in a dungeon, already awaiting one, or already queued), requirements not being met when bypassReqs=false, and the dungeon currently being saved.
Note that this path does not consult hasAvailableInstances(). The instance caps are enforced on the normal queue path, not here, which is what makes this a force-entry.
getAllDungeons
Collection<AbstractDungeon> getAllDungeons()
Returns every registered dungeon on the server.
Loot Table Methods
createLootTable
LootTable createLootTable(String namespace, List<ItemStack> items, int weight, int minItems, int maxItems)
Builds a new in-memory LootTable with one entry per item, all sharing the given weight and the minItems/maxItems amount range. null entries in the list are skipped. The returned table is not registered yet.
registerLootTable
boolean registerLootTable(String id, LootTable table)
Registers a table under id and persists it to loottables.yml. Returns false if id or table is null, or if that id is already taken; in those cases the call is a no-op. The registry key is independent of the table's own namespace.
LootTablelives innet.playavalon.mythicdungeons.dungeons.rewards, which is outside the two package trees shipped in the published API jar. See Introduction to API.
Party Methods
Read this first. Nine of the eleven party methods below are gated on Mythic Dungeons' own party system. If
General.PartyPlugininconfig.ymlis anything other thanDefaultorDungeonParties, or parties are disabled entirely, they returnfalse(ornullforgetParty) without doing anything, and the console logsCannot process API call. Party system is not enabled or the internal party system is not selected.once per call. The twoisPartyQueuedForDungeonoverloads are the only ungated ones. If the server runs a third-party party plugin, read the party throughMythicPlayer.getDungeonParty(), which returns theIDungeonPartywrapper for whatever plugin is in use.
createParty
boolean createParty(Player target)
Creates a new party with target as the leader. Returns false if the player is already in a party.
removeFromParty
boolean removeFromParty(Player target)
Removes the player from whatever party they're in. Returns false if they aren't in one.
disbandParty
boolean disbandParty(MythicParty party)
boolean disbandParty(Player target)
Disbands a party, either by passing the party object directly or by passing one of its members. Removes every member.
The Player overload returns false when that player has no party. The MythicParty overload has no such guard and will throw a NullPointerException if you pass null, so check before calling it.
inviteToParty
boolean inviteToParty(Player source, Player target)
Sends a party invite from source's party to target. The target then needs to call acceptPartyInvite (or decline). Returns false if source has no party or target is already in one.
acceptPartyInvite / declinePartyInvite
boolean acceptPartyInvite(Player target)
boolean declinePartyInvite(Player target)
Resolves a pending invite for target. Both return false if the player is already in a party or has no invite pending.
acceptPartyInvite returns true on success. declinePartyInvite does not: it clears the invite and then returns false regardless, so callers cannot tell "declined" from "there was nothing to decline". Treat its return value as meaningless.
setPartyLeader
boolean setPartyLeader(Player player)
Promotes player to be the leader of their current party.
getParty
MythicParty getParty(Player player)
Returns the party the player is in, or null if none.
isPartyQueuedForDungeon
@Nullable String isPartyQueuedForDungeon(Player player)
@Nullable String isPartyQueuedForDungeon(IDungeonParty party)
Returns the dungeon's world name (the folder name under plugins/MythicDungeons/maps, the same string AbstractDungeon.getWorldName() returns), or null if not queued. It is not the coloured display name.
Neither overload is gated on the internal party system. Both actually look up a single player's queue entry rather than a party-wide one: the Player overload uses that player's own entry, and the IDungeonParty overload uses the party leader's.
Caution: the
IDungeonPartyoverload throws on a disbanded party. Itsparty.getLeader() == nullguard cannot fire for aMythicParty, becausegetLeader()dereferences the leader field thatdisband()has already nulled. It can also throw further down if the leader is not currently tracked. Check the party is live before calling it.
Reference: types you'll encounter
These types appear all over the API. The lists below show the most useful getters on each; the source is the canonical reference for the full list.
AbstractDungeon
The dungeon definition (config + map). All play and edit instances of this dungeon share the same AbstractDungeon.
String getWorldName(): internal name / world folder.String getDisplayName(): colored display name fromconfig.yml.Map<String, DungeonDifficulty> getDifficultyLevels(): every configured difficulty.List<AbstractInstance> getInstances(): every currently running instance of this dungeon.boolean hasAvailableInstances():trueif at least one instance slot is free.General.MaxInstances: 0in the dungeon's own config means unlimited, so this returnstrue. Do not confuse that key with the separate server-wideGeneral.MaxInstancesinconfig.yml(default10), which caps how many instances may exist across all dungeons at once.boolean hasAvailableInstances(String difficulty): difficulty-aware variant. The base implementation ignores the argument and defers to the no-arg form; continuous dungeons override it to only count instances of the requested difficulty.Date getNextUnlockTime(): when the dungeon's access cooldown next resets, driven byGeneral.AccessCooldown.*. Returnsnew Date()(now) when the cooldown is disabled, so it is nevernull. HonoursCooldownTypeTIMER/DAILY/WEEKLY/MONTHLYplusCooldownTimeandResetDay.Date getNextLootTime(): the same thing for the loot cooldown, driven byGeneral.LootCooldown.*. Also returnsnew Date()when disabled.<T extends AbstractDungeon> T as(Class<T> clazz): casts this dungeon to a concrete dungeon type, ornullif it is not that type.
v2.0.1: see also
getEffectiveTimeLimit(DungeonDifficulty),getEffectivePlayerLives(DungeonDifficulty),getEffectiveMaxPlayers(DungeonDifficulty),getEffectiveKeepInventoryOnEnter(DungeonDifficulty), andgetEffectiveInstantRespawnPlayers(DungeonDifficulty)for per-difficulty overrides. Each has a second overload taking an extraInstancePlayable, which is what resolves dynamic expressions in the underlying config value; the one-argument forms passnulland so only see the static value. The keys behind them areGeneral.TimeLimit,General.PlayerLives,General.MaxPlayers,General.KeepInventoryOnEnter(defaulttrue) andGeneral.InstantRespawnPlayers(defaultfalse). See Dungeon Config.
AbstractInstance
A single live instance of a dungeon. Comes in two main flavors: InstancePlayable (subclasses include InstanceClassic, InstanceProcedural, InstanceContinuous) and InstanceEditable.
AbstractDungeon getDungeon(): the parent dungeon definition.World getInstanceWorld(): the Bukkit world that hosts this instance.UUID getUuid(): unique identifier for this instance.List<MythicPlayer> getPlayers(): everyone currently in the instance.Map<Location, DungeonFunction> getFunctions(): placed functions, keyed by location.DungeonDifficulty getCurrentDifficulty(): the difficulty applied;nullin edit mode. v2.0.1boolean isLoaded()/boolean isDisposing(): load and teardown state.
Navigating the type hierarchy. Rather than casting by hand:
boolean isPlayInstance()/boolean isEditInstance(): which flavour this is.@Nullable InstancePlayable asPlayInstance()/@Nullable InstanceEditable asEditInstance(): the cast, ornull.@Nullable <T extends AbstractInstance> T as(Class<T> clazz): cast to a specific subclass such asInstanceProcedural.class, ornullif it is not that type.
Locating players and positions.
boolean isPlayerInInstance(Player player):trueif the player is tracked by this instance or is standing inside its bounds.boolean isLocationInInstance(Location loc): bounds check. In an edit instance (no bounds) it falls back to comparing worlds. This is the correct way to resolve aLocationin One-World mode, where the world name alone is ambiguous.
InstancePlayable
Subclass of AbstractInstance for play instances (not edit mode).
DungeonDifficulty getDifficulty(): chosen difficulty for this play.int getTimeElapsed(): seconds since the dungeon started.int getTimeLeft(): seconds remaining (0= unlimited).int modifyTimeLeft(int deltaSeconds, boolean clampToZero): adjust the remaining time by a signed number of seconds, returning the new value. A no-op (returnstimeLeftunchanged) when the dungeon has no time limit or has not started. WithclampToZerothe result floors at1, so the adjustment itself cannot end the run.String getStatus()/void setStatus(String): a free-form status string set by Dungeon Status functions. The setter firesDungeonStatusChangeEventwhen the value actually changes, and is safe to call off the main thread (the event dispatch is deferred).void setDifficulty(DungeonDifficulty): firesDungeonDifficultyChangeEventon a real change, with the same async safety.List<MythicPlayer> getLivingPlayers(): players still alive (non-spectating).Map<UUID, Integer> getPlayerLives(): lives remaining per player.int getParticipants(): how many players the run started with.Location getLobbyLoc(): the lobby location, when the dungeon uses one.boolean isLivesEnabled():truewhen the effectivePlayerLivesis not zero. Negative values therefore count as enabled; only0disables lives.boolean isStarted():trueonce the run has started. With a lobby that is after the ready-check; without one it happens a tick after the instance loads. Procedural dungeons always take the no-lobby path. (There is nohasStarted(); the accessor isisStarted().)boolean isDungeonFinished():trueafter a Finish Dungeon function has been used.Set<Entity> getEntities(): entities tracked for this run. Backed by a weak set, so it will not by itself keep the world alive. See Avoiding Memory Leaks.Map<UUID, BukkitRunnable> getOfflineTrackers(): the per-player grace-period tasks that run while a member is disconnected.IVariableHandler<?> getInstanceVariables()/PlayerVariables getPlayerVariables()/BossBarHandler getBossBarHandler(): the dungeon variable and boss bar state for this run.
MythicPlayer
Wraps a Bukkit Player with dungeon-specific state.
Player getPlayer(): the underlying Bukkit player.AbstractInstance getInstance(): the dungeon instance the player is currently in, ornull.IDungeonParty getDungeonParty(): the player's party, ornull. This is the party-plugin-agnostic view;getMythicParty()returns the built-inMythicPartyand isnullwhen a third-party party plugin is in use.boolean isDead():truebetween dying and respawning. It is set on every death, before the lives check, and cleared again on respawn and whenever the player is added to an instance. It is not an "out of lives" flag. For that, test!instance.getLivingPlayers().contains(mythicPlayer).boolean isSpectating():trueif the player is in spectator mode in this dungeon.Hotbar getCurrentHotbar()/getPreviousHotbar(): the editor hotbar menu stack. See GUI Menus.List<ItemStack> getRewardsInv(): the player's pending rewards. It returns the merge of two sources: the rewards persisted in the player's own data file, plus anything the current instance is holding for them. The persisted bag is keyed per MythicRPG profile when MythicRPG is installed, so different characters have different bags. Reward functions route items here whenGiveLootAfterCompletionis enabled; the Random Reward function additionally routes here whenKeepInventoryOnEnterisfalse.Location getDungeonSavePoint(String dungeon): the player's last save point in a particular dungeon, if any.Location getSavedPosition()/GameMode getSavedGameMode(): where and how the player was before entering, restored on exit.Location getTargetLocation()/void setTargetLocation(Location): scratch location used by the in-game element editor.
To obtain a MythicPlayer from a Bukkit Player:
MythicPlayer mp = MythicDungeons.inst().getMythicPlayer(player);
The Player overload creates and registers the wrapper on demand, so it does not return null for an online player. The getMythicPlayer(UUID) overload is a plain registry lookup and returns null for anyone who is not currently tracked, which includes offline players. Null-check that one.
DungeonDifficulty
A configured difficulty level. See Dungeon Config for the YAML side.
String getNamespace(): config key (e.g."HARD","NIGHTMARE").String getDisplay(): colored display name.double getMobHealthScale()/getMobDamageScale()/getMobSpawnScale(): mob scaling multipliers. Default1.int getMythicMobLevel(): bonus levels applied to Mythic Mob spawns. Default0.RangedNumber getBonusLoot(): extra rolls on loot tables.double[] getBonusLootChances(): the per-roll chances for those extra rolls. Empty by default.ItemStack getIcon(): menu item representation.Map<String, Object> getOverrides()/Object getOverride(String key): per-difficulty config overrides. v2.0.1Map<String, MobOverride> getMobOverrides()/MobOverride getMobOverride(String mobId): per-mob overrides declared underMobOverridesin the difficulty section.
Static values versus dynamic expressions. The no-arg scale getters return the value parsed once out of the config. Each also has an overload taking the running InstancePlayable:
double health = difficulty.getMobHealthScale(instance);
Those overloads resolve dynamic expressions (for example a value written in terms of the current player count) against that instance. If a difficulty uses dynamic values, the no-arg getters give you the fallback, not the live number. The overloads exist for getMobHealthScale, getMobSpawnScale, getMobDamageScale, getMythicMobLevel and getBonusLoot.
Caution:
DungeonDifficultyhas a second, single-Stringconstructor intended for API use. Objects built with it have no icon, sogetIcon()throws aNullPointerExceptionon them. Only theConfigurationSectionconstructor, which Mythic Dungeons uses when reading a dungeon config, populates the icon.
MythicParty / IDungeonParty
A dungeon party. MythicParty is the built-in implementation of IDungeonParty; third-party party plugins implement the interface directly, and MythicPlayer.getDungeonParty() gives you whichever is in use.
IDungeonParty (the portable view, works with any party plugin):
List<Player> getPlayers(): all members, as Bukkit players.@NotNull OfflinePlayer getLeader(): the party leader. Note the type: it is anOfflinePlayeron the interface, not aMythicPlayer.void addPlayer(Player)/void removePlayer(Player): membership changes.boolean hasPlayer(Player): membership test (default method).void partyMessage(String msg): send a colourised message to every member (default method).Location getPartySavePoint(String dungeon): the leader's save point for that dungeon (default method).void initDungeonParty(Plugin plugin)/void initDungeonParty(String... names): binds this party onto its members'MythicPlayers, but only when the server's configuredGeneral.PartyPluginmatches the plugin name you pass. This is the hook a party-plugin integration calls. See Adding Party Support.void setAwaitingDungeon(boolean): flags every member as waiting on a dungeon (default method).
MythicParty adds, on top of those:
Player getLeader(): narrows the return type to an onlinePlayer. It dereferences the leader field directly, so it throws afterdisband().MythicPlayer getMythicLeader(): the leader as aMythicPlayer.List<MythicPlayer> getMythicPlayers(): all members asMythicPlayers. This is the member list; there is nogetMembers().MythicPlayer getPlayer(String name): look up a member by name.void removePlayer(Player player, boolean withAlert)andremovePlayer(Player, boolean withAlert, boolean kickFromDungeon): removal with control over the party message and whether the player is pulled out of the dungeon.void kickPlayer(Player)/void kickPlayer(String name): kick with the kick messages andMythicPartyKickEvent.void disband(): disbands the party and clears every member.void setMythicLeader(Player)/void changeLeader(Player): promote a leader.changeLeaderrefuses players who are not in the party;setMythicLeaderdoes not check.boolean isPlayerOnline(Player)/void setPlayerOnline(Player, boolean): online tracking. Taking the last member offline disbands the party.void sendChatMessage(Player, String)/void leaderMessage(String)/void sendPartyInfo(Player): party chat and info output.
There is no size() and no isLeader(...) on either type. For a member count use getPlayers().size() (or getMythicPlayers().size()); to test leadership compare against getLeader().
Beyond the service interface
MythicDungeonsService is the supported surface, but the plugin class exposes more. Everything in this section is reached through MythicDungeons.inst(), which means it is not available when you compile only against the published API jar. See Introduction to API.
Registering custom elements
<T extends DungeonFunction> void registerFunction(Class<T> function)
<T extends DungeonTrigger> void registerTrigger(Class<T> trigger)
<T extends TriggerCondition> void registerCondition(Class<T> condition)
void registerFunctions(String functionsPackage)
void registerTriggers(String triggersPackage)
void registerConditions(String conditionsPackage)
The three single-class calls register one element and also call ConfigurationSerialization.registerClass for you, so you never do that yourself. registerTrigger additionally inserts the new trigger into the already-built picker menu, which is what makes post-startup registration work.
The three package calls scan the named package with Reflections and register every class carrying the matching @DeclaredFunction / @DeclaredTrigger / @DeclaredCondition annotation. This is the normal way to register a whole package of elements from your own plugin. See Getting Started with Elements.
Registering other extension types
<T extends AbstractDungeon> void registerDungeonType(Class<T> type, String name, String... aliases)
<T extends Layout> void registerLayout(Class<T> type, String name, String... aliases)
<T extends InstanceListener> void registerInstanceListener(Class<T> type)
registerInstanceListener wires up every @EventHandler method on the listener class so that it is dispatched per active instance, with each instance's own listener as the receiver.
Version information
String getVersion() // e.g. "2.0.1"
String getBuildNumber() // the build suffix, or "????" when there isn't one
Both derive from the version string in plugin.yml, split on -. getVersion() is the part before the first hyphen.
World generators
Mythic Dungeons registers chunk generators under its own plugin name, so any world creator can ask for them by id:
| Generator id | Result |
|---|---|
void |
an empty world |
block.<MATERIAL> |
a world filled with that material, for example block.STONE. An unrecognised material falls back to STONE. |
The void id and the block prefix are matched case-insensitively, but the material name after the dot must match the Bukkit Material constant exactly, in upper case. Use MythicDungeons.qualifyGeneratorName(id) to turn a bare id into the MythicDungeons:<id> form that Bukkit's WorldCreator.generator(String) expects; a bare id is otherwise parsed as a plugin name and silently ignored.
Alternative entry point
For convenience, the plugin singleton also implements MythicDungeonsService:
MythicDungeons md = MythicDungeons.inst();
md.isPlayerInDungeon(player); // same as the service lookup
Use this if you've already added a hard depend on MythicDungeons in your plugin.yml and you compile against the full plugin jar. The MythicDungeons class sits in the root package, which is not shipped in the published API artifact, so this snippet does not compile against that artifact. Prefer the ServicesManager lookup if you support soft-dep / optional integration, since the service won't be registered when MD is absent.
Other API packages
These are part of the published API but are not documented method by method here. Read them from the sources or javadoc jar (see Introduction to API).
| Package | What lives there |
|---|---|
api.annotations |
@SavedField, @Hidden, @Relocatable, @DeclaredFunction, @DeclaredTrigger, @DeclaredCondition. See Getting Started with Elements. |
api.parents.elements |
DungeonElement, DungeonFunction, DungeonTrigger, TriggerCondition, FunctionCategory. |
api.events |
Every Bukkit event Mythic Dungeons fires. See Events. |
api.blocks |
MovingBlock, MovingBlockCluster, PushableBlock, PushableBlockCluster. |
api.chunkgenerators |
VoidGenerator, FullBlockGenerator, DungeonChunkGenerator. |
api.config |
AvalonConfiguration, AsyncConfiguration, AvalonSerializable. |
api.exceptions |
DungeonInitException, DungeonDisposalException. |
api.queue |
QueueData, the state of one queued party. |
api.generation |
The procedural generator: Layout and its subclasses, StructurePiece, and the rooms types (InstanceRoom, RotatedRoom, Connector, ConnectorDoor, and friends). |
api.party |
IDungeonParty. See Adding Party Support. |