From 96742e6c423a5b8a23b81d9d70020faa7ab6c899 Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sat, 19 Jan 2019 18:51:18 -0800 Subject: [PATCH] mcMMO now alerts you when you progress in a skill --- Changelog.txt | 1 + .../nossr50/datatypes/player/McMMOPlayer.java | 11 +++- .../skills/subskills/AbstractSubSkill.java | 8 ++- .../acrobatics/AcrobaticsSubSkill.java | 5 +- .../skills/subskills/acrobatics/Roll.java | 2 +- .../gmail/nossr50/listeners/SelfListener.java | 8 ++- src/main/java/com/gmail/nossr50/mcMMO.java | 4 ++ .../skills/SkillUnlockNotificationTask.java | 41 +++++++++++++ .../nossr50/util/TextComponentFactory.java | 9 +++ .../util/player/NotificationManager.java | 16 +++++ .../gmail/nossr50/util/skills/RankUtils.java | 61 +++++++++++++++++-- .../resources/locale/locale_en_US.properties | 3 +- 12 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/gmail/nossr50/runnables/skills/SkillUnlockNotificationTask.java diff --git a/Changelog.txt b/Changelog.txt index 647237105..f2e4374ef 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -17,6 +17,7 @@ Version 2.1.0 + Certain elements of mcMMO's UI have been restyled + Added the tagline "Overhaul Era" to various locations until 3.0.0 comes out ! (Scoreboards) Scoreboards are now disabled by default, I don't like them. You can turn them back on in config.yml + + (Experience) mcMMO now notifies you when you progress in a skill! + (Experience) Coral (blocks) now give Mining XP + (Experience) Coral (plants) now give Herbalism XP + (Experience) Blue Ice now gives Mining XP diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java index f8c87cfcf..788d83945 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -55,6 +55,7 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.plugin.Plugin; import java.util.HashMap; import java.util.Map; @@ -142,17 +143,25 @@ public class McMMOPlayer { experienceBarManager.hideExperienceBar(primarySkillType); }*/ - public void processPostXpEvent(XPGainReason xpGainReason, PrimarySkillType primarySkillType, mcMMO plugin) + public void processPostXpEvent(XPGainReason xpGainReason, PrimarySkillType primarySkillType, mcMMO plugin, int xpGained) { if(xpGainReason != XPGainReason.SHARED_PVP && xpGainReason != XPGainReason.SHARED_PVE && xpGainReason != XPGainReason.VAMPIRISM) updateXPBar(primarySkillType, plugin); } + public void processUnlockNotifications(mcMMO plugin, PrimarySkillType primarySkillType, int level) + { + RankUtils.executeSkillUnlockNotifications(plugin, this, primarySkillType, profile.getSkillLevel(primarySkillType)); + } + public void updateXPBar(PrimarySkillType primarySkillType, mcMMO plugin) { + //Skill Unlock Notifications + if(primarySkillType.isChildSkill()) return; + //XP BAR UPDATES experienceBarManager.updateExperienceBar(primarySkillType, plugin); } diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/AbstractSubSkill.java b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/AbstractSubSkill.java index 9a1a1b1ca..2e7c9a1f5 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/AbstractSubSkill.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/AbstractSubSkill.java @@ -1,6 +1,7 @@ package com.gmail.nossr50.datatypes.skills.subskills; import com.gmail.nossr50.config.CoreSkillsConfig; +import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.skills.subskills.interfaces.Interaction; import com.gmail.nossr50.datatypes.skills.subskills.interfaces.Rank; import com.gmail.nossr50.datatypes.skills.subskills.interfaces.SubSkill; @@ -14,11 +15,13 @@ public abstract class AbstractSubSkill implements SubSkill, Interaction, Rank, S */ protected String configKeySubSkill; protected String configKeyPrimary; + protected SubSkillType subSkillType; - public AbstractSubSkill(String configKeySubSkill, String configKeyPrimary) + public AbstractSubSkill(String configKeySubSkill, String configKeyPrimary, SubSkillType subSkillType) { this.configKeySubSkill = configKeySubSkill; this.configKeyPrimary = configKeyPrimary; + this.subSkillType = subSkillType; } /** @@ -55,6 +58,9 @@ public abstract class AbstractSubSkill implements SubSkill, Interaction, Rank, S player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.Header")); player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.SubSkillHeader", getConfigKeyName())); player.sendMessage(LocaleLoader.getString("Commands.MmoInfo.DetailsHeader")); + } + public SubSkillType getSubSkillType() { + return subSkillType; } } diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/AcrobaticsSubSkill.java b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/AcrobaticsSubSkill.java index 30c53594f..d692747b8 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/AcrobaticsSubSkill.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/AcrobaticsSubSkill.java @@ -1,6 +1,7 @@ package com.gmail.nossr50.datatypes.skills.subskills.acrobatics; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; +import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill; import com.gmail.nossr50.datatypes.skills.subskills.interfaces.InteractType; import com.gmail.nossr50.locale.LocaleLoader; @@ -13,8 +14,8 @@ public abstract class AcrobaticsSubSkill extends AbstractSubSkill { protected EventPriority interactionPriority; - public AcrobaticsSubSkill(String configKeySub, EventPriority interactionPriority) { - super(configKeySub, "Acrobatics"); + public AcrobaticsSubSkill(String configKeySub, EventPriority interactionPriority, SubSkillType subSkillType) { + super(configKeySub, "Acrobatics", subSkillType); this.interactionPriority = interactionPriority; } 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 65204d626..c65e68c74 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 @@ -34,7 +34,7 @@ public class Roll extends AcrobaticsSubSkill implements RandomChance { protected Location lastFallLocation; public Roll() { - super("Roll", EventPriority.HIGHEST); + super("Roll", EventPriority.HIGHEST, SubSkillType.ACROBATICS_ROLL); } /** diff --git a/src/main/java/com/gmail/nossr50/listeners/SelfListener.java b/src/main/java/com/gmail/nossr50/listeners/SelfListener.java index 75e7848c8..f9e6308b3 100644 --- a/src/main/java/com/gmail/nossr50/listeners/SelfListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/SelfListener.java @@ -30,6 +30,8 @@ public class SelfListener implements Listener { Player player = event.getPlayer(); PrimarySkillType skill = event.getSkill(); + UserManager.getPlayer(player).processUnlockNotifications(plugin, event.getSkill(), event.getSkillLevel()); + if(Config.getInstance().getScoreboardsEnabled()) ScoreboardManager.handleLevelUp(player, skill); @@ -63,7 +65,7 @@ public class SelfListener implements Listener { if (event.getXpGainReason() == XPGainReason.COMMAND) { //Update the XP Bar - mcMMOPlayer.processPostXpEvent(event.getXpGainReason(), primarySkillType, plugin); + mcMMOPlayer.processPostXpEvent(event.getXpGainReason(), primarySkillType, plugin, (int) event.getRawXpGained()); return; } @@ -72,7 +74,7 @@ public class SelfListener implements Listener { if (threshold <= 0 || !ExperienceConfig.getInstance().getDiminishedReturnsEnabled()) { // Diminished returns is turned off //Update the XP Bar - mcMMOPlayer.processPostXpEvent(event.getXpGainReason(), primarySkillType, plugin); + mcMMOPlayer.processPostXpEvent(event.getXpGainReason(), primarySkillType, plugin, (int) event.getRawXpGained()); return; } @@ -118,6 +120,6 @@ public class SelfListener implements Listener { //Update the XP Bar if(!event.isCancelled()) - mcMMOPlayer.processPostXpEvent(event.getXpGainReason(), primarySkillType, plugin); + mcMMOPlayer.processPostXpEvent(event.getXpGainReason(), primarySkillType, plugin, (int) event.getRawXpGained()); } } diff --git a/src/main/java/com/gmail/nossr50/mcMMO.java b/src/main/java/com/gmail/nossr50/mcMMO.java index 660e13554..4376215a9 100644 --- a/src/main/java/com/gmail/nossr50/mcMMO.java +++ b/src/main/java/com/gmail/nossr50/mcMMO.java @@ -41,6 +41,7 @@ import com.gmail.nossr50.util.commands.CommandRegistrationManager; import com.gmail.nossr50.util.experience.FormulaManager; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.scoreboards.ScoreboardManager; +import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.upgrade.UpgradeManager; import com.google.common.base.Charsets; import net.shatteredlands.shatt.backup.ZipLibrary; @@ -181,6 +182,9 @@ public class mcMMO extends JavaPlugin { Permissions.generateWorldTeleportPermissions(); } + //Populate Ranked Skill Maps (DO THIS LAST) + RankUtils.populateRanks(); + //If anonymous statistics are enabled then use them Metrics metrics; diff --git a/src/main/java/com/gmail/nossr50/runnables/skills/SkillUnlockNotificationTask.java b/src/main/java/com/gmail/nossr50/runnables/skills/SkillUnlockNotificationTask.java new file mode 100644 index 000000000..2e23e42eb --- /dev/null +++ b/src/main/java/com/gmail/nossr50/runnables/skills/SkillUnlockNotificationTask.java @@ -0,0 +1,41 @@ +package com.gmail.nossr50.runnables.skills; + +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.skills.SubSkillType; +import com.gmail.nossr50.util.player.NotificationManager; +import org.bukkit.scheduler.BukkitRunnable; + + +public class SkillUnlockNotificationTask extends BukkitRunnable { + private McMMOPlayer mcMMOPlayer; + private SubSkillType subSkillType; + private int rank; + /** + * Notify a player about a newly unlocked subskill + * @param mcMMOPlayer target player + * @param subSkillType the subskill that they just unlocked + * @param rank the rank of the subskill + */ + public SkillUnlockNotificationTask(McMMOPlayer mcMMOPlayer, SubSkillType subSkillType, int rank) + { + this.mcMMOPlayer = mcMMOPlayer; + this.subSkillType = subSkillType; + this.rank = rank; + } + /** + * When an object implementing interface Runnable is used + * to create a thread, starting the thread causes the object's + * run method to be called in that separately executing + * thread. + *

+ * The general contract of the method run is that it may + * take any action whatsoever. + * + * @see Thread#run() + */ + @Override + public void run() { + //mcMMOPlayer.getPlayer().sendTitle(subSkillType.getLocaleName(), "Rank "+rank, 7, 20, 7); + NotificationManager.sendPlayerUnlockNotification(mcMMOPlayer, subSkillType); + } +} diff --git a/src/main/java/com/gmail/nossr50/util/TextComponentFactory.java b/src/main/java/com/gmail/nossr50/util/TextComponentFactory.java index 619ab02f3..04e1530a1 100644 --- a/src/main/java/com/gmail/nossr50/util/TextComponentFactory.java +++ b/src/main/java/com/gmail/nossr50/util/TextComponentFactory.java @@ -516,6 +516,15 @@ public class TextComponentFactory { } } } + + public static TextComponent getSubSkillUnlockedNotificationComponents(Player player, SubSkillType subSkillType) + { + TextComponent unlockMessage = new TextComponent(""); + unlockMessage.setText(LocaleLoader.getString("JSON.SkillUnlockMessage", subSkillType.getLocaleName(), RankUtils.getRank(player, subSkillType))); + unlockMessage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, getSubSkillHoverComponent(player, subSkillType))); + unlockMessage.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/"+subSkillType.getParentSkill().toString().toLowerCase())); + return unlockMessage; + } } diff --git a/src/main/java/com/gmail/nossr50/util/player/NotificationManager.java b/src/main/java/com/gmail/nossr50/util/player/NotificationManager.java index cb77f7869..613026873 100644 --- a/src/main/java/com/gmail/nossr50/util/player/NotificationManager.java +++ b/src/main/java/com/gmail/nossr50/util/player/NotificationManager.java @@ -4,9 +4,12 @@ import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; +import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.events.skills.McMMOPlayerNotificationEvent; +import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.TextComponentFactory; +import com.gmail.nossr50.util.skills.RankUtils; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; @@ -115,4 +118,17 @@ public class NotificationManager { player.sendTitle(title, subtitle, i1, i2, i3); } } + + public static void sendPlayerUnlockNotification(McMMOPlayer mcMMOPlayer, SubSkillType subSkillType) + { + //CHAT MESSAGE + mcMMOPlayer.getPlayer().spigot().sendMessage(TextComponentFactory.getSubSkillUnlockedNotificationComponents(mcMMOPlayer.getPlayer(), subSkillType)); + + //ACTION BAR MESSAGE + /*if(AdvancedConfig.getInstance().doesNotificationUseActionBar(NotificationType.SUBSKILL_UNLOCKED)) + mcMMOPlayer.getPlayer().spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(LocaleLoader.getString("JSON.SkillUnlockMessage", + subSkillType.getLocaleName(), + String.valueOf(RankUtils.getRank(mcMMOPlayer.getPlayer(), + subSkillType)))));*/ + } } diff --git a/src/main/java/com/gmail/nossr50/util/skills/RankUtils.java b/src/main/java/com/gmail/nossr50/util/skills/RankUtils.java index a142b840d..4288771ae 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/RankUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/RankUtils.java @@ -1,16 +1,55 @@ package com.gmail.nossr50.util.skills; import com.gmail.nossr50.config.RankConfig; +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.skills.SuperAbilityType; import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill; +import com.gmail.nossr50.listeners.InteractionManager; +import com.gmail.nossr50.runnables.skills.SkillUnlockNotificationTask; import com.gmail.nossr50.util.player.UserManager; import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import java.util.ArrayList; import java.util.HashMap; public class RankUtils { - public static HashMap> subSkillRanks; + private static HashMap> subSkillRanks; + + /** + * + * @param plugin plugin instance ref + * @param mcMMOPlayer target player + * @param primarySkillType + * @param newLevel the new level of this skill + */ + public static void executeSkillUnlockNotifications(Plugin plugin, McMMOPlayer mcMMOPlayer, PrimarySkillType primarySkillType, int newLevel) + { + int count = 0; + + for(SubSkillType subSkillType : primarySkillType.getSkillAbilities()) + { + int playerRankInSkill = getRank(mcMMOPlayer.getPlayer(), subSkillType); + + HashMap innerMap = subSkillRanks.get(subSkillType.toString()); + + //If the skill doesn't have registered ranks gtfo + if(innerMap == null || innerMap.get(playerRankInSkill) == null) + return; + + //The players level is the exact level requirement for this skill + if(newLevel == innerMap.get(playerRankInSkill)) + { + SkillUnlockNotificationTask skillUnlockNotificationTask = new SkillUnlockNotificationTask(mcMMOPlayer, subSkillType, newLevel); + + skillUnlockNotificationTask.runTaskLater(plugin, ((count * 5) + 1) * 20); + + count++; + } + } + } /* NEW SYSTEM */ private static void addRanks(AbstractSubSkill abstractSubSkill) @@ -39,6 +78,22 @@ public class RankUtils { } } + /** + * Populates the ranks for every skill we know about + */ + public static void populateRanks() + { + for(SubSkillType subSkillType : SubSkillType.values()) + { + addRanks(subSkillType); + } + + for(AbstractSubSkill abstractSubSkill : InteractionManager.getSubSkillList()) + { + addRanks(abstractSubSkill); + } + } + /** * Returns whether or not the player has unlocked the first rank in target subskill * @param player the player @@ -190,8 +245,6 @@ public class RankUtils { HashMap rankMap = subSkillRanks.get(abstractSubSkill.getConfigKeyName()); - //TODO: Remove this debug code - //System.out.println("[DEBUG]: Rank "+rank+" for "+subSkillName.toString()+" requires skill level "+getRankUnlockLevel(subSkillType, rank)); rankMap.put(rank, getRankUnlockLevel(abstractSubSkill, rank)); } @@ -202,8 +255,6 @@ public class RankUtils { HashMap rankMap = subSkillRanks.get(subSkillType.toString()); - //TODO: Remove this debug code - //System.out.println("[DEBUG]: Rank "+rank+" for "+subSkillName.toString()+" requires skill level "+getRankUnlockLevel(subSkillType, rank)); rankMap.put(rank, getRankUnlockLevel(subSkillType, rank)); } diff --git a/src/main/resources/locale/locale_en_US.properties b/src/main/resources/locale/locale_en_US.properties index d4937aa5c..0c9e98945 100644 --- a/src/main/resources/locale/locale_en_US.properties +++ b/src/main/resources/locale/locale_en_US.properties @@ -46,6 +46,7 @@ JSON.URL.Patreon=Support nossr50 and his work for mcMMO on Patreon! JSON.URL.Spigot=The official mcMMO Spigot Resource Page! JSON.URL.Translation=Translate mcMMO into other languages! JSON.URL.Wiki=The official mcMMO wiki! +JSON.SkillUnlockMessage=[[GOLD]][ mcMMO[[YELLOW]] @[[DARK_AQUA]]{0} [[GOLD]]Rank [[DARK_AQUA]]{1}[[GOLD]] Unlocked! ] #This is the message sent to players when an ability is activated JSON.Notification.SuperAbility={0} @@ -95,7 +96,7 @@ XPBar.Taming=Taming Lv.[[GOLD]]{0} XPBar.Unarmed=Unarmed Lv.[[GOLD]]{0} XPBar.Woodcutting=Woodcutting Lv.[[GOLD]]{0} #This is just a preset template that gets used if the 'ExtraDetails' setting is turned on in experience.yml (off by default), you can ignore this template and just edit the strings above -XPBar.Complex.Template={0} [[GRAY]] {4}[[WHITE]]% [[GRAY]]([[WHITE]]{1}[[GRAY]]/[[WHITE]]{2}[[GRAY]]) +XPBar.Complex.Template={0} [[DARK_AQUA]] {4}[[WHITE]]% [[DARK_AQUA]]([[WHITE]]{1}[[DARK_AQUA]]/[[WHITE]]{2}[[DARK_AQUA]]) # XP BAR Allows for the following variables -- {0} = Skill Level, {1} Current XP, {2} XP Needed for next level, {3} Power Level, {4} Percentage of Level # Make sure you turn on Experience_Bars.ThisMayCauseLag.AlwaysUpdateTitlesWhenXPIsGained if you want the XP bar title to update every time a player gains XP! # END STYLING