From 426b1304e2c2137202cbbde26959b8288ed1f7ce Mon Sep 17 00:00:00 2001 From: nossr50 Date: Wed, 10 Apr 2019 01:52:34 -0700 Subject: [PATCH 1/4] Numerous tweaks + failsafes added to Loading/Saving of players --- Changelog.txt | 9 ++++++ pom.xml | 2 +- .../datatypes/player/PlayerProfile.java | 32 +++++++++++++++++-- .../nossr50/listeners/PlayerListener.java | 3 +- .../player/PlayerProfileLoadingTask.java | 29 ++++++++++------- .../player/PlayerProfileSaveTask.java | 7 +++- .../resources/locale/locale_en_US.properties | 4 +-- 7 files changed, 67 insertions(+), 19 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 7570bd3f8..c2a876b27 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -7,6 +7,15 @@ Key: ! Change - Removal +Version 2.1.40 + Added new locale string "Profile.Loading.FailureNotice" + Added new locale string "Profile.Loading.FailurePlayer" + mcMMO no longer gives up forever if a player profile fails to load and the player is still online + mcMMO will attempt to save a profile up to 10 times now, previously it would only try one time. + Player data for mcMMO is now loaded 3 seconds after a player connects in order to give any ongoing save tasks from other servers a small grace period to finish. This will mostly be useful to Bungee servers. + +NOTES: I received reports from some users saying that saving and loading was failing could fail and not recover, I have implemented some fail safes to greatly reduce the the odds of that happening. + Version 2.1.39 Salvaging an item should now only play the item break sound (was playing the anvil sound simultaneously before) Fixed bug where Tall_Grass was not giving full XP diff --git a/pom.xml b/pom.xml index 52390ed8b..20a75ca9b 100755 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.gmail.nossr50.mcMMO mcMMO - 2.1.39 + 2.1.40-SNAPSHOT mcMMO https://github.com/mcMMO-Dev/mcMMO diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java index 454002b68..ed09844b1 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java @@ -13,6 +13,7 @@ import com.gmail.nossr50.runnables.player.PlayerProfileSaveTask; import com.gmail.nossr50.skills.child.FamilyTree; import com.gmail.nossr50.util.player.UserManager; import com.google.common.collect.ImmutableMap; +import org.bukkit.Bukkit; import java.util.HashMap; import java.util.Map; @@ -29,6 +30,7 @@ public class PlayerProfile { /* HUDs */ private MobHealthbarType mobHealthbarType; private int scoreboardTipsShown; + private int saveAttempts = 0; /* Skill Data */ private final Map skills = new HashMap(); // Skill & Level @@ -36,7 +38,7 @@ public class PlayerProfile { private final Map abilityDATS = new HashMap(); // Ability & Cooldown private final Map uniquePlayerData = new HashMap<>(); //Misc data that doesn't fit into other categories (chimaera wing, etc..) - // Store previous XP gains for deminished returns + // Store previous XP gains for diminished returns private DelayQueue gainedSkillsXp = new DelayQueue(); private HashMap rollingSkillsXp = new HashMap(); @@ -94,8 +96,13 @@ public class PlayerProfile { new PlayerProfileSaveTask(this).runTaskAsynchronously(mcMMO.p); } + public void scheduleAsyncSaveDelay() { + new PlayerProfileSaveTask(this).runTaskLaterAsynchronously(mcMMO.p, 20); + } + public void save() { if (!changed || !loaded) { + saveAttempts = 0; return; } @@ -104,8 +111,29 @@ public class PlayerProfile { changed = !mcMMO.getDatabaseManager().saveUser(profileCopy); if (changed) { - mcMMO.p.getLogger().warning("PlayerProfile saving failed for player: " + playerName + " " + uuid); + mcMMO.p.getLogger().severe("PlayerProfile saving failed for player: " + playerName + " " + uuid); + + if(saveAttempts > 0) + { + mcMMO.p.getLogger().severe("Attempted to save profile for player "+getPlayerName() + + " resulted in failure. "+saveAttempts+" have been made so far."); + } + + if(saveAttempts < 10) + { + saveAttempts++; + scheduleAsyncSaveDelay(); + return; + } else { + mcMMO.p.getLogger().severe("mcMMO has failed to save the profile for " + +getPlayerName()+" numerous times." + + " mcMMO will now stop attempting to save this profile." + + " Check your console for errors and inspect your DB for issues."); + } + } + + saveAttempts = 0; } public String getPlayerName() { diff --git a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java index 5b169b8d4..ce52b80cd 100644 --- a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java @@ -484,7 +484,8 @@ public class PlayerListener implements Listener { return; } - new PlayerProfileLoadingTask(player).runTaskLaterAsynchronously(mcMMO.p, 1); // 1 Tick delay to ensure the player is marked as online before we begin loading + //Delay loading for 3 seconds in case the player has a save task running, its hacky but it should do the trick + new PlayerProfileLoadingTask(player).runTaskLaterAsynchronously(mcMMO.p, 60); if (Config.getInstance().getMOTDEnabled() && Permissions.motd(player)) { Motd.displayAll(player); diff --git a/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileLoadingTask.java b/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileLoadingTask.java index 2f5e561f1..4736ce5cd 100644 --- a/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileLoadingTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileLoadingTask.java @@ -14,7 +14,6 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; public class PlayerProfileLoadingTask extends BukkitRunnable { - private static final int MAX_TRIES = 5; private final Player player; private int attempt = 0; @@ -37,9 +36,6 @@ public class PlayerProfileLoadingTask extends BukkitRunnable { return; } - // Increment attempt counter and try - attempt++; - PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(player.getName(), player.getUniqueId(), true); // If successful, schedule the apply if (profile.isLoaded()) { @@ -47,14 +43,24 @@ public class PlayerProfileLoadingTask extends BukkitRunnable { return; } - // If we've failed five times, give up - if (attempt >= MAX_TRIES) { - mcMMO.p.getLogger().severe("Giving up on attempting to load the PlayerProfile for " + player.getName()); - mcMMO.p.getServer().broadcast(LocaleLoader.getString("Profile.Loading.AdminFailureNotice", player.getName()), Server.BROADCAST_CHANNEL_ADMINISTRATIVE); - player.sendMessage(LocaleLoader.getString("Profile.Loading.Failure").split("\n")); - return; + // Print errors to console/logs if we're failing at least 2 times in a row to load the profile + if (attempt >= 3) + { + //Log the error + mcMMO.p.getLogger().severe(LocaleLoader.getString("Profile.Loading.FailureNotice", + player.getName(), String.valueOf(attempt))); + + //Notify the admins + mcMMO.p.getServer().broadcast(LocaleLoader.getString("Profile.Loading.FailureNotice", player.getName()), Server.BROADCAST_CHANNEL_ADMINISTRATIVE); + + //Notify the player + player.sendMessage(LocaleLoader.getString("Profile.Loading.FailurePlayer", String.valueOf(attempt)).split("\n")); } - new PlayerProfileLoadingTask(player, attempt).runTaskLaterAsynchronously(mcMMO.p, 100 * attempt); + + // Increment attempt counter and try + attempt++; + + new PlayerProfileLoadingTask(player, attempt).runTaskLaterAsynchronously(mcMMO.p, 100); } private class ApplySuccessfulProfile extends BukkitRunnable { @@ -90,7 +96,6 @@ public class PlayerProfileLoadingTask extends BukkitRunnable { player.sendMessage(LocaleLoader.getString("Profile.Loading.Success")); } - } } } diff --git a/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java b/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java index 414896983..e6f402de5 100644 --- a/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java @@ -12,6 +12,11 @@ public class PlayerProfileSaveTask extends BukkitRunnable { @Override public void run() { - playerProfile.save(); + boolean saveSuccess = playerProfile.save(); + + if(!saveSuccess) + { + playerProfile.scheduleAsyncSaveDelay(); + } } } diff --git a/src/main/resources/locale/locale_en_US.properties b/src/main/resources/locale/locale_en_US.properties index 1d21f42da..411eb88d4 100644 --- a/src/main/resources/locale/locale_en_US.properties +++ b/src/main/resources/locale/locale_en_US.properties @@ -1069,8 +1069,8 @@ Scoreboard.Misc.Overall=[[GOLD]]Overall Scoreboard.Misc.Ability=Ability #DATABASE RECOVERY Profile.Loading.Success=[[GREEN]]Your mcMMO profile has been loaded. -Profile.Loading.Failure=[[RED]]mcMMO still cannot load your data. You may want to [[AQUA]]contact the server owner.\n[[YELLOW]]You can still play on the server, but you will have [[BOLD]]no mcMMO levels[[YELLOW]] and any XP you get [[BOLD]]will not be saved[[YELLOW]]. -Profile.Loading.AdminFailureNotice=[[DARK_RED]][A][[RED]] mcMMO was unable to load the player data for [[YELLOW]]{0}[[RED]]. [[LIGHT_PURPLE]]Please inspect your database setup. +Profile.Loading.FailurePlayer=[[RED]]mcMMO is having trouble loading your data, we have attempted to load it [[GREEN]]{0}[[RED]] times.[[LIGHT_GRAY]] You may want to contact the server admins about this issue. mcMMO will attempt to load your data until you disconnect, you will not gain XP or be able to use skills while the data is not loaded. +Profile.Loading.FailureNotice=[[DARK_RED]][A][[RED]] mcMMO was unable to load the player data for [[YELLOW]]{0}[[RED]]. [[LIGHT_PURPLE]]Please inspect your database setup. Attempts made so far {1}. #Holiday Holiday.AprilFools.Levelup=[[GOLD]]{0} is now level [[GREEN]]{1}[[GOLD]]! Holiday.Anniversary=[[BLUE]]Happy {0} Year Anniversary!\n[[BLUE]]In honor of all of nossr50's work and all the devs, here's a firework show! From 87bf3a5b40ec98044405a8ba8c43038b02d7e3b0 Mon Sep 17 00:00:00 2001 From: nossr50 Date: Thu, 11 Apr 2019 00:00:22 -0700 Subject: [PATCH 2/4] fixing an oopsie --- .../nossr50/runnables/player/PlayerProfileSaveTask.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java b/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java index e6f402de5..414896983 100644 --- a/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java @@ -12,11 +12,6 @@ public class PlayerProfileSaveTask extends BukkitRunnable { @Override public void run() { - boolean saveSuccess = playerProfile.save(); - - if(!saveSuccess) - { - playerProfile.scheduleAsyncSaveDelay(); - } + playerProfile.save(); } } From 8b0a580505fe1c4d70e485b28d143d4cb1fad2d9 Mon Sep 17 00:00:00 2001 From: nossr50 Date: Thu, 11 Apr 2019 03:49:13 -0700 Subject: [PATCH 3/4] Fixing Party Chat Bug --- Changelog.txt | 2 ++ pom.xml | 2 +- src/main/java/com/gmail/nossr50/chat/ChatManager.java | 10 +++++++--- .../com/gmail/nossr50/util/player/UserManager.java | 6 +++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index c2a876b27..40bb1cd5a 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -8,10 +8,12 @@ Key: - Removal Version 2.1.40 + (API) mcMMO will now return null in all cases for UserManager.getPlayerProfile() if they have not been loaded yet Added new locale string "Profile.Loading.FailureNotice" Added new locale string "Profile.Loading.FailurePlayer" mcMMO no longer gives up forever if a player profile fails to load and the player is still online mcMMO will attempt to save a profile up to 10 times now, previously it would only try one time. + Fixed an ArrayIndexOutOfBounds error with Party Chat Player data for mcMMO is now loaded 3 seconds after a player connects in order to give any ongoing save tasks from other servers a small grace period to finish. This will mostly be useful to Bungee servers. NOTES: I received reports from some users saying that saving and loading was failing could fail and not recover, I have implemented some fail safes to greatly reduce the the odds of that happening. diff --git a/pom.xml b/pom.xml index 20a75ca9b..f5086f40b 100755 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.gmail.nossr50.mcMMO mcMMO - 2.1.40-SNAPSHOT + 2.1.40 mcMMO https://github.com/mcMMO-Dev/mcMMO diff --git a/src/main/java/com/gmail/nossr50/chat/ChatManager.java b/src/main/java/com/gmail/nossr50/chat/ChatManager.java index a7d5311bb..30908b216 100644 --- a/src/main/java/com/gmail/nossr50/chat/ChatManager.java +++ b/src/main/java/com/gmail/nossr50/chat/ChatManager.java @@ -1,6 +1,8 @@ package com.gmail.nossr50.chat; import com.gmail.nossr50.datatypes.party.Party; +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.events.chat.McMMOChatEvent; import com.gmail.nossr50.events.chat.McMMOPartyChatEvent; import com.gmail.nossr50.locale.LocaleLoader; @@ -46,12 +48,14 @@ public abstract class ChatManager { McMMOPartyChatEvent partyChatEvent = (McMMOPartyChatEvent) event; //Find the people with permissions - for(Player player : event.getPlugin().getServer().getOnlinePlayers()) + for(McMMOPlayer mcMMOPlayer : UserManager.getPlayers()) { + Player player = mcMMOPlayer.getPlayer(); + //Check for toggled players - if(UserManager.getPlayer(player).isPartyChatSpying()) + if(mcMMOPlayer.isPartyChatSpying()) { - Party adminParty = UserManager.getPlayer(player).getParty(); + Party adminParty = mcMMOPlayer.getParty(); //Only message admins not part of this party if(adminParty != null) diff --git a/src/main/java/com/gmail/nossr50/util/player/UserManager.java b/src/main/java/com/gmail/nossr50/util/player/UserManager.java index 3c5411bc9..ff0a53597 100644 --- a/src/main/java/com/gmail/nossr50/util/player/UserManager.java +++ b/src/main/java/com/gmail/nossr50/util/player/UserManager.java @@ -96,7 +96,11 @@ public final class UserManager { } public static McMMOPlayer getPlayer(Player player) { - return (McMMOPlayer) player.getMetadata(mcMMO.playerDataKey).get(0).value(); + //Avoid Array Index out of bounds + if(player.hasMetadata(mcMMO.playerDataKey)) + return (McMMOPlayer) player.getMetadata(mcMMO.playerDataKey).get(0).value(); + else + return null; } private static McMMOPlayer retrieveMcMMOPlayer(String playerName, boolean offlineValid) { From 00cc5f0845b842e1f2219e38a289d7a4411caeff Mon Sep 17 00:00:00 2001 From: nossr50 Date: Thu, 11 Apr 2019 04:09:00 -0700 Subject: [PATCH 4/4] Move Fall data to AcrobaticsManager --- Changelog.txt | 1 + .../com/gmail/nossr50/chat/ChatManager.java | 1 - .../datatypes/player/PlayerProfile.java | 1 - .../skills/subskills/acrobatics/Roll.java | 31 ++----------------- .../skills/acrobatics/AcrobaticsManager.java | 14 +++++++++ .../nossr50/skills/mining/BlastMining.java | 2 -- 6 files changed, 18 insertions(+), 32 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 40bb1cd5a..c357aaa5d 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -9,6 +9,7 @@ Key: Version 2.1.40 (API) mcMMO will now return null in all cases for UserManager.getPlayerProfile() if they have not been loaded yet + (API) Roll stores exploit data in AcrobaticsManager now Added new locale string "Profile.Loading.FailureNotice" Added new locale string "Profile.Loading.FailurePlayer" mcMMO no longer gives up forever if a player profile fails to load and the player is still online diff --git a/src/main/java/com/gmail/nossr50/chat/ChatManager.java b/src/main/java/com/gmail/nossr50/chat/ChatManager.java index 30908b216..d91d5885e 100644 --- a/src/main/java/com/gmail/nossr50/chat/ChatManager.java +++ b/src/main/java/com/gmail/nossr50/chat/ChatManager.java @@ -2,7 +2,6 @@ package com.gmail.nossr50.chat; import com.gmail.nossr50.datatypes.party.Party; import com.gmail.nossr50.datatypes.player.McMMOPlayer; -import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.events.chat.McMMOChatEvent; import com.gmail.nossr50.events.chat.McMMOPartyChatEvent; import com.gmail.nossr50.locale.LocaleLoader; diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java index ed09844b1..f71ceeca1 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java @@ -13,7 +13,6 @@ import com.gmail.nossr50.runnables.player.PlayerProfileSaveTask; import com.gmail.nossr50.skills.child.FamilyTree; import com.gmail.nossr50.util.player.UserManager; import com.google.common.collect.ImmutableMap; -import org.bukkit.Bukkit; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java index 0d349ecdf..5beeb42ab 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java @@ -1,9 +1,7 @@ package com.gmail.nossr50.datatypes.skills.subskills.acrobatics; import com.gmail.nossr50.config.AdvancedConfig; -import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.experience.ExperienceConfig; -import com.gmail.nossr50.datatypes.LimitedSizeList; import com.gmail.nossr50.datatypes.experience.XPGainReason; import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.player.McMMOPlayer; @@ -34,14 +32,11 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.inventory.ItemStack; -import java.util.HashMap; - public class Roll extends AcrobaticsSubSkill { - protected HashMap fallLocationMap; + public Roll() { super("Roll", EventPriority.HIGHEST, SubSkillType.ACROBATICS_ROLL); - fallLocationMap = new HashMap<>(); } /** @@ -280,25 +275,11 @@ public class Roll extends AcrobaticsSubSkill { return true; } - if(fallLocationMap.get(player) == null) - fallLocationMap.put(player, new LimitedSizeList(50)); - LimitedSizeList fallLocations = fallLocationMap.get(player); - - if(fallLocations.contains(getBlockLocation(player))) + if(UserManager.getPlayer(player).getAcrobaticsManager().hasFallenInLocationBefore(getBlockLocation(player))) return true; return false; //NOT EXPLOITING -/* - Location fallLocation = player.getLocation(); - int maxTries = Config.getInstance().getAcrobaticsAFKMaxTries(); - - boolean sameLocation = (lastFallLocation != null && Misc.isNear(lastFallLocation, fallLocation, 2)); - - fallTries = sameLocation ? Math.min(fallTries + 1, maxTries) : Math.max(fallTries - 1, 0); - lastFallLocation = fallLocation; - - return fallTries + 1 > maxTries;*/ } private float calculateRollXP(Player player, double damage, boolean isRoll) { @@ -426,13 +407,7 @@ public class Roll extends AcrobaticsSubSkill { public void addFallLocation(Player player) { - if(fallLocationMap.get(player) == null) - fallLocationMap.put(player, new LimitedSizeList(50)); - - LimitedSizeList fallLocations = fallLocationMap.get(player); - - Location loc = getBlockLocation(player); - fallLocations.add(loc); + UserManager.getPlayer(player).getAcrobaticsManager().addLocationToFallMap(getBlockLocation(player)); } public Location getBlockLocation(Player player) diff --git a/src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java b/src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java index 238f8dde3..fc45b061f 100644 --- a/src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java +++ b/src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java @@ -1,6 +1,7 @@ package com.gmail.nossr50.skills.acrobatics; import com.gmail.nossr50.config.experience.ExperienceConfig; +import com.gmail.nossr50.datatypes.LimitedSizeList; import com.gmail.nossr50.datatypes.experience.XPGainReason; import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.player.McMMOPlayer; @@ -15,6 +16,7 @@ import com.gmail.nossr50.util.skills.ParticleEffectUtils; import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.SkillActivationType; import com.gmail.nossr50.util.skills.SkillUtils; +import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.LightningStrike; import org.bukkit.entity.Player; @@ -23,11 +25,23 @@ public class AcrobaticsManager extends SkillManager { public AcrobaticsManager(McMMOPlayer mcMMOPlayer) { super(mcMMOPlayer, PrimarySkillType.ACROBATICS); + fallLocationMap = new LimitedSizeList(50); } private long rollXPCooldown = 0; private long rollXPInterval = (1000 * 10); //1 Minute private long rollXPIntervalLengthen = (1000 * 10); //10 Seconds + private LimitedSizeList fallLocationMap; + + public boolean hasFallenInLocationBefore(Location location) + { + return fallLocationMap.contains(location); + } + + public void addLocationToFallMap(Location location) + { + fallLocationMap.add(location); + } public boolean canGainRollXP() { diff --git a/src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java b/src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java index a3c23a8d2..5ed629a80 100644 --- a/src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java +++ b/src/main/java/com/gmail/nossr50/skills/mining/BlastMining.java @@ -1,12 +1,10 @@ package com.gmail.nossr50.skills.mining; import com.gmail.nossr50.config.AdvancedConfig; -import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.skills.RankUtils; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.entity.TNTPrimed; import org.bukkit.event.entity.EntityDamageByEntityEvent;