diff --git a/Changelog.txt b/Changelog.txt
index 146aa67b2..0696b54d7 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -1,4 +1,13 @@
Version 2.1.81
+ Fixed a bug where Arrow Deflect would never trigger outside of PVP
+ Fixed a bug where failing to salvage enchantments incorrectly colored the text
+ mcMMO no longer allows players to keep enchantments exceeding normal limitations by default when salvaging or repairing (you can turn this off in the config, see below)
+ Added new setting 'ExploitFix.UnsafeEnchantments' to experience.yml, turn this on to allow players to salvage/repair enchantments higher than normal game restrictions
+
+ NOTES:
+ If a player tries to salvage/repair an item with an illegal enchant (for example Sharpness X) it will downgrade that item to the highest legal version when calculating rewards
+ If you don't like this change you can turn it off in experience.yml under 'ExploitFix.UnsafeEnchantments'
+
Version 2.1.80
(Fix) mcMMO now respects the NBT "Unbreakable" tag and does not deal durability damage to items with that tag
diff --git a/pom.xml b/pom.xml
index 5908de545..65095a77f 100755
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
com.gmail.nossr50.mcMMO
mcMMO
- 2.1.81-SNAPSHOT
+ 2.1.81
mcMMO
https://github.com/mcMMO-Dev/mcMMO
diff --git a/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java b/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java
index 3f134cf66..641b0e4a7 100644
--- a/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java
+++ b/src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java
@@ -147,6 +147,7 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
/* EXPLOIT TOGGLES */
public boolean isEndermanEndermiteFarmingPrevented() { return config.getBoolean("ExploitFix.EndermanEndermiteFarms", true); }
public boolean isPistonExploitPrevented() { return config.getBoolean("ExploitFix.Pistons", false); }
+ public boolean allowUnsafeEnchantments() { return config.getBoolean("ExploitFix.UnsafeEnchantments", false); }
public boolean isFishingExploitingPrevented() { return config.getBoolean("ExploitFix.Fishing", true); }
public boolean isAcrobaticsExploitingPrevented() { return config.getBoolean("ExploitFix.Acrobatics", true); }
diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java
index b548f1668..c7f26431c 100644
--- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java
+++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java
@@ -17,6 +17,7 @@ import com.gmail.nossr50.skills.mining.BlastMining;
import com.gmail.nossr50.skills.mining.MiningManager;
import com.gmail.nossr50.skills.taming.Taming;
import com.gmail.nossr50.skills.taming.TamingManager;
+import com.gmail.nossr50.skills.unarmed.UnarmedManager;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
@@ -346,6 +347,18 @@ public class EntityListener implements Listener {
if (projectileSource instanceof LivingEntity) {
attacker = (LivingEntity) projectileSource;
}
+
+ if(defender instanceof Player) {
+ Player playerDefender = (Player) defender;
+ UnarmedManager unarmedManager = UserManager.getPlayer(playerDefender).getUnarmedManager();
+
+ if (unarmedManager.canDeflect()) {
+ if(unarmedManager.deflectCheck()) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
}
else if (attacker instanceof Tameable) {
AnimalTamer animalTamer = ((Tameable) attacker).getOwner();
diff --git a/src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java b/src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java
index 31d8c7e5f..1f36ad650 100644
--- a/src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java
+++ b/src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java
@@ -328,10 +328,17 @@ public class RepairManager extends SkillManager {
boolean downgraded = false;
for (Entry enchant : enchants.entrySet()) {
+ int enchantLevel = enchant.getValue();
+
+ if(!ExperienceConfig.getInstance().allowUnsafeEnchantments()) {
+ if(enchantLevel > enchant.getKey().getMaxLevel()) {
+ enchantLevel = enchant.getKey().getMaxLevel();
+ }
+ }
+
Enchantment enchantment = enchant.getKey();
if (RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getKeepEnchantChance(), getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING))) {
- int enchantLevel = enchant.getValue();
if (ArcaneForging.arcaneForgingDowngrades && enchantLevel > 1
&& (!RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(100 - getDowngradeEnchantChance(), getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING)))) {
@@ -347,13 +354,13 @@ public class RepairManager extends SkillManager {
Map newEnchants = item.getEnchantments();
if (newEnchants.isEmpty()) {
- NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Arcane.Fail");
+ NotificationManager.sendPlayerInformationChatOnly(getPlayer(), "Repair.Arcane.Fail");
}
else if (downgraded || newEnchants.size() < enchants.size()) {
- NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Arcane.Downgrade");
+ NotificationManager.sendPlayerInformationChatOnly(getPlayer(), "Repair.Arcane.Downgrade");
}
else {
- NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Repair.Arcane.Perfect");
+ NotificationManager.sendPlayerInformationChatOnly(getPlayer(), "Repair.Arcane.Perfect");
}
}
diff --git a/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java b/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java
index 5dcf8f867..e7fd5bb44 100644
--- a/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java
+++ b/src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java
@@ -2,6 +2,7 @@ package com.gmail.nossr50.skills.salvage;
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;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@@ -214,7 +215,7 @@ public class SalvageManager extends SkillManager {
Player player = getPlayer();
if (!RankUtils.hasUnlockedSubskill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE) || !Permissions.arcaneSalvage(player)) {
- NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.ArcaneFailed");
+ NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.ArcaneFailed");
return null;
}
@@ -225,15 +226,24 @@ public class SalvageManager extends SkillManager {
int arcaneFailureCount = 0;
for (Entry enchant : enchants.entrySet()) {
+
+ int enchantLevel = enchant.getValue();
+
+ if(!ExperienceConfig.getInstance().allowUnsafeEnchantments()) {
+ if(enchantLevel > enchant.getKey().getMaxLevel()) {
+ enchantLevel = enchant.getKey().getMaxLevel();
+ }
+ }
+
if (!Salvage.arcaneSalvageEnchantLoss
|| Permissions.hasSalvageEnchantBypassPerk(player)
|| RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getExtractFullEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
- enchantMeta.addStoredEnchant(enchant.getKey(), enchant.getValue(), true);
+ enchantMeta.addStoredEnchant(enchant.getKey(), enchantLevel, true);
}
- else if (enchant.getValue() > 1
+ else if (enchantLevel > 1
&& Salvage.arcaneSalvageDowngrades
&& RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getExtractPartialEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
- enchantMeta.addStoredEnchant(enchant.getKey(), enchant.getValue() - 1, true);
+ enchantMeta.addStoredEnchant(enchant.getKey(), enchantLevel - 1, true);
downgraded = true;
} else {
arcaneFailureCount++;
@@ -242,11 +252,11 @@ public class SalvageManager extends SkillManager {
if(failedAllEnchants(arcaneFailureCount, enchants.entrySet().size()))
{
- NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.ArcaneFailed");
+ NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.ArcaneFailed");
return null;
} else if(downgraded)
{
- NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.ArcanePartial");
+ NotificationManager.sendPlayerInformationChatOnly(player, "Salvage.Skills.ArcanePartial");
}
book.setItemMeta(enchantMeta);
diff --git a/src/main/resources/experience.yml b/src/main/resources/experience.yml
index 8c7959fc9..d2a291463 100644
--- a/src/main/resources/experience.yml
+++ b/src/main/resources/experience.yml
@@ -27,6 +27,7 @@ EarlyGameBoost:
#Used to determine the cap of the max boot, with default level cap it will be 5 on standard, and 50 on retro
MaxLevelMultiplier: 0.05
ExploitFix:
+ UnsafeEnchantments: false
# Prevent many exploits related to fishing
Fishing: true
EndermanEndermiteFarms: true