Explorar o código

Add broadcasting when players reach certain level milestones (defaults to every 100 levels)

nossr50 %!s(int64=4) %!d(string=hai) anos
pai
achega
f38d92497a

+ 4 - 0
Changelog.txt

@@ -1,5 +1,9 @@
 Version 2.1.171
     Axes can now replant cocoa plants (thanks Lyther)
+    Players who level up at certain milestones have their level ups broadcast to the server (very configurable and optional, see notes)
+    Added Level_Up_Chat_Broadcasts settings to config.yml under General
+    New locale string 'Broadcasts.LevelUpMilestone'
+
 Version 2.1.170
     Reverted a change that broke compatibility with the mcMMO papi ecloud thingy
 

+ 10 - 1
src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java

@@ -1,11 +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.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.Permissions;
+import com.gmail.nossr50.util.player.UserManager;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 
@@ -30,7 +32,14 @@ public class AddlevelsCommand extends ExperienceCommand {
             return;
         }
 
-        EventUtils.tryLevelChangeEvent(player, skill, value, xpRemoved, true, XPGainReason.COMMAND);
+        McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
+
+        if(mmoPlayer == null) {
+            EventUtils.tryLevelChangeEvent(player, skill, value, xpRemoved, true, XPGainReason.COMMAND);
+        } else {
+            EventUtils.tryLevelChangeEvent(mmoPlayer, skill, value, xpRemoved, true, XPGainReason.COMMAND);
+        }
+
     }
 
     @Override

+ 10 - 1
src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java

@@ -1,11 +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.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.Permissions;
+import com.gmail.nossr50.util.player.UserManager;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 
@@ -36,7 +38,14 @@ public class MmoeditCommand extends ExperienceCommand {
             return;
         }
 
-        EventUtils.tryLevelEditEvent(player, skill, 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, skill, value, xpRemoved, value > skillLevel, XPGainReason.COMMAND, skillLevel);
+        }
+
     }
 
     @Override

+ 8 - 0
src/main/java/com/gmail/nossr50/config/Config.java

@@ -581,4 +581,12 @@ 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); }
+
 }

+ 100 - 0
src/main/java/com/gmail/nossr50/datatypes/LevelUpBroadcastPredicate.java

@@ -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 +
+                '}';
+    }
+}

+ 1 - 1
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -652,7 +652,7 @@ public class McMMOPlayer implements Identified {
             levelsGained++;
         }
 
-        if (EventUtils.tryLevelChangeEvent(player, primarySkillType, levelsGained, xpRemoved, true, xpGainReason)) {
+        if (EventUtils.tryLevelChangeEvent(this, primarySkillType, levelsGained, xpRemoved, true, xpGainReason)) {
             return;
         }
 

+ 37 - 0
src/main/java/com/gmail/nossr50/util/EventUtils.java

@@ -32,6 +32,7 @@ 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;
@@ -232,6 +233,24 @@ 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));
+            }
+        }
+
+        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);
@@ -248,6 +267,24 @@ 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));
+            }
+        }
+
+        return isCancelled;
+    }
+
     /**
      * Simulate a block break event.
      *

+ 43 - 0
src/main/java/com/gmail/nossr50/util/player/NotificationManager.java

@@ -2,6 +2,7 @@ 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.interactions.NotificationType;
 import com.gmail.nossr50.datatypes.notifications.SensitiveCommandType;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
@@ -19,14 +20,23 @@ 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;
 import org.bukkit.SoundCategory;
 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
@@ -256,4 +266,37 @@ public class NotificationManager {
         return newArray;
     }
 
+    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()) {
+            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.toString());
+                Component message = Component.text(localeMessage).hoverEvent(levelMilestoneHover);
+
+                audience.sendMessage(Identity.nil(), message);
+            }
+        }
+    }
+
+    //TODO: Could cache
+    public static @NotNull LevelUpBroadcastPredicate<CommandSender> getLevelUpBroadcastPredicate(@NotNull CommandSender levelUpPlayer) {
+        return new LevelUpBroadcastPredicate<>(levelUpPlayer);
+    }
+
 }

+ 18 - 0
src/main/resources/config.yml

@@ -8,6 +8,24 @@
 #  Settings for mcMMO in general
 ###
 General:
+    # When players reach certain level milestones messages will be broadcast
+    Level_Up_Chat_Broadcasts:
+        # Whether or not level up broadcasts are enabled
+        Enabled: true
+        # How often to broadcast, you can change this to 1 to always broadcast a level up event, a setting of 100 will limit it to every 100 levels (for example level 100, level 200, etc)
+        Milestone_Interval: 100
+        Broadcast_Targets:
+            # Send the message to the console as well
+            Send_To_Console: true
+            # Whether or not to only send chat messages to party members
+            Only_Party_Members: false
+            # Whether or not players who recieve a level up broadcast have to be on the same world as the one who leveled up
+            Only_Same_World: false
+            # Distance restrictions
+            Distance_Restrictions:
+                Restrict_Distance: false
+                # When using Restrict_Distance the blow setting configures the range of the broadcast
+                Restricted_Radius: 100
         # Turning this on will scale mcMMO around 1-1000 with default scaling factor
         # Everything in your config related to skill level requirements, skill level bonuses, etc will be multiplied by 10 when this mode is on
         # This change is purely cosmetic, it retains the old feel of mcMMO where you could level up thousands of times

+ 2 - 1
src/main/resources/locale/locale_en_US.properties

@@ -1135,4 +1135,5 @@ Chat.Style.Party.Leader=&a(P) &r{0} &6\u2192 &r{1}
 Chat.Identity.Console=&6* Console *
 Chat.Channel.On=&6(&amcMMO-Chat&6) &eYour chat messages will now be automatically delivered to the &a{0}&e chat channel.
 Chat.Channel.Off=&6(&amcMMO-Chat&6) &7Your chat messages will no longer be automatically delivered to specific chat channels.
-Chat.Spy.Party=&6[&eSPY&6-&a{2}&6] &r{0} &b\u2192 &r{1}
+Chat.Spy.Party=&6[&eSPY&6-&a{2}&6] &r{0} &b\u2192 &r{1}
+Broadcasts.LevelUpMilestone=&6(&amcMMO&6) {0}&7 has reached level &a{1}&7 in [[DARK_AQUA]]{2}&7!