Merge branch 'master' of github.com:mcMMO-Dev/mcMMO into tridentsxbows

This commit is contained in:
nossr50
2021-02-05 15:51:51 -08:00
55 changed files with 3383 additions and 2740 deletions

View File

@@ -84,7 +84,7 @@ public class CommandManager {
private void validatePermission(@NotNull String permissionNode, @NotNull Permissible permissible) {
if(!permissible.hasPermission(permissionNode)) {
throw new ConditionFailedException("You do not have the appropriate permission to use this command.");
throw new ConditionFailedException(LocaleLoader.getString("mcMMO.NoPermission"));
}
}
@@ -97,7 +97,7 @@ public class CommandManager {
public void validateLoadedData(@NotNull Player player) {
if(mcMMO.getUserManager().queryPlayer(player) == null) {
throw new ConditionFailedException("Your mcMMO player data has not yet loaded!");
throw new ConditionFailedException(LocaleLoader.getString("Profile.PendingLoad"));
}
}

View File

@@ -3,6 +3,7 @@ package com.gmail.nossr50.commands.chat;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Default;
import com.gmail.nossr50.commands.CommandManager;
@@ -12,6 +13,7 @@ import com.gmail.nossr50.util.player.UserManager;
import com.neetgames.mcmmo.player.OnlineMMOPlayer;
import org.jetbrains.annotations.NotNull;
@CommandPermission("mcmmo.chat.adminchat")
@CommandAlias("ac|a|adminchat|achat") //Kept for historical reasons
public class AdminChatCommand extends BaseCommand {
private final @NotNull mcMMO pluginRef;

View File

@@ -3,6 +3,7 @@ package com.gmail.nossr50.commands.chat;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.BukkitCommandIssuer;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Default;
import com.gmail.nossr50.commands.CommandManager;
@@ -16,6 +17,7 @@ import com.neetgames.mcmmo.player.OnlineMMOPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@CommandPermission("mcmmo.chat.partychat")
@CommandAlias("pc|p|partychat|pchat") //Kept for historical reasons
public class PartyChatCommand extends BaseCommand {
private final @NotNull mcMMO pluginRef;

View File

@@ -1,10 +1,13 @@
package com.gmail.nossr50.commands.experience;
import com.gmail.nossr50.datatypes.experience.XPGainReason;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Permissions;
import com.neetgames.mcmmo.skill.RootSkill;
import com.gmail.nossr50.util.player.UserManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -29,7 +32,13 @@ public class AddlevelsCommand extends ExperienceCommand {
return;
}
EventUtils.tryLevelChangeEvent(player, rootSkill, value, xpRemoved, true, XPGainReason.COMMAND);
McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
if(mmoPlayer == null) {
EventUtils.tryLevelChangeEvent(player, rootSkill, value, xpRemoved, true, XPGainReason.COMMAND);
} else {
EventUtils.tryLevelChangeEvent(mmoPlayer, skill, value, xpRemoved, true, XPGainReason.COMMAND);
}
}
@Override

View File

@@ -1,10 +1,13 @@
package com.gmail.nossr50.commands.experience;
import com.gmail.nossr50.datatypes.experience.XPGainReason;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Permissions;
import com.neetgames.mcmmo.skill.RootSkill;
import com.gmail.nossr50.util.player.UserManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -35,7 +38,14 @@ public class MmoeditCommand extends ExperienceCommand {
return;
}
EventUtils.tryLevelEditEvent(player, rootSkill, value, xpRemoved, value > skillLevel, XPGainReason.COMMAND, skillLevel);
McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
if(mmoPlayer != null) {
EventUtils.tryLevelEditEvent(mmoPlayer, skill, value, xpRemoved, value > skillLevel, XPGainReason.COMMAND, skillLevel);
} else {
EventUtils.tryLevelEditEvent(player, rootSkill, value, xpRemoved, value > skillLevel, XPGainReason.COMMAND, skillLevel);
}
}
@Override

View File

@@ -451,23 +451,6 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
reason.add("Skills.Woodcutting.HarvestLumber.MaxBonusLevel should be at least 1!");
}
/* KRAKEN */
if (getKrakenTriesBeforeRelease() < 1) {
reason.add("Kraken.Tries_Before_Release should be at least 1!");
}
if (getKrakenHealth() < 1) {
reason.add("Kraken.Health should be at least 1!");
}
if (getKrakenAttackInterval() < 1) {
reason.add("Kraken.Attack_Interval_Seconds should be at least 1!");
}
if (getKrakenAttackDamage() < 1) {
reason.add("Kraken.Attack_Damage should be at least 1!");
}
return noErrorsInConfig(reason);
}
@@ -835,19 +818,5 @@ public class AdvancedConfig extends AutoUpdateConfigLoader {
public boolean getDisarmProtected() { return config.getBoolean("Skills.Unarmed.Disarm.AntiTheft", false); }
/* WOODCUTTING */
/*public int getLeafBlowUnlockLevel() { return config.getInt("Skills.Woodcutting.LeafBlower.UnlockLevel", 100); }*/
/* KRAKEN STUFF */
public boolean getKrakenEnabled() { return config.getBoolean("Kraken.Enabled", true); }
public int getKrakenTriesBeforeRelease() { return config.getInt("Kraken.Tries_Before_Release", 50); }
public double getKrakenHealth() { return config.getDouble("Kraken.Health", 50.0D); }
public String getKrakenName() { return config.getString("Kraken.Name", "The Kraken"); }
public int getKrakenAttackInterval() { return config.getInt("Kraken.Attack_Interval_Seconds", 1); }
public double getKrakenAttackDamage() { return config.getDouble("Kraken.Attack_Damage", 1.0D); }
public boolean getKrakenGlobalEffectsEnabled() { return config.getBoolean("Kraken.Global_Effects", false); }
public boolean getKrakenEscapeAllowed() { return config.getBoolean("Kraken.Allow_Escaping", false); }
public String getServerUnleashMessage() { return config.getString("Kraken.Unleashed_Message.Server", ""); }
public String getPlayerUnleashMessage() { return config.getString("Kraken.Unleashed_Message.Player", ""); }
public String getPlayerDefeatMessage() { return config.getString("Kraken.Defeated_Message.Killed", ""); }
public String getPlayerEscapeMessage() { return config.getString("Kraken.Defeated_Message.Escape", ""); }
public boolean isKnockOnWoodXPOrbEnabled() { return config.getBoolean("Skills.Woodcutting.TreeFeller.Knock_On_Wood.Add_XP_Orbs_To_Drops", true); }
}

View File

@@ -596,4 +596,20 @@ public class Config extends AutoUpdateConfigLoader {
public boolean playerJoinEventInfo() { return config.getBoolean("General.EventInfoOnPlayerJoin", true);}
public boolean adminNotifications() { return config.getBoolean("General.AdminNotifications", true);}
public boolean shouldLevelUpBroadcasts() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Enabled", true); }
public boolean shouldLevelUpBroadcastToConsole() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Targets.Send_To_Console", true); }
public boolean isLevelUpBroadcastsPartyMembersOnly() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Targets.Only_Party_Members", false); }
public boolean isLevelUpBroadcastsSameWorldOnly() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Targets.Only_Same_World", false); }
public boolean shouldLevelUpBroadcastsRestrictDistance() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Targets.Distance_Restrictions.Restrict_Distance", false); }
public int getLevelUpBroadcastRadius() { return config.getInt("General.Level_Up_Chat_Broadcasts.Broadcast_Targets.Distance_Restrictions.Restricted_Radius", 100); }
public int getLevelUpBroadcastInterval() { return config.getInt("General.Level_Up_Chat_Broadcasts.Milestone_Interval", 100); }
public boolean shouldPowerLevelUpBroadcasts() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Powerlevels.Enabled", true); }
public boolean shouldPowerLevelUpBroadcastToConsole() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Powerlevels.Broadcast_Targets.Send_To_Console", true); }
public boolean isPowerLevelUpBroadcastsPartyMembersOnly() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Powerlevels.Broadcast_Targets.Only_Party_Members", false); }
public boolean isPowerLevelUpBroadcastsSameWorldOnly() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Powerlevels.Broadcast_Targets.Only_Same_World", false); }
public boolean shouldPowerLevelUpBroadcastsRestrictDistance() { return config.getBoolean("General.Level_Up_Chat_Broadcasts.Broadcast_Powerlevels.Broadcast_Targets.Distance_Restrictions.Restrict_Distance", false); }
public int getPowerLevelUpBroadcastRadius() { return config.getInt("General.Level_Up_Chat_Broadcasts.Broadcast_Powerlevels.Broadcast_Targets.Distance_Restrictions.Restricted_Radius", 100); }
public int getPowerLevelUpBroadcastInterval() { return config.getInt("General.Level_Up_Chat_Broadcasts.Broadcast_Powerlevels.Milestone_Interval", 100); }
}

View File

@@ -0,0 +1,100 @@
package com.gmail.nossr50.datatypes;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.party.Party;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.player.UserManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.function.Predicate;
//TODO: Allow for offline players to broadcast
public class LevelUpBroadcastPredicate<T extends CommandSender> implements Predicate<T> {
private final @NotNull T broadcaster;
public LevelUpBroadcastPredicate(@NotNull T broadcaster) {
this.broadcaster = broadcaster;
}
@Override
public boolean test(@NotNull T t) {
Player broadcastingPlayer = (Player) broadcaster; //Always a player no need to check cast
//Broadcaster should be online
if(!broadcastingPlayer.isOnline()) {
return false;
}
McMMOPlayer mmoBroadcastingPlayer = UserManager.getPlayer(broadcastingPlayer);
if(mmoBroadcastingPlayer == null) {
//This should never be null, but just in case...
mcMMO.p.getLogger().severe("McMMOPlayer was null for broadcaster in LevelUpBroadcastPredicate when it should never be null!");
return false;
}
if(t instanceof Player) {
Player listeningPlayer = (Player) t;
//Party Member Check
if(Config.getInstance().isLevelUpBroadcastsPartyMembersOnly()) {
McMMOPlayer mmoListeningPlayer = UserManager.getPlayer(listeningPlayer);
if(mmoListeningPlayer == null) {
return false; //No profile so therefor no party
}
Party playerWhoLeveledParty = mmoBroadcastingPlayer.getParty();
Party broadcastRecipientParty = mmoListeningPlayer.getParty();
if(playerWhoLeveledParty == null || broadcastRecipientParty == null) {
return false; //No party on either player when being in the same party is required
}
if(!playerWhoLeveledParty.equals(broadcastRecipientParty)) {
return false; //Not in the same party when it is required
}
}
//Same world check
if(isLevelUpBroadcastsSameWorldOnly()) {
if(!mmoBroadcastingPlayer.getPlayer().getWorld().equals(listeningPlayer.getWorld())) {
return false; //Not in the same world when its required
}
//Distance checks
if(Config.getInstance().shouldLevelUpBroadcastsRestrictDistance()) {
if(!Misc.isNear(mmoBroadcastingPlayer.getPlayer().getLocation(), listeningPlayer.getLocation(), Config.getInstance().getLevelUpBroadcastRadius())) {
return false;
}
}
}
//Visibility checks
if(!listeningPlayer.canSee(mmoBroadcastingPlayer.getPlayer())) {
return false; //Player who leveled should be invisible to this player so don't send the message
}
return true;
} else {
//Send out to console
return Config.getInstance().shouldLevelUpBroadcastToConsole();
}
}
private static boolean isLevelUpBroadcastsSameWorldOnly() {
return Config.getInstance().isLevelUpBroadcastsSameWorldOnly();
}
@Override
public String toString() {
return "LevelUpBroadcastPredicate{" +
"broadcaster=" + broadcaster +
'}';
}
}

View File

@@ -0,0 +1,100 @@
package com.gmail.nossr50.datatypes;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.party.Party;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.player.UserManager;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.function.Predicate;
//TODO: Allow for offline players to broadcast
public class PowerLevelUpBroadcastPredicate<T extends CommandSender> implements Predicate<T> {
private final @NotNull T broadcaster;
public PowerLevelUpBroadcastPredicate(@NotNull T broadcaster) {
this.broadcaster = broadcaster;
}
@Override
public boolean test(@NotNull T t) {
Player broadcastingPlayer = (Player) broadcaster; //Always a player no need to check cast
//Broadcaster should be online
if(!broadcastingPlayer.isOnline()) {
return false;
}
McMMOPlayer mmoBroadcastingPlayer = UserManager.getPlayer(broadcastingPlayer);
if(mmoBroadcastingPlayer == null) {
//This should never be null, but just in case...
mcMMO.p.getLogger().severe("McMMOPlayer was null for broadcaster in LevelUpBroadcastPredicate when it should never be null!");
return false;
}
if(t instanceof Player) {
Player listeningPlayer = (Player) t;
//Party Member Check
if(Config.getInstance().isPowerLevelUpBroadcastsPartyMembersOnly()) {
McMMOPlayer mmoListeningPlayer = UserManager.getPlayer(listeningPlayer);
if(mmoListeningPlayer == null) {
return false; //No profile so therefor no party
}
Party playerWhoLeveledParty = mmoBroadcastingPlayer.getParty();
Party broadcastRecipientParty = mmoListeningPlayer.getParty();
if(playerWhoLeveledParty == null || broadcastRecipientParty == null) {
return false; //No party on either player when being in the same party is required
}
if(!playerWhoLeveledParty.equals(broadcastRecipientParty)) {
return false; //Not in the same party when it is required
}
}
//Same world check
if(isPowerLevelUpBroadcastsSameWorldOnly()) {
if(!mmoBroadcastingPlayer.getPlayer().getWorld().equals(listeningPlayer.getWorld())) {
return false; //Not in the same world when its required
}
//Distance checks
if(Config.getInstance().shouldPowerLevelUpBroadcastsRestrictDistance()) {
if(!Misc.isNear(mmoBroadcastingPlayer.getPlayer().getLocation(), listeningPlayer.getLocation(), Config.getInstance().getPowerLevelUpBroadcastRadius())) {
return false;
}
}
}
//Visibility checks
if(!listeningPlayer.canSee(mmoBroadcastingPlayer.getPlayer())) {
return false; //Player who leveled should be invisible to this player so don't send the message
}
return true;
} else {
//Send out to console
return Config.getInstance().shouldPowerLevelUpBroadcastToConsole();
}
}
private static boolean isPowerLevelUpBroadcastsSameWorldOnly() {
return Config.getInstance().isPowerLevelUpBroadcastsSameWorldOnly();
}
@Override
public String toString() {
return "PowerLevelUpBroadcastPredicate{" +
"broadcaster=" + broadcaster +
'}';
}
}

View File

@@ -1,5 +1,6 @@
package com.gmail.nossr50.events.skills;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@@ -16,7 +17,7 @@ public class SkillActivationPerkEvent extends Event {
private final int maxTicks;
public SkillActivationPerkEvent(Player player, int ticks, int maxTicks) {
super(!Bukkit.isPrimaryThread());
this.player = player;
this.ticks = ticks;
this.maxTicks = maxTicks;

View File

@@ -0,0 +1,23 @@
package com.gmail.nossr50.events.skills.secondaryabilities;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class SubSkillBlockEvent extends SubSkillEvent {
private final @NotNull Block block;
public SubSkillBlockEvent(@NotNull Player player, @NotNull SubSkillType subSkillType, @NotNull Block block) {
super(player, subSkillType);
this.block = block;
}
/**
* Get the block associated with this event
* @return the block associated with this event
*/
public @NotNull Block getBlock() {
return block;
}
}

View File

@@ -142,7 +142,7 @@ public class EntityListener implements Listener {
projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(pluginRef, Math.min(event.getForce() * AdvancedConfig.getInstance().getForceMultiplier(), 1.0)));
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(pluginRef, projectile.getLocation()));
//Cleanup metadata in 1 minute in case normal collection falls through
CombatUtils.cleanupArrowMetadata((Projectile) projectile);
CombatUtils.delayArrowMetaCleanup((Projectile) projectile);
}
}

View File

@@ -67,10 +67,12 @@ public class PlayerListener implements Listener {
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getPlayer().getWorld())) {
//Remove scoreboards
ScoreboardManager.teardownPlayer(event.getPlayer());
if(Config.getInstance().getScoreboardsEnabled()) {
ScoreboardManager.teardownPlayer(event.getPlayer());
}
return;
} else if(WorldBlacklist.isWorldBlacklisted(event.getFrom().getWorld())) {
//This only fires if they are traveling to a non-blacklisted world from a blacklisted world
} else if(WorldBlacklist.isWorldBlacklisted(event.getFrom().getWorld()) && Config.getInstance().getScoreboardsEnabled()) {
//This only fires if they are travelling to a non-blacklisted world from a blacklisted world
//Setup scoreboards
ScoreboardManager.setupPlayer(event.getPlayer());
@@ -782,7 +784,7 @@ public class PlayerListener implements Listener {
player.setVelocity(player.getEyeLocation().getDirection().multiply(10));
}
((McMMOPlayer) (mmoPlayer)).getFishingManager().setFishingRodCastTimestamp();
//mcMMOPlayer.getFishingManager().setFishingRodCastTimestamp();
}
}

View File

@@ -259,13 +259,13 @@ public class mcMMO extends JavaPlugin {
Metrics metrics;
if(Config.getInstance().getIsMetricsEnabled()) {
metrics = new Metrics(this);
metrics = new Metrics(this, 3894);
metrics.addCustomChart(new Metrics.SimplePie("version", () -> getDescription().getVersion()));
if(Config.getInstance().getIsRetroMode())
metrics.addCustomChart(new Metrics.SimplePie("scaling", () -> "Standard"));
metrics.addCustomChart(new Metrics.SimplePie("leveling_system", () -> "Retro"));
else
metrics.addCustomChart(new Metrics.SimplePie("scaling", () -> "Retro"));
metrics.addCustomChart(new Metrics.SimplePie("leveling_system", () -> "Standard"));
}
}
catch (Throwable t) {

View File

@@ -25,8 +25,6 @@ import com.gmail.nossr50.util.random.RandomChanceUtil;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -72,36 +70,36 @@ public class FishingManager extends SkillManager {
return mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null && getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER) && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MASTER_ANGLER);
}
public void setFishingRodCastTimestamp()
{
long currentTime = System.currentTimeMillis();
//Only track spam casting if the fishing hook is fresh
if(currentTime > fishHookSpawnTimestamp + 1000)
return;
if(currentTime < fishingRodCastTimestamp + FISHING_ROD_CAST_CD_MILLISECONDS)
{
ItemStack fishingRod = getPlayer().getInventory().getItemInMainHand();
//Ensure correct hand item is damaged
if(fishingRod.getType() != Material.FISHING_ROD) {
fishingRod = getPlayer().getInventory().getItemInOffHand();
}
getPlayer().setFoodLevel(Math.max(getPlayer().getFoodLevel() - 1, 0));
fishingRod.setDurability((short) (fishingRod.getDurability() + 5));
getPlayer().updateInventory();
if(lastWarnedExhaust + (1000) < currentTime)
{
getPlayer().sendMessage(LocaleLoader.getString("Fishing.Exhausting"));
lastWarnedExhaust = currentTime;
SoundManager.sendSound(getPlayer(), getPlayer().getLocation(), SoundType.TIRED);
}
}
fishingRodCastTimestamp = System.currentTimeMillis();
}
// public void setFishingRodCastTimestamp()
// {
// long currentTime = System.currentTimeMillis();
// //Only track spam casting if the fishing hook is fresh
// if(currentTime > fishHookSpawnTimestamp + 1000)
// return;
//
// if(currentTime < fishingRodCastTimestamp + FISHING_ROD_CAST_CD_MILLISECONDS)
// {
// ItemStack fishingRod = getPlayer().getInventory().getItemInMainHand();
//
// //Ensure correct hand item is damaged
// if(fishingRod.getType() != Material.FISHING_ROD) {
// fishingRod = getPlayer().getInventory().getItemInOffHand();
// }
//
// getPlayer().setFoodLevel(Math.max(getPlayer().getFoodLevel() - 1, 0));
// fishingRod.setDurability((short) (fishingRod.getDurability() + 5));
// getPlayer().updateInventory();
//
// if(lastWarnedExhaust + (1000) < currentTime)
// {
// getPlayer().sendMessage(LocaleLoader.getString("Fishing.Exhausting"));
// lastWarnedExhaust = currentTime;
// SoundManager.sendSound(getPlayer(), getPlayer().getLocation(), SoundType.TIRED);
// }
// }
//
// fishingRodCastTimestamp = System.currentTimeMillis();
// }
public void setFishHookReference(FishHook fishHook)
{

View File

@@ -752,11 +752,16 @@ public class HerbalismManager extends SkillManager {
return false;
}
playerInventory.removeItem(seedStack);
player.updateInventory(); // Needed until replacement available
//Play sound
SoundManager.sendSound(player, player.getLocation(), SoundType.ITEM_CONSUMED);
return true;
if(EventUtils.callSubSkillBlockEvent(player, SubSkillType.HERBALISM_GREEN_THUMB, blockState.getBlock()).isCancelled()) {
return false;
} else {
playerInventory.removeItem(seedStack);
player.updateInventory(); // Needed until replacement available
//Play sound
SoundManager.sendSound(player, player.getLocation(), SoundType.ITEM_CONSUMED);
return true;
}
// new HerbalismBlockUpdaterTask(blockState).runTaskLater(mcMMO.p, 0);
}

View File

@@ -1,6 +1,7 @@
package com.gmail.nossr50.skills.woodcutting;
import com.gmail.nossr50.api.ItemSpawnReason;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.interactions.NotificationType;
@@ -305,9 +306,11 @@ public class WoodcuttingManager extends SkillManager {
Misc.spawnItemsFromCollection(Misc.getBlockCenter(blockState), block.getDrops(), ItemSpawnReason.TREE_FELLER_DISPLACED_BLOCK);
if(RankUtils.hasReachedRank(2, mmoPlayer, SubSkillType.WOODCUTTING_KNOCK_ON_WOOD)) {
if(RandomChanceUtil.rollDice(75, 100)) {
int randOrbCount = Math.max(1, Misc.getRandom().nextInt(20));
Misc.spawnExperienceOrb(blockState.getLocation(), randOrbCount);
if(AdvancedConfig.getInstance().isKnockOnWoodXPOrbEnabled()) {
if(RandomChanceUtil.rollDice(10, 100)) {
int randOrbCount = Math.max(1, Misc.getRandom().nextInt(100));
Misc.spawnExperienceOrb(blockState.getLocation(), randOrbCount);
}
}
}

View File

@@ -26,10 +26,13 @@ import com.gmail.nossr50.events.skills.fishing.McMMOPlayerFishingTreasureEvent;
import com.gmail.nossr50.events.skills.fishing.McMMOPlayerMagicHunterEvent;
import com.gmail.nossr50.events.skills.repair.McMMOPlayerRepairCheckEvent;
import com.gmail.nossr50.events.skills.salvage.McMMOPlayerSalvageCheckEvent;
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillBlockEvent;
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillEvent;
import com.gmail.nossr50.events.skills.unarmed.McMMOPlayerDisarmEvent;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.CombatUtils;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
@@ -186,13 +189,28 @@ public final class EventUtils {
* @return the event after it has been fired
*/
@Deprecated
public static SubSkillEvent callSubSkillEvent(Player player, SubSkillType subSkillType) {
public static @NotNull SubSkillEvent callSubSkillEvent(Player player, SubSkillType subSkillType) {
SubSkillEvent event = new SubSkillEvent(player, subSkillType);
mcMMO.p.getServer().getPluginManager().callEvent(event);
return event;
}
/**
* Calls a new SubSkillBlockEvent for this SubSkill and its related block and then returns it
* @param player target player
* @param subSkillType target subskill
* @param block associated block
* @return the event after it has been fired
*/
@Deprecated
public static @NotNull SubSkillBlockEvent callSubSkillBlockEvent(@NotNull Player player, @NotNull SubSkillType subSkillType, @NotNull Block block) {
SubSkillBlockEvent event = new SubSkillBlockEvent(player, subSkillType, block);
mcMMO.p.getServer().getPluginManager().callEvent(event);
return event;
}
/**
* Calls a new SubSkillEvent for this SubSkill and then returns it
* @param player target player
@@ -229,6 +247,26 @@ public final class EventUtils {
return isCancelled;
}
public static boolean tryLevelChangeEvent(@NotNull McMMOPlayer mmoPlayer, PrimarySkillType skill, int levelsChanged, float xpRemoved, boolean isLevelUp, XPGainReason xpGainReason) {
McMMOPlayerLevelChangeEvent event = isLevelUp ? new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), skill, levelsChanged, xpGainReason) : new McMMOPlayerLevelDownEvent(mmoPlayer.getPlayer(), skill, levelsChanged, xpGainReason);
mcMMO.p.getServer().getPluginManager().callEvent(event);
boolean isCancelled = event.isCancelled();
if (isCancelled) {
mmoPlayer.modifySkill(skill, mmoPlayer.getSkillLevel(skill) - (isLevelUp ? levelsChanged : -levelsChanged));
mmoPlayer.addXp(skill, xpRemoved);
} else {
if (isLevelUp) {
NotificationManager.processLevelUpBroadcasting(mmoPlayer, skill, mmoPlayer.getSkillLevel(skill));
NotificationManager.processPowerLevelUpBroadcasting(mmoPlayer, mmoPlayer.getPowerLevel());
}
}
return isCancelled;
}
public static boolean tryLevelEditEvent(Player player, PrimarySkillType skill, int levelsChanged, float xpRemoved, boolean isLevelUp, XPGainReason xpGainReason, int oldLevel) {
McMMOPlayerLevelChangeEvent event = isLevelUp ? new McMMOPlayerLevelUpEvent(player, skill, levelsChanged - oldLevel, xpGainReason) : new McMMOPlayerLevelDownEvent(player, skill, levelsChanged, xpGainReason);
mcMMO.p.getServer().getPluginManager().callEvent(event);
@@ -245,6 +283,25 @@ public final class EventUtils {
return isCancelled;
}
public static boolean tryLevelEditEvent(@NotNull McMMOPlayer mmoPlayer, PrimarySkillType skill, int levelsChanged, float xpRemoved, boolean isLevelUp, XPGainReason xpGainReason, int oldLevel) {
McMMOPlayerLevelChangeEvent event = isLevelUp ? new McMMOPlayerLevelUpEvent(mmoPlayer.getPlayer(), skill, levelsChanged - oldLevel, xpGainReason) : new McMMOPlayerLevelDownEvent(mmoPlayer.getPlayer(), skill, levelsChanged, xpGainReason);
mcMMO.p.getServer().getPluginManager().callEvent(event);
boolean isCancelled = event.isCancelled();
if (isCancelled) {
mmoPlayer.modifySkill(skill, mmoPlayer.getSkillLevel(skill) - (isLevelUp ? levelsChanged : -levelsChanged));
mmoPlayer.addXp(skill, xpRemoved);
} else {
if (isLevelUp) {
NotificationManager.processLevelUpBroadcasting(mmoPlayer, skill, mmoPlayer.getSkillLevel(skill));
NotificationManager.processPowerLevelUpBroadcasting(mmoPlayer, mmoPlayer.getPowerLevel());
}
}
return isCancelled;
}
/**
* Simulate a block break event.
*

View File

@@ -1,6 +1,5 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.meta.OldName;
import com.gmail.nossr50.mcMMO;
@@ -62,10 +61,6 @@ public final class MobHealthbarUtils {
if (oldName == null) {
oldName = "";
}
else if (oldName.equalsIgnoreCase(AdvancedConfig.getInstance().getKrakenName())) {
return;
}
boolean oldNameVisible = target.isCustomNameVisible();
String newName = createHealthDisplay(Config.getInstance().getMobHealthbarDefault(), target, damage);

View File

@@ -27,6 +27,7 @@ public final class Permissions {
* GENERAL
*/
public static boolean motd(Permissible permissible) { return permissible.hasPermission("mcmmo.motd"); }
public static boolean levelUpBroadcast(Permissible permissible) { return permissible.hasPermission("mcmmo.broadcast.levelup"); }
public static boolean mobHealthDisplay(Permissible permissible) { return permissible.hasPermission("mcmmo.mobhealthdisplay"); }
public static boolean updateNotifications(Permissible permissible) {return permissible.hasPermission("mcmmo.tools.updatecheck"); }
public static boolean chimaeraWing(Permissible permissible) { return permissible.hasPermission("mcmmo.item.chimaerawing"); }

View File

@@ -14,6 +14,7 @@ import com.gmail.nossr50.util.nms.NMSVersion;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import com.gmail.nossr50.util.text.StringUtils;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
@@ -102,7 +103,6 @@ public class CompatibilityManager {
private void initPersistentDataLayer() {
if(minecraftGameVersion.getMinorVersion().asInt() >= 14 || minecraftGameVersion.getMajorVersion().asInt() >= 2) {
persistentDataLayer = new SpigotPersistentDataLayer_1_14();
} else {
@@ -138,11 +138,11 @@ public class CompatibilityManager {
return isFullyCompatibleServerSoftware;
}
public NMSVersion getNmsVersion() {
public @NotNull NMSVersion getNmsVersion() {
return nmsVersion;
}
private NMSVersion determineNMSVersion() {
private @NotNull NMSVersion determineNMSVersion() {
if (minecraftGameVersion.getMajorVersion().asInt() == 1) {
switch (minecraftGameVersion.getMinorVersion().asInt()) {
case 12:
@@ -160,8 +160,10 @@ public class CompatibilityManager {
return NMSVersion.NMS_1_16_2;
} else if(minecraftGameVersion.getPatchVersion().asInt() == 3) {
return NMSVersion.NMS_1_16_3;
} else if(minecraftGameVersion.getPatchVersion().asInt() >= 4) {
} else if(minecraftGameVersion.getPatchVersion().asInt() == 4) {
return NMSVersion.NMS_1_16_4;
} else if(minecraftGameVersion.getPatchVersion().asInt() >= 5) {
return NMSVersion.NMS_1_16_5;
}
}
}

View File

@@ -1,42 +1,42 @@
package com.gmail.nossr50.util.compat.layers.attackcooldown;
import com.gmail.nossr50.util.nms.NMSVersion;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
public class DummyPlayerAttackCooldownToolLayer extends PlayerAttackCooldownToolLayer {
public DummyPlayerAttackCooldownToolLayer() {
super(NMSVersion.UNSUPPORTED);
}
@Override
public boolean initializeLayer() {
return noErrorsOnInitialize;
}
@Override
public float getAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
return 1.0F; //Always full strength
}
@Override
public float getCooldownValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
return 0F;
}
@Override
public void resetAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
//Do nothing
}
@Override
public int getCooldownFieldValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
return 0;
}
@Override
public void setCooldownFieldValue(@NotNull Player player, int fieldValue) throws InvocationTargetException, IllegalAccessException {
}
}
//package com.gmail.nossr50.util.compat.layers.attackcooldown;
//
//import com.gmail.nossr50.util.nms.NMSVersion;
//import org.bukkit.entity.Player;
//import org.jetbrains.annotations.NotNull;
//
//import java.lang.reflect.InvocationTargetException;
//
//public class DummyPlayerAttackCooldownToolLayer extends PlayerAttackCooldownToolLayer {
// public DummyPlayerAttackCooldownToolLayer() {
// super(NMSVersion.UNSUPPORTED);
// }
//
// @Override
// public boolean initializeLayer() {
// return noErrorsOnInitialize;
// }
//
// @Override
// public float getAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// return 1.0F; //Always full strength
// }
//
// @Override
// public float getCooldownValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// return 0F;
// }
//
// @Override
// public void resetAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// //Do nothing
// }
//
// @Override
// public int getCooldownFieldValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// return 0;
// }
//
// @Override
// public void setCooldownFieldValue(@NotNull Player player, int fieldValue) throws InvocationTargetException, IllegalAccessException {
// }
//}

View File

@@ -1,237 +1,238 @@
package com.gmail.nossr50.util.compat.layers.attackcooldown;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.layers.AbstractNMSCompatibilityLayer;
import com.gmail.nossr50.util.nms.NMSConstants;
import com.gmail.nossr50.util.nms.NMSVersion;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
*
* These classes are a band-aid solution for adding NMS support into 2.1.XXX
* In 2.2 we are switching to modules and that will clean things up significantly
*
*/
public class PlayerAttackCooldownToolLayer extends AbstractNMSCompatibilityLayer implements PlayerAttackCooldownMethods {
private final String cbNMSVersionPath;
protected Class<?> craftPlayerClass;
protected Class<?> entityHumanClass;
protected Class<?> entityLivingClass;
protected Method playerAttackCooldownMethod;
protected Method playerAttackStrengthMethod;
protected Method resetPlayerAttackCooldownMethod;
protected Method setPlayerAttackStrengthMethod;
protected Method getHandleMethod;
protected Field attackCooldownField;
protected String attackStrengthFieldName;
public PlayerAttackCooldownToolLayer(@NotNull NMSVersion nmsVersion) {
super(nmsVersion);
mcMMO.p.getLogger().info("Loading Compatibility Layer... (Player Attack Cooldown Exploit Prevention)");
if(!isCompatibleWithMinecraftVersion(nmsVersion)) {
mcMMO.p.getLogger().severe("this version of mcMMO does not support NMS for this version of Minecraft, try updating mcMMO or updating Minecraft. Not all versions of Minecraft will have NMS support built into mcMMO.");
cbNMSVersionPath = "";
} else {
if(NMSConstants.getCraftBukkitVersionPath(nmsVersion) != null) {
cbNMSVersionPath = NMSConstants.getCraftBukkitVersionPath(nmsVersion);
noErrorsOnInitialize = initializeLayer();
if(noErrorsOnInitialize) {
mcMMO.p.getLogger().info("Successfully Loaded Compatibility Layer! (Player Attack Cooldown Exploit Prevention)");
}
} else {
mcMMO.p.getLogger().info("Failed to load - CL (Player Attack Cooldown Exploit Prevention) Could not find CB NMS path for CL");
flagErrorsDuringStartup();
mcMMO.p.getLogger().warning("Could not wire NMS package path for CraftBukkit!");
cbNMSVersionPath = "";
}
}
}
public static boolean isCompatibleWithMinecraftVersion(@NotNull NMSVersion nmsVersion) {
switch(nmsVersion) {
case NMS_1_13_2:
case NMS_1_14_4:
case NMS_1_15_2:
case NMS_1_16_4:
return true;
default:
return false;
}
}
/**
* Cache all reflection methods/types/classes needed for the NMS of this CompatibilityLayer
* @param cooldownMethodName the cooldown method name
* @param attackStrengthMethodName the attack strength method name
* @param resetAttackCooldownMethodName the reset attack cooldown method name
* @param getHandleMethodName the get handle method name
* @return true if NMS was successfully wired
*/
public boolean wireNMS(@NotNull String cooldownMethodName, @NotNull String attackStrengthMethodName, @NotNull String resetAttackCooldownMethodName, @NotNull String getHandleMethodName, @NotNull String attackStrengthFieldName) {
entityHumanClass = initEntityHumanClass();
if (entityHumanClass != null) {
entityLivingClass = entityHumanClass.getSuperclass();
}
craftPlayerClass = initCraftPlayerClass();
this.attackStrengthFieldName = attackStrengthFieldName;
try {
this.attackCooldownField = entityLivingClass.getDeclaredField(attackStrengthFieldName);
this.attackCooldownField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
try {
this.playerAttackCooldownMethod = entityHumanClass.getMethod(cooldownMethodName);
this.playerAttackStrengthMethod = entityHumanClass.getMethod(attackStrengthMethodName, float.class);
this.resetPlayerAttackCooldownMethod = entityHumanClass.getMethod(resetAttackCooldownMethodName);
if (craftPlayerClass != null) {
this.getHandleMethod = craftPlayerClass.getMethod(getHandleMethodName);
} else {
return false;
}
return true;
} catch (NoSuchMethodException e) {
flagErrorsDuringStartup();
e.printStackTrace();
return false;
}
}
/**
* Get the cached player attack cooldown method
* @return the cached player attack cooldown method
*/
private @Nullable Method getPlayerAttackCooldownMethod() {
return playerAttackCooldownMethod;
}
/**
* Get the cached player attack strength method
* @return the cached player attack strength method
*/
private @Nullable Method getPlayerAttackStrengthMethod() {
return playerAttackStrengthMethod;
}
/**
* Get the cached player attack cooldown reset method
* @return the cached player attack cooldown reset method
*/
private @Nullable Method getResetPlayerAttackCooldownMethod() {
return resetPlayerAttackCooldownMethod;
}
/**
* Grab the CraftPlayer class type from NMS
* @return the CraftPlayer class type from NMS
*/
private @Nullable Class<?> initCraftPlayerClass() {
try {
return Class.forName(NMSConstants.getCraftPlayerClassPath(cbNMSVersionPath));
} catch (ClassNotFoundException e) {
flagErrorsDuringStartup();
e.printStackTrace();
return null;
}
}
/**
* Grab the EntityHuman class type from NMS
* @return the EntityHuman class type from NMS
*/
private @Nullable Class<?> initEntityHumanClass() {
try {
return Class.forName(NMSConstants.getEntityHumanClassPath(cbNMSVersionPath));
} catch (ClassNotFoundException e) {
flagErrorsDuringStartup();
e.printStackTrace();
return null;
}
}
private void flagErrorsDuringStartup() {
noErrorsOnInitialize = false;
}
/**
* Grabs the attack strength for a player
* Should be noted that as of today there is no way to capture a players current attack strength in spigot when they attack an entity outside of network packet listening
* @param player target player
* @return the float value of the player's attack strength
*/
@Override
public float getAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
Object craftPlayer = craftPlayerClass.cast(player);
Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
return (float) playerAttackStrengthMethod.invoke(entityHuman, 0F); //Add no adjustment ticks
}
@Override
public float getCooldownValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
Object craftPlayer = craftPlayerClass.cast(player);
Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
return (float) playerAttackCooldownMethod.invoke(entityHuman); //Add no adjustment ticks
}
@Override
public void resetAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
Object craftPlayer = craftPlayerClass.cast(player);
Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
Object entityLiving = entityLivingClass.cast(entityHuman);
resetPlayerAttackCooldownMethod.invoke(entityLiving);
}
@Override
public int getCooldownFieldValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
Object craftPlayer = craftPlayerClass.cast(player);
Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
Object entityLiving = entityLivingClass.cast(entityHuman);
return attackCooldownField.getInt(entityLiving);
}
@Override
public void setCooldownFieldValue(@NotNull Player player, int fieldValue) throws InvocationTargetException, IllegalAccessException {
Object craftPlayer = craftPlayerClass.cast(player);
Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
attackCooldownField.setInt(entityHuman, fieldValue);
}
@Override
public boolean initializeLayer() {
switch(nmsVersion) {
case NMS_1_12_2:
return wireNMS("dr", "n", "ds", "getHandle", "at");
case NMS_1_13_2:
return wireNMS("dG", "r", "dH", "getHandle", "at");
case NMS_1_14_4:
return wireNMS("dY", "s", "dZ", "getHandle", "at");
case NMS_1_15_2:
return wireNMS("ex", "s", "ey", "getHandle", "at");
case NMS_1_16_4:
return wireNMS("eR", "getAttackCooldown", "resetAttackCooldown", "getHandle", "at");
default:
throw new RuntimeException("Unexpected NMS version support in PlayerAttackCooldown compatibility layer initialization!");
}
}
}
//package com.gmail.nossr50.util.compat.layers.attackcooldown;
//
//import com.gmail.nossr50.mcMMO;
//import com.gmail.nossr50.util.compat.layers.AbstractNMSCompatibilityLayer;
//import com.gmail.nossr50.util.nms.NMSConstants;
//import com.gmail.nossr50.util.nms.NMSVersion;
//import org.bukkit.entity.Player;
//import org.jetbrains.annotations.NotNull;
//import org.jetbrains.annotations.Nullable;
//
//import java.lang.reflect.Field;
//import java.lang.reflect.InvocationTargetException;
//import java.lang.reflect.Method;
//
///**
// *
// * These classes are a band-aid solution for adding NMS support into 2.1.XXX
// * In 2.2 we are switching to modules and that will clean things up significantly
// *
// */
//public class PlayerAttackCooldownToolLayer extends AbstractNMSCompatibilityLayer implements PlayerAttackCooldownMethods {
//
// private final String cbNMSVersionPath;
//
// protected Class<?> craftPlayerClass;
// protected Class<?> entityHumanClass;
// protected Class<?> entityLivingClass;
//
// protected Method playerAttackCooldownMethod;
// protected Method playerAttackStrengthMethod;
// protected Method resetPlayerAttackCooldownMethod;
// protected Method setPlayerAttackStrengthMethod;
// protected Method getHandleMethod;
// protected Field attackCooldownField;
// protected String attackStrengthFieldName;
//
// public PlayerAttackCooldownToolLayer(@NotNull NMSVersion nmsVersion) {
// super(nmsVersion);
// mcMMO.p.getLogger().info("Loading Compatibility Layer... (Player Attack Cooldown Exploit Prevention)");
// if(!isCompatibleWithMinecraftVersion(nmsVersion)) {
// mcMMO.p.getLogger().severe("this version of mcMMO does not support NMS for this version of Minecraft, try updating mcMMO or updating Minecraft. Not all versions of Minecraft will have NMS support built into mcMMO.");
// cbNMSVersionPath = "";
// } else {
// if(NMSConstants.getCraftBukkitVersionPath(nmsVersion) != null) {
// cbNMSVersionPath = NMSConstants.getCraftBukkitVersionPath(nmsVersion);
// noErrorsOnInitialize = initializeLayer();
//
// if(noErrorsOnInitialize) {
// mcMMO.p.getLogger().info("Successfully Loaded Compatibility Layer! (Player Attack Cooldown Exploit Prevention)");
// }
// } else {
// mcMMO.p.getLogger().info("Failed to load - CL (Player Attack Cooldown Exploit Prevention) Could not find CB NMS path for CL");
// flagErrorsDuringStartup();
// mcMMO.p.getLogger().warning("Could not wire NMS package path for CraftBukkit!");
// cbNMSVersionPath = "";
// }
// }
// }
//
// public static boolean isCompatibleWithMinecraftVersion(@NotNull NMSVersion nmsVersion) {
// switch(nmsVersion) {
// case NMS_1_13_2:
// case NMS_1_14_4:
// case NMS_1_15_2:
// case NMS_1_16_4:
// case NMS_1_16_5:
// return true;
// default:
// return false;
// }
// }
//
// /**
// * Cache all reflection methods/types/classes needed for the NMS of this CompatibilityLayer
// * @param cooldownMethodName the cooldown method name
// * @param attackStrengthMethodName the attack strength method name
// * @param resetAttackCooldownMethodName the reset attack cooldown method name
// * @param getHandleMethodName the get handle method name
// * @return true if NMS was successfully wired
// */
// public boolean wireNMS(@NotNull String cooldownMethodName, @NotNull String attackStrengthMethodName, @NotNull String resetAttackCooldownMethodName, @NotNull String getHandleMethodName, @NotNull String attackStrengthFieldName) {
// entityHumanClass = initEntityHumanClass();
//
// if (entityHumanClass != null) {
// entityLivingClass = entityHumanClass.getSuperclass();
// }
//
// craftPlayerClass = initCraftPlayerClass();
// this.attackStrengthFieldName = attackStrengthFieldName;
//
// try {
// this.attackCooldownField = entityLivingClass.getDeclaredField(attackStrengthFieldName);
// this.attackCooldownField.setAccessible(true);
// } catch (NoSuchFieldException e) {
// e.printStackTrace();
// }
//
// try {
// this.playerAttackCooldownMethod = entityHumanClass.getMethod(cooldownMethodName);
// this.playerAttackStrengthMethod = entityHumanClass.getMethod(attackStrengthMethodName, float.class);
// this.resetPlayerAttackCooldownMethod = entityHumanClass.getMethod(resetAttackCooldownMethodName);
//
// if (craftPlayerClass != null) {
// this.getHandleMethod = craftPlayerClass.getMethod(getHandleMethodName);
// } else {
// return false;
// }
// return true;
// } catch (NoSuchMethodException e) {
// flagErrorsDuringStartup();
// e.printStackTrace();
// return false;
// }
// }
//
// /**
// * Get the cached player attack cooldown method
// * @return the cached player attack cooldown method
// */
// private @Nullable Method getPlayerAttackCooldownMethod() {
// return playerAttackCooldownMethod;
// }
//
// /**
// * Get the cached player attack strength method
// * @return the cached player attack strength method
// */
// private @Nullable Method getPlayerAttackStrengthMethod() {
// return playerAttackStrengthMethod;
// }
//
// /**
// * Get the cached player attack cooldown reset method
// * @return the cached player attack cooldown reset method
// */
// private @Nullable Method getResetPlayerAttackCooldownMethod() {
// return resetPlayerAttackCooldownMethod;
// }
//
// /**
// * Grab the CraftPlayer class type from NMS
// * @return the CraftPlayer class type from NMS
// */
// private @Nullable Class<?> initCraftPlayerClass() {
// try {
// return Class.forName(NMSConstants.getCraftPlayerClassPath(cbNMSVersionPath));
// } catch (ClassNotFoundException e) {
// flagErrorsDuringStartup();
// e.printStackTrace();
// return null;
// }
// }
//
// /**
// * Grab the EntityHuman class type from NMS
// * @return the EntityHuman class type from NMS
// */
// private @Nullable Class<?> initEntityHumanClass() {
// try {
// return Class.forName(NMSConstants.getEntityHumanClassPath(cbNMSVersionPath));
// } catch (ClassNotFoundException e) {
// flagErrorsDuringStartup();
// e.printStackTrace();
// return null;
// }
// }
//
// private void flagErrorsDuringStartup() {
// noErrorsOnInitialize = false;
// }
//
// /**
// * Grabs the attack strength for a player
// * Should be noted that as of today there is no way to capture a players current attack strength in spigot when they attack an entity outside of network packet listening
// * @param player target player
// * @return the float value of the player's attack strength
// */
// @Override
// public float getAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
//
// return (float) playerAttackStrengthMethod.invoke(entityHuman, 0F); //Add no adjustment ticks
// }
//
// @Override
// public float getCooldownValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
//
// return (float) playerAttackCooldownMethod.invoke(entityHuman); //Add no adjustment ticks
// }
//
// @Override
// public void resetAttackStrength(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
// Object entityLiving = entityLivingClass.cast(entityHuman);
//
// resetPlayerAttackCooldownMethod.invoke(entityLiving);
// }
//
// @Override
// public int getCooldownFieldValue(@NotNull Player player) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
// Object entityLiving = entityLivingClass.cast(entityHuman);
//
// return attackCooldownField.getInt(entityLiving);
// }
//
// @Override
// public void setCooldownFieldValue(@NotNull Player player, int fieldValue) throws InvocationTargetException, IllegalAccessException {
// Object craftPlayer = craftPlayerClass.cast(player);
// Object entityHuman = entityHumanClass.cast(getHandleMethod.invoke(craftPlayer));
//
// attackCooldownField.setInt(entityHuman, fieldValue);
// }
//
// @Override
// public boolean initializeLayer() {
// switch(nmsVersion) {
// case NMS_1_12_2:
// return wireNMS("dr", "n", "ds", "getHandle", "at");
// case NMS_1_13_2:
// return wireNMS("dG", "r", "dH", "getHandle", "at");
// case NMS_1_14_4:
// return wireNMS("dY", "s", "dZ", "getHandle", "at");
// case NMS_1_15_2:
// return wireNMS("ex", "s", "ey", "getHandle", "at");
// case NMS_1_16_4:
// return wireNMS("eR", "getAttackCooldown", "resetAttackCooldown", "getHandle", "at");
// default:
// throw new RuntimeException("Unexpected NMS version support in PlayerAttackCooldown compatibility layer initialization!");
// }
// }
//}
//

View File

@@ -21,6 +21,7 @@ public enum NMSVersion {
NMS_1_16_2("1.16.2"),
NMS_1_16_3("1.16.3"),
NMS_1_16_4("1.16.4"),
NMS_1_16_5("1.16.5"),
//Version not known to this build of mcMMO
UNSUPPORTED("unsupported");

View File

@@ -2,6 +2,8 @@ package com.gmail.nossr50.util.player;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.LevelUpBroadcastPredicate;
import com.gmail.nossr50.datatypes.PowerLevelUpBroadcastPredicate;
import com.gmail.nossr50.datatypes.interactions.NotificationType;
import com.gmail.nossr50.datatypes.notifications.SensitiveCommandType;
import com.gmail.nossr50.datatypes.skills.CoreSkills;
@@ -21,6 +23,8 @@ import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.MessageType;
import net.kyori.adventure.identity.Identity;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Server;
@@ -29,7 +33,13 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.time.LocalDate;
public class NotificationManager {
public static final String HEX_BEIGE_COLOR = "#c2a66e";
public static final String HEX_LIME_GREEN_COLOR = "#8ec26e";
/**
* Sends players notifications from mcMMO
* Does so by sending out an event so other plugins can cancel it
@@ -270,4 +280,83 @@ public class NotificationManager {
return newArray;
}
//TODO: Remove the code duplication, am lazy atm
//TODO: Fix broadcasts being skipped for situations where a player skips over the milestone like with the addlevels command
public static void processLevelUpBroadcasting(@NotNull McMMOPlayer mmoPlayer, @NotNull PrimarySkillType primarySkillType, int level) {
if(level <= 0)
return;
//Check if broadcasting is enabled
if(Config.getInstance().shouldLevelUpBroadcasts()) {
//Permission check
if(!Permissions.levelUpBroadcast(mmoPlayer.getPlayer())) {
return;
}
int levelInterval = Config.getInstance().getLevelUpBroadcastInterval();
int remainder = level % levelInterval;
if(remainder == 0) {
//Grab appropriate audience
Audience audience = mcMMO.getAudiences().filter(getLevelUpBroadcastPredicate(mmoPlayer.getPlayer()));
//TODO: Make prettier
HoverEvent<Component> levelMilestoneHover = Component.text(mmoPlayer.getPlayer().getName())
.append(Component.newline())
.append(Component.text(LocalDate.now().toString()))
.append(Component.newline())
.append(Component.text(primarySkillType.getName()+" reached level "+level)).color(TextColor.fromHexString(HEX_BEIGE_COLOR))
.asHoverEvent();
String localeMessage = LocaleLoader.getString("Broadcasts.LevelUpMilestone", mmoPlayer.getPlayer().getDisplayName(), level, primarySkillType.getName());
Component message = Component.text(localeMessage).hoverEvent(levelMilestoneHover);
Bukkit.getScheduler().runTaskLater(mcMMO.p, () -> audience.sendMessage(Identity.nil(), message), 0);
}
}
}
//TODO: Remove the code duplication, am lazy atm
//TODO: Fix broadcasts being skipped for situations where a player skips over the milestone like with the addlevels command
public static void processPowerLevelUpBroadcasting(@NotNull McMMOPlayer mmoPlayer, int powerLevel) {
if(powerLevel <= 0)
return;
//Check if broadcasting is enabled
if(Config.getInstance().shouldPowerLevelUpBroadcasts()) {
//Permission check
if(!Permissions.levelUpBroadcast(mmoPlayer.getPlayer())) {
return;
}
int levelInterval = Config.getInstance().getPowerLevelUpBroadcastInterval();
int remainder = powerLevel % levelInterval;
if(remainder == 0) {
//Grab appropriate audience
Audience audience = mcMMO.getAudiences().filter(getPowerLevelUpBroadcastPredicate(mmoPlayer.getPlayer()));
//TODO: Make prettier
HoverEvent<Component> levelMilestoneHover = Component.text(mmoPlayer.getPlayer().getName())
.append(Component.newline())
.append(Component.text(LocalDate.now().toString()))
.append(Component.newline())
.append(Component.text("Power level has reached "+powerLevel)).color(TextColor.fromHexString(HEX_BEIGE_COLOR))
.asHoverEvent();
String localeMessage = LocaleLoader.getString("Broadcasts.PowerLevelUpMilestone", mmoPlayer.getPlayer().getDisplayName(), powerLevel);
Component message = Component.text(localeMessage).hoverEvent(levelMilestoneHover);
Bukkit.getScheduler().runTaskLater(mcMMO.p, () -> audience.sendMessage(Identity.nil(), message), 0);
}
}
}
//TODO: Could cache
public static @NotNull LevelUpBroadcastPredicate<CommandSender> getLevelUpBroadcastPredicate(@NotNull CommandSender levelUpPlayer) {
return new LevelUpBroadcastPredicate<>(levelUpPlayer);
}
public static @NotNull PowerLevelUpBroadcastPredicate<CommandSender> getPowerLevelUpBroadcastPredicate(@NotNull CommandSender levelUpPlayer) {
return new PowerLevelUpBroadcastPredicate<>(levelUpPlayer);
}
}

View File

@@ -75,6 +75,25 @@ public class RandomChanceSkill implements RandomChanceExecution {
this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
}
public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, boolean luckyOverride) {
if (hasCap)
this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);
else
this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
if (player != null && mcMMOPlayer != null) {
this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
} else {
this.skillLevel = 0;
}
isLucky = luckyOverride;
this.resultModifier = 1.0D;
this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
}
public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, double resultModifier) {
if (hasCap)
this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);

View File

@@ -14,6 +14,12 @@ public class RandomChanceSkillStatic extends RandomChanceSkill {
this.xPos = xPos;
}
public RandomChanceSkillStatic(double xPos, @Nullable Player player, @NotNull SubSkillType subSkillType, boolean luckyOverride) {
super(player, subSkillType, false, luckyOverride);
this.xPos = xPos;
}
public RandomChanceSkillStatic(double xPos, @Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
super(player, subSkillType, resultModifier);

View File

@@ -45,12 +45,12 @@ public class RandomChanceUtil {
}
}
public static double getActivationChance(@NotNull SkillActivationType skillActivationType, @NotNull SubSkillType subSkillType, @Nullable Player player) {
public static double getActivationChance(@NotNull SkillActivationType skillActivationType, @NotNull SubSkillType subSkillType, @Nullable Player player, boolean luckyOverride) {
switch (skillActivationType) {
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
return getRandomChanceExecutionSuccess(player, subSkillType, true);
return getRandomChanceExecutionSuccess(player, subSkillType, true, luckyOverride);
case RANDOM_STATIC_CHANCE:
return getRandomStaticChanceExecutionSuccess(player, subSkillType);
return getRandomStaticChanceExecutionSuccess(player, subSkillType, luckyOverride);
default:
return 0.1337;
}
@@ -129,6 +129,10 @@ public class RandomChanceUtil {
return getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
}
public static double getRandomChanceExecutionChance(@NotNull RandomChanceExecution randomChance, boolean luckyOverride) {
return getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
}
public static double getRandomChanceExecutionChance(@NotNull RandomChanceStatic randomChance) {
double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
@@ -194,9 +198,14 @@ public class RandomChanceUtil {
return calculateChanceOfSuccess(rcs);
}
public static double getRandomStaticChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType) {
public static double getRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, boolean luckyOverride) {
RandomChanceSkill rcs = new RandomChanceSkill(player, subSkillType, hasCap, luckyOverride);
return calculateChanceOfSuccess(rcs);
}
public static double getRandomStaticChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean luckyOverride) {
try {
return getRandomChanceExecutionChance(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType));
return getRandomChanceExecutionChance(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType, luckyOverride));
} catch (InvalidStaticChance invalidStaticChance) {
//Catch invalid static skills
invalidStaticChance.printStackTrace();
@@ -259,13 +268,15 @@ public class RandomChanceUtil {
}
public static String @NotNull [] calculateAbilityDisplayValues(@NotNull SkillActivationType skillActivationType, @NotNull Player player, @NotNull SubSkillType subSkillType) {
double successChance = getActivationChance(skillActivationType, subSkillType, player);
double successChance = getActivationChance(skillActivationType, subSkillType, player, false);
double successChanceLucky = getActivationChance(skillActivationType, subSkillType, player, true);
String[] displayValues = new String[2];
boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
displayValues[1] = isLucky ? percent.format(Math.min(successChance * 1.3333D, 100.0D) / 100.0D) : null;
displayValues[1] = isLucky ? percent.format(Math.min(successChanceLucky, 100.0D) / 100.0D) : null;
return displayValues;
}
@@ -288,16 +299,16 @@ public class RandomChanceUtil {
}
public static String @NotNull [] calculateAbilityDisplayValuesCustom(@NotNull SkillActivationType skillActivationType, @NotNull Player player, @NotNull SubSkillType subSkillType, double multiplier) {
double successChance = getActivationChance(skillActivationType, subSkillType, player);
double successChance = getActivationChance(skillActivationType, subSkillType, player, false);
double successChanceLucky = getActivationChance(skillActivationType, subSkillType, player, true);
//TODO: Most likely incorrectly displays the value for graceful roll but gonna ignore for now...
successChance *= multiplier; //Currently only used for graceful roll
String[] displayValues = new String[2];
//TODO: Account for lucky in this
boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
displayValues[1] = isLucky ? percent.format(Math.min(successChance * 1.3333D, 100.0D) / 100.0D) : null;
displayValues[1] = isLucky ? percent.format(Math.min(successChanceLucky, 100.0D) / 100.0D) : null;
return displayValues;
}

View File

@@ -29,14 +29,12 @@ import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.*;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource;