mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-24 22:26:46 +01:00
some work on experience rewrites
This commit is contained in:
parent
704e24d58b
commit
4e81d4ddb6
12
pom.xml
12
pom.xml
@ -116,6 +116,8 @@
|
||||
<include>net.kyori:adventure-text-serializer-bungeecord</include>
|
||||
<include>net.kyori:adventure-text-serializer-craftbukkit</include>
|
||||
<include>co.aikar:acf-bukkit</include>
|
||||
<include>com.neetgames:mcMMO-API</include>
|
||||
<include>com.neetgames:jmal</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<!-- <dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>-->
|
||||
@ -193,6 +195,16 @@
|
||||
<!-- ... -->
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.neetgames</groupId>
|
||||
<artifactId>mcMMO-API</artifactId>
|
||||
<version>0.01.00-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.neetgames</groupId>
|
||||
<artifactId>jmal</artifactId>
|
||||
<version>0.01.00-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>co.aikar</groupId>
|
||||
<artifactId>acf-bukkit</artifactId> <!-- Don't forget to replace this -->
|
||||
|
@ -0,0 +1,18 @@
|
||||
package com.gmail.nossr50.datatypes.experience;
|
||||
|
||||
import com.gmail.nossr50.datatypes.experience.context.NullExperienceContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ExperienceContextBuilder {
|
||||
|
||||
private static final @NotNull NullExperienceContext nullExperienceContext = new NullExperienceContext();
|
||||
|
||||
/**
|
||||
* Return a null experience context
|
||||
* @return a null experience context
|
||||
*/
|
||||
public static NullExperienceContext nullContext() {
|
||||
return nullExperienceContext;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.gmail.nossr50.datatypes.experience;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ExperienceGain {
|
||||
/**
|
||||
* Get the target skill for this XP gain
|
||||
* We define this by a String to allow for custom skills
|
||||
* @return The target skill
|
||||
*/
|
||||
@NotNull UUID getTargetSkill();
|
||||
|
||||
/**
|
||||
* Value of the experience gain, this is the raw value before any mutations are done via modifiers or otherwise
|
||||
* @return the value of this {@link ExperienceGain}
|
||||
*/
|
||||
int getValue();
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.gmail.nossr50.datatypes.experience;
|
||||
|
||||
public class ExperienceGainBuilder {
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.gmail.nossr50.datatypes.player;
|
||||
package com.gmail.nossr50.datatypes.experience;
|
||||
|
||||
import com.gmail.nossr50.config.Config;
|
||||
import com.gmail.nossr50.config.experience.ExperienceConfig;
|
||||
@ -7,6 +7,8 @@ import com.gmail.nossr50.datatypes.experience.SkillXpGain;
|
||||
import com.gmail.nossr50.datatypes.experience.XPGainReason;
|
||||
import com.gmail.nossr50.datatypes.experience.XPGainSource;
|
||||
import com.gmail.nossr50.datatypes.party.Party;
|
||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||
import com.gmail.nossr50.datatypes.player.PersistentPlayerData;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.party.ShareHandler;
|
||||
@ -26,19 +28,24 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ExperienceManager {
|
||||
|
||||
private boolean isUsingUnarmed = false;
|
||||
|
||||
private final @NotNull PersistentPlayerData persistentPlayerDataRef;
|
||||
private final @NotNull McMMOPlayer mmoPlayer;
|
||||
private @Nullable McMMOPlayer mmoPlayer;
|
||||
|
||||
public ExperienceManager(@NotNull McMMOPlayer mmoPlayer) {
|
||||
this.mmoPlayer = mmoPlayer;
|
||||
this.persistentPlayerDataRef = mmoPlayer.getPersistentPlayerData();
|
||||
}
|
||||
|
||||
public ExperienceManager(@NotNull PersistentPlayerData persistentPlayerData) {
|
||||
this.persistentPlayerDataRef = persistentPlayerData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the power level of this player.
|
||||
* A power level is the sum of all skill levels for this player
|
||||
@ -60,7 +67,7 @@ public class ExperienceManager {
|
||||
* @param primarySkillType target skill
|
||||
* @return the value of raw XP for target skill
|
||||
*/
|
||||
public float getSkillXpLevelRaw(PrimarySkillType primarySkillType) {
|
||||
public float getSkillXpLevelRaw(@NotNull PrimarySkillType primarySkillType) {
|
||||
return persistentPlayerDataRef.getSkillsExperienceMap().get(primarySkillType);
|
||||
}
|
||||
|
||||
@ -289,7 +296,7 @@ public class ExperienceManager {
|
||||
public float getRegisteredXpGain(@NotNull PrimarySkillType primarySkillType) {
|
||||
float xp = 0F;
|
||||
|
||||
if (rollingSkillsXp.get(primarySkillType) != null) {
|
||||
if (get(primarySkillType) != null) { //??
|
||||
xp = rollingSkillsXp.get(primarySkillType);
|
||||
}
|
||||
|
||||
@ -359,15 +366,18 @@ public class ExperienceManager {
|
||||
* @param xp Experience amount to add
|
||||
*/
|
||||
public void applyXpGain(@NotNull PrimarySkillType primarySkillType, float xp, @NotNull XPGainReason xpGainReason, @NotNull XPGainSource xpGainSource) {
|
||||
//Only check for permissions if the player is online, otherwise just assume a command is being executed by an admin or some other means and add the XP
|
||||
if(mmoPlayer != null) {
|
||||
if (!primarySkillType.getPermissions(mmoPlayer.getPlayer())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (primarySkillType.isChildSkill()) {
|
||||
Set<PrimarySkillType> parentSkills = FamilyTree.getParents(primarySkillType);
|
||||
|
||||
for (PrimarySkillType parentSkill : parentSkills) {
|
||||
applyXpGain(mmoPlayer, parentSkill, xp / parentSkills.size(), xpGainReason, xpGainSource);
|
||||
applyXpGain(parentSkill, xp / parentSkills.size(), xpGainReason, xpGainSource);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -377,16 +387,22 @@ public class ExperienceManager {
|
||||
return;
|
||||
}
|
||||
|
||||
mmoPlayer.getExperienceManager().setUsingUnarmed(primarySkillType == PrimarySkillType.UNARMED);
|
||||
updateLevelStats(mmoPlayer, primarySkillType, xpGainReason, xpGainSource);
|
||||
setUsingUnarmed(primarySkillType == PrimarySkillType.UNARMED);
|
||||
updateLevelStats(primarySkillType, xpGainReason, xpGainSource);
|
||||
}
|
||||
|
||||
public void processPostXpEvent(@NotNull PrimarySkillType primarySkillType, @NotNull Plugin plugin, @NotNull XPGainSource xpGainSource)
|
||||
{
|
||||
/*
|
||||
* Everything in this method requires an online player, so if they aren't online we don't waste our time
|
||||
*/
|
||||
if(mmoPlayer == null)
|
||||
return;
|
||||
|
||||
//Check if they've reached the power level cap just now
|
||||
if(mmoPlayer.getExperienceManager().hasReachedPowerLevelCap()) {
|
||||
if(hasReachedPowerLevelCap()) {
|
||||
NotificationManager.sendPlayerInformationChatOnly(mmoPlayer.getPlayer(), "LevelCap.PowerLevel", String.valueOf(Config.getInstance().getPowerLevelCap()));
|
||||
} else if(mmoPlayer.getExperienceManager().hasReachedLevelCap(primarySkillType)) {
|
||||
} else if(hasReachedLevelCap(primarySkillType)) {
|
||||
NotificationManager.sendPlayerInformationChatOnly(mmoPlayer.getPlayer(), "LevelCap.Skill", String.valueOf(Config.getInstance().getLevelCap(primarySkillType)), primarySkillType.getName());
|
||||
}
|
||||
|
||||
@ -407,25 +423,24 @@ public class ExperienceManager {
|
||||
* @param primarySkillType The skill to check
|
||||
*/
|
||||
public void updateLevelStats(@NotNull PrimarySkillType primarySkillType, @NotNull XPGainReason xpGainReason, @NotNull XPGainSource xpGainSource) {
|
||||
ExperienceManager em = mmoPlayer.getExperienceManager();
|
||||
if(em.hasReachedLevelCap(primarySkillType))
|
||||
if(hasReachedLevelCap(primarySkillType))
|
||||
return;
|
||||
|
||||
if (em.getSkillXpLevelRaw(primarySkillType) < em.getXpToLevel(primarySkillType)) {
|
||||
processPostXpEvent(mmoPlayer, primarySkillType, mcMMO.p, xpGainSource);
|
||||
if (getSkillXpLevelRaw(primarySkillType) < getXpToLevel(primarySkillType)) {
|
||||
processPostXpEvent(primarySkillType, mcMMO.p, xpGainSource);
|
||||
return;
|
||||
}
|
||||
|
||||
int levelsGained = 0;
|
||||
float xpRemoved = 0;
|
||||
|
||||
while (em.getSkillXpLevelRaw(primarySkillType) >= em.getXpToLevel(primarySkillType)) {
|
||||
if (em.hasReachedLevelCap(primarySkillType)) {
|
||||
em.setSkillXpValue(primarySkillType, 0);
|
||||
while (getSkillXpLevelRaw(primarySkillType) >= getXpToLevel(primarySkillType)) {
|
||||
if (hasReachedLevelCap(primarySkillType)) {
|
||||
setSkillXpValue(primarySkillType, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
xpRemoved += em.levelUp(primarySkillType);
|
||||
xpRemoved += levelUp(primarySkillType);
|
||||
levelsGained++;
|
||||
}
|
||||
|
||||
@ -441,10 +456,10 @@ public class ExperienceManager {
|
||||
* Check to see if the player unlocked any new skills
|
||||
*/
|
||||
|
||||
NotificationManager.sendPlayerLevelUpNotification(mmoPlayer, primarySkillType, levelsGained, em.getSkillLevel(primarySkillType));
|
||||
NotificationManager.sendPlayerLevelUpNotification(mmoPlayer, primarySkillType, levelsGained, getSkillLevel(primarySkillType));
|
||||
|
||||
//UPDATE XP BARS
|
||||
processPostXpEvent(mmoPlayer, primarySkillType, mcMMO.p, xpGainSource);
|
||||
processPostXpEvent(primarySkillType, mcMMO.p, xpGainSource);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.gmail.nossr50.datatypes.experience;
|
||||
|
||||
public class ExperienceProcessor {
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package com.gmail.nossr50.datatypes.experience;
|
||||
|
||||
public enum ExperienceVector {
|
||||
ALL,
|
||||
TARGETED,
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.gmail.nossr50.datatypes.experience;
|
||||
|
||||
public interface PartyExperienceGain extends ExperienceGain {
|
||||
|
||||
/**
|
||||
* The original value of this experience gain
|
||||
* This is not equivalent to the amount of XP the players in party will get, but it was the value of the XP before it was distributed to party members
|
||||
* @return the original value of the experience gain
|
||||
*/
|
||||
int originalValue();
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.gmail.nossr50.datatypes.experience.capture;
|
||||
|
||||
import com.gmail.nossr50.datatypes.experience.context.ExperienceContext;
|
||||
import com.neetgames.mcmmo.skill.SkillIdentity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class ExperienceCapture {
|
||||
private @NotNull ExperienceContext experienceContext;
|
||||
private @NotNull HashSet<SkillIdentity> affectedSkills;
|
||||
|
||||
public ExperienceCapture(@NotNull ExperienceContext experienceContext, @NotNull HashSet<SkillIdentity> affectedSkills) {
|
||||
this.experienceContext = experienceContext;
|
||||
this.affectedSkills = affectedSkills;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not a skill is targeted in this experience capture
|
||||
* @param skillIdentity target skill
|
||||
* @return true if this skill is targeted in this experience capture
|
||||
*/
|
||||
public boolean isSkillAffected(@NotNull SkillIdentity skillIdentity) {
|
||||
return affectedSkills.contains(skillIdentity);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.gmail.nossr50.datatypes.experience.capture;
|
||||
|
||||
import com.gmail.nossr50.datatypes.player.PlayerProfile;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import com.gmail.nossr50.datatypes.skills.SkillIdentity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface ExperienceSnapshot {
|
||||
/**
|
||||
* Check whether or not a skill is targeted in this experience capture
|
||||
*
|
||||
* @param skillIdentity target skill
|
||||
* @return true if this skill is targeted in this experience capture
|
||||
*/
|
||||
boolean isSkillAffected(@NotNull SkillIdentity skillIdentity);
|
||||
|
||||
/**
|
||||
* Check whether or not a skill is targeted in this experience capture
|
||||
*
|
||||
* @param skillId target skill
|
||||
* @return true if this skill is targeted in this experience capture
|
||||
*/
|
||||
boolean isSkillAffected(@NotNull String skillId);
|
||||
|
||||
/**
|
||||
* Check whether or not a skill is targeted in this experience capture
|
||||
*
|
||||
* @param primarySkillType target skill
|
||||
* @return true if this skill is targeted in this experience capture
|
||||
* @deprecated the {@link PrimarySkillType} type is going to be phased out in favour of {@link SkillIdentity} at some point in the future
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isSkillAffected(@NotNull PrimarySkillType primarySkillType);
|
||||
|
||||
@NotNull PlayerProfile[] getPlayers();
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.gmail.nossr50.datatypes.experience;
|
||||
|
||||
import com.gmail.nossr50.datatypes.experience.capture.ExperienceCapture;
|
||||
import com.gmail.nossr50.datatypes.experience.context.ExperienceContext;
|
||||
import com.gmail.nossr50.datatypes.skills.SkillIdentity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class MultiExperienceCapture extends ExperienceCapture {
|
||||
private @NotNull ExperienceContext experienceContext;
|
||||
private @NotNull HashSet<SkillIdentity> affectedSkills;
|
||||
|
||||
public ExperienceCapture(@NotNull ExperienceContext experienceContext, @NotNull HashSet<SkillIdentity> affectedSkills) {
|
||||
this.experienceContext = experienceContext;
|
||||
this.affectedSkills = affectedSkills;
|
||||
}
|
||||
|
||||
public MultiExperienceCapture(@NotNull ExperienceContext experienceContext, @NotNull HashSet<SkillIdentity> affectedSkills) {
|
||||
super(experienceContext, affectedSkills);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not a skill is targeted in this experience capture
|
||||
* @param skillIdentity target skill
|
||||
* @return true if this skill is targeted in this experience capture
|
||||
*/
|
||||
public boolean isSkillAffected(@NotNull SkillIdentity skillIdentity) {
|
||||
return affectedSkills.contains(skillIdentity);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.gmail.nossr50.datatypes.experience.context;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BlockExperienceContext implements ExperienceContext {
|
||||
|
||||
@NotNull Block blockExperienceContext;
|
||||
|
||||
public BlockExperienceContext(@NotNull Block block) {
|
||||
this.blockExperienceContext = block;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getContext() {
|
||||
return blockExperienceContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Block involved in this experience context
|
||||
*
|
||||
* @return the {@link Block} involved in this experience context
|
||||
*/
|
||||
public @NotNull Block getBlockExperienceContext() {
|
||||
return blockExperienceContext;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.gmail.nossr50.datatypes.experience.context;
|
||||
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CombatContext implements ExperienceContext {
|
||||
|
||||
private final @NotNull LivingEntity livingEntity;
|
||||
|
||||
public CombatContext(@NotNull LivingEntity livingEntity) {
|
||||
this.livingEntity = livingEntity;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getContext() {
|
||||
return livingEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link LivingEntity} involved in this experience context
|
||||
*
|
||||
* @return the {@link LivingEntity} involved in this experience context
|
||||
*/
|
||||
public @NotNull LivingEntity getLivingEntity() {
|
||||
return livingEntity;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.gmail.nossr50.datatypes.experience.context;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface ExperienceContext {
|
||||
/**
|
||||
* The source for this experience gain, can be anything from a block to an entity, etc
|
||||
* Context is available as long as it can be
|
||||
* @return the context (source) of this experience
|
||||
*/
|
||||
@Nullable Object getContext();
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.gmail.nossr50.datatypes.experience.context;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Represents an experience context with an undefined source
|
||||
*/
|
||||
public class NullExperienceContext implements ExperienceContext {
|
||||
@Override
|
||||
public @Nullable Object getContext() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.gmail.nossr50.datatypes.experience.context;
|
||||
|
||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface SharedExperienceContext {
|
||||
/**
|
||||
* The {@link McMMOPlayer} who originally gained the XP that was then shared
|
||||
* @return the {@link McMMOPlayer} to which this experience context originates
|
||||
*/
|
||||
@NotNull McMMOPlayer getSharedContextSource();
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.gmail.nossr50.datatypes.player;
|
||||
|
||||
import com.gmail.nossr50.datatypes.MobHealthBarType;
|
||||
import com.gmail.nossr50.datatypes.experience.ExperienceManager;
|
||||
import com.gmail.nossr50.datatypes.party.Party;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.gmail.nossr50.datatypes.skills;
|
||||
|
||||
public interface PrimarySkill {
|
||||
|
||||
}
|
@ -18,6 +18,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
*
|
||||
* Skills with parents do not gain experience, and instead their intended effects will be based on the strength of the parent skill (its level)
|
||||
* Skills are registered, no two skills can share the same fully qualified name (in this case, a combination of the namespace and skill name)
|
||||
*
|
||||
* A fully qualified name is generated based on the namespace and skill name
|
||||
* @see #genFullyQualifiedName()
|
||||
*/
|
||||
public class SkillIdentity {
|
||||
@NotNull private final String nameSpace;
|
||||
|
@ -0,0 +1,24 @@
|
||||
package com.gmail.nossr50.events.experience;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ExperienceCaptureEvent extends PlayerEvent {
|
||||
|
||||
public ExperienceCaptureEvent(@NotNull Player who) {
|
||||
super(who);
|
||||
}
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
@ -258,7 +258,7 @@ public class HerbalismManager extends SkillManager {
|
||||
public void checkDoubleDropsOnBrokenPlants(Player player, Collection<Block> brokenPlants) {
|
||||
|
||||
//Only proceed if skill unlocked and permission enabled
|
||||
if (!RankUtils.hasUnlockedSubskill(player, SubSkillType.HERBALISM_DOUBLE_DROPS)
|
||||
if (!RankUtils.hasUnlockedSubskill(mmoPlayer, SubSkillType.HERBALISM_DOUBLE_DROPS)
|
||||
|| !Permissions.isSubSkillEnabled(player, SubSkillType.HERBALISM_DOUBLE_DROPS)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,23 +1,12 @@
|
||||
package com.gmail.nossr50.util.experience;
|
||||
|
||||
import com.gmail.nossr50.config.Config;
|
||||
import com.gmail.nossr50.config.experience.ExperienceConfig;
|
||||
import com.gmail.nossr50.datatypes.experience.XPGainReason;
|
||||
import com.gmail.nossr50.datatypes.experience.XPGainSource;
|
||||
import com.gmail.nossr50.datatypes.player.ExperienceManager;
|
||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.skills.child.FamilyTree;
|
||||
import com.gmail.nossr50.util.EventUtils;
|
||||
import com.gmail.nossr50.util.player.NotificationManager;
|
||||
import com.gmail.nossr50.util.sounds.SoundManager;
|
||||
import com.gmail.nossr50.util.sounds.SoundType;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class ExperienceUtils {
|
||||
private ExperienceUtils() {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user