Fix voting rewards

This commit is contained in:
NotAlexNoyle committed 2026-08-03 09:28:10 -04:00
1 parent 12b77c50ce
commit d38e70e012
9 files changed
+238 -46

No files matched your search

@@ -81,7 +81,9 @@ import com.bencodez.votingplugin.listeners.PlayerInteract;
import com.bencodez.votingplugin.listeners.PlayerJoinEvent;
import com.bencodez.votingplugin.listeners.PlayerVoteListener;
import com.bencodez.votingplugin.listeners.SignChange;
import com.bencodez.votingplugin.listeners.SurvivalRewardGate;
import com.bencodez.votingplugin.listeners.VotiferEvent;
import com.bencodez.votingplugin.listeners.WeekStreakExpBonus;
import com.bencodez.votingplugin.listeners.VotingPluginUpdateEvent;
import com.bencodez.votingplugin.objects.VoteSite;
import com.bencodez.votingplugin.placeholders.MVdWPlaceholders;
@@ -1490,6 +1492,8 @@ public class VotingPluginMain extends AdvancedCorePlugin {
pm.registerEvents(new VotiferEvent(this), this);
}
pm.registerEvents(new PlayerVoteListener(this), this);
pm.registerEvents(new SurvivalRewardGate(this), this);
pm.registerEvents(new WeekStreakExpBonus(this), this);
pm.registerEvents(new SignChange(this), this);
pm.registerEvents(new BlockBreak(this), this);
if (!plugin.getConfigFile().isDisableInteractEvent()) {
@@ -12,7 +12,6 @@ import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
@@ -78,6 +77,9 @@ import com.bencodez.votingplugin.objects.VoteSite;
import com.bencodez.votingplugin.topvoter.TopVoter;
import com.bencodez.votingplugin.user.VotingPluginUser;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
// TODO: Auto-generated Javadoc
/**
* The Class CommandLoader.
@@ -818,8 +820,10 @@ public class CommandLoader {
@Override
public void execute(CommandSender sender, String[] args) {
sender.sendMessage(ChatColor.GREEN + "UUID of player " + ChatColor.DARK_GREEN + args[1]
+ ChatColor.GREEN + " is: " + PlayerManager.getInstance().getUUID(args[1]));
sender.sendMessage(Component.text("UUID of player ", NamedTextColor.GREEN)
.append(Component.text(args[1], NamedTextColor.DARK_GREEN))
.append(Component.text(" is: " + PlayerManager.getInstance().getUUID(args[1]),
NamedTextColor.GREEN)));
}
});
@@ -830,11 +834,11 @@ public class CommandLoader {
@Override
public void execute(CommandSender sender, String[] args) {
try {
sender.sendMessage(ChatColor.GREEN + "PlayerName of player " + ChatColor.DARK_GREEN + args[1]
+ ChatColor.GREEN + " is: "
+ PlayerManager.getInstance().getPlayerName(
sender.sendMessage(Component.text("PlayerName of player ", NamedTextColor.GREEN)
.append(Component.text(args[1], NamedTextColor.DARK_GREEN))
.append(Component.text(" is: " + PlayerManager.getInstance().getPlayerName(
plugin.getVotingPluginUserManager().getVotingPluginUser(UUID.fromString(args[1])),
args[1]));
args[1]), NamedTextColor.GREEN)));
} catch (IllegalArgumentException e) {
sendMessage(sender, "&cInvalid uuid");
}
@@ -23,7 +23,8 @@ import com.bencodez.votingplugin.VotingPluginMain;
import com.bencodez.votingplugin.topvoter.TopVoterPlayer;
import com.bencodez.votingplugin.user.VotingPluginUser;
import net.md_5.bungee.api.ChatColor;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
public class VoteTopVoterPreviousMonths extends GUIHandler {
@@ -68,18 +69,19 @@ public class VoteTopVoterPreviousMonths extends GUIHandler {
if (!yearMonthList.isEmpty()) {
yearMonth = yearMonthList.get(0);
}
player.sendMessage(ChatColor.RED + "Can't open previous months, no data");
player.sendMessage(Component.text("Can't open previous months, no data", NamedTextColor.RED));
return;
}
if (yearMonthList.size() <= index) {
player.sendMessage(ChatColor.RED + "Can't open previous months, no data for requested index");
player.sendMessage(
Component.text("Can't open previous months, no data for requested index", NamedTextColor.RED));
return;
}
yearMonth = yearMonthList.get(index);
Set<Entry<TopVoterPlayer, Integer>> users = null;
if (!plugin.getPreviousMonthsTopVoters().containsKey(yearMonth)) {
player.sendMessage(ChatColor.RED + "Can't open previous months, no data");
player.sendMessage(Component.text("Can't open previous months, no data", NamedTextColor.RED));
return;
}
users = plugin.getPreviousMonthsTopVoters().get(yearMonth).entrySet();
@@ -7,7 +7,6 @@ import java.util.Collections;
import java.util.Comparator;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -213,7 +212,7 @@ public class ConfigVoteSites extends YMLFile {
try {
data.save(dFile);
} catch (IOException e) {
plugin.getLogger().severe(ChatColor.RED + "Could not create VoteSites/" + siteName + ".yml!");
plugin.getLogger().severe("Could not create VoteSites/" + siteName + ".yml!");
}
}
@@ -0,0 +1,103 @@
package com.bencodez.votingplugin.listeners;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import com.bencodez.advancedcore.api.user.AdvancedCoreUser;
import com.bencodez.advancedcore.listeners.PlayerRewardEvent;
import com.bencodez.votingplugin.VotingPluginMain;
import com.bencodez.votingplugin.user.VotingPluginUser;
// Rewards given outside survival in the main worlds get wiped by
// GameModeInventories' per-gamemode XP/inventory swap or land in the wrong
// context, so bank them until the player is eligible again.
public class SurvivalRewardGate implements Listener {
private static final Set<String> REWARD_WORLDS = Set.of("world", "world_nether", "world_the_end");
private static final long NOTICE_THROTTLE_MILLIS = 30000L;
static boolean eligibleForRewards(Player player) {
return player.getGameMode() == GameMode.SURVIVAL && REWARD_WORLDS.contains(player.getWorld().getName());
}
private final VotingPluginMain plugin;
private final ConcurrentHashMap<UUID, Long> lastBankNotice = new ConcurrentHashMap<>();
public SurvivalRewardGate(VotingPluginMain plugin) {
this.plugin = plugin;
}
// Fires on an async thread; PlayerRewardEvent does not implement Cancellable
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerReward(PlayerRewardEvent event) {
if (event.isCancelled()) {
return;
}
AdvancedCoreUser user = event.getPlayer();
if (user == null) {
return;
}
Player player = user.getPlayer();
if (player == null) {
// truly offline: stock offline handling applies
return;
}
if (eligibleForRewards(player)) {
return;
}
event.setCancelled(true);
user.addOfflineRewards(event.getReward(), event.getRewardOptions().getPlaceholders());
plugin.debug("Banked reward " + event.getReward().getRewardName() + " for " + user.getPlayerName()
+ " until survival in a main world");
notifyBanked(player);
}
private void notifyBanked(Player player) {
long now = System.currentTimeMillis();
Long last = lastBankNotice.put(player.getUniqueId(), now);
if (last != null && now - last < NOTICE_THROTTLE_MILLIS) {
return;
}
plugin.getLogger().info(player.getName() + " has vote rewards banked until survival in a main world");
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onGameModeChange(PlayerGameModeChangeEvent event) {
if (event.getNewGameMode() != GameMode.SURVIVAL) {
return;
}
scheduleReplay(event.getPlayer().getUniqueId());
}
@EventHandler(priority = EventPriority.MONITOR)
public void onWorldChange(PlayerChangedWorldEvent event) {
scheduleReplay(event.getPlayer().getUniqueId());
}
private void scheduleReplay(UUID uuid) {
// 1 tick later the change is applied and GameModeInventories' restore has settled
Bukkit.getScheduler().runTaskLater(plugin, () -> {
Player player = Bukkit.getPlayer(uuid);
if (player == null || !player.isOnline() || !eligibleForRewards(player)) {
return;
}
// reward replay fires the async PlayerRewardEvent, so hop off the main thread
plugin.getLoginTimer().execute(() -> {
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(player);
user.offVote();
user.checkOfflineRewards();
});
}, 1L);
}
}
@@ -0,0 +1,91 @@
package com.bencodez.votingplugin.listeners;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import com.bencodez.advancedcore.api.rewards.Reward;
import com.bencodez.advancedcore.api.user.AdvancedCoreUser;
import com.bencodez.advancedcore.listeners.PlayerRewardEvent;
import com.bencodez.votingplugin.VotingPluginMain;
import com.bencodez.votingplugin.user.VotingPluginUser;
import net.kyori.adventure.text.minimessage.MiniMessage;
// Each full week of voting every day adds a bonus level on top of the per-site
// EXPLevels reward, capping the streak credit at MAX_WEEKS; missing a day
// resets the day streak and with it the bonus.
public class WeekStreakExpBonus implements Listener {
private static final String SITE_REWARD_PREFIX = "VoteSites.";
private static final String SITE_REWARD_SUFFIX = ".Rewards";
private static final int BASE_LEVELS = 15;
private static final int MAX_WEEKS = 52;
private static final int DAYS_PER_WEEK = 7;
private final VotingPluginMain plugin;
public WeekStreakExpBonus(VotingPluginMain plugin) {
this.plugin = plugin;
}
// Runs after SurvivalRewardGate (HIGHEST); a banked reward arrives cancelled
// here and earns its bonus when the replay passes the gate
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerReward(PlayerRewardEvent event) {
if (event.isCancelled()) {
return;
}
Reward reward = event.getReward();
if (reward == null || reward.getRewardName() == null) {
return;
}
String name = reward.getRewardName();
if (!name.startsWith(SITE_REWARD_PREFIX) || !name.endsWith(SITE_REWARD_SUFFIX)) {
return;
}
AdvancedCoreUser acUser = event.getPlayer();
if (acUser == null) {
return;
}
Player player = acUser.getPlayer();
if (player == null || !SurvivalRewardGate.eligibleForRewards(player)) {
return;
}
final UUID uuid = player.getUniqueId();
// async event; XP must change on the main thread
Bukkit.getScheduler().runTask(plugin, () -> {
Player target = Bukkit.getPlayer(uuid);
if (target == null || !target.isOnline() || !SurvivalRewardGate.eligibleForRewards(target)) {
return;
}
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(target);
int dayStreak = user.getDayVoteStreak();
int weeks = dayStreak / DAYS_PER_WEEK;
int bonus = Math.min(weeks, MAX_WEEKS);
if (bonus > 0) {
target.giveExpLevels(bonus);
plugin.debug("Week streak bonus: +" + bonus + " levels for " + target.getName());
}
target.sendMessage(MiniMessage.miniMessage().deserialize(buildMessage(dayStreak, weeks, bonus)));
});
}
private String buildMessage(int dayStreak, int weeks, int bonus) {
int total = BASE_LEVELS + bonus;
if (bonus > 0) {
return "<green>+" + total + " XP levels <gray>(" + weeks
+ " week streak <dark_gray>-</dark_gray> vote every day to keep it)";
}
if (dayStreak > 0) {
return "<green>+" + total + " XP levels <gray>(" + dayStreak + "/" + DAYS_PER_WEEK
+ " days to your first bonus level)";
}
return "<green>+" + total + " XP levels <gray>(vote every day for a week to earn bonus XP)";
}
}
@@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
@@ -18,6 +17,9 @@ import com.bencodez.simpleapi.messages.MessageAPI;
import com.bencodez.votingplugin.VotingPluginMain;
import com.bencodez.votingplugin.user.VotingPluginUser;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import lombok.Getter;
import lombok.Setter;
@@ -178,8 +180,8 @@ public class VoteSite {
}
public String getVoteURLJsonStrip() {
String url = ChatColor
.stripColor(MessageAPI.colorize(PlaceholderUtils.parseJson(getVoteURL(false)).toPlainText()));
String url = PlainTextComponentSerializer.plainText().serialize(LegacyComponentSerializer.legacySection()
.deserialize(MessageAPI.colorize(PlaceholderUtils.parseJson(getVoteURL(false)).toPlainText())));
if (!url.startsWith("http")) {
if (!url.startsWith("www.")) {
url = "https://www." + url;
+15 -26
View File
@@ -5,9 +5,7 @@
# Rewards will be given if there is a reward to give, otherwise they will be ignored
# First vote rewards
FirstVote:
Messages:
Player: '&aYou voted for your first time!'
FirstVote: {}
# First vote of the day reward
FirstVoteToday: {}
@@ -15,9 +13,7 @@ FirstVoteToday: {}
# All vote rewards
# One time reward for voting on all sites in one day
# Enable ExtraAllSitesCheck if you get double rewards
AllSites:
Messages:
Player: '&aYou voted on all sites in 1 day!'
AllSites: {}
# Give a reward for voting on all sites minus 1
# Similar to allsites
@@ -60,7 +56,7 @@ Cumulative:
# Vote party configuration
VoteParty:
Enabled: true
Enabled: false
VotesRequired: 50
GiveAllPlayers: false
GiveOnlinePlayersOnly: true
@@ -79,38 +75,34 @@ VoteParty:
VoteReminderAtVotes: []
GlobalCommands: []
GlobalRandomCommand: []
Rewards:
Commands:
- 'xp give %player% 50L'
Rewards:
EXPLevels: 50
ResetMilestonesMonthly: false
MileStones:
'100':
Enabled: true
Enabled: false
Rewards:
Messages:
Player: '&aYou reached the 100 votes milestone!'
Commands:
- 'xp give %player% 100L'
EXPLevels: 100
VoteStreak:
Day:
'7':
Enabled: true
Enabled: false
Rewards:
Messages:
Player: "&aYou voted for 7 Days in a row!"
Commands:
- 'xp give %player% 50L'
EXPLevels: 50
Week:
'4':
Enabled: true
Enabled: false
Rewards:
Messages:
Player: "&aYou voted for 4 Weeks in a row!"
Commands:
- 'xp give %player% 200L'
EXPLevels: 200
Month:
'2':
Enabled: false
@@ -147,7 +139,7 @@ LoginRewards: {}
# Will queue until player logs in unless forceoffline is enabled
LogoutRewards: {}
EnableMonthlyAwards: true
EnableMonthlyAwards: false
MonthlyAwards:
1:
@@ -158,8 +150,7 @@ MonthlyAwards:
DIAMOND_BLOCK:
Material: 'DIAMOND_BLOCK'
Amount: 5
Commands:
- 'xp give %player% 500L'
EXPLevels: 500
2:
Rewards:
Messages:
@@ -168,8 +159,7 @@ MonthlyAwards:
DIAMOND_BLOCK:
Material: 'DIAMOND_BLOCK'
Amount: 3
Commands:
- 'xp give %player% 300L'
EXPLevels: 300
3:
Rewards:
Messages:
@@ -178,8 +168,7 @@ MonthlyAwards:
DIAMOND_BLOCK:
Material: 'DIAMOND_BLOCK'
Amount: 1
Commands:
- 'xp give %player% 100L'
EXPLevels: 100
EnableWeeklyAwards: false
# Rewards to give on weekly top voter
+2 -4
View File
@@ -14,8 +14,7 @@ VoteSites:
Material: 'DIAMOND'
Amount: 1
Rewards:
Commands:
- 'xp give %player% 15L'
EXPLevels: 15
Messages:
Player: '&aThank you for voting on MinecraftServerList!'
@@ -34,8 +33,7 @@ VoteSites:
Material: 'EMERALD'
Amount: 1
Rewards:
Commands:
- 'xp give %player% 15L'
EXPLevels: 15
Messages:
Player: '&aThank you for voting on MinecraftServersGG!'