formatting applied to most of the source code to tidy things up, and misc refactors

This commit is contained in:
nossr50
2025-07-03 14:03:43 -07:00
parent f322d05159
commit e52371aeb3
440 changed files with 11762 additions and 7365 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,11 @@ import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import org.apache.commons.lang3.RandomUtils;
import org.bukkit.*;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.SoundCategory;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.LivingEntity;
@@ -17,7 +21,8 @@ import org.jetbrains.annotations.NotNull;
public final class ParticleEffectUtils {
private ParticleEffectUtils() {}
private ParticleEffectUtils() {
}
public static void playGreenThumbEffect(Location location) {
World world = location.getWorld();
@@ -39,8 +44,10 @@ public final class ParticleEffectUtils {
return;
}
SoundManager.sendCategorizedSound(livingEntity.getLocation(), SoundType.CRIPPLE, SoundCategory.PLAYERS, 0.2F);
livingEntity.getWorld().playEffect(getParticleLocation(livingEntity), Effect.ANVIL_BREAK, null, 20);
SoundManager.sendCategorizedSound(livingEntity.getLocation(), SoundType.CRIPPLE,
SoundCategory.PLAYERS, 0.2F);
livingEntity.getWorld()
.playEffect(getParticleLocation(livingEntity), Effect.ANVIL_BREAK, null, 20);
if (livingEntity instanceof Player player) {
final McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
@@ -93,8 +100,9 @@ public final class ParticleEffectUtils {
return;
}
if (location.getWorld() == null)
if (location.getWorld() == null) {
return;
}
location.getWorld().playEffect(location, Effect.MOBSPAWNER_FLAMES, 1);
}
@@ -102,8 +110,9 @@ public final class ParticleEffectUtils {
public static void playSmokeEffect(Location location) {
World world = location.getWorld();
if (world == null)
if (world == null) {
return;
}
// Have to do it this way, because not all block directions are valid for smoke
world.playEffect(location, Effect.SMOKE, BlockFace.SOUTH_EAST);
@@ -124,7 +133,9 @@ public final class ParticleEffectUtils {
Location location = livingEntity.getEyeLocation();
livingEntity.getWorld().createExplosion(location.getX(), location.getY(), location.getZ(), 0F, false, false);
livingEntity.getWorld()
.createExplosion(location.getX(), location.getY(), location.getZ(), 0F, false,
false);
}
public static void playCallOfTheWildEffect(LivingEntity livingEntity) {
@@ -132,7 +143,8 @@ public final class ParticleEffectUtils {
return;
}
livingEntity.getWorld().playEffect(livingEntity.getEyeLocation(), Effect.MOBSPAWNER_FLAMES, 1);
livingEntity.getWorld()
.playEffect(livingEntity.getEyeLocation(), Effect.MOBSPAWNER_FLAMES, 1);
}
public static void playAbilityDisabledEffect(Player player) {

View File

@@ -14,7 +14,8 @@ public final class PerksUtils {
private static final int LUCKY_SKILL_ACTIVATION_CHANCE = 75;
private static final int NORMAL_SKILL_ACTIVATION_CHANCE = 100;
private PerksUtils() {}
private PerksUtils() {
}
public static int handleCooldownPerks(Player player, int cooldown) {
if (Permissions.halvedCooldowns(player)) {
@@ -41,7 +42,8 @@ public final class PerksUtils {
ticks += 4;
}
final SkillActivationPerkEvent skillActivationPerkEvent = new SkillActivationPerkEvent(player, ticks, maxTicks);
final SkillActivationPerkEvent skillActivationPerkEvent = new SkillActivationPerkEvent(
player, ticks, maxTicks);
Bukkit.getPluginManager().callEvent(skillActivationPerkEvent);
return skillActivationPerkEvent.getTicks();
}
@@ -50,11 +52,13 @@ public final class PerksUtils {
double modifier = 1.0F;
if (Permissions.customXpBoost(player, skill)) {
if (UserManager.getPlayer(player) != null && UserManager.getPlayer(player).isDebugMode()) {
player.sendMessage(ChatColor.GOLD + "[DEBUG] " + ChatColor.DARK_GRAY + "XP Perk Multiplier IS CUSTOM! ");
if (UserManager.getPlayer(player) != null && UserManager.getPlayer(player)
.isDebugMode()) {
player.sendMessage(ChatColor.GOLD + "[DEBUG] " + ChatColor.DARK_GRAY
+ "XP Perk Multiplier IS CUSTOM! ");
}
modifier = ExperienceConfig.getInstance().getCustomXpPerkBoost();
modifier = ExperienceConfig.getInstance().getCustomXpPerkBoost();
} else if (Permissions.quadrupleXp(player, skill)) {
modifier = 4;
} else if (Permissions.tripleXp(player, skill)) {
@@ -74,9 +78,13 @@ public final class PerksUtils {
float modifiedXP = (float) (xp * modifier);
if (UserManager.getPlayer(player) != null && UserManager.getPlayer(player).isDebugMode()) {
player.sendMessage(ChatColor.GOLD + "[DEBUG] " + ChatColor.RESET + "XP Perk Multiplier - " + ChatColor.GOLD + modifier);
player.sendMessage(ChatColor.GOLD + "[DEBUG] " + ChatColor.RESET + "Original XP before perk boosts " + ChatColor.RED + (double) xp);
player.sendMessage(ChatColor.GOLD + "[DEBUG] " + ChatColor.RESET + "XP AFTER PERKS " + ChatColor.DARK_RED + modifiedXP);
player.sendMessage(
ChatColor.GOLD + "[DEBUG] " + ChatColor.RESET + "XP Perk Multiplier - "
+ ChatColor.GOLD + modifier);
player.sendMessage(ChatColor.GOLD + "[DEBUG] " + ChatColor.RESET
+ "Original XP before perk boosts " + ChatColor.RED + (double) xp);
player.sendMessage(ChatColor.GOLD + "[DEBUG] " + ChatColor.RESET + "XP AFTER PERKS "
+ ChatColor.DARK_RED + modifiedXP);
}
return modifiedXP;

View File

@@ -1,5 +1,8 @@
package com.gmail.nossr50.util.skills;
import static com.gmail.nossr50.util.MetadataConstants.ARROW_METADATA_KEYS;
import static com.gmail.nossr50.util.MetadataConstants.MCMMO_METADATA_VALUE;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.MetadataConstants;
import org.bukkit.block.BlockFace;
@@ -11,9 +14,6 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import static com.gmail.nossr50.util.MetadataConstants.ARROW_METADATA_KEYS;
import static com.gmail.nossr50.util.MetadataConstants.MCMMO_METADATA_VALUE;
public class ProjectileUtils {
public static Vector getNormal(BlockFace blockFace) {
@@ -47,13 +47,14 @@ public class ProjectileUtils {
* @param targetArrow The arrow to which metadata is copied.
*/
public static void copyArrowMetadata(@NotNull Plugin pluginRef, @NotNull Arrow sourceArrow,
@NotNull Arrow targetArrow) {
@NotNull Arrow targetArrow) {
ARROW_METADATA_KEYS.stream()
.filter(sourceArrow::hasMetadata)
.forEach(key -> {
final MetadataValue metadataValue = sourceArrow.getMetadata(key).get(0);
if (key.equals(MetadataConstants.METADATA_KEY_BOW_FORCE)) {
targetArrow.setMetadata(key, new FixedMetadataValue(pluginRef, metadataValue.asDouble()));
targetArrow.setMetadata(key,
new FixedMetadataValue(pluginRef, metadataValue.asDouble()));
} else if (key.equals(MetadataConstants.METADATA_KEY_CROSSBOW_PROJECTILE)) {
targetArrow.setMetadata(key, MCMMO_METADATA_VALUE);
} else {

View File

@@ -11,41 +11,45 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.skills.SkillUnlockNotificationTask;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
import java.util.HashMap;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
public class RankUtils {
private static HashMap<String, HashMap<Integer, Integer>> subSkillRanks;
private static int count = 0;
/**
*
* @param plugin plugin instance ref
* @param mcMMOPlayer target player
* @param mmoPlayer target player
* @param primarySkillType the skill to check
* @param newLevel the new level of this skill
*/
public static void executeSkillUnlockNotifications(Plugin plugin, McMMOPlayer mcMMOPlayer, PrimarySkillType primarySkillType, int newLevel) {
for(SubSkillType subSkillType : mcMMO.p.getSkillTools().getSubSkills(primarySkillType)) {
int playerRankInSkill = getRank(mcMMOPlayer.getPlayer(), subSkillType);
public static void executeSkillUnlockNotifications(Plugin plugin, McMMOPlayer mmoPlayer,
PrimarySkillType primarySkillType, int newLevel) {
for (SubSkillType subSkillType : mcMMO.p.getSkillTools().getSubSkills(primarySkillType)) {
int playerRankInSkill = getRank(mmoPlayer.getPlayer(), subSkillType);
HashMap<Integer, Integer> innerMap = subSkillRanks.get(subSkillType.toString());
//If the skill doesn't have registered ranks gtfo
if (innerMap == null || innerMap.get(playerRankInSkill) == null)
if (innerMap == null || innerMap.get(playerRankInSkill) == null) {
continue;
}
//Don't send notifications if the player lacks the permission node
if (!Permissions.isSubSkillEnabled(mcMMOPlayer.getPlayer(), subSkillType))
if (!Permissions.isSubSkillEnabled(mmoPlayer.getPlayer(), subSkillType)) {
continue;
}
//The players level is the exact level requirement for this skill
if (newLevel == innerMap.get(playerRankInSkill)) {
SkillUnlockNotificationTask skillUnlockNotificationTask = new SkillUnlockNotificationTask(mcMMOPlayer, subSkillType, newLevel);
SkillUnlockNotificationTask skillUnlockNotificationTask = new SkillUnlockNotificationTask(
mmoPlayer, subSkillType, newLevel);
mcMMO.p.getFoliaLib().getScheduler().runAtEntityLater(mcMMOPlayer.getPlayer(), skillUnlockNotificationTask, (count * 100L));
mcMMO.p.getFoliaLib().getScheduler()
.runAtEntityLater(mmoPlayer.getPlayer(), skillUnlockNotificationTask,
(count * 100L));
count++;
}
@@ -62,9 +66,9 @@ public class RankUtils {
/* NEW SYSTEM */
private static void addRanks(AbstractSubSkill abstractSubSkill) {
//Fill out the rank array
for(int i = 0; i < abstractSubSkill.getNumRanks(); i++) {
for (int i = 0; i < abstractSubSkill.getNumRanks(); i++) {
//This adds the highest ranks first
addRank(abstractSubSkill, abstractSubSkill.getNumRanks()-i);
addRank(abstractSubSkill, abstractSubSkill.getNumRanks() - i);
//TODO: Remove debug code
/*System.out.println("DEBUG: Adding rank "+(numRanks-i)+" to "+subSkillType.toString());*/
@@ -73,9 +77,9 @@ public class RankUtils {
private static void addRanks(SubSkillType subSkillType) {
//Fill out the rank array
for(int i = 0; i < subSkillType.getNumRanks(); i++) {
for (int i = 0; i < subSkillType.getNumRanks(); i++) {
//This adds the highest ranks first
addRank(subSkillType, subSkillType.getNumRanks()-i);
addRank(subSkillType, subSkillType.getNumRanks() - i);
//TODO: Remove debug code
/*System.out.println("DEBUG: Adding rank "+(numRanks-i)+" to "+subSkillType.toString());*/
@@ -86,17 +90,18 @@ public class RankUtils {
* Populates the ranks for every skill we know about
*/
public static void populateRanks() {
for(SubSkillType subSkillType : SubSkillType.values()) {
for (SubSkillType subSkillType : SubSkillType.values()) {
addRanks(subSkillType);
}
for(AbstractSubSkill abstractSubSkill : InteractionManager.getSubSkillList()) {
for (AbstractSubSkill abstractSubSkill : InteractionManager.getSubSkillList()) {
addRanks(abstractSubSkill);
}
}
/**
* Returns whether the player has unlocked the first rank in target subskill
*
* @param player the player
* @param subSkillType the target subskill
* @return true if the player has at least one rank in the skill
@@ -110,6 +115,7 @@ public class RankUtils {
/**
* Returns whether the player has unlocked the first rank in target subskill
*
* @param player the player
* @param abstractSubSkill the target subskill
* @return true if the player has at least one rank in the skill
@@ -123,6 +129,7 @@ public class RankUtils {
/**
* Returns whether the player has reached the specified rank in target subskill
*
* @param rank the target rank
* @param player the player
* @param subSkillType the target subskill
@@ -134,20 +141,24 @@ public class RankUtils {
/**
* Returns whether the player has reached the specified rank in target subskill
*
* @param rank the target rank
* @param player the player
* @param abstractSubSkill the target subskill
* @return true if the player is at least that rank in this subskill
*/
public static boolean hasReachedRank(int rank, Player player, AbstractSubSkill abstractSubSkill) {
public static boolean hasReachedRank(int rank, Player player,
AbstractSubSkill abstractSubSkill) {
return getRank(player, abstractSubSkill) >= rank;
}
/**
* Gets the current rank of the subskill for the player
*
* @param mmoPlayer The player in question
* @param subSkillType Target subskill
* @return The rank the player currently has achieved in this skill. -1 for skills without ranks.
* @return The rank the player currently has achieved in this skill. -1 for skills without
* ranks.
*/
public static int getRank(McMMOPlayer mmoPlayer, SubSkillType subSkillType) {
return getRank(mmoPlayer.getPlayer(), subSkillType);
@@ -155,44 +166,53 @@ public class RankUtils {
/**
* Gets the current rank of the subskill for the player
*
* @param player The player in question
* @param subSkillType Target subskill
* @return The rank the player currently has achieved in this skill. -1 for skills without ranks.
* @return The rank the player currently has achieved in this skill. -1 for skills without
* ranks.
*/
public static int getRank(Player player, SubSkillType subSkillType) {
String skillName = subSkillType.toString();
int numRanks = subSkillType.getNumRanks();
if (subSkillRanks == null)
if (subSkillRanks == null) {
subSkillRanks = new HashMap<>();
}
if (numRanks == 0)
if (numRanks == 0) {
return -1; //-1 Means the skill doesn't have ranks
}
if (subSkillRanks.get(skillName) == null && numRanks > 0)
if (subSkillRanks.get(skillName) == null && numRanks > 0) {
addRanks(subSkillType);
}
//Get our rank map
HashMap<Integer, Integer> rankMap = subSkillRanks.get(skillName);
if (UserManager.getPlayer(player) == null)
if (UserManager.getPlayer(player) == null) {
return 0;
}
//Skill level of parent skill
int currentSkillLevel = UserManager.getPlayer(player).getSkillLevel(subSkillType.getParentSkill());
int currentSkillLevel = UserManager.getPlayer(player)
.getSkillLevel(subSkillType.getParentSkill());
for(int i = 0; i < numRanks; i++) {
for (int i = 0; i < numRanks; i++) {
//Compare against the highest to lowest rank in that order
int rank = numRanks-i;
int rank = numRanks - i;
int unlockLevel = getRankUnlockLevel(subSkillType, rank);
//If we check all ranks and still cannot unlock the skill, we return rank 0
if (rank == 0)
if (rank == 0) {
return 0;
}
//True if our skill level can unlock the current rank
if (currentSkillLevel >= unlockLevel)
if (currentSkillLevel >= unlockLevel) {
return rank;
}
}
return 0; //We should never reach this
@@ -200,44 +220,53 @@ public class RankUtils {
/**
* Gets the current rank of the subskill for the player
*
* @param player The player in question
* @param abstractSubSkill Target subskill
* @return The rank the player currently has achieved in this skill. -1 for skills without ranks.
* @return The rank the player currently has achieved in this skill. -1 for skills without
* ranks.
*/
public static int getRank(Player player, AbstractSubSkill abstractSubSkill) {
String skillName = abstractSubSkill.getConfigKeyName();
int numRanks = abstractSubSkill.getNumRanks();
if (subSkillRanks == null)
if (subSkillRanks == null) {
subSkillRanks = new HashMap<>();
}
if (numRanks == 0)
if (numRanks == 0) {
return -1; //-1 Means the skill doesn't have ranks
}
if (subSkillRanks.get(skillName) == null && numRanks > 0)
if (subSkillRanks.get(skillName) == null && numRanks > 0) {
addRanks(abstractSubSkill);
}
//Get our rank map
HashMap<Integer, Integer> rankMap = subSkillRanks.get(skillName);
if (UserManager.getPlayer(player) == null)
if (UserManager.getPlayer(player) == null) {
return 0;
}
//Skill level of parent skill
int currentSkillLevel = UserManager.getPlayer(player).getSkillLevel(abstractSubSkill.getPrimarySkill());
int currentSkillLevel = UserManager.getPlayer(player)
.getSkillLevel(abstractSubSkill.getPrimarySkill());
for(int i = 0; i < numRanks; i++) {
for (int i = 0; i < numRanks; i++) {
//Compare against the highest to lowest rank in that order
int rank = numRanks-i;
int rank = numRanks - i;
int unlockLevel = getRankUnlockLevel(abstractSubSkill, rank);
//If we check all ranks and still cannot unlock the skill, we return rank 0
if (rank == 0)
if (rank == 0) {
return 0;
}
//True if our skill level can unlock the current rank
if (currentSkillLevel >= unlockLevel)
if (currentSkillLevel >= unlockLevel) {
return rank;
}
}
return 0; //We should never reach this
@@ -245,6 +274,7 @@ public class RankUtils {
/**
* Adds ranks to our map
*
* @param abstractSubSkill The subskill to add ranks for
* @param rank The rank to add
*/
@@ -266,14 +296,16 @@ public class RankUtils {
}
private static void initMaps(String s) {
if (subSkillRanks == null)
if (subSkillRanks == null) {
subSkillRanks = new HashMap<>();
}
subSkillRanks.computeIfAbsent(s, k -> new HashMap<>());
}
/**
* Gets the unlock level for a specific rank in a subskill
*
* @param subSkillType The target subskill
* @param rank The target rank
* @return The level at which this rank unlocks
@@ -288,6 +320,7 @@ public class RankUtils {
/**
* Get the level at which a skill is unlocked for a player (this is the first rank of a skill)
*
* @param subSkillType target subskill
* @return The unlock requirements for rank 1 in this skill
*/
@@ -297,6 +330,7 @@ public class RankUtils {
/**
* Get the level at which a skill is unlocked for a player (this is the first rank of a skill)
*
* @param abstractSubSkill target subskill
* @return The unlock requirements for rank 1 in this skill
*/
@@ -306,6 +340,7 @@ public class RankUtils {
/**
* Get the highest rank of a subskill
*
* @param subSkillType target subskill
* @return the last rank of a subskill
*/
@@ -319,6 +354,7 @@ public class RankUtils {
/**
* Get the highest rank of a subskill
*
* @param abstractSubSkill target subskill
* @return the last rank of a subskill
*/

View File

@@ -13,14 +13,18 @@ import com.gmail.nossr50.util.text.StringUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.VisibleForTesting;
import java.util.*;
public class SkillTools {
private final mcMMO pluginRef;
// TODO: Java has immutable types now, switch to those
@@ -46,9 +50,11 @@ public class SkillTools {
static {
ArrayList<PrimarySkillType> tempNonChildSkills = new ArrayList<>();
for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType != PrimarySkillType.SALVAGE && primarySkillType != PrimarySkillType.SMELTING)
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType != PrimarySkillType.SALVAGE
&& primarySkillType != PrimarySkillType.SMELTING) {
tempNonChildSkills.add(primarySkillType);
}
}
NON_CHILD_SKILLS = ImmutableList.copyOf(tempNonChildSkills);
@@ -62,11 +68,12 @@ public class SkillTools {
/*
* Setup subskill -> parent relationship map
*/
EnumMap<SubSkillType, PrimarySkillType> tempSubParentMap = new EnumMap<>(SubSkillType.class);
EnumMap<SubSkillType, PrimarySkillType> tempSubParentMap = new EnumMap<>(
SubSkillType.class);
//Super hacky and disgusting
for(PrimarySkillType primarySkillType1 : PrimarySkillType.values()) {
for(SubSkillType subSkillType : SubSkillType.values()) {
for (PrimarySkillType primarySkillType1 : PrimarySkillType.values()) {
for (SubSkillType subSkillType : SubSkillType.values()) {
String[] splitSubSkillName = subSkillType.toString().split("_");
if (primarySkillType1.toString().equalsIgnoreCase(splitSubSkillName[0])) {
@@ -82,15 +89,16 @@ public class SkillTools {
* Setup primary -> (collection) subskill map
*/
EnumMap<PrimarySkillType, Set<SubSkillType>> tempPrimaryChildMap = new EnumMap<>(PrimarySkillType.class);
EnumMap<PrimarySkillType, Set<SubSkillType>> tempPrimaryChildMap = new EnumMap<>(
PrimarySkillType.class);
//Init the empty Hash Sets
for(PrimarySkillType primarySkillType1 : PrimarySkillType.values()) {
for (PrimarySkillType primarySkillType1 : PrimarySkillType.values()) {
tempPrimaryChildMap.put(primarySkillType1, new HashSet<>());
}
//Fill in the hash sets
for(SubSkillType subSkillType : SubSkillType.values()) {
for (SubSkillType subSkillType : SubSkillType.values()) {
PrimarySkillType parentSkill = subSkillParentRelationshipMap.get(subSkillType);
//Add this subskill as a child
@@ -119,10 +127,12 @@ public class SkillTools {
* Setup primary -> ability map
*/
EnumMap<SuperAbilityType, PrimarySkillType> tempAbilityParentRelationshipMap = new EnumMap<>(SuperAbilityType.class);
EnumMap<PrimarySkillType, SuperAbilityType> tempMainActivatedAbilityChildMap = new EnumMap<>(PrimarySkillType.class);
EnumMap<SuperAbilityType, PrimarySkillType> tempAbilityParentRelationshipMap = new EnumMap<>(
SuperAbilityType.class);
EnumMap<PrimarySkillType, SuperAbilityType> tempMainActivatedAbilityChildMap = new EnumMap<>(
PrimarySkillType.class);
for(SuperAbilityType superAbilityType : SuperAbilityType.values()) {
for (SuperAbilityType superAbilityType : SuperAbilityType.values()) {
try {
PrimarySkillType parent = getSuperAbilityParent(superAbilityType);
tempAbilityParentRelationshipMap.put(superAbilityType, parent);
@@ -146,8 +156,9 @@ public class SkillTools {
List<PrimarySkillType> childSkills = new ArrayList<>();
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (isChildSkill(primarySkillType))
if (isChildSkill(primarySkillType)) {
childSkills.add(primarySkillType);
}
}
CHILD_SKILLS = ImmutableList.copyOf(childSkills);
@@ -200,7 +211,8 @@ public class SkillTools {
EXACT_SUBSKILL_NAMES = ImmutableSet.copyOf(buildExactSubSkillNameList());
}
private @NotNull PrimarySkillType getSuperAbilityParent(SuperAbilityType superAbilityType) throws InvalidSkillException {
private @NotNull PrimarySkillType getSuperAbilityParent(SuperAbilityType superAbilityType)
throws InvalidSkillException {
return switch (superAbilityType) {
case BERSERK -> PrimarySkillType.UNARMED;
case GREEN_TERRA -> PrimarySkillType.HERBALISM;
@@ -217,14 +229,14 @@ public class SkillTools {
}
/**
* Makes a list of the "nice" version of sub skill names
* Used in tab completion mostly
* Makes a list of the "nice" version of sub skill names Used in tab completion mostly
*
* @return a list of formatted sub skill names
*/
private @NotNull ArrayList<String> buildFormattedSubSkillNameList() {
ArrayList<String> subSkillNameList = new ArrayList<>();
for(SubSkillType subSkillType : SubSkillType.values()) {
for (SubSkillType subSkillType : SubSkillType.values()) {
subSkillNameList.add(subSkillType.getNiceNameNoSpaces(subSkillType));
}
@@ -234,7 +246,7 @@ public class SkillTools {
private @NotNull HashSet<String> buildExactSubSkillNameList() {
HashSet<String> subSkillNameExactSet = new HashSet<>();
for(SubSkillType subSkillType : SubSkillType.values()) {
for (SubSkillType subSkillType : SubSkillType.values()) {
subSkillNameExactSet.add(subSkillType.toString());
}
@@ -243,13 +255,14 @@ public class SkillTools {
/**
* Builds a list of localized {@link PrimarySkillType} names
*
* @return list of localized {@link PrimarySkillType} names
*/
@VisibleForTesting
private @NotNull ArrayList<String> buildLocalizedPrimarySkillNames() {
ArrayList<String> localizedSkillNameList = new ArrayList<>();
for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
localizedSkillNameList.add(getLocalizedSkillName(primarySkillType));
}
@@ -259,10 +272,9 @@ public class SkillTools {
}
/**
* Matches a string of a skill to a skill
* This is NOT case sensitive
* First it checks the locale file and tries to match by the localized name of the skill
* Then if nothing is found it checks against the hard coded "name" of the skill, which is just its name in English
* Matches a string of a skill to a skill This is NOT case sensitive First it checks the locale
* file and tries to match by the localized name of the skill Then if nothing is found it checks
* against the hard coded "name" of the skill, which is just its name in English
*
* @param skillName target skill name
* @return the matching PrimarySkillType if one is found, otherwise null
@@ -270,7 +282,8 @@ public class SkillTools {
public PrimarySkillType matchSkill(String skillName) {
if (!pluginRef.getGeneralConfig().getLocale().equalsIgnoreCase("en_US")) {
for (PrimarySkillType type : PrimarySkillType.values()) {
if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(type.name()) + ".SkillName"))) {
if (skillName.equalsIgnoreCase(LocaleLoader.getString(
StringUtils.getCapitalized(type.name()) + ".SkillName"))) {
return type;
}
}
@@ -283,15 +296,17 @@ public class SkillTools {
}
if (!skillName.equalsIgnoreCase("all")) {
pluginRef.getLogger().warning("Invalid mcMMO skill (" + skillName + ")"); //TODO: Localize
pluginRef.getLogger()
.warning("Invalid mcMMO skill (" + skillName + ")"); //TODO: Localize
}
return null;
}
/**
* Gets the PrimarySkillStype to which a SubSkillType belongs
* Return null if it does not belong to one.. which should be impossible in most circumstances
* Gets the PrimarySkillStype to which a SubSkillType belongs Return null if it does not belong
* to one.. which should be impossible in most circumstances
*
* @param subSkillType target subskill
* @return the PrimarySkillType of this SubSkill, null if it doesn't exist
*/
@@ -300,8 +315,9 @@ public class SkillTools {
}
/**
* Gets the PrimarySkillStype to which a SuperAbilityType belongs
* Return null if it does not belong to one.. which should be impossible in most circumstances
* Gets the PrimarySkillStype to which a SuperAbilityType belongs Return null if it does not
* belong to one.. which should be impossible in most circumstances
*
* @param superAbilityType target super ability
* @return the PrimarySkillType of this SuperAbilityType, null if it doesn't exist
*/
@@ -310,14 +326,16 @@ public class SkillTools {
}
public SuperAbilityType getSuperAbility(PrimarySkillType primarySkillType) {
if (mainActivatedAbilityChildMap.get(primarySkillType) == null)
if (mainActivatedAbilityChildMap.get(primarySkillType) == null) {
return null;
}
return mainActivatedAbilityChildMap.get(primarySkillType);
}
public boolean isSuperAbilityUnlocked(PrimarySkillType primarySkillType, Player player) {
SuperAbilityType superAbilityType = mcMMO.p.getSkillTools().getSuperAbility(primarySkillType);
SuperAbilityType superAbilityType = mcMMO.p.getSkillTools()
.getSuperAbility(primarySkillType);
SubSkillType subSkillType = superAbilityType.getSubSkillTypeDefinition();
return RankUtils.hasUnlockedSubskill(player, subSkillType);
}
@@ -360,11 +378,13 @@ public class SkillTools {
/**
* Get the localized name for a {@link PrimarySkillType}
*
* @param primarySkillType target {@link PrimarySkillType}
* @return the localized name for a {@link PrimarySkillType}
*/
public String getLocalizedSkillName(PrimarySkillType primarySkillType) {
return LocaleLoader.getString(StringUtils.getCapitalized(primarySkillType.toString()) + ".SkillName");
return LocaleLoader.getString(
StringUtils.getCapitalized(primarySkillType.toString()) + ".SkillName");
}
public boolean doesPlayerHaveSkillPermission(Player player, PrimarySkillType primarySkillType) {
@@ -372,7 +392,9 @@ public class SkillTools {
}
public boolean canCombatSkillsTrigger(PrimarySkillType primarySkillType, Entity target) {
return (target instanceof Player || (target instanceof Tameable && ((Tameable) target).isTamed())) ? getPVPEnabled(primarySkillType) : getPVEEnabled(primarySkillType);
return (target instanceof Player || (target instanceof Tameable
&& ((Tameable) target).isTamed())) ? getPVPEnabled(primarySkillType)
: getPVEEnabled(primarySkillType);
}
public String getCapitalizedPrimarySkillName(PrimarySkillType primarySkillType) {
@@ -422,7 +444,8 @@ public class SkillTools {
return MISC_SKILLS;
}
public @NotNull ImmutableList<PrimarySkillType> getChildSkillParents(PrimarySkillType childSkill)
public @NotNull ImmutableList<PrimarySkillType> getChildSkillParents(
PrimarySkillType childSkill)
throws IllegalArgumentException {
switch (childSkill) {
case SALVAGE -> {
@@ -431,7 +454,8 @@ public class SkillTools {
case SMELTING -> {
return SMELTING_PARENTS;
}
default -> throw new IllegalArgumentException("Skill " + childSkill + " is not a child skill");
default -> throw new IllegalArgumentException(
"Skill " + childSkill + " is not a child skill");
}
}
}

View File

@@ -1,5 +1,10 @@
package com.gmail.nossr50.util.skills;
import static com.gmail.nossr50.util.ItemMetadataUtils.isLegacyAbilityTool;
import static com.gmail.nossr50.util.ItemMetadataUtils.isSuperAbilityBoosted;
import static com.gmail.nossr50.util.ItemMetadataUtils.removeBonusDigSpeedOnSuperAbilityTool;
import static com.gmail.nossr50.util.PotionEffectUtil.getHastePotionEffectType;
import com.gmail.nossr50.config.HiddenConfig;
import com.gmail.nossr50.datatypes.experience.XPGainReason;
import com.gmail.nossr50.datatypes.experience.XPGainSource;
@@ -17,6 +22,7 @@ import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.text.StringUtils;
import java.util.Iterator;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -30,39 +36,39 @@ import org.bukkit.potion.PotionEffect;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import static com.gmail.nossr50.util.ItemMetadataUtils.*;
import static com.gmail.nossr50.util.PotionEffectUtil.getHastePotionEffectType;
public final class SkillUtils {
/**
* This is a static utility class, therefore we don't want any instances of
* this class. Making the constructor private prevents accidents like that.
* This is a static utility class, therefore we don't want any instances of this class. Making
* the constructor private prevents accidents like that.
*/
private SkillUtils() {}
public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason) {
mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF);
private SkillUtils() {
}
public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason, XPGainSource xpGainSource) {
mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, xpGainSource);
public static void applyXpGain(McMMOPlayer mmoPlayer, PrimarySkillType skill, float xp,
XPGainReason xpGainReason) {
mmoPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF);
}
public static void applyXpGain(McMMOPlayer mmoPlayer, PrimarySkillType skill, float xp,
XPGainReason xpGainReason, XPGainSource xpGainSource) {
mmoPlayer.beginXpGain(skill, xp, xpGainReason, xpGainSource);
}
/*
* Skill Stat Calculations
*/
public static String[] calculateLengthDisplayValues(Player player, float skillValue, PrimarySkillType skill) {
int maxLength = mcMMO.p.getSkillTools().getSuperAbilityMaxLength(mcMMO.p.getSkillTools().getSuperAbility(skill));
public static String[] calculateLengthDisplayValues(Player player, float skillValue,
PrimarySkillType skill) {
int maxLength = mcMMO.p.getSkillTools()
.getSuperAbilityMaxLength(mcMMO.p.getSkillTools().getSuperAbility(skill));
int abilityLengthVar = mcMMO.p.getAdvancedConfig().getAbilityLength();
int abilityLengthCap = mcMMO.p.getAdvancedConfig().getAbilityLengthCap();
int length;
if (abilityLengthCap > 0) {
length = (int) Math.min(abilityLengthCap, 2 + (skillValue / abilityLengthVar));
length = (int) Math.min(abilityLengthCap, 2 + (skillValue / abilityLengthVar));
} else {
length = 2 + (int) (skillValue / abilityLengthVar);
}
@@ -73,20 +79,21 @@ public final class SkillUtils {
length = Math.min(length, maxLength);
}
return new String[] { String.valueOf(length), String.valueOf(enduranceLength) };
return new String[]{String.valueOf(length), String.valueOf(enduranceLength)};
}
/*
* Others
*/
public static int handleFoodSkills(Player player, int eventFoodLevel, SubSkillType subSkillType) {
public static int handleFoodSkills(Player player, int eventFoodLevel,
SubSkillType subSkillType) {
int curRank = RankUtils.getRank(player, subSkillType);
int currentFoodLevel = player.getFoodLevel();
int foodChange = eventFoodLevel - currentFoodLevel;
foodChange+=curRank;
foodChange += curRank;
return currentFoodLevel + foodChange;
}
@@ -97,24 +104,24 @@ public final class SkillUtils {
* @param deactivatedTimeStamp Time of deactivation
* @param cooldown The length of the cooldown
* @param player The Player to check for cooldown perks
*
* @return the number of seconds remaining before the cooldown expires
*/
public static int calculateTimeLeft(long deactivatedTimeStamp, int cooldown, Player player) {
return (int) (((deactivatedTimeStamp + (PerksUtils.handleCooldownPerks(player, cooldown) * Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis()) / Misc.TIME_CONVERSION_FACTOR);
return (int) (((deactivatedTimeStamp + (PerksUtils.handleCooldownPerks(player, cooldown)
* Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis())
/ Misc.TIME_CONVERSION_FACTOR);
}
/**
* Check if the cooldown has expired.
* This does NOT account for cooldown perks!
* Check if the cooldown has expired. This does NOT account for cooldown perks!
*
* @param deactivatedTimeStamp Time of deactivation in seconds
* @param cooldown The length of the cooldown in seconds
*
* @return true if the cooldown is expired
*/
public static boolean cooldownExpired(long deactivatedTimeStamp, int cooldown) {
return System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
return System.currentTimeMillis()
>= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
}
/**
@@ -124,15 +131,19 @@ public final class SkillUtils {
* @return true if this is a valid skill, false otherwise
*/
public static boolean isSkill(String skillName) {
return mcMMO.p.getGeneralConfig().getLocale().equalsIgnoreCase("en_US") ? mcMMO.p.getSkillTools().matchSkill(skillName) != null : isLocalizedSkill(skillName);
return mcMMO.p.getGeneralConfig().getLocale().equalsIgnoreCase("en_US") ?
mcMMO.p.getSkillTools().matchSkill(skillName) != null : isLocalizedSkill(skillName);
}
public static void sendSkillMessage(Player player, NotificationType notificationType, String key) {
public static void sendSkillMessage(Player player, NotificationType notificationType,
String key) {
Location location = player.getLocation();
for (Player otherPlayer : player.getWorld().getPlayers()) {
if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
NotificationManager.sendNearbyPlayersInformation(otherPlayer, notificationType, key, player.getName());
if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(),
Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
NotificationManager.sendNearbyPlayersInformation(otherPlayer, notificationType, key,
player.getName());
}
}
}
@@ -141,15 +152,18 @@ public final class SkillUtils {
if (HiddenConfig.getInstance().useEnchantmentBuffs()) {
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (heldItem == null)
if (heldItem == null) {
return;
}
if (!ItemUtils.canBeSuperAbilityDigBoosted(heldItem)) {
return;
}
int originalDigSpeed = heldItem.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getEfficiency());
ItemUtils.addDigSpeedToItem(heldItem, heldItem.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getEfficiency()));
int originalDigSpeed = heldItem.getEnchantmentLevel(
mcMMO.p.getEnchantmentMapper().getEfficiency());
ItemUtils.addDigSpeedToItem(heldItem,
heldItem.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getEfficiency()));
//1.13.2+ will have persistent metadata for this item
ItemMetadataUtils.setSuperAbilityBoostedItem(heldItem, originalDigSpeed);
@@ -167,13 +181,15 @@ public final class SkillUtils {
}
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
final McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
//Not Loaded
if (mcMMOPlayer == null)
if (mmoPlayer == null) {
return;
}
PrimarySkillType skill = mcMMOPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER) ? PrimarySkillType.MINING : PrimarySkillType.EXCAVATION;
PrimarySkillType skill = mmoPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER)
? PrimarySkillType.MINING : PrimarySkillType.EXCAVATION;
int abilityLengthVar = mcMMO.p.getAdvancedConfig().getAbilityLength();
int abilityLengthCap = mcMMO.p.getAdvancedConfig().getAbilityLengthCap();
@@ -181,14 +197,21 @@ public final class SkillUtils {
int ticks;
if (abilityLengthCap > 0) {
ticks = PerksUtils.handleActivationPerks(player, Math.min(abilityLengthCap, 2 + (mcMMOPlayer.getSkillLevel(skill) / abilityLengthVar)),
mcMMO.p.getSkillTools().getSuperAbilityMaxLength(mcMMO.p.getSkillTools().getSuperAbility(skill))) * Misc.TICK_CONVERSION_FACTOR;
ticks = PerksUtils.handleActivationPerks(player, Math.min(abilityLengthCap,
2 + (mmoPlayer.getSkillLevel(skill) / abilityLengthVar)),
mcMMO.p.getSkillTools().getSuperAbilityMaxLength(
mcMMO.p.getSkillTools().getSuperAbility(skill)))
* Misc.TICK_CONVERSION_FACTOR;
} else {
ticks = PerksUtils.handleActivationPerks(player, 2 + ((mcMMOPlayer.getSkillLevel(skill)) / abilityLengthVar),
mcMMO.p.getSkillTools().getSuperAbilityMaxLength(mcMMO.p.getSkillTools().getSuperAbility(skill))) * Misc.TICK_CONVERSION_FACTOR;
ticks = PerksUtils.handleActivationPerks(player,
2 + ((mmoPlayer.getSkillLevel(skill)) / abilityLengthVar),
mcMMO.p.getSkillTools().getSuperAbilityMaxLength(
mcMMO.p.getSkillTools().getSuperAbility(skill)))
* Misc.TICK_CONVERSION_FACTOR;
}
PotionEffect abilityBuff = new PotionEffect(getHastePotionEffectType(), duration + ticks, amplifier + 10);
PotionEffect abilityBuff = new PotionEffect(getHastePotionEffectType(),
duration + ticks, amplifier + 10);
player.addPotionEffect(abilityBuff, true);
}
}
@@ -200,12 +223,13 @@ public final class SkillUtils {
}
public static void removeAbilityBuff(@Nullable ItemStack itemStack) {
if (itemStack == null)
if (itemStack == null) {
return;
}
if (!ItemUtils.canBeSuperAbilityDigBoosted(itemStack))
if (!ItemUtils.canBeSuperAbilityDigBoosted(itemStack)) {
return;
}
//1.13.2+ will have persistent metadata for this itemStack
if (isLegacyAbilityTool(itemStack)) {
@@ -230,27 +254,35 @@ public final class SkillUtils {
}
/**
* Modify the durability of an ItemStack, using Tools specific formula for unbreaking enchant damage reduction
* Modify the durability of an ItemStack, using Tools specific formula for unbreaking enchant
* damage reduction
*
* @param itemStack The ItemStack which durability should be modified
* @param durabilityModifier the amount to modify the durability by
* @param maxDamageModifier the amount to adjust the max damage by
*/
public static void handleDurabilityChange(ItemStack itemStack, double durabilityModifier, double maxDamageModifier) {
public static void handleDurabilityChange(ItemStack itemStack, double durabilityModifier,
double maxDamageModifier) {
if (itemStack.hasItemMeta() && itemStack.getItemMeta().isUnbreakable()) {
return;
}
Material type = itemStack.getType();
short maxDurability = mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getUnbreaking()) + 1), maxDurability * maxDamageModifier);
short maxDurability =
mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager()
.getRepairable(type).getMaximumDurability() : type.getMaxDurability();
durabilityModifier = (int) Math.min(durabilityModifier / (
itemStack.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getUnbreaking()) + 1),
maxDurability * maxDamageModifier);
itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
itemStack.setDurability(
(short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
}
private static boolean isLocalizedSkill(String skillName) {
for (PrimarySkillType skill : PrimarySkillType.values()) {
if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
if (skillName.equalsIgnoreCase(LocaleLoader.getString(
StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
return true;
}
}
@@ -260,22 +292,29 @@ public final class SkillUtils {
/**
* Modify the durability of an ItemStack, using Armor specific formula for unbreaking enchant damage reduction
* Modify the durability of an ItemStack, using Armor specific formula for unbreaking enchant
* damage reduction
*
* @param itemStack The ItemStack which durability should be modified
* @param durabilityModifier the amount to modify the durability by
* @param maxDamageModifier the amount to adjust the max damage by
*/
public static void handleArmorDurabilityChange(ItemStack itemStack, double durabilityModifier, double maxDamageModifier) {
public static void handleArmorDurabilityChange(ItemStack itemStack, double durabilityModifier,
double maxDamageModifier) {
if (itemStack.hasItemMeta() && itemStack.getItemMeta().isUnbreakable()) {
return;
}
Material type = itemStack.getType();
short maxDurability = mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
durabilityModifier = (int) Math.min(durabilityModifier * (0.6 + 0.4/ (itemStack.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getUnbreaking()) + 1)), maxDurability * maxDamageModifier);
short maxDurability =
mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager()
.getRepairable(type).getMaximumDurability() : type.getMaxDurability();
durabilityModifier = (int) Math.min(durabilityModifier * (0.6 + 0.4 / (
itemStack.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getUnbreaking()) + 1)),
maxDurability * maxDamageModifier);
itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
itemStack.setDurability(
(short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
}
@Nullable
@@ -307,7 +346,8 @@ public final class SkillUtils {
return getRepairAndSalvageQuantities(item.getType(), getRepairAndSalvageItem(item));
}
public static int getRepairAndSalvageQuantities(Material itemMaterial, Material recipeMaterial) {
public static int getRepairAndSalvageQuantities(Material itemMaterial,
Material recipeMaterial) {
int quantity = 0;
if (mcMMO.getMaterialMapStore().isPrismarineTool(itemMaterial)) {
@@ -320,11 +360,13 @@ public final class SkillUtils {
return 4;
}
for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
for (Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator();
recipeIterator.hasNext(); ) {
Recipe bukkitRecipe = recipeIterator.next();
if (bukkitRecipe.getResult().getType() != itemMaterial)
if (bukkitRecipe.getResult().getType() != itemMaterial) {
continue;
}
if (bukkitRecipe instanceof ShapelessRecipe) {
for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
@@ -335,7 +377,8 @@ public final class SkillUtils {
}
}
} else if (bukkitRecipe instanceof ShapedRecipe) {
for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap().values()) {
for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap()
.values()) {
if (ingredient != null
&& (recipeMaterial == null || ingredient.getType() == recipeMaterial)
&& (ingredient.getType() == recipeMaterial)) {
@@ -350,11 +393,13 @@ public final class SkillUtils {
/**
* Checks if a player can use a skill
*
* @param player target player
* @param subSkillType target subskill
* @return true if the player has permission and has the skill unlocked
*/
public static boolean canUseSubskill(Player player, @NotNull SubSkillType subSkillType) {
return Permissions.isSubSkillEnabled(player, subSkillType) && RankUtils.hasUnlockedSubskill(player, subSkillType);
return Permissions.isSubSkillEnabled(player, subSkillType) && RankUtils.hasUnlockedSubskill(
player, subSkillType);
}
}