From b48a3801026736d4c52bf2cb1fb2f848d436129f Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 28 Jul 2026 16:33:14 -0600 Subject: [PATCH] Add rewards for votes rejected by vote delay --- .../bencodez/votingplugin/BungeeHandler.java | 43 +++++++++++++++++++ .../votingplugin/VotingPluginMain.java | 23 ++++++++++ .../votingplugin/config/ConfigVoteSites.java | 35 +++++++++++++++ .../listeners/PlayerVoteListener.java | 7 +++ .../votingplugin/proxy/VotingPluginProxy.java | 12 ++++++ .../votingplugin/proxy/VotingPluginWire.java | 26 +++++++++++ .../votingplugin/votesites/VoteSite.java | 16 +++++++ VotingPlugin/src/main/resources/VoteSites.yml | 6 +++ .../tests/VotingPluginWireTest.java | 15 +++++++ 9 files changed, 183 insertions(+) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/BungeeHandler.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/BungeeHandler.java index b9da73c96..16508014b 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/BungeeHandler.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/BungeeHandler.java @@ -272,6 +272,12 @@ public void onReceive(JsonEnvelope msg) { } }); + globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_DELAY_REJECTED) { + @Override + public void onReceive(JsonEnvelope msg) { + handleWireVoteDelayRejected(msg); + } + }); globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_UPDATE) { @Override public void onReceive(JsonEnvelope msg) { @@ -557,6 +563,43 @@ private static long readLongSafe(String v, long def) { } } + private void handleWireVoteDelayRejected(JsonEnvelope msg) { + if (msg.getSchema() != VotingPluginWire.SCHEMA_VERSION) { + plugin.getLogger().warning("Incompatible version with bungee/proxy, please update all servers: " + + msg.getSchema() + " != " + VotingPluginWire.SCHEMA_VERSION); + return; + } + + if (!plugin.getOptions().isProcessRewards()) { + return; + } + + VotingPluginWire.VoteDelayRejected rejected = VotingPluginWire.readVoteDelayRejected(msg); + if (rejected.uuid.isEmpty() || rejected.service.isEmpty()) { + return; + } + + UUID javaUuid; + try { + javaUuid = UUID.fromString(rejected.uuid); + } catch (IllegalArgumentException e) { + plugin.getLogger().warning("Invalid UUID in VoteDelayRejected: " + rejected.uuid); + return; + } + + VoteSite voteSite = plugin.getVoteSiteManager() + .getVoteSite(plugin.getVoteSiteManager().getVoteSiteName(true, rejected.service), true); + if (voteSite == null) { + plugin.getLogger().warning("No voting site with the service site: '" + rejected.service + "'"); + return; + } + + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(javaUuid, rejected.player); + user.cache(); + user.updateName(true); + voteSite.giveWaitUntilVoteDelayRewards(user, rejected.wasOnline && user.isOnline(), true); + } + /** * Wire vote handler (Vote + VoteOnline). */ diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java index 529db8dcb..d0c238f40 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java @@ -854,6 +854,29 @@ public void setData(String path, Object value) { } }); + addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteSites." + site.getKey() + ".WaitUntilVoteDelayRewards") { + + @Override + public void createSection(String key) { + getConfigVoteSites().createSection(key); + } + + @Override + public ConfigurationSection getFileData() { + return getConfigVoteSites().getData(); + } + + @Override + public void save() { + getConfigVoteSites().saveData(); + } + + @Override + public void setData(String path, Object value) { + getConfigVoteSites().setValue(path, value); + } + }); + addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteSites." + site.getKey() + ".CoolDownEndRewards") { @Override diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/ConfigVoteSites.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/ConfigVoteSites.java index ffffe1500..5188c9b2f 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/ConfigVoteSites.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/ConfigVoteSites.java @@ -60,6 +60,7 @@ public void generateVoteSite(String siteName) { set(siteName, "DisplayItem.Material", "STONE"); set(siteName, "DisplayItem.Amount", 1); set(siteName, "Rewards.Messages.Player", "&aThanks for voting on %ServiceSite%!"); + set(siteName, "WaitUntilVoteDelayRewards", Collections.emptyMap()); plugin.loadVoteSites(); @@ -86,6 +87,30 @@ public void setData(String path, Object value) { } }); + plugin.addDirectlyDefinedRewards( + new DirectlyDefinedReward("VoteSites." + siteName + ".WaitUntilVoteDelayRewards") { + + @Override + public void createSection(String key) { + plugin.getConfigVoteSites().createSection(key); + } + + @Override + public ConfigurationSection getFileData() { + return plugin.getConfigVoteSites().getData(); + } + + @Override + public void save() { + plugin.getConfigVoteSites().saveData(); + } + + @Override + public void setData(String path, Object value) { + plugin.getConfigVoteSites().setValue(path, value); + } + }); + plugin.addDirectlyDefinedRewards( new DirectlyDefinedReward("VoteSites." + siteName + ".CoolDownEndRewards") { @@ -194,6 +219,16 @@ public String getRewardsPath(String siteName) { return "VoteSites." + siteName + ".Rewards"; } + /** + * Gets the rewards path used when a vote is rejected by WaitUntilVoteDelay. + * + * @param siteName the site name + * @return the wait-until-vote-delay rewards path + */ + public String getWaitUntilVoteDelayRewardsPath(String siteName) { + return "VoteSites." + siteName + ".WaitUntilVoteDelayRewards"; + } + /** * Gets the service site. * diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerVoteListener.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerVoteListener.java index 8f9527b1e..b7234a14b 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerVoteListener.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerVoteListener.java @@ -153,6 +153,13 @@ public void onplayerVote(PlayerVoteEvent event) { } else { if (!user.hasPermission("VotingPlugin.BypassWaitUntilVoteDelay")) { plugin.getLogger().info(user.getPlayerName() + " must wait until votedelay is over, ignoring vote"); + boolean online = user.isOnline(); + if (event.isBungee()) { + online = event.isWasOnline(); + } + if (plugin.getOptions().isProcessRewards()) { + voteSite.giveWaitUntilVoteDelayRewards(user, online, event.isBungee()); + } return; } plugin.getLogger() diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxy.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxy.java index cb4cd8fd6..c7d15c4d4 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxy.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginProxy.java @@ -1499,6 +1499,17 @@ public void status() { } } + private void sendVoteDelayRejected(String player, String uuid, String service, boolean playerOnline, + String playerServer) { + if (!playerOnline || playerServer == null || !getAllAvailableServers().contains(playerServer)) { + debug("Not sending vote delay rejection for " + player + " because the player is offline"); + return; + } + + globalMessageProxyHandler.sendMessage(playerServer, 1, + VotingPluginWire.voteDelayRejected(player, uuid, service, true)); + } + public String getWaitUntilDelaySiteFromService(String service) { for (String site : getConfig().getWaitUntilVoteDelaySites()) { if (getConfig().getWaitUntilVoteDelayService(site).equalsIgnoreCase(service)) { @@ -1718,6 +1729,7 @@ private synchronized void vote(String player, String service, boolean realVote, if (!checkVoteDelay(uuid, service, data)) { log("Vote delay is not met for " + player + "/" + service + ", skipping vote"); + sendVoteDelayRejected(player, uuid, service, playerOnline, playerServer); return; } diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginWire.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginWire.java index faf989cac..d1e2da386 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginWire.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/proxy/VotingPluginWire.java @@ -31,6 +31,7 @@ private VotingPluginWire() { public static final String SUB_VOTE = "Vote"; public static final String SUB_VOTE_ONLINE = "VoteOnline"; public static final String SUB_VOTE_UPDATE = "VoteUpdate"; + public static final String SUB_VOTE_DELAY_REJECTED = "VoteDelayRejected"; public static final String SUB_VOTE_BROADCAST = "VoteBroadcast"; public static final String SUB_BUNGEE_TIME_CHANGE = "BungeeTimeChange"; @@ -108,6 +109,11 @@ public static JsonEnvelope voteOnline(String player, String uuid, String service .put(K_NUM, num).put(K_NUMBER_OF_VOTES, numberOfVotes).build(); } + public static JsonEnvelope voteDelayRejected(String player, String uuid, String service, boolean wasOnline) { + return base(SUB_VOTE_DELAY_REJECTED).put(K_PLAYER, safe(player)).put(K_UUID, safe(uuid)) + .put(K_SERVICE, safe(service)).put(K_WAS_ONLINE, wasOnline).build(); + } + public static JsonEnvelope voteBroadcast(String uuid, String player, String service, long time, String totals) { return base(SUB_VOTE_BROADCAST).put(K_UUID, safe(uuid)).put(K_PLAYER, safe(player)) .put(K_SERVICE, safe(service)).put(K_TIME, time).put(K_TOTALS, safe(totals)).build(); @@ -232,6 +238,26 @@ public static Vote readVote(JsonEnvelope env) { broadcast, num, numberOfVotes); } + public static final class VoteDelayRejected { + public final String player; + public final String uuid; + public final String service; + public final boolean wasOnline; + + private VoteDelayRejected(String player, String uuid, String service, boolean wasOnline) { + this.player = player; + this.uuid = uuid; + this.service = service; + this.wasOnline = wasOnline; + } + } + + public static VoteDelayRejected readVoteDelayRejected(JsonEnvelope env) { + Map f = env.getFields(); + return new VoteDelayRejected(safe(f.get(K_PLAYER)), safe(f.get(K_UUID)), safe(f.get(K_SERVICE)), + readBool(f, K_WAS_ONLINE, false)); + } + public static final class VoteUpdate { public final String uuid; public final int votePartyCurrent; diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSite.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSite.java index 8d52e3458..89ca8d2ce 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSite.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSite.java @@ -141,6 +141,22 @@ public void giveRewards(VotingPluginUser user, boolean online, boolean bungee) { } + /** + * Gives rewards configured for a vote rejected by WaitUntilVoteDelay. + * + * @param user the voting user + * @param online whether the player was online when the vote was received + * @param bungee whether the vote came through the proxy + */ + public void giveWaitUntilVoteDelayRewards(VotingPluginUser user, boolean online, boolean bungee) { + new RewardBuilder(plugin.getConfigVoteSites().getData(), + plugin.getConfigVoteSites().getWaitUntilVoteDelayRewardsPath(key)).setOnline(online) + .withPlaceHolder("ServiceSite", getServiceSite()) + .withPlaceHolder("SiteName", getDisplayName()) + .withPlaceHolder("VoteDelay", "" + getVoteDelay()) + .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); + } + public boolean hasRewards() { return plugin.getRewardHandler().hasRewards(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getRewardsPath(key)); diff --git a/VotingPlugin/src/main/resources/VoteSites.yml b/VotingPlugin/src/main/resources/VoteSites.yml index 9e72fe825..4db6ef5ea 100644 --- a/VotingPlugin/src/main/resources/VoteSites.yml +++ b/VotingPlugin/src/main/resources/VoteSites.yml @@ -99,6 +99,12 @@ VoteSites: # Recommend: false WaitUntilVoteDelay: false + # Reward to run when a real vote is rejected because VoteDelay has not ended + # This supports standard rewards and the placeholders %ServiceSite%, %SiteName%, %VoteDelay%, and %VoteURL% + #WaitUntilVoteDelayRewards: + # Messages: + # Player: '&cYour vote was not accepted because the vote delay has not ended.' + # Reset vote delay each day (for certain sites that do this) # Recommend: false VoteDelayDaily: false diff --git a/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/VotingPluginWireTest.java b/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/VotingPluginWireTest.java index f4ea5dbed..78c0a3534 100644 --- a/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/VotingPluginWireTest.java +++ b/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/VotingPluginWireTest.java @@ -10,6 +10,7 @@ import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; import com.bencodez.votingplugin.proxy.VotingPluginWire; import com.bencodez.votingplugin.proxy.VotingPluginWire.Vote; +import com.bencodez.votingplugin.proxy.VotingPluginWire.VoteDelayRejected; /** * Tests proxy vote wire encoding and decoding. @@ -39,4 +40,18 @@ public void voteOnlineRoundTripAllowsMissingVoteId() { assertNull(vote.voteId); } + + @Test + public void voteDelayRejectedRoundTripPreservesContext() { + String uuid = UUID.randomUUID().toString(); + JsonEnvelope envelope = VotingPluginWire.voteDelayRejected("Player", uuid, "Service", true); + + VoteDelayRejected rejected = VotingPluginWire.readVoteDelayRejected(envelope); + + assertEquals(VotingPluginWire.SUB_VOTE_DELAY_REJECTED, envelope.getSubChannel()); + assertEquals("Player", rejected.player); + assertEquals(uuid, rejected.uuid); + assertEquals("Service", rejected.service); + assertEquals(true, rejected.wasOnline); + } }