mcMMO 2.2.000-RC1 candidate for release

This commit is contained in:
nossr50
2024-03-30 06:16:10 -07:00
142 changed files with 3589 additions and 1994 deletions

View File

@@ -10,13 +10,13 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.metadata.MobMetaFlagType;
import com.gmail.nossr50.metadata.MobMetadataService;
import com.gmail.nossr50.party.PartyManager;
import com.gmail.nossr50.runnables.skills.AwardCombatXpTask;
import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
import com.gmail.nossr50.skills.archery.ArcheryManager;
import com.gmail.nossr50.skills.axes.AxesManager;
import com.gmail.nossr50.skills.swords.SwordsManager;
import com.gmail.nossr50.skills.taming.TamingManager;
import com.gmail.nossr50.skills.tridents.TridentsManager;
import com.gmail.nossr50.skills.unarmed.UnarmedManager;
import com.gmail.nossr50.util.*;
import com.gmail.nossr50.util.player.NotificationManager;
@@ -45,7 +45,6 @@ public final class CombatUtils {
return mcMMO.getMetadataService().getMobMetadataService();
}
//Likely.. because who knows what plugins are throwing around
public static boolean isDamageLikelyFromNormalCombat(@NotNull DamageCause damageCause) {
return switch (damageCause) {
case ENTITY_ATTACK, ENTITY_SWEEP_ATTACK, PROJECTILE -> true;
@@ -112,6 +111,78 @@ public final class CombatUtils {
}
}
}
private static void processTridentCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) {
return;
}
double boostedDamage = event.getDamage();
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Make sure the profiles been loaded
if(mcMMOPlayer == null) {
return;
}
TridentsManager tridentsManager = mcMMOPlayer.getTridentsManager();
if (tridentsManager.canActivateAbility()) {
mcMMOPlayer.checkAbilityActivation(PrimarySkillType.TRIDENTS);
}
if (SkillUtils.canUseSubskill(player, SubSkillType.TRIDENTS_IMPALE)) {
boostedDamage += (tridentsManager.impaleDamageBonus() * mcMMOPlayer.getAttackStrength());
}
if(canUseLimitBreak(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK)) {
boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength());
}
event.setDamage(boostedDamage);
processCombatXP(mcMMOPlayer, target, PrimarySkillType.TRIDENTS);
printFinalDamageDebug(player, event, mcMMOPlayer);
}
private static void processCrossbowsCombat(@NotNull LivingEntity target, @NotNull Player player,
@NotNull EntityDamageByEntityEvent event, @NotNull Arrow arrow) {
double initialDamage = event.getDamage();
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Make sure the profiles been loaded
if(mcMMOPlayer == null) {
delayArrowMetaCleanup(arrow);
return;
}
double boostedDamage = event.getDamage();
if (SkillUtils.canUseSubskill(player, SubSkillType.CROSSBOWS_POWERED_SHOT)) {
//Not Additive
boostedDamage = mcMMOPlayer.getCrossbowsManager().poweredShot(initialDamage);
}
if(canUseLimitBreak(player, target, SubSkillType.CROSSBOWS_CROSSBOWS_LIMIT_BREAK)) {
boostedDamage+=getLimitBreakDamage(player, target, SubSkillType.CROSSBOWS_CROSSBOWS_LIMIT_BREAK);
}
double distanceMultiplier = ArcheryManager.distanceXpBonusMultiplier(target, arrow);
double forceMultiplier = 1.0;
event.setDamage(boostedDamage);
processCombatXP(mcMMOPlayer, target, PrimarySkillType.CROSSBOWS, forceMultiplier * distanceMultiplier);
printFinalDamageDebug(player, event, mcMMOPlayer,
"Distance Multiplier: "+distanceMultiplier,
"Force Multiplier: "+forceMultiplier,
"Initial Damage: "+initialDamage,
"Final Damage: "+boostedDamage);
//Clean data
delayArrowMetaCleanup(arrow);
}
private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) {
@@ -240,14 +311,15 @@ public final class CombatUtils {
}
private static void processArcheryCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event, @NotNull Projectile arrow) {
private static void processArcheryCombat(@NotNull LivingEntity target, @NotNull Player player,
@NotNull EntityDamageByEntityEvent event, @NotNull Arrow arrow) {
double initialDamage = event.getDamage();
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Make sure the profiles been loaded
if(mcMMOPlayer == null) {
cleanupArrowMetadata(arrow);
delayArrowMetaCleanup(arrow);
return;
}
@@ -273,7 +345,7 @@ public final class CombatUtils {
boostedDamage+=getLimitBreakDamage(player, target, SubSkillType.ARCHERY_ARCHERY_LIMIT_BREAK);
}
double distanceMultiplier = archeryManager.distanceXpBonusMultiplier(target, arrow);
double distanceMultiplier = ArcheryManager.distanceXpBonusMultiplier(target, arrow);
double forceMultiplier = 1.0; //Hacky Fix - some plugins spawn arrows and assign them to players after the ProjectileLaunchEvent fires
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE))
@@ -288,7 +360,7 @@ public final class CombatUtils {
"Initial Damage: "+initialDamage,
"Final Damage: "+boostedDamage);
//Clean data
cleanupArrowMetadata(arrow);
delayArrowMetaCleanup(arrow);
}
/**
@@ -387,6 +459,15 @@ public final class CombatUtils {
processUnarmedCombat(target, player, event);
}
}
else if (ItemUtils.isTrident(heldItem)) {
if (!mcMMO.p.getSkillTools().canCombatSkillsTrigger(PrimarySkillType.TRIDENTS, target)) {
return;
}
if (mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.TRIDENTS)) {
processTridentCombat(target, player, event);
}
}
}
else if (entityType == EntityType.WOLF) {
@@ -400,20 +481,25 @@ public final class CombatUtils {
}
}
}
else if (entityType == EntityType.ARROW || entityType == EntityType.SPECTRAL_ARROW) {
Projectile arrow = (Projectile) painSource;
else if (painSource instanceof Arrow arrow) {
ProjectileSource projectileSource = arrow.getShooter();
boolean isCrossbow = arrow.isShotFromCrossbow();
if (projectileSource instanceof Player player) {
if (projectileSource instanceof Player player && mcMMO.p.getSkillTools().canCombatSkillsTrigger(PrimarySkillType.ARCHERY, target)) {
if (!Misc.isNPCEntityExcludingVillagers(player) && mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.ARCHERY)) {
processArcheryCombat(target, player, event, arrow);
if (!Misc.isNPCEntityExcludingVillagers(player)) {
if(!isCrossbow && mcMMO.p.getSkillTools().canCombatSkillsTrigger(PrimarySkillType.ARCHERY, target)) {
processArcheryCombat(target, player, event, arrow);
} else if(isCrossbow && mcMMO.p.getSkillTools().canCombatSkillsTrigger(PrimarySkillType.CROSSBOWS, target)) {
processCrossbowsCombat(target, player, event, arrow);
}
} else {
//Cleanup Arrow
cleanupArrowMetadata(arrow);
delayArrowMetaCleanup(arrow);
}
if (target.getType() != EntityType.CREEPER && !Misc.isNPCEntityExcludingVillagers(player) && mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.TAMING)) {
if (target.getType() != EntityType.CREEPER
&& !Misc.isNPCEntityExcludingVillagers(player)
&& mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.TAMING)) {
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
if(mcMMOPlayer == null)
@@ -424,7 +510,6 @@ public final class CombatUtils {
}
}
}
}
/**
@@ -625,7 +710,7 @@ public final class CombatUtils {
}
public static boolean hasIgnoreDamageMetadata(@NotNull LivingEntity target) {
return target.getMetadata(MetadataConstants.METADATA_KEY_CUSTOM_DAMAGE).size() != 0;
return target.hasMetadata(MetadataConstants.METADATA_KEY_CUSTOM_DAMAGE);
}
public static void dealNoInvulnerabilityTickDamageRupture(@NotNull LivingEntity target, double damage, Entity attacker, int toolTier) {
@@ -634,35 +719,6 @@ public final class CombatUtils {
}
dealNoInvulnerabilityTickDamage(target, damage, attacker);
// //IFrame storage
//// int noDamageTicks = target.getNoDamageTicks();
//
//// String debug = "BLEED DMG RESULT: INC DMG:"+damage+", HP-Before:"+target.getHealth()+", HP-After:";
//
//// double incDmg = getFakeDamageFinalResult(attacker, target, DamageCause.ENTITY_ATTACK, damage);
//
//// double newHealth = Math.max(0, target.getHealth() - incDmg);
//
// //Don't kill things with a stone or wooden weapon
//// if(toolTier < 3 && newHealth == 0)
//// return;
//
// target.setMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY, mcMMO.metadataValue);
//
// if(newHealth == 0 && !(target instanceof Player))
// {
// target.damage(99999, attacker);
// }
// else
// {
//// Vector beforeRuptureVec = new Vector(target.getVelocity().getX(), target.getVelocity().getY(), target.getVelocity().getZ()); ;
// target.damage(damage, attacker);
//// debug+=target.getHealth();
// Bukkit.broadcastMessage(debug);
//// target.setNoDamageTicks(noDamageTicks); //Do not add additional IFrames
//// target.setVelocity(beforeRuptureVec);
// }
}
/**
@@ -745,14 +801,16 @@ public final class CombatUtils {
XPGainReason xpGainReason;
if (target instanceof Player defender) {
if (!ExperienceConfig.getInstance().getExperienceGainsPlayerVersusPlayerEnabled() ||
if (!ExperienceConfig.getInstance().getExperienceGainsPlayerVersusPlayerEnabled()
||
(mcMMO.p.getPartyConfig().isPartyEnabled() && mcMMO.p.getPartyManager().inSameParty(mcMMOPlayer.getPlayer(), (Player) target))) {
return;
}
xpGainReason = XPGainReason.PVP;
if (defender.isOnline() && SkillUtils.cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)) {
if (defender.isOnline()
&& SkillUtils.cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)) {
baseXP = 20 * ExperienceConfig.getInstance().getPlayerVersusPlayerXP();
}
}
@@ -811,7 +869,7 @@ public final class CombatUtils {
baseXP *= multiplier;
if (baseXP != 0) {
if (baseXP > 0) {
mcMMO.p.getFoliaLib().getImpl().runAtEntity(mcMMOPlayer.getPlayer(), new AwardCombatXpTask(mcMMOPlayer, primarySkillType, baseXP, target, xpGainReason));
}
}
@@ -949,31 +1007,12 @@ public final class CombatUtils {
}
}
/**
* Clean up metadata from a projectile
*
* @param entity projectile
*/
public static void cleanupArrowMetadata(@NotNull Projectile entity) {
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_INF_ARROW)) {
entity.removeMetadata(MetadataConstants.METADATA_KEY_INF_ARROW, mcMMO.p);
}
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE)) {
entity.removeMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE, mcMMO.p);
}
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE)) {
entity.removeMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE, mcMMO.p);
}
}
/**
* Clean up metadata from a projectile after a minute has passed
*
* @param entity the projectile
* @param arrow the projectile
*/
public static void delayArrowMetaCleanup(@NotNull Projectile entity) {
mcMMO.p.getFoliaLib().getImpl().runLater(() -> cleanupArrowMetadata(entity), 20*60);
public static void delayArrowMetaCleanup(@NotNull Arrow arrow) {
mcMMO.p.getFoliaLib().getImpl().runLater(() -> ProjectileUtils.cleanupProjectileMetadata(arrow), 20*120);
}
}

View File

@@ -0,0 +1,84 @@
package com.gmail.nossr50.util.skills;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.MetadataConstants;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Arrow;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
public class ProjectileUtils {
public static Vector getNormal(BlockFace blockFace) {
return switch (blockFace) {
case UP -> new Vector(0, 1, 0);
case DOWN -> new Vector(0, -1, 0);
case NORTH -> new Vector(0, 0, -1);
case SOUTH -> new Vector(0, 0, 1);
case EAST -> new Vector(1, 0, 0);
case WEST -> new Vector(-1, 0, 0);
default -> new Vector(0, 0, 0);
};
}
/**
* Clean up all possible mcMMO related metadata for a projectile
*
* @param arrow projectile
*/
// TODO: Add test
public static void cleanupProjectileMetadata(@NotNull Arrow arrow) {
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_INF_ARROW)) {
arrow.removeMetadata(MetadataConstants.METADATA_KEY_INF_ARROW, mcMMO.p);
}
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE)) {
arrow.removeMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE, mcMMO.p);
}
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE)) {
arrow.removeMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE, mcMMO.p);
}
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
arrow.removeMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW, mcMMO.p);
}
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW)) {
arrow.removeMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW, mcMMO.p);
}
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_BOUNCE_COUNT)) {
arrow.removeMetadata(MetadataConstants.METADATA_KEY_BOUNCE_COUNT, mcMMO.p);
}
}
public static void copyArrowMetadata(@NotNull Plugin pluginRef, @NotNull Arrow arrowToCopy, @NotNull Arrow newArrow) {
if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_INF_ARROW)) {
newArrow.setMetadata(MetadataConstants.METADATA_KEY_INF_ARROW,
arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_INF_ARROW).get(0));
}
if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE)) {
newArrow.setMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE,
new FixedMetadataValue(pluginRef,
arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE).get(0).asDouble()));
}
if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE)) {
newArrow.setMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE,
arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE).get(0));
}
if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
newArrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW).get(0));
}
if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW)) {
newArrow.setMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW,
arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW).get(0));
}
}
}

View File

@@ -24,7 +24,7 @@ public class RankUtils {
*
* @param plugin plugin instance ref
* @param mcMMOPlayer target player
* @param primarySkillType
* @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)
@@ -55,6 +55,9 @@ public class RankUtils {
}
}
/**
* Reset the interval between skill unlock notifications
*/
public static void resetUnlockDelayTimer()
{
count = 0;

View File

@@ -30,6 +30,8 @@ public class SkillTools {
public final @NotNull ImmutableSet<String> EXACT_SUBSKILL_NAMES;
public final @NotNull ImmutableList<PrimarySkillType> CHILD_SKILLS;
public final static @NotNull ImmutableList<PrimarySkillType> NON_CHILD_SKILLS;
public final static @NotNull ImmutableList<PrimarySkillType> SALVAGE_PARENTS;
public final static @NotNull ImmutableList<PrimarySkillType> SMELTING_PARENTS;
public final @NotNull ImmutableList<PrimarySkillType> COMBAT_SKILLS;
public final @NotNull ImmutableList<PrimarySkillType> GATHERING_SKILLS;
public final @NotNull ImmutableList<PrimarySkillType> MISC_SKILLS;
@@ -50,9 +52,11 @@ public class SkillTools {
}
NON_CHILD_SKILLS = ImmutableList.copyOf(tempNonChildSkills);
SALVAGE_PARENTS = ImmutableList.of(PrimarySkillType.REPAIR, PrimarySkillType.FISHING);
SMELTING_PARENTS = ImmutableList.of(PrimarySkillType.MINING, PrimarySkillType.REPAIR);
}
public SkillTools(@NotNull mcMMO pluginRef) {
public SkillTools(@NotNull mcMMO pluginRef) throws InvalidSkillException {
this.pluginRef = pluginRef;
/*
@@ -140,26 +144,38 @@ public class SkillTools {
*/
List<PrimarySkillType> childSkills = new ArrayList<>();
// List<PrimarySkillType> nonChildSkills = new ArrayList<>();
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (isChildSkill(primarySkillType))
childSkills.add(primarySkillType);
// } {
// nonChildSkills.add(primarySkillType);
// }
}
CHILD_SKILLS = ImmutableList.copyOf(childSkills);
// NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
/*
* Build categorized skill lists
*/
COMBAT_SKILLS = ImmutableList.of(PrimarySkillType.ARCHERY, PrimarySkillType.AXES, PrimarySkillType.SWORDS, PrimarySkillType.TAMING, PrimarySkillType.UNARMED);
GATHERING_SKILLS = ImmutableList.of(PrimarySkillType.EXCAVATION, PrimarySkillType.FISHING, PrimarySkillType.HERBALISM, PrimarySkillType.MINING, PrimarySkillType.WOODCUTTING);
MISC_SKILLS = ImmutableList.of(PrimarySkillType.ACROBATICS, PrimarySkillType.ALCHEMY, PrimarySkillType.REPAIR, PrimarySkillType.SALVAGE, PrimarySkillType.SMELTING);
COMBAT_SKILLS = ImmutableList.of(
PrimarySkillType.ARCHERY,
PrimarySkillType.AXES,
PrimarySkillType.CROSSBOWS,
PrimarySkillType.SWORDS,
PrimarySkillType.TAMING,
PrimarySkillType.TRIDENTS,
PrimarySkillType.UNARMED);
GATHERING_SKILLS = ImmutableList.of(
PrimarySkillType.EXCAVATION,
PrimarySkillType.FISHING,
PrimarySkillType.HERBALISM,
PrimarySkillType.MINING,
PrimarySkillType.WOODCUTTING);
MISC_SKILLS = ImmutableList.of(
PrimarySkillType.ACROBATICS,
PrimarySkillType.ALCHEMY,
PrimarySkillType.REPAIR,
PrimarySkillType.SALVAGE,
PrimarySkillType.SMELTING);
/*
* Build formatted/localized/etc string lists
@@ -171,25 +187,18 @@ public class SkillTools {
}
private @NotNull PrimarySkillType getSuperAbilityParent(SuperAbilityType superAbilityType) throws InvalidSkillException {
switch(superAbilityType) {
case BERSERK:
return PrimarySkillType.UNARMED;
case GREEN_TERRA:
return PrimarySkillType.HERBALISM;
case TREE_FELLER:
return PrimarySkillType.WOODCUTTING;
case SUPER_BREAKER:
case BLAST_MINING:
return PrimarySkillType.MINING;
case SKULL_SPLITTER:
return PrimarySkillType.AXES;
case SERRATED_STRIKES:
return PrimarySkillType.SWORDS;
case GIGA_DRILL_BREAKER:
return PrimarySkillType.EXCAVATION;
default:
throw new InvalidSkillException("No parent defined for super ability! "+superAbilityType.toString());
}
return switch (superAbilityType) {
case BERSERK -> PrimarySkillType.UNARMED;
case GREEN_TERRA -> PrimarySkillType.HERBALISM;
case TREE_FELLER -> PrimarySkillType.WOODCUTTING;
case SUPER_BREAKER, BLAST_MINING -> PrimarySkillType.MINING;
case SKULL_SPLITTER -> PrimarySkillType.AXES;
case SERRATED_STRIKES -> PrimarySkillType.SWORDS;
case GIGA_DRILL_BREAKER -> PrimarySkillType.EXCAVATION;
case SUPER_SHOTGUN -> PrimarySkillType.CROSSBOWS;
case TRIDENTS_SUPER_ABILITY -> PrimarySkillType.TRIDENTS;
case EXPLOSIVE_SHOT -> PrimarySkillType.ARCHERY;
};
}
/**
@@ -319,7 +328,6 @@ public class SkillTools {
}
public Set<SubSkillType> getSubSkills(PrimarySkillType primarySkillType) {
//TODO: Cache this!
return primarySkillChildrenMap.get(primarySkillType);
}
@@ -329,14 +337,10 @@ public class SkillTools {
// TODO: This is a little "hacky", we probably need to add something to distinguish child skills in the enum, or to use another enum for them
public static boolean isChildSkill(PrimarySkillType primarySkillType) {
switch (primarySkillType) {
case SALVAGE:
case SMELTING:
return true;
default:
return false;
}
return switch (primarySkillType) {
case SALVAGE, SMELTING -> true;
default -> false;
};
}
/**
@@ -401,34 +405,7 @@ public class SkillTools {
* @return true if the player has permissions, false otherwise
*/
public boolean superAbilityPermissionCheck(SuperAbilityType superAbilityType, Player player) {
switch (superAbilityType) {
case BERSERK:
return Permissions.berserk(player);
case BLAST_MINING:
return Permissions.remoteDetonation(player);
case GIGA_DRILL_BREAKER:
return Permissions.gigaDrillBreaker(player);
case GREEN_TERRA:
return Permissions.greenTerra(player);
case SERRATED_STRIKES:
return Permissions.serratedStrikes(player);
case SKULL_SPLITTER:
return Permissions.skullSplitter(player);
case SUPER_BREAKER:
return Permissions.superBreaker(player);
case TREE_FELLER:
return Permissions.treeFeller(player);
default:
return false;
}
return superAbilityType.getPermissions(player);
}
public @NotNull List<PrimarySkillType> getChildSkills() {
@@ -450,4 +427,17 @@ public class SkillTools {
public @NotNull ImmutableList<PrimarySkillType> getMiscSkills() {
return MISC_SKILLS;
}
public @NotNull ImmutableList<PrimarySkillType> getChildSkillParents(PrimarySkillType childSkill)
throws IllegalArgumentException {
switch (childSkill) {
case SALVAGE -> {
return SALVAGE_PARENTS;
}
case SMELTING -> {
return SMELTING_PARENTS;
}
default -> throw new IllegalArgumentException("Skill " + childSkill + " is not a child skill");
}
}
}

View File

@@ -13,6 +13,7 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.metadata.ItemMetadataService;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Misc;
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;
@@ -33,6 +34,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import static java.util.Objects.requireNonNull;
public final class SkillUtils {
/**
* This is a static utility class, therefore we don't want any instances of
@@ -264,8 +267,8 @@ public final class SkillUtils {
return false;
}
/**
* Modify the durability of an ItemStack, using Armor specific formula for unbreaking enchant damage reduction
*
@@ -352,4 +355,14 @@ public final class SkillUtils {
return quantity;
}
/**
* 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);
}
}