From 5205dee4f35f039f1e45417fa60c48f60b86141d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:08:52 -0600 Subject: [PATCH 01/71] Extract backend processed vote cache --- .../cache/ProcessedVoteCache.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/cache/ProcessedVoteCache.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/cache/ProcessedVoteCache.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/cache/ProcessedVoteCache.java new file mode 100644 index 0000000000..0fae384443 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/cache/ProcessedVoteCache.java @@ -0,0 +1,60 @@ +package com.bencodez.votingplugin.backendproxy.cache; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import lombok.Getter; + +/** + * Tracks recently processed proxy vote ids so duplicate delivery is ignored. + */ +public class ProcessedVoteCache { + + private static final long DEFAULT_TTL_MILLIS = TimeUnit.MINUTES.toMillis(30); + + @Getter + private final ConcurrentHashMap processedVotes = new ConcurrentHashMap<>(); + private final long ttlMillis; + + public ProcessedVoteCache() { + this(DEFAULT_TTL_MILLIS); + } + + public ProcessedVoteCache(long ttlMillis) { + this.ttlMillis = ttlMillis; + } + + public boolean reserve(UUID voteId) { + if (voteId == null) { + return true; + } + + long now = System.currentTimeMillis(); + long expiresAt = now + ttlMillis; + + while (true) { + Long currentExpiry = processedVotes.get(voteId); + if (currentExpiry == null) { + if (processedVotes.putIfAbsent(voteId, expiresAt) == null) { + cleanup(now); + return true; + } + continue; + } + + if (currentExpiry > now) { + return false; + } + + if (processedVotes.replace(voteId, currentExpiry, expiresAt)) { + cleanup(now); + return true; + } + } + } + + private void cleanup(long now) { + processedVotes.entrySet().removeIf(entry -> entry.getValue() <= now); + } +} From 211919e976b9f6c9ec99c61468fb3610a5a88a7d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:09:03 -0600 Subject: [PATCH 02/71] Extract backend vote party sync state --- .../voteparty/BackendVotePartySync.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/voteparty/BackendVotePartySync.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/voteparty/BackendVotePartySync.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/voteparty/BackendVotePartySync.java new file mode 100644 index 0000000000..87c10392f4 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/voteparty/BackendVotePartySync.java @@ -0,0 +1,64 @@ +package com.bencodez.votingplugin.backendproxy.voteparty; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.misc.MiscUtils; +import com.bencodez.advancedcore.api.rewards.RewardBuilder; +import com.bencodez.votingplugin.VotingPluginMain; + +import lombok.Getter; + +/** + * Owns backend-side cached proxy vote-party state and proxy vote-party events. + */ +public class BackendVotePartySync { + + private final VotingPluginMain plugin; + + @Getter + private int current; + @Getter + private int required; + + public BackendVotePartySync(VotingPluginMain plugin) { + this.plugin = plugin; + current = plugin.getServerData().getBungeeVotePartyCurrent(); + required = plugin.getServerData().getBungeeVotePartyRequired(); + } + + public void update(int votePartyCurrent, int votePartyRequired) { + if (votePartyCurrent >= 0 || current == -2) { + current = votePartyCurrent; + } + if (votePartyRequired >= 0 || required == -2) { + required = votePartyRequired; + } + persist(); + } + + public void replace(int votePartyCurrent, int votePartyRequired) { + current = votePartyCurrent; + required = votePartyRequired; + persist(); + } + + public void persist() { + plugin.getServerData().setBungeeVotePartyCurrent(current); + plugin.getServerData().setBungeeVotePartyRequired(required); + } + + public void runGlobalRewards() { + for (final String command : plugin.getBungeeSettings().getBungeeVotePartyGlobalCommands()) { + plugin.getBukkitScheduler().runTask(plugin, + () -> Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command)); + } + for (Player player : Bukkit.getOnlinePlayers()) { + new RewardBuilder(plugin.getBungeeSettings().getData(), "BungeeVotePartyRewards").send(player); + } + } + + public void broadcast(String message) { + MiscUtils.getInstance().broadcast(message); + } +} From ef0dfc6b067aa2ac431930244ea0b70aac382756 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:09:23 -0600 Subject: [PATCH 03/71] Extract backend global data sync --- .../global/BackendGlobalDataSync.java | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/global/BackendGlobalDataSync.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/global/BackendGlobalDataSync.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/global/BackendGlobalDataSync.java new file mode 100644 index 0000000000..adaaee969a --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/global/BackendGlobalDataSync.java @@ -0,0 +1,175 @@ +package com.bencodez.votingplugin.backendproxy.global; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import com.bencodez.advancedcore.api.time.TimeType; +import com.bencodez.advancedcore.api.user.UserStorage; +import com.bencodez.advancedcore.bungeeapi.globaldata.GlobalDataHandler; +import com.bencodez.advancedcore.bungeeapi.globaldata.GlobalMySQL; +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.sql.data.DataValue; +import com.bencodez.simpleapi.sql.data.DataValueBoolean; +import com.bencodez.simpleapi.sql.mysql.config.MysqlConfigSpigot; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.proxy.VotingPluginWire; + +import lombok.Getter; + +/** + * Owns backend global-data polling and proxy-driven time-change processing. + */ +public class BackendGlobalDataSync { + + private final VotingPluginMain plugin; + private final Consumer sender; + + @Getter + private GlobalDataHandler globalDataHandler; + @Getter + private ScheduledExecutorService timer; + + public BackendGlobalDataSync(VotingPluginMain plugin, Consumer sender) { + this.plugin = plugin; + this.sender = sender; + } + + public void checkGlobalData() { + if (globalDataHandler == null) { + return; + } + HashMap data = globalDataHandler.getExact(plugin.getBungeeSettings().getServer()); + + if (data.containsKey("ForceUpdate") && checkGlobalDataTimeValue(data.get("ForceUpdate"))) { + if (plugin.getStorageType().equals(UserStorage.MYSQL)) { + plugin.getMysql().clearCacheBasic(); + } + plugin.getUserManager().getDataManager().clearCache(); + plugin.setUpdate(true); + plugin.update(); + globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), "ForceUpdate", false); + } + + boolean forceUpdate = checkGlobalDataTime(TimeType.MONTH, data); + forceUpdate |= checkGlobalDataTime(TimeType.WEEK, data); + forceUpdate |= checkGlobalDataTime(TimeType.DAY, data); + + if (forceUpdate) { + HashMap dataToSet = new HashMap<>(); + dataToSet.put("FinishedProcessing", new DataValueBoolean(true)); + dataToSet.put("Processing", new DataValueBoolean(false)); + globalDataHandler.setData(plugin.getBungeeSettings().getServer(), dataToSet); + } + } + + public boolean checkGlobalDataTime(TimeType type, HashMap data) { + if (!data.containsKey(type.toString()) || !checkGlobalDataTimeValue(data.get(type.toString()))) { + return false; + } + + long lastUpdated = Long.valueOf(data.get("LastUpdated").getString()).longValue(); + plugin.debug("LastUpdated: " + lastUpdated); + if (LocalDateTime.now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli() - lastUpdated > 1000 * 60 * 60 * 2) { + plugin.getLogger().warning("Ignoring bungee time change since it was more than 2 hours ago"); + globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), type.toString(), false); + return false; + } + + globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), "Processing", true); + plugin.debug("Detected time change from bungee: " + type.toString()); + plugin.getTimeChecker().forceChanged(type, false, true, true); + globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), type.toString(), false); + + JsonEnvelope.Builder builder = JsonEnvelope.builder("TimeChangeFinished").schema(VotingPluginWire.SCHEMA_VERSION); + builder.put("server", plugin.getBungeeSettings().getServer()); + sender.accept(builder.build()); + return true; + } + + public boolean checkGlobalDataTimeValue(DataValue data) { + if (data.isBoolean()) { + return data.getBoolean(); + } + return Boolean.valueOf(data.getString()); + } + + public void load() { + if (!plugin.getBungeeSettings().isGloblalDataEnabled()) { + return; + } + + shutdownTimer(); + timer = Executors.newScheduledThreadPool(1); + timer.scheduleWithFixedDelay(this::checkGlobalData, 60, 10, TimeUnit.SECONDS); + timer.scheduleWithFixedDelay(() -> { + if (globalDataHandler != null) { + globalDataHandler.setString(plugin.getBungeeSettings().getServer(), "LastOnline", + "" + LocalDateTime.now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()); + } + }, 1, 60, TimeUnit.MINUTES); + + closeGlobalMysql(); + + if (plugin.getBungeeSettings().isGloblalDataUseMainMySQL() + && plugin.getStorageType().equals(UserStorage.MYSQL)) { + globalDataHandler = new GlobalDataHandler(new GlobalMySQL("VotingPlugin_GlobalData", plugin.getMysql().getMysql()) { + @Override public void debugEx(Exception e) { plugin.debug(e); } + @Override public void debugLog(String text) { plugin.debug(text); } + @Override public void info(String text) { plugin.getLogger().info(text); } + @Override public void logSevere(String text) { plugin.getLogger().severe(text); } + @Override public void warning(String text) { plugin.getLogger().warning(text); } + }); + } else { + globalDataHandler = new GlobalDataHandler(new GlobalMySQL("VotingPlugin_GlobalData", + new MysqlConfigSpigot(plugin.getBungeeSettings().getData().getConfigurationSection("GlobalData"))) { + @Override public void debugEx(Exception e) { plugin.debug(e); } + @Override public void debugLog(String text) { plugin.debug(text); } + @Override public void info(String text) { plugin.getLogger().info(text); } + @Override public void logSevere(String text) { plugin.getLogger().severe(text); } + @Override public void warning(String text) { plugin.getLogger().warning(text); } + }); + } + + for (Map.Entry column : Map.of( + "IgnoreTime", "VARCHAR(5)", + "MONTH", "VARCHAR(5)", + "WEEK", "VARCHAR(5)", + "DAY", "VARCHAR(5)", + "FinishedProcessing", "VARCHAR(5)", + "Processing", "VARCHAR(5)", + "LastUpdated", "MEDIUMTEXT", + "ForceUpdate", "VARCHAR(5)").entrySet()) { + globalDataHandler.getGlobalMysql().alterColumnType(column.getKey(), column.getValue()); + } + plugin.getTimeChecker().setProcessingEnabled(false); + } + + public void close() { + closeGlobalMysql(); + } + + private void closeGlobalMysql() { + if (globalDataHandler != null) { + globalDataHandler.getGlobalMysql().close(); + } + } + + private void shutdownTimer() { + if (timer == null) { + return; + } + timer.shutdown(); + try { + timer.awaitTermination(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + timer.shutdownNow(); + } +} From e305540a34621714306a18ab89b4f5c731019c75 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:09:32 -0600 Subject: [PATCH 04/71] Add backend proxy transport contract --- .../transport/BackendProxyTransport.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/BackendProxyTransport.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/BackendProxyTransport.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/BackendProxyTransport.java new file mode 100644 index 0000000000..5e7b40b49b --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/BackendProxyTransport.java @@ -0,0 +1,16 @@ +package com.bencodez.votingplugin.backendproxy.transport; + +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; + +/** + * Transport used by a backend server to communicate with the VotingPlugin proxy. + */ +public interface BackendProxyTransport { + + void start(GlobalMessageHandler messageHandler); + + void send(JsonEnvelope envelope); + + void close(); +} From 6378e9748bcf84b6f35f7d2316a72df9a0591927 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:09:49 -0600 Subject: [PATCH 05/71] Extract backend MySQL transport --- .../transport/MysqlBackendProxyTransport.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/MysqlBackendProxyTransport.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/MysqlBackendProxyTransport.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/MysqlBackendProxyTransport.java new file mode 100644 index 0000000000..d55b2e88f8 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/MysqlBackendProxyTransport.java @@ -0,0 +1,58 @@ +package com.bencodez.votingplugin.backendproxy.transport; + +import java.sql.SQLException; + +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; +import com.bencodez.simpleapi.servercomm.mysql.MySqlMessenger; +import com.bencodez.votingplugin.VotingPluginMain; + +import lombok.Getter; + +public class MysqlBackendProxyTransport implements BackendProxyTransport { + + private final VotingPluginMain plugin; + @Getter + private MySqlMessenger messenger; + + public MysqlBackendProxyTransport(VotingPluginMain plugin) { + this.plugin = plugin; + } + + @Override + public void start(GlobalMessageHandler messageHandler) { + plugin.registerBungeeChannels(plugin.getBungeeSettings().getPluginMessagingChannel()); + try { + messenger = new MySqlMessenger("VotingPlugin", + plugin.getMysql().getMysql().getConnectionManager().getDataSource(), + MySqlMessenger.Mode.BACKEND, plugin.getOptions().getServer(), msg -> { + if (plugin.getBungeeSettings().isBungeeDebug()) { + plugin.debug("Proxy sent envelope: " + msg.envelope.getSubChannel() + " " + + msg.envelope.getFields()); + } + messageHandler.onMessage(msg.envelope); + }); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void send(JsonEnvelope envelope) { + if (messenger == null) { + return; + } + try { + messenger.sendToProxy(envelope); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void close() { + if (messenger != null) { + messenger.shutdown(); + } + } +} From c44c347be24421e1e7da145d9ce40ae2d9cf9cf5 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:10:01 -0600 Subject: [PATCH 06/71] Extract plugin messaging backend transport --- .../PluginMessagingBackendProxyTransport.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/PluginMessagingBackendProxyTransport.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/PluginMessagingBackendProxyTransport.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/PluginMessagingBackendProxyTransport.java new file mode 100644 index 0000000000..6616ff748d --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/PluginMessagingBackendProxyTransport.java @@ -0,0 +1,45 @@ +package com.bencodez.votingplugin.backendproxy.transport; + +import java.io.File; + +import com.bencodez.simpleapi.encryption.EncryptionHandler; +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; +import com.bencodez.simpleapi.servercomm.pluginmessage.PluginMessageHandler; +import com.bencodez.votingplugin.VotingPluginMain; + +public class PluginMessagingBackendProxyTransport implements BackendProxyTransport { + + private final VotingPluginMain plugin; + + public PluginMessagingBackendProxyTransport(VotingPluginMain plugin) { + this.plugin = plugin; + } + + @Override + public void start(GlobalMessageHandler messageHandler) { + plugin.registerBungeeChannels(plugin.getBungeeSettings().getPluginMessagingChannel()); + if (plugin.getBungeeSettings().isPluginMessageEncryption()) { + EncryptionHandler encryptionHandler = new EncryptionHandler(plugin.getName(), + new File(plugin.getDataFolder(), "secretkey.key")); + plugin.getPluginMessaging().setEncryptionHandler(encryptionHandler); + } + plugin.getPluginMessaging().setDebug(plugin.getBungeeSettings().isBungeeDebug()); + plugin.getPluginMessaging().add(new PluginMessageHandler() { + @Override + public void onReceive(JsonEnvelope envelope) { + messageHandler.onMessage(envelope); + } + }); + } + + @Override + public void send(JsonEnvelope envelope) { + plugin.getPluginMessaging().sendEnvelope(envelope); + } + + @Override + public void close() { + // Plugin messaging is owned by the plugin lifecycle. + } +} From 16becd377d6d5339af6f9a4b49a12b4c21926afb Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:10:12 -0600 Subject: [PATCH 07/71] Extract socket backend transport --- .../SocketBackendProxyTransport.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/SocketBackendProxyTransport.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/SocketBackendProxyTransport.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/SocketBackendProxyTransport.java new file mode 100644 index 0000000000..c4342ca58a --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/SocketBackendProxyTransport.java @@ -0,0 +1,66 @@ +package com.bencodez.votingplugin.backendproxy.transport; + +import java.io.File; + +import com.bencodez.simpleapi.encryption.EncryptionHandler; +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; +import com.bencodez.simpleapi.servercomm.sockets.ClientHandler; +import com.bencodez.simpleapi.servercomm.sockets.SocketHandler; +import com.bencodez.simpleapi.servercomm.sockets.SocketReceiver; +import com.bencodez.votingplugin.VotingPluginMain; + +import lombok.Getter; + +public class SocketBackendProxyTransport implements BackendProxyTransport { + + private final VotingPluginMain plugin; + @Getter + private ClientHandler clientHandler; + @Getter + private SocketHandler socketHandler; + + public SocketBackendProxyTransport(VotingPluginMain plugin) { + this.plugin = plugin; + } + + @Override + public void start(GlobalMessageHandler messageHandler) { + EncryptionHandler encryptionHandler = new EncryptionHandler(plugin.getName(), + new File(plugin.getDataFolder(), "secretkey.key")); + clientHandler = new ClientHandler(plugin.getBungeeSettings().getBungeeServerHost(), + plugin.getBungeeSettings().getBungeeServerPort(), encryptionHandler, + plugin.getBungeeSettings().isBungeeDebug()); + socketHandler = new SocketHandler("vp-socket", plugin.getBungeeSettings().getSpigotServerHost(), + plugin.getBungeeSettings().getSpigotServerPort(), encryptionHandler, + plugin.getBungeeSettings().isBungeeDebug()) { + @Override + public void log(String str) { + plugin.getLogger().info(str); + } + }; + socketHandler.add(new SocketReceiver() { + @Override + public void onReceiveEnvelope(JsonEnvelope envelope) { + messageHandler.onMessage(envelope); + } + }); + } + + @Override + public void send(JsonEnvelope envelope) { + if (clientHandler != null) { + clientHandler.sendEnvelope(envelope); + } + } + + @Override + public void close() { + if (socketHandler != null) { + socketHandler.closeConnection(); + } + if (clientHandler != null) { + clientHandler.stopConnection(); + } + } +} From 98363e12d2890e7ffb1cc18104227ccc69b4b65a Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:10:22 -0600 Subject: [PATCH 08/71] Extract Redis backend transport --- .../transport/RedisBackendProxyTransport.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/RedisBackendProxyTransport.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/RedisBackendProxyTransport.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/RedisBackendProxyTransport.java new file mode 100644 index 0000000000..34873e5282 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/RedisBackendProxyTransport.java @@ -0,0 +1,57 @@ +package com.bencodez.votingplugin.backendproxy.transport; + +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; +import com.bencodez.simpleapi.servercomm.redis.RedisHandler; +import com.bencodez.simpleapi.servercomm.redis.RedisListener; +import com.bencodez.votingplugin.VotingPluginMain; + +import lombok.Getter; + +public class RedisBackendProxyTransport implements BackendProxyTransport { + + private final VotingPluginMain plugin; + @Getter + private RedisHandler redisHandler; + private Thread listenerThread; + + public RedisBackendProxyTransport(VotingPluginMain plugin) { + this.plugin = plugin; + } + + @Override + public void start(GlobalMessageHandler messageHandler) { + redisHandler = new RedisHandler(plugin.getBungeeSettings().getRedisHost(), + plugin.getBungeeSettings().getRedisPort(), plugin.getBungeeSettings().getRedisUsername(), + plugin.getBungeeSettings().getRedisPassword(), plugin.getBungeeSettings().getRedisdbindex()) { + @Override + public void debug(String message) { + if (plugin.getBungeeSettings().isBungeeDebug()) { + plugin.debug(message); + } + } + }; + + listenerThread = new Thread(() -> { + if (plugin.isEnabled()) { + RedisListener listener = redisHandler.createEnvelopeListener( + plugin.getBungeeSettings().getRedisPrefix() + "VotingPlugin_" + plugin.getBungeeSettings().getServer(), + (ch, envelope) -> messageHandler.onMessage(envelope)); + redisHandler.loadListener(listener); + } + }, "VotingPlugin-Redis-Backend"); + listenerThread.start(); + } + + @Override + public void send(JsonEnvelope envelope) { + if (redisHandler != null) { + redisHandler.publishEnvelope(plugin.getBungeeSettings().getRedisPrefix() + "VotingPlugin", envelope); + } + } + + @Override + public void close() { + // Preserve current Redis lifecycle behavior; the listener is owned by RedisHandler. + } +} From 280ded8f6584595c65444d5524eb041da6b2336f Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:10:35 -0600 Subject: [PATCH 09/71] Extract MQTT backend transport --- .../transport/MqttBackendProxyTransport.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/MqttBackendProxyTransport.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/MqttBackendProxyTransport.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/MqttBackendProxyTransport.java new file mode 100644 index 0000000000..f092e77da2 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/MqttBackendProxyTransport.java @@ -0,0 +1,58 @@ +package com.bencodez.votingplugin.backendproxy.transport; + +import org.eclipse.paho.client.mqttv3.MqttException; + +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; +import com.bencodez.simpleapi.servercomm.mqtt.MqttHandler; +import com.bencodez.simpleapi.servercomm.mqtt.MqttServerComm; +import com.bencodez.votingplugin.VotingPluginMain; + +import lombok.Getter; + +public class MqttBackendProxyTransport implements BackendProxyTransport { + + private final VotingPluginMain plugin; + @Getter + private MqttHandler mqttHandler; + + public MqttBackendProxyTransport(VotingPluginMain plugin) { + this.plugin = plugin; + } + + @Override + public void start(GlobalMessageHandler messageHandler) { + try { + String id = plugin.getBungeeSettings().getMqttClientID(); + if (id.isEmpty()) { + id = plugin.getOptions().getServer(); + } + mqttHandler = new MqttHandler(new MqttServerComm(id, plugin.getBungeeSettings().getMqttBrokerURL(), + plugin.getBungeeSettings().getMqttUsername(), plugin.getBungeeSettings().getMqttPassword()), 2); + mqttHandler.subscribeEnvelopes(plugin.getBungeeSettings().getMqttPrefix() + "votingplugin/servers/" + + plugin.getOptions().getServer(), (topic, envelope) -> messageHandler.onMessage(envelope)); + } catch (MqttException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void send(JsonEnvelope envelope) { + if (mqttHandler == null) { + return; + } + try { + mqttHandler.publishEnvelope(plugin.getBungeeSettings().getMqttPrefix() + "votingplugin/servers/proxy", + envelope); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void close() { + // Preserve current MQTT lifecycle behavior. + } +} From fa5f35e93c725e36e7c4cfb5d7131335bebdd08d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:10:47 -0600 Subject: [PATCH 10/71] Add backend proxy transport manager --- .../BackendProxyTransportManager.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/BackendProxyTransportManager.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/BackendProxyTransportManager.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/BackendProxyTransportManager.java new file mode 100644 index 0000000000..e8377f7538 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/transport/BackendProxyTransportManager.java @@ -0,0 +1,86 @@ +package com.bencodez.votingplugin.backendproxy.transport; + +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; +import com.bencodez.simpleapi.servercomm.mqtt.MqttHandler; +import com.bencodez.simpleapi.servercomm.mysql.MySqlMessenger; +import com.bencodez.simpleapi.servercomm.redis.RedisHandler; +import com.bencodez.simpleapi.servercomm.sockets.ClientHandler; +import com.bencodez.simpleapi.servercomm.sockets.SocketHandler; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.proxy.BungeeMethod; + +/** + * Selects and owns the active backend-to-proxy transport. + */ +public class BackendProxyTransportManager { + + private final VotingPluginMain plugin; + private BackendProxyTransport transport; + + public BackendProxyTransportManager(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public void start(BungeeMethod method, GlobalMessageHandler messageHandler) { + close(); + switch (method) { + case MYSQL: + transport = new MysqlBackendProxyTransport(plugin); + break; + case PLUGINMESSAGING: + transport = new PluginMessagingBackendProxyTransport(plugin); + break; + case SOCKETS: + transport = new SocketBackendProxyTransport(plugin); + break; + case REDIS: + transport = new RedisBackendProxyTransport(plugin); + break; + case MQTT: + transport = new MqttBackendProxyTransport(plugin); + break; + default: + throw new IllegalArgumentException("Unsupported backend proxy method: " + method); + } + transport.start(messageHandler); + } + + public void send(JsonEnvelope envelope) { + if (transport != null) { + transport.send(envelope); + } + } + + public void close() { + if (transport != null) { + transport.close(); + transport = null; + } + } + + public ClientHandler getClientHandler() { + return transport instanceof SocketBackendProxyTransport + ? ((SocketBackendProxyTransport) transport).getClientHandler() : null; + } + + public SocketHandler getSocketHandler() { + return transport instanceof SocketBackendProxyTransport + ? ((SocketBackendProxyTransport) transport).getSocketHandler() : null; + } + + public RedisHandler getRedisHandler() { + return transport instanceof RedisBackendProxyTransport + ? ((RedisBackendProxyTransport) transport).getRedisHandler() : null; + } + + public MySqlMessenger getBackendMysqlMessenger() { + return transport instanceof MysqlBackendProxyTransport + ? ((MysqlBackendProxyTransport) transport).getMessenger() : null; + } + + public MqttHandler getMqttHandler() { + return transport instanceof MqttBackendProxyTransport + ? ((MqttBackendProxyTransport) transport).getMqttHandler() : null; + } +} From 94213eafdd3643648a6c3c3eae899d60f98e6551 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:11:18 -0600 Subject: [PATCH 11/71] Extract backend proxy message routing --- .../messaging/BackendProxyMessageRouter.java | 263 ++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/messaging/BackendProxyMessageRouter.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/messaging/BackendProxyMessageRouter.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/messaging/BackendProxyMessageRouter.java new file mode 100644 index 0000000000..59563bffbd --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/messaging/BackendProxyMessageRouter.java @@ -0,0 +1,263 @@ +package com.bencodez.votingplugin.backendproxy.messaging; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; +import com.bencodez.simpleapi.servercomm.global.GlobalMessageListener; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.backendproxy.cache.ProcessedVoteCache; +import com.bencodez.votingplugin.backendproxy.global.BackendGlobalDataSync; +import com.bencodez.votingplugin.backendproxy.presence.BackendPresenceManager; +import com.bencodez.votingplugin.backendproxy.voteparty.BackendVotePartySync; +import com.bencodez.votingplugin.proxy.BungeeMethod; +import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; +import com.bencodez.votingplugin.proxy.VotingPluginWire; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.util.ServiceSiteValidator; +import com.bencodez.votingplugin.votesites.VoteSite; + +/** + * Registers and handles backend-side proxy message routes. + */ +public class BackendProxyMessageRouter { + + private final VotingPluginMain plugin; + private final BackendPresenceManager presenceManager; + private final BackendGlobalDataSync globalDataSync; + private final BackendVotePartySync votePartySync; + private final ProcessedVoteCache processedVoteCache; + + public BackendProxyMessageRouter(VotingPluginMain plugin, BackendPresenceManager presenceManager, + BackendGlobalDataSync globalDataSync, BackendVotePartySync votePartySync, + ProcessedVoteCache processedVoteCache) { + this.plugin = plugin; + this.presenceManager = presenceManager; + this.globalDataSync = globalDataSync; + this.votePartySync = votePartySync; + this.processedVoteCache = processedVoteCache; + } + + public void register(GlobalMessageHandler messages, BungeeMethod method) { + messages.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE) { + @Override public void onReceive(JsonEnvelope msg) { handleWireVote(msg); } + }); + messages.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_ONLINE) { + @Override public void onReceive(JsonEnvelope msg) { handleWireVote(msg); } + }); + messages.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_DELAY_REJECTED) { + @Override public void onReceive(JsonEnvelope msg) { handleWireVoteDelayRejected(msg); } + }); + + if (method.supportsBackendPresence()) { + messages.addListener(new GlobalMessageListener(VotingPluginWire.SUB_PRESENCE_RESYNC_REQUEST) { + @Override public void onReceive(JsonEnvelope msg) { presenceManager.handleResyncRequest(msg); } + }); + messages.addListener(new GlobalMessageListener(VotingPluginWire.SUB_PRESENCE_SNAPSHOT_REQUEST) { + @Override public void onReceive(JsonEnvelope msg) { presenceManager.handleSnapshotRequest(msg); } + }); + } + + messages.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_UPDATE) { + @Override public void onReceive(JsonEnvelope msg) { handleVoteUpdate(msg); } + }); + messages.addListener(new GlobalMessageListener(VotingPluginWire.SUB_BUNGEE_TIME_CHANGE) { + @Override public void onReceive(JsonEnvelope msg) { globalDataSync.checkGlobalData(); } + }); + messages.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_BROADCAST) { + @Override public void onReceive(JsonEnvelope msg) { handleVoteBroadcast(msg); } + }); + messages.addListener(new GlobalMessageListener("Status") { + @Override public void onReceive(JsonEnvelope msg) { + HashMap out = new HashMap<>(); + out.put("server", nvl(msg.getFields().get("server"))); + sendSubChannel(messages, "statusokay", out); + } + }); + messages.addListener(new GlobalMessageListener("ServerName") { + @Override public void onReceive(JsonEnvelope msg) { + String server = nvl(msg.getFields().get("server")); + if (!plugin.getOptions().getServer().equals(server)) { + plugin.getLogger().warning("Server name doesn't match in BungeeSettings.yml, should be " + server); + } + } + }); + messages.addListener(new GlobalMessageListener("VotePartyBungee") { + @Override public void onReceive(JsonEnvelope msg) { votePartySync.runGlobalRewards(); } + }); + messages.addListener(new GlobalMessageListener("VotePartyBroadcast") { + @Override public void onReceive(JsonEnvelope msg) { + votePartySync.broadcast(nvl(msg.getFields().get("broadcast"))); + } + }); + } + + private void handleVoteUpdate(JsonEnvelope msg) { + VotingPluginWire.VoteUpdate update = VotingPluginWire.readVoteUpdate(msg); + String playerUuid = update.uuid; + if (playerUuid == null || playerUuid.isEmpty()) { + return; + } + + plugin.debug("pluginmessaging voteupdate received for " + playerUuid + ": " + update.votePartyCurrent + "/" + + update.votePartyRequired + " on " + update.service); + votePartySync.update(update.votePartyCurrent, update.votePartyRequired); + + VotingPluginUser user; + try { + user = plugin.getVotingPluginUserManager().getVotingPluginUser(UUID.fromString(playerUuid)); + } catch (IllegalArgumentException e) { + plugin.getLogger().warning("Invalid UUID in VoteUpdate: " + playerUuid); + return; + } + user.cache(); + user.offVote(); + + if (update.service != null && !update.service.isEmpty() && update.time > 0) { + user.setTime(plugin.getVoteSiteManager().getVoteSite(update.service, true), update.time); + } else if (update.service != null && !update.service.isEmpty() && update.time <= 0 + && plugin.getBungeeSettings().isBungeeDebug()) { + plugin.debug("Invalid last vote time received from bungee: " + update.time); + } + plugin.setUpdate(true); + } + + private void handleVoteBroadcast(JsonEnvelope msg) { + Map fields = msg.getFields(); + String uuidStr = nvl(fields.get(VotingPluginWire.K_UUID)); + String playerName = nvl(fields.get(VotingPluginWire.K_PLAYER)); + String service = nvl(fields.get(VotingPluginWire.K_SERVICE)); + if (uuidStr.isEmpty() || service.isEmpty()) { + return; + } + + UUID javaUuid; + try { + javaUuid = UUID.fromString(uuidStr); + } catch (Exception e) { + plugin.getLogger().warning("Invalid UUID in VoteBroadcast: " + uuidStr); + return; + } + + String totalsRaw = nvl(fields.get(VotingPluginWire.K_TOTALS)); + VoteTotalsSnapshot totals = totalsRaw.isEmpty() ? null : VoteTotalsSnapshot.parseStorage(totalsRaw); + VoteSite voteSite = plugin.getVoteSiteManager() + .getVoteSite(plugin.getVoteSiteManager().getVoteSiteName(true, service), true); + if (voteSite == null) { + plugin.getLogger().warning("No voting site with the service site: '" + service + "'"); + return; + } + if (!voteSite.isEnabled()) { + plugin.debug("Votesite: " + voteSite.getKey() + " is not enabled (VoteBroadcast)"); + return; + } + + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(javaUuid, playerName); + user.cache(); + user.updateName(true); + if (plugin.getBroadcastHandler() == null || user.isVanished()) { + if (user.isVanished()) { + plugin.debug("Not broadcasting vote for vanished user: " + user.getPlayerName()); + } + return; + } + + boolean online = fields.containsKey(VotingPluginWire.K_WAS_ONLINE) + ? Boolean.parseBoolean(fields.get(VotingPluginWire.K_WAS_ONLINE)) : user.isOnline(); + plugin.getBroadcastHandler().broadcastVote(user.getJavaUUID(), user.getPlayerName(), + voteSite.getDisplayName(), online, totals); + } + + private void handleWireVoteDelayRejected(JsonEnvelope msg) { + if (!validSchema(msg) || !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); + } + + private void handleWireVote(JsonEnvelope msg) { + if (!validSchema(msg)) { + return; + } + VotingPluginWire.Vote vote = VotingPluginWire.readVote(msg); + if (vote.uuid == null || vote.uuid.isEmpty()) { + return; + } + if (!ServiceSiteValidator.isValid(vote.service)) { + plugin.getLogger().warning("Rejected proxy vote with invalid service site '" + + ServiceSiteValidator.sanitizeForLog(vote.service) + "'"); + return; + } + + plugin.debug("wire vote received from " + vote.player + "/" + vote.uuid + " on " + vote.service); + VoteTotalsSnapshot totals = VoteTotalsSnapshot.parseStorage(vote.totals == null ? "" : vote.totals); + @SuppressWarnings("deprecation") + UUID voteId = vote.voteId != null ? vote.voteId : totals.getVoteUUID(); + if (!processedVoteCache.reserve(voteId)) { + plugin.debug("Ignoring duplicate wire vote " + voteId + " for " + vote.player + " on " + vote.service); + return; + } + + UUID javaUuid; + try { + javaUuid = UUID.fromString(vote.uuid); + } catch (IllegalArgumentException e) { + plugin.getLogger().warning("Invalid UUID in proxy vote: " + vote.uuid); + return; + } + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(javaUuid, vote.player); + votePartySync.replace(totals.getVotePartyCurrent(), totals.getVotePartyRequired()); + user.cache(); + user.bungeeVotePluginMessaging(vote.service, vote.time, totals, !vote.manageTotals, + vote.wasOnline, vote.broadcast, vote.num); + if (plugin.getBungeeSettings().isPerServerPoints()) { + user.addPoints(plugin.getConfigFile().getPointsOnVote()); + } + if (vote.service != null && !vote.service.isEmpty()) { + plugin.getServerData().addServiceSite(vote.service); + } + } + + private boolean validSchema(JsonEnvelope msg) { + if (msg.getSchema() == VotingPluginWire.SCHEMA_VERSION) { + return true; + } + plugin.getLogger().warning("Incompatible version with bungee/proxy, please update all servers: " + + msg.getSchema() + " != " + VotingPluginWire.SCHEMA_VERSION); + return false; + } + + private void sendSubChannel(GlobalMessageHandler messages, String subChannel, HashMap fields) { + JsonEnvelope.Builder builder = JsonEnvelope.builder(subChannel).schema(VotingPluginWire.SCHEMA_VERSION); + for (Map.Entry entry : fields.entrySet()) { + builder.put(entry.getKey(), entry.getValue()); + } + messages.sendMessage(builder.build()); + } + + private static String nvl(String value) { + return value == null ? "" : value; + } +} From 2bd8c064d1df467ad7df71fcf1c3d1027d80c414 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:11:48 -0600 Subject: [PATCH 12/71] Make BackendProxyHandler a coordinator --- .../backendproxy/BackendProxyHandler.java | 839 ++---------------- 1 file changed, 75 insertions(+), 764 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/BackendProxyHandler.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/BackendProxyHandler.java index 00c4d1435a..f167a8f385 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/BackendProxyHandler.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/BackendProxyHandler.java @@ -1,868 +1,179 @@ -// File: com/bencodez/votingplugin/backendproxy/BackendProxyHandler.java package com.bencodez.votingplugin.backendproxy; -import java.io.File; -import java.sql.SQLException; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; import org.bukkit.event.Listener; -import org.eclipse.paho.client.mqttv3.MqttException; -import com.bencodez.advancedcore.api.misc.MiscUtils; -import com.bencodez.advancedcore.api.rewards.RewardBuilder; import com.bencodez.advancedcore.api.time.TimeType; -import com.bencodez.advancedcore.api.user.UserStorage; -import com.bencodez.advancedcore.bungeeapi.globaldata.GlobalDataHandler; -import com.bencodez.advancedcore.bungeeapi.globaldata.GlobalMySQL; -import com.bencodez.simpleapi.encryption.EncryptionHandler; import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope; import com.bencodez.simpleapi.servercomm.global.GlobalMessageHandler; -import com.bencodez.simpleapi.servercomm.global.GlobalMessageListener; import com.bencodez.simpleapi.servercomm.mqtt.MqttHandler; -import com.bencodez.simpleapi.servercomm.mqtt.MqttServerComm; import com.bencodez.simpleapi.servercomm.mysql.MySqlMessenger; -import com.bencodez.simpleapi.servercomm.pluginmessage.PluginMessageHandler; import com.bencodez.simpleapi.servercomm.redis.RedisHandler; -import com.bencodez.simpleapi.servercomm.redis.RedisListener; import com.bencodez.simpleapi.servercomm.sockets.ClientHandler; import com.bencodez.simpleapi.servercomm.sockets.SocketHandler; -import com.bencodez.simpleapi.servercomm.sockets.SocketReceiver; import com.bencodez.simpleapi.sql.data.DataValue; -import com.bencodez.simpleapi.sql.data.DataValueBoolean; -import com.bencodez.simpleapi.sql.mysql.config.MysqlConfigSpigot; import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.backendproxy.cache.ProcessedVoteCache; +import com.bencodez.votingplugin.backendproxy.global.BackendGlobalDataSync; +import com.bencodez.votingplugin.backendproxy.messaging.BackendProxyMessageRouter; import com.bencodez.votingplugin.backendproxy.presence.BackendPresenceManager; +import com.bencodez.votingplugin.backendproxy.transport.BackendProxyTransportManager; +import com.bencodez.votingplugin.backendproxy.voteparty.BackendVotePartySync; import com.bencodez.votingplugin.proxy.BungeeMethod; -import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; -import com.bencodez.votingplugin.proxy.VotingPluginWire; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.util.ServiceSiteValidator; -import com.bencodez.votingplugin.votesites.VoteSite; import lombok.Getter; /** - * Handler for Bungee/proxy server integration. + * Coordinates backend/proxy communication components. */ public class BackendProxyHandler implements Listener { - private static final long PROCESSED_VOTE_TTL_MILLIS = TimeUnit.MINUTES.toMillis(30); + private final VotingPluginMain plugin; + private final ProcessedVoteCache processedVoteCache = new ProcessedVoteCache(); + private final BackendProxyTransportManager transportManager; + private final BackendGlobalDataSync globalDataSync; - @Getter - private final ConcurrentHashMap processedWireVotes = new ConcurrentHashMap<>(); private BackendPresenceManager presenceManager; - - @Getter - private ClientHandler clientHandler; - - private EncryptionHandler encryptionHandler; + private BackendVotePartySync votePartySync; + private BackendProxyMessageRouter messageRouter; @Getter private BungeeMethod method; - - private VotingPluginMain plugin; - - @Getter - private int bungeeVotePartyCurrent = -2; - - @Getter - private int bungeeVotePartyRequired = -2; - - @Getter - private SocketHandler socketHandler; - - private GlobalDataHandler globalDataHandler; - - @Getter - private ScheduledExecutorService timer; - - @Getter - private RedisHandler redisHandler; - @Getter private GlobalMessageHandler globalMessageHandler; - private Thread redisThread; - - @Getter - private MySqlMessenger backendMysqlMessenger; - - @Getter - private MqttHandler mqttHandler; - - /** - * Constructs a new BackendProxyHandler. - * - * @param plugin the main plugin instance - */ public BackendProxyHandler(VotingPluginMain plugin) { this.plugin = plugin; + transportManager = new BackendProxyTransportManager(plugin); + globalDataSync = new BackendGlobalDataSync(plugin, this::sendEnvelope); } /** - * Checks and processes global data from the global data handler. - */ - public void checkGlobalData() { - HashMap data = globalDataHandler.getExact(plugin.getBungeeSettings().getServer()); - - if (data.containsKey("ForceUpdate")) { - boolean b = checkGlobalDataTimeValue(data.get("ForceUpdate")); - if (b) { - if (plugin.getStorageType().equals(UserStorage.MYSQL)) { - plugin.getMysql().clearCacheBasic(); - } - plugin.getUserManager().getDataManager().clearCache(); - plugin.setUpdate(true); - plugin.update(); - globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), "ForceUpdate", false); - } - } - - boolean forceUpdate = false; - - if (checkGlobalDataTime(TimeType.MONTH, data)) { - forceUpdate = true; - } - if (checkGlobalDataTime(TimeType.WEEK, data)) { - forceUpdate = true; - } - if (checkGlobalDataTime(TimeType.DAY, data)) { - forceUpdate = true; - } - - if (forceUpdate) { - HashMap dataToSet = new HashMap<>(); - dataToSet.put("FinishedProcessing", new DataValueBoolean(true)); - dataToSet.put("Processing", new DataValueBoolean(false)); - globalDataHandler.setData(plugin.getBungeeSettings().getServer(), dataToSet); - } - } - - /** - * Checks global data for a time type change. - * - * @param type the time type to check - * @param data the global data map - * @return true if currently processing a time change - */ - public boolean checkGlobalDataTime(TimeType type, HashMap data) { - boolean isProcessing = false; - if (data.containsKey(type.toString())) { - - DataValue value = data.get(type.toString()); - boolean b = checkGlobalDataTimeValue(value); - if (b) { - long lastUpdated = Long.valueOf(data.get("LastUpdated").getString()).longValue(); - plugin.debug("LastUpdated: " + lastUpdated); - if (LocalDateTime.now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli() - lastUpdated > 1000 * 60 * 60 - * 2) { - plugin.getLogger().warning("Ignoring bungee time change since it was more than 2 hours ago"); - globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), type.toString(), false); - return false; - } - - globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), "Processing", true); - isProcessing = true; - - plugin.debug("Detected time change from bungee: " + type.toString()); - plugin.getTimeChecker().forceChanged(type, false, true, true); - globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), type.toString(), false); - - HashMap fields = new HashMap<>(); - fields.put("server", plugin.getBungeeSettings().getServer()); - sendSubChannel("TimeChangeFinished", fields); - } - } - return isProcessing; - } - - /** - * Checks and extracts the boolean value from a DataValue. - * - * @param data the data value - * @return the boolean value - */ - public boolean checkGlobalDataTimeValue(DataValue data) { - if (data.isBoolean()) { - return data.getBoolean(); - } - return Boolean.valueOf(data.getString()); - } - - /** - * Closes and cleans up all handlers and connections. - */ - public void close() { - if (presenceManager != null) { - presenceManager.stop(); - } - - if (backendMysqlMessenger != null) { - backendMysqlMessenger.shutdown(); - } - - if (socketHandler != null) { - socketHandler.closeConnection(); - } - if (clientHandler != null) { - clientHandler.stopConnection(); - } - plugin.getServerData().setBungeeVotePartyCurrent(bungeeVotePartyCurrent); - plugin.getServerData().setBungeeVotePartyRequired(bungeeVotePartyRequired); - if (globalDataHandler != null) { - globalDataHandler.getGlobalMysql().close(); - } - } - - /** - * Loads and initializes the bungee handler with the configured method. + * Loads the configured backend/proxy communication components. */ public void load() { plugin.debug("Loading backend proxy handler"); - method = BungeeMethod.getByName(plugin.getBungeeSettings().getBungeeMethod()); - plugin.getLogger().info("Using BungeeMethod: " + method.toString()); - loadGlobalMysql(); - + globalDataSync.load(); globalMessageHandler = new GlobalMessageHandler() { @Override public void sendMessage(JsonEnvelope envelope) { - if (method.equals(BungeeMethod.MYSQL)) { - try { - backendMysqlMessenger.sendToProxy(envelope); - } catch (SQLException e) { - e.printStackTrace(); - } - } else if (method.equals(BungeeMethod.PLUGINMESSAGING)) { - plugin.getPluginMessaging().sendEnvelope(envelope); - } else if (method.equals(BungeeMethod.SOCKETS)) { - sendEnvelopeSocket(envelope); - } else if (method.equals(BungeeMethod.REDIS)) { - redisHandler.publishEnvelope(plugin.getBungeeSettings().getRedisPrefix() + "VotingPlugin", - envelope); - } else if (method.equals(BungeeMethod.MQTT)) { - try { - mqttHandler.publishEnvelope( - plugin.getBungeeSettings().getMqttPrefix() + "votingplugin/servers/proxy", envelope); - } catch (Exception e) { - e.printStackTrace(); - } - } + transportManager.send(envelope); } }; presenceManager = new BackendPresenceManager(plugin, method, globalMessageHandler); - - globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE) { - @Override - public void onReceive(JsonEnvelope msg) { - handleWireVote(msg); - } - }); - - globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_ONLINE) { - @Override - public void onReceive(JsonEnvelope msg) { - handleWireVote(msg); - } - }); - - globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_DELAY_REJECTED) { - @Override - public void onReceive(JsonEnvelope msg) { - handleWireVoteDelayRejected(msg); - } - }); - - if (method.supportsBackendPresence()) { - globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_PRESENCE_RESYNC_REQUEST) { - @Override - public void onReceive(JsonEnvelope msg) { - presenceManager.handleResyncRequest(msg); - } - }); - globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_PRESENCE_SNAPSHOT_REQUEST) { - @Override - public void onReceive(JsonEnvelope msg) { - presenceManager.handleSnapshotRequest(msg); - } - }); - } - - globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_UPDATE) { - @Override - public void onReceive(JsonEnvelope msg) { - VotingPluginWire.VoteUpdate v = VotingPluginWire.readVoteUpdate(msg); - - String playerUuid = v.uuid; - if (playerUuid == null || playerUuid.isEmpty()) { - return; - } - - plugin.debug("pluginmessaging voteupdate received for " + playerUuid + ": " + v.votePartyCurrent + "/" - + v.votePartyRequired + " on " + v.service); - - if (v.votePartyCurrent >= 0 || bungeeVotePartyCurrent == -2) { - bungeeVotePartyCurrent = v.votePartyCurrent; - } - if (v.votePartyRequired >= 0 || bungeeVotePartyRequired == -2) { - bungeeVotePartyRequired = v.votePartyRequired; - } - plugin.getServerData().setBungeeVotePartyCurrent(bungeeVotePartyCurrent); - plugin.getServerData().setBungeeVotePartyRequired(bungeeVotePartyRequired); - - VotingPluginUser user = plugin.getVotingPluginUserManager() - .getVotingPluginUser(UUID.fromString(playerUuid)); - user.cache(); - user.offVote(); - - String service = v.service; - long time = v.time; - - if (service != null && !service.isEmpty() && time > 0) { - user.setTime(plugin.getVoteSiteManager().getVoteSite(service, true), time); - } else if (service != null && !service.isEmpty() && time <= 0 - && plugin.getBungeeSettings().isBungeeDebug()) { - plugin.debug("Invalid last vote time received from bungee: " + time); - } - - plugin.setUpdate(true); - } - }); - - globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_BUNGEE_TIME_CHANGE) { - @Override - public void onReceive(JsonEnvelope msg) { - checkGlobalData(); - } - }); - - globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_BROADCAST) { - @Override - public void onReceive(JsonEnvelope msg) { - Map f = msg.getFields(); - - final String uuidStr = nvl(f.get(VotingPluginWire.K_UUID)); - final String playerNameRaw = nvl(f.get(VotingPluginWire.K_PLAYER)); - final String service = nvl(f.get(VotingPluginWire.K_SERVICE)); - - if (uuidStr.isEmpty() || service.isEmpty()) { - return; - } - - UUID javaUuid; - try { - javaUuid = UUID.fromString(uuidStr); - } catch (Exception e) { - plugin.getLogger().warning("Invalid UUID in VoteBroadcast: " + uuidStr); - return; - } - - @SuppressWarnings("unused") - final long time = readLongSafe(f.get(VotingPluginWire.K_TIME), 0L); - final String totalsRaw = nvl(f.get(VotingPluginWire.K_TOTALS)); - final VoteTotalsSnapshot totals = totalsRaw.isEmpty() ? null : VoteTotalsSnapshot.parseStorage(totalsRaw); - - VoteSite voteSite = plugin.getVoteSiteManager() - .getVoteSite(plugin.getVoteSiteManager().getVoteSiteName(true, service), true); - - if (voteSite == null) { - plugin.getLogger().warning("No voting site with the service site: '" + service + "'"); - return; - } - if (!voteSite.isEnabled()) { - plugin.debug("Votesite: " + voteSite.getKey() + " is not enabled (VoteBroadcast)"); - return; - } - - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(javaUuid, playerNameRaw); - user.cache(); - user.updateName(true); - - if (plugin.getBroadcastHandler() == null) { - return; - } - - if (user.isVanished()) { - plugin.debug("Not broadcasting vote for vanished user: " + user.getPlayerName()); - return; - } - - final boolean online = f.containsKey(VotingPluginWire.K_WAS_ONLINE) - ? Boolean.parseBoolean(f.get(VotingPluginWire.K_WAS_ONLINE)) - : user.isOnline(); - plugin.getBroadcastHandler().broadcastVote(user.getJavaUUID(), user.getPlayerName(), - voteSite.getDisplayName(), online, totals); - } - }); - - globalMessageHandler.addListener(new GlobalMessageListener("Status") { - @Override - public void onReceive(JsonEnvelope msg) { - String server = nvl(msg.getFields().get("server")); - HashMap out = new HashMap<>(); - out.put("server", server); - sendSubChannel("statusokay", out); - } - }); - - globalMessageHandler.addListener(new GlobalMessageListener("ServerName") { - @Override - public void onReceive(JsonEnvelope msg) { - String server = nvl(msg.getFields().get("server")); - if (!plugin.getOptions().getServer().equals(server)) { - plugin.getLogger().warning("Server name doesn't match in BungeeSettings.yml, should be " + server); - } - } - }); - - globalMessageHandler.addListener(new GlobalMessageListener("VotePartyBungee") { - @Override - public void onReceive(JsonEnvelope msg) { - for (final String cmd : plugin.getBungeeSettings().getBungeeVotePartyGlobalCommands()) { - plugin.getBukkitScheduler().runTask(plugin, new Runnable() { - @Override - public void run() { - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), cmd); - } - }); - } - for (Player p : Bukkit.getOnlinePlayers()) { - new RewardBuilder(plugin.getBungeeSettings().getData(), "BungeeVotePartyRewards").send(p); - } - } - }); - - globalMessageHandler.addListener(new GlobalMessageListener("VotePartyBroadcast") { - @Override - public void onReceive(JsonEnvelope msg) { - String broadcast = nvl(msg.getFields().get("broadcast")); - MiscUtils.getInstance().broadcast(broadcast); - } - }); - - if (method.equals(BungeeMethod.MYSQL)) { - plugin.registerBungeeChannels(plugin.getBungeeSettings().getPluginMessagingChannel()); - - try { - backendMysqlMessenger = new MySqlMessenger("VotingPlugin", - plugin.getMysql().getMysql().getConnectionManager().getDataSource(), - MySqlMessenger.Mode.BACKEND, plugin.getOptions().getServer(), msg -> { - if (plugin.getBungeeSettings().isBungeeDebug()) { - plugin.debug("Proxy sent envelope: " + msg.envelope.getSubChannel() + " " - + msg.envelope.getFields()); - } - globalMessageHandler.onMessage(msg.envelope); - }); - } catch (SQLException e) { - e.printStackTrace(); - } - } else if (method.equals(BungeeMethod.REDIS)) { - redisHandler = new RedisHandler(plugin.getBungeeSettings().getRedisHost(), - plugin.getBungeeSettings().getRedisPort(), plugin.getBungeeSettings().getRedisUsername(), - plugin.getBungeeSettings().getRedisPassword(), plugin.getBungeeSettings().getRedisdbindex()) { - - @Override - public void debug(String message) { - if (plugin.getBungeeSettings().isBungeeDebug()) { - plugin.debug(message); - } - } - }; - - redisThread = new Thread(new Runnable() { - @Override - public void run() { - if (plugin.isEnabled()) { - RedisListener listener = redisHandler.createEnvelopeListener( - plugin.getBungeeSettings().getRedisPrefix() + "VotingPlugin_" - + plugin.getBungeeSettings().getServer(), - (ch, env) -> globalMessageHandler.onMessage(env)); - redisHandler.loadListener(listener); - } - } - }); - redisThread.start(); - - } else if (method.equals(BungeeMethod.PLUGINMESSAGING)) { - plugin.registerBungeeChannels(plugin.getBungeeSettings().getPluginMessagingChannel()); - - if (plugin.getBungeeSettings().isPluginMessageEncryption()) { - encryptionHandler = new EncryptionHandler(plugin.getName(), new File(plugin.getDataFolder(), "secretkey.key")); - plugin.getPluginMessaging().setEncryptionHandler(encryptionHandler); - } - - plugin.getPluginMessaging().setDebug(plugin.getBungeeSettings().isBungeeDebug()); - - plugin.getPluginMessaging().add(new PluginMessageHandler() { - @Override - public void onReceive(JsonEnvelope envelope) { - globalMessageHandler.onMessage(envelope); - } - }); - - } else if (method.equals(BungeeMethod.SOCKETS)) { - encryptionHandler = new EncryptionHandler(plugin.getName(), new File(plugin.getDataFolder(), "secretkey.key")); - - clientHandler = new ClientHandler(plugin.getBungeeSettings().getBungeeServerHost(), - plugin.getBungeeSettings().getBungeeServerPort(), encryptionHandler, - plugin.getBungeeSettings().isBungeeDebug()); - - socketHandler = new SocketHandler("vp-socket", plugin.getBungeeSettings().getSpigotServerHost(), - plugin.getBungeeSettings().getSpigotServerPort(), encryptionHandler, - plugin.getBungeeSettings().isBungeeDebug()) { - - @Override - public void log(String str) { - plugin.getLogger().info(str); - } - }; - - socketHandler.add(new SocketReceiver() { - @Override - public void onReceiveEnvelope(JsonEnvelope envelope) { - globalMessageHandler.onMessage(envelope); - } - }); - - } else if (method.equals(BungeeMethod.MQTT)) { - try { - String id = plugin.getBungeeSettings().getMqttClientID(); - if (id.isEmpty()) { - id = plugin.getOptions().getServer(); - } - mqttHandler = new MqttHandler(new MqttServerComm(id, plugin.getBungeeSettings().getMqttBrokerURL(), - plugin.getBungeeSettings().getMqttUsername(), plugin.getBungeeSettings().getMqttPassword()), 2); - - mqttHandler.subscribeEnvelopes(plugin.getBungeeSettings().getMqttPrefix() + "votingplugin/servers/" - + plugin.getOptions().getServer(), (topic, envelope) -> globalMessageHandler.onMessage(envelope)); - - } catch (MqttException e) { - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - bungeeVotePartyCurrent = plugin.getServerData().getBungeeVotePartyCurrent(); - bungeeVotePartyRequired = plugin.getServerData().getBungeeVotePartyRequired(); + votePartySync = new BackendVotePartySync(plugin); + messageRouter = new BackendProxyMessageRouter(plugin, presenceManager, globalDataSync, votePartySync, + processedVoteCache); + messageRouter.register(globalMessageHandler, method); + transportManager.start(method, globalMessageHandler); if (plugin.getOptions().getServer().equalsIgnoreCase("pleaseset")) { plugin.getLogger().warning("Server name for bungee voting is not set, please set it"); } - presenceManager.start(); } /** - * Announces a player login to the configured proxy transport. + * Closes backend/proxy components and persists cached proxy state. */ + public void close() { + if (presenceManager != null) { + presenceManager.stop(); + } + transportManager.close(); + if (votePartySync != null) { + votePartySync.persist(); + } + globalDataSync.close(); + } + public void playerOnline(String playerName, String uuid) { - presenceManager.playerOnline(playerName, uuid); + if (presenceManager != null) { + presenceManager.playerOnline(playerName, uuid); + } } - /** - * Announces a player disconnect when backend presence is supported. - */ public void playerOffline(String playerName) { - presenceManager.playerOffline(playerName); + if (presenceManager != null) { + presenceManager.playerOffline(playerName); + } } - /** - * Restarts presence reporting when the configured backend identity changes. - */ public void reloadPresenceReporting() { if (presenceManager != null) { presenceManager.reload(); } } - /** - * Stops presence reporting without closing the global-message handler. - */ public void disablePresenceReporting() { if (presenceManager != null) { presenceManager.stop(); } } - private static long readLongSafe(String v, long def) { - if (v == null) - return def; - try { - return Long.parseLong(v); - } catch (Exception ignored) { - return def; - } + public void loadGlobalMysql() { + globalDataSync.load(); } - 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); + public void checkGlobalData() { + globalDataSync.checkGlobalData(); } - /** - * Wire vote handler (Vote + VoteOnline). - */ - private void handleWireVote(JsonEnvelope msg) { - int schema = msg.getSchema(); - if (schema != VotingPluginWire.SCHEMA_VERSION) { - plugin.getLogger().warning("Incompatible version with bungee/proxy, please update all servers: " + schema - + " != " + VotingPluginWire.SCHEMA_VERSION); - return; - } - - VotingPluginWire.Vote v = VotingPluginWire.readVote(msg); - - String uuidStr = v.uuid; - String player = v.player; - String service = v.service; - - if (uuidStr == null || uuidStr.isEmpty()) { - return; - } - if (!ServiceSiteValidator.isValid(service)) { - plugin.getLogger().warning("Rejected proxy vote with invalid service site '" - + ServiceSiteValidator.sanitizeForLog(service) + "'"); - return; - } - - plugin.debug("wire vote received from " + player + "/" + uuidStr + " on " + service); - - VoteTotalsSnapshot text = VoteTotalsSnapshot.parseStorage(v.totals == null ? "" : v.totals); - @SuppressWarnings("deprecation") - UUID voteId = v.voteId != null ? v.voteId : text.getVoteUUID(); - - if (!reserveWireVote(voteId)) { - plugin.debug("Ignoring duplicate wire vote " + voteId + " for " + player + " on " + service); - return; - } - - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(UUID.fromString(uuidStr), player); - - bungeeVotePartyCurrent = text.getVotePartyCurrent(); - bungeeVotePartyRequired = text.getVotePartyRequired(); - plugin.getServerData().setBungeeVotePartyCurrent(bungeeVotePartyCurrent); - plugin.getServerData().setBungeeVotePartyRequired(bungeeVotePartyRequired); - - user.cache(); - - boolean setTotalsOnBackend = !v.manageTotals; - user.bungeeVotePluginMessaging(service, v.time, text, setTotalsOnBackend, v.wasOnline, v.broadcast, v.num); - - if (plugin.getBungeeSettings().isPerServerPoints()) { - user.addPoints(plugin.getConfigFile().getPointsOnVote()); - } - - if (service != null && !service.isEmpty()) { - plugin.getServerData().addServiceSite(service); - } - - @SuppressWarnings("unused") - int _ignored = v.numberOfVotes; + public boolean checkGlobalDataTime(TimeType type, HashMap data) { + return globalDataSync.checkGlobalDataTime(type, data); } - private boolean reserveWireVote(UUID voteId) { - if (voteId == null) { - return true; - } + public boolean checkGlobalDataTimeValue(DataValue data) { + return globalDataSync.checkGlobalDataTimeValue(data); + } - long now = System.currentTimeMillis(); - long expiresAt = now + PROCESSED_VOTE_TTL_MILLIS; - - while (true) { - Long currentExpiry = processedWireVotes.get(voteId); - if (currentExpiry == null) { - if (processedWireVotes.putIfAbsent(voteId, expiresAt) == null) { - cleanupProcessedWireVotes(now); - return true; - } - continue; - } + public ConcurrentHashMap getProcessedWireVotes() { + return processedVoteCache.getProcessedVotes(); + } - if (currentExpiry > now) { - return false; - } + public int getBungeeVotePartyCurrent() { + return votePartySync == null ? plugin.getServerData().getBungeeVotePartyCurrent() : votePartySync.getCurrent(); + } - if (processedWireVotes.replace(voteId, currentExpiry, expiresAt)) { - cleanupProcessedWireVotes(now); - return true; - } - } + public int getBungeeVotePartyRequired() { + return votePartySync == null ? plugin.getServerData().getBungeeVotePartyRequired() : votePartySync.getRequired(); } - private void cleanupProcessedWireVotes(long now) { - processedWireVotes.entrySet().removeIf(entry -> entry.getValue() <= now); + public ScheduledExecutorService getTimer() { + return globalDataSync.getTimer(); } - /** - * Loads the global MySQL handler for cross-server data synchronization. - */ - public void loadGlobalMysql() { - if (plugin.getBungeeSettings().isGloblalDataEnabled()) { - if (timer != null) { - timer.shutdown(); - try { - timer.awaitTermination(5, TimeUnit.SECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } - timer.shutdownNow(); - } - timer = Executors.newScheduledThreadPool(1); - timer.scheduleWithFixedDelay(new Runnable() { - @Override - public void run() { - checkGlobalData(); - } - }, 60, 10, TimeUnit.SECONDS); - timer.scheduleWithFixedDelay(new Runnable() { - @Override - public void run() { - globalDataHandler.setString(plugin.getBungeeSettings().getServer(), "LastOnline", - "" + LocalDateTime.now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()); - } - }, 1, 60, TimeUnit.MINUTES); - - if (globalDataHandler != null) { - globalDataHandler.getGlobalMysql().close(); - } + public ClientHandler getClientHandler() { + return transportManager.getClientHandler(); + } - if (plugin.getBungeeSettings().isGloblalDataUseMainMySQL() - && plugin.getStorageType().equals(UserStorage.MYSQL)) { - globalDataHandler = new GlobalDataHandler( - new GlobalMySQL("VotingPlugin_GlobalData", plugin.getMysql().getMysql()) { - @Override - public void debugEx(Exception e) { - plugin.debug(e); - } - - @Override - public void debugLog(String text) { - plugin.debug(text); - } - - @Override - public void info(String text) { - plugin.getLogger().info(text); - } - - @Override - public void logSevere(String text) { - plugin.getLogger().severe(text); - } - - @Override - public void warning(String text) { - plugin.getLogger().warning(text); - } - }); - } else { - globalDataHandler = new GlobalDataHandler( - new GlobalMySQL("VotingPlugin_GlobalData", new MysqlConfigSpigot( - plugin.getBungeeSettings().getData().getConfigurationSection("GlobalData"))) { - @Override - public void debugEx(Exception e) { - plugin.debug(e); - } - - @Override - public void debugLog(String text) { - plugin.debug(text); - } - - @Override - public void info(String text) { - plugin.getLogger().info(text); - } - - @Override - public void logSevere(String text) { - plugin.getLogger().severe(text); - } - - @Override - public void warning(String text) { - plugin.getLogger().warning(text); - } - }); - } + public SocketHandler getSocketHandler() { + return transportManager.getSocketHandler(); + } - globalDataHandler.getGlobalMysql().alterColumnType("IgnoreTime", "VARCHAR(5)"); - globalDataHandler.getGlobalMysql().alterColumnType("MONTH", "VARCHAR(5)"); - globalDataHandler.getGlobalMysql().alterColumnType("WEEK", "VARCHAR(5)"); - globalDataHandler.getGlobalMysql().alterColumnType("DAY", "VARCHAR(5)"); - globalDataHandler.getGlobalMysql().alterColumnType("FinishedProcessing", "VARCHAR(5)"); - globalDataHandler.getGlobalMysql().alterColumnType("Processing", "VARCHAR(5)"); - globalDataHandler.getGlobalMysql().alterColumnType("LastUpdated", "MEDIUMTEXT"); - globalDataHandler.getGlobalMysql().alterColumnType("ForceUpdate", "VARCHAR(5)"); - plugin.getTimeChecker().setProcessingEnabled(false); - } + public RedisHandler getRedisHandler() { + return transportManager.getRedisHandler(); } - private void sendEnvelopeSocket(JsonEnvelope envelope) { - if (clientHandler != null) { - clientHandler.sendEnvelope(envelope); - } + public MySqlMessenger getBackendMysqlMessenger() { + return transportManager.getBackendMysqlMessenger(); } - private void sendSubChannel(String subChannel, HashMap fields) { - JsonEnvelope.Builder b = JsonEnvelope.builder(subChannel).schema(VotingPluginWire.SCHEMA_VERSION); - if (fields != null) { - for (Map.Entry e : fields.entrySet()) { - b.put(e.getKey(), e.getValue()); - } - } - globalMessageHandler.sendMessage(b.build()); + public MqttHandler getMqttHandler() { + return transportManager.getMqttHandler(); } - private static String nvl(String s) { - return s == null ? "" : s; + private void sendEnvelope(JsonEnvelope envelope) { + if (globalMessageHandler != null) { + globalMessageHandler.sendMessage(envelope); + } } } From ad2b36018f675205a3d0b7b4a5911368a4562b41 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:12:01 -0600 Subject: [PATCH 13/71] Add directly defined reward path helper --- .../rewards/DirectlyDefinedRewardPath.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/DirectlyDefinedRewardPath.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/DirectlyDefinedRewardPath.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/DirectlyDefinedRewardPath.java new file mode 100644 index 0000000000..b48ec0edaa --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/DirectlyDefinedRewardPath.java @@ -0,0 +1,39 @@ +package com.bencodez.votingplugin.rewards; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.advancedcore.api.rewards.DirectlyDefinedReward; +import com.bencodez.simpleapi.file.YMLFile; + +/** + * Creates directly-defined reward editors backed by a VotingPlugin YAML file. + */ +public final class DirectlyDefinedRewardPath { + + private DirectlyDefinedRewardPath() { + } + + public static DirectlyDefinedReward of(String path, YMLFile file) { + return new DirectlyDefinedReward(path) { + @Override + public void createSection(String key) { + file.createSection(key); + } + + @Override + public ConfigurationSection getFileData() { + return file.getData(); + } + + @Override + public void save() { + file.saveData(); + } + + @Override + public void setData(String dataPath, Object value) { + file.setValue(dataPath, value); + } + }; + } +} From 1f538a5725d0c8a8bed136b647863ddd1445108d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:12:13 -0600 Subject: [PATCH 14/71] Move vote reminder reward path registration --- .../VoteReminderRewardRegistrar.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/votereminding/VoteReminderRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/votereminding/VoteReminderRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votereminding/VoteReminderRewardRegistrar.java new file mode 100644 index 0000000000..0e79779acd --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votereminding/VoteReminderRewardRegistrar.java @@ -0,0 +1,31 @@ +package com.bencodez.votingplugin.votereminding; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.advancedcore.api.rewards.DirectlyDefinedReward; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined vote reminder reward paths. */ +public final class VoteReminderRewardRegistrar { + + private VoteReminderRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + plugin.addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteReminderOptions.Defaults.Rewards") { + @Override public void createSection(String key) { plugin.getConfigFile().saveData(); } + @Override public ConfigurationSection getFileData() { return plugin.getConfigFile().getData(); } + @Override public void save() { plugin.getConfigFile().saveData(); } + @Override public void setData(String path, Object value) { plugin.getConfigFile().setValue(path, value); } + }); + + ConfigurationSection reminders = plugin.getConfigFile().getData().getConfigurationSection("VoteReminders"); + if (reminders != null) { + for (String key : reminders.getKeys(false)) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of("VoteReminders." + key + ".Rewards", + plugin.getConfigFile())); + } + } + } +} From 847349446642be3b81505a96419e8a15ed80cca6 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:12:23 -0600 Subject: [PATCH 15/71] Move vote site reward path registration --- .../votesites/VoteSiteRewardRegistrar.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSiteRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSiteRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSiteRewardRegistrar.java new file mode 100644 index 0000000000..2ce1301c78 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSiteRewardRegistrar.java @@ -0,0 +1,25 @@ +package com.bencodez.votingplugin.votesites; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined vote-site reward paths. */ +public final class VoteSiteRewardRegistrar { + + private VoteSiteRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of("AnySiteRewards", plugin.getSpecialRewardsConfig())); + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of("EverySiteReward", plugin.getConfigVoteSites())); + + for (VoteSite site : plugin.getVoteSiteManager().getVoteSites()) { + String base = "VoteSites." + site.getKey(); + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of(base + ".Rewards", plugin.getConfigVoteSites())); + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of(base + ".WaitUntilVoteDelayRewards", + plugin.getConfigVoteSites())); + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of(base + ".CoolDownEndRewards", + plugin.getConfigVoteSites())); + } + } +} From cce2ad3325dd92b38fd71a07b5516980249bcfe9 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:12:32 -0600 Subject: [PATCH 16/71] Move general special reward path registration --- .../SpecialRewardsRewardRegistrar.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewardsRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewardsRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewardsRewardRegistrar.java new file mode 100644 index 0000000000..c7b6a6bdd9 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewardsRewardRegistrar.java @@ -0,0 +1,37 @@ +package com.bencodez.votingplugin.specialrewards; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined general and legacy special reward paths. */ +public final class SpecialRewardsRewardRegistrar { + + private SpecialRewardsRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + String[] simplePaths = { + "VoteCoolDownEndedReward", "LoginRewards", "LogoutRewards", + "AllSites", "AlmostAllSites", "FirstVote", "FirstVoteToday", "NameMCLikeReward.Rewards" + }; + for (String path : simplePaths) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of(path, plugin.getSpecialRewardsConfig())); + } + + registerLegacyGroup(plugin, "Cumulative"); + registerLegacyGroup(plugin, "Milestones"); + } + + private static void registerLegacyGroup(VotingPluginMain plugin, String key) { + ConfigurationSection section = plugin.getSpecialRewardsConfig().getData().getConfigurationSection(key); + if (section == null) { + return; + } + for (String entry : section.getKeys(false)) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of(key + "." + entry + ".Rewards", + plugin.getSpecialRewardsConfig())); + } + } +} From b4304f69fb20dd640b52b6499efb155e00a9cb6a Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:12:43 -0600 Subject: [PATCH 17/71] Move vote party reward path registration --- .../voteparty/VotePartyRewardRegistrar.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyRewardRegistrar.java new file mode 100644 index 0000000000..50ddd13fe9 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyRewardRegistrar.java @@ -0,0 +1,16 @@ +package com.bencodez.votingplugin.specialrewards.voteparty; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined vote-party reward paths. */ +public final class VotePartyRewardRegistrar { + + private VotePartyRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of("VoteParty.Rewards", + plugin.getSpecialRewardsConfig())); + } +} From 87dc19cfea203a512613294528bfbdb9ec1328ad Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:12:55 -0600 Subject: [PATCH 18/71] Move vote milestone reward path registration --- .../VoteMilestoneRewardRegistrar.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/votemilestones/VoteMilestoneRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/votemilestones/VoteMilestoneRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/votemilestones/VoteMilestoneRewardRegistrar.java new file mode 100644 index 0000000000..8073e5b5e8 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/votemilestones/VoteMilestoneRewardRegistrar.java @@ -0,0 +1,25 @@ +package com.bencodez.votingplugin.specialrewards.votemilestones; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined VoteMilestones reward paths. */ +public final class VoteMilestoneRewardRegistrar { + + private VoteMilestoneRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + ConfigurationSection section = plugin.getSpecialRewardsConfig().getData() + .getConfigurationSection("VoteMilestones"); + if (section == null) { + return; + } + for (String milestoneId : section.getKeys(false)) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + "VoteMilestones." + milestoneId + ".Rewards", plugin.getSpecialRewardsConfig())); + } + } +} From b91ae03c969e0266ef81335c5d318a9da5cc1932 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:13:12 -0600 Subject: [PATCH 19/71] Move vote streak reward path registration --- .../votestreak/VoteStreakRewardRegistrar.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/votestreak/VoteStreakRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/votestreak/VoteStreakRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/votestreak/VoteStreakRewardRegistrar.java new file mode 100644 index 0000000000..f74fb5a9d0 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/votestreak/VoteStreakRewardRegistrar.java @@ -0,0 +1,67 @@ +package com.bencodez.votingplugin.specialrewards.votestreak; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined vote-streak reward paths. */ +public final class VoteStreakRewardRegistrar { + + private VoteStreakRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + registerCurrent(plugin); + registerLegacy(plugin); + } + + private static void registerCurrent(VotingPluginMain plugin) { + ConfigurationSection streaks = plugin.getSpecialRewardsConfig().getData().getConfigurationSection("VoteStreaks"); + if (streaks == null) { + return; + } + + for (String streakId : streaks.getKeys(false)) { + if ("ProgressGroups".equalsIgnoreCase(streakId) || streaks.getConfigurationSection(streakId) == null) { + continue; + } + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + "VoteStreaks." + streakId + ".Rewards", plugin.getSpecialRewardsConfig())); + } + + ConfigurationSection groups = streaks.getConfigurationSection("ProgressGroups"); + if (groups == null) { + return; + } + for (String groupId : groups.getKeys(false)) { + ConfigurationSection group = groups.getConfigurationSection(groupId); + if (group == null) { + continue; + } + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + "VoteStreaks.ProgressGroups." + groupId + ".LostRewards", plugin.getSpecialRewardsConfig())); + ConfigurationSection milestones = group.getConfigurationSection("Milestones"); + if (milestones == null) { + continue; + } + for (String milestoneId : milestones.getKeys(false)) { + if (milestones.getConfigurationSection(milestoneId) == null) { + continue; + } + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + "VoteStreaks.ProgressGroups." + groupId + ".Milestones." + milestoneId + ".Rewards", + plugin.getSpecialRewardsConfig())); + } + } + } + + private static void registerLegacy(VotingPluginMain plugin) { + for (String type : new String[] { "Day", "Week", "Month" }) { + for (String value : plugin.getSpecialRewardsConfig().getVoteStreakVotes(type)) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + "VoteStreak." + type + "." + value + ".Rewards", plugin.getSpecialRewardsConfig())); + } + } + } +} From 42f7b931b31a0e7cf4178712f2defa723ab9cb7d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:13:21 -0600 Subject: [PATCH 20/71] Move top voter reward path registration --- .../topvoter/TopVoterRewardRegistrar.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRewardRegistrar.java new file mode 100644 index 0000000000..c03120151c --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRewardRegistrar.java @@ -0,0 +1,26 @@ +package com.bencodez.votingplugin.topvoter; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined top-voter award reward paths. */ +public final class TopVoterRewardRegistrar { + + private TopVoterRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + for (String path : plugin.getSpecialRewardsConfig().getMonthlyPossibleRewardPlaces()) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + plugin.getSpecialRewardsConfig().getMonthlyAwardRewardsPath(path), plugin.getSpecialRewardsConfig())); + } + for (String path : plugin.getSpecialRewardsConfig().getWeeklyPossibleRewardPlaces()) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + plugin.getSpecialRewardsConfig().getWeeklyAwardRewardsPath(path), plugin.getSpecialRewardsConfig())); + } + for (String path : plugin.getSpecialRewardsConfig().getDailyPossibleRewardPlaces()) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + plugin.getSpecialRewardsConfig().getDailyAwardRewardsPath(path), plugin.getSpecialRewardsConfig())); + } + } +} From 2fd72704417ffcef33d8d48e9b9799b4eed89e9d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:13:29 -0600 Subject: [PATCH 21/71] Move vote shop reward path registration --- .../voteshop/VoteShopRewardRegistrar.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/voteshop/VoteShopRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/voteshop/VoteShopRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/voteshop/VoteShopRewardRegistrar.java new file mode 100644 index 0000000000..e477c0854e --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/voteshop/VoteShopRewardRegistrar.java @@ -0,0 +1,35 @@ +package com.bencodez.votingplugin.voteshop; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined vote-shop reward paths. */ +public final class VoteShopRewardRegistrar { + + private VoteShopRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + for (String identifier : plugin.getShopFile().getShopIdentifiers()) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of("Shop." + identifier + ".Rewards", + plugin.getShopFile())); + } + + ConfigurationSection categories = plugin.getShopFile().getCategoriesSection(); + if (categories == null) { + return; + } + for (String category : categories.getKeys(false)) { + ConfigurationSection shop = plugin.getShopFile().getCategoryShopSection(category); + if (shop == null) { + continue; + } + for (String item : shop.getKeys(false)) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of( + "Categories." + category + "." + item + ".Rewards", plugin.getShopFile())); + } + } + } +} From 7164e2c5181941267411387c6835483172c18056 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:13:41 -0600 Subject: [PATCH 22/71] Move backend proxy reward path registration --- .../BackendProxyRewardRegistrar.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/BackendProxyRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/BackendProxyRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/BackendProxyRewardRegistrar.java new file mode 100644 index 0000000000..87475240dd --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backendproxy/BackendProxyRewardRegistrar.java @@ -0,0 +1,16 @@ +package com.bencodez.votingplugin.backendproxy; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.DirectlyDefinedRewardPath; + +/** Registers directly-defined backend/proxy reward paths. */ +public final class BackendProxyRewardRegistrar { + + private BackendProxyRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + plugin.addDirectlyDefinedRewards(DirectlyDefinedRewardPath.of("BungeeVotePartyRewards", + plugin.getBungeeSettings())); + } +} From ec717f6b820896e79eba358857cbb264686a5af5 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:13:57 -0600 Subject: [PATCH 23/71] Test processed vote cache extraction --- .../cache/ProcessedVoteCacheTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backendproxy/cache/ProcessedVoteCacheTest.java diff --git a/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backendproxy/cache/ProcessedVoteCacheTest.java b/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backendproxy/cache/ProcessedVoteCacheTest.java new file mode 100644 index 0000000000..883d906749 --- /dev/null +++ b/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backendproxy/cache/ProcessedVoteCacheTest.java @@ -0,0 +1,37 @@ +package com.bencodez.votingplugin.tests.backendproxy.cache; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.UUID; + +import org.junit.jupiter.api.Test; + +import com.bencodez.votingplugin.backendproxy.cache.ProcessedVoteCache; + +public class ProcessedVoteCacheTest { + + @Test + public void duplicateVoteIdIsRejected() { + ProcessedVoteCache cache = new ProcessedVoteCache(); + UUID voteId = UUID.randomUUID(); + assertTrue(cache.reserve(voteId)); + assertFalse(cache.reserve(voteId)); + } + + @Test + public void nullVoteIdsRemainCompatible() { + ProcessedVoteCache cache = new ProcessedVoteCache(); + assertTrue(cache.reserve(null)); + assertTrue(cache.reserve(null)); + } + + @Test + public void expiredVoteIdCanBeReservedAgain() throws Exception { + ProcessedVoteCache cache = new ProcessedVoteCache(1); + UUID voteId = UUID.randomUUID(); + assertTrue(cache.reserve(voteId)); + Thread.sleep(5); + assertTrue(cache.reserve(voteId)); + } +} From 1ba3f87f389d7353317bc6eae5ed8678cbf2dbf2 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:14:16 -0600 Subject: [PATCH 24/71] Run backend proxy component refactor --- .../refactor-backendproxy-components.yml | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 .github/workflows/refactor-backendproxy-components.yml diff --git a/.github/workflows/refactor-backendproxy-components.yml b/.github/workflows/refactor-backendproxy-components.yml new file mode 100644 index 0000000000..e483be1a08 --- /dev/null +++ b/.github/workflows/refactor-backendproxy-components.yml @@ -0,0 +1,75 @@ +name: Refactor backend proxy components + +on: + pull_request: + branches: + - master + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + refactor: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: refactor/backendproxy-components + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + - name: Replace directly-defined reward orchestration + run: | + python - <<'PY' + from pathlib import Path + + path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') + text = path.read_text() + + imports = { + 'import com.bencodez.votingplugin.backendproxy.BackendProxyHandler;\n': 'import com.bencodez.votingplugin.backendproxy.BackendProxyHandler;\nimport com.bencodez.votingplugin.backendproxy.BackendProxyRewardRegistrar;\n', + 'import com.bencodez.votingplugin.specialrewards.SpecialRewards;\n': 'import com.bencodez.votingplugin.specialrewards.SpecialRewards;\nimport com.bencodez.votingplugin.specialrewards.SpecialRewardsRewardRegistrar;\n', + 'import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestonesManager;\n': 'import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestoneRewardRegistrar;\nimport com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestonesManager;\n', + 'import com.bencodez.votingplugin.specialrewards.voteparty.VoteParty;\n': 'import com.bencodez.votingplugin.specialrewards.voteparty.VoteParty;\nimport com.bencodez.votingplugin.specialrewards.voteparty.VotePartyRewardRegistrar;\n', + 'import com.bencodez.votingplugin.specialrewards.votestreak.VoteStreakHandler;\n': 'import com.bencodez.votingplugin.specialrewards.votestreak.VoteStreakHandler;\nimport com.bencodez.votingplugin.specialrewards.votestreak.VoteStreakRewardRegistrar;\n', + 'import com.bencodez.votingplugin.topvoter.TopVoterState;\n': 'import com.bencodez.votingplugin.topvoter.TopVoterState;\nimport com.bencodez.votingplugin.topvoter.TopVoterRewardRegistrar;\n', + 'import com.bencodez.votingplugin.votereminding.VoteRemindersManager;\n': 'import com.bencodez.votingplugin.votereminding.VoteReminderRewardRegistrar;\nimport com.bencodez.votingplugin.votereminding.VoteRemindersManager;\n', + 'import com.bencodez.votingplugin.voteshop.VoteShopManager;\n': 'import com.bencodez.votingplugin.voteshop.VoteShopManager;\nimport com.bencodez.votingplugin.voteshop.VoteShopRewardRegistrar;\n', + 'import com.bencodez.votingplugin.votesites.VoteSiteManager;\n': 'import com.bencodez.votingplugin.votesites.VoteSiteManager;\nimport com.bencodez.votingplugin.votesites.VoteSiteRewardRegistrar;\n', + } + for old, new in imports.items(): + if new not in text: + if old not in text: + raise SystemExit('import anchor not found: ' + old.strip()) + text = text.replace(old, new, 1) + + start_marker = '\tprivate void addSpecialRewardsEditorPath(String rewardPath) {' + end_marker = '\n\tprivate void loadTimer() {' + start = text.find(start_marker) + end = text.find(end_marker, start) + if start < 0 or end < 0: + raise SystemExit('directly-defined block markers not found') + + replacement = '''\tpublic void loadDirectlyDefined() {\n\t\tgetRewardHandler().getDirectlyDefinedRewards().clear();\n\n\t\tVoteReminderRewardRegistrar.register(this);\n\t\tSpecialRewardsRewardRegistrar.register(this);\n\t\tVoteSiteRewardRegistrar.register(this);\n\t\tVotePartyRewardRegistrar.register(this);\n\t\tVoteMilestoneRewardRegistrar.register(this);\n\t\tVoteStreakRewardRegistrar.register(this);\n\t\tTopVoterRewardRegistrar.register(this);\n\t\tVoteShopRewardRegistrar.register(this);\n\t\tBackendProxyRewardRegistrar.register(this);\n\n\t\tgetRewardHandler().checkDirectlyDefined();\n\t}\n''' + text = text[:start] + replacement + text[end:] + path.write_text(text) + PY + - name: Build + run: mvn -B -f VotingPlugin/pom.xml package + - name: Commit refactor + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A VotingPlugin + git commit -m 'Split backend proxy components and reward path ownership' + git push origin HEAD:refactor/backendproxy-components + - name: Remove temporary workflow + run: | + git pull --rebase origin refactor/backendproxy-components + git rm .github/workflows/refactor-backendproxy-components.yml + git commit -m 'Remove temporary refactor workflow' + git push origin HEAD:refactor/backendproxy-components From 408cb931fd8d6247f6f46857653e4a9656d743d9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 23:15:03 +0000 Subject: [PATCH 25/71] Split backend proxy components and reward path ownership --- .../votingplugin/VotingPluginMain.java | 736 +----------------- 1 file changed, 18 insertions(+), 718 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java index 875c6a4fec..2f351ef0b1 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java @@ -62,6 +62,7 @@ import com.bencodez.simpleapi.updater.Updater; import com.bencodez.votingplugin.broadcast.BroadcastHandler; import com.bencodez.votingplugin.backendproxy.BackendProxyHandler; +import com.bencodez.votingplugin.backendproxy.BackendProxyRewardRegistrar; import com.bencodez.votingplugin.broadcast.BroadcastSettings; import com.bencodez.votingplugin.commands.CommandLoader; import com.bencodez.votingplugin.commands.executers.CommandAdminVote; @@ -94,15 +95,20 @@ import com.bencodez.votingplugin.signs.Signs; import com.bencodez.votingplugin.specialrewards.NameMCLikeCheckerTask; import com.bencodez.votingplugin.specialrewards.SpecialRewards; +import com.bencodez.votingplugin.specialrewards.SpecialRewardsRewardRegistrar; +import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestoneRewardRegistrar; import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestonesManager; import com.bencodez.votingplugin.specialrewards.voteparty.VoteParty; +import com.bencodez.votingplugin.specialrewards.voteparty.VotePartyRewardRegistrar; import com.bencodez.votingplugin.specialrewards.votestreak.VoteStreakHandler; +import com.bencodez.votingplugin.specialrewards.votestreak.VoteStreakRewardRegistrar; import com.bencodez.votingplugin.test.VoteTester; import com.bencodez.votingplugin.timequeue.TimeQueueHandler; import com.bencodez.votingplugin.topvoter.TopVoter; import com.bencodez.votingplugin.topvoter.TopVoterHandler; import com.bencodez.votingplugin.topvoter.TopVoterPlayer; import com.bencodez.votingplugin.topvoter.TopVoterState; +import com.bencodez.votingplugin.topvoter.TopVoterRewardRegistrar; import com.bencodez.votingplugin.updater.CheckUpdate; import com.bencodez.votingplugin.user.UserManager; import com.bencodez.votingplugin.user.VotingPluginUser; @@ -113,11 +119,14 @@ import com.bencodez.votingplugin.votelog.listeners.VoteShopPurchaseLoggerListener; import com.bencodez.votingplugin.votereminding.VoteRemindersLegacyMigrator; import com.bencodez.votingplugin.votereminding.VoteRemindersListener; +import com.bencodez.votingplugin.votereminding.VoteReminderRewardRegistrar; import com.bencodez.votingplugin.votereminding.VoteRemindersManager; import com.bencodez.votingplugin.votereminding.store.UserDataVoteReminderCooldownStore; import com.bencodez.votingplugin.voteshop.VoteShopManager; +import com.bencodez.votingplugin.voteshop.VoteShopRewardRegistrar; import com.bencodez.votingplugin.votesites.VoteSite; import com.bencodez.votingplugin.votesites.VoteSiteManager; +import com.bencodez.votingplugin.votesites.VoteSiteRewardRegistrar; import com.bencodez.votingplugin.webhook.VotingPluginWebhooks; import com.bencodez.votingplugin.webhook.WebhookRewardEntry; import com.bencodez.votingplugin.webhook.WebhookRewardParser; @@ -469,729 +478,20 @@ private void loadBungeeHandler() { * * @param rewardPath full configuration path to the rewards section */ - private void addSpecialRewardsEditorPath(String rewardPath) { - addDirectlyDefinedRewards(new DirectlyDefinedReward(rewardPath) { - - @Override - public void setData(String path, Object value) { - plugin.getSpecialRewardsConfig().getData().set(path, value); - } - - @Override - public void createSection(String key) { - plugin.getSpecialRewardsConfig().getData().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return plugin.getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - plugin.getSpecialRewardsConfig().saveData(); - } - }); - } - public void loadDirectlyDefined() { getRewardHandler().getDirectlyDefinedRewards().clear(); - addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteReminderOptions.Defaults.Rewards") { - - @Override - public void createSection(String key) { - getConfigFile().saveData(); - } - - @Override - public ConfigurationSection getFileData() { - return getConfigFile().getData(); - } - - @Override - public void save() { - getConfigFile().saveData(); - } - - @Override - public void setData(String path, Object value) { - getConfigFile().setValue(path, value); - } - }); - - ConfigurationSection sec = getConfigFile().getData().getConfigurationSection("VoteReminders"); - - if (sec != null) { - for (String key : sec.getKeys(false)) { - addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteReminders." + key + ".Rewards") { - - @Override - public void createSection(String key) { - getConfigFile().saveData(); - } - - @Override - public ConfigurationSection getFileData() { - return getConfigFile().getData(); - } - - @Override - public void save() { - getConfigFile().saveData(); - } - - @Override - public void setData(String path, Object value) { - getConfigFile().setValue(path, value); - } - }); - } - } - - // vote cooldown ended - addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteCoolDownEndedReward") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - // any site rewards - addDirectlyDefinedRewards(new DirectlyDefinedReward("AnySiteRewards") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - addDirectlyDefinedRewards(new DirectlyDefinedReward("EverySiteReward") { - - @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); - } - }); - - // login rewards - addDirectlyDefinedRewards(new DirectlyDefinedReward("LoginRewards") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - // logout rewards - addDirectlyDefinedRewards(new DirectlyDefinedReward("LogoutRewards") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - // VoteParty - addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteParty.Rewards") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - // legacy reward handlng for migrator - if (getSpecialRewardsConfig().getData().getConfigurationSection("Cumulative") != null) { - for (String num : getSpecialRewardsConfig().getData().getConfigurationSection("Cumulative") - .getKeys(false)) { - addDirectlyDefinedRewards(new DirectlyDefinedReward("Cumulative." + num + ".Rewards") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - } - } - - if (getSpecialRewardsConfig().getData().getConfigurationSection("Milestones") != null) { - for (String num : getSpecialRewardsConfig().getData().getConfigurationSection("Milestones") - .getKeys(false)) { - addDirectlyDefinedRewards(new DirectlyDefinedReward("Milestones." + num + ".Rewards") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - } - } - - // legacy for migrator - addDirectlyDefinedRewards(new DirectlyDefinedReward("AllSites") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - // legacy for migrator - addDirectlyDefinedRewards(new DirectlyDefinedReward("AlmostAllSites") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - // legacy for migrator - addDirectlyDefinedRewards(new DirectlyDefinedReward("FirstVote") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - // legacy for migrator - addDirectlyDefinedRewards(new DirectlyDefinedReward("FirstVoteToday") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - // VoteSites - for (VoteSite site : plugin.getVoteSiteManager().getVoteSites()) { - addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteSites." + site.getKey() + ".Rewards") { - - @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() + ".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 - 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); - } - }); - } - - ConfigurationSection voteMilestonesSection = plugin.getSpecialRewardsConfig().getData() - .getConfigurationSection("VoteMilestones"); - - if (voteMilestonesSection != null) { - for (String milestoneId : voteMilestonesSection.getKeys(false)) { - addSpecialRewardsEditorPath("VoteMilestones." + milestoneId + ".Rewards"); - } - } - - // VoteStreak rewards - ConfigurationSection voteStreaksSection = plugin.getSpecialRewardsConfig().getData() - .getConfigurationSection("VoteStreaks"); - - if (voteStreaksSection != null) { - for (String streakId : voteStreaksSection.getKeys(false)) { - if ("ProgressGroups".equalsIgnoreCase(streakId)) { - continue; - } - - ConfigurationSection streakSection = voteStreaksSection.getConfigurationSection(streakId); - if (streakSection == null) { - continue; - } - - addSpecialRewardsEditorPath("VoteStreaks." + streakId + ".Rewards"); - } - - ConfigurationSection progressGroupsSection = voteStreaksSection.getConfigurationSection("ProgressGroups"); - - if (progressGroupsSection != null) { - for (String groupId : progressGroupsSection.getKeys(false)) { - ConfigurationSection groupSection = progressGroupsSection.getConfigurationSection(groupId); - if (groupSection == null) { - continue; - } - - addSpecialRewardsEditorPath( - "VoteStreaks.ProgressGroups." + groupId + ".LostRewards"); - - ConfigurationSection milestonesSection = groupSection.getConfigurationSection("Milestones"); - if (milestonesSection == null) { - continue; - } - - for (String milestoneId : milestonesSection.getKeys(false)) { - ConfigurationSection milestoneSection = milestonesSection - .getConfigurationSection(milestoneId); - - if (milestoneSection == null) { - continue; - } - - addSpecialRewardsEditorPath( - "VoteStreaks.ProgressGroups." + groupId - + ".Milestones." + milestoneId + ".Rewards"); - } - } - } - } - - // vote streaks, old way - String[] types = new String[] { "Day", "Week", "Month" }; - for (String type : types) { - for (String str : plugin.getSpecialRewardsConfig().getVoteStreakVotes(type)) { - addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteStreak." + type + "." + str + ".Rewards") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - } - } - - for (String path : plugin.getSpecialRewardsConfig().getMonthlyPossibleRewardPlaces()) { - addDirectlyDefinedRewards( - new DirectlyDefinedReward(plugin.getSpecialRewardsConfig().getMonthlyAwardRewardsPath(path)) { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - } - - for (String path : plugin.getSpecialRewardsConfig().getWeeklyPossibleRewardPlaces()) { - addDirectlyDefinedRewards( - new DirectlyDefinedReward(plugin.getSpecialRewardsConfig().getWeeklyAwardRewardsPath(path)) { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - } - - for (String path : plugin.getSpecialRewardsConfig().getDailyPossibleRewardPlaces()) { - addDirectlyDefinedRewards( - new DirectlyDefinedReward(plugin.getSpecialRewardsConfig().getDailyAwardRewardsPath(path)) { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - } - - for (String identifier : plugin.getShopFile().getShopIdentifiers()) { - addDirectlyDefinedRewards(new DirectlyDefinedReward("Shop." + identifier + ".Rewards") { - - @Override - public void createSection(String key) { - getShopFile().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getShopFile().getData(); - } - - @Override - public void save() { - getShopFile().saveData(); - } - - @Override - public void setData(String path, Object value) { - getShopFile().setValue(path, value); - } - }); - } - - ConfigurationSection categoriesSection = plugin.getShopFile().getCategoriesSection(); - if (categoriesSection != null) { - for (String categoryShop : categoriesSection.getKeys(false)) { - if (plugin.getShopFile().getCategoryShopSection(categoryShop) != null) { - for (String categoryShopItems : plugin.getShopFile().getCategoryShopSection(categoryShop) - .getKeys(false)) { - addDirectlyDefinedRewards(new DirectlyDefinedReward( - "Categories." + categoryShop + "." + categoryShopItems + ".Rewards") { - - @Override - public void createSection(String key) { - getShopFile().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getShopFile().getData(); - } - - @Override - public void save() { - getShopFile().saveData(); - } - - @Override - public void setData(String path, Object value) { - getShopFile().setValue(path, value); - } - }); - } - } - } - } - - // NameMC like reward - addDirectlyDefinedRewards(new DirectlyDefinedReward("NameMCLikeReward.Rewards") { - - @Override - public void createSection(String key) { - getSpecialRewardsConfig().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getSpecialRewardsConfig().getData(); - } - - @Override - public void save() { - getSpecialRewardsConfig().saveData(); - } - - @Override - public void setData(String path, Object value) { - getSpecialRewardsConfig().setValue(path, value); - } - }); - - addDirectlyDefinedRewards(new DirectlyDefinedReward("BungeeVotePartyRewards") { - - @Override - public void createSection(String key) { - getBungeeSettings().createSection(key); - } - - @Override - public ConfigurationSection getFileData() { - return getBungeeSettings().getData(); - } - - @Override - public void save() { - getBungeeSettings().saveData(); - } - - @Override - public void setData(String path, Object value) { - getBungeeSettings().setValue(path, value); - } - }); + VoteReminderRewardRegistrar.register(this); + SpecialRewardsRewardRegistrar.register(this); + VoteSiteRewardRegistrar.register(this); + VotePartyRewardRegistrar.register(this); + VoteMilestoneRewardRegistrar.register(this); + VoteStreakRewardRegistrar.register(this); + TopVoterRewardRegistrar.register(this); + VoteShopRewardRegistrar.register(this); + BackendProxyRewardRegistrar.register(this); getRewardHandler().checkDirectlyDefined(); - } private void loadTimer() { From b2d18793ab6671f4396303b576eff68153a68de9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 23:15:05 +0000 Subject: [PATCH 26/71] Remove temporary refactor workflow --- .../refactor-backendproxy-components.yml | 75 ------------------- 1 file changed, 75 deletions(-) delete mode 100644 .github/workflows/refactor-backendproxy-components.yml diff --git a/.github/workflows/refactor-backendproxy-components.yml b/.github/workflows/refactor-backendproxy-components.yml deleted file mode 100644 index e483be1a08..0000000000 --- a/.github/workflows/refactor-backendproxy-components.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: Refactor backend proxy components - -on: - pull_request: - branches: - - master - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - refactor: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: refactor/backendproxy-components - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '21' - cache: maven - - name: Replace directly-defined reward orchestration - run: | - python - <<'PY' - from pathlib import Path - - path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') - text = path.read_text() - - imports = { - 'import com.bencodez.votingplugin.backendproxy.BackendProxyHandler;\n': 'import com.bencodez.votingplugin.backendproxy.BackendProxyHandler;\nimport com.bencodez.votingplugin.backendproxy.BackendProxyRewardRegistrar;\n', - 'import com.bencodez.votingplugin.specialrewards.SpecialRewards;\n': 'import com.bencodez.votingplugin.specialrewards.SpecialRewards;\nimport com.bencodez.votingplugin.specialrewards.SpecialRewardsRewardRegistrar;\n', - 'import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestonesManager;\n': 'import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestoneRewardRegistrar;\nimport com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestonesManager;\n', - 'import com.bencodez.votingplugin.specialrewards.voteparty.VoteParty;\n': 'import com.bencodez.votingplugin.specialrewards.voteparty.VoteParty;\nimport com.bencodez.votingplugin.specialrewards.voteparty.VotePartyRewardRegistrar;\n', - 'import com.bencodez.votingplugin.specialrewards.votestreak.VoteStreakHandler;\n': 'import com.bencodez.votingplugin.specialrewards.votestreak.VoteStreakHandler;\nimport com.bencodez.votingplugin.specialrewards.votestreak.VoteStreakRewardRegistrar;\n', - 'import com.bencodez.votingplugin.topvoter.TopVoterState;\n': 'import com.bencodez.votingplugin.topvoter.TopVoterState;\nimport com.bencodez.votingplugin.topvoter.TopVoterRewardRegistrar;\n', - 'import com.bencodez.votingplugin.votereminding.VoteRemindersManager;\n': 'import com.bencodez.votingplugin.votereminding.VoteReminderRewardRegistrar;\nimport com.bencodez.votingplugin.votereminding.VoteRemindersManager;\n', - 'import com.bencodez.votingplugin.voteshop.VoteShopManager;\n': 'import com.bencodez.votingplugin.voteshop.VoteShopManager;\nimport com.bencodez.votingplugin.voteshop.VoteShopRewardRegistrar;\n', - 'import com.bencodez.votingplugin.votesites.VoteSiteManager;\n': 'import com.bencodez.votingplugin.votesites.VoteSiteManager;\nimport com.bencodez.votingplugin.votesites.VoteSiteRewardRegistrar;\n', - } - for old, new in imports.items(): - if new not in text: - if old not in text: - raise SystemExit('import anchor not found: ' + old.strip()) - text = text.replace(old, new, 1) - - start_marker = '\tprivate void addSpecialRewardsEditorPath(String rewardPath) {' - end_marker = '\n\tprivate void loadTimer() {' - start = text.find(start_marker) - end = text.find(end_marker, start) - if start < 0 or end < 0: - raise SystemExit('directly-defined block markers not found') - - replacement = '''\tpublic void loadDirectlyDefined() {\n\t\tgetRewardHandler().getDirectlyDefinedRewards().clear();\n\n\t\tVoteReminderRewardRegistrar.register(this);\n\t\tSpecialRewardsRewardRegistrar.register(this);\n\t\tVoteSiteRewardRegistrar.register(this);\n\t\tVotePartyRewardRegistrar.register(this);\n\t\tVoteMilestoneRewardRegistrar.register(this);\n\t\tVoteStreakRewardRegistrar.register(this);\n\t\tTopVoterRewardRegistrar.register(this);\n\t\tVoteShopRewardRegistrar.register(this);\n\t\tBackendProxyRewardRegistrar.register(this);\n\n\t\tgetRewardHandler().checkDirectlyDefined();\n\t}\n''' - text = text[:start] + replacement + text[end:] - path.write_text(text) - PY - - name: Build - run: mvn -B -f VotingPlugin/pom.xml package - - name: Commit refactor - run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A VotingPlugin - git commit -m 'Split backend proxy components and reward path ownership' - git push origin HEAD:refactor/backendproxy-components - - name: Remove temporary workflow - run: | - git pull --rebase origin refactor/backendproxy-components - git rm .github/workflows/refactor-backendproxy-components.yml - git commit -m 'Remove temporary refactor workflow' - git push origin HEAD:refactor/backendproxy-components From 30ca646f67068a8d4a125a8e5189f7e203b0a9ba Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:16:41 -0600 Subject: [PATCH 27/71] Strengthen processed vote cache tests --- .../tests/backendproxy/cache/ProcessedVoteCacheTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backendproxy/cache/ProcessedVoteCacheTest.java b/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backendproxy/cache/ProcessedVoteCacheTest.java index 883d906749..f98fce6761 100644 --- a/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backendproxy/cache/ProcessedVoteCacheTest.java +++ b/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backendproxy/cache/ProcessedVoteCacheTest.java @@ -1,5 +1,6 @@ package com.bencodez.votingplugin.tests.backendproxy.cache; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -17,6 +18,7 @@ public void duplicateVoteIdIsRejected() { UUID voteId = UUID.randomUUID(); assertTrue(cache.reserve(voteId)); assertFalse(cache.reserve(voteId)); + assertEquals(1, cache.getProcessedVotes().size()); } @Test @@ -24,6 +26,7 @@ public void nullVoteIdsRemainCompatible() { ProcessedVoteCache cache = new ProcessedVoteCache(); assertTrue(cache.reserve(null)); assertTrue(cache.reserve(null)); + assertTrue(cache.getProcessedVotes().isEmpty()); } @Test @@ -33,5 +36,6 @@ public void expiredVoteIdCanBeReservedAgain() throws Exception { assertTrue(cache.reserve(voteId)); Thread.sleep(5); assertTrue(cache.reserve(voteId)); + assertEquals(1, cache.getProcessedVotes().size()); } } From f0cea43aa27fd588a58ec92a7e9131c1a13cecdb Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:18:14 -0600 Subject: [PATCH 28/71] Extract Points reward injection --- .../rewards/builtin/RewardPoints.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardPoints.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardPoints.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardPoints.java new file mode 100644 index 0000000000..820e8e204f --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardPoints.java @@ -0,0 +1,53 @@ +package com.bencodez.votingplugin.rewards.builtin; + +import java.util.HashMap; + +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.inventory.editgui.EditGUIButton; +import com.bencodez.advancedcore.api.inventory.editgui.valuetypes.EditGUIValueNumber; +import com.bencodez.advancedcore.api.item.ItemBuilder; +import com.bencodez.advancedcore.api.rewards.Reward; +import com.bencodez.advancedcore.api.rewards.RewardEditData; +import com.bencodez.advancedcore.api.rewards.injected.RewardInject; +import com.bencodez.advancedcore.api.rewards.injected.RewardInjectInt; +import com.bencodez.advancedcore.api.rewards.injected.RewardInjectValidator; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.user.VotingPluginUser; + +/** VotingPlugin's injected Points reward. */ +public class RewardPoints extends RewardInjectInt { + + private final VotingPluginMain plugin; + + public RewardPoints(VotingPluginMain plugin) { + super("Points", 0); + this.plugin = plugin; + synchronize().asPlaceholder("newpoints").addEditButton( + new EditGUIButton(new ItemBuilder(Material.PAPER), new EditGUIValueNumber("Points", null) { + @Override + public void setValue(Player player, Number value) { + RewardEditData reward = (RewardEditData) getInv().getData("Reward"); + reward.setValue("Points", value.intValue()); + } + }.addLore("Give player voting points"))).validator(new RewardInjectValidator() { + @Override + public void onValidate(Reward reward, RewardInject inject, ConfigurationSection data) { + if (data.getInt(inject.getPath(), -1) == 0) { + warning(reward, inject, "Points can not be 0"); + } + } + }); + } + + @Override + public String onRewardRequest(Reward reward, com.bencodez.advancedcore.api.user.AdvancedCoreUser user, int num, + HashMap placeholders) { + VotingPluginUser vpUser = plugin.getVotingPluginUserManager().getVotingPluginUser(user); + String result = "" + vpUser.addPoints(num); + plugin.debug("Setting points to " + result); + return result; + } +} From e0cc2bd02c955bc0f2f1b627d903e0f29c704301 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:18:22 -0600 Subject: [PATCH 29/71] Extract VoteBossBar reward injection --- .../rewards/builtin/RewardVoteBossBar.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardVoteBossBar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardVoteBossBar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardVoteBossBar.java new file mode 100644 index 0000000000..0562bddfa2 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardVoteBossBar.java @@ -0,0 +1,34 @@ +package com.bencodez.votingplugin.rewards.builtin; + +import java.util.HashMap; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.rewards.Reward; +import com.bencodez.advancedcore.api.rewards.injected.RewardInjectConfigurationSection; +import com.bencodez.votingplugin.VotingPluginMain; + +/** VotingPlugin's injected vote progress boss-bar reward. */ +public class RewardVoteBossBar extends RewardInjectConfigurationSection { + + private final VotingPluginMain plugin; + + public RewardVoteBossBar(VotingPluginMain plugin) { + super("VoteBossBar"); + this.plugin = plugin; + } + + @Override + public String onRewardRequested(Reward reward, com.bencodez.advancedcore.api.user.AdvancedCoreUser user, + ConfigurationSection section, HashMap placeholders) { + if (section.getBoolean("Enabled")) { + user.sendBossBar(PlaceholderUtils.replacePlaceHolder(section.getString("Message", ""), placeholders), + section.getString("Color", "BLUE"), section.getString("Style", "SOLID"), + (double) plugin.getVotingPluginUserManager().getVotingPluginUser(user).getSitesVotedOn() + / plugin.getVoteSites().size(), + section.getInt("Delay", 30)); + } + return null; + } +} From 4ddf5b732d31d035cc4168229b7f5aa8e5e4be77 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:18:30 -0600 Subject: [PATCH 30/71] Extract Webhook reward injection --- .../rewards/builtin/RewardWebhook.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardWebhook.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardWebhook.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardWebhook.java new file mode 100644 index 0000000000..d1dc662b6d --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/RewardWebhook.java @@ -0,0 +1,39 @@ +package com.bencodez.votingplugin.rewards.builtin; + +import java.util.HashMap; +import java.util.List; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.rewards.Reward; +import com.bencodez.advancedcore.api.rewards.injected.RewardInjectConfigurationSection; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.webhook.WebhookRewardEntry; +import com.bencodez.votingplugin.webhook.WebhookRewardParser; + +/** VotingPlugin's injected webhook reward. */ +public class RewardWebhook extends RewardInjectConfigurationSection { + + private final VotingPluginMain plugin; + + public RewardWebhook(VotingPluginMain plugin) { + super("WebhookReward"); + this.plugin = plugin; + } + + @Override + public String onRewardRequested(Reward reward, com.bencodez.advancedcore.api.user.AdvancedCoreUser user, + ConfigurationSection section, HashMap placeholders) { + if (section == null || plugin.getWebhooks() == null) { + return null; + } + List entries = WebhookRewardParser.parse(section); + if (entries == null || entries.isEmpty()) { + return null; + } + plugin.getWebhooks().createExecutor().executeAll(entries, + input -> PlaceholderUtils.replacePlaceHolder(input, placeholders)); + return null; + } +} From 250b4334610dd135df3bcfce3cb504ccc571eb43 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:19:43 -0600 Subject: [PATCH 31/71] Extract VoteTotal requirement injection --- .../requirements/RequirementVoteTotal.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/requirements/RequirementVoteTotal.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/requirements/RequirementVoteTotal.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/requirements/RequirementVoteTotal.java new file mode 100644 index 0000000000..d276ce6da3 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/requirements/RequirementVoteTotal.java @@ -0,0 +1,51 @@ +package com.bencodez.votingplugin.rewards.builtin.requirements; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.advancedcore.api.rewards.Reward; +import com.bencodez.advancedcore.api.rewards.RewardOptions; +import com.bencodez.advancedcore.api.rewards.injectedrequirement.RequirementInjectConfigurationSection; +import com.bencodez.advancedcore.api.user.AdvancedCoreUser; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.topvoter.TopVoter; +import com.bencodez.votingplugin.user.VotingPluginUser; + +/** VotingPlugin vote-total/points reward requirement. */ +public class RequirementVoteTotal extends RequirementInjectConfigurationSection { + + private final VotingPluginMain plugin; + + public RequirementVoteTotal(VotingPluginMain plugin) { + super("VoteTotal"); + this.plugin = plugin; + } + + @Override + public boolean onRequirementsRequested(Reward reward, AdvancedCoreUser acUser, ConfigurationSection section, + RewardOptions rewardOptions) { + boolean atleast = section.getBoolean("AtleastMode", false); + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(acUser); + + for (TopVoter top : TopVoter.values()) { + int required = section.getInt(top.toString(), -1); + if (required < 0) { + continue; + } + int total = user.getTotal(top); + if (atleast ? total < required : total != required) { + plugin.debug("Failed requirement " + top + " " + total + (atleast ? "/" : "!=") + required); + return false; + } + } + + int pointsRequired = section.getInt("Points", -1); + if (pointsRequired >= 0) { + int points = user.getPoints(); + if (atleast ? points < pointsRequired : points != pointsRequired) { + plugin.debug("Failed requirement points " + points + (atleast ? "/" : "!=") + pointsRequired); + return false; + } + } + return true; + } +} From 5955abdb35e00c46e3abd49c65c61c4602c0001e Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:19:58 -0600 Subject: [PATCH 32/71] Extract reward total placeholders --- .../placeholders/RewardTotalPlaceholder.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/placeholders/RewardTotalPlaceholder.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/placeholders/RewardTotalPlaceholder.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/placeholders/RewardTotalPlaceholder.java new file mode 100644 index 0000000000..753e07f6c4 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/builtin/placeholders/RewardTotalPlaceholder.java @@ -0,0 +1,25 @@ +package com.bencodez.votingplugin.rewards.builtin.placeholders; + +import com.bencodez.advancedcore.api.rewards.Reward; +import com.bencodez.advancedcore.api.rewards.RewardPlaceholderHandle; +import com.bencodez.advancedcore.api.user.AdvancedCoreUser; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.topvoter.TopVoter; + +/** Reward placeholder exposing one VotingPlugin total. */ +public class RewardTotalPlaceholder extends RewardPlaceholderHandle { + + private final VotingPluginMain plugin; + private final TopVoter topVoter; + + public RewardTotalPlaceholder(VotingPluginMain plugin, TopVoter topVoter) { + super("Total_" + topVoter.toString()); + this.plugin = plugin; + this.topVoter = topVoter; + } + + @Override + public String getValue(Reward reward, AdvancedCoreUser user) { + return "" + plugin.getVotingPluginUserManager().getVotingPluginUser(user).getTotal(topVoter); + } +} From 7937a02b236e373837b793e1dec3b7cebd8c1d1b Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:20:12 -0600 Subject: [PATCH 33/71] Add VotingPlugin reward registration coordinator --- .../rewards/VotingPluginRewardRegistrar.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/VotingPluginRewardRegistrar.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/VotingPluginRewardRegistrar.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/VotingPluginRewardRegistrar.java new file mode 100644 index 0000000000..330955f31b --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/rewards/VotingPluginRewardRegistrar.java @@ -0,0 +1,27 @@ +package com.bencodez.votingplugin.rewards; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.rewards.builtin.RewardPoints; +import com.bencodez.votingplugin.rewards.builtin.RewardVoteBossBar; +import com.bencodez.votingplugin.rewards.builtin.RewardWebhook; +import com.bencodez.votingplugin.rewards.builtin.placeholders.RewardTotalPlaceholder; +import com.bencodez.votingplugin.rewards.builtin.requirements.RequirementVoteTotal; +import com.bencodez.votingplugin.topvoter.TopVoter; + +/** Registers VotingPlugin-specific AdvancedCore reward extensions. */ +public final class VotingPluginRewardRegistrar { + + private VotingPluginRewardRegistrar() { + } + + public static void register(VotingPluginMain plugin) { + plugin.getRewardHandler().addInjectedReward(new RewardPoints(plugin)); + plugin.getRewardHandler().addInjectedReward(new RewardVoteBossBar(plugin)); + plugin.getRewardHandler().addInjectedReward(new RewardWebhook(plugin)); + plugin.getRewardHandler().addInjectedRequirements(new RequirementVoteTotal(plugin)); + + for (TopVoter topVoter : TopVoter.values()) { + plugin.getRewardHandler().addPlaceholder(new RewardTotalPlaceholder(plugin, topVoter)); + } + } +} From a9c33ba667c42e6cffd3e0a77902767ad21f467b Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:20:29 -0600 Subject: [PATCH 34/71] Run VotingPlugin reward registration refactor --- .../refactor-votingplugin-rewards.yml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/refactor-votingplugin-rewards.yml diff --git a/.github/workflows/refactor-votingplugin-rewards.yml b/.github/workflows/refactor-votingplugin-rewards.yml new file mode 100644 index 0000000000..811c0f6bea --- /dev/null +++ b/.github/workflows/refactor-votingplugin-rewards.yml @@ -0,0 +1,63 @@ +name: Refactor VotingPlugin reward registration + +on: + pull_request: + branches: + - refactor/backendproxy-components + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + refactor: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: refactor/votingplugin-reward-registration + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + - name: Replace inline reward registration + run: | + python - <<'PY' + from pathlib import Path + path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') + text = path.read_text() + + anchor = 'import com.bencodez.votingplugin.presets.VoteSitePresetSetupHandler;\n' + new_import = 'import com.bencodez.votingplugin.rewards.VotingPluginRewardRegistrar;\n' + if new_import not in text: + if anchor not in text: + raise SystemExit('reward registrar import anchor not found') + text = text.replace(anchor, anchor + new_import, 1) + + start_marker = '\t\t// Add rewards\n' + end_marker = '\n\t\tplugin.getLogger().info("Enabled VotingPlugin "' + start = text.find(start_marker) + end = text.find(end_marker, start) + if start < 0 or end < 0: + raise SystemExit('inline reward block markers not found') + + text = text[:start] + '\t\tVotingPluginRewardRegistrar.register(this);\n' + text[end:] + path.write_text(text) + PY + - name: Build + run: mvn -B -f VotingPlugin/pom.xml package + - name: Commit refactor + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A VotingPlugin + git commit -m 'Move VotingPlugin reward registration out of main' + git push origin HEAD:refactor/votingplugin-reward-registration + - name: Remove temporary workflow + run: | + git pull --rebase origin refactor/votingplugin-reward-registration + git rm .github/workflows/refactor-votingplugin-rewards.yml + git commit -m 'Remove temporary reward refactor workflow' + git push origin HEAD:refactor/votingplugin-reward-registration From 707d49de31a24220085e5a3e315599bec5d55dbb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 23:21:19 +0000 Subject: [PATCH 35/71] Move VotingPlugin reward registration out of main --- .../votingplugin/VotingPluginMain.java | 129 +----------------- 1 file changed, 2 insertions(+), 127 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java index 2f351ef0b1..e283d45ed9 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java @@ -91,6 +91,7 @@ import com.bencodez.votingplugin.placeholders.PlaceHolders; import com.bencodez.votingplugin.placeholders.VotingPluginExpansion; import com.bencodez.votingplugin.presets.VoteSitePresetSetupHandler; +import com.bencodez.votingplugin.rewards.VotingPluginRewardRegistrar; import com.bencodez.votingplugin.servicesites.ServiceSiteHandler; import com.bencodez.votingplugin.signs.Signs; import com.bencodez.votingplugin.specialrewards.NameMCLikeCheckerTask; @@ -699,133 +700,7 @@ public Object getObject(OfflinePlayer player) { nameMCLikeCheckerTask.runTaskTimerAsynchronously(this, 20L, interval); } - // Add rewards - getRewardHandler().addInjectedReward(new RewardInjectInt("Points", 0) { - - @Override - public String onRewardRequest(Reward reward, com.bencodez.advancedcore.api.user.AdvancedCoreUser user, - int num, HashMap placeholders) { - VotingPluginUser vpUser = getVotingPluginUserManager().getVotingPluginUser(user); - String str = "" + vpUser.addPoints(num); - debug("Setting points to " + str); - return str; - } - }.synchronize().asPlaceholder("newpoints").addEditButton( - new EditGUIButton(new ItemBuilder(Material.PAPER), new EditGUIValueNumber("Points", null) { - - @Override - public void setValue(Player player, Number value) { - RewardEditData reward = (RewardEditData) getInv().getData("Reward"); - reward.setValue("Points", value.intValue()); - } - }.addLore("Give player voting points"))).validator(new RewardInjectValidator() { - - @Override - public void onValidate(Reward reward, RewardInject inject, ConfigurationSection data) { - if (data.getInt(inject.getPath(), -1) == 0) { - warning(reward, inject, "Points can not be 0"); - } - } - })); - - getRewardHandler().addInjectedReward(new RewardInjectConfigurationSection("VoteBossBar") { - - @Override - public String onRewardRequested(Reward arg0, com.bencodez.advancedcore.api.user.AdvancedCoreUser user, - ConfigurationSection section, HashMap placeholders) { - if (section.getBoolean("Enabled")) { - user.sendBossBar( - PlaceholderUtils.replacePlaceHolder(section.getString("Message", ""), placeholders), - section.getString("Color", "BLUE"), section.getString("Style", "SOLID"), - (double) getVotingPluginUserManager().getVotingPluginUser(user).getSitesVotedOn() - / plugin.getVoteSites().size(), - section.getInt("Delay", 30)); - } - return null; - } - }); - - getRewardHandler().addInjectedReward(new RewardInjectConfigurationSection("WebhookReward") { - - @Override - public String onRewardRequested(Reward reward, AdvancedCoreUser user, ConfigurationSection section, - HashMap placeholders) { - - if (section == null || webhooks == null) { - return null; - } - - // Parse list from inside this section - List entries = WebhookRewardParser.parse(section); - - if (entries == null || entries.isEmpty()) { - return null; - } - - webhooks.createExecutor().executeAll(entries, (input) -> { - return PlaceholderUtils.replacePlaceHolder(input, placeholders); - }); - - return null; - } - }); - - getRewardHandler().addInjectedRequirements(new RequirementInjectConfigurationSection("VoteTotal") { - - @Override - public boolean onRequirementsRequested(Reward reward, AdvancedCoreUser acUser, ConfigurationSection section, - RewardOptions rewardOptions) { - boolean atleast = section.getBoolean("AtleastMode", false); - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(acUser); - - for (TopVoter top : TopVoter.values()) { - int required = section.getInt(top.toString(), -1); - if (required >= 0) { - int total = user.getTotal(top); - if (atleast) { - if (total < required) { - debug("Failed requirement " + top.toString() + " " + total + "/" + required); - return false; - } - } else { - if (total != required) { - debug("Failed requirement " + top.toString() + " " + total + "!=" + required); - return false; - } - } - } - } - - int pointsRequired = section.getInt("Points", -1); - if (pointsRequired >= 0) { - int points = user.getPoints(); - if (atleast) { - if (points < pointsRequired) { - debug("Failed requirement points " + points + "/" + pointsRequired); - return false; - } - } else { - if (points != pointsRequired) { - debug("Failed requirement points " + points + "!=" + pointsRequired); - return false; - } - } - } - - return true; - } - }); - - for (final TopVoter top : TopVoter.values()) { - getRewardHandler().addPlaceholder(new RewardPlaceholderHandle("Total_" + top.toString()) { - - @Override - public String getValue(Reward reward, com.bencodez.advancedcore.api.user.AdvancedCoreUser user) { - VotingPluginUser vUser = getVotingPluginUserManager().getVotingPluginUser(user); - return "" + vUser.getTotal(top); - } - }); - } + VotingPluginRewardRegistrar.register(this); plugin.getLogger().info("Enabled VotingPlugin " + plugin.getDescription().getVersion()); if (plugin.getDescription().getVersion().contains("SNAPSHOT")) { From 789e4f45017ce257d91557a5b3af3848984f2c29 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 23:21:20 +0000 Subject: [PATCH 36/71] Remove temporary reward refactor workflow --- .../refactor-votingplugin-rewards.yml | 63 ------------------- 1 file changed, 63 deletions(-) delete mode 100644 .github/workflows/refactor-votingplugin-rewards.yml diff --git a/.github/workflows/refactor-votingplugin-rewards.yml b/.github/workflows/refactor-votingplugin-rewards.yml deleted file mode 100644 index 811c0f6bea..0000000000 --- a/.github/workflows/refactor-votingplugin-rewards.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Refactor VotingPlugin reward registration - -on: - pull_request: - branches: - - refactor/backendproxy-components - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - refactor: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: refactor/votingplugin-reward-registration - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '21' - cache: maven - - name: Replace inline reward registration - run: | - python - <<'PY' - from pathlib import Path - path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') - text = path.read_text() - - anchor = 'import com.bencodez.votingplugin.presets.VoteSitePresetSetupHandler;\n' - new_import = 'import com.bencodez.votingplugin.rewards.VotingPluginRewardRegistrar;\n' - if new_import not in text: - if anchor not in text: - raise SystemExit('reward registrar import anchor not found') - text = text.replace(anchor, anchor + new_import, 1) - - start_marker = '\t\t// Add rewards\n' - end_marker = '\n\t\tplugin.getLogger().info("Enabled VotingPlugin "' - start = text.find(start_marker) - end = text.find(end_marker, start) - if start < 0 or end < 0: - raise SystemExit('inline reward block markers not found') - - text = text[:start] + '\t\tVotingPluginRewardRegistrar.register(this);\n' + text[end:] - path.write_text(text) - PY - - name: Build - run: mvn -B -f VotingPlugin/pom.xml package - - name: Commit refactor - run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A VotingPlugin - git commit -m 'Move VotingPlugin reward registration out of main' - git push origin HEAD:refactor/votingplugin-reward-registration - - name: Remove temporary workflow - run: | - git pull --rebase origin refactor/votingplugin-reward-registration - git rm .github/workflows/refactor-votingplugin-rewards.yml - git commit -m 'Remove temporary reward refactor workflow' - git push origin HEAD:refactor/votingplugin-reward-registration From 9f00eb497018babfabb0e088bc88236888d62447 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:22:09 -0600 Subject: [PATCH 37/71] Extract top voter ranking logic --- .../topvoter/TopVoterRanking.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRanking.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRanking.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRanking.java new file mode 100644 index 0000000000..112eac5d61 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRanking.java @@ -0,0 +1,55 @@ +package com.bencodez.votingplugin.topvoter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +/** Ranking utilities shared by top-voter loading and reward handling. */ +public final class TopVoterRanking { + + private TopVoterRanking() { + } + + public static LinkedHashMap sortByValues( + LinkedHashMap map, boolean ascending) { + List> entries = new ArrayList<>(map.entrySet()); + entries.sort((first, second) -> { + int result = ascending ? first.getValue().compareTo(second.getValue()) + : second.getValue().compareTo(first.getValue()); + if (result != 0) { + return result; + } + return ascending + ? second.getKey().getLastVoteTime().compareTo(first.getKey().getLastVoteTime()) + : first.getKey().getLastVoteTime().compareTo(second.getKey().getLastVoteTime()); + }); + + LinkedHashMap sorted = new LinkedHashMap<>(); + for (Entry entry : entries) { + sorted.put(entry.getKey(), entry.getValue()); + } + return sorted; + } + + public static HashMap mapAwardPlaces(Set places) { + HashMap mapped = new HashMap<>(); + for (String place : places) { + String[] data = place.split("-"); + try { + if (data.length > 1) { + for (int index = Integer.parseInt(data[0]); index < Integer.parseInt(data[1]); index++) { + mapped.put(index, place); + } + } else { + mapped.put(Integer.parseInt(data[0]), place); + } + } catch (RuntimeException ignored) { + // Invalid place specifications are ignored just as they were by the handler. + } + } + return mapped; + } +} From 150dea6eb346875caa6a9b8bd541d67f991a4110 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:22:35 -0600 Subject: [PATCH 38/71] Extract top voter loading logic --- .../votingplugin/topvoter/TopVoterLoader.java | 208 ++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterLoader.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterLoader.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterLoader.java new file mode 100644 index 0000000000..c6c6485d0b --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterLoader.java @@ -0,0 +1,208 @@ +package com.bencodez.votingplugin.topvoter; + +import java.time.LocalDateTime; +import java.time.Month; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import com.bencodez.advancedcore.api.user.UserDataFetchMode; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.simpleapi.sql.Column; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.user.VotingPluginUser; + +/** Loads top-voter rankings from user storage. */ +public class TopVoterLoader { + + private final VotingPluginMain plugin; + + public TopVoterLoader(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public LinkedHashMap getMonthlyTopVotersAtTime(LocalDateTime atTime) { + LinkedHashMap topVoters = new LinkedHashMap<>(); + CountDownLatch latch = new CountDownLatch(1); + plugin.getUserManager().forEachUserKeys((uuid, columns) -> { + if (plugin != null && plugin.isEnabled() && uuid != null) { + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + user.updateTempCacheWithColumns(columns); + int total = user.getTotal(TopVoter.Monthly, atTime); + if (total > 0) { + topVoters.put(user.getTopVoterPlayer(), total); + } + user.clearTempCache(); + } + }, count -> latch.countDown()); + + try { + latch.await(10, TimeUnit.MINUTES); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + return TopVoterRanking.sortByValues(topVoters, false); + } + + public LinkedHashMap getTopVotersOfMonth(YearMonth month, + HashMap> columnsByPlayer) { + LinkedHashMap totals = new LinkedHashMap<>(); + LocalDateTime atTime = month.atDay(15).atTime(0, 0); + for (Entry> playerData : columnsByPlayer.entrySet()) { + UUID uuid = playerData.getKey(); + if (uuid == null) { + continue; + } + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + user.updateTempCacheWithColumns(playerData.getValue()); + int total = user.getTotal(TopVoter.Monthly, atTime); + if (total > 0) { + totals.put(user.getTopVoterPlayer(), total); + } + user.clearTempCache(); + } + return TopVoterRanking.sortByValues(totals, false); + } + + public void loadLastMonth() { + if (!plugin.getGui().isLastMonthGUI()) { + return; + } + plugin.getTopVoterState().getLastMonthTopVoters().clear(); + HashMap totals = new HashMap<>(); + LocalDateTime lastMonthTime = plugin.getTimeChecker().getTime().minusMonths(1); + boolean useDateTotalsPrimary = plugin.getConfigFile().isUseMonthDateTotalsAsPrimaryTotal(); + + plugin.getUserManager().forEachUserKeys((uuid, columns) -> { + if (uuid == null || plugin == null || !plugin.isEnabled()) { + return; + } + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + user.updateTempCacheWithColumns(columns); + try { + int total = useDateTotalsPrimary ? user.getTotal(TopVoter.Monthly, lastMonthTime) + : user.getLastMonthTotal(); + if (total > 0) { + totals.put(user.getTopVoterPlayer(), total); + } + } finally { + user.clearTempCache(); + } + }, count -> { + plugin.getTopVoterState().getLastMonthTopVoters() + .putAll(TopVoterRanking.sortByValues(new LinkedHashMap<>(totals), false)); + plugin.debug("Loaded last month top voters"); + }); + } + + public void loadPreviousMonthTopVoters() { + if (!plugin.getConfigFile().isStoreMonthTotalsWithDate()) { + return; + } + + LocalDateTime now = plugin.getTimeChecker().getTime(); + YearMonth currentMonth = YearMonth.of(now.getYear(), now.getMonth()); + ArrayList months = new ArrayList<>(); + ArrayList monthColumns = new ArrayList<>(); + + for (String column : plugin.getUserManager().getAllColumns()) { + YearMonth month = parseMonthColumn(column); + if (month != null && month.isBefore(currentMonth)) { + months.add(month); + monthColumns.add(column); + } + } + if (months.isEmpty()) { + return; + } + + Integer[] order = new Integer[months.size()]; + for (int index = 0; index < order.length; index++) { + order[index] = index; + } + java.util.Arrays.sort(order, (left, right) -> months.get(left).compareTo(months.get(right))); + ArrayList sortedMonths = new ArrayList<>(months.size()); + ArrayList sortedColumns = new ArrayList<>(months.size()); + for (Integer index : order) { + sortedMonths.add(months.get(index)); + sortedColumns.add(monthColumns.get(index)); + } + months.clear(); + months.addAll(sortedMonths); + monthColumns.clear(); + monthColumns.addAll(sortedColumns); + + LinkedHashMap> previous = plugin.getTopVoterState() + .getPreviousMonthsTopVoters(); + previous.clear(); + for (YearMonth month : months) { + plugin.debug("Loading previous month top voters of " + month); + previous.put(month, new LinkedHashMap<>()); + } + + @SuppressWarnings("unchecked") + LinkedHashMap[] monthMaps = new LinkedHashMap[months.size()]; + for (int index = 0; index < months.size(); index++) { + monthMaps[index] = previous.get(months.get(index)); + } + String[] monthColumnNames = monthColumns.toArray(new String[0]); + + plugin.getUserManager().forEachUserKeys((uuid, columns) -> { + if (uuid == null) { + return; + } + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + user.updateTempCacheWithColumns(columns); + try { + TopVoterPlayer player = null; + for (int index = 0; index < monthColumnNames.length; index++) { + int total = user.getData().getInt(monthColumnNames[index], 0, UserDataFetchMode.TEMP_ONLY); + if (total > 0) { + if (player == null) { + player = user.getTopVoterPlayer(); + } + monthMaps[index].put(player, total); + } + } + } finally { + user.clearTempCache(); + } + }, count -> { + for (int index = 0; index < months.size(); index++) { + YearMonth month = months.get(index); + previous.put(month, TopVoterRanking.sortByValues(previous.get(month), false)); + } + plugin.extraDebug("Previous Months: " + previous.keySet()); + }); + } + + static YearMonth parseMonthColumn(String column) { + if (column == null || !column.startsWith("MonthTotal-")) { + return null; + } + int firstDash = column.indexOf('-'); + int secondDash = column.indexOf('-', firstDash + 1); + if (firstDash < 0 || secondDash < 0) { + return null; + } + String month = column.substring(firstDash + 1, secondDash); + String year = column.substring(secondDash + 1); + if (!MessageAPI.isInt(year)) { + return null; + } + try { + return YearMonth.of(Integer.parseInt(year), Month.valueOf(month)); + } catch (RuntimeException ignored) { + return null; + } + } +} From 27c8cb2e340d575e4cb888bca76aef4206f6c9b9 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:23:04 -0600 Subject: [PATCH 39/71] Preserve top voter place parse diagnostics --- .../com/bencodez/votingplugin/topvoter/TopVoterRanking.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRanking.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRanking.java index 112eac5d61..49b0cdc5a7 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRanking.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterRanking.java @@ -46,8 +46,8 @@ public static HashMap mapAwardPlaces(Set places) { } else { mapped.put(Integer.parseInt(data[0]), place); } - } catch (RuntimeException ignored) { - // Invalid place specifications are ignored just as they were by the handler. + } catch (RuntimeException e) { + e.printStackTrace(); } } return mapped; From d8c3e1c260e8f74c777a2e480e37b0263e3bd33c Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:23:12 -0600 Subject: [PATCH 40/71] Test top voter month column parsing --- .../topvoter/TopVoterLoaderTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 VotingPlugin/src/test/java/com/bencodez/votingplugin/topvoter/TopVoterLoaderTest.java diff --git a/VotingPlugin/src/test/java/com/bencodez/votingplugin/topvoter/TopVoterLoaderTest.java b/VotingPlugin/src/test/java/com/bencodez/votingplugin/topvoter/TopVoterLoaderTest.java new file mode 100644 index 0000000000..2fd872f13f --- /dev/null +++ b/VotingPlugin/src/test/java/com/bencodez/votingplugin/topvoter/TopVoterLoaderTest.java @@ -0,0 +1,25 @@ +package com.bencodez.votingplugin.topvoter; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.time.YearMonth; + +import org.junit.jupiter.api.Test; + +public class TopVoterLoaderTest { + + @Test + public void parsesStoredMonthColumns() { + assertEquals(YearMonth.of(2025, 1), TopVoterLoader.parseMonthColumn("MonthTotal-JANUARY-2025")); + assertEquals(YearMonth.of(2026, 12), TopVoterLoader.parseMonthColumn("MonthTotal-DECEMBER-2026")); + } + + @Test + public void rejectsMalformedMonthColumns() { + assertNull(TopVoterLoader.parseMonthColumn("MonthTotal-BAD-2025")); + assertNull(TopVoterLoader.parseMonthColumn("MonthTotal-JANUARY-nope")); + assertNull(TopVoterLoader.parseMonthColumn("Other-JANUARY-2025")); + assertNull(TopVoterLoader.parseMonthColumn(null)); + } +} From d36f643e18f44b9aaf8735906362599ab60942bb Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:23:33 -0600 Subject: [PATCH 41/71] Run top voter handler refactor --- .../workflows/refactor-topvoter-handler.yml | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 .github/workflows/refactor-topvoter-handler.yml diff --git a/.github/workflows/refactor-topvoter-handler.yml b/.github/workflows/refactor-topvoter-handler.yml new file mode 100644 index 0000000000..182fb4473b --- /dev/null +++ b/.github/workflows/refactor-topvoter-handler.yml @@ -0,0 +1,98 @@ +name: Refactor top voter handler + +on: + pull_request: + branches: + - refactor/votingplugin-reward-registration + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + refactor: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: refactor/topvoter-handler + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + - name: Split top voter loading and ranking + run: | + python - <<'PY' + from pathlib import Path + + def replace_method(text, marker, replacement): + start = text.find(marker) + if start < 0: + raise SystemExit('method marker not found: ' + marker) + brace = text.find('{', start) + if brace < 0: + raise SystemExit('method brace not found: ' + marker) + depth = 0 + pos = brace + while pos < len(text): + if text[pos] == '{': + depth += 1 + elif text[pos] == '}': + depth -= 1 + if depth == 0: + return text[:start] + replacement + text[pos + 1:] + pos += 1 + raise SystemExit('unterminated method: ' + marker) + + handler = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterHandler.java') + text = handler.read_text() + field_anchor = '\tprivate VotingPluginMain plugin;\n' + if '\tprivate final TopVoterLoader loader;\n' not in text: + text = text.replace(field_anchor, field_anchor + '\tprivate final TopVoterLoader loader;\n', 1) + ctor_anchor = '\t\tthis.plugin = plugin;\n' + if '\t\tthis.loader = new TopVoterLoader(plugin);\n' not in text: + text = text.replace(ctor_anchor, ctor_anchor + '\t\tthis.loader = new TopVoterLoader(plugin);\n', 1) + + text = replace_method(text, + '\tpublic LinkedHashMap getMonthlyTopVotersAtTime(LocalDateTime atTime)', + '\tpublic LinkedHashMap getMonthlyTopVotersAtTime(LocalDateTime atTime) {\n\t\treturn loader.getMonthlyTopVotersAtTime(atTime);\n\t}\n') + text = replace_method(text, + '\tpublic LinkedHashMap getTopVotersOfMonth(YearMonth month,', + '\tpublic LinkedHashMap getTopVotersOfMonth(YearMonth month,\n\t\t\tHashMap> cols) {\n\t\treturn loader.getTopVotersOfMonth(month, cols);\n\t}\n') + text = replace_method(text, '\tpublic void loadLastMonth()', + '\tpublic void loadLastMonth() {\n\t\tloader.loadLastMonth();\n\t}\n') + text = replace_method(text, '\tpublic void loadPreviousMonthTopVoters()', + '\tpublic void loadPreviousMonthTopVoters() {\n\t\tloader.loadPreviousMonthTopVoters();\n\t}\n') + text = replace_method(text, '\tprivate HashMap handlePlaces(Set places)', + '\tprivate HashMap handlePlaces(Set places) {\n\t\treturn TopVoterRanking.mapAwardPlaces(places);\n\t}\n') + text = replace_method(text, + '\tpublic LinkedHashMap sortByValues(LinkedHashMap map,', + '\tpublic LinkedHashMap sortByValues(LinkedHashMap map,\n\t\t\tfinal boolean order) {\n\t\treturn TopVoterRanking.sortByValues(map, order);\n\t}\n') + text = text.replace('ArrayList users = plugin.convertSet(plugin.getTopVoter(TopVoter.Weekly).keySet());', + 'ArrayList users = new ArrayList<>(plugin.getTopVoterState().getTopVoters(TopVoter.Weekly).keySet());') + handler.write_text(text) + + main = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') + main_text = main.read_text() + main_text = replace_method(main_text, '\tpublic ArrayList convertSet(Set set)', '') + main_text = replace_method(main_text, '\tpublic void checkFirstTimeLoaded()', '') + main_text = main_text.replace('\n\tprivate boolean firstTimeLoaded = false;\n', '\n') + main.write_text(main_text) + PY + - name: Build + run: mvn -B -f VotingPlugin/pom.xml package + - name: Commit refactor + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A VotingPlugin + git commit -m 'Split top voter loading and ranking' + git push origin HEAD:refactor/topvoter-handler + - name: Remove temporary workflow + run: | + git pull --rebase origin refactor/topvoter-handler + git rm .github/workflows/refactor-topvoter-handler.yml + git commit -m 'Remove temporary top voter refactor workflow' + git push origin HEAD:refactor/topvoter-handler From d31cbb670e66176c62671573b32b9468627a2fbf Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:27:01 -0600 Subject: [PATCH 42/71] Run top voter refactor against master PR --- .github/workflows/refactor-topvoter-handler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/refactor-topvoter-handler.yml b/.github/workflows/refactor-topvoter-handler.yml index 182fb4473b..9744fa07db 100644 --- a/.github/workflows/refactor-topvoter-handler.yml +++ b/.github/workflows/refactor-topvoter-handler.yml @@ -3,7 +3,7 @@ name: Refactor top voter handler on: pull_request: branches: - - refactor/votingplugin-reward-registration + - master types: [opened, synchronize, reopened] permissions: From 68fd9b42ea1237b024e208e2bcff899104827dd5 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 17:28:37 -0600 Subject: [PATCH 43/71] Fix top voter refactor leftovers --- .github/workflows/refactor-topvoter-handler.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/refactor-topvoter-handler.yml b/.github/workflows/refactor-topvoter-handler.yml index 9744fa07db..d3d6770337 100644 --- a/.github/workflows/refactor-topvoter-handler.yml +++ b/.github/workflows/refactor-topvoter-handler.yml @@ -70,12 +70,17 @@ jobs: text = replace_method(text, '\tpublic LinkedHashMap sortByValues(LinkedHashMap map,', '\tpublic LinkedHashMap sortByValues(LinkedHashMap map,\n\t\t\tfinal boolean order) {\n\t\treturn TopVoterRanking.sortByValues(map, order);\n\t}\n') - text = text.replace('ArrayList users = plugin.convertSet(plugin.getTopVoter(TopVoter.Weekly).keySet());', - 'ArrayList users = new ArrayList<>(plugin.getTopVoterState().getTopVoters(TopVoter.Weekly).keySet());') handler.write_text(text) + source_root = Path('VotingPlugin/src/main/java') + for source in source_root.rglob('*.java'): + source_text = source.read_text() + if 'plugin.convertSet(' in source_text: + source.write_text(source_text.replace('plugin.convertSet(', 'new ArrayList<>(')) + main = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') main_text = main.read_text() + main_text = main_text.replace('\n\t\t\t\tcheckFirstTimeLoaded();\n', '\n') main_text = replace_method(main_text, '\tpublic ArrayList convertSet(Set set)', '') main_text = replace_method(main_text, '\tpublic void checkFirstTimeLoaded()', '') main_text = main_text.replace('\n\tprivate boolean firstTimeLoaded = false;\n', '\n') From 7fb50dc1162968a3815769d44c9582ed369088e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 23:29:12 +0000 Subject: [PATCH 44/71] Split top voter loading and ranking --- .../votingplugin/VotingPluginMain.java | 26 +- .../votingplugin/signs/SignHandler.java | 636 +++--- .../topvoter/TopVoterHandler.java | 1944 +++++++---------- 3 files changed, 1167 insertions(+), 1439 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java index e283d45ed9..7e58920864 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java @@ -268,7 +268,6 @@ public class VotingPluginMain extends AdvancedCorePlugin { @Getter private long lastBackgroundTaskTimeTaken = -1; - private boolean firstTimeLoaded = false; @Getter @Setter @@ -291,25 +290,7 @@ public void basicBungeeUpdate() { } } - public void checkFirstTimeLoaded() { - if (!firstTimeLoaded) { - - if (getGui().isChestVoteTopUseSkull()) { - int maxToLoad = 200; - for (TopVoter top : getTopVoter().keySet()) { - int num = 1; - Set players = getTopVoter().get(top).keySet(); - for (TopVoterPlayer p : players) { - if (num <= maxToLoad) { - getSkullCacheHandler().addToCache(p.getUuid(), p.getPlayerName()); - } - num++; - } - } - } - } - firstTimeLoaded = true; - } + /** * Check votifier. @@ -351,9 +332,7 @@ public void loadVoteShopManager() { voteShopManager = new VoteShopManager(this); } - public ArrayList convertSet(Set set) { - return new ArrayList<>(set); - } + @Override public FileConfiguration getConfig() { @@ -1212,7 +1191,6 @@ public synchronized void update() { serverData.updateValues(); getSigns().updateSigns(); - checkFirstTimeLoaded(); if (plugin.getConfigFile().isDiscordSRVEnabled() && getDiscordHandler() != null) { for (TopVoter top : TopVoter.values()) { diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java index 0b62bc7ce4..688eda03a1 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java @@ -1,318 +1,318 @@ -package com.bencodez.votingplugin.signs; - -import java.util.ArrayList; -import java.util.UUID; - -import org.bukkit.Location; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; -import org.bukkit.block.BlockState; -import org.bukkit.block.Sign; -import org.bukkit.block.Skull; -import org.bukkit.block.data.Directional; -import org.bukkit.inventory.meta.SkullMeta; - -import com.bencodez.advancedcore.api.misc.MiscUtils; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.topvoter.TopVoter; -import com.bencodez.votingplugin.topvoter.TopVoterPlayer; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class SignHandler. - */ -public class SignHandler { - - @Getter - @Setter - private String data; - - /** The lines. */ - private ArrayList lines; - - @Getter - @Setter - private Location location; - - private String playerName; - - private UUID uuid; - - private VotingPluginMain plugin; - - private int position; - - @Getter - @Setter - private String sign; - - @Getter - @Setter - private Location skullLocation; - - @Getter - @Setter - private boolean valid; - - private int votes; - - /** - * Constructs a new SignHandler. - * - * @param plugin the main plugin instance - * @param sign the sign identifier - * @param location the sign location - * @param skullLocation the skull location - * @param data the sign data - * @param position the sign position - */ - public SignHandler(VotingPluginMain plugin, String sign, Location location, Location skullLocation, String data, - int position) { - this.plugin = plugin; - setSign(sign); - setLocation(location); - setSkullLocation(skullLocation); - setData(data); - this.position = position; - setValid(true); - lines = new ArrayList<>(); - checkValidSign(); - playerName = ""; - } - - @SuppressWarnings("deprecation") - private boolean checkSkull(Block block) { - if (block.getState() instanceof Skull) { - if (!playerName.equals("No Player")) { - Skull skull = (Skull) block.getState(); - try { - SkullMeta meta = (SkullMeta) plugin.getSkullCacheHandler().getSkull(uuid, playerName).getItemMeta(); - skull.setOwnerProfile(meta.getOwnerProfile()); - skull.update(true, false); - } catch (Exception e) { - plugin.debug("Failed to set skull for " + playerName); - plugin.debug(e); - skull.setOwner(playerName); - skull.update(true, false); - } - - } - return true; - } - return false; - } - - /** - * Check skulls. - */ - public void checkSkulls() { - if (noNameAvailable()) { - return; - } - if (skullLocation != null) { - checkSkull(skullLocation.getBlock()); - return; - } - - Location loc = location; - Location loc1 = new Location(loc.getWorld(), loc.getBlockX() - 1, loc.getBlockY() - 1, loc.getBlockZ() - 1); - Location loc2 = new Location(loc.getWorld(), loc.getBlockX() + 1, loc.getBlockY() + 1, loc.getBlockZ() + 1); - updateSkulls(loc1, loc2); - } - - /** - * Check valid sign. - */ - public void checkValidSign() { - plugin.getBukkitScheduler().runTask(plugin, new Runnable() { - - @Override - public void run() { - try { - setValid(getLocation().getBlock().getState() instanceof Sign); - } catch (Exception ex) { - setValid(false); - } - } - }, getLocation()); - - } - - /** - * Gets the right click message. - * - * @return the right click message - */ - public String getRightClickMessage() { - String msg = plugin.getConfigFile().getFormatSignTopVoterSignRightClickMessage(); - msg = msg.replace("%player%", playerName); - msg = msg.replace("%position%", "" + position); - msg = msg.replace("%votes%", "" + votes); - msg = msg.replace("%SiteName%", data); - return msg; - } - - /** - * Checks if is location same. - * - * @param loc the loc - * @return true, if is location same - */ - public boolean isLocationSame(Location loc) { - return loc.equals(getLocation()); - } - - /** - * Checks if skull location is set. - * - * @return true if skull is set - */ - public boolean isSkullSet() { - return skullLocation != null; - } - - /** - * Checks if no player name is available. - * - * @return true if no name available - */ - public boolean noNameAvailable() { - return playerName.equalsIgnoreCase("No Player") || playerName.equals(""); - } - - /** - * Removes the sign. - */ - public void removeSign() { - plugin.getServerData().removeSign(sign); - } - - /** - * Store sign. - */ - public void storeSign() { - plugin.getServerData().setSign(sign, location, skullLocation, data, position); - } - - /** - * Update lines. - */ - public void updateLines() { - lines = new ArrayList<>(); - checkValidSign(); - if (position != 0) { - String line1 = plugin.getConfigFile().getFormatSignTopVoterSignLine1(); - String line2 = plugin.getConfigFile().getFormatSignTopVoterSignLine2(); - String line3 = plugin.getConfigFile().getFormatSignTopVoterSignLine3(); - String line4 = plugin.getConfigFile().getFormatSignTopVoterSignLine4(); - lines.add(line1); - lines.add(line2); - lines.add(line3); - lines.add(line4); - - ArrayList users = null; - if (data.equalsIgnoreCase("all")) { - users = plugin.convertSet(plugin.getTopVoter(TopVoter.AllTime).keySet()); - } else if (data.equalsIgnoreCase("monthly")) { - users = plugin.convertSet(plugin.getTopVoter(TopVoter.Monthly).keySet()); - } else if (data.equalsIgnoreCase("weekly")) { - users = plugin.convertSet(plugin.getTopVoter(TopVoter.Weekly).keySet()); - } else if (data.equalsIgnoreCase("daily")) { - users = plugin.convertSet(plugin.getTopVoter(TopVoter.Daily).keySet()); - } - - if (users != null && users.size() >= position) { - TopVoterPlayer user = users.get(position - 1); - playerName = user.getPlayerName(); - uuid = user.getUuid(); - - votes = 0; - if (data.equalsIgnoreCase("all")) { - votes = plugin.getTopVoter(TopVoter.AllTime).get(user); - } else if (data.equalsIgnoreCase("monthly")) { - votes = plugin.getTopVoter(TopVoter.Monthly).get(user); - } else if (data.equalsIgnoreCase("weekly")) { - votes = plugin.getTopVoter(TopVoter.Weekly).get(user); - } else if (data.equalsIgnoreCase("daily")) { - votes = plugin.getTopVoter(TopVoter.Daily).get(user); - } - - for (int j = 0; j < lines.size(); j++) { - lines.set(j, lines.get(j).replace("%votes%", "" + votes).replace("%player%", playerName)); - } - } else { - playerName = "No Player"; - votes = 0; - for (int j = 0; j < lines.size(); j++) { - lines.set(j, lines.get(j).replace("%votes%", "" + votes).replace("%player%", playerName)); - } - } - - for (int j = 0; j < lines.size(); j++) { - lines.set(j, lines.get(j).replace("%SiteName%", data).replace("%position%", "" + position)); - } - - lines = ArrayUtils.colorize(lines); - - } - - } - - /** - * Update sign. - * - * @param delay the delay - */ - public void updateSign(int delay) { - plugin.getBukkitScheduler().runTaskLater(plugin, new Runnable() { - - @SuppressWarnings("deprecation") - @Override - public void run() { - try { - BlockState state = getLocation().getBlock().getState(); - if (state instanceof Sign) { - Sign s = (Sign) state; - - for (int j = 0; j < lines.size() && j < 4; j++) { - s.setLine(j, lines.get(j)); - } - s.update(); - checkSkulls(); - } - - } catch (Exception ex) { - plugin.debug("Failed to update sign at " + getLocation().toString()); - VotingPluginMain.plugin.debug(ex); - } - } - }, delay, getLocation()); - } - - /** - * Updates skulls in the specified region. - * - * @param loc1 the first location - * @param loc2 the second location - */ - public void updateSkulls(Location loc1, Location loc2) { - BlockState state = getLocation().getBlock().getState(); - if (state instanceof Sign && state.getBlockData() instanceof Directional) { - Directional s = (Directional) state.getBlockData(); - Block b = location.getBlock().getRelative(s.getFacing()); - Block above = b.getRelative(BlockFace.UP); - if (checkSkull(above)) { - return; - } - - } - - for (Block block : MiscUtils.getInstance().getRegionBlocks(location.getWorld(), loc1, loc2)) { - checkSkull(block); - } - } -} +package com.bencodez.votingplugin.signs; + +import java.util.ArrayList; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; +import org.bukkit.block.Skull; +import org.bukkit.block.data.Directional; +import org.bukkit.inventory.meta.SkullMeta; + +import com.bencodez.advancedcore.api.misc.MiscUtils; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.topvoter.TopVoter; +import com.bencodez.votingplugin.topvoter.TopVoterPlayer; + +import lombok.Getter; +import lombok.Setter; + +// TODO: Auto-generated Javadoc +/** + * The Class SignHandler. + */ +public class SignHandler { + + @Getter + @Setter + private String data; + + /** The lines. */ + private ArrayList lines; + + @Getter + @Setter + private Location location; + + private String playerName; + + private UUID uuid; + + private VotingPluginMain plugin; + + private int position; + + @Getter + @Setter + private String sign; + + @Getter + @Setter + private Location skullLocation; + + @Getter + @Setter + private boolean valid; + + private int votes; + + /** + * Constructs a new SignHandler. + * + * @param plugin the main plugin instance + * @param sign the sign identifier + * @param location the sign location + * @param skullLocation the skull location + * @param data the sign data + * @param position the sign position + */ + public SignHandler(VotingPluginMain plugin, String sign, Location location, Location skullLocation, String data, + int position) { + this.plugin = plugin; + setSign(sign); + setLocation(location); + setSkullLocation(skullLocation); + setData(data); + this.position = position; + setValid(true); + lines = new ArrayList<>(); + checkValidSign(); + playerName = ""; + } + + @SuppressWarnings("deprecation") + private boolean checkSkull(Block block) { + if (block.getState() instanceof Skull) { + if (!playerName.equals("No Player")) { + Skull skull = (Skull) block.getState(); + try { + SkullMeta meta = (SkullMeta) plugin.getSkullCacheHandler().getSkull(uuid, playerName).getItemMeta(); + skull.setOwnerProfile(meta.getOwnerProfile()); + skull.update(true, false); + } catch (Exception e) { + plugin.debug("Failed to set skull for " + playerName); + plugin.debug(e); + skull.setOwner(playerName); + skull.update(true, false); + } + + } + return true; + } + return false; + } + + /** + * Check skulls. + */ + public void checkSkulls() { + if (noNameAvailable()) { + return; + } + if (skullLocation != null) { + checkSkull(skullLocation.getBlock()); + return; + } + + Location loc = location; + Location loc1 = new Location(loc.getWorld(), loc.getBlockX() - 1, loc.getBlockY() - 1, loc.getBlockZ() - 1); + Location loc2 = new Location(loc.getWorld(), loc.getBlockX() + 1, loc.getBlockY() + 1, loc.getBlockZ() + 1); + updateSkulls(loc1, loc2); + } + + /** + * Check valid sign. + */ + public void checkValidSign() { + plugin.getBukkitScheduler().runTask(plugin, new Runnable() { + + @Override + public void run() { + try { + setValid(getLocation().getBlock().getState() instanceof Sign); + } catch (Exception ex) { + setValid(false); + } + } + }, getLocation()); + + } + + /** + * Gets the right click message. + * + * @return the right click message + */ + public String getRightClickMessage() { + String msg = plugin.getConfigFile().getFormatSignTopVoterSignRightClickMessage(); + msg = msg.replace("%player%", playerName); + msg = msg.replace("%position%", "" + position); + msg = msg.replace("%votes%", "" + votes); + msg = msg.replace("%SiteName%", data); + return msg; + } + + /** + * Checks if is location same. + * + * @param loc the loc + * @return true, if is location same + */ + public boolean isLocationSame(Location loc) { + return loc.equals(getLocation()); + } + + /** + * Checks if skull location is set. + * + * @return true if skull is set + */ + public boolean isSkullSet() { + return skullLocation != null; + } + + /** + * Checks if no player name is available. + * + * @return true if no name available + */ + public boolean noNameAvailable() { + return playerName.equalsIgnoreCase("No Player") || playerName.equals(""); + } + + /** + * Removes the sign. + */ + public void removeSign() { + plugin.getServerData().removeSign(sign); + } + + /** + * Store sign. + */ + public void storeSign() { + plugin.getServerData().setSign(sign, location, skullLocation, data, position); + } + + /** + * Update lines. + */ + public void updateLines() { + lines = new ArrayList<>(); + checkValidSign(); + if (position != 0) { + String line1 = plugin.getConfigFile().getFormatSignTopVoterSignLine1(); + String line2 = plugin.getConfigFile().getFormatSignTopVoterSignLine2(); + String line3 = plugin.getConfigFile().getFormatSignTopVoterSignLine3(); + String line4 = plugin.getConfigFile().getFormatSignTopVoterSignLine4(); + lines.add(line1); + lines.add(line2); + lines.add(line3); + lines.add(line4); + + ArrayList users = null; + if (data.equalsIgnoreCase("all")) { + users = new ArrayList<>(plugin.getTopVoter(TopVoter.AllTime).keySet()); + } else if (data.equalsIgnoreCase("monthly")) { + users = new ArrayList<>(plugin.getTopVoter(TopVoter.Monthly).keySet()); + } else if (data.equalsIgnoreCase("weekly")) { + users = new ArrayList<>(plugin.getTopVoter(TopVoter.Weekly).keySet()); + } else if (data.equalsIgnoreCase("daily")) { + users = new ArrayList<>(plugin.getTopVoter(TopVoter.Daily).keySet()); + } + + if (users != null && users.size() >= position) { + TopVoterPlayer user = users.get(position - 1); + playerName = user.getPlayerName(); + uuid = user.getUuid(); + + votes = 0; + if (data.equalsIgnoreCase("all")) { + votes = plugin.getTopVoter(TopVoter.AllTime).get(user); + } else if (data.equalsIgnoreCase("monthly")) { + votes = plugin.getTopVoter(TopVoter.Monthly).get(user); + } else if (data.equalsIgnoreCase("weekly")) { + votes = plugin.getTopVoter(TopVoter.Weekly).get(user); + } else if (data.equalsIgnoreCase("daily")) { + votes = plugin.getTopVoter(TopVoter.Daily).get(user); + } + + for (int j = 0; j < lines.size(); j++) { + lines.set(j, lines.get(j).replace("%votes%", "" + votes).replace("%player%", playerName)); + } + } else { + playerName = "No Player"; + votes = 0; + for (int j = 0; j < lines.size(); j++) { + lines.set(j, lines.get(j).replace("%votes%", "" + votes).replace("%player%", playerName)); + } + } + + for (int j = 0; j < lines.size(); j++) { + lines.set(j, lines.get(j).replace("%SiteName%", data).replace("%position%", "" + position)); + } + + lines = ArrayUtils.colorize(lines); + + } + + } + + /** + * Update sign. + * + * @param delay the delay + */ + public void updateSign(int delay) { + plugin.getBukkitScheduler().runTaskLater(plugin, new Runnable() { + + @SuppressWarnings("deprecation") + @Override + public void run() { + try { + BlockState state = getLocation().getBlock().getState(); + if (state instanceof Sign) { + Sign s = (Sign) state; + + for (int j = 0; j < lines.size() && j < 4; j++) { + s.setLine(j, lines.get(j)); + } + s.update(); + checkSkulls(); + } + + } catch (Exception ex) { + plugin.debug("Failed to update sign at " + getLocation().toString()); + VotingPluginMain.plugin.debug(ex); + } + } + }, delay, getLocation()); + } + + /** + * Updates skulls in the specified region. + * + * @param loc1 the first location + * @param loc2 the second location + */ + public void updateSkulls(Location loc1, Location loc2) { + BlockState state = getLocation().getBlock().getState(); + if (state instanceof Sign && state.getBlockData() instanceof Directional) { + Directional s = (Directional) state.getBlockData(); + Block b = location.getBlock().getRelative(s.getFacing()); + Block above = b.getRelative(BlockFace.UP); + if (checkSkull(above)) { + return; + } + + } + + for (Block block : MiscUtils.getInstance().getRegionBlocks(location.getWorld(), loc1, loc2)) { + checkSkull(block); + } + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterHandler.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterHandler.java index 3d02d832a6..7a5eee0eac 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterHandler.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterHandler.java @@ -1,1097 +1,847 @@ -package com.bencodez.votingplugin.topvoter; - -import java.io.File; -import java.time.LocalDateTime; -import java.time.Month; -import java.time.YearMonth; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; - -import com.bencodez.advancedcore.api.time.TimeType; -import com.bencodez.advancedcore.api.time.events.DateChangedEvent; -import com.bencodez.advancedcore.api.time.events.DayChangeEvent; -import com.bencodez.advancedcore.api.time.events.MonthChangeEvent; -import com.bencodez.advancedcore.api.time.events.PreDateChangedEvent; -import com.bencodez.advancedcore.api.time.events.WeekChangeEvent; -import com.bencodez.advancedcore.api.user.UserDataFetchMode; -import com.bencodez.advancedcore.api.user.UserStorage; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.simpleapi.file.YMLFileHandler; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.sql.Column; -import com.bencodez.simpleapi.sql.DataType; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.user.VotingPluginUser; - -/** - * Handles top voter rankings and statistics. - */ -public class TopVoterHandler implements Listener { - - private VotingPluginMain plugin; - - /** - * Constructs a new top voter handler. - * @param plugin the plugin instance - */ - public TopVoterHandler(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * Checks if bungee should handle resets. - * @return true if bungee handles resets - */ - public boolean bungeeHandleResets() { - if (plugin.getBungeeSettings().isUseBungeecoord()) { - if (plugin.getBungeeSettings().isGloblalDataEnabled()) { - return true; - } - } - - return false; - } - - /** - * Gets monthly top voters at a specific time. - * @param atTime the time to check - * @return map of top voters and their vote counts - */ - public LinkedHashMap getMonthlyTopVotersAtTime(LocalDateTime atTime) { - // int limitSize = plugin.getConfigFile().getMaxiumNumberOfTopVotersToLoad(); - - LinkedHashMap topVoter = new LinkedHashMap<>(); - - // forEachUserKeys is callback-based; wait for completion because this method - // returns a value. - // NOTE: do not call this from the main thread if forEachUserKeys is async. - CountDownLatch latch = new CountDownLatch(1); - - plugin.getUserManager().forEachUserKeys((uuid, columns) -> { - if (plugin != null && plugin.isEnabled() && uuid != null) { - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - user.updateTempCacheWithColumns(columns); - - int total = user.getTotal(TopVoter.Monthly, atTime); - if (total > 0) { - topVoter.put(user.getTopVoterPlayer(), total); - } - - user.clearTempCache(); - } - }, (count) -> { - latch.countDown(); - }); - - try { - latch.await(10, TimeUnit.MINUTES); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - - return sortByValues(topVoter, false); - - } - - /** - * Gets the top voter blacklist. - * @return list of blacklisted players - */ - public ArrayList getTopVoterBlackList() { - return plugin.getConfigFile().getBlackList(); - } - - /** - * Gets top voters for a specific month. - * @param month the year-month to check - * @param cols player data columns - * @return map of top voters and their vote counts - */ - public LinkedHashMap getTopVotersOfMonth(YearMonth month, - HashMap> cols) { - - LinkedHashMap totals = new LinkedHashMap<>(); - LocalDateTime atTime = month.atDay(15).atTime(0, 0); - for (Entry> playerData : cols.entrySet()) { - - String uuid = playerData.getKey().toString(); - if (uuid != null && !uuid.isEmpty()) { - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(UUID.fromString(uuid), - false); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - user.updateTempCacheWithColumns(playerData.getValue()); - int total = 0; - total = user.getTotal(TopVoter.Monthly, atTime); - - if (total > 0) { - totals.put(user.getTopVoterPlayer(), total); - } - user.clearTempCache(); - } - } - - return sortByValues(totals, false); - } - - /** - * Top voters weekly. - * - * @return the string[] - */ - - /** - * Gets weekly top voters as formatted strings. - * @return array of formatted top voter lines - */ - public String[] getTopVotersWeekly() { - ArrayList msg = new ArrayList<>(); - ArrayList users = plugin.convertSet(plugin.getTopVoter(TopVoter.Weekly).keySet()); - for (int i = 0; i < users.size(); i++) { - String line = plugin.getConfigFile().getFormatCommandsVoteTopLine().replace("%num%", "" + (i + 1)) - .replace("%player%", users.get(i).getPlayerName()) - .replace("%votes%", "" + plugin.getTopVoter(TopVoter.Weekly).get(users.get(i))); - msg.add(line); - } - msg = ArrayUtils.colorize(msg); - return ArrayUtils.convert(msg); - } - - private HashMap handlePlaces(Set places) { - HashMap place = new HashMap<>(); - for (String p : places) { - String[] data = p.split("-"); - try { - if (data.length > 1) { - for (int i = Integer.parseInt(data[0]); i < Integer.parseInt(data[1]); i++) { - place.put(i, p); - } - } else { - place.put(Integer.parseInt(data[0]), p); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - return place; - } - - /** - * Loads last month's top voter data. - */ - public void loadLastMonth() { - if (!plugin.getGui().isLastMonthGUI()) { - return; - } - - plugin.getLastMonthTopVoter().clear(); - - // If you don’t need insertion order here, HashMap is faster. - final HashMap totals = new HashMap<>(); - - final LocalDateTime lastMonthTime = plugin.getTimeChecker().getTime().minusMonths(1); - final boolean useDateTotalsPrimary = plugin.getConfigFile().isUseMonthDateTotalsAsPrimaryTotal(); - - plugin.getUserManager().forEachUserKeys((uuid, columns) -> { - if (uuid == null || plugin == null || !plugin.isEnabled()) { - return; - } - - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - user.updateTempCacheWithColumns(columns); - - try { - final int total = useDateTotalsPrimary ? user.getTotal(TopVoter.Monthly, lastMonthTime) - : user.getLastMonthTotal(); - - if (total > 0) { - // Only build tvp if we actually need it - totals.put(user.getTopVoterPlayer(), total); - } - } finally { - user.clearTempCache(); - } - - }, (count) -> { - plugin.getLastMonthTopVoter().putAll(sortByValues(new LinkedHashMap<>(totals), false)); - plugin.debug("Loaded last month top voters"); - }); - } - - /** - * Loads previous month top voters for all configured months. - */ - public void loadPreviousMonthTopVoters() { - if (!plugin.getConfigFile().isStoreMonthTotalsWithDate()) { - return; - } - - final LocalDateTime now = plugin.getTimeChecker().getTime(); - final YearMonth currentYm = YearMonth.of(now.getYear(), now.getMonth()); - - // Discover month columns -> YearMonth list + matching column names - final ArrayList months = new ArrayList<>(); - final ArrayList monthColumns = new ArrayList<>(); - - for (String column : plugin.getUserManager().getAllColumns()) { - if (!column.startsWith("MonthTotal-")) { - continue; - } - - // Expected: MonthTotal-MONTH-YEAR (ex: MonthTotal-JANUARY-2025) - // Faster than split("-") (regex) - final int firstDash = column.indexOf('-'); // after MonthTotal - final int secondDash = column.indexOf('-', firstDash + 1); // after MONTH - if (firstDash < 0 || secondDash < 0) { - continue; - } - - final String monthStr = column.substring(firstDash + 1, secondDash); - final String yearStr = column.substring(secondDash + 1); - - if (!MessageAPI.isInt(yearStr)) { - continue; - } - - try { - final int year = Integer.parseInt(yearStr); - final Month month = Month.valueOf(monthStr); - final YearMonth ym = YearMonth.of(year, month); - - if (ym.isBefore(currentYm)) { - months.add(ym); - monthColumns.add(column); - } - } catch (Exception ignored) { - // bad month string etc. - } - } - - if (months.isEmpty()) { - return; - } - - // Sort months AND keep monthColumns aligned - { - final Integer[] idx = new Integer[months.size()]; - for (int i = 0; i < idx.length; i++) - idx[i] = i; - - java.util.Arrays.sort(idx, (a, b) -> months.get(a).compareTo(months.get(b))); - - final ArrayList monthsSorted = new ArrayList<>(months.size()); - final ArrayList colsSorted = new ArrayList<>(months.size()); - for (int i = 0; i < idx.length; i++) { - monthsSorted.add(months.get(idx[i])); - colsSorted.add(monthColumns.get(idx[i])); - } - - months.clear(); - months.addAll(monthsSorted); - - monthColumns.clear(); - monthColumns.addAll(colsSorted); - } - - // Prepare destination maps once - final LinkedHashMap> prev = plugin - .getPreviousMonthsTopVoters(); - prev.clear(); - - for (YearMonth ym : months) { - plugin.debug("Loading previous month top voters of " + ym); - prev.put(ym, new LinkedHashMap<>()); - } - - @SuppressWarnings("unchecked") - final LinkedHashMap[] monthMaps = new LinkedHashMap[months.size()]; - for (int i = 0; i < months.size(); i++) { - monthMaps[i] = prev.get(months.get(i)); - } - - // Snapshot arrays for faster access inside the loop - final String[] monthColsArr = monthColumns.toArray(new String[0]); - - plugin.getUserManager().forEachUserKeys((uuid, columns) -> { - if (uuid == null) { - return; - } - - final VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - user.updateTempCacheWithColumns(columns); - - try { - TopVoterPlayer tvp = null; - - // Read MonthTotal-* columns directly (FAST) - for (int i = 0; i < monthColsArr.length; i++) { - final int total = user.getData().getInt(monthColsArr[i], 0, UserDataFetchMode.TEMP_ONLY); - if (total > 0) { - if (tvp == null) { - tvp = user.getTopVoterPlayer(); - } - monthMaps[i].put(tvp, total); - } - } - } finally { - user.clearTempCache(); - } - - }, (count) -> { - // Sort each month map once - for (int i = 0; i < months.size(); i++) { - final YearMonth ym = months.get(i); - prev.put(ym, sortByValues(prev.get(ym), false)); - } - - plugin.extraDebug("Previous Months: " + prev.keySet()); - }); - } - - /** - * Handles date change events. - * - * @param event date changed event - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onDateChanged(DateChangedEvent event) { - plugin.setUpdate(true); - plugin.update(); - if (event.getTimeType().equals(TimeType.MONTH)) { - loadLastMonth(); - } - if (plugin.getStorageType().equals(UserStorage.MYSQL)) { - plugin.getMysql().clearCacheBasic(); - } - } - - /** - * Handles day change events. - * @param event the day change event - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onDayChange(DayChangeEvent event) { - synchronized (VotingPluginMain.plugin) { - long startTime = System.currentTimeMillis(); - if (plugin.getConfigFile().isStoreTopVotersDaily()) { - plugin.getLogger().info("Saving TopVoters Daily"); - storeTopVoters(TopVoter.Daily); - } - - plugin.getUserManager().copyColumnData(TopVoter.Daily.getColumnName(), TopVoter.Daily.getLastColumnName()); - if (plugin.getConfigFile().isUseVoteStreaks() || plugin.getConfigFile().isUseHighestTotals()) { - plugin.getUserManager().forEachUserKeys((uuid, columns) -> { - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - user.updateTempCacheWithColumns(columns); - - if (plugin.getConfigFile().isUseVoteStreaks()) { - if (!user.voteStreakUpdatedToday(LocalDateTime.now().minusDays(1))) { - if (user.getDayVoteStreak() != 0) { - user.setDayVoteStreak(0); - } - } - } - - if (plugin.getConfigFile().isUseHighestTotals()) { - if (user.getHighestDailyTotal() < user.getTotal(TopVoter.Daily)) { - user.setHighestDailyTotal(user.getTotal(TopVoter.Daily)); - } - } - user.clearTempCache(); - }, (count) -> { - // finished - }); - } - - try { - if (plugin.getSpecialRewardsConfig().isEnableDailyRewards()) { - HashMap places = handlePlaces( - plugin.getSpecialRewardsConfig().getDailyPossibleRewardPlaces()); - int i = 0; - int lastTotal = -1; - @SuppressWarnings("unchecked") - LinkedHashMap clone = (LinkedHashMap) plugin - .getTopVoter(TopVoter.Daily).clone(); - for (Entry entry : clone.entrySet()) { - if (plugin.getConfigFile().isTopVoterAwardsTies()) { - if (entry.getValue().intValue() != lastTotal) { - i++; - } - } else { - i++; - } - if (places.containsKey(i)) { - VotingPluginUser user = entry.getKey().getUser(); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - if (!plugin.getConfigFile().isTopVoterIgnorePermission() || !user.isTopVoterIgnore()) { - user.giveDailyTopVoterAward(i, places.get(i)); - plugin.getLogger().info( - "Giving daily top voter reward " + i + " to " + entry.getKey().getPlayerName()); - } - } - lastTotal = entry.getValue().intValue(); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - for (String shopIdent : plugin.getShopFile().getShopIdentifiers()) { - if (plugin.getShopFile().getVoteShopResetDaily(shopIdent)) { - resetVoteShopLimit(shopIdent); - } - } - - // give time for other servers to catch up - if (!plugin.getTopVoterHandler().bungeeHandleResets() && plugin.getBungeeSettings().isUseBungeecoord()) { - plugin.debug("Delaying time change 10 seconds for other servers to catchup"); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - if (!bungeeHandleResets()) { - resetTotals(TopVoter.Daily); - } - - if (plugin.getStorageType().equals(UserStorage.MYSQL)) { - plugin.getMysql().clearCacheBasic(); - } - - long now = ((System.currentTimeMillis() - startTime) / 1000); - plugin.getLogger().info("Finished processing day change, took " + now + " seconds"); - } - } - - /** - * Handles month change events. - * @param event the month change event - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onMonthChange(MonthChangeEvent event) { - long startTime = System.currentTimeMillis(); - synchronized (VotingPluginMain.plugin) { - plugin.getLogger().info("Saving TopVoters Monthly"); - storeTopVoters(TopVoter.Monthly); - if (!bungeeHandleResets()) { - plugin.getUserManager().copyColumnData(TopVoter.Monthly.getColumnName(), - TopVoter.Monthly.getLastColumnName()); - } - LocalDateTime lastMonthTime = plugin.getTimeChecker().getTime().minusMonths(1); - if (plugin.getConfigFile().isUseHighestTotals() || plugin.getConfigFile().isUseVoteStreaks()) { - plugin.getUserManager().forEachUserKeys((uuid, columns) -> { - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - user.updateTempCacheWithColumns(columns); - - if (plugin.getConfigFile().isUseVoteStreaks()) { - if (user.getTotal(TopVoter.Monthly, lastMonthTime) == 0 && user.getMonthVoteStreak() != 0) { - user.setMonthVoteStreak(0); - } else { - if (!plugin.getSpecialRewardsConfig().isVoteStreakRequirementUsePercentage() - || user.hasPercentageTotal(TopVoter.Monthly, - plugin.getSpecialRewardsConfig().getVoteStreakRequirementMonth(), - lastMonthTime)) { - user.addMonthVoteStreak(); - plugin.getSpecialRewards().checkVoteStreak(null, user, "Month", - plugin.getBungeeSettings().isUseBungeecoord()); - } - } - } - - // using new system - // user.setLastMonthTotal(user.getTotal(TopVoter.Monthly)); - - if (plugin.getConfigFile().isUseHighestTotals()) { - if (user.getHighestMonthlyTotal() < user.getTotal(TopVoter.Monthly, lastMonthTime)) { - user.setHighestMonthlyTotal(user.getTotal(TopVoter.Monthly, lastMonthTime)); - } - } - user.clearTempCache(); - }, (count) -> { - // finished - }); - - } - - try { - if (plugin.getSpecialRewardsConfig().isEnableMonthlyAwards()) { - HashMap places = handlePlaces( - plugin.getSpecialRewardsConfig().getMonthlyPossibleRewardPlaces()); - int i = 0; - int lastTotal = -1; - - LinkedHashMap topVoters = null; - if (plugin.getConfigFile().isUseMonthDateTotalsAsPrimaryTotal()) { - topVoters = getMonthlyTopVotersAtTime(lastMonthTime); - } else { - @SuppressWarnings("unchecked") - LinkedHashMap clone = (LinkedHashMap) plugin - .getTopVoter(TopVoter.Monthly).clone(); - topVoters = clone; - } - - for (Entry entry : topVoters.entrySet()) { - if (plugin.getConfigFile().isTopVoterAwardsTies()) { - if (entry.getValue().intValue() != lastTotal) { - i++; - } - } else { - i++; - } - - if (places.containsKey(i)) { - VotingPluginUser user = entry.getKey().getUser(); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - if (!plugin.getConfigFile().isTopVoterIgnorePermission() || !user.isTopVoterIgnore()) { - user.giveMonthlyTopVoterAward(i, places.get(i)); - plugin.getLogger().info("Giving Monthly top voter reward " + i + " to " - + entry.getKey().getPlayerName()); - } - } - lastTotal = entry.getValue().intValue(); - } - - } - } catch (Exception e) { - e.printStackTrace(); - } - - for (String shopIdent : plugin.getShopFile().getShopIdentifiers()) { - if (plugin.getShopFile().getVoteShopResetMonthly(shopIdent)) { - resetVoteShopLimit(shopIdent); - } - } - - // give time for other servers to catch up - if (!bungeeHandleResets() && plugin.getBungeeSettings().isUseBungeecoord()) { - plugin.debug("Delaying time change 10 seconds for other servers to catchup"); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - if (!bungeeHandleResets()) { - resetTotals(TopVoter.Monthly); - } - - if (plugin.getStorageType().equals(UserStorage.MYSQL)) { - plugin.getMysql().clearCacheBasic(); - } - long now = ((System.currentTimeMillis() - startTime) / 1000); - plugin.getLogger().info("Finished processing day change, took " + now + " seconds"); - } - } - - /** - * Handles pre-date change events. - * @param event the pre-date changed event - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPreDateChanged(PreDateChangedEvent event) { - if (event.getTimeType().equals(TimeType.DAY)) { - plugin.getBannedPlayers().clear(); - for (OfflinePlayer p : Bukkit.getBannedPlayers()) { - plugin.getBannedPlayers().add(p.getUniqueId().toString()); - } - } - plugin.setUpdate(true); - plugin.update(); - } - - /** - * Handles week change events. - * - * @param event week change event - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onWeekChange(WeekChangeEvent event) { - long startTime = System.currentTimeMillis(); - synchronized (VotingPluginMain.plugin) { - if (plugin.getConfigFile().isStoreTopVotersWeekly()) { - plugin.getLogger().info("Saving TopVoters Weekly"); - storeTopVoters(TopVoter.Weekly); - } - - plugin.getUserManager().copyColumnData(TopVoter.Weekly.getColumnName(), - TopVoter.Weekly.getLastColumnName()); - if (plugin.getConfigFile().isUseVoteStreaks() || plugin.getConfigFile().isUseHighestTotals()) { - plugin.getUserManager().forEachUserKeys((uuid, columns) -> { - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - user.updateTempCacheWithColumns(columns); - - if (plugin.getConfigFile().isUseVoteStreaks()) { - if (user.getTotal(TopVoter.Weekly) == 0 && user.getWeekVoteStreak() != 0) { - user.setWeekVoteStreak(0); - } else { - if (!plugin.getSpecialRewardsConfig().isVoteStreakRequirementUsePercentage() - || user.hasPercentageTotal(TopVoter.Weekly, - plugin.getSpecialRewardsConfig().getVoteStreakRequirementWeek(), null)) { - user.addWeekVoteStreak(); - plugin.getSpecialRewards().checkVoteStreak(null, user, "Week", - plugin.getBungeeSettings().isUseBungeecoord()); - } - } - } - - if (plugin.getConfigFile().isUseHighestTotals()) { - if (user.getHighestWeeklyTotal() < user.getTotal(TopVoter.Weekly)) { - user.setHighestWeeklyTotal(user.getTotal(TopVoter.Weekly)); - } - } - user.clearTempCache(); - }, (count) -> { - // finished - }); - } - - try { - if (plugin.getSpecialRewardsConfig().isEnableWeeklyAwards()) { - HashMap places = handlePlaces( - plugin.getSpecialRewardsConfig().getWeeklyPossibleRewardPlaces()); - int i = 0; - int lastTotal = -1; - @SuppressWarnings("unchecked") - LinkedHashMap clone = (LinkedHashMap) plugin - .getTopVoter(TopVoter.Weekly).clone(); - for (Entry entry : clone.entrySet()) { - if (plugin.getConfigFile().isTopVoterAwardsTies()) { - if (entry.getValue().intValue() != lastTotal) { - i++; - } - } else { - i++; - } - if (places.containsKey(i)) { - VotingPluginUser user = entry.getKey().getUser(); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - if (!plugin.getConfigFile().isTopVoterIgnorePermission() || !user.isTopVoterIgnore()) { - user.giveWeeklyTopVoterAward(i, places.get(i)); - plugin.getLogger().info("Giving weekly top voter reward " + i + " to " - + entry.getKey().getPlayerName()); - } - } - lastTotal = entry.getValue().intValue(); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - for (String shopIdent : plugin.getShopFile().getShopIdentifiers()) { - if (plugin.getShopFile().getVoteShopResetWeekly(shopIdent)) { - resetVoteShopLimit(shopIdent); - } - } - - // give time for other servers to catch up - if (!plugin.getTopVoterHandler().bungeeHandleResets() && plugin.getBungeeSettings().isUseBungeecoord()) { - plugin.debug("Delaying time change 10 seconds for other servers to catchup"); - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - if (!bungeeHandleResets()) { - resetTotals(TopVoter.Weekly); - } - - if (plugin.getStorageType().equals(UserStorage.MYSQL)) { - plugin.getMysql().clearCacheBasic(); - } - - long now = ((System.currentTimeMillis() - startTime) / 1000); - plugin.getLogger().info("Finished processing day change, took " + now + " seconds"); - } - } - - /** - * Registers this handler as a listener. - */ - public void register() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - /** - * Resets vote totals for a specific period. - * @param topVoter the top voter period to reset - */ - public void resetTotals(TopVoter topVoter) { - plugin.getUserManager().removeAllKeyValues(topVoter.getColumnName(), DataType.INTEGER); - } - - /** - * Resets vote shop limits for a specific shop. - * @param shopIdent the shop identifier - */ - public void resetVoteShopLimit(String shopIdent) { - plugin.getUserManager().removeAllKeyValues("VoteShopLimit" + shopIdent, DataType.INTEGER); - } - - /** - * Sorts top voters by their vote counts. - * @param map the map to sort - * @param order true for ascending order, false for descending - * @return sorted map of top voters - */ - public LinkedHashMap sortByValues(LinkedHashMap map, - final boolean order) { - - List> list = new LinkedList<>(map.entrySet()); - - // Sorting the list based on values - Collections.sort(list, new Comparator>() { - @Override - public int compare(Entry o1, Entry o2) { - if (order) { - int result = (o1.getValue()).compareTo(o2.getValue()); - if (result != 0) { - return result; - } - return o2.getKey().getLastVoteTime().compareTo(o1.getKey().getLastVoteTime()); - } - int result = (o2.getValue()).compareTo(o1.getValue()); - if (result != 0) { - return result; - } - return o1.getKey().getLastVoteTime().compareTo(o2.getKey().getLastVoteTime()); - } - }); - - // Maintaining insertion order with the help of LinkedList - LinkedHashMap sortedMap = new LinkedHashMap<>(); - for (Entry entry : list) { - sortedMap.put(entry.getKey(), entry.getValue()); - } - - return sortedMap; - } - - /** - * Stores top voter data to file. - * @param top the top voter period to store - */ - public void storeTopVoters(TopVoter top) { - LocalDateTime time = LocalDateTime.now().minusDays(1); - String month = time.getMonth().toString(); - int year = time.getYear(); - int week = time.getDayOfYear(); - int day = time.getDayOfMonth(); - String fileName = "TopVoter" + File.separator + top.toString() + File.separator + year + "_" + month; - - if (top.equals(TopVoter.Daily)) { - fileName += "_" + day; - } else if (top.equals(TopVoter.Weekly)) { - fileName += "_" + week; - } - fileName += "_" + System.currentTimeMillis() + ".yml"; - - YMLFileHandler file = new YMLFileHandler(plugin, new File(plugin.getDataFolder(), fileName)); - file.setup(); - file.header("Saving top voters for " + top.toString() + ", file also contains other top voter info as backup"); - for (TopVoter cTop : TopVoter.values()) { - ArrayList topVoters = new ArrayList<>(); - int cTotal = 0; - try { - ArrayList nums = plugin.getUserManager().getNumbersInColumn(cTop.getColumnName()); - for (Integer num : nums) { - cTotal += num.intValue(); - } - topVoters.add("Combined total: " + cTotal); - } catch (Exception e) { - e.printStackTrace(); - } - if (plugin.getTopVoter().containsKey(cTop)) { - - int count = 1; - for (Entry entry : plugin.getTopVoter(cTop).entrySet()) { - topVoters.add(count + ": " + entry.getKey().getPlayerName() + ": " + entry.getValue()); - count++; - } - file.getData().set(cTop.toString(), topVoters); - } - } - file.saveData(); - } - - /** - * Top voter all time - * - * @param page the page - * @return the string[] - */ - public String[] topVoterAllTime(int page) { - int pagesize = plugin.getConfigFile().getFormatPageSize(); - ArrayList msg = new ArrayList<>(); - ArrayList topVoters = new ArrayList<>(); - int count = 1; - for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { - String line = plugin.getConfigFile().getFormatCommandsVoteTopLine(); - line = line.replace("%num%", "" + count); - line = line.replace("%player%", entry.getKey().getPlayerName()); - line = line.replace("%votes%", "" + entry.getValue()); - topVoters.add(line); - count++; - } - - int pageSize = (topVoters.size() / pagesize); - if ((topVoters.size() % pagesize) != 0) { - pageSize++; - } - - String title = plugin.getConfigFile().getFormatCommandVoteTopTitle(); - title = title.replace("%page%", "" + page); - title = title.replace("%maxpages%", "" + pageSize); - title = title.replace("%Top%", plugin.getConfigFile().getFormatTopVoterAllTime()); - msg.add(MessageAPI.colorize(title)); - - for (int i = (page - 1) * pagesize; (i < topVoters.size()) && (i < (((page - 1) * pagesize) + 10)); i++) { - msg.add(topVoters.get(i)); - } - - msg = ArrayUtils.colorize(msg); - return ArrayUtils.convert(msg); - } - - /** - * Gets daily top voters with pagination. - * @param page the page number - * @return array of formatted top voter lines - */ - public String[] topVoterDaily(int page) { - int pagesize = plugin.getConfigFile().getFormatPageSize(); - ArrayList msg = new ArrayList<>(); - ArrayList topVoters = new ArrayList<>(); - int count = 1; - for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { - String line = plugin.getConfigFile().getFormatCommandsVoteTopLine(); - line = line.replace("%num%", "" + count); - line = line.replace("%player%", entry.getKey().getPlayerName()); - line = line.replace("%votes%", "" + entry.getValue()); - topVoters.add(line); - count++; - } - - int pageSize = (topVoters.size() / pagesize); - if ((topVoters.size() % pagesize) != 0) { - pageSize++; - } - - String title = plugin.getConfigFile().getFormatCommandVoteTopTitle(); - title = title.replace("%page%", "" + page); - title = title.replace("%maxpages%", "" + pageSize); - title = title.replace("%Top%", plugin.getConfigFile().getFormatTopVoterDaily()); - msg.add(MessageAPI.colorize(title)); - - for (int i = (page - 1) * pagesize; (i < topVoters.size()) && (i < (((page - 1) * pagesize) + 10)); i++) { - msg.add(topVoters.get(i)); - } - - msg = ArrayUtils.colorize(msg); - return ArrayUtils.convert(msg); - } - - /** - * Gets monthly top voters with pagination. - * @param page the page number - * @return array of formatted top voter lines - */ - public String[] topVoterMonthly(int page) { - int pagesize = plugin.getConfigFile().getFormatPageSize(); - ArrayList msg = new ArrayList<>(); - ArrayList topVoters = new ArrayList<>(); - int count = 1; - for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { - String line = plugin.getConfigFile().getFormatCommandsVoteTopLine(); - line = line.replace("%num%", "" + count); - line = line.replace("%player%", entry.getKey().getPlayerName()); - line = line.replace("%votes%", "" + entry.getValue()); - topVoters.add(line); - count++; - } - - int pageSize = (topVoters.size() / pagesize); - if ((topVoters.size() % pagesize) != 0) { - pageSize++; - } - - String title = plugin.getConfigFile().getFormatCommandVoteTopTitle(); - title = title.replace("%page%", "" + page); - title = title.replace("%maxpages%", "" + pageSize); - title = title.replace("%Top%", plugin.getConfigFile().getFormatTopVoterMonthly()); - msg.add(MessageAPI.colorize(title)); - - for (int i = (page - 1) * pagesize; (i < topVoters.size()) && (i < (((page - 1) * pagesize) + 10)); i++) { - msg.add(topVoters.get(i)); - } - - msg = ArrayUtils.colorize(msg); - return ArrayUtils.convert(msg); - } - - /** - * Gets all-time top voters as formatted strings. - * @return array of formatted top voter lines - */ - public String[] topVotersAllTime() { - ArrayList msg = new ArrayList<>(); - List> list = new LinkedList<>(plugin.getTopVoter(TopVoter.AllTime).entrySet()); - int i = 0; - for (Entry entry : list) { - String line = "%num%: %player%, %votes%"; - line = line.replace("%num%", "" + (i + 1)); - try { - line = line.replace("%player%", entry.getKey().getPlayerName()); - } catch (Exception ex) { - VotingPluginMain.plugin.debug(ex); - } - line = line.replace("%votes%", "" + entry.getValue()); - - msg.add(line); - i++; - } - - msg = ArrayUtils.colorize(msg); - return ArrayUtils.convert(msg); - } - - /** - * Gets daily top voters as formatted strings. - * @return array of formatted top voter lines - */ - public String[] topVotersDaily() { - ArrayList msg = new ArrayList<>(); - ArrayList users = plugin.convertSet(plugin.getTopVoter(TopVoter.Daily).keySet()); - for (int i = 0; i < users.size(); i++) { - String line = "%num%: %player%, %votes%"; - line = line.replace("%num%", "" + (i + 1)); - try { - line = line.replace("%player%", users.get(i).getPlayerName()); - } catch (Exception ex) { - VotingPluginMain.plugin.debug(ex); - } - line = line.replace("%votes%", "" + plugin.getTopVoter(TopVoter.Monthly).get(users.get(i))); - msg.add(line); - } - - msg = ArrayUtils.colorize(msg); - return ArrayUtils.convert(msg); - } - - /** - * Gets monthly top voters as formatted strings. - * @return array of formatted top voter lines - */ - public String[] topVotersMonthly() { - ArrayList msg = new ArrayList<>(); - List> list = new LinkedList<>(plugin.getTopVoter(TopVoter.Monthly).entrySet()); - int i = 0; - for (Entry entry : list) { - String line = "%num%: %player%, %votes%"; - line = line.replace("%num%", "" + (i + 1)); - try { - line = line.replace("%player%", entry.getKey().getPlayerName()); - } catch (Exception ex) { - VotingPluginMain.plugin.debug(ex); - } - line = line.replace("%votes%", "" + entry.getValue()); - - msg.add(line); - i++; - } - - msg = ArrayUtils.colorize(msg); - return ArrayUtils.convert(msg); - } - - /** - * Gets weekly top voters with pagination. - * @param page the page number - * @return array of formatted top voter lines - */ - public String[] topVoterWeekly(int page) { - int pagesize = plugin.getConfigFile().getFormatPageSize(); - ArrayList msg = new ArrayList<>(); - ArrayList topVoters = new ArrayList<>(); - int count = 1; - for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { - String line = plugin.getConfigFile().getFormatCommandsVoteTopLine(); - line = line.replace("%num%", "" + count); - line = line.replace("%player%", entry.getKey().getPlayerName()); - line = line.replace("%votes%", "" + entry.getValue()); - topVoters.add(line); - count++; - } - - int pageSize = (topVoters.size() / pagesize); - if ((topVoters.size() % pagesize) != 0) { - pageSize++; - } - - String title = plugin.getConfigFile().getFormatCommandVoteTopTitle(); - title = title.replace("%page%", "" + page); - title = title.replace("%maxpages%", "" + pageSize); - title = title.replace("%Top%", plugin.getConfigFile().getFormatTopVoterWeekly()); - msg.add(MessageAPI.colorize(title)); - - for (int i = (page - 1) * pagesize; (i < topVoters.size()) && (i < (((page - 1) * pagesize) + 10)); i++) { - msg.add(topVoters.get(i)); - } - - msg = ArrayUtils.colorize(msg); - return ArrayUtils.convert(msg); - } - - /** - * Updates top voter rankings for a specific period. - * @param tempTopVoter map of top voter periods to player rankings - */ - public synchronized void updateTopVoters( - LinkedHashMap> tempTopVoter) { - - int limitSize = plugin.getConfigFile().getMaxiumNumberOfTopVotersToLoad(); - for (Entry> entry : tempTopVoter.entrySet()) { - LinkedHashMap map = entry.getValue(); - map = sortByValues(map, false); - if (limitSize > 0) { - ArrayList listKeys = new ArrayList<>(map.keySet()); - if (listKeys.size() > limitSize) { - for (int i = listKeys.size() - 1; i >= 0 && i >= limitSize; i--) { - map.remove(listKeys.get(i)); - } - } - - } - tempTopVoter.put(entry.getKey(), map); - plugin.setTopVoter(tempTopVoter); - plugin.debug(entry.getKey().getName() + " TopVoter loaded, number of players " + map.size()); - - } - - plugin.debug("Updated TopVoter"); - } -} +package com.bencodez.votingplugin.topvoter; + +import java.io.File; +import java.time.LocalDateTime; +import java.time.Month; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import com.bencodez.advancedcore.api.time.TimeType; +import com.bencodez.advancedcore.api.time.events.DateChangedEvent; +import com.bencodez.advancedcore.api.time.events.DayChangeEvent; +import com.bencodez.advancedcore.api.time.events.MonthChangeEvent; +import com.bencodez.advancedcore.api.time.events.PreDateChangedEvent; +import com.bencodez.advancedcore.api.time.events.WeekChangeEvent; +import com.bencodez.advancedcore.api.user.UserDataFetchMode; +import com.bencodez.advancedcore.api.user.UserStorage; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.simpleapi.file.YMLFileHandler; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.simpleapi.sql.Column; +import com.bencodez.simpleapi.sql.DataType; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.user.VotingPluginUser; + +/** + * Handles top voter rankings and statistics. + */ +public class TopVoterHandler implements Listener { + + private VotingPluginMain plugin; + private final TopVoterLoader loader; + + /** + * Constructs a new top voter handler. + * @param plugin the plugin instance + */ + public TopVoterHandler(VotingPluginMain plugin) { + this.plugin = plugin; + this.loader = new TopVoterLoader(plugin); + } + + /** + * Checks if bungee should handle resets. + * @return true if bungee handles resets + */ + public boolean bungeeHandleResets() { + if (plugin.getBungeeSettings().isUseBungeecoord()) { + if (plugin.getBungeeSettings().isGloblalDataEnabled()) { + return true; + } + } + + return false; + } + + /** + * Gets monthly top voters at a specific time. + * @param atTime the time to check + * @return map of top voters and their vote counts + */ + public LinkedHashMap getMonthlyTopVotersAtTime(LocalDateTime atTime) { + return loader.getMonthlyTopVotersAtTime(atTime); + } + + + /** + * Gets the top voter blacklist. + * @return list of blacklisted players + */ + public ArrayList getTopVoterBlackList() { + return plugin.getConfigFile().getBlackList(); + } + + /** + * Gets top voters for a specific month. + * @param month the year-month to check + * @param cols player data columns + * @return map of top voters and their vote counts + */ + public LinkedHashMap getTopVotersOfMonth(YearMonth month, + HashMap> cols) { + return loader.getTopVotersOfMonth(month, cols); + } + + + /** + * Top voters weekly. + * + * @return the string[] + */ + + /** + * Gets weekly top voters as formatted strings. + * @return array of formatted top voter lines + */ + public String[] getTopVotersWeekly() { + ArrayList msg = new ArrayList<>(); + ArrayList users = new ArrayList<>(plugin.getTopVoter(TopVoter.Weekly).keySet()); + for (int i = 0; i < users.size(); i++) { + String line = plugin.getConfigFile().getFormatCommandsVoteTopLine().replace("%num%", "" + (i + 1)) + .replace("%player%", users.get(i).getPlayerName()) + .replace("%votes%", "" + plugin.getTopVoter(TopVoter.Weekly).get(users.get(i))); + msg.add(line); + } + msg = ArrayUtils.colorize(msg); + return ArrayUtils.convert(msg); + } + + private HashMap handlePlaces(Set places) { + return TopVoterRanking.mapAwardPlaces(places); + } + + + /** + * Loads last month's top voter data. + */ + public void loadLastMonth() { + loader.loadLastMonth(); + } + + + /** + * Loads previous month top voters for all configured months. + */ + public void loadPreviousMonthTopVoters() { + loader.loadPreviousMonthTopVoters(); + } + + + /** + * Handles date change events. + * + * @param event date changed event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onDateChanged(DateChangedEvent event) { + plugin.setUpdate(true); + plugin.update(); + if (event.getTimeType().equals(TimeType.MONTH)) { + loadLastMonth(); + } + if (plugin.getStorageType().equals(UserStorage.MYSQL)) { + plugin.getMysql().clearCacheBasic(); + } + } + + /** + * Handles day change events. + * @param event the day change event + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onDayChange(DayChangeEvent event) { + synchronized (VotingPluginMain.plugin) { + long startTime = System.currentTimeMillis(); + if (plugin.getConfigFile().isStoreTopVotersDaily()) { + plugin.getLogger().info("Saving TopVoters Daily"); + storeTopVoters(TopVoter.Daily); + } + + plugin.getUserManager().copyColumnData(TopVoter.Daily.getColumnName(), TopVoter.Daily.getLastColumnName()); + if (plugin.getConfigFile().isUseVoteStreaks() || plugin.getConfigFile().isUseHighestTotals()) { + plugin.getUserManager().forEachUserKeys((uuid, columns) -> { + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + user.updateTempCacheWithColumns(columns); + + if (plugin.getConfigFile().isUseVoteStreaks()) { + if (!user.voteStreakUpdatedToday(LocalDateTime.now().minusDays(1))) { + if (user.getDayVoteStreak() != 0) { + user.setDayVoteStreak(0); + } + } + } + + if (plugin.getConfigFile().isUseHighestTotals()) { + if (user.getHighestDailyTotal() < user.getTotal(TopVoter.Daily)) { + user.setHighestDailyTotal(user.getTotal(TopVoter.Daily)); + } + } + user.clearTempCache(); + }, (count) -> { + // finished + }); + } + + try { + if (plugin.getSpecialRewardsConfig().isEnableDailyRewards()) { + HashMap places = handlePlaces( + plugin.getSpecialRewardsConfig().getDailyPossibleRewardPlaces()); + int i = 0; + int lastTotal = -1; + @SuppressWarnings("unchecked") + LinkedHashMap clone = (LinkedHashMap) plugin + .getTopVoter(TopVoter.Daily).clone(); + for (Entry entry : clone.entrySet()) { + if (plugin.getConfigFile().isTopVoterAwardsTies()) { + if (entry.getValue().intValue() != lastTotal) { + i++; + } + } else { + i++; + } + if (places.containsKey(i)) { + VotingPluginUser user = entry.getKey().getUser(); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + if (!plugin.getConfigFile().isTopVoterIgnorePermission() || !user.isTopVoterIgnore()) { + user.giveDailyTopVoterAward(i, places.get(i)); + plugin.getLogger().info( + "Giving daily top voter reward " + i + " to " + entry.getKey().getPlayerName()); + } + } + lastTotal = entry.getValue().intValue(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + for (String shopIdent : plugin.getShopFile().getShopIdentifiers()) { + if (plugin.getShopFile().getVoteShopResetDaily(shopIdent)) { + resetVoteShopLimit(shopIdent); + } + } + + // give time for other servers to catch up + if (!plugin.getTopVoterHandler().bungeeHandleResets() && plugin.getBungeeSettings().isUseBungeecoord()) { + plugin.debug("Delaying time change 10 seconds for other servers to catchup"); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + if (!bungeeHandleResets()) { + resetTotals(TopVoter.Daily); + } + + if (plugin.getStorageType().equals(UserStorage.MYSQL)) { + plugin.getMysql().clearCacheBasic(); + } + + long now = ((System.currentTimeMillis() - startTime) / 1000); + plugin.getLogger().info("Finished processing day change, took " + now + " seconds"); + } + } + + /** + * Handles month change events. + * @param event the month change event + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onMonthChange(MonthChangeEvent event) { + long startTime = System.currentTimeMillis(); + synchronized (VotingPluginMain.plugin) { + plugin.getLogger().info("Saving TopVoters Monthly"); + storeTopVoters(TopVoter.Monthly); + if (!bungeeHandleResets()) { + plugin.getUserManager().copyColumnData(TopVoter.Monthly.getColumnName(), + TopVoter.Monthly.getLastColumnName()); + } + LocalDateTime lastMonthTime = plugin.getTimeChecker().getTime().minusMonths(1); + if (plugin.getConfigFile().isUseHighestTotals() || plugin.getConfigFile().isUseVoteStreaks()) { + plugin.getUserManager().forEachUserKeys((uuid, columns) -> { + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + user.updateTempCacheWithColumns(columns); + + if (plugin.getConfigFile().isUseVoteStreaks()) { + if (user.getTotal(TopVoter.Monthly, lastMonthTime) == 0 && user.getMonthVoteStreak() != 0) { + user.setMonthVoteStreak(0); + } else { + if (!plugin.getSpecialRewardsConfig().isVoteStreakRequirementUsePercentage() + || user.hasPercentageTotal(TopVoter.Monthly, + plugin.getSpecialRewardsConfig().getVoteStreakRequirementMonth(), + lastMonthTime)) { + user.addMonthVoteStreak(); + plugin.getSpecialRewards().checkVoteStreak(null, user, "Month", + plugin.getBungeeSettings().isUseBungeecoord()); + } + } + } + + // using new system + // user.setLastMonthTotal(user.getTotal(TopVoter.Monthly)); + + if (plugin.getConfigFile().isUseHighestTotals()) { + if (user.getHighestMonthlyTotal() < user.getTotal(TopVoter.Monthly, lastMonthTime)) { + user.setHighestMonthlyTotal(user.getTotal(TopVoter.Monthly, lastMonthTime)); + } + } + user.clearTempCache(); + }, (count) -> { + // finished + }); + + } + + try { + if (plugin.getSpecialRewardsConfig().isEnableMonthlyAwards()) { + HashMap places = handlePlaces( + plugin.getSpecialRewardsConfig().getMonthlyPossibleRewardPlaces()); + int i = 0; + int lastTotal = -1; + + LinkedHashMap topVoters = null; + if (plugin.getConfigFile().isUseMonthDateTotalsAsPrimaryTotal()) { + topVoters = getMonthlyTopVotersAtTime(lastMonthTime); + } else { + @SuppressWarnings("unchecked") + LinkedHashMap clone = (LinkedHashMap) plugin + .getTopVoter(TopVoter.Monthly).clone(); + topVoters = clone; + } + + for (Entry entry : topVoters.entrySet()) { + if (plugin.getConfigFile().isTopVoterAwardsTies()) { + if (entry.getValue().intValue() != lastTotal) { + i++; + } + } else { + i++; + } + + if (places.containsKey(i)) { + VotingPluginUser user = entry.getKey().getUser(); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + if (!plugin.getConfigFile().isTopVoterIgnorePermission() || !user.isTopVoterIgnore()) { + user.giveMonthlyTopVoterAward(i, places.get(i)); + plugin.getLogger().info("Giving Monthly top voter reward " + i + " to " + + entry.getKey().getPlayerName()); + } + } + lastTotal = entry.getValue().intValue(); + } + + } + } catch (Exception e) { + e.printStackTrace(); + } + + for (String shopIdent : plugin.getShopFile().getShopIdentifiers()) { + if (plugin.getShopFile().getVoteShopResetMonthly(shopIdent)) { + resetVoteShopLimit(shopIdent); + } + } + + // give time for other servers to catch up + if (!bungeeHandleResets() && plugin.getBungeeSettings().isUseBungeecoord()) { + plugin.debug("Delaying time change 10 seconds for other servers to catchup"); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + if (!bungeeHandleResets()) { + resetTotals(TopVoter.Monthly); + } + + if (plugin.getStorageType().equals(UserStorage.MYSQL)) { + plugin.getMysql().clearCacheBasic(); + } + long now = ((System.currentTimeMillis() - startTime) / 1000); + plugin.getLogger().info("Finished processing day change, took " + now + " seconds"); + } + } + + /** + * Handles pre-date change events. + * @param event the pre-date changed event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPreDateChanged(PreDateChangedEvent event) { + if (event.getTimeType().equals(TimeType.DAY)) { + plugin.getBannedPlayers().clear(); + for (OfflinePlayer p : Bukkit.getBannedPlayers()) { + plugin.getBannedPlayers().add(p.getUniqueId().toString()); + } + } + plugin.setUpdate(true); + plugin.update(); + } + + /** + * Handles week change events. + * + * @param event week change event + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onWeekChange(WeekChangeEvent event) { + long startTime = System.currentTimeMillis(); + synchronized (VotingPluginMain.plugin) { + if (plugin.getConfigFile().isStoreTopVotersWeekly()) { + plugin.getLogger().info("Saving TopVoters Weekly"); + storeTopVoters(TopVoter.Weekly); + } + + plugin.getUserManager().copyColumnData(TopVoter.Weekly.getColumnName(), + TopVoter.Weekly.getLastColumnName()); + if (plugin.getConfigFile().isUseVoteStreaks() || plugin.getConfigFile().isUseHighestTotals()) { + plugin.getUserManager().forEachUserKeys((uuid, columns) -> { + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + user.updateTempCacheWithColumns(columns); + + if (plugin.getConfigFile().isUseVoteStreaks()) { + if (user.getTotal(TopVoter.Weekly) == 0 && user.getWeekVoteStreak() != 0) { + user.setWeekVoteStreak(0); + } else { + if (!plugin.getSpecialRewardsConfig().isVoteStreakRequirementUsePercentage() + || user.hasPercentageTotal(TopVoter.Weekly, + plugin.getSpecialRewardsConfig().getVoteStreakRequirementWeek(), null)) { + user.addWeekVoteStreak(); + plugin.getSpecialRewards().checkVoteStreak(null, user, "Week", + plugin.getBungeeSettings().isUseBungeecoord()); + } + } + } + + if (plugin.getConfigFile().isUseHighestTotals()) { + if (user.getHighestWeeklyTotal() < user.getTotal(TopVoter.Weekly)) { + user.setHighestWeeklyTotal(user.getTotal(TopVoter.Weekly)); + } + } + user.clearTempCache(); + }, (count) -> { + // finished + }); + } + + try { + if (plugin.getSpecialRewardsConfig().isEnableWeeklyAwards()) { + HashMap places = handlePlaces( + plugin.getSpecialRewardsConfig().getWeeklyPossibleRewardPlaces()); + int i = 0; + int lastTotal = -1; + @SuppressWarnings("unchecked") + LinkedHashMap clone = (LinkedHashMap) plugin + .getTopVoter(TopVoter.Weekly).clone(); + for (Entry entry : clone.entrySet()) { + if (plugin.getConfigFile().isTopVoterAwardsTies()) { + if (entry.getValue().intValue() != lastTotal) { + i++; + } + } else { + i++; + } + if (places.containsKey(i)) { + VotingPluginUser user = entry.getKey().getUser(); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + if (!plugin.getConfigFile().isTopVoterIgnorePermission() || !user.isTopVoterIgnore()) { + user.giveWeeklyTopVoterAward(i, places.get(i)); + plugin.getLogger().info("Giving weekly top voter reward " + i + " to " + + entry.getKey().getPlayerName()); + } + } + lastTotal = entry.getValue().intValue(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + for (String shopIdent : plugin.getShopFile().getShopIdentifiers()) { + if (plugin.getShopFile().getVoteShopResetWeekly(shopIdent)) { + resetVoteShopLimit(shopIdent); + } + } + + // give time for other servers to catch up + if (!plugin.getTopVoterHandler().bungeeHandleResets() && plugin.getBungeeSettings().isUseBungeecoord()) { + plugin.debug("Delaying time change 10 seconds for other servers to catchup"); + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + if (!bungeeHandleResets()) { + resetTotals(TopVoter.Weekly); + } + + if (plugin.getStorageType().equals(UserStorage.MYSQL)) { + plugin.getMysql().clearCacheBasic(); + } + + long now = ((System.currentTimeMillis() - startTime) / 1000); + plugin.getLogger().info("Finished processing day change, took " + now + " seconds"); + } + } + + /** + * Registers this handler as a listener. + */ + public void register() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + /** + * Resets vote totals for a specific period. + * @param topVoter the top voter period to reset + */ + public void resetTotals(TopVoter topVoter) { + plugin.getUserManager().removeAllKeyValues(topVoter.getColumnName(), DataType.INTEGER); + } + + /** + * Resets vote shop limits for a specific shop. + * @param shopIdent the shop identifier + */ + public void resetVoteShopLimit(String shopIdent) { + plugin.getUserManager().removeAllKeyValues("VoteShopLimit" + shopIdent, DataType.INTEGER); + } + + /** + * Sorts top voters by their vote counts. + * @param map the map to sort + * @param order true for ascending order, false for descending + * @return sorted map of top voters + */ + public LinkedHashMap sortByValues(LinkedHashMap map, + final boolean order) { + return TopVoterRanking.sortByValues(map, order); + } + + + /** + * Stores top voter data to file. + * @param top the top voter period to store + */ + public void storeTopVoters(TopVoter top) { + LocalDateTime time = LocalDateTime.now().minusDays(1); + String month = time.getMonth().toString(); + int year = time.getYear(); + int week = time.getDayOfYear(); + int day = time.getDayOfMonth(); + String fileName = "TopVoter" + File.separator + top.toString() + File.separator + year + "_" + month; + + if (top.equals(TopVoter.Daily)) { + fileName += "_" + day; + } else if (top.equals(TopVoter.Weekly)) { + fileName += "_" + week; + } + fileName += "_" + System.currentTimeMillis() + ".yml"; + + YMLFileHandler file = new YMLFileHandler(plugin, new File(plugin.getDataFolder(), fileName)); + file.setup(); + file.header("Saving top voters for " + top.toString() + ", file also contains other top voter info as backup"); + for (TopVoter cTop : TopVoter.values()) { + ArrayList topVoters = new ArrayList<>(); + int cTotal = 0; + try { + ArrayList nums = plugin.getUserManager().getNumbersInColumn(cTop.getColumnName()); + for (Integer num : nums) { + cTotal += num.intValue(); + } + topVoters.add("Combined total: " + cTotal); + } catch (Exception e) { + e.printStackTrace(); + } + if (plugin.getTopVoter().containsKey(cTop)) { + + int count = 1; + for (Entry entry : plugin.getTopVoter(cTop).entrySet()) { + topVoters.add(count + ": " + entry.getKey().getPlayerName() + ": " + entry.getValue()); + count++; + } + file.getData().set(cTop.toString(), topVoters); + } + } + file.saveData(); + } + + /** + * Top voter all time + * + * @param page the page + * @return the string[] + */ + public String[] topVoterAllTime(int page) { + int pagesize = plugin.getConfigFile().getFormatPageSize(); + ArrayList msg = new ArrayList<>(); + ArrayList topVoters = new ArrayList<>(); + int count = 1; + for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { + String line = plugin.getConfigFile().getFormatCommandsVoteTopLine(); + line = line.replace("%num%", "" + count); + line = line.replace("%player%", entry.getKey().getPlayerName()); + line = line.replace("%votes%", "" + entry.getValue()); + topVoters.add(line); + count++; + } + + int pageSize = (topVoters.size() / pagesize); + if ((topVoters.size() % pagesize) != 0) { + pageSize++; + } + + String title = plugin.getConfigFile().getFormatCommandVoteTopTitle(); + title = title.replace("%page%", "" + page); + title = title.replace("%maxpages%", "" + pageSize); + title = title.replace("%Top%", plugin.getConfigFile().getFormatTopVoterAllTime()); + msg.add(MessageAPI.colorize(title)); + + for (int i = (page - 1) * pagesize; (i < topVoters.size()) && (i < (((page - 1) * pagesize) + 10)); i++) { + msg.add(topVoters.get(i)); + } + + msg = ArrayUtils.colorize(msg); + return ArrayUtils.convert(msg); + } + + /** + * Gets daily top voters with pagination. + * @param page the page number + * @return array of formatted top voter lines + */ + public String[] topVoterDaily(int page) { + int pagesize = plugin.getConfigFile().getFormatPageSize(); + ArrayList msg = new ArrayList<>(); + ArrayList topVoters = new ArrayList<>(); + int count = 1; + for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { + String line = plugin.getConfigFile().getFormatCommandsVoteTopLine(); + line = line.replace("%num%", "" + count); + line = line.replace("%player%", entry.getKey().getPlayerName()); + line = line.replace("%votes%", "" + entry.getValue()); + topVoters.add(line); + count++; + } + + int pageSize = (topVoters.size() / pagesize); + if ((topVoters.size() % pagesize) != 0) { + pageSize++; + } + + String title = plugin.getConfigFile().getFormatCommandVoteTopTitle(); + title = title.replace("%page%", "" + page); + title = title.replace("%maxpages%", "" + pageSize); + title = title.replace("%Top%", plugin.getConfigFile().getFormatTopVoterDaily()); + msg.add(MessageAPI.colorize(title)); + + for (int i = (page - 1) * pagesize; (i < topVoters.size()) && (i < (((page - 1) * pagesize) + 10)); i++) { + msg.add(topVoters.get(i)); + } + + msg = ArrayUtils.colorize(msg); + return ArrayUtils.convert(msg); + } + + /** + * Gets monthly top voters with pagination. + * @param page the page number + * @return array of formatted top voter lines + */ + public String[] topVoterMonthly(int page) { + int pagesize = plugin.getConfigFile().getFormatPageSize(); + ArrayList msg = new ArrayList<>(); + ArrayList topVoters = new ArrayList<>(); + int count = 1; + for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { + String line = plugin.getConfigFile().getFormatCommandsVoteTopLine(); + line = line.replace("%num%", "" + count); + line = line.replace("%player%", entry.getKey().getPlayerName()); + line = line.replace("%votes%", "" + entry.getValue()); + topVoters.add(line); + count++; + } + + int pageSize = (topVoters.size() / pagesize); + if ((topVoters.size() % pagesize) != 0) { + pageSize++; + } + + String title = plugin.getConfigFile().getFormatCommandVoteTopTitle(); + title = title.replace("%page%", "" + page); + title = title.replace("%maxpages%", "" + pageSize); + title = title.replace("%Top%", plugin.getConfigFile().getFormatTopVoterMonthly()); + msg.add(MessageAPI.colorize(title)); + + for (int i = (page - 1) * pagesize; (i < topVoters.size()) && (i < (((page - 1) * pagesize) + 10)); i++) { + msg.add(topVoters.get(i)); + } + + msg = ArrayUtils.colorize(msg); + return ArrayUtils.convert(msg); + } + + /** + * Gets all-time top voters as formatted strings. + * @return array of formatted top voter lines + */ + public String[] topVotersAllTime() { + ArrayList msg = new ArrayList<>(); + List> list = new LinkedList<>(plugin.getTopVoter(TopVoter.AllTime).entrySet()); + int i = 0; + for (Entry entry : list) { + String line = "%num%: %player%, %votes%"; + line = line.replace("%num%", "" + (i + 1)); + try { + line = line.replace("%player%", entry.getKey().getPlayerName()); + } catch (Exception ex) { + VotingPluginMain.plugin.debug(ex); + } + line = line.replace("%votes%", "" + entry.getValue()); + + msg.add(line); + i++; + } + + msg = ArrayUtils.colorize(msg); + return ArrayUtils.convert(msg); + } + + /** + * Gets daily top voters as formatted strings. + * @return array of formatted top voter lines + */ + public String[] topVotersDaily() { + ArrayList msg = new ArrayList<>(); + ArrayList users = new ArrayList<>(plugin.getTopVoter(TopVoter.Daily).keySet()); + for (int i = 0; i < users.size(); i++) { + String line = "%num%: %player%, %votes%"; + line = line.replace("%num%", "" + (i + 1)); + try { + line = line.replace("%player%", users.get(i).getPlayerName()); + } catch (Exception ex) { + VotingPluginMain.plugin.debug(ex); + } + line = line.replace("%votes%", "" + plugin.getTopVoter(TopVoter.Monthly).get(users.get(i))); + msg.add(line); + } + + msg = ArrayUtils.colorize(msg); + return ArrayUtils.convert(msg); + } + + /** + * Gets monthly top voters as formatted strings. + * @return array of formatted top voter lines + */ + public String[] topVotersMonthly() { + ArrayList msg = new ArrayList<>(); + List> list = new LinkedList<>(plugin.getTopVoter(TopVoter.Monthly).entrySet()); + int i = 0; + for (Entry entry : list) { + String line = "%num%: %player%, %votes%"; + line = line.replace("%num%", "" + (i + 1)); + try { + line = line.replace("%player%", entry.getKey().getPlayerName()); + } catch (Exception ex) { + VotingPluginMain.plugin.debug(ex); + } + line = line.replace("%votes%", "" + entry.getValue()); + + msg.add(line); + i++; + } + + msg = ArrayUtils.colorize(msg); + return ArrayUtils.convert(msg); + } + + /** + * Gets weekly top voters with pagination. + * @param page the page number + * @return array of formatted top voter lines + */ + public String[] topVoterWeekly(int page) { + int pagesize = plugin.getConfigFile().getFormatPageSize(); + ArrayList msg = new ArrayList<>(); + ArrayList topVoters = new ArrayList<>(); + int count = 1; + for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { + String line = plugin.getConfigFile().getFormatCommandsVoteTopLine(); + line = line.replace("%num%", "" + count); + line = line.replace("%player%", entry.getKey().getPlayerName()); + line = line.replace("%votes%", "" + entry.getValue()); + topVoters.add(line); + count++; + } + + int pageSize = (topVoters.size() / pagesize); + if ((topVoters.size() % pagesize) != 0) { + pageSize++; + } + + String title = plugin.getConfigFile().getFormatCommandVoteTopTitle(); + title = title.replace("%page%", "" + page); + title = title.replace("%maxpages%", "" + pageSize); + title = title.replace("%Top%", plugin.getConfigFile().getFormatTopVoterWeekly()); + msg.add(MessageAPI.colorize(title)); + + for (int i = (page - 1) * pagesize; (i < topVoters.size()) && (i < (((page - 1) * pagesize) + 10)); i++) { + msg.add(topVoters.get(i)); + } + + msg = ArrayUtils.colorize(msg); + return ArrayUtils.convert(msg); + } + + /** + * Updates top voter rankings for a specific period. + * @param tempTopVoter map of top voter periods to player rankings + */ + public synchronized void updateTopVoters( + LinkedHashMap> tempTopVoter) { + + int limitSize = plugin.getConfigFile().getMaxiumNumberOfTopVotersToLoad(); + for (Entry> entry : tempTopVoter.entrySet()) { + LinkedHashMap map = entry.getValue(); + map = sortByValues(map, false); + if (limitSize > 0) { + ArrayList listKeys = new ArrayList<>(map.keySet()); + if (listKeys.size() > limitSize) { + for (int i = listKeys.size() - 1; i >= 0 && i >= limitSize; i--) { + map.remove(listKeys.get(i)); + } + } + + } + tempTopVoter.put(entry.getKey(), map); + plugin.setTopVoter(tempTopVoter); + plugin.debug(entry.getKey().getName() + " TopVoter loaded, number of players " + map.size()); + + } + + plugin.debug("Updated TopVoter"); + } +} From 01215e22c193477844dfe8e1860435e7b965a15a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 23:29:14 +0000 Subject: [PATCH 45/71] Remove temporary top voter refactor workflow --- .../workflows/refactor-topvoter-handler.yml | 103 ------------------ 1 file changed, 103 deletions(-) delete mode 100644 .github/workflows/refactor-topvoter-handler.yml diff --git a/.github/workflows/refactor-topvoter-handler.yml b/.github/workflows/refactor-topvoter-handler.yml deleted file mode 100644 index d3d6770337..0000000000 --- a/.github/workflows/refactor-topvoter-handler.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: Refactor top voter handler - -on: - pull_request: - branches: - - master - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - refactor: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: refactor/topvoter-handler - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '21' - cache: maven - - name: Split top voter loading and ranking - run: | - python - <<'PY' - from pathlib import Path - - def replace_method(text, marker, replacement): - start = text.find(marker) - if start < 0: - raise SystemExit('method marker not found: ' + marker) - brace = text.find('{', start) - if brace < 0: - raise SystemExit('method brace not found: ' + marker) - depth = 0 - pos = brace - while pos < len(text): - if text[pos] == '{': - depth += 1 - elif text[pos] == '}': - depth -= 1 - if depth == 0: - return text[:start] + replacement + text[pos + 1:] - pos += 1 - raise SystemExit('unterminated method: ' + marker) - - handler = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/topvoter/TopVoterHandler.java') - text = handler.read_text() - field_anchor = '\tprivate VotingPluginMain plugin;\n' - if '\tprivate final TopVoterLoader loader;\n' not in text: - text = text.replace(field_anchor, field_anchor + '\tprivate final TopVoterLoader loader;\n', 1) - ctor_anchor = '\t\tthis.plugin = plugin;\n' - if '\t\tthis.loader = new TopVoterLoader(plugin);\n' not in text: - text = text.replace(ctor_anchor, ctor_anchor + '\t\tthis.loader = new TopVoterLoader(plugin);\n', 1) - - text = replace_method(text, - '\tpublic LinkedHashMap getMonthlyTopVotersAtTime(LocalDateTime atTime)', - '\tpublic LinkedHashMap getMonthlyTopVotersAtTime(LocalDateTime atTime) {\n\t\treturn loader.getMonthlyTopVotersAtTime(atTime);\n\t}\n') - text = replace_method(text, - '\tpublic LinkedHashMap getTopVotersOfMonth(YearMonth month,', - '\tpublic LinkedHashMap getTopVotersOfMonth(YearMonth month,\n\t\t\tHashMap> cols) {\n\t\treturn loader.getTopVotersOfMonth(month, cols);\n\t}\n') - text = replace_method(text, '\tpublic void loadLastMonth()', - '\tpublic void loadLastMonth() {\n\t\tloader.loadLastMonth();\n\t}\n') - text = replace_method(text, '\tpublic void loadPreviousMonthTopVoters()', - '\tpublic void loadPreviousMonthTopVoters() {\n\t\tloader.loadPreviousMonthTopVoters();\n\t}\n') - text = replace_method(text, '\tprivate HashMap handlePlaces(Set places)', - '\tprivate HashMap handlePlaces(Set places) {\n\t\treturn TopVoterRanking.mapAwardPlaces(places);\n\t}\n') - text = replace_method(text, - '\tpublic LinkedHashMap sortByValues(LinkedHashMap map,', - '\tpublic LinkedHashMap sortByValues(LinkedHashMap map,\n\t\t\tfinal boolean order) {\n\t\treturn TopVoterRanking.sortByValues(map, order);\n\t}\n') - handler.write_text(text) - - source_root = Path('VotingPlugin/src/main/java') - for source in source_root.rglob('*.java'): - source_text = source.read_text() - if 'plugin.convertSet(' in source_text: - source.write_text(source_text.replace('plugin.convertSet(', 'new ArrayList<>(')) - - main = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') - main_text = main.read_text() - main_text = main_text.replace('\n\t\t\t\tcheckFirstTimeLoaded();\n', '\n') - main_text = replace_method(main_text, '\tpublic ArrayList convertSet(Set set)', '') - main_text = replace_method(main_text, '\tpublic void checkFirstTimeLoaded()', '') - main_text = main_text.replace('\n\tprivate boolean firstTimeLoaded = false;\n', '\n') - main.write_text(main_text) - PY - - name: Build - run: mvn -B -f VotingPlugin/pom.xml package - - name: Commit refactor - run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A VotingPlugin - git commit -m 'Split top voter loading and ranking' - git push origin HEAD:refactor/topvoter-handler - - name: Remove temporary workflow - run: | - git pull --rebase origin refactor/topvoter-handler - git rm .github/workflows/refactor-topvoter-handler.yml - git commit -m 'Remove temporary top voter refactor workflow' - git push origin HEAD:refactor/topvoter-handler From 3845cd9cef603a8d9db0a6c6cf71cc3e753e7e5f Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:08:50 -0600 Subject: [PATCH 46/71] Add version info component --- .../version/VotingPluginVersionInfo.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/version/VotingPluginVersionInfo.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/version/VotingPluginVersionInfo.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/version/VotingPluginVersionInfo.java new file mode 100644 index 0000000000..6669498657 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/version/VotingPluginVersionInfo.java @@ -0,0 +1,60 @@ +package com.bencodez.votingplugin.version; + +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.security.CodeSource; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.bukkit.configuration.file.YamlConfiguration; + +import com.bencodez.votingplugin.VotingPluginMain; + +import lombok.Getter; + +/** Owns VotingPlugin build metadata embedded in votingpluginversion.yml. */ +@Getter +public final class VotingPluginVersionInfo { + + private final VotingPluginMain plugin; + private String profile = ""; + private String buildNumber = "NOTSET"; + private String time = ""; + + public VotingPluginVersionInfo(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public void load() { + YamlConfiguration config = loadVersionFile(); + if (config == null) { + return; + } + time = config.getString("time", ""); + profile = config.getString("profile", ""); + buildNumber = config.getString("buildnumber", "NOTSET"); + } + + private YamlConfiguration loadVersionFile() { + try { + CodeSource source = plugin.getClass().getProtectionDomain().getCodeSource(); + if (source == null) { + return null; + } + URL jar = source.getLocation(); + try (ZipInputStream zip = new ZipInputStream(jar.openStream())) { + ZipEntry entry; + while ((entry = zip.getNextEntry()) != null) { + if ("votingpluginversion.yml".equals(entry.getName())) { + Reader reader = new InputStreamReader(zip); + return YamlConfiguration.loadConfiguration(reader); + } + } + } + } catch (Exception e) { + plugin.debug(e); + } + return null; + } +} From 04c2e46920f4d4746501271b6e7db800c54cd411 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:08:57 -0600 Subject: [PATCH 47/71] Add config health component --- .../config/VotingPluginConfigHealth.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/config/VotingPluginConfigHealth.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/VotingPluginConfigHealth.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/VotingPluginConfigHealth.java new file mode 100644 index 0000000000..77d3977f66 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/VotingPluginConfigHealth.java @@ -0,0 +1,29 @@ +package com.bencodez.votingplugin.config; + +import com.bencodez.votingplugin.VotingPluginMain; + +/** Owns aggregate YAML load-health reporting for VotingPlugin configuration files. */ +public final class VotingPluginConfigHealth { + + private final VotingPluginMain plugin; + private boolean ymlError; + + public VotingPluginConfigHealth(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public void check() { + ymlError = plugin.getConfigFile().isFailedToRead() || plugin.getConfigVoteSites().isFailedToRead() + || plugin.getSpecialRewardsConfig().isFailedToRead() || plugin.getBungeeSettings().isFailedToRead() + || plugin.getGui().isFailedToRead(); + + if (ymlError) { + plugin.getBukkitScheduler().runTaskLaterAsynchronously(plugin, + () -> plugin.getLogger().severe("Failed to load a file, check startup log"), 1); + } + } + + public boolean hasYmlError() { + return ymlError; + } +} From 59281e55f2d7084fb0a5bc9b01ff001775a54920 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:09:06 -0600 Subject: [PATCH 48/71] Add Votifier integration component --- .../votifier/VotifierIntegration.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/integration/votifier/VotifierIntegration.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/integration/votifier/VotifierIntegration.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/integration/votifier/VotifierIntegration.java new file mode 100644 index 0000000000..1440b21488 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/integration/votifier/VotifierIntegration.java @@ -0,0 +1,32 @@ +package com.bencodez.votingplugin.integration.votifier; + +import com.bencodez.votingplugin.VotingPluginMain; + +/** Owns Votifier/NuVotifier availability detection. */ +public final class VotifierIntegration { + + private final VotingPluginMain plugin; + private boolean loaded = true; + + public VotifierIntegration(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public void detect() { + loaded = true; + try { + Class.forName("com.vexsoftware.votifier.model.VotifierEvent"); + } catch (ClassNotFoundException e) { + if (!plugin.getBungeeSettings().isUseBungeecoord()) { + plugin.getLogger().warning("No VotifierEvent found, install Votifier, NuVotifier, or another Votifier plugin"); + } else { + plugin.debug("No VotifierEvent found, but usebungeecoord enabled"); + } + loaded = false; + } + } + + public boolean isLoaded() { + return loaded; + } +} From de0b9d9b8bd5ce2538892822e38af39282b6a5d4 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:09:27 -0600 Subject: [PATCH 49/71] Add vote log manager --- .../votingplugin/votelog/VoteLogManager.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/votelog/VoteLogManager.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/votelog/VoteLogManager.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votelog/VoteLogManager.java new file mode 100644 index 0000000000..8eef82197d --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votelog/VoteLogManager.java @@ -0,0 +1,99 @@ +package com.bencodez.votingplugin.votelog; + +import java.util.concurrent.TimeUnit; + +import com.bencodez.simpleapi.sql.mysql.config.MysqlConfigSpigot; +import com.bencodez.votingplugin.VotingPluginMain; + +/** Owns vote-log table setup and maintenance scheduling. */ +public final class VoteLogManager { + + private final VotingPluginMain plugin; + private VoteLogMysqlTable voteLogMysqlTable; + + public VoteLogManager(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public void load() { + if (!plugin.getConfigFile().isVoteLoggingEnabled()) { + plugin.debug("Vote logging MySQL disabled"); + return; + } + + MysqlConfigSpigot config = new MysqlConfigSpigot(plugin.getConfigFile().getVoteLoggingSection()); + if (plugin.getConfigFile().isVoteLoggingUseMainMySQL()) { + voteLogMysqlTable = createMainMysqlTable(config); + } else { + voteLogMysqlTable = createDedicatedMysqlTable(config); + } + + plugin.getTimer().scheduleAtFixedRate( + () -> voteLogMysqlTable.purgeOlderThanDays(plugin.getConfigFile().getVoteLoggingPurgeDays(), 100), + 60, 60 * 60, TimeUnit.SECONDS); + plugin.debug("Vote logging MySQL enabled"); + } + + public VoteLogMysqlTable getVoteLogMysqlTable() { + return voteLogMysqlTable; + } + + private VoteLogMysqlTable createMainMysqlTable(MysqlConfigSpigot config) { + return new VoteLogMysqlTable("votingplugin_votelog", plugin.getMysql().getMysql(), config, + plugin.getOptions().getDebug().isDebug()) { + @Override + public void logSevere(String string) { + plugin.getLogger().severe(string); + } + + @Override + public void logInfo(String string) { + plugin.getLogger().info(string); + } + + @Override + public String getServerName() { + return serverName(); + } + + @Override + public void debug(Throwable throwable) { + debugThrowable(throwable); + } + }; + } + + private VoteLogMysqlTable createDedicatedMysqlTable(MysqlConfigSpigot config) { + return new VoteLogMysqlTable("votingplugin_votelog", config, plugin.getOptions().getDebug().isDebug()) { + @Override + public void logSevere(String string) { + plugin.getLogger().severe(string); + } + + @Override + public void logInfo(String string) { + plugin.getLogger().info(string); + } + + @Override + public String getServerName() { + return serverName(); + } + + @Override + public void debug(Throwable throwable) { + debugThrowable(throwable); + } + }; + } + + private String serverName() { + return plugin.getBungeeSettings().isUseBungeecoord() ? plugin.getBungeeSettings().getServer() : ""; + } + + private void debugThrowable(Throwable throwable) { + if (plugin.getOptions().getDebug().isDebug()) { + plugin.debug(throwable); + } + } +} From d6f65ae55ecf3063be52124951060a7fcbe0f2c3 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:09:35 -0600 Subject: [PATCH 50/71] Add webhook lifecycle manager --- .../webhook/VotingPluginWebhookManager.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/webhook/VotingPluginWebhookManager.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/webhook/VotingPluginWebhookManager.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/webhook/VotingPluginWebhookManager.java new file mode 100644 index 0000000000..0b307f8360 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/webhook/VotingPluginWebhookManager.java @@ -0,0 +1,38 @@ +package com.bencodez.votingplugin.webhook; + +import com.bencodez.votingplugin.VotingPluginMain; + +/** Owns VotingPlugin webhook startup, reload, and shutdown lifecycle. */ +public final class VotingPluginWebhookManager { + + private final VotingPluginMain plugin; + private VotingPluginWebhooks webhooks; + + public VotingPluginWebhookManager(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public void load() { + if (webhooks == null) { + webhooks = new VotingPluginWebhooks(plugin); + } + reload(); + } + + public void reload() { + if (webhooks != null) { + webhooks.reload(plugin.getConfig().getConfigurationSection("Webhooks")); + } + } + + public void shutdown() { + if (webhooks != null) { + webhooks.shutdown(); + webhooks = null; + } + } + + public VotingPluginWebhooks getWebhooks() { + return webhooks; + } +} From 98de92cb2e2e8beb47fccfb09c1c77edb23d84f0 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:10:07 -0600 Subject: [PATCH 51/71] Add lifecycle refactor workflow --- .github/workflows/refactor-main-lifecycle.yml | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 .github/workflows/refactor-main-lifecycle.yml diff --git a/.github/workflows/refactor-main-lifecycle.yml b/.github/workflows/refactor-main-lifecycle.yml new file mode 100644 index 0000000000..a130bd14e0 --- /dev/null +++ b/.github/workflows/refactor-main-lifecycle.yml @@ -0,0 +1,135 @@ +name: Refactor main lifecycle services + +on: + pull_request: + branches: + - master + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + refactor: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: refactor/main-lifecycle-services + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + - name: Move lifecycle ownership out of main + run: | + python - <<'PY' + from pathlib import Path + + def replace_method(text, marker, replacement): + start = text.find(marker) + if start < 0: + raise SystemExit('method marker not found: ' + marker) + brace = text.find('{', start) + depth = 0 + for pos in range(brace, len(text)): + if text[pos] == '{': depth += 1 + elif text[pos] == '}': + depth -= 1 + if depth == 0: + return text[:start] + replacement + text[pos + 1:] + raise SystemExit('unterminated method: ' + marker) + + path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') + text = path.read_text() + + # Imports for feature-owned lifecycle components. + anchors = { + 'import com.bencodez.votingplugin.config.VotingPluginConfigHealth;\n': 'import com.bencodez.votingplugin.config.SpecialRewardsConfig;\n', + 'import com.bencodez.votingplugin.integration.votifier.VotifierIntegration;\n': 'import com.bencodez.votingplugin.listeners.BlockBreak;\n', + 'import com.bencodez.votingplugin.version.VotingPluginVersionInfo;\n': 'import com.bencodez.votingplugin.user.VotingPluginUser;\n', + 'import com.bencodez.votingplugin.votelog.VoteLogManager;\n': 'import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;\n', + 'import com.bencodez.votingplugin.webhook.VotingPluginWebhookManager;\n': 'import com.bencodez.votingplugin.webhook.VotingPluginWebhooks;\n', + } + for new, anchor in anchors.items(): + if new not in text: + text = text.replace(anchor, anchor + new, 1) + + # Remove imports no longer needed by main. + for line in [ + 'import java.io.InputStreamReader;\n', 'import java.io.Reader;\n', 'import java.net.URL;\n', + 'import java.security.CodeSource;\n', 'import java.util.zip.ZipEntry;\n', 'import java.util.zip.ZipInputStream;\n', + 'import org.bukkit.configuration.file.YamlConfiguration;\n', + ]: + text = text.replace(line, '') + + # Replace state fields with feature components. + for block in [ + '\n\t@Getter\n\tprivate String profile = "";\n', + '\n\t@Getter\n\tprivate String buildNumber = "NOTSET";\n', + '\n\t@Getter\n\tprivate String time = "";\n', + '\n\tprivate boolean votifierLoaded = true;\n', + '\n\t@Getter\n\tprivate boolean ymlError = false;\n', + '\n\t@Getter\n\tprivate VoteLogMysqlTable voteLogMysqlTable;\n', + '\n\t@Getter\n\tprivate VotingPluginWebhooks webhooks;\n', + ]: + text = text.replace(block, '\n') + + field_anchor = '\t@Getter\n\tprivate DiscordHandler discordHandler;\n' + lifecycle_fields = '''\t@Getter\n\tprivate DiscordHandler discordHandler;\n\n\tprivate VotingPluginVersionInfo versionInfo;\n\tprivate VotingPluginConfigHealth configHealth;\n\tprivate VotifierIntegration votifierIntegration;\n\tprivate VoteLogManager voteLogManager;\n\tprivate VotingPluginWebhookManager webhookManager;\n''' + text = text.replace(field_anchor, lifecycle_fields, 1) + + text = replace_method(text, '\tprivate void checkVotifier()', + '\tprivate void checkVotifier() {\n\t\tif (votifierIntegration == null) {\n\t\t\tvotifierIntegration = new VotifierIntegration(this);\n\t\t}\n\t\tvotifierIntegration.detect();\n\t}\n') + text = replace_method(text, '\tprivate void checkYMLError()', + '\tprivate void checkYMLError() {\n\t\tif (configHealth == null) {\n\t\t\tconfigHealth = new VotingPluginConfigHealth(this);\n\t\t}\n\t\tconfigHealth.check();\n\t}\n') + text = replace_method(text, '\tprivate YamlConfiguration getVersionFile()', '') + text = replace_method(text, '\tprivate void loadVersionFile()', + '\tprivate void loadVersionFile() {\n\t\tversionInfo = new VotingPluginVersionInfo(this);\n\t\tversionInfo.load();\n\t}\n') + text = replace_method(text, '\tpublic void loadVoteLoggingMySQL()', + '\tpublic void loadVoteLoggingMySQL() {\n\t\tif (voteLogManager == null) {\n\t\t\tvoteLogManager = new VoteLogManager(this);\n\t\t}\n\t\tvoteLogManager.load();\n\t}\n') + + # Preserve public getter surface as delegates. + getter_anchor = '\tpublic void loadVoteShopManager() {\n' + getters = '''\tpublic String getProfile() {\n\t\treturn versionInfo == null ? "" : versionInfo.getProfile();\n\t}\n\n\tpublic String getBuildNumber() {\n\t\treturn versionInfo == null ? "NOTSET" : versionInfo.getBuildNumber();\n\t}\n\n\tpublic String getTime() {\n\t\treturn versionInfo == null ? "" : versionInfo.getTime();\n\t}\n\n\tpublic boolean isYmlError() {\n\t\treturn configHealth != null && configHealth.hasYmlError();\n\t}\n\n\tpublic boolean isVotifierLoaded() {\n\t\treturn votifierIntegration == null || votifierIntegration.isLoaded();\n\t}\n\n\tpublic VoteLogMysqlTable getVoteLogMysqlTable() {\n\t\treturn voteLogManager == null ? null : voteLogManager.getVoteLogMysqlTable();\n\t}\n\n\tpublic VotingPluginWebhooks getWebhooks() {\n\t\treturn webhookManager == null ? null : webhookManager.getWebhooks();\n\t}\n\n''' + text = text.replace(getter_anchor, getters + getter_anchor, 1) + + # Event registration should use integration state instead of the removed field. + text = text.replace('if (votifierLoaded) {', 'if (isVotifierLoaded()) {') + + # Webhook lifecycle ownership. + old_webhook_start = '''\t\twebhooks = new VotingPluginWebhooks(this);\n\t\twebhooks.reload(getConfig().getConfigurationSection("Webhooks"));''' + new_webhook_start = '''\t\twebhookManager = new VotingPluginWebhookManager(this);\n\t\twebhookManager.load();''' + text = text.replace(old_webhook_start, new_webhook_start) + old_unload = '''\t\tif (webhooks != null) {\n\t\t\twebhooks.shutdown();\n\t\t\twebhooks = null;\n\t\t}''' + text = text.replace(old_unload, '''\t\tif (webhookManager != null) {\n\t\t\twebhookManager.shutdown();\n\t\t}''') + text = text.replace('webhooks.reload(getConfig().getConfigurationSection("Webhooks"));', + 'if (webhookManager != null) { webhookManager.reload(); }') + + # Existing reward code uses the compatibility getter rather than a removed field. + text = text.replace('section == null || webhooks == null', 'section == null || getWebhooks() == null') + text = text.replace('webhooks.createExecutor()', 'getWebhooks().createExecutor()') + text = text.replace(' + buildNumber)', ' + getBuildNumber())') + + # Remove generated JavaPlugin override comments in the touched main class. + text = text.replace('''\n\t/*\n\t * (non-Javadoc)\n\t *\n\t * @see org.bukkit.plugin.java.JavaPlugin#onEnable()\n\t */''', '') + text = text.replace('''\n\t/*\n\t * (non-Javadoc)\n\t *\n\t * @see org.bukkit.plugin.java.JavaPlugin#onDisable()\n\t */''', '') + + path.write_text(text) + PY + - name: Build + run: mvn -B -f VotingPlugin/pom.xml package + - name: Commit lifecycle refactor + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A VotingPlugin + git commit -m 'Move lifecycle services out of VotingPluginMain' + git push origin HEAD:refactor/main-lifecycle-services + - name: Remove temporary workflow + run: | + git pull --rebase origin refactor/main-lifecycle-services + git rm .github/workflows/refactor-main-lifecycle.yml + git commit -m 'Remove temporary lifecycle refactor workflow' + git push origin HEAD:refactor/main-lifecycle-services From 1a951c9a6e781efd8d0e54dfd798c599482e4d52 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:11:08 +0000 Subject: [PATCH 52/71] Move lifecycle services out of VotingPluginMain --- .../votingplugin/VotingPluginMain.java | 230 +++++------------- 1 file changed, 60 insertions(+), 170 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java index 7e58920864..969c3d5027 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java @@ -1,10 +1,6 @@ package com.bencodez.votingplugin; import java.io.File; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URL; -import java.security.CodeSource; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; @@ -20,15 +16,12 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.permissions.Permission; @@ -77,10 +70,12 @@ import com.bencodez.votingplugin.config.GUI; import com.bencodez.votingplugin.config.ShopFile; import com.bencodez.votingplugin.config.SpecialRewardsConfig; +import com.bencodez.votingplugin.config.VotingPluginConfigHealth; import com.bencodez.votingplugin.cooldown.CoolDownCheck; import com.bencodez.votingplugin.data.ServerData; import com.bencodez.votingplugin.discord.DiscordHandler; import com.bencodez.votingplugin.listeners.BlockBreak; +import com.bencodez.votingplugin.integration.votifier.VotifierIntegration; import com.bencodez.votingplugin.listeners.PlayerInteract; import com.bencodez.votingplugin.listeners.PlayerJoinEvent; import com.bencodez.votingplugin.listeners.PlayerVoteListener; @@ -113,7 +108,9 @@ import com.bencodez.votingplugin.updater.CheckUpdate; import com.bencodez.votingplugin.user.UserManager; import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.version.VotingPluginVersionInfo; import com.bencodez.votingplugin.votelog.VoteLogMysqlTable; +import com.bencodez.votingplugin.votelog.VoteLogManager; import com.bencodez.votingplugin.votelog.listeners.PlayerPostVoteLoggerListener; import com.bencodez.votingplugin.votelog.listeners.PlayerSpecialRewardLoggerListener; import com.bencodez.votingplugin.votelog.listeners.VoteMilestoneVoteLogListener; @@ -129,6 +126,7 @@ import com.bencodez.votingplugin.votesites.VoteSiteManager; import com.bencodez.votingplugin.votesites.VoteSiteRewardRegistrar; import com.bencodez.votingplugin.webhook.VotingPluginWebhooks; +import com.bencodez.votingplugin.webhook.VotingPluginWebhookManager; import com.bencodez.votingplugin.webhook.WebhookRewardEntry; import com.bencodez.votingplugin.webhook.WebhookRewardParser; @@ -192,11 +190,7 @@ public class VotingPluginMain extends AdvancedCorePlugin { @Getter private VoteTester voteTester; - @Getter - private String profile = ""; - @Getter - private String buildNumber = "NOTSET"; @Getter private ServerData serverData; @@ -211,8 +205,6 @@ public class VotingPluginMain extends AdvancedCorePlugin { @Getter private SpecialRewardsConfig specialRewardsConfig; - @Getter - private String time = ""; @Getter private TopVoterHandler topVoterHandler; @@ -248,10 +240,7 @@ public class VotingPluginMain extends AdvancedCorePlugin { @Getter private VoteSiteManager voteSiteManager; - private boolean votifierLoaded = true; - @Getter - private boolean ymlError = false; @Getter private ScheduledExecutorService voteTimer; @@ -276,6 +265,12 @@ public class VotingPluginMain extends AdvancedCorePlugin { @Getter private DiscordHandler discordHandler; + private VotingPluginVersionInfo versionInfo; + private VotingPluginConfigHealth configHealth; + private VotifierIntegration votifierIntegration; + private VoteLogManager voteLogManager; + private VotingPluginWebhookManager webhookManager; + public void addDirectlyDefinedRewards(DirectlyDefinedReward directlyDefinedReward) { getRewardHandler().addDirectlyDefined(directlyDefinedReward); } @@ -296,36 +291,47 @@ public void basicBungeeUpdate() { * Check votifier. */ private void checkVotifier() { - try { - Class.forName("com.vexsoftware.votifier.model.VotifierEvent"); - } catch (ClassNotFoundException e) { - if (!bungeeSettings.isUseBungeecoord()) { - plugin.getLogger() - .warning("No VotifierEvent found, install Votifier, NuVotifier, or another Votifier plugin"); - } else { - plugin.debug("No VotifierEvent found, but usebungeecoord enabled"); - } - votifierLoaded = false; + if (votifierIntegration == null) { + votifierIntegration = new VotifierIntegration(this); } + votifierIntegration.detect(); } + private void checkYMLError() { - if (configFile.isFailedToRead() || configVoteSites.isFailedToRead() || specialRewardsConfig.isFailedToRead() - || bungeeSettings.isFailedToRead() || gui.isFailedToRead()) { - ymlError = true; - } else { - ymlError = false; + if (configHealth == null) { + configHealth = new VotingPluginConfigHealth(this); } + configHealth.check(); + } - if (ymlError) { - plugin.getBukkitScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { - @Override - public void run() { - plugin.getLogger().severe("Failed to load a file, check startup log"); - } - }, 1); - } + public String getProfile() { + return versionInfo == null ? "" : versionInfo.getProfile(); + } + + public String getBuildNumber() { + return versionInfo == null ? "NOTSET" : versionInfo.getBuildNumber(); + } + + public String getTime() { + return versionInfo == null ? "" : versionInfo.getTime(); + } + + public boolean isYmlError() { + return configHealth != null && configHealth.hasYmlError(); + } + + public boolean isVotifierLoaded() { + return votifierIntegration == null || votifierIntegration.isLoaded(); + } + + public VoteLogMysqlTable getVoteLogMysqlTable() { + return voteLogManager == null ? null : voteLogManager.getVoteLogMysqlTable(); + } + + public VotingPluginWebhooks getWebhooks() { + return webhookManager == null ? null : webhookManager.getWebhooks(); } public void loadVoteShopManager() { @@ -383,33 +389,7 @@ public VotingPluginUser getUser(UUID uuid) { return getVotingPluginUserManager().getVotingPluginUser(uuid); } - private YamlConfiguration getVersionFile() { - try { - CodeSource src = this.getClass().getProtectionDomain().getCodeSource(); - if (src != null) { - URL jar = src.getLocation(); - ZipInputStream zip = null; - zip = new ZipInputStream(jar.openStream()); - while (true) { - ZipEntry e = zip.getNextEntry(); - if (e != null) { - String name = e.getName(); - if (name.equals("votingpluginversion.yml")) { - Reader defConfigStream = new InputStreamReader(zip); - if (defConfigStream != null) { - YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream); - defConfigStream.close(); - return defConfig; - } - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + @Deprecated public VoteSite getVoteSite(String site, boolean checkEnabled) { @@ -508,14 +488,11 @@ public void run() { } private void loadVersionFile() { - YamlConfiguration conf = getVersionFile(); - if (conf != null) { - time = conf.getString("time", ""); - profile = conf.getString("profile", ""); - buildNumber = conf.getString("buildnumber", "NOTSET"); - } + versionInfo = new VotingPluginVersionInfo(this); + versionInfo.load(); } + public void loadVoteSites() { configVoteSites.setup(); voteSiteManager = new VoteSiteManager(this); @@ -668,8 +645,8 @@ public Object getObject(OfflinePlayer player) { // load vote logging if enabled loadVoteLoggingMySQL(); - webhooks = new VotingPluginWebhooks(this); - webhooks.reload(getConfig().getConfigurationSection("Webhooks")); + webhookManager = new VotingPluginWebhookManager(this); + webhookManager.load(); if (getSpecialRewardsConfig().isNameMCLikeRewardEnabled()) { nameMCLikeCheckerTask = new NameMCLikeCheckerTask(this); @@ -684,7 +661,7 @@ public Object getObject(OfflinePlayer player) { plugin.getLogger().info("Enabled VotingPlugin " + plugin.getDescription().getVersion()); if (plugin.getDescription().getVersion().contains("SNAPSHOT")) { plugin.getLogger().info( - "Using dev build, this is not a stable build, use at your own risk. Build number: " + buildNumber); + "Using dev build, this is not a stable build, use at your own risk. Build number: " + getBuildNumber()); } boolean hasRewards = getRewardHandler().hasRewards(getConfigVoteSites().getData(), @@ -784,11 +761,6 @@ private void migrateVoteBroadcast(Config configFile) { configFile.saveData(); } - /* - * (non-Javadoc) - * - * @see org.bukkit.plugin.java.JavaPlugin#onEnable() - */ @Override public void onPreLoad() { plugin = this; @@ -827,11 +799,6 @@ public void onFinish() { } - /* - * (non-Javadoc) - * - * @see org.bukkit.plugin.java.JavaPlugin#onDisable() - */ @Override public void onUnLoad() { if (getBackendProxyHandler() != null) { @@ -841,9 +808,8 @@ public void onUnLoad() { debug(e); } } - if (webhooks != null) { - webhooks.shutdown(); - webhooks = null; + if (webhookManager != null) { + webhookManager.shutdown(); } voteTimer.shutdown(); try { @@ -914,7 +880,7 @@ private void registerEvents() { PluginManager pm = getServer().getPluginManager(); pm.registerEvents(new PlayerJoinEvent(this), this); - if (votifierLoaded) { + if (isVotifierLoaded()) { pm.registerEvents(new VotiferEvent(this), this); } pm.registerEvents(new PlayerVoteListener(this), this); @@ -1005,7 +971,7 @@ private void reloadPlugin(boolean userStorage) { voteRemindersManager.reload(); } - webhooks.reload(getConfig().getConfigurationSection("Webhooks")); + if (webhookManager != null) { webhookManager.reload(); } coolDownCheck.checkEnabled(); @@ -1221,95 +1187,19 @@ public synchronized void update() { } } - @Getter - private VoteLogMysqlTable voteLogMysqlTable; @Getter private VoteMilestonesManager voteMilestonesManager; - @Getter - private VotingPluginWebhooks webhooks; public void loadVoteLoggingMySQL() { - if (getConfigFile().isVoteLoggingEnabled()) { - if (getConfigFile().isVoteLoggingUseMainMySQL()) { - voteLogMysqlTable = new VoteLogMysqlTable("votingplugin_votelog", getMysql().getMysql(), - new MysqlConfigSpigot(getConfigFile().getVoteLoggingSection()), - getOptions().getDebug().isDebug()) { - - @Override - public void logSevere(String string) { - plugin.getLogger().severe(string); - } - - @Override - public void logInfo(String string) { - plugin.getLogger().info(string); - } - - @Override - public String getServerName() { - if (plugin.getBungeeSettings().isUseBungeecoord()) { - return plugin.getBungeeSettings().getServer(); - } else { - return ""; - } - } - - @Override - public void debug(Throwable t) { - if (getOptions().getDebug().isDebug()) { - plugin.debug(t); - } - } - }; - } else { - voteLogMysqlTable = new VoteLogMysqlTable("votingplugin_votelog", - new MysqlConfigSpigot(getConfigFile().getVoteLoggingSection()), - getOptions().getDebug().isDebug()) { - - @Override - public void logSevere(String string) { - plugin.getLogger().severe(string); - } - - @Override - public void logInfo(String string) { - plugin.getLogger().info(string); - } - - @Override - public void debug(Throwable t) { - if (getOptions().getDebug().isDebug()) { - plugin.debug(t); - } - } - - @Override - public String getServerName() { - if (plugin.getBungeeSettings().isUseBungeecoord()) { - return plugin.getBungeeSettings().getServer(); - } else { - return ""; - } - } - }; - } - - getTimer().scheduleAtFixedRate(new Runnable() { - - @Override - public void run() { - voteLogMysqlTable.purgeOlderThanDays(getConfigFile().getVoteLoggingPurgeDays(), 100); - } - }, 60, 60 * 60, TimeUnit.SECONDS); // Purge old logs every hour - - debug("Vote logging MySQL enabled"); - } else { - debug("Vote logging MySQL disabled"); + if (voteLogManager == null) { + voteLogManager = new VoteLogManager(this); } + voteLogManager.load(); } + public void updateAdvancedCoreHook() { getJavascriptEngine().put("VotingPlugin", this); allowDownloadingFromSpigot(15358); From cb0eac2ce27584a2422431b8d7b304f20c52d352 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:11:10 +0000 Subject: [PATCH 53/71] Remove temporary lifecycle refactor workflow --- .github/workflows/refactor-main-lifecycle.yml | 135 ------------------ 1 file changed, 135 deletions(-) delete mode 100644 .github/workflows/refactor-main-lifecycle.yml diff --git a/.github/workflows/refactor-main-lifecycle.yml b/.github/workflows/refactor-main-lifecycle.yml deleted file mode 100644 index a130bd14e0..0000000000 --- a/.github/workflows/refactor-main-lifecycle.yml +++ /dev/null @@ -1,135 +0,0 @@ -name: Refactor main lifecycle services - -on: - pull_request: - branches: - - master - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - refactor: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: refactor/main-lifecycle-services - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '21' - cache: maven - - name: Move lifecycle ownership out of main - run: | - python - <<'PY' - from pathlib import Path - - def replace_method(text, marker, replacement): - start = text.find(marker) - if start < 0: - raise SystemExit('method marker not found: ' + marker) - brace = text.find('{', start) - depth = 0 - for pos in range(brace, len(text)): - if text[pos] == '{': depth += 1 - elif text[pos] == '}': - depth -= 1 - if depth == 0: - return text[:start] + replacement + text[pos + 1:] - raise SystemExit('unterminated method: ' + marker) - - path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') - text = path.read_text() - - # Imports for feature-owned lifecycle components. - anchors = { - 'import com.bencodez.votingplugin.config.VotingPluginConfigHealth;\n': 'import com.bencodez.votingplugin.config.SpecialRewardsConfig;\n', - 'import com.bencodez.votingplugin.integration.votifier.VotifierIntegration;\n': 'import com.bencodez.votingplugin.listeners.BlockBreak;\n', - 'import com.bencodez.votingplugin.version.VotingPluginVersionInfo;\n': 'import com.bencodez.votingplugin.user.VotingPluginUser;\n', - 'import com.bencodez.votingplugin.votelog.VoteLogManager;\n': 'import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;\n', - 'import com.bencodez.votingplugin.webhook.VotingPluginWebhookManager;\n': 'import com.bencodez.votingplugin.webhook.VotingPluginWebhooks;\n', - } - for new, anchor in anchors.items(): - if new not in text: - text = text.replace(anchor, anchor + new, 1) - - # Remove imports no longer needed by main. - for line in [ - 'import java.io.InputStreamReader;\n', 'import java.io.Reader;\n', 'import java.net.URL;\n', - 'import java.security.CodeSource;\n', 'import java.util.zip.ZipEntry;\n', 'import java.util.zip.ZipInputStream;\n', - 'import org.bukkit.configuration.file.YamlConfiguration;\n', - ]: - text = text.replace(line, '') - - # Replace state fields with feature components. - for block in [ - '\n\t@Getter\n\tprivate String profile = "";\n', - '\n\t@Getter\n\tprivate String buildNumber = "NOTSET";\n', - '\n\t@Getter\n\tprivate String time = "";\n', - '\n\tprivate boolean votifierLoaded = true;\n', - '\n\t@Getter\n\tprivate boolean ymlError = false;\n', - '\n\t@Getter\n\tprivate VoteLogMysqlTable voteLogMysqlTable;\n', - '\n\t@Getter\n\tprivate VotingPluginWebhooks webhooks;\n', - ]: - text = text.replace(block, '\n') - - field_anchor = '\t@Getter\n\tprivate DiscordHandler discordHandler;\n' - lifecycle_fields = '''\t@Getter\n\tprivate DiscordHandler discordHandler;\n\n\tprivate VotingPluginVersionInfo versionInfo;\n\tprivate VotingPluginConfigHealth configHealth;\n\tprivate VotifierIntegration votifierIntegration;\n\tprivate VoteLogManager voteLogManager;\n\tprivate VotingPluginWebhookManager webhookManager;\n''' - text = text.replace(field_anchor, lifecycle_fields, 1) - - text = replace_method(text, '\tprivate void checkVotifier()', - '\tprivate void checkVotifier() {\n\t\tif (votifierIntegration == null) {\n\t\t\tvotifierIntegration = new VotifierIntegration(this);\n\t\t}\n\t\tvotifierIntegration.detect();\n\t}\n') - text = replace_method(text, '\tprivate void checkYMLError()', - '\tprivate void checkYMLError() {\n\t\tif (configHealth == null) {\n\t\t\tconfigHealth = new VotingPluginConfigHealth(this);\n\t\t}\n\t\tconfigHealth.check();\n\t}\n') - text = replace_method(text, '\tprivate YamlConfiguration getVersionFile()', '') - text = replace_method(text, '\tprivate void loadVersionFile()', - '\tprivate void loadVersionFile() {\n\t\tversionInfo = new VotingPluginVersionInfo(this);\n\t\tversionInfo.load();\n\t}\n') - text = replace_method(text, '\tpublic void loadVoteLoggingMySQL()', - '\tpublic void loadVoteLoggingMySQL() {\n\t\tif (voteLogManager == null) {\n\t\t\tvoteLogManager = new VoteLogManager(this);\n\t\t}\n\t\tvoteLogManager.load();\n\t}\n') - - # Preserve public getter surface as delegates. - getter_anchor = '\tpublic void loadVoteShopManager() {\n' - getters = '''\tpublic String getProfile() {\n\t\treturn versionInfo == null ? "" : versionInfo.getProfile();\n\t}\n\n\tpublic String getBuildNumber() {\n\t\treturn versionInfo == null ? "NOTSET" : versionInfo.getBuildNumber();\n\t}\n\n\tpublic String getTime() {\n\t\treturn versionInfo == null ? "" : versionInfo.getTime();\n\t}\n\n\tpublic boolean isYmlError() {\n\t\treturn configHealth != null && configHealth.hasYmlError();\n\t}\n\n\tpublic boolean isVotifierLoaded() {\n\t\treturn votifierIntegration == null || votifierIntegration.isLoaded();\n\t}\n\n\tpublic VoteLogMysqlTable getVoteLogMysqlTable() {\n\t\treturn voteLogManager == null ? null : voteLogManager.getVoteLogMysqlTable();\n\t}\n\n\tpublic VotingPluginWebhooks getWebhooks() {\n\t\treturn webhookManager == null ? null : webhookManager.getWebhooks();\n\t}\n\n''' - text = text.replace(getter_anchor, getters + getter_anchor, 1) - - # Event registration should use integration state instead of the removed field. - text = text.replace('if (votifierLoaded) {', 'if (isVotifierLoaded()) {') - - # Webhook lifecycle ownership. - old_webhook_start = '''\t\twebhooks = new VotingPluginWebhooks(this);\n\t\twebhooks.reload(getConfig().getConfigurationSection("Webhooks"));''' - new_webhook_start = '''\t\twebhookManager = new VotingPluginWebhookManager(this);\n\t\twebhookManager.load();''' - text = text.replace(old_webhook_start, new_webhook_start) - old_unload = '''\t\tif (webhooks != null) {\n\t\t\twebhooks.shutdown();\n\t\t\twebhooks = null;\n\t\t}''' - text = text.replace(old_unload, '''\t\tif (webhookManager != null) {\n\t\t\twebhookManager.shutdown();\n\t\t}''') - text = text.replace('webhooks.reload(getConfig().getConfigurationSection("Webhooks"));', - 'if (webhookManager != null) { webhookManager.reload(); }') - - # Existing reward code uses the compatibility getter rather than a removed field. - text = text.replace('section == null || webhooks == null', 'section == null || getWebhooks() == null') - text = text.replace('webhooks.createExecutor()', 'getWebhooks().createExecutor()') - text = text.replace(' + buildNumber)', ' + getBuildNumber())') - - # Remove generated JavaPlugin override comments in the touched main class. - text = text.replace('''\n\t/*\n\t * (non-Javadoc)\n\t *\n\t * @see org.bukkit.plugin.java.JavaPlugin#onEnable()\n\t */''', '') - text = text.replace('''\n\t/*\n\t * (non-Javadoc)\n\t *\n\t * @see org.bukkit.plugin.java.JavaPlugin#onDisable()\n\t */''', '') - - path.write_text(text) - PY - - name: Build - run: mvn -B -f VotingPlugin/pom.xml package - - name: Commit lifecycle refactor - run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A VotingPlugin - git commit -m 'Move lifecycle services out of VotingPluginMain' - git push origin HEAD:refactor/main-lifecycle-services - - name: Remove temporary workflow - run: | - git pull --rebase origin refactor/main-lifecycle-services - git rm .github/workflows/refactor-main-lifecycle.yml - git commit -m 'Remove temporary lifecycle refactor workflow' - git push origin HEAD:refactor/main-lifecycle-services From 4628f9409aafc44c5b276ee17b29eb2f6781eb90 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:13:04 -0600 Subject: [PATCH 54/71] Add background task component --- .../VotingPluginBackgroundTask.java | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/backgroundtask/VotingPluginBackgroundTask.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/backgroundtask/VotingPluginBackgroundTask.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backgroundtask/VotingPluginBackgroundTask.java new file mode 100644 index 0000000000..5e25f63cf3 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/backgroundtask/VotingPluginBackgroundTask.java @@ -0,0 +1,185 @@ +package com.bencodez.votingplugin.backgroundtask; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; + +import com.bencodez.advancedcore.api.user.UserDataFetchMode; +import com.bencodez.simpleapi.skull.SkullCache; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.topvoter.TopVoter; +import com.bencodez.votingplugin.topvoter.TopVoterPlayer; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +/** Owns VotingPlugin's periodic background data refresh task and its state. */ +public final class VotingPluginBackgroundTask { + + private final VotingPluginMain plugin; + private volatile boolean requested; + private volatile boolean running; + private volatile long lastRunTimeSeconds = -1; + + public VotingPluginBackgroundTask(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public synchronized void run() { + if (!(requested || plugin.getConfigFile().isAlwaysUpdate())) { + return; + } + if (!plugin.isEnabled() || running) { + return; + } + if (plugin.getConfigFile().isUpdateWithPlayersOnlineOnly() && Bukkit.getOnlinePlayers().isEmpty()) { + return; + } + + running = true; + requested = false; + try { + runRefresh(); + } finally { + running = false; + } + } + + private void runRefresh() { + synchronized (plugin) { + try { + if (!plugin.isEnabled()) { + return; + } + + plugin.getUserManager().getDataManager().clearCacheBasic(); + SkullCache.flushWeek(); + plugin.debug("Starting background task, current cached users: " + + plugin.getUserManager().getDataManager().getUserDataCache().keySet().size()); + + boolean extraBackgroundUpdate = plugin.getConfigFile().isExtraBackgroundUpdate(); + long startTime = System.currentTimeMillis(); + LinkedHashMap> voteToday = new LinkedHashMap<>(); + LinkedHashMap> tempTopVoter = new LinkedHashMap<>(); + + ArrayList topVotersToCheck = new ArrayList<>(); + for (TopVoter top : TopVoter.values()) { + if (plugin.getConfigFile().getLoadTopVoter(top)) { + topVotersToCheck.add(top); + tempTopVoter.put(top, new LinkedHashMap<>()); + } + } + + boolean ignorePermission = plugin.getConfigFile().isTopVoterIgnorePermission(); + ArrayList blackList = plugin.getConfigFile().getBlackList(); + ZoneId zone = ZoneId.systemDefault(); + LocalDate today = LocalDate.now(zone); + long startOfDayMs = today.atStartOfDay(zone).toInstant().toEpochMilli(); + long startOfNextDayMs = today.plusDays(1).atStartOfDay(zone).toInstant().toEpochMilli(); + long afterSetup = System.currentTimeMillis(); + + plugin.getUserManager().forEachUserKeys((uuid, columns) -> { + if (!plugin.isEnabled()) { + return; + } + + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false); + user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); + user.updateTempCacheWithColumns(columns); + try { + if (!user.isBanned() && !blackList.contains(user.getPlayerName())) { + if (!ignorePermission || !user.isTopVoterIgnore()) { + TopVoterPlayer player = user.getTopVoterPlayer(); + for (TopVoter top : topVotersToCheck) { + int total = user.getTotal(top); + if (total > 0) { + tempTopVoter.get(top).put(player, total); + } + } + } + + HashMap times = null; + for (Entry entry : user.getLastVotes().entrySet()) { + VoteSite site = entry.getKey(); + if (!site.isEnabled() || site.isHidden()) { + continue; + } + long time = entry.getValue(); + if (time >= startOfDayMs && time < startOfNextDayMs) { + if (times == null) { + times = new HashMap<>(); + } + times.put(site, LocalDateTime.ofInstant(Instant.ofEpochMilli(time), zone)); + } + } + if (times != null && !times.isEmpty()) { + voteToday.put(user.getTopVoterPlayer(), times); + } + } + + if (extraBackgroundUpdate && user.isOnline()) { + user.offVote(); + } + if (!plugin.getPlaceholders().getCacheLevel().onlineOnly() || user.isOnline()) { + plugin.getPlaceholders().onUpdate(user, false); + } + } finally { + user.clearTempCache(); + } + }, count -> { + long elapsed = (System.currentTimeMillis() - afterSetup) / 1000; + plugin.debug("Finished getting player data in " + elapsed + " seconds, " + count + " users, " + + plugin.getStorageType()); + }); + + plugin.getTopVoterHandler().updateTopVoters(tempTopVoter); + plugin.getPlaceholders().onUpdate(); + plugin.setVoteToday(voteToday); + plugin.getServerData().updateValues(); + plugin.getSigns().updateSigns(); + + if (plugin.getConfigFile().isDiscordSRVEnabled() && plugin.getDiscordHandler() != null) { + for (TopVoter top : TopVoter.values()) { + if (!plugin.getConfigFile().isDiscordSRVTopVoterNewMessageOnUpdate(top)) { + plugin.getDiscordHandler().updateTopVoterMessageId(top); + } + } + } + + plugin.getUserManager().getDataManager().clearNonNeededCachedUsers(); + plugin.extraDebug("Current cached users: " + + plugin.getUserManager().getDataManager().getUserDataCache().keySet().size()); + + lastRunTimeSeconds = (System.currentTimeMillis() - startTime) / 1000; + plugin.debug("Background task finished. Total time: " + lastRunTimeSeconds + " seconds"); + } catch (Exception exception) { + if (plugin.isEnabled()) { + plugin.getLogger().info("Looks like something went wrong"); + } + plugin.debug(exception); + } + } + } + + public boolean isRequested() { + return requested; + } + + public void setRequested(boolean requested) { + this.requested = requested; + } + + public boolean isRunning() { + return running; + } + + public long getLastRunTimeSeconds() { + return lastRunTimeSeconds; + } +} From ca3ddb9227e7651aed5d727450263436198beba2 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:13:12 -0600 Subject: [PATCH 55/71] Test background task state --- .../VotingPluginBackgroundTaskTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backgroundtask/VotingPluginBackgroundTaskTest.java diff --git a/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backgroundtask/VotingPluginBackgroundTaskTest.java b/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backgroundtask/VotingPluginBackgroundTaskTest.java new file mode 100644 index 0000000000..61a63b59fb --- /dev/null +++ b/VotingPlugin/src/test/java/com/bencodez/votingplugin/tests/backgroundtask/VotingPluginBackgroundTaskTest.java @@ -0,0 +1,23 @@ +package com.bencodez.votingplugin.tests.backgroundtask; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; + +import org.junit.jupiter.api.Test; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.backgroundtask.VotingPluginBackgroundTask; + +public class VotingPluginBackgroundTaskTest { + + @Test + public void requestedStateCanBeDelegated() { + VotingPluginBackgroundTask task = new VotingPluginBackgroundTask(mock(VotingPluginMain.class)); + assertFalse(task.isRequested()); + task.setRequested(true); + assertTrue(task.isRequested()); + task.setRequested(false); + assertFalse(task.isRequested()); + } +} From 4ddf66946d105732d1f76ebd57d201fefd36399b Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:13:27 -0600 Subject: [PATCH 56/71] Add background task refactor workflow --- .../workflows/refactor-background-task.yml | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 .github/workflows/refactor-background-task.yml diff --git a/.github/workflows/refactor-background-task.yml b/.github/workflows/refactor-background-task.yml new file mode 100644 index 0000000000..f162b9a6dc --- /dev/null +++ b/.github/workflows/refactor-background-task.yml @@ -0,0 +1,97 @@ +name: Extract background task + +on: + pull_request: + branches: + - master + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + refactor: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: refactor/background-task + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + - name: Delegate background task from main + run: | + python - <<'PY' + from pathlib import Path + + def replace_method(text, marker, replacement): + start = text.find(marker) + if start < 0: + raise SystemExit('method marker not found: ' + marker) + brace = text.find('{', start) + depth = 0 + for pos in range(brace, len(text)): + if text[pos] == '{': depth += 1 + elif text[pos] == '}': + depth -= 1 + if depth == 0: + return text[:start] + replacement + text[pos + 1:] + raise SystemExit('unterminated method: ' + marker) + + path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') + text = path.read_text() + anchor = 'import com.bencodez.votingplugin.backendproxy.BackendProxyHandler;\n' + imp = 'import com.bencodez.votingplugin.backgroundtask.VotingPluginBackgroundTask;\n' + if imp not in text: + text = text.replace(anchor, anchor + imp, 1) + + for block in [ + '\n\t@Getter\n\t@Setter\n\tprivate boolean update = false;\n', + '\n\t@Getter\n\tprivate boolean updateStarted = false;\n', + '\n\t@Getter\n\tprivate long lastBackgroundTaskTimeTaken = -1;\n', + ]: + text = text.replace(block, '\n') + + field_anchor = '\tprivate VotingPluginVersionInfo versionInfo;\n' + if '\tprivate VotingPluginBackgroundTask backgroundTask;\n' not in text: + text = text.replace(field_anchor, '\tprivate VotingPluginBackgroundTask backgroundTask;\n' + field_anchor, 1) + + delegates = '''\tpublic boolean isUpdate() {\n\t\treturn backgroundTask != null && backgroundTask.isRequested();\n\t}\n\n\tpublic void setUpdate(boolean update) {\n\t\tif (backgroundTask == null) {\n\t\t\tbackgroundTask = new VotingPluginBackgroundTask(this);\n\t\t}\n\t\tbackgroundTask.setRequested(update);\n\t}\n\n\tpublic boolean isUpdateStarted() {\n\t\treturn backgroundTask != null && backgroundTask.isRunning();\n\t}\n\n\tpublic long getLastBackgroundTaskTimeTaken() {\n\t\treturn backgroundTask == null ? -1 : backgroundTask.getLastRunTimeSeconds();\n\t}\n\n''' + method_anchor = '\tpublic void addDirectlyDefinedRewards(' + text = text.replace(method_anchor, delegates + method_anchor, 1) + + text = replace_method(text, '\tpublic synchronized void update()', + '\tpublic synchronized void update() {\n\t\tif (backgroundTask == null) {\n\t\t\tbackgroundTask = new VotingPluginBackgroundTask(this);\n\t\t}\n\t\tbackgroundTask.run();\n\t}\n') + + # Construct at plugin preload so all later request/update calls use the component. + preload = '\t\tplugin = this;\n' + if '\t\tbackgroundTask = new VotingPluginBackgroundTask(this);\n' not in text: + text = text.replace(preload, preload + '\t\tbackgroundTask = new VotingPluginBackgroundTask(this);\n', 1) + + # Remove imports that were only used by the extracted update body. + for line in [ + 'import java.time.Instant;\n', 'import java.time.LocalDate;\n', + 'import com.bencodez.advancedcore.api.user.UserDataFetchMode;\n', + 'import com.bencodez.simpleapi.skull.SkullCache;\n', + ]: + text = text.replace(line, '') + path.write_text(text) + PY + - name: Build + run: mvn -B -f VotingPlugin/pom.xml package + - name: Commit background task refactor + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A VotingPlugin + git commit -m 'Extract VotingPlugin background task' + git push origin HEAD:refactor/background-task + - name: Remove temporary workflow + run: | + git pull --rebase origin refactor/background-task + git rm .github/workflows/refactor-background-task.yml + git commit -m 'Remove temporary background task workflow' + git push origin HEAD:refactor/background-task From e737974d6bf968a3871309aa3a10cc73890c2520 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:14:23 +0000 Subject: [PATCH 57/71] Extract VotingPlugin background task --- .../votingplugin/VotingPluginMain.java | 190 +++--------------- 1 file changed, 25 insertions(+), 165 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java index 969c3d5027..6f824dc868 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java @@ -1,8 +1,6 @@ package com.bencodez.votingplugin; import java.io.File; -import java.time.Instant; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.YearMonth; import java.time.ZoneId; @@ -46,15 +44,14 @@ import com.bencodez.advancedcore.api.rewards.injected.RewardInjectValidator; import com.bencodez.advancedcore.api.rewards.injectedrequirement.RequirementInjectConfigurationSection; import com.bencodez.advancedcore.api.user.AdvancedCoreUser; -import com.bencodez.advancedcore.api.user.UserDataFetchMode; import com.bencodez.advancedcore.api.user.UserStartup; import com.bencodez.simpleapi.file.YMLConfig; -import com.bencodez.simpleapi.skull.SkullCache; import com.bencodez.simpleapi.sql.mysql.config.MysqlConfigSpigot; import com.bencodez.simpleapi.time.ParsedDuration; import com.bencodez.simpleapi.updater.Updater; import com.bencodez.votingplugin.broadcast.BroadcastHandler; import com.bencodez.votingplugin.backendproxy.BackendProxyHandler; +import com.bencodez.votingplugin.backgroundtask.VotingPluginBackgroundTask; import com.bencodez.votingplugin.backendproxy.BackendProxyRewardRegistrar; import com.bencodez.votingplugin.broadcast.BroadcastSettings; import com.bencodez.votingplugin.commands.CommandLoader; @@ -212,16 +209,11 @@ public class VotingPluginMain extends AdvancedCorePlugin { @Getter private TopVoterState topVoterState; - @Getter - @Setter - private boolean update = false; @Getter @Setter private Updater updater; - @Getter - private boolean updateStarted = false; @Getter @Setter @@ -254,8 +246,6 @@ public class VotingPluginMain extends AdvancedCorePlugin { @Getter private ServiceSiteHandler serviceSiteHandler; - @Getter - private long lastBackgroundTaskTimeTaken = -1; @Getter @@ -265,12 +255,32 @@ public class VotingPluginMain extends AdvancedCorePlugin { @Getter private DiscordHandler discordHandler; + private VotingPluginBackgroundTask backgroundTask; private VotingPluginVersionInfo versionInfo; private VotingPluginConfigHealth configHealth; private VotifierIntegration votifierIntegration; private VoteLogManager voteLogManager; private VotingPluginWebhookManager webhookManager; + public boolean isUpdate() { + return backgroundTask != null && backgroundTask.isRequested(); + } + + public void setUpdate(boolean update) { + if (backgroundTask == null) { + backgroundTask = new VotingPluginBackgroundTask(this); + } + backgroundTask.setRequested(update); + } + + public boolean isUpdateStarted() { + return backgroundTask != null && backgroundTask.isRunning(); + } + + public long getLastBackgroundTaskTimeTaken() { + return backgroundTask == null ? -1 : backgroundTask.getLastRunTimeSeconds(); + } + public void addDirectlyDefinedRewards(DirectlyDefinedReward directlyDefinedReward) { getRewardHandler().addDirectlyDefined(directlyDefinedReward); } @@ -1030,164 +1040,14 @@ private void setupFiles() { } public synchronized void update() { - if (!(update || configFile.isAlwaysUpdate())) { - return; - } - if (plugin == null) { - return; - } - if (updateStarted) { - return; - } - if (configFile.isUpdateWithPlayersOnlineOnly() && Bukkit.getOnlinePlayers().isEmpty()) { - return; - } - - updateStarted = true; - update = false; - - synchronized (plugin) { - try { - if (plugin == null || !plugin.isEnabled()) { - return; - } - - getUserManager().getDataManager().clearCacheBasic(); - SkullCache.flushWeek(); - - plugin.debug("Starting background task, current cached users: " - + plugin.getUserManager().getDataManager().getUserDataCache().keySet().size()); - - boolean extraBackgroundUpdate = configFile.isExtraBackgroundUpdate(); - long startTime = System.currentTimeMillis(); - - LinkedHashMap> voteToday = new LinkedHashMap<>(); - LinkedHashMap> tempTopVoter = new LinkedHashMap<>(); - - ArrayList topVotersToCheck = new ArrayList<>(); - for (TopVoter top : TopVoter.values()) { - if (plugin == null) { - return; - } - if (plugin.getConfigFile().getLoadTopVoter(top)) { - topVotersToCheck.add(top); - tempTopVoter.put(top, new LinkedHashMap<>()); - } - } - - boolean topVoterIgnorePermissionUse = plugin.getConfigFile().isTopVoterIgnorePermission(); - ArrayList blackList = plugin.getConfigFile().getBlackList(); - - // Compute "today" bounds once (avoid LocalDateTime.now() + MiscUtils - // conversions in tight loops) - final ZoneId zone = ZoneId.systemDefault(); - final LocalDate today = LocalDate.now(zone); - final long startOfDayMs = today.atStartOfDay(zone).toInstant().toEpochMilli(); - final long startOfNextDayMs = today.plusDays(1).atStartOfDay(zone).toInstant().toEpochMilli(); - - final long afterSetup = System.currentTimeMillis(); - - // STREAM all users (MYSQL/SQLITE/FLAT) via the new shortcut method - plugin.getUserManager().forEachUserKeys((uuid, columns) -> { - if (plugin == null || !plugin.isEnabled()) { - return; - } - - VotingPluginUser user = getVotingPluginUserManager().getVotingPluginUser(uuid, false); - user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY); - user.updateTempCacheWithColumns(columns); - - try { - if (!user.isBanned() && !blackList.contains(user.getPlayerName())) { - - if (!topVoterIgnorePermissionUse || !user.isTopVoterIgnore()) { - TopVoterPlayer tvp = user.getTopVoterPlayer(); - for (TopVoter top : topVotersToCheck) { - int total = user.getTotal(top); - if (total > 0) { - tempTopVoter.get(top).put(tvp, total); - } - } - } - - // Only allocate if we actually find a "today" vote - HashMap times = null; - - for (Entry entry : user.getLastVotes().entrySet()) { - VoteSite site = entry.getKey(); - if (!site.isEnabled() || site.isHidden()) { - continue; - } - - long time = entry.getValue(); - if (time >= startOfDayMs && time < startOfNextDayMs) { - if (times == null) { - times = new HashMap<>(); - } - times.put(site, LocalDateTime.ofInstant(Instant.ofEpochMilli(time), zone)); - } - } - - if (times != null && !times.isEmpty()) { - voteToday.put(user.getTopVoterPlayer(), times); - } - } - - if (extraBackgroundUpdate && user.isOnline()) { - user.offVote(); - } - - if (!plugin.getPlaceholders().getCacheLevel().onlineOnly() || user.isOnline()) { - plugin.getPlaceholders().onUpdate(user, false); - } - } finally { - user.clearTempCache(); - } - - }, (count) -> { - long time1 = (System.currentTimeMillis() - afterSetup) / 1000; - plugin.debug("Finished getting player data in " + time1 + " seconds, " + count + " users, " - + plugin.getStorageType()); - }); - - // Final processing (runs once after ALL users processed) - topVoterHandler.updateTopVoters(tempTopVoter); - placeholders.onUpdate(); - setVoteToday(voteToday); - serverData.updateValues(); - getSigns().updateSigns(); - - - if (plugin.getConfigFile().isDiscordSRVEnabled() && getDiscordHandler() != null) { - for (TopVoter top : TopVoter.values()) { - if (!plugin.getConfigFile().isDiscordSRVTopVoterNewMessageOnUpdate(top)) { - getDiscordHandler().updateTopVoterMessageId(top); - } - } - } - - plugin.getUserManager().getDataManager().clearNonNeededCachedUsers(); - plugin.extraDebug("Current cached users: " - + plugin.getUserManager().getDataManager().getUserDataCache().keySet().size()); - - update = false; - - long totalTime = (System.currentTimeMillis() - startTime) / 1000; - lastBackgroundTaskTimeTaken = totalTime; - plugin.debug("Background task finished. Total time: " + totalTime + " seconds"); - - } catch (Exception ex) { - if (plugin != null) { - plugin.getLogger().info("Looks like something went wrong"); - } - ex.printStackTrace(); - } finally { - updateStarted = false; - } + if (backgroundTask == null) { + backgroundTask = new VotingPluginBackgroundTask(this); } + backgroundTask.run(); } + @Getter private VoteMilestonesManager voteMilestonesManager; From 656e9b050cbf39b0750329a460127e998bf95dca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:14:25 +0000 Subject: [PATCH 58/71] Remove temporary background task workflow --- .../workflows/refactor-background-task.yml | 97 ------------------- 1 file changed, 97 deletions(-) delete mode 100644 .github/workflows/refactor-background-task.yml diff --git a/.github/workflows/refactor-background-task.yml b/.github/workflows/refactor-background-task.yml deleted file mode 100644 index f162b9a6dc..0000000000 --- a/.github/workflows/refactor-background-task.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: Extract background task - -on: - pull_request: - branches: - - master - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - refactor: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: refactor/background-task - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '21' - cache: maven - - name: Delegate background task from main - run: | - python - <<'PY' - from pathlib import Path - - def replace_method(text, marker, replacement): - start = text.find(marker) - if start < 0: - raise SystemExit('method marker not found: ' + marker) - brace = text.find('{', start) - depth = 0 - for pos in range(brace, len(text)): - if text[pos] == '{': depth += 1 - elif text[pos] == '}': - depth -= 1 - if depth == 0: - return text[:start] + replacement + text[pos + 1:] - raise SystemExit('unterminated method: ' + marker) - - path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java') - text = path.read_text() - anchor = 'import com.bencodez.votingplugin.backendproxy.BackendProxyHandler;\n' - imp = 'import com.bencodez.votingplugin.backgroundtask.VotingPluginBackgroundTask;\n' - if imp not in text: - text = text.replace(anchor, anchor + imp, 1) - - for block in [ - '\n\t@Getter\n\t@Setter\n\tprivate boolean update = false;\n', - '\n\t@Getter\n\tprivate boolean updateStarted = false;\n', - '\n\t@Getter\n\tprivate long lastBackgroundTaskTimeTaken = -1;\n', - ]: - text = text.replace(block, '\n') - - field_anchor = '\tprivate VotingPluginVersionInfo versionInfo;\n' - if '\tprivate VotingPluginBackgroundTask backgroundTask;\n' not in text: - text = text.replace(field_anchor, '\tprivate VotingPluginBackgroundTask backgroundTask;\n' + field_anchor, 1) - - delegates = '''\tpublic boolean isUpdate() {\n\t\treturn backgroundTask != null && backgroundTask.isRequested();\n\t}\n\n\tpublic void setUpdate(boolean update) {\n\t\tif (backgroundTask == null) {\n\t\t\tbackgroundTask = new VotingPluginBackgroundTask(this);\n\t\t}\n\t\tbackgroundTask.setRequested(update);\n\t}\n\n\tpublic boolean isUpdateStarted() {\n\t\treturn backgroundTask != null && backgroundTask.isRunning();\n\t}\n\n\tpublic long getLastBackgroundTaskTimeTaken() {\n\t\treturn backgroundTask == null ? -1 : backgroundTask.getLastRunTimeSeconds();\n\t}\n\n''' - method_anchor = '\tpublic void addDirectlyDefinedRewards(' - text = text.replace(method_anchor, delegates + method_anchor, 1) - - text = replace_method(text, '\tpublic synchronized void update()', - '\tpublic synchronized void update() {\n\t\tif (backgroundTask == null) {\n\t\t\tbackgroundTask = new VotingPluginBackgroundTask(this);\n\t\t}\n\t\tbackgroundTask.run();\n\t}\n') - - # Construct at plugin preload so all later request/update calls use the component. - preload = '\t\tplugin = this;\n' - if '\t\tbackgroundTask = new VotingPluginBackgroundTask(this);\n' not in text: - text = text.replace(preload, preload + '\t\tbackgroundTask = new VotingPluginBackgroundTask(this);\n', 1) - - # Remove imports that were only used by the extracted update body. - for line in [ - 'import java.time.Instant;\n', 'import java.time.LocalDate;\n', - 'import com.bencodez.advancedcore.api.user.UserDataFetchMode;\n', - 'import com.bencodez.simpleapi.skull.SkullCache;\n', - ]: - text = text.replace(line, '') - path.write_text(text) - PY - - name: Build - run: mvn -B -f VotingPlugin/pom.xml package - - name: Commit background task refactor - run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A VotingPlugin - git commit -m 'Extract VotingPlugin background task' - git push origin HEAD:refactor/background-task - - name: Remove temporary workflow - run: | - git pull --rebase origin refactor/background-task - git rm .github/workflows/refactor-background-task.yml - git commit -m 'Remove temporary background task workflow' - git push origin HEAD:refactor/background-task From 2d80136ee4d4e18a74c3d0cecc9e5b8e37a52946 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:15:16 -0600 Subject: [PATCH 59/71] Add VoteParty state component --- .../voteparty/VotePartyState.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyState.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyState.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyState.java new file mode 100644 index 0000000000..99d31ce860 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyState.java @@ -0,0 +1,62 @@ +package com.bencodez.votingplugin.specialrewards.voteparty; + +import java.util.ArrayList; +import java.util.List; + +import com.bencodez.simpleapi.sql.DataType; +import com.bencodez.votingplugin.VotingPluginMain; + +/** Owns persistent VoteParty totals, participant state, and per-user counters. */ +public final class VotePartyState { + + private static final String TOTAL_PATH = "VoteParty.Total"; + private static final String VOTED_PATH = "VoteParty.Voted"; + private static final String USER_COUNT_KEY = "VotePartyVotes"; + + private final VotingPluginMain plugin; + + public VotePartyState(VotingPluginMain plugin) { + this.plugin = plugin; + } + + public int getTotalVotes() { + return plugin.getServerData().getData().getInt(TOTAL_PATH); + } + + public void setTotalVotes(int value) { + plugin.getServerData().getData().set(TOTAL_PATH, value); + plugin.getServerData().saveData(); + } + + public List getVotedUsers() { + List users = plugin.getServerData().getData().getStringList(VOTED_PATH); + return users == null ? new ArrayList<>() : users; + } + + public void setVotedUsers(List users) { + plugin.getServerData().getData().set(VOTED_PATH, users); + plugin.getServerData().saveData(); + } + + public int getVotesRequired() { + int required = plugin.getSpecialRewardsConfig().getVotePartyVotesRequired(); + int extra = plugin.getServerData().getVotePartyExtraRequired(); + return extra > 0 ? required + extra : required; + } + + public int getNeededVotes() { + return getVotesRequired() - getTotalVotes(); + } + + public void reset(boolean resetTotal) { + if (resetTotal) { + setTotalVotes(0); + } + setVotedUsers(new ArrayList<>()); + resetUserCounts(); + } + + public void resetUserCounts() { + plugin.getUserManager().removeAllKeyValues(USER_COUNT_KEY, DataType.INTEGER); + } +} From ac0b777027de27a7e500696cf197fa66da0e7bb4 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:15:32 -0600 Subject: [PATCH 60/71] Add VoteParty reward handler --- .../voteparty/VotePartyRewardHandler.java | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyRewardHandler.java diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyRewardHandler.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyRewardHandler.java new file mode 100644 index 0000000000..86a2097139 --- /dev/null +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VotePartyRewardHandler.java @@ -0,0 +1,126 @@ +package com.bencodez.votingplugin.specialrewards.voteparty; + +import java.util.ArrayList; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.misc.MiscUtils; +import com.bencodez.advancedcore.api.rewards.RewardBuilder; +import com.bencodez.advancedcore.api.user.UserDataFetchMode; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.user.VotingPluginUser; + +/** Owns VoteParty reward delivery and global command fan-out. */ +public final class VotePartyRewardHandler { + + private final VotingPluginMain plugin; + private final VotePartyState state; + + public VotePartyRewardHandler(VotingPluginMain plugin, VotePartyState state) { + this.plugin = plugin; + this.state = state; + } + + public void giveReward(VotingPluginUser user, boolean useBungee) { + if (plugin.getSpecialRewardsConfig().getVotePartyUserVotesRequired() > 0 + && user.getVotePartyVotes() < plugin.getSpecialRewardsConfig().getVotePartyUserVotesRequired()) { + return; + } + giveReward(user, user.isOnline(), useBungee); + } + + public void giveReward(VotingPluginUser user, boolean online, boolean useBungee) { + new RewardBuilder(plugin.getSpecialRewardsConfig().getData(), + plugin.getSpecialRewardsConfig().getVotePartyRewardsPath()).setOnline(online) + .withPlaceHolder("VotesRequired", "" + plugin.getSpecialRewardsConfig().getVotePartyVotesRequired()) + .withPlaceHolder("FirstVotePartyToday", "" + !plugin.getServerData().isLastVotePartySameDay()) + .setServer(useBungee).send(user); + } + + public void giveRewards(VotingPluginUser triggeringUser, boolean forceBungee) { + MiscUtils.getInstance().broadcast(plugin.getSpecialRewardsConfig().getVotePartyBroadcast()); + dispatchGlobalCommands(randomOnlinePlayerName()); + + if (plugin.getSpecialRewardsConfig().isVotePartyGiveAllPlayers()) { + giveAllPlayers(triggeringUser, forceBungee); + } else { + giveVotedPlayers(triggeringUser, forceBungee); + } + } + + public String randomOnlinePlayerName() { + ArrayList players = new ArrayList<>(); + for (Player player : Bukkit.getOnlinePlayers()) { + players.add(player.getName()); + } + if (players.isEmpty()) { + return "No Player"; + } + return players.get(ThreadLocalRandom.current().nextInt(players.size())); + } + + private void dispatchGlobalCommands(String randomPlayer) { + for (String command : plugin.getSpecialRewardsConfig().getVotePartyGlobalCommands()) { + plugin.getBukkitScheduler().runTask(plugin, + () -> Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), + PlaceholderUtils.replacePlaceHolder(command, "randomonlineplayer", randomPlayer))); + } + + ArrayList randomCommands = plugin.getSpecialRewardsConfig().getVotePartyGlobalRandomCommand(); + if (!randomCommands.isEmpty()) { + plugin.getBukkitScheduler().runTask(plugin, () -> Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), + PlaceholderUtils.replacePlaceHolder( + randomCommands.get(ThreadLocalRandom.current().nextInt(randomCommands.size())), + "randomonlineplayer", randomPlayer))); + } + } + + private void giveAllPlayers(VotingPluginUser triggeringUser, boolean forceBungee) { + plugin.debug("Trying to give all players vote party"); + ArrayList alreadyGiven = new ArrayList<>(); + for (Player player : Bukkit.getOnlinePlayers()) { + VotingPluginUser user = resolveUser(triggeringUser, player.getUniqueId(), player); + if (!plugin.getSpecialRewardsConfig().isVotePartyGiveOnlinePlayersOnly() || user.isOnline()) { + giveReward(user, forceBungee); + } + alreadyGiven.add(player.getUniqueId().toString()); + } + + for (String uuid : plugin.getVotingPluginUserManager().getAllUUIDs()) { + if (alreadyGiven.contains(uuid)) { + continue; + } + VotingPluginUser user = resolveUser(triggeringUser, UUID.fromString(uuid), null); + if (!plugin.getSpecialRewardsConfig().isVotePartyGiveOnlinePlayersOnly() || user.isOnline()) { + giveReward(user, forceBungee); + } + } + } + + private void giveVotedPlayers(VotingPluginUser triggeringUser, boolean forceBungee) { + plugin.debug("Trying to give all voted players vote party"); + plugin.debug(ArrayUtils.makeStringList(state.getVotedUsers())); + for (String uuid : state.getVotedUsers()) { + VotingPluginUser user = resolveUser(triggeringUser, UUID.fromString(uuid), null); + if (!plugin.getSpecialRewardsConfig().isVotePartyGiveOnlinePlayersOnly() || user.isOnline()) { + giveReward(user, forceBungee); + } + } + } + + private VotingPluginUser resolveUser(VotingPluginUser triggeringUser, UUID uuid, Player onlinePlayer) { + if (triggeringUser != null && triggeringUser.getJavaUUID().equals(uuid)) { + return triggeringUser; + } + VotingPluginUser user = onlinePlayer == null + ? plugin.getVotingPluginUserManager().getVotingPluginUser(uuid) + : plugin.getVotingPluginUserManager().getVotingPluginUser(onlinePlayer); + user.userDataFetechMode(UserDataFetchMode.NO_CACHE); + return user; + } +} From 6f142e7f31ba2b509c6e61db3dd38729ec0b3ad4 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:16:00 -0600 Subject: [PATCH 61/71] Add VoteParty refactor workflow --- .../refactor-voteparty-components.yml | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 .github/workflows/refactor-voteparty-components.yml diff --git a/.github/workflows/refactor-voteparty-components.yml b/.github/workflows/refactor-voteparty-components.yml new file mode 100644 index 0000000000..06f5ad9ce0 --- /dev/null +++ b/.github/workflows/refactor-voteparty-components.yml @@ -0,0 +1,108 @@ +name: Split VoteParty components + +on: + pull_request: + branches: + - master + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + refactor: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: refactor/voteparty-components + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + - name: Delegate VoteParty state and rewards + run: | + python - <<'PY' + from pathlib import Path + + def replace_method(text, marker, replacement): + start = text.find(marker) + if start < 0: + raise SystemExit('method marker not found: ' + marker) + brace = text.find('{', start) + depth = 0 + for pos in range(brace, len(text)): + if text[pos] == '{': depth += 1 + elif text[pos] == '}': + depth -= 1 + if depth == 0: + return text[:start] + replacement + text[pos + 1:] + raise SystemExit('unterminated method: ' + marker) + + path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VoteParty.java') + text = path.read_text() + + # Remove generated boilerplate and imports now owned by reward/state components. + text = text.replace('// TODO: Auto-generated Javadoc\n/**\n * The Class VoteParty.\n */\n', '/** Coordinates VoteParty voting, reminders, commands, and reset events. */\n') + for line in [ + 'import java.util.Random;\n', 'import java.util.UUID;\n', + 'import java.util.concurrent.ThreadLocalRandom;\n', + 'import com.bencodez.advancedcore.api.rewards.RewardBuilder;\n', + 'import com.bencodez.advancedcore.api.user.UserDataFetchMode;\n', + 'import com.bencodez.simpleapi.sql.DataType;\n', + ]: + text = text.replace(line, '') + + field = '\tprivate VotingPluginMain plugin;\n' + text = text.replace(field, field + '\tprivate final VotePartyState state;\n\tprivate final VotePartyRewardHandler rewardHandler;\n', 1) + ctor = '\t\tthis.plugin = plugin;\n' + text = text.replace(ctor, ctor + '\t\tthis.state = new VotePartyState(plugin);\n\t\tthis.rewardHandler = new VotePartyRewardHandler(plugin, state);\n', 1) + + text = replace_method(text, '\tpublic void addTotal(VotingPluginUser user)', + '\tpublic void addTotal(VotingPluginUser user) {\n\t\tstate.setTotalVotes(state.getTotalVotes() + 1);\n\t\tuser.setVotePartyVotes(user.getVotePartyVotes() + 1);\n\t\tplugin.getPlaceholders().onVotePartyUpdate();\n\t}\n') + text = replace_method(text, '\tpublic void addVotePlayer(VotingPluginUser user)', + '\tpublic void addVotePlayer(VotingPluginUser user) {\n\t\tString uuid = user.getUUID();\n\t\tList voted = state.getVotedUsers();\n\t\tif (!voted.contains(uuid)) {\n\t\t\tvoted.add(uuid);\n\t\t\tstate.setVotedUsers(voted);\n\t\t}\n\t}\n') + text = replace_method(text, '\tpublic int getNeededVotes()', + '\tpublic int getNeededVotes() {\n\t\treturn state.getNeededVotes();\n\t}\n') + text = replace_method(text, '\tpublic String getRandomPlayerName()', + '\tpublic String getRandomPlayerName() {\n\t\treturn rewardHandler.randomOnlinePlayerName();\n\t}\n') + text = replace_method(text, '\tpublic int getTotalVotes()', + '\tpublic int getTotalVotes() {\n\t\treturn state.getTotalVotes();\n\t}\n') + text = replace_method(text, '\tpublic List getVotedUsers()', + '\tpublic List getVotedUsers() {\n\t\treturn state.getVotedUsers();\n\t}\n') + text = replace_method(text, '\tpublic int getVotesRequired()', + '\tpublic int getVotesRequired() {\n\t\treturn state.getVotesRequired();\n\t}\n') + text = replace_method(text, '\tpublic void giveReward(VotingPluginUser user, boolean useBungee)', + '\tpublic void giveReward(VotingPluginUser user, boolean useBungee) {\n\t\trewardHandler.giveReward(user, useBungee);\n\t}\n') + text = replace_method(text, '\tpublic void giveReward(VotingPluginUser user, boolean online, boolean useBungee)', + '\tpublic void giveReward(VotingPluginUser user, boolean online, boolean useBungee) {\n\t\trewardHandler.giveReward(user, online, useBungee);\n\t}\n') + text = replace_method(text, '\tpublic void giveRewards(VotingPluginUser orgUser, boolean forceBungee)', + '\tpublic void giveRewards(VotingPluginUser orgUser, boolean forceBungee) {\n\t\trewardHandler.giveRewards(orgUser, forceBungee);\n\t\treset(false);\n\t}\n') + text = replace_method(text, '\tpublic void reset(boolean override)', + '\tpublic void reset(boolean override) {\n\t\tstate.reset(override);\n\t}\n') + text = replace_method(text, '\tpublic void resetVotePartyCount()', + '\tpublic void resetVotePartyCount() {\n\t\tstate.resetUserCounts();\n\t}\n') + text = replace_method(text, '\tpublic void setTotalVotes(int value)', + '\tpublic void setTotalVotes(int value) {\n\t\tstate.setTotalVotes(value);\n\t}\n') + text = replace_method(text, '\tpublic void setVotedUsers(List value)', + '\tpublic void setVotedUsers(List value) {\n\t\tstate.setVotedUsers(value);\n\t}\n') + + path.write_text(text) + PY + - name: Build + run: mvn -B -f VotingPlugin/pom.xml package + - name: Commit VoteParty refactor + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A VotingPlugin + git commit -m 'Split VoteParty state and reward handling' + git push origin HEAD:refactor/voteparty-components + - name: Remove temporary workflow + run: | + git pull --rebase origin refactor/voteparty-components + git rm .github/workflows/refactor-voteparty-components.yml + git commit -m 'Remove temporary VoteParty refactor workflow' + git push origin HEAD:refactor/voteparty-components From a895b57bb29c8ff6e3ea9f13a3128d57d98b832e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:17:01 +0000 Subject: [PATCH 62/71] Split VoteParty state and reward handling --- .../specialrewards/voteparty/VoteParty.java | 840 ++++++++---------- 1 file changed, 365 insertions(+), 475 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VoteParty.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VoteParty.java index 2177fb8a99..32ce597d22 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VoteParty.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VoteParty.java @@ -1,475 +1,365 @@ - -package com.bencodez.votingplugin.specialrewards.voteparty; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; - -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -import com.bencodez.advancedcore.api.messages.PlaceholderUtils; -import com.bencodez.advancedcore.api.misc.MiscUtils; -import com.bencodez.advancedcore.api.rewards.RewardBuilder; -import com.bencodez.advancedcore.api.time.events.DayChangeEvent; -import com.bencodez.advancedcore.api.time.events.MonthChangeEvent; -import com.bencodez.advancedcore.api.time.events.WeekChangeEvent; -import com.bencodez.advancedcore.api.user.UserDataFetchMode; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.sql.DataType; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.events.VotePartyEvent; -import com.bencodez.votingplugin.user.VotingPluginUser; - -// TODO: Auto-generated Javadoc -/** - * The Class VoteParty. - */ -public class VoteParty implements Listener { - - private VotingPluginMain plugin; - - /** - * Constructs a new VoteParty. - * - * @param plugin the main plugin instance - */ - public VoteParty(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * Adds a vote total for the user. - * - * @param user the voting plugin user - */ - public void addTotal(VotingPluginUser user) { - setTotalVotes(getTotalVotes() + 1); - user.setVotePartyVotes(user.getVotePartyVotes() + 1); - plugin.getPlaceholders().onVotePartyUpdate(); - } - - /** - * Adds the vote player. - * - * @param user the user - */ - public void addVotePlayer(VotingPluginUser user) { - String uuid = user.getUUID(); - List voted = getVotedUsers(); - if (voted == null) { - voted = new ArrayList<>(); - } - if (!voted.contains(uuid)) { - voted.add(uuid); - setVotedUsers(voted); - } - } - - /** - * Checks if vote party requirements are met and triggers if appropriate. - * - * @param user the voting plugin user - * @param forceBungee whether to force Bungee processing - */ - public void check(VotingPluginUser user, boolean forceBungee) { - if (getTotalVotes() < getVotesRequired()) { - plugin.extraDebug("Not enough votes for vote party: " + getTotalVotes() + " / " + getVotesRequired()); - return; - } - - if (plugin.getSpecialRewardsConfig().isVotePartyOnlyOncePerDay() - && plugin.getServerData().isLastVotePartySameDay()) { - plugin.extraDebug("Already had vote party today"); - return; - } - if (plugin.getSpecialRewardsConfig().isVotePartyOnlyOncePerWeek() - && plugin.getServerData().isLastVotePartySameWeek()) { - plugin.extraDebug("Already had vote party this week"); - return; - } - if (plugin.getSpecialRewardsConfig().isVotePartyResetCount()) { - setTotalVotes(getTotalVotes() - getVotesRequired()); - } - - VotePartyEvent event = new VotePartyEvent(); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - - giveRewards(user, forceBungee); - - if (plugin.getSpecialRewardsConfig().getVotePartyIncreaseVotesRequired() > 0) { - plugin.getServerData().setVotePartyExtraRequired(plugin.getServerData().getVotePartyExtraRequired() - + plugin.getSpecialRewardsConfig().getVotePartyIncreaseVotesRequired()); - } - - plugin.getServerData().updateLastVoteParty(); - - if (plugin.getSpecialRewardsConfig().isVotePartyOnlyOncePerWeek()) { - plugin.getServerData().updateLastVotePartyWeek(); - } - - } - - /** - * Checks and sends vote reminders if requirements are met. - * - * @param user the voting plugin user - */ - public void checkVoteReminder(VotingPluginUser user) { - if (!user.isVanished()) { - int neededVotes = getNeededVotes(); - - for (Integer num1 : plugin.getSpecialRewardsConfig().getVotePartyVoteReminderAtVotes()) { - int num = num1.intValue(); - if (neededVotes == num) { - String broadcastMessage = plugin.getSpecialRewardsConfig().getVotePartyVoteReminderBroadcast(); - HashMap placeholders = new HashMap<>(); - placeholders.put("player", user.getPlayerName()); - placeholders.put("votesrequired", "" + neededVotes); - MiscUtils.getInstance() - .broadcast(PlaceholderUtils.replacePlaceHolder(broadcastMessage, placeholders)); - - MiscUtils.getInstance().executeConsoleCommands( - plugin.getSpecialRewardsConfig().getVotePartyVoteReminderCommands(), placeholders, false); - } - } - } - - } - - /** - * Command vote party. - * - * @param sender the sender - */ - public void commandVoteParty(CommandSender sender) { - if (plugin.getSpecialRewardsConfig().isVotePartyEnabled()) { - ArrayList msg = plugin.getConfigFile().getFormatCommandsVoteParty(); - int votesRequired = getVotesRequired(); - int votes = getTotalVotes(); - int neededVotes = votesRequired - votes; - HashMap placeholders = new HashMap<>(); - placeholders.put("votesrequired", "" + votesRequired); - placeholders.put("neededvotes", "" + neededVotes); - placeholders.put("votes", "" + votes); - msg = ArrayUtils.colorize(PlaceholderUtils.replacePlaceHolder(msg, placeholders)); - if (sender instanceof Player) { - Player p = (Player) sender; - sender.sendMessage(ArrayUtils.convert(PlaceholderUtils.replacePlaceHolders(msg, p))); - } else { - sender.sendMessage(ArrayUtils.convert(msg)); - } - } else { - sender.sendMessage(MessageAPI.colorize("&cVoteParty not enabled")); - } - } - - /** - * Gets the needed votes. - * - * @return the needed votes - */ - public int getNeededVotes() { - int votesRequired = getVotesRequired(); - int votes = getTotalVotes(); - int neededVotes = votesRequired - votes; - return neededVotes; - } - - /** - * Gets a random player name from voted users. - * - * @return random player name or "No Player" if none available - */ - public String getRandomPlayerName() { - ArrayList allPlayers = new ArrayList<>(); - for (Player players : Bukkit.getOnlinePlayers()) { - allPlayers.add(players.getName()); - } - if (allPlayers.size() == 0) { - return "No Player"; - } - int random = new Random().nextInt(allPlayers.size()); - return allPlayers.get(random); - } - - /** - * Gets the total votes. - * - * @return the total votes - */ - public int getTotalVotes() { - return plugin.getServerData().getData().getInt("VoteParty.Total"); - } - - /** - * Gets the voted users. - * - * @return the voted users - */ - public List getVotedUsers() { - List list = plugin.getServerData().getData().getStringList("VoteParty.Voted"); - if (list != null) { - return list; - } - return new ArrayList<>(); - } - - /** - * Gets the number of votes required for the vote party. - * - * @return votes required including extra requirements - */ - public int getVotesRequired() { - int required = plugin.getSpecialRewardsConfig().getVotePartyVotesRequired(); - int extra = plugin.getServerData().getVotePartyExtraRequired(); - if (extra > 0) { - return required + extra; - } - return required; - } - - /** - * Gives vote party reward to a user. - * - * @param user the voting plugin user - * @param useBungee whether to use Bungee processing - */ - public void giveReward(VotingPluginUser user, boolean useBungee) { - if (plugin.getSpecialRewardsConfig().getVotePartyUserVotesRequired() > 0) { - if (user.getVotePartyVotes() < plugin.getSpecialRewardsConfig().getVotePartyUserVotesRequired()) { - return; - } - } - giveReward(user, user.isOnline(), useBungee); - } - - /** - * Gives vote party reward to a user with online status. - * - * @param user the voting plugin user - * @param online whether the user is online - * @param useBungee whether to use Bungee processing - */ - public void giveReward(VotingPluginUser user, boolean online, boolean useBungee) { - new RewardBuilder(plugin.getSpecialRewardsConfig().getData(), - plugin.getSpecialRewardsConfig().getVotePartyRewardsPath()).setOnline(online) - .withPlaceHolder("VotesRequired", "" + plugin.getSpecialRewardsConfig().getVotePartyVotesRequired()) - .withPlaceHolder("FirstVotePartyToday", "" + !plugin.getServerData().isLastVotePartySameDay()) - .setServer(useBungee).send(user); - } - - /** - * Gives rewards to all eligible players for the vote party. - * - * @param orgUser the original voting user who triggered the party - * @param forceBungee whether to force Bungee processing - */ - public void giveRewards(VotingPluginUser orgUser, boolean forceBungee) { - MiscUtils.getInstance().broadcast(plugin.getSpecialRewardsConfig().getVotePartyBroadcast()); - - String player = getRandomPlayerName(); - for (final String cmd : plugin.getSpecialRewardsConfig().getVotePartyGlobalCommands()) { - plugin.getBukkitScheduler().runTask(plugin, new Runnable() { - - @Override - public void run() { - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), - PlaceholderUtils.replacePlaceHolder(cmd, "randomonlineplayer", player)); - } - - }); - } - - final ArrayList list = plugin.getSpecialRewardsConfig().getVotePartyGlobalRandomCommand(); - if (list.size() > 0) { - plugin.getBukkitScheduler().runTask(plugin, new Runnable() { - - @Override - public void run() { - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), PlaceholderUtils.replacePlaceHolder( - list.get(ThreadLocalRandom.current().nextInt(list.size())), "randomonlineplayer", player)); - } - - }); - } - - if (plugin.getSpecialRewardsConfig().isVotePartyGiveAllPlayers()) { - plugin.debug("Trying to give all players vote party"); - - ArrayList alreadyGotten = new ArrayList<>(); - for (Player p : Bukkit.getOnlinePlayers()) { - VotingPluginUser user; - if (orgUser != null && orgUser.getJavaUUID().equals(p.getUniqueId())) { - user = orgUser; - } else { - user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); - user.userDataFetechMode(UserDataFetchMode.NO_CACHE); - } - - if (!plugin.getSpecialRewardsConfig().isVotePartyGiveOnlinePlayersOnly() || user.isOnline()) { - giveReward(user, forceBungee); - } - alreadyGotten.add(p.getUniqueId().toString()); - } - for (String uuid : plugin.getVotingPluginUserManager().getAllUUIDs()) { - if (!alreadyGotten.contains(uuid)) { - VotingPluginUser user; - if (orgUser != null && orgUser.getJavaUUID().toString().equals(uuid)) { - user = orgUser; - } else { - user = plugin.getVotingPluginUserManager().getVotingPluginUser(UUID.fromString(uuid)); - user.userDataFetechMode(UserDataFetchMode.NO_CACHE); - } - - if (!plugin.getSpecialRewardsConfig().isVotePartyGiveOnlinePlayersOnly() || user.isOnline()) { - giveReward(user, forceBungee); - } - } - } - } else { - plugin.debug("Trying to give all voted players vote party"); - plugin.debug(ArrayUtils.makeStringList(getVotedUsers())); - for (String uuid : - - getVotedUsers()) { - VotingPluginUser user; - if (orgUser != null && orgUser.getJavaUUID().toString().equals(uuid)) { - user = orgUser; - } else { - user = plugin.getVotingPluginUserManager().getVotingPluginUser(UUID.fromString(uuid)); - user.userDataFetechMode(UserDataFetchMode.NO_CACHE); - } - if (!plugin.getSpecialRewardsConfig().isVotePartyGiveOnlinePlayersOnly() || user.isOnline()) { - giveReward(user, forceBungee); - } - - } - } - - reset(false); - } - - /** - * Handles day change events to reset vote party if configured. - * - * @param event the day change event - */ - @EventHandler - public void onDayChange(DayChangeEvent event) { - if (plugin.getSpecialRewardsConfig().isVotePartyResetEachDay()) { - reset(true); - } - } - - /** - * Handles month change events to reset vote party if configured. - * - * @param event the month change event - */ - @EventHandler - public void onMonthChange(MonthChangeEvent event) { - if (plugin.getSpecialRewardsConfig().isVotePartyResetMonthly()) { - reset(true); - } - - if (plugin.getSpecialRewardsConfig().isVotePartyResetExtraVotesMonthly()) { - plugin.getServerData().setVotePartyExtraRequired(0); - } - } - - /** - * Handles week change events to reset vote party if configured. - * - * @param event the week change event - */ - @EventHandler - public void onWeekChange(WeekChangeEvent event) { - if (plugin.getSpecialRewardsConfig().isVotePartyResetWeekly()) { - reset(true); - } - - if (plugin.getSpecialRewardsConfig().isVotePartyResetExtraVotesWeekly()) { - plugin.getServerData().setVotePartyExtraRequired(0); - } - } - - /** - * Registers this class as an event listener. - */ - public void register() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - /** - * Resets the vote party state. - * - * @param override whether to override total votes to zero - */ - public void reset(boolean override) { - if (override) { - setTotalVotes(0); - } - setVotedUsers(new ArrayList<>()); - resetVotePartyCount(); - - } - - /** - * Resets the vote party count for all users. - */ - public void resetVotePartyCount() { - plugin.getUserManager().removeAllKeyValues("VotePartyVotes", DataType.INTEGER); - } - - /** - * Sets the total votes. - * - * @param value the new total votes - */ - public void setTotalVotes(int value) { - plugin.getServerData().getData().set("VoteParty.Total", value); - plugin.getServerData().saveData(); - } - - /** - * Sets the voted users. - * - * @param value the new voted users - */ - public void setVotedUsers(List value) { - plugin.getServerData().getData().set("VoteParty.Voted", value); - plugin.getServerData().saveData(); - } - - /** - * Processes a vote for the vote party system. - * - * @param user the voting plugin user - * @param realVote whether this is a real vote - * @param forceBungee whether to force Bungee processing - */ - public synchronized void vote(VotingPluginUser user, boolean realVote, boolean forceBungee) { - if (plugin.getSpecialRewardsConfig().isVotePartyEnabled()) { - if (plugin.getSpecialRewardsConfig().isVotePartyCountFakeVotes() || realVote) { - if (plugin.getSpecialRewardsConfig().isVotePartyCountOfflineVotes() || user.isOnline()) { - addTotal(user); - addVotePlayer(user); - check(user, forceBungee); - checkVoteReminder(user); - } - } - } - } - -} + +package com.bencodez.votingplugin.specialrewards.voteparty; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.misc.MiscUtils; +import com.bencodez.advancedcore.api.time.events.DayChangeEvent; +import com.bencodez.advancedcore.api.time.events.MonthChangeEvent; +import com.bencodez.advancedcore.api.time.events.WeekChangeEvent; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.events.VotePartyEvent; +import com.bencodez.votingplugin.user.VotingPluginUser; + +/** Coordinates VoteParty voting, reminders, commands, and reset events. */ +public class VoteParty implements Listener { + + private VotingPluginMain plugin; + private final VotePartyState state; + private final VotePartyRewardHandler rewardHandler; + + /** + * Constructs a new VoteParty. + * + * @param plugin the main plugin instance + */ + public VoteParty(VotingPluginMain plugin) { + this.plugin = plugin; + this.state = new VotePartyState(plugin); + this.rewardHandler = new VotePartyRewardHandler(plugin, state); + } + + /** + * Adds a vote total for the user. + * + * @param user the voting plugin user + */ + public void addTotal(VotingPluginUser user) { + state.setTotalVotes(state.getTotalVotes() + 1); + user.setVotePartyVotes(user.getVotePartyVotes() + 1); + plugin.getPlaceholders().onVotePartyUpdate(); + } + + + /** + * Adds the vote player. + * + * @param user the user + */ + public void addVotePlayer(VotingPluginUser user) { + String uuid = user.getUUID(); + List voted = state.getVotedUsers(); + if (!voted.contains(uuid)) { + voted.add(uuid); + state.setVotedUsers(voted); + } + } + + + /** + * Checks if vote party requirements are met and triggers if appropriate. + * + * @param user the voting plugin user + * @param forceBungee whether to force Bungee processing + */ + public void check(VotingPluginUser user, boolean forceBungee) { + if (getTotalVotes() < getVotesRequired()) { + plugin.extraDebug("Not enough votes for vote party: " + getTotalVotes() + " / " + getVotesRequired()); + return; + } + + if (plugin.getSpecialRewardsConfig().isVotePartyOnlyOncePerDay() + && plugin.getServerData().isLastVotePartySameDay()) { + plugin.extraDebug("Already had vote party today"); + return; + } + if (plugin.getSpecialRewardsConfig().isVotePartyOnlyOncePerWeek() + && plugin.getServerData().isLastVotePartySameWeek()) { + plugin.extraDebug("Already had vote party this week"); + return; + } + if (plugin.getSpecialRewardsConfig().isVotePartyResetCount()) { + setTotalVotes(getTotalVotes() - getVotesRequired()); + } + + VotePartyEvent event = new VotePartyEvent(); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + + giveRewards(user, forceBungee); + + if (plugin.getSpecialRewardsConfig().getVotePartyIncreaseVotesRequired() > 0) { + plugin.getServerData().setVotePartyExtraRequired(plugin.getServerData().getVotePartyExtraRequired() + + plugin.getSpecialRewardsConfig().getVotePartyIncreaseVotesRequired()); + } + + plugin.getServerData().updateLastVoteParty(); + + if (plugin.getSpecialRewardsConfig().isVotePartyOnlyOncePerWeek()) { + plugin.getServerData().updateLastVotePartyWeek(); + } + + } + + /** + * Checks and sends vote reminders if requirements are met. + * + * @param user the voting plugin user + */ + public void checkVoteReminder(VotingPluginUser user) { + if (!user.isVanished()) { + int neededVotes = getNeededVotes(); + + for (Integer num1 : plugin.getSpecialRewardsConfig().getVotePartyVoteReminderAtVotes()) { + int num = num1.intValue(); + if (neededVotes == num) { + String broadcastMessage = plugin.getSpecialRewardsConfig().getVotePartyVoteReminderBroadcast(); + HashMap placeholders = new HashMap<>(); + placeholders.put("player", user.getPlayerName()); + placeholders.put("votesrequired", "" + neededVotes); + MiscUtils.getInstance() + .broadcast(PlaceholderUtils.replacePlaceHolder(broadcastMessage, placeholders)); + + MiscUtils.getInstance().executeConsoleCommands( + plugin.getSpecialRewardsConfig().getVotePartyVoteReminderCommands(), placeholders, false); + } + } + } + + } + + /** + * Command vote party. + * + * @param sender the sender + */ + public void commandVoteParty(CommandSender sender) { + if (plugin.getSpecialRewardsConfig().isVotePartyEnabled()) { + ArrayList msg = plugin.getConfigFile().getFormatCommandsVoteParty(); + int votesRequired = getVotesRequired(); + int votes = getTotalVotes(); + int neededVotes = votesRequired - votes; + HashMap placeholders = new HashMap<>(); + placeholders.put("votesrequired", "" + votesRequired); + placeholders.put("neededvotes", "" + neededVotes); + placeholders.put("votes", "" + votes); + msg = ArrayUtils.colorize(PlaceholderUtils.replacePlaceHolder(msg, placeholders)); + if (sender instanceof Player) { + Player p = (Player) sender; + sender.sendMessage(ArrayUtils.convert(PlaceholderUtils.replacePlaceHolders(msg, p))); + } else { + sender.sendMessage(ArrayUtils.convert(msg)); + } + } else { + sender.sendMessage(MessageAPI.colorize("&cVoteParty not enabled")); + } + } + + /** + * Gets the needed votes. + * + * @return the needed votes + */ + public int getNeededVotes() { + return state.getNeededVotes(); + } + + + /** + * Gets a random player name from voted users. + * + * @return random player name or "No Player" if none available + */ + public String getRandomPlayerName() { + return rewardHandler.randomOnlinePlayerName(); + } + + + /** + * Gets the total votes. + * + * @return the total votes + */ + public int getTotalVotes() { + return state.getTotalVotes(); + } + + + /** + * Gets the voted users. + * + * @return the voted users + */ + public List getVotedUsers() { + return state.getVotedUsers(); + } + + + /** + * Gets the number of votes required for the vote party. + * + * @return votes required including extra requirements + */ + public int getVotesRequired() { + return state.getVotesRequired(); + } + + + /** + * Gives vote party reward to a user. + * + * @param user the voting plugin user + * @param useBungee whether to use Bungee processing + */ + public void giveReward(VotingPluginUser user, boolean useBungee) { + rewardHandler.giveReward(user, useBungee); + } + + + /** + * Gives vote party reward to a user with online status. + * + * @param user the voting plugin user + * @param online whether the user is online + * @param useBungee whether to use Bungee processing + */ + public void giveReward(VotingPluginUser user, boolean online, boolean useBungee) { + rewardHandler.giveReward(user, online, useBungee); + } + + + /** + * Gives rewards to all eligible players for the vote party. + * + * @param orgUser the original voting user who triggered the party + * @param forceBungee whether to force Bungee processing + */ + public void giveRewards(VotingPluginUser orgUser, boolean forceBungee) { + rewardHandler.giveRewards(orgUser, forceBungee); + reset(false); + } + + + /** + * Handles day change events to reset vote party if configured. + * + * @param event the day change event + */ + @EventHandler + public void onDayChange(DayChangeEvent event) { + if (plugin.getSpecialRewardsConfig().isVotePartyResetEachDay()) { + reset(true); + } + } + + /** + * Handles month change events to reset vote party if configured. + * + * @param event the month change event + */ + @EventHandler + public void onMonthChange(MonthChangeEvent event) { + if (plugin.getSpecialRewardsConfig().isVotePartyResetMonthly()) { + reset(true); + } + + if (plugin.getSpecialRewardsConfig().isVotePartyResetExtraVotesMonthly()) { + plugin.getServerData().setVotePartyExtraRequired(0); + } + } + + /** + * Handles week change events to reset vote party if configured. + * + * @param event the week change event + */ + @EventHandler + public void onWeekChange(WeekChangeEvent event) { + if (plugin.getSpecialRewardsConfig().isVotePartyResetWeekly()) { + reset(true); + } + + if (plugin.getSpecialRewardsConfig().isVotePartyResetExtraVotesWeekly()) { + plugin.getServerData().setVotePartyExtraRequired(0); + } + } + + /** + * Registers this class as an event listener. + */ + public void register() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + /** + * Resets the vote party state. + * + * @param override whether to override total votes to zero + */ + public void reset(boolean override) { + state.reset(override); + } + + + /** + * Resets the vote party count for all users. + */ + public void resetVotePartyCount() { + state.resetUserCounts(); + } + + + /** + * Sets the total votes. + * + * @param value the new total votes + */ + public void setTotalVotes(int value) { + state.setTotalVotes(value); + } + + + /** + * Sets the voted users. + * + * @param value the new voted users + */ + public void setVotedUsers(List value) { + state.setVotedUsers(value); + } + + + /** + * Processes a vote for the vote party system. + * + * @param user the voting plugin user + * @param realVote whether this is a real vote + * @param forceBungee whether to force Bungee processing + */ + public synchronized void vote(VotingPluginUser user, boolean realVote, boolean forceBungee) { + if (plugin.getSpecialRewardsConfig().isVotePartyEnabled()) { + if (plugin.getSpecialRewardsConfig().isVotePartyCountFakeVotes() || realVote) { + if (plugin.getSpecialRewardsConfig().isVotePartyCountOfflineVotes() || user.isOnline()) { + addTotal(user); + addVotePlayer(user); + check(user, forceBungee); + checkVoteReminder(user); + } + } + } + } + +} From 9f223b8880ff22a9562aad74883da749d92d1090 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:17:02 +0000 Subject: [PATCH 63/71] Remove temporary VoteParty refactor workflow --- .../refactor-voteparty-components.yml | 108 ------------------ 1 file changed, 108 deletions(-) delete mode 100644 .github/workflows/refactor-voteparty-components.yml diff --git a/.github/workflows/refactor-voteparty-components.yml b/.github/workflows/refactor-voteparty-components.yml deleted file mode 100644 index 06f5ad9ce0..0000000000 --- a/.github/workflows/refactor-voteparty-components.yml +++ /dev/null @@ -1,108 +0,0 @@ -name: Split VoteParty components - -on: - pull_request: - branches: - - master - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - refactor: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: refactor/voteparty-components - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '21' - cache: maven - - name: Delegate VoteParty state and rewards - run: | - python - <<'PY' - from pathlib import Path - - def replace_method(text, marker, replacement): - start = text.find(marker) - if start < 0: - raise SystemExit('method marker not found: ' + marker) - brace = text.find('{', start) - depth = 0 - for pos in range(brace, len(text)): - if text[pos] == '{': depth += 1 - elif text[pos] == '}': - depth -= 1 - if depth == 0: - return text[:start] + replacement + text[pos + 1:] - raise SystemExit('unterminated method: ' + marker) - - path = Path('VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/voteparty/VoteParty.java') - text = path.read_text() - - # Remove generated boilerplate and imports now owned by reward/state components. - text = text.replace('// TODO: Auto-generated Javadoc\n/**\n * The Class VoteParty.\n */\n', '/** Coordinates VoteParty voting, reminders, commands, and reset events. */\n') - for line in [ - 'import java.util.Random;\n', 'import java.util.UUID;\n', - 'import java.util.concurrent.ThreadLocalRandom;\n', - 'import com.bencodez.advancedcore.api.rewards.RewardBuilder;\n', - 'import com.bencodez.advancedcore.api.user.UserDataFetchMode;\n', - 'import com.bencodez.simpleapi.sql.DataType;\n', - ]: - text = text.replace(line, '') - - field = '\tprivate VotingPluginMain plugin;\n' - text = text.replace(field, field + '\tprivate final VotePartyState state;\n\tprivate final VotePartyRewardHandler rewardHandler;\n', 1) - ctor = '\t\tthis.plugin = plugin;\n' - text = text.replace(ctor, ctor + '\t\tthis.state = new VotePartyState(plugin);\n\t\tthis.rewardHandler = new VotePartyRewardHandler(plugin, state);\n', 1) - - text = replace_method(text, '\tpublic void addTotal(VotingPluginUser user)', - '\tpublic void addTotal(VotingPluginUser user) {\n\t\tstate.setTotalVotes(state.getTotalVotes() + 1);\n\t\tuser.setVotePartyVotes(user.getVotePartyVotes() + 1);\n\t\tplugin.getPlaceholders().onVotePartyUpdate();\n\t}\n') - text = replace_method(text, '\tpublic void addVotePlayer(VotingPluginUser user)', - '\tpublic void addVotePlayer(VotingPluginUser user) {\n\t\tString uuid = user.getUUID();\n\t\tList voted = state.getVotedUsers();\n\t\tif (!voted.contains(uuid)) {\n\t\t\tvoted.add(uuid);\n\t\t\tstate.setVotedUsers(voted);\n\t\t}\n\t}\n') - text = replace_method(text, '\tpublic int getNeededVotes()', - '\tpublic int getNeededVotes() {\n\t\treturn state.getNeededVotes();\n\t}\n') - text = replace_method(text, '\tpublic String getRandomPlayerName()', - '\tpublic String getRandomPlayerName() {\n\t\treturn rewardHandler.randomOnlinePlayerName();\n\t}\n') - text = replace_method(text, '\tpublic int getTotalVotes()', - '\tpublic int getTotalVotes() {\n\t\treturn state.getTotalVotes();\n\t}\n') - text = replace_method(text, '\tpublic List getVotedUsers()', - '\tpublic List getVotedUsers() {\n\t\treturn state.getVotedUsers();\n\t}\n') - text = replace_method(text, '\tpublic int getVotesRequired()', - '\tpublic int getVotesRequired() {\n\t\treturn state.getVotesRequired();\n\t}\n') - text = replace_method(text, '\tpublic void giveReward(VotingPluginUser user, boolean useBungee)', - '\tpublic void giveReward(VotingPluginUser user, boolean useBungee) {\n\t\trewardHandler.giveReward(user, useBungee);\n\t}\n') - text = replace_method(text, '\tpublic void giveReward(VotingPluginUser user, boolean online, boolean useBungee)', - '\tpublic void giveReward(VotingPluginUser user, boolean online, boolean useBungee) {\n\t\trewardHandler.giveReward(user, online, useBungee);\n\t}\n') - text = replace_method(text, '\tpublic void giveRewards(VotingPluginUser orgUser, boolean forceBungee)', - '\tpublic void giveRewards(VotingPluginUser orgUser, boolean forceBungee) {\n\t\trewardHandler.giveRewards(orgUser, forceBungee);\n\t\treset(false);\n\t}\n') - text = replace_method(text, '\tpublic void reset(boolean override)', - '\tpublic void reset(boolean override) {\n\t\tstate.reset(override);\n\t}\n') - text = replace_method(text, '\tpublic void resetVotePartyCount()', - '\tpublic void resetVotePartyCount() {\n\t\tstate.resetUserCounts();\n\t}\n') - text = replace_method(text, '\tpublic void setTotalVotes(int value)', - '\tpublic void setTotalVotes(int value) {\n\t\tstate.setTotalVotes(value);\n\t}\n') - text = replace_method(text, '\tpublic void setVotedUsers(List value)', - '\tpublic void setVotedUsers(List value) {\n\t\tstate.setVotedUsers(value);\n\t}\n') - - path.write_text(text) - PY - - name: Build - run: mvn -B -f VotingPlugin/pom.xml package - - name: Commit VoteParty refactor - run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A VotingPlugin - git commit -m 'Split VoteParty state and reward handling' - git push origin HEAD:refactor/voteparty-components - - name: Remove temporary workflow - run: | - git pull --rebase origin refactor/voteparty-components - git rm .github/workflows/refactor-voteparty-components.yml - git commit -m 'Remove temporary VoteParty refactor workflow' - git push origin HEAD:refactor/voteparty-components From e9224eb9d357611efe46291412c6fc82c5906e89 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:18:00 -0600 Subject: [PATCH 64/71] Add generated comment cleanup workflow --- .../cleanup-generated-comments-round2.yml | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .github/workflows/cleanup-generated-comments-round2.yml diff --git a/.github/workflows/cleanup-generated-comments-round2.yml b/.github/workflows/cleanup-generated-comments-round2.yml new file mode 100644 index 0000000000..7015f9723f --- /dev/null +++ b/.github/workflows/cleanup-generated-comments-round2.yml @@ -0,0 +1,67 @@ +name: Clean generated comments round 2 + +on: + pull_request: + branches: + - master + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + cleanup: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: cleanup/generated-comments-round2 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + - name: Remove generated comment boilerplate + run: | + python - <<'PY' + from pathlib import Path + import re + + root = Path('VotingPlugin/src/main/java') + changed = [] + for path in root.rglob('*.java'): + text = path.read_text() + original = text + text = re.sub(r'(?m)^\s*// TODO: Auto-generated Javadoc\s*\n', '', text) + text = re.sub(r'(?ms)^\s*/\*\*\s*\n\s*\* The Class [^\n]+\.\s*\n\s*\*/\s*\n', '', text) + text = re.sub(r'(?ms)^\s*/\*\s*\n\s*\* \(non-Javadoc\)\s*\n(?:\s*\*.*\n)*?\s*\*/\s*\n', '', text) + if text != original: + path.write_text(text) + changed.append(str(path)) + + if not changed: + raise SystemExit('No generated comment boilerplate found') + print('\n'.join(changed)) + PY + - name: Verify generated markers are gone + run: | + if grep -R --line-number --include='*.java' 'TODO: Auto-generated Javadoc\|(non-Javadoc)\|The Class ' VotingPlugin/src/main/java; then + echo 'Generated comment markers remain' + exit 1 + fi + - name: Build + run: mvn -B -f VotingPlugin/pom.xml package + - name: Commit cleanup + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A VotingPlugin + git commit -m 'Remove remaining generated comment boilerplate' + git push origin HEAD:cleanup/generated-comments-round2 + - name: Remove temporary workflow + run: | + git pull --rebase origin cleanup/generated-comments-round2 + git rm .github/workflows/cleanup-generated-comments-round2.yml + git commit -m 'Remove temporary comment cleanup workflow' + git push origin HEAD:cleanup/generated-comments-round2 From 6f0284e1005467444ee454efe555099f5516d56e Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:19:12 -0600 Subject: [PATCH 65/71] Keep descriptive user Javadoc --- .github/workflows/cleanup-generated-comments-round2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cleanup-generated-comments-round2.yml b/.github/workflows/cleanup-generated-comments-round2.yml index 7015f9723f..5c61a0ad3b 100644 --- a/.github/workflows/cleanup-generated-comments-round2.yml +++ b/.github/workflows/cleanup-generated-comments-round2.yml @@ -46,7 +46,7 @@ jobs: PY - name: Verify generated markers are gone run: | - if grep -R --line-number --include='*.java' 'TODO: Auto-generated Javadoc\|(non-Javadoc)\|The Class ' VotingPlugin/src/main/java; then + if grep -R --line-number --include='*.java' 'TODO: Auto-generated Javadoc\|(non-Javadoc)' VotingPlugin/src/main/java; then echo 'Generated comment markers remain' exit 1 fi From bdb90454d392e4e8183f99545fb0e4b316e61e74 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:20:36 -0600 Subject: [PATCH 66/71] Limit generated comment removal to comment blocks --- .github/workflows/cleanup-generated-comments-round2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cleanup-generated-comments-round2.yml b/.github/workflows/cleanup-generated-comments-round2.yml index 5c61a0ad3b..5513c778c2 100644 --- a/.github/workflows/cleanup-generated-comments-round2.yml +++ b/.github/workflows/cleanup-generated-comments-round2.yml @@ -35,7 +35,7 @@ jobs: original = text text = re.sub(r'(?m)^\s*// TODO: Auto-generated Javadoc\s*\n', '', text) text = re.sub(r'(?ms)^\s*/\*\*\s*\n\s*\* The Class [^\n]+\.\s*\n\s*\*/\s*\n', '', text) - text = re.sub(r'(?ms)^\s*/\*\s*\n\s*\* \(non-Javadoc\)\s*\n(?:\s*\*.*\n)*?\s*\*/\s*\n', '', text) + text = re.sub(r'(?ms)^\s*/\*\s*\n\s*\* \(non-Javadoc\).*?\*/\s*\n', '', text) if text != original: path.write_text(text) changed.append(str(path)) From 057c1c76995930df809bae09890879fef7368477 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:21:18 +0000 Subject: [PATCH 67/71] Remove remaining generated comment boilerplate --- .../votingplugin/VotingPluginMain.java | 4 - .../votingplugin/commands/CommandLoader.java | 5 - .../tabcompleter/AdminVoteTabCompleter.java | 12 - .../tabcompleter/AliasesTabCompleter.java | 12 - .../bencodez/votingplugin/config/Config.java | 1897 ++++++------ .../votingplugin/config/ConfigVoteSites.java | 1353 +++++---- .../votingplugin/data/ServerData.java | 1115 ++++--- .../events/PlayerPostVoteEvent.java | 235 +- .../events/PlayerReceivePointsEvent.java | 123 +- .../events/PlayerSpecialRewardEvent.java | 131 +- .../events/PlayerVoteCoolDownEndEvent.java | 103 +- .../votingplugin/events/PlayerVoteEvent.java | 215 +- .../PlayerVoteSiteCoolDownEndEvent.java | 117 +- .../votingplugin/events/VotePartyEvent.java | 85 +- .../votingplugin/listeners/BlockBreak.java | 109 +- .../listeners/PlayerInteract.java | 173 +- .../listeners/PlayerJoinEvent.java | 254 +- .../listeners/PlayerVoteListener.java | 579 ++-- .../votingplugin/listeners/SignChange.java | 129 +- .../votingplugin/listeners/VotiferEvent.java | 268 +- .../listeners/VotingPluginUpdateEvent.java | 79 +- .../placeholders/MVdWPlaceholders.java | 5 - .../placeholders/PlaceHolders.java | 2645 ++++++++--------- .../votingplugin/signs/SignHandler.java | 5 - .../bencodez/votingplugin/signs/Signs.java | 179 +- .../specialrewards/SpecialRewards.java | 237 +- .../votingplugin/updater/CheckUpdate.java | 199 +- .../votingplugin/votesites/VoteSite.java | 408 ++- 28 files changed, 5242 insertions(+), 5434 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java index 6f824dc868..dcc163bcb4 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java @@ -129,10 +129,6 @@ import lombok.Getter; import lombok.Setter; - -/** - * The Class Main. - */ public class VotingPluginMain extends AdvancedCorePlugin { @Getter diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/CommandLoader.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/CommandLoader.java index fc742f704b..fb4b46ec45 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/CommandLoader.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/CommandLoader.java @@ -90,11 +90,6 @@ import com.bencodez.votingplugin.topvoter.TopVoter; import com.bencodez.votingplugin.user.VotingPluginUser; import com.bencodez.votingplugin.votesites.VoteSite; - -// TODO: Auto-generated Javadoc -/** - * The Class CommandLoader. - */ public class CommandLoader { private String adminPerm = "VotingPlugin.Admin"; diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AdminVoteTabCompleter.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AdminVoteTabCompleter.java index 5e3420176f..341ec79bbc 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AdminVoteTabCompleter.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AdminVoteTabCompleter.java @@ -13,22 +13,10 @@ import com.bencodez.advancedcore.api.command.AdvancedCoreTabCompleteHandler; import com.bencodez.simpleapi.messages.MessageAPI; import com.bencodez.votingplugin.VotingPluginMain; - -/** - * The Class AdminVoteTabCompleter. - */ public class AdminVoteTabCompleter implements TabCompleter { /** The plugin. */ VotingPluginMain plugin = VotingPluginMain.plugin; - - /* - * (non-Javadoc) - * - * @see org.bukkit.command.TabCompleter#onTabComplete(org.bukkit.command. - * CommandSender, org.bukkit.command.Command, java.lang.String, - * java.lang.String[]) - */ @Override public List onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) { diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AliasesTabCompleter.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AliasesTabCompleter.java index 5b7f55c01c..9e167575c4 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AliasesTabCompleter.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AliasesTabCompleter.java @@ -16,10 +16,6 @@ import com.bencodez.simpleapi.command.TabCompleteHandler; import com.bencodez.simpleapi.messages.MessageAPI; import com.bencodez.votingplugin.VotingPluginMain; - -/** - * The Class AliasesTabCompleter. - */ public class AliasesTabCompleter implements TabCompleter { private boolean adminCommand; @@ -29,14 +25,6 @@ public class AliasesTabCompleter implements TabCompleter { /** The plugin. */ VotingPluginMain plugin = VotingPluginMain.plugin; - - /* - * (non-Javadoc) - * - * @see org.bukkit.command.TabCompleter#onTabComplete(org.bukkit.command. - * CommandSender, org.bukkit.command.Command, java.lang.String, - * java.lang.String[]) - */ @Override public List onTabComplete(CommandSender sender, Command cmd, String alias, String[] argsIn) { ArrayList msgArray = new ArrayList<>(); diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/Config.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/Config.java index 2baa296895..ad3835c19a 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/Config.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/Config.java @@ -1,86 +1,81 @@ -package com.bencodez.votingplugin.config; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -import org.bukkit.configuration.ConfigurationSection; - -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.simpleapi.file.YMLFile; -import com.bencodez.simpleapi.file.annotation.AnnotationHandler; -import com.bencodez.simpleapi.file.annotation.ConfigDataBoolean; -import com.bencodez.simpleapi.file.annotation.ConfigDataInt; -import com.bencodez.simpleapi.file.annotation.ConfigDataKeys; -import com.bencodez.simpleapi.file.annotation.ConfigDataListString; -import com.bencodez.simpleapi.file.annotation.ConfigDataLong; -import com.bencodez.simpleapi.file.annotation.ConfigDataString; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.placeholders.PlaceholderCacheLevel; -import com.bencodez.votingplugin.topvoter.TopVoter; - -import lombok.Getter; - -// TODO: Auto-generated Javadoc -/** - * The Class Config. - */ -public class Config extends YMLFile { - - @ConfigDataBoolean(path = "AddCustomCommands") - @Getter - private boolean addCustomCommands = false; - - @ConfigDataBoolean(path = "AddTotals") - @Getter - private boolean addTotals = true; - - @ConfigDataBoolean(path = "AddTotalsOffline") - @Getter - private boolean addTotalsOffline = true; - - @ConfigDataBoolean(path = "LoadInteralExpansion") - @Getter - private boolean loadInteralExpansion = true; - - @ConfigDataBoolean(path = "PerSiteCoolDownEvents") - @Getter - private boolean perSiteCoolDownEvents = false; - - @ConfigDataInt(path = "LimitVotePoints") - @Getter - private int limitVotePoints = -1; - - /** Whether YAML files should be case insensitive. */ - @ConfigDataBoolean(path = "CaseInsensitiveYMLFiles") - @Getter - public boolean caseInsensitiveYMLFiles = false; - - @ConfigDataBoolean(path = "QueueVotesDuringTimeChange") - @Getter - private boolean queueVotesDuringTimeChange = false; - - @ConfigDataBoolean(path = "AdvancedServiceSiteHandling") - @Getter - private boolean advancedServiceSiteHandling = false; - - @ConfigDataBoolean(path = "AllowUnjoined") - @Getter - private boolean allowUnjoined = false; - - @ConfigDataBoolean(path = "PreloadSkulls") - @Getter - private boolean preloadSkulls = false; - - @ConfigDataBoolean(path = "DiscordSRV.Enabled") - @Getter - private boolean discordSRVEnabled = false; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.Enabled") - @Getter - private boolean discordSRVTopVoterAllTimeEnabled = false; - +package com.bencodez.votingplugin.config; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.simpleapi.file.YMLFile; +import com.bencodez.simpleapi.file.annotation.AnnotationHandler; +import com.bencodez.simpleapi.file.annotation.ConfigDataBoolean; +import com.bencodez.simpleapi.file.annotation.ConfigDataInt; +import com.bencodez.simpleapi.file.annotation.ConfigDataKeys; +import com.bencodez.simpleapi.file.annotation.ConfigDataListString; +import com.bencodez.simpleapi.file.annotation.ConfigDataLong; +import com.bencodez.simpleapi.file.annotation.ConfigDataString; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.placeholders.PlaceholderCacheLevel; +import com.bencodez.votingplugin.topvoter.TopVoter; + +import lombok.Getter; +public class Config extends YMLFile { + + @ConfigDataBoolean(path = "AddCustomCommands") + @Getter + private boolean addCustomCommands = false; + + @ConfigDataBoolean(path = "AddTotals") + @Getter + private boolean addTotals = true; + + @ConfigDataBoolean(path = "AddTotalsOffline") + @Getter + private boolean addTotalsOffline = true; + + @ConfigDataBoolean(path = "LoadInteralExpansion") + @Getter + private boolean loadInteralExpansion = true; + + @ConfigDataBoolean(path = "PerSiteCoolDownEvents") + @Getter + private boolean perSiteCoolDownEvents = false; + + @ConfigDataInt(path = "LimitVotePoints") + @Getter + private int limitVotePoints = -1; + + /** Whether YAML files should be case insensitive. */ + @ConfigDataBoolean(path = "CaseInsensitiveYMLFiles") + @Getter + public boolean caseInsensitiveYMLFiles = false; + + @ConfigDataBoolean(path = "QueueVotesDuringTimeChange") + @Getter + private boolean queueVotesDuringTimeChange = false; + + @ConfigDataBoolean(path = "AdvancedServiceSiteHandling") + @Getter + private boolean advancedServiceSiteHandling = false; + + @ConfigDataBoolean(path = "AllowUnjoined") + @Getter + private boolean allowUnjoined = false; + + @ConfigDataBoolean(path = "PreloadSkulls") + @Getter + private boolean preloadSkulls = false; + + @ConfigDataBoolean(path = "DiscordSRV.Enabled") + @Getter + private boolean discordSRVEnabled = false; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.Enabled") + @Getter + private boolean discordSRVTopVoterAllTimeEnabled = false; + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.NewMessageOnUpdate") @Getter private boolean discordSRVTopVoterAllTimeNewMessageOnUpdate = false; @@ -88,871 +83,871 @@ public class Config extends YMLFile { @ConfigDataBoolean(path = "DiscordSRV.TopVoter.AutoRecoverMessageOnFailure") @Getter private boolean discordSRVTopVoterAutoRecoverMessageOnFailure = true; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.NewMessageOnUpdate") - @Getter - private boolean discordSRVTopVoterMonthlyNewMessageOnUpdate = false; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.NewMessageOnUpdate") - @Getter - private boolean discordSRVTopVoterWeeklyNewMessageOnUpdate = false; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.NewMessageOnUpdate") - @Getter - private boolean discordSRVTopVoterDailyNewMessageOnUpdate = false; - - @ConfigDataLong(path = "DiscordSRV.TopVoter.AllTime.Channel") - @Getter - private long discordSRVTopVoterAllTimeChannel = 0; - - @ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.Title") - @Getter - private String discordSRVTopVoterAllTimeTitle = "All Time Top Voters"; - - @ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.RankDisplay") - @Getter - private String discordSRVTopVoterAllTimeRankDisplay = "%rank%: %player% - %votes% Votes"; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.Enabled") - @Getter - private boolean discordSRVTopVoterMonthlyEnabled = false; - - @ConfigDataLong(path = "DiscordSRV.TopVoter.Monthly.Channel") - @Getter - private long discordSRVTopVoterMonthlyChannel = 0; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.Title") - @Getter - private String discordSRVTopVoterMonthlyTitle = "Top Voters of the Month"; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.RankDisplay") - @Getter - private String discordSRVTopVoterMonthlyRankDisplay = "%rank%: %player% - %votes% Votes"; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.Enabled") - @Getter - private boolean discordSRVTopVoterWeeklyEnabled = false; - - @ConfigDataLong(path = "DiscordSRV.TopVoter.Weekly.Channel") - @Getter - private long discordSRVTopVoterWeeklyChannel = 0; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.Title") - @Getter - private String discordSRVTopVoterWeeklyTitle = "Top Voters of the Week"; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.RankDisplay") - @Getter - private String discordSRVTopVoterWeeklyRankDisplay = "%rank%: %player% - %votes% Votes"; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.Enabled") - @Getter - private boolean discordSRVTopVoterDailyEnabled = false; - - @ConfigDataLong(path = "DiscordSRV.TopVoter.Daily.Channel") - @Getter - private long discordSRVTopVoterDailyChannel = 0; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Daily.Title") - @Getter - private String discordSRVTopVoterDailyTitle = "Top Voters of the Day"; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Daily.RankDisplay") - @Getter - private String discordSRVTopVoterDailyRankDisplay = "%rank%: %player% - %votes% Votes"; - - // VoteLogging configuration section - minimal options mirror Config.yml - @ConfigDataBoolean(path = "VoteLogging.Enabled") - @Getter - private boolean voteLoggingEnabled = false; - - @ConfigDataInt(path = "VoteLogging.PurgeDays") - @Getter - private int voteLoggingPurgeDays = 30; - - @ConfigDataBoolean(path = "VoteLogging.UseMainMySQL") - @Getter - private boolean voteLoggingUseMainMySQL = true; - - /** - * Gets the vote logging configuration section. - * - * @return the vote logging configuration section - */ - public ConfigurationSection getVoteLoggingSection() { - if (!getData().isConfigurationSection("VoteLogging")) { - getData().createSection("VoteLogging"); - } - return getData().getConfigurationSection("VoteLogging"); - } - - /** - * Checks if DiscordSRV top voter is enabled. - * - * @param topVoter the top voter type - * @return true if enabled - */ - public boolean isDiscordSRVTopVoterEnabled(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return isDiscordSRVTopVoterAllTimeEnabled(); - case Monthly: - return isDiscordSRVTopVoterMonthlyEnabled(); - case Weekly: - return isDiscordSRVTopVoterWeeklyEnabled(); - case Daily: - return isDiscordSRVTopVoterDailyEnabled(); - default: - return false; - } - } - - /** - * Checks if DiscordSRV top voter should send a new message on update. - * - * @param topVoter the top voter type - * @return true if new message should be sent - */ - public boolean isDiscordSRVTopVoterNewMessageOnUpdate(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return isDiscordSRVTopVoterAllTimeNewMessageOnUpdate(); - case Monthly: - return isDiscordSRVTopVoterMonthlyNewMessageOnUpdate(); - case Weekly: - return isDiscordSRVTopVoterWeeklyNewMessageOnUpdate(); - case Daily: - return isDiscordSRVTopVoterDailyNewMessageOnUpdate(); - default: - return false; - } - } - - /** - * Gets the DiscordSRV top voter channel ID. - * - * @param topVoter the top voter type - * @return the channel ID - */ - public long getDiscordSRVTopVoterChannel(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return getDiscordSRVTopVoterAllTimeChannel(); - case Monthly: - return getDiscordSRVTopVoterMonthlyChannel(); - case Weekly: - return getDiscordSRVTopVoterWeeklyChannel(); - case Daily: - return getDiscordSRVTopVoterDailyChannel(); - default: - return 0; - } - } - - /** - * Gets the DiscordSRV top voter title. - * - * @param topVoter the top voter type - * @return the title - */ - public String getDiscordSRVTopVoterTitle(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return getDiscordSRVTopVoterAllTimeTitle(); - case Monthly: - return getDiscordSRVTopVoterMonthlyTitle(); - case Weekly: - return getDiscordSRVTopVoterWeeklyTitle(); - case Daily: - return getDiscordSRVTopVoterDailyTitle(); - default: - return ""; - } - } - - /** - * Gets the DiscordSRV top voter rank display format. - * - * @param topVoter the top voter type - * @return the rank display format - */ - public String getDiscordSRVTopVoterRankDisplay(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return getDiscordSRVTopVoterAllTimeRankDisplay(); - case Monthly: - return getDiscordSRVTopVoterMonthlyRankDisplay(); - case Weekly: - return getDiscordSRVTopVoterWeeklyRankDisplay(); - case Daily: - return getDiscordSRVTopVoterDailyRankDisplay(); - default: - return ""; - } - } - - @ConfigDataBoolean(path = "AllowUnJoinedCheckServer") - @Getter - private boolean allowUnJoinedCheckServer = true; - - @ConfigDataBoolean(path = "AllowVotePointTransfers") - @Getter - private boolean allowVotePointTransfers = false; - - @ConfigDataBoolean(path = "AlternateUUIDLookup") - @Getter - private boolean alternateUUIDLookup = false; - - @ConfigDataBoolean(path = "AlwaysCloseInventory") - @Getter - private boolean alwaysCloseInventory = false; - - @ConfigDataBoolean(path = "ExtraVoteShopCheck") - @Getter - private boolean extraVoteShopCheck = true; - - @ConfigDataBoolean(path = "AlwaysUpdate") - @Getter - private boolean alwaysUpdate = false; - - @ConfigDataBoolean(path = "AutoCreateVoteSites") - @Getter - private boolean autoCreateVoteSites = true; - - @ConfigDataBoolean(path = "CountFakeVotes") - @Getter - private boolean countFakeVotes = true; - - @ConfigDataString(path = "DelayBetweenUpdates") - @Getter - private String delayBetweenUpdates = "3m"; - - @ConfigDataBoolean(path = "DisableAdvancedTab") - @Getter - private boolean disableAdvancedTab = false; - - @ConfigDataBoolean(path = "DisableCoolDownCheck") - @Getter - private boolean disableCoolDownCheck = false; - - @ConfigDataListString(path = "DisabledCommands") - @Getter - private ArrayList disabledCommands = new ArrayList<>(); - - @ConfigDataListString(path = "DisabledDefaultPermissions") - @Getter - private ArrayList disabledDefaultPermissions = new ArrayList<>(); - - @ConfigDataListString(path = "CachedPlaceholders") - @Getter - private ArrayList cachedPlaceholders = new ArrayList<>(); - - @ConfigDataBoolean(path = "DisableInteractEvent") - @Getter - private boolean disableInteractEvent = false; - - @ConfigDataBoolean(path = "DisableNoServiceSiteMessage") - @Getter - private boolean disableNoServiceSiteMessage = false; - - @ConfigDataString(path = "Format.Commands.AdminVote.Points.PlayerRemoved") - @Getter - private String formatCommandsAdminVotePointsPlayerRemoved = "&c%amount% voting points have been removed from you"; - - @ConfigDataString(path = "Format.Commands.AdminVote.Points.PlayerGiven") - @Getter - private String formatCommandsAdminVotePointsPlayerGiven = "&cYou have been given %amount% voting points"; - - @ConfigDataBoolean(path = "DisableUpdateChecking") - @Getter - private boolean disableUpdateChecking = false; - - @ConfigDataBoolean(path = "ExtraAllSitesCheck") - @Getter - private boolean extraAllSitesCheck = false; - - @ConfigDataBoolean(path = "CloseInventoryOnVote") - @Getter - private boolean closeInventoryOnVote = true; - - @ConfigDataBoolean(path = "ExtraBackgroundUpdate") - @Getter - private boolean extraBackgroundUpdate = false; - - @ConfigDataBoolean(path = "Format.Commands.Vote.ForceLinks") - @Getter - private boolean formatCommandsVoteForceLinks = true; - - @ConfigDataString(path = "Format.Commands.Vote.Last.LastVoted") - @Getter - private String formatCommandsVoteLastLastVoted = "%times% ago"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NotEnoughPoints") - @Getter - private String formatCommandsVoteGivePointsNotEnoughPoints = "&cNot enough points"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NotJoinedServer") - @Getter - private String formatCommandsVoteGivePointsNotJoinedServer = "&c%player% has not joined the server"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NumberLowerThanZero") - @Getter - private String formatCommandsVoteGivePointsNumberLowerThanZero = "&cNumber of points needs to be greater than 0"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.TransferFrom") - @Getter - private String formatCommandsVoteGivePointsTransferFrom = "&c%transfer% points given to %touser%"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.TransferTo") - @Getter - private String formatCommandsVoteGivePointsTransferTo = "&cYou received %transfer points from %fromuser%"; - - @ConfigDataString(path = "Format.Commands.Vote.Last.Line", defaultValue = "&3%SiteName%: &6%timeSince% ago") - @Getter - private String formatCommandsVoteLastLine; - - @ConfigDataString(path = "Format.Commands.Vote.Last.NeverVoted", defaultValue = "Never voted") - @Getter - private String formatCommandsVoteLastNeverVoted; - - @ConfigDataBoolean(path = "Format.Commands.Vote.Last.IncludeSeconds") - @Getter - private boolean formatCommandsVoteLastIncludeSeconds = true; - - @ConfigDataString(path = "Format.Commands.Vote.Last.TimeFormat", defaultValue = "%amount% %TimeType%") - @Getter - private String formatCommandsVoteLastTimeFormat; - - @ConfigDataString(path = "Format.Commands.Vote.Today.Line") - @Getter - private String formatCommandsVoteTodayLine = "&6%player% : %VoteSite% : %Time%"; - - @ConfigDataListString(path = "Format.Commands.Vote.Today.Title") - @Getter - private ArrayList formatCommandsVoteTodayTitle = ArrayUtils - .convert(new String[] { "&cToday's Votes %page%/%maxpage%", "&cPlayerName : VoteSite : Time" }); - - @ConfigDataString(path = "Format.Commands.Vote.ToggleBroadcasts.Disabled") - @Getter - private String formatCommandsVoteToggleBroadcastDisabled = "&cYou will no longer see vote broadcasts"; - - @ConfigDataString(path = "Format.Commands.Vote.ToggleBroadcasts.Enabled") - @Getter - private String formatCommandsVoteToggleBroadcastEnabled = "&cYou will now see vote broadcasts"; - - @ConfigDataString(path = "Format.Commands.Vote.ToggleReminders.Disabled") - @Getter - private String formatCommandsVoteToggleRemindersDisabled = "&cVote reminders disabled"; - - @ConfigDataString(path = "Format.Commands.Vote.ToggleReminders.Enabled") - @Getter - private String formatCommandsVoteToggleRemindersEnabled = "&cVote reminders enabled"; - - @Getter - private int formatPageSize = 10; - - @ConfigDataString(path = "Format.TimeFormats.Day", defaultValue = "Day") - @Getter - private String formatTimeFormatsDay; - - @ConfigDataString(path = "Format.TimeFormats.Days", defaultValue = "Days") - @Getter - private String formatTimeFormatsDays; - - @ConfigDataString(path = "Format.TimeFormats.Hour", defaultValue = "Hour") - @Getter - private String formatTimeFormatsHour; - - @ConfigDataString(path = "Format.TimeFormats.Hours", defaultValue = "Hours") - @Getter - private String formatTimeFormatsHours; - - @ConfigDataString(path = "Format.TimeFormats.Minute", defaultValue = "Minute") - @Getter - private String formatTimeFormatsMinute; - - @ConfigDataString(path = "Format.TimeFormats.Minutes", defaultValue = "Minutes") - @Getter - private String formatTimeFormatsMinutes; - - @ConfigDataString(path = "Format.TimeFormats.Second", defaultValue = "Second") - @Getter - private String formatTimeFormatsSecond; - - @ConfigDataString(path = "Format.TimeFormats.Seconds", defaultValue = "Seconds") - @Getter - private String formatTimeFormatsSeconds; - - @ConfigDataBoolean(path = "LimitMonthlyVotes") - @Getter - private boolean limitMonthlyVotes = false; - - @ConfigDataBoolean(path = "LoadCommandAliases") - @Getter - private boolean loadCommandAliases = true; - - @ConfigDataInt(path = "MaxiumNumberOfTopVotersToLoad") - @Getter - private int MaxiumNumberOfTopVotersToLoad = 1000; - - @ConfigDataBoolean(path = "OverrideVersionDisable") - @Getter - private boolean overrideVersionDisable = false; - - @ConfigDataBoolean(path = "PreventRepeatMilestones") - @Getter - private boolean preventRepeatMilestones = false; - - @ConfigDataBoolean(path = "OfflineVotesLimit.Enabled") - @Getter - private boolean offlineVotesLimitEnabled = false; - - @ConfigDataInt(path = "OfflineVotesLimit.Amount") - @Getter - private int offlineVotesLimitAmount = 5; - - @ConfigDataBoolean(path = "UpdateWithPlayersOnlineOnly") - @Getter - private boolean updateWithPlayersOnlineOnly = false; - - @ConfigDataBoolean(path = "UseHighestTotals") - @Getter - private boolean useHighestTotals = true; - - @ConfigDataBoolean(path = "UseJavascriptPlaceholders") - @Getter - private boolean useJavascriptPlaceholders = false; - - @ConfigDataBoolean(path = "UseVoteGUIMainCommand") - @Getter - private boolean useVoteGUIMainCommand = false; - - @ConfigDataBoolean(path = "UseVoteStreaks") - @Getter - private boolean useVoteStreaks = true; - - @ConfigDataListString(path = "VotingBroadcastBlacklist") - @Getter - private ArrayList votingBroadcastBlacklist = new ArrayList<>(); - - @ConfigDataKeys(path = "CustomCommands") - @Getter - private Set customCommands = new HashSet<>(); - - @ConfigDataKeys(path = "CustomPlaceholderReturns") - @Getter - private Set customPlaceholderReturns = new HashSet<>(); - - @ConfigDataBoolean(path = "Format.Commands.Vote.AutoInputSites") - @Getter - private boolean formatCommandsVoteAutoInputSites = true; - - @ConfigDataBoolean(path = "Format.Commands.Vote.OnlyShowSitesToVote") - @Getter - private boolean formatCommandsVoteOnlyShowSitesToVote = false; - - @ConfigDataListString(path = "Format.Commands.Vote.Best.Lines") - @Getter - private ArrayList formatCommandsVoteBestLines = new ArrayList<>(); - - @ConfigDataString(path = "Format.Commands.Vote.Best.Title") - @Getter - private String formatCommandsVoteBestTitle = "&3&l%player% Best Votes"; - - @ConfigDataString(path = "Format.Commands.Vote.Help.HoverColor") - @Getter - private String formatCommandsVoteHelpHoverColor = "AQUA"; - - @ConfigDataString(path = "Format.Commands.Vote.Help.Line") - @Getter - private String formatCommandsVoteHelpLine = "&6%Command% - &6%HelpMessage%"; - - @ConfigDataBoolean(path = "Format.Commands.Vote.Help.RequirePermission") - @Getter - private boolean formatCommandsVoteHelpRequirePermission = false; - - @ConfigDataString(path = "Format.Commands.Vote.Help.Title") - @Getter - private String formatCommandsVoteHelpTitle = "&6Voting Player Help"; - - @ConfigDataString(path = "Format.Commands.Vote.Last.Title") - @Getter - private String formatCommandsVoteLastTitle = "&3&l%player% Last Vote Times:"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Info.CanVote") - @Getter - private String formatCommandsVoteNextInfoCanVote = "Go Vote!"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Info.Error") - @Getter - private String formatCommandsVoteNextInfoError = ""; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Info.TimeUntilVote") - @Getter - private String formatCommandsVoteNextInfoTime = "&cCould not caculate time until next vote!"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Info.VoteDelayDaily") - @Getter - private String formatCommandsVoteNextInfoVoteDelayDaily = "%hours% Hours and %minutes% Minutes"; - - @ConfigDataString(path = "PlaceholderCacheLevel", options = { "AUTO", "SPECIFIC", "NONE" }) - @Getter - private String placeholderCacheLevelString = "AUTO"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Layout") - @Getter - private String formatCommandsVoteNextLayout = "&3%SiteName%: &6%info%"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Title") - @Getter - private String formatCommandsVoteNextTitle = "&3&l%player% Next Votes:"; - - @ConfigDataString(path = "Format.Commands.Vote.Streak.Title") - @Getter - private String formatCommandsVoteStreakTitle = "&3&l%player% Vote Streak"; - - @ConfigDataString(path = "Format.Commands.Vote.Sites") - @Getter - private String formatCommandsVoteURLS = "&4%num%: &c&l%SiteName% - &c%url%"; - - @ConfigDataString(path = "Format.Commands.Vote.Points") - @Getter - private String formatCommandsVotePoints = "&a%Player% currently has &a&l%Points%&a Points!"; - - @ConfigDataString(path = "Format.Commands.Vote.Top.Line") - @Getter - private String formatCommandsVoteTopLine = "&c%num%: &6%player%, %votes%"; - - @ConfigDataString(path = "Format.Commands.Vote.Top.Title") - @Getter - private String formatCommandVoteTopTitle = "&3Top %Top% Voters %page%/%maxpages%"; - - @ConfigDataString(path = "Format.NextPage") - @Getter - private String formatNextPage = "&aNext Page"; - - @ConfigDataString(path = "Format.NoPerms") - @Getter - private String formatNoPerms = "&cYou do not have enough permission!"; - - @ConfigDataString(path = "Format.NotNumber") - @Getter - private String formatNotNumber = "&cError on &6%arg%&c, number expected!"; - - @ConfigDataString(path = "Format.PrevPage") - @Getter - private String formatPrevPage = "&aPrevious Page"; - - @ConfigDataString(path = "Format.ShopFailed") - @Getter - private String formatShopFailedMsg = "&cYou do not have %Points% points to purhcase this!"; - - @ConfigDataString(path = "Format.ShopNotPurchasable") - @Getter - private String formatShopNotPurchasable = "&cThis item is not buyable!"; - - @ConfigDataString(path = "Format.ShopPurchase") - @Getter - private String formatShopPurchaseMsg = "&aYou bought the %Identifier% for %Points% Points!"; - - @ConfigDataString(path = "Format.Signs.TopVoterSign.Line1") - @Getter - private String formatSignTopVoterSignLine1 = "TopVoter: %SiteName%"; - - @ConfigDataString(path = "Format.Signs.TopVoterSign.Line2") - @Getter - private String formatSignTopVoterSignLine2 = "#%position%"; - - @ConfigDataString(path = "Format.Signs.TopVoterSign.Line3") - @Getter - private String formatSignTopVoterSignLine3 = "%player%"; - - @ConfigDataString(path = "Format.Signs.TopVoterSign.Line4") - @Getter - private String formatSignTopVoterSignLine4 = "%votes% Votes"; - - @ConfigDataString(path = "Format.Signs.RightClickMessage") - @Getter - private String formatSignTopVoterSignRightClickMessage = "&c&l%player% &cis &c&l%position% &cwith &c&l%votes% &cin &c&l%SiteName%"; - - @ConfigDataString(path = "Format.TimeFormat") - @Getter - private String formatTimeFormat = "EEE, d MMM yyyy HH:mm"; - - @ConfigDataString(path = "Format.TopVoter.AllTime") - @Getter - private String formatTopVoterAllTime = "AllTime"; - - @ConfigDataString(path = "Format.TopVoter.Daily") - @Getter - private String formatTopVoterDaily = "Daily"; - - @ConfigDataString(path = "Format.TopVoter.Monthly") - @Getter - private String formatTopVoterMonthly = "Monthly"; - - @ConfigDataString(path = "Format.TopVoterAwardMsg") - @Getter - private String formatTopVoterRewardMsg = "&aYou came in %place% in top voters of the month! Here is an award!"; - - @ConfigDataString(path = "Format.TopVoter.Weekly") - @Getter - private String formatTopVoterWeekly = "Weekly"; - - @ConfigDataString(path = "Format.UserNotExist") - @Getter - private String formatUserNotExist = "&cUser does not exist: %player%"; - - @ConfigDataString(path = "Format.InvalidCommand.Vote") - @Getter - private String formatInvalidCommandVote = "&4No valid arguments, see /vote help!"; - @ConfigDataString(path = "Format.InvalidCommand.AdminVote") - @Getter - private String formatInvalidCommandAdminVote = "&4No valid arguments, see /adminvote help!"; - @ConfigDataBoolean(path = "GiveDefaultPermission") - @Getter - private boolean giveDefaultPermission = true; - - @ConfigDataBoolean(path = "LoadTopVoter.AllTime") - @Getter - private boolean loadTopVoterAllTime = true; - - @ConfigDataBoolean(path = "LoadTopVoter.Monthly") - @Getter - private boolean loadTopVoterMonthly = true; - - @ConfigDataBoolean(path = "LoadTopVoter.Daily") - @Getter - private boolean loadTopVoterDaily = false; - - @ConfigDataBoolean(path = "LoadTopVoter.Weekly") - @Getter - private boolean loadTopVoterWeekly = false; - - @ConfigDataInt(path = "PointsOnVote") - @Getter - private int pointsOnVote = 1; - - @ConfigDataBoolean(path = "PurgeNoDataOnStartup") - @Getter - private boolean purgeNoDataOnStartup = false; - - @ConfigDataBoolean(path = "StoreMonthTotalsWithDate") - @Getter - private boolean storeMonthTotalsWithDate = false; - - @ConfigDataBoolean(path = "UseMonthDateTotalsAsPrimaryTotal") - @Getter - private boolean useMonthDateTotalsAsPrimaryTotal = false; - - @ConfigDataString(path = "RequestAPI.DefaultMethod") - @Getter - private String requestAPIDefaultMethod = "ANVIL"; - - @ConfigDataListString(path = "RequestAPI.DisabledMethods") - @Getter - private ArrayList requestAPIDisabledMethods = new ArrayList<>(); - - @ConfigDataBoolean(path = "StoreTopVoters.Daily") - @Getter - private boolean storeTopVotersDaily = false; - - @ConfigDataBoolean(path = "StoreTopVoters.Weekly") - @Getter - private boolean storeTopVotersWeekly = false; - - @ConfigDataBoolean(path = "TopVoterAwardsTies") - @Getter - private boolean topVoterAwardsTies = true; - - @ConfigDataBoolean(path = "TopVoterIgnorePermission") - @Getter - private boolean topVoterIgnorePermission = false; - - @ConfigDataString(path = "VoteTopDefault") - @Getter - private String voteTopDefault = "Monthly"; - - @ConfigDataBoolean(path = "AlwaysProcessAsyncPlaceholders") - @Getter - private boolean alwaysProcessAsyncPlaceholders = false; - - /** - * Constructs a new Config. - * - * @param plugin the main plugin instance - */ - public Config(VotingPluginMain plugin) { - super(plugin, new File(plugin.getDataFolder(), "Config.yml")); - setIgnoreCase(true); - } - - /** - * Gets the black list. - * - * @return the black list - */ - @SuppressWarnings("unchecked") - public ArrayList getBlackList() { - return (ArrayList) getData().getList("BlackList", new ArrayList<>()); - } - - /** - * Gets the custom commands configuration section. - * - * @param ident the command identifier - * @return the configuration section - */ - public ConfigurationSection getCustomCommands(String ident) { - return getData().getConfigurationSection("CustomCommands." + ident); - } - - /** - * Gets the custom placeholder return keys. - * - * @param placeholder the placeholder name - * @return set of return keys - */ - public Set getCustomPlaceholderReturns(String placeholder) { - Set str = getData().getConfigurationSection("CustomPlaceholderReturns." + placeholder).getKeys(false); - if (str == null) { - str = new HashSet<>(); - } - return str; - } - - /** - * Gets a custom placeholder return value. - * - * @param placeholder the placeholder name - * @param returnString the return key - * @return the return value - */ - public String getCustomPlaceholderReturns(String placeholder, String returnString) { - return getData().getString("CustomPlaceholderReturns." + placeholder + "." + returnString, ""); - } - - /** - * Gets the commands vote party. - * - * @return the commands vote party - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteParty() { - ArrayList msg = new ArrayList<>(); - msg.add("&cCurrently at &6%Votes%&c, &6%NeededVotes% &cmore votes to go to reach &6%VotesRequired%"); - return (ArrayList) getData().getList("Format.Commands.Vote.Party", msg); - - } - - /** - * Gets the vote streak lines format. - * - * @return list of format lines - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteStreakLines() { - return (ArrayList) getData().getList("Format.Commands.Vote.Streak.Lines", new ArrayList<>()); - } - - /** - * Gets the commands vote text. - * - * @return the commands vote text - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteText() { - ArrayList str = new ArrayList<>(); - str.add("&4&lVote for our server!"); - return (ArrayList) getData().getList("Format.Commands.Vote.Text", str); - } - - /** - * Gets the vote total format lines. - * - * @return list of format lines - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteTotal() { - ArrayList list = (ArrayList) getData().getList("Format.Commands.Vote.Total", new ArrayList<>()); - if (list.isEmpty()) { - list.add("&3&l%player% Total Votes:"); - list.add("&3&lDaily Total: &6&l%DailyTotal%"); - list.add("&3&lWeekly Total: &6&l%WeeklyTotal%"); - list.add("&3&lMonthly Total: &6&l%MonthlyTotal%"); - list.add("&3&lAllTime Total: &6&l%AllTimeTotal%"); - } - return list; - } - - /** - * Gets the vote total all format lines. - * - * @return list of format lines - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteTotalAll() { - - ArrayList list = (ArrayList) getData().getList("Format.Commands.Vote.TotalAll", - new ArrayList<>()); - if (list.isEmpty()) { - list.add("&3&lServer Total Votes:"); - list.add("&3&lDaily Total: &6&l%DailyTotal%"); - list.add("&3&lWeekly Total: &6&l%WeeklyTotal%"); - list.add("&3&lMonthly Total: &6&l%MonthlyTotal%"); - list.add("&3&lAllTime Total: &6&l%AllTimeTotal%"); - } - return list; - } - - /** - * Gets the vote help. - * - * @return the vote help - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatVoteHelp() { - return (ArrayList) getData().getList("Format.Commands.Vote.Help.Lines", new ArrayList<>()); - } - - /** - * Checks if a top voter type should be loaded. - * - * @param top the top voter type - * @return true if should be loaded - */ - public boolean getLoadTopVoter(TopVoter top) { - switch (top) { - case AllTime: - return isLoadTopVoterAllTime(); - case Daily: - return isLoadTopVoterDaily(); - case Monthly: - return isLoadTopVoterMonthly(); - case Weekly: - return isLoadTopVoterWeekly(); - default: - return false; - } - } - - /** - * Gets the placeholder cache level. - * - * @return the cache level - */ - public PlaceholderCacheLevel getPlaceholderCacheLevel() { - return PlaceholderCacheLevel.getCache(getPlaceholderCacheLevelString()); - } - - @Override - public void loadValues() { - new AnnotationHandler().load(getData(), this); - } - - @Override - public void onFileCreation() { - getPlugin().saveResource("Config.yml", true); - } - -} + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.NewMessageOnUpdate") + @Getter + private boolean discordSRVTopVoterMonthlyNewMessageOnUpdate = false; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.NewMessageOnUpdate") + @Getter + private boolean discordSRVTopVoterWeeklyNewMessageOnUpdate = false; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.NewMessageOnUpdate") + @Getter + private boolean discordSRVTopVoterDailyNewMessageOnUpdate = false; + + @ConfigDataLong(path = "DiscordSRV.TopVoter.AllTime.Channel") + @Getter + private long discordSRVTopVoterAllTimeChannel = 0; + + @ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.Title") + @Getter + private String discordSRVTopVoterAllTimeTitle = "All Time Top Voters"; + + @ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.RankDisplay") + @Getter + private String discordSRVTopVoterAllTimeRankDisplay = "%rank%: %player% - %votes% Votes"; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.Enabled") + @Getter + private boolean discordSRVTopVoterMonthlyEnabled = false; + + @ConfigDataLong(path = "DiscordSRV.TopVoter.Monthly.Channel") + @Getter + private long discordSRVTopVoterMonthlyChannel = 0; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.Title") + @Getter + private String discordSRVTopVoterMonthlyTitle = "Top Voters of the Month"; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.RankDisplay") + @Getter + private String discordSRVTopVoterMonthlyRankDisplay = "%rank%: %player% - %votes% Votes"; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.Enabled") + @Getter + private boolean discordSRVTopVoterWeeklyEnabled = false; + + @ConfigDataLong(path = "DiscordSRV.TopVoter.Weekly.Channel") + @Getter + private long discordSRVTopVoterWeeklyChannel = 0; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.Title") + @Getter + private String discordSRVTopVoterWeeklyTitle = "Top Voters of the Week"; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.RankDisplay") + @Getter + private String discordSRVTopVoterWeeklyRankDisplay = "%rank%: %player% - %votes% Votes"; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.Enabled") + @Getter + private boolean discordSRVTopVoterDailyEnabled = false; + + @ConfigDataLong(path = "DiscordSRV.TopVoter.Daily.Channel") + @Getter + private long discordSRVTopVoterDailyChannel = 0; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Daily.Title") + @Getter + private String discordSRVTopVoterDailyTitle = "Top Voters of the Day"; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Daily.RankDisplay") + @Getter + private String discordSRVTopVoterDailyRankDisplay = "%rank%: %player% - %votes% Votes"; + + // VoteLogging configuration section - minimal options mirror Config.yml + @ConfigDataBoolean(path = "VoteLogging.Enabled") + @Getter + private boolean voteLoggingEnabled = false; + + @ConfigDataInt(path = "VoteLogging.PurgeDays") + @Getter + private int voteLoggingPurgeDays = 30; + + @ConfigDataBoolean(path = "VoteLogging.UseMainMySQL") + @Getter + private boolean voteLoggingUseMainMySQL = true; + + /** + * Gets the vote logging configuration section. + * + * @return the vote logging configuration section + */ + public ConfigurationSection getVoteLoggingSection() { + if (!getData().isConfigurationSection("VoteLogging")) { + getData().createSection("VoteLogging"); + } + return getData().getConfigurationSection("VoteLogging"); + } + + /** + * Checks if DiscordSRV top voter is enabled. + * + * @param topVoter the top voter type + * @return true if enabled + */ + public boolean isDiscordSRVTopVoterEnabled(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return isDiscordSRVTopVoterAllTimeEnabled(); + case Monthly: + return isDiscordSRVTopVoterMonthlyEnabled(); + case Weekly: + return isDiscordSRVTopVoterWeeklyEnabled(); + case Daily: + return isDiscordSRVTopVoterDailyEnabled(); + default: + return false; + } + } + + /** + * Checks if DiscordSRV top voter should send a new message on update. + * + * @param topVoter the top voter type + * @return true if new message should be sent + */ + public boolean isDiscordSRVTopVoterNewMessageOnUpdate(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return isDiscordSRVTopVoterAllTimeNewMessageOnUpdate(); + case Monthly: + return isDiscordSRVTopVoterMonthlyNewMessageOnUpdate(); + case Weekly: + return isDiscordSRVTopVoterWeeklyNewMessageOnUpdate(); + case Daily: + return isDiscordSRVTopVoterDailyNewMessageOnUpdate(); + default: + return false; + } + } + + /** + * Gets the DiscordSRV top voter channel ID. + * + * @param topVoter the top voter type + * @return the channel ID + */ + public long getDiscordSRVTopVoterChannel(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return getDiscordSRVTopVoterAllTimeChannel(); + case Monthly: + return getDiscordSRVTopVoterMonthlyChannel(); + case Weekly: + return getDiscordSRVTopVoterWeeklyChannel(); + case Daily: + return getDiscordSRVTopVoterDailyChannel(); + default: + return 0; + } + } + + /** + * Gets the DiscordSRV top voter title. + * + * @param topVoter the top voter type + * @return the title + */ + public String getDiscordSRVTopVoterTitle(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return getDiscordSRVTopVoterAllTimeTitle(); + case Monthly: + return getDiscordSRVTopVoterMonthlyTitle(); + case Weekly: + return getDiscordSRVTopVoterWeeklyTitle(); + case Daily: + return getDiscordSRVTopVoterDailyTitle(); + default: + return ""; + } + } + + /** + * Gets the DiscordSRV top voter rank display format. + * + * @param topVoter the top voter type + * @return the rank display format + */ + public String getDiscordSRVTopVoterRankDisplay(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return getDiscordSRVTopVoterAllTimeRankDisplay(); + case Monthly: + return getDiscordSRVTopVoterMonthlyRankDisplay(); + case Weekly: + return getDiscordSRVTopVoterWeeklyRankDisplay(); + case Daily: + return getDiscordSRVTopVoterDailyRankDisplay(); + default: + return ""; + } + } + + @ConfigDataBoolean(path = "AllowUnJoinedCheckServer") + @Getter + private boolean allowUnJoinedCheckServer = true; + + @ConfigDataBoolean(path = "AllowVotePointTransfers") + @Getter + private boolean allowVotePointTransfers = false; + + @ConfigDataBoolean(path = "AlternateUUIDLookup") + @Getter + private boolean alternateUUIDLookup = false; + + @ConfigDataBoolean(path = "AlwaysCloseInventory") + @Getter + private boolean alwaysCloseInventory = false; + + @ConfigDataBoolean(path = "ExtraVoteShopCheck") + @Getter + private boolean extraVoteShopCheck = true; + + @ConfigDataBoolean(path = "AlwaysUpdate") + @Getter + private boolean alwaysUpdate = false; + + @ConfigDataBoolean(path = "AutoCreateVoteSites") + @Getter + private boolean autoCreateVoteSites = true; + + @ConfigDataBoolean(path = "CountFakeVotes") + @Getter + private boolean countFakeVotes = true; + + @ConfigDataString(path = "DelayBetweenUpdates") + @Getter + private String delayBetweenUpdates = "3m"; + + @ConfigDataBoolean(path = "DisableAdvancedTab") + @Getter + private boolean disableAdvancedTab = false; + + @ConfigDataBoolean(path = "DisableCoolDownCheck") + @Getter + private boolean disableCoolDownCheck = false; + + @ConfigDataListString(path = "DisabledCommands") + @Getter + private ArrayList disabledCommands = new ArrayList<>(); + + @ConfigDataListString(path = "DisabledDefaultPermissions") + @Getter + private ArrayList disabledDefaultPermissions = new ArrayList<>(); + + @ConfigDataListString(path = "CachedPlaceholders") + @Getter + private ArrayList cachedPlaceholders = new ArrayList<>(); + + @ConfigDataBoolean(path = "DisableInteractEvent") + @Getter + private boolean disableInteractEvent = false; + + @ConfigDataBoolean(path = "DisableNoServiceSiteMessage") + @Getter + private boolean disableNoServiceSiteMessage = false; + + @ConfigDataString(path = "Format.Commands.AdminVote.Points.PlayerRemoved") + @Getter + private String formatCommandsAdminVotePointsPlayerRemoved = "&c%amount% voting points have been removed from you"; + + @ConfigDataString(path = "Format.Commands.AdminVote.Points.PlayerGiven") + @Getter + private String formatCommandsAdminVotePointsPlayerGiven = "&cYou have been given %amount% voting points"; + + @ConfigDataBoolean(path = "DisableUpdateChecking") + @Getter + private boolean disableUpdateChecking = false; + + @ConfigDataBoolean(path = "ExtraAllSitesCheck") + @Getter + private boolean extraAllSitesCheck = false; + + @ConfigDataBoolean(path = "CloseInventoryOnVote") + @Getter + private boolean closeInventoryOnVote = true; + + @ConfigDataBoolean(path = "ExtraBackgroundUpdate") + @Getter + private boolean extraBackgroundUpdate = false; + + @ConfigDataBoolean(path = "Format.Commands.Vote.ForceLinks") + @Getter + private boolean formatCommandsVoteForceLinks = true; + + @ConfigDataString(path = "Format.Commands.Vote.Last.LastVoted") + @Getter + private String formatCommandsVoteLastLastVoted = "%times% ago"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NotEnoughPoints") + @Getter + private String formatCommandsVoteGivePointsNotEnoughPoints = "&cNot enough points"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NotJoinedServer") + @Getter + private String formatCommandsVoteGivePointsNotJoinedServer = "&c%player% has not joined the server"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NumberLowerThanZero") + @Getter + private String formatCommandsVoteGivePointsNumberLowerThanZero = "&cNumber of points needs to be greater than 0"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.TransferFrom") + @Getter + private String formatCommandsVoteGivePointsTransferFrom = "&c%transfer% points given to %touser%"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.TransferTo") + @Getter + private String formatCommandsVoteGivePointsTransferTo = "&cYou received %transfer points from %fromuser%"; + + @ConfigDataString(path = "Format.Commands.Vote.Last.Line", defaultValue = "&3%SiteName%: &6%timeSince% ago") + @Getter + private String formatCommandsVoteLastLine; + + @ConfigDataString(path = "Format.Commands.Vote.Last.NeverVoted", defaultValue = "Never voted") + @Getter + private String formatCommandsVoteLastNeverVoted; + + @ConfigDataBoolean(path = "Format.Commands.Vote.Last.IncludeSeconds") + @Getter + private boolean formatCommandsVoteLastIncludeSeconds = true; + + @ConfigDataString(path = "Format.Commands.Vote.Last.TimeFormat", defaultValue = "%amount% %TimeType%") + @Getter + private String formatCommandsVoteLastTimeFormat; + + @ConfigDataString(path = "Format.Commands.Vote.Today.Line") + @Getter + private String formatCommandsVoteTodayLine = "&6%player% : %VoteSite% : %Time%"; + + @ConfigDataListString(path = "Format.Commands.Vote.Today.Title") + @Getter + private ArrayList formatCommandsVoteTodayTitle = ArrayUtils + .convert(new String[] { "&cToday's Votes %page%/%maxpage%", "&cPlayerName : VoteSite : Time" }); + + @ConfigDataString(path = "Format.Commands.Vote.ToggleBroadcasts.Disabled") + @Getter + private String formatCommandsVoteToggleBroadcastDisabled = "&cYou will no longer see vote broadcasts"; + + @ConfigDataString(path = "Format.Commands.Vote.ToggleBroadcasts.Enabled") + @Getter + private String formatCommandsVoteToggleBroadcastEnabled = "&cYou will now see vote broadcasts"; + + @ConfigDataString(path = "Format.Commands.Vote.ToggleReminders.Disabled") + @Getter + private String formatCommandsVoteToggleRemindersDisabled = "&cVote reminders disabled"; + + @ConfigDataString(path = "Format.Commands.Vote.ToggleReminders.Enabled") + @Getter + private String formatCommandsVoteToggleRemindersEnabled = "&cVote reminders enabled"; + + @Getter + private int formatPageSize = 10; + + @ConfigDataString(path = "Format.TimeFormats.Day", defaultValue = "Day") + @Getter + private String formatTimeFormatsDay; + + @ConfigDataString(path = "Format.TimeFormats.Days", defaultValue = "Days") + @Getter + private String formatTimeFormatsDays; + + @ConfigDataString(path = "Format.TimeFormats.Hour", defaultValue = "Hour") + @Getter + private String formatTimeFormatsHour; + + @ConfigDataString(path = "Format.TimeFormats.Hours", defaultValue = "Hours") + @Getter + private String formatTimeFormatsHours; + + @ConfigDataString(path = "Format.TimeFormats.Minute", defaultValue = "Minute") + @Getter + private String formatTimeFormatsMinute; + + @ConfigDataString(path = "Format.TimeFormats.Minutes", defaultValue = "Minutes") + @Getter + private String formatTimeFormatsMinutes; + + @ConfigDataString(path = "Format.TimeFormats.Second", defaultValue = "Second") + @Getter + private String formatTimeFormatsSecond; + + @ConfigDataString(path = "Format.TimeFormats.Seconds", defaultValue = "Seconds") + @Getter + private String formatTimeFormatsSeconds; + + @ConfigDataBoolean(path = "LimitMonthlyVotes") + @Getter + private boolean limitMonthlyVotes = false; + + @ConfigDataBoolean(path = "LoadCommandAliases") + @Getter + private boolean loadCommandAliases = true; + + @ConfigDataInt(path = "MaxiumNumberOfTopVotersToLoad") + @Getter + private int MaxiumNumberOfTopVotersToLoad = 1000; + + @ConfigDataBoolean(path = "OverrideVersionDisable") + @Getter + private boolean overrideVersionDisable = false; + + @ConfigDataBoolean(path = "PreventRepeatMilestones") + @Getter + private boolean preventRepeatMilestones = false; + + @ConfigDataBoolean(path = "OfflineVotesLimit.Enabled") + @Getter + private boolean offlineVotesLimitEnabled = false; + + @ConfigDataInt(path = "OfflineVotesLimit.Amount") + @Getter + private int offlineVotesLimitAmount = 5; + + @ConfigDataBoolean(path = "UpdateWithPlayersOnlineOnly") + @Getter + private boolean updateWithPlayersOnlineOnly = false; + + @ConfigDataBoolean(path = "UseHighestTotals") + @Getter + private boolean useHighestTotals = true; + + @ConfigDataBoolean(path = "UseJavascriptPlaceholders") + @Getter + private boolean useJavascriptPlaceholders = false; + + @ConfigDataBoolean(path = "UseVoteGUIMainCommand") + @Getter + private boolean useVoteGUIMainCommand = false; + + @ConfigDataBoolean(path = "UseVoteStreaks") + @Getter + private boolean useVoteStreaks = true; + + @ConfigDataListString(path = "VotingBroadcastBlacklist") + @Getter + private ArrayList votingBroadcastBlacklist = new ArrayList<>(); + + @ConfigDataKeys(path = "CustomCommands") + @Getter + private Set customCommands = new HashSet<>(); + + @ConfigDataKeys(path = "CustomPlaceholderReturns") + @Getter + private Set customPlaceholderReturns = new HashSet<>(); + + @ConfigDataBoolean(path = "Format.Commands.Vote.AutoInputSites") + @Getter + private boolean formatCommandsVoteAutoInputSites = true; + + @ConfigDataBoolean(path = "Format.Commands.Vote.OnlyShowSitesToVote") + @Getter + private boolean formatCommandsVoteOnlyShowSitesToVote = false; + + @ConfigDataListString(path = "Format.Commands.Vote.Best.Lines") + @Getter + private ArrayList formatCommandsVoteBestLines = new ArrayList<>(); + + @ConfigDataString(path = "Format.Commands.Vote.Best.Title") + @Getter + private String formatCommandsVoteBestTitle = "&3&l%player% Best Votes"; + + @ConfigDataString(path = "Format.Commands.Vote.Help.HoverColor") + @Getter + private String formatCommandsVoteHelpHoverColor = "AQUA"; + + @ConfigDataString(path = "Format.Commands.Vote.Help.Line") + @Getter + private String formatCommandsVoteHelpLine = "&6%Command% - &6%HelpMessage%"; + + @ConfigDataBoolean(path = "Format.Commands.Vote.Help.RequirePermission") + @Getter + private boolean formatCommandsVoteHelpRequirePermission = false; + + @ConfigDataString(path = "Format.Commands.Vote.Help.Title") + @Getter + private String formatCommandsVoteHelpTitle = "&6Voting Player Help"; + + @ConfigDataString(path = "Format.Commands.Vote.Last.Title") + @Getter + private String formatCommandsVoteLastTitle = "&3&l%player% Last Vote Times:"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Info.CanVote") + @Getter + private String formatCommandsVoteNextInfoCanVote = "Go Vote!"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Info.Error") + @Getter + private String formatCommandsVoteNextInfoError = ""; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Info.TimeUntilVote") + @Getter + private String formatCommandsVoteNextInfoTime = "&cCould not caculate time until next vote!"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Info.VoteDelayDaily") + @Getter + private String formatCommandsVoteNextInfoVoteDelayDaily = "%hours% Hours and %minutes% Minutes"; + + @ConfigDataString(path = "PlaceholderCacheLevel", options = { "AUTO", "SPECIFIC", "NONE" }) + @Getter + private String placeholderCacheLevelString = "AUTO"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Layout") + @Getter + private String formatCommandsVoteNextLayout = "&3%SiteName%: &6%info%"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Title") + @Getter + private String formatCommandsVoteNextTitle = "&3&l%player% Next Votes:"; + + @ConfigDataString(path = "Format.Commands.Vote.Streak.Title") + @Getter + private String formatCommandsVoteStreakTitle = "&3&l%player% Vote Streak"; + + @ConfigDataString(path = "Format.Commands.Vote.Sites") + @Getter + private String formatCommandsVoteURLS = "&4%num%: &c&l%SiteName% - &c%url%"; + + @ConfigDataString(path = "Format.Commands.Vote.Points") + @Getter + private String formatCommandsVotePoints = "&a%Player% currently has &a&l%Points%&a Points!"; + + @ConfigDataString(path = "Format.Commands.Vote.Top.Line") + @Getter + private String formatCommandsVoteTopLine = "&c%num%: &6%player%, %votes%"; + + @ConfigDataString(path = "Format.Commands.Vote.Top.Title") + @Getter + private String formatCommandVoteTopTitle = "&3Top %Top% Voters %page%/%maxpages%"; + + @ConfigDataString(path = "Format.NextPage") + @Getter + private String formatNextPage = "&aNext Page"; + + @ConfigDataString(path = "Format.NoPerms") + @Getter + private String formatNoPerms = "&cYou do not have enough permission!"; + + @ConfigDataString(path = "Format.NotNumber") + @Getter + private String formatNotNumber = "&cError on &6%arg%&c, number expected!"; + + @ConfigDataString(path = "Format.PrevPage") + @Getter + private String formatPrevPage = "&aPrevious Page"; + + @ConfigDataString(path = "Format.ShopFailed") + @Getter + private String formatShopFailedMsg = "&cYou do not have %Points% points to purhcase this!"; + + @ConfigDataString(path = "Format.ShopNotPurchasable") + @Getter + private String formatShopNotPurchasable = "&cThis item is not buyable!"; + + @ConfigDataString(path = "Format.ShopPurchase") + @Getter + private String formatShopPurchaseMsg = "&aYou bought the %Identifier% for %Points% Points!"; + + @ConfigDataString(path = "Format.Signs.TopVoterSign.Line1") + @Getter + private String formatSignTopVoterSignLine1 = "TopVoter: %SiteName%"; + + @ConfigDataString(path = "Format.Signs.TopVoterSign.Line2") + @Getter + private String formatSignTopVoterSignLine2 = "#%position%"; + + @ConfigDataString(path = "Format.Signs.TopVoterSign.Line3") + @Getter + private String formatSignTopVoterSignLine3 = "%player%"; + + @ConfigDataString(path = "Format.Signs.TopVoterSign.Line4") + @Getter + private String formatSignTopVoterSignLine4 = "%votes% Votes"; + + @ConfigDataString(path = "Format.Signs.RightClickMessage") + @Getter + private String formatSignTopVoterSignRightClickMessage = "&c&l%player% &cis &c&l%position% &cwith &c&l%votes% &cin &c&l%SiteName%"; + + @ConfigDataString(path = "Format.TimeFormat") + @Getter + private String formatTimeFormat = "EEE, d MMM yyyy HH:mm"; + + @ConfigDataString(path = "Format.TopVoter.AllTime") + @Getter + private String formatTopVoterAllTime = "AllTime"; + + @ConfigDataString(path = "Format.TopVoter.Daily") + @Getter + private String formatTopVoterDaily = "Daily"; + + @ConfigDataString(path = "Format.TopVoter.Monthly") + @Getter + private String formatTopVoterMonthly = "Monthly"; + + @ConfigDataString(path = "Format.TopVoterAwardMsg") + @Getter + private String formatTopVoterRewardMsg = "&aYou came in %place% in top voters of the month! Here is an award!"; + + @ConfigDataString(path = "Format.TopVoter.Weekly") + @Getter + private String formatTopVoterWeekly = "Weekly"; + + @ConfigDataString(path = "Format.UserNotExist") + @Getter + private String formatUserNotExist = "&cUser does not exist: %player%"; + + @ConfigDataString(path = "Format.InvalidCommand.Vote") + @Getter + private String formatInvalidCommandVote = "&4No valid arguments, see /vote help!"; + @ConfigDataString(path = "Format.InvalidCommand.AdminVote") + @Getter + private String formatInvalidCommandAdminVote = "&4No valid arguments, see /adminvote help!"; + @ConfigDataBoolean(path = "GiveDefaultPermission") + @Getter + private boolean giveDefaultPermission = true; + + @ConfigDataBoolean(path = "LoadTopVoter.AllTime") + @Getter + private boolean loadTopVoterAllTime = true; + + @ConfigDataBoolean(path = "LoadTopVoter.Monthly") + @Getter + private boolean loadTopVoterMonthly = true; + + @ConfigDataBoolean(path = "LoadTopVoter.Daily") + @Getter + private boolean loadTopVoterDaily = false; + + @ConfigDataBoolean(path = "LoadTopVoter.Weekly") + @Getter + private boolean loadTopVoterWeekly = false; + + @ConfigDataInt(path = "PointsOnVote") + @Getter + private int pointsOnVote = 1; + + @ConfigDataBoolean(path = "PurgeNoDataOnStartup") + @Getter + private boolean purgeNoDataOnStartup = false; + + @ConfigDataBoolean(path = "StoreMonthTotalsWithDate") + @Getter + private boolean storeMonthTotalsWithDate = false; + + @ConfigDataBoolean(path = "UseMonthDateTotalsAsPrimaryTotal") + @Getter + private boolean useMonthDateTotalsAsPrimaryTotal = false; + + @ConfigDataString(path = "RequestAPI.DefaultMethod") + @Getter + private String requestAPIDefaultMethod = "ANVIL"; + + @ConfigDataListString(path = "RequestAPI.DisabledMethods") + @Getter + private ArrayList requestAPIDisabledMethods = new ArrayList<>(); + + @ConfigDataBoolean(path = "StoreTopVoters.Daily") + @Getter + private boolean storeTopVotersDaily = false; + + @ConfigDataBoolean(path = "StoreTopVoters.Weekly") + @Getter + private boolean storeTopVotersWeekly = false; + + @ConfigDataBoolean(path = "TopVoterAwardsTies") + @Getter + private boolean topVoterAwardsTies = true; + + @ConfigDataBoolean(path = "TopVoterIgnorePermission") + @Getter + private boolean topVoterIgnorePermission = false; + + @ConfigDataString(path = "VoteTopDefault") + @Getter + private String voteTopDefault = "Monthly"; + + @ConfigDataBoolean(path = "AlwaysProcessAsyncPlaceholders") + @Getter + private boolean alwaysProcessAsyncPlaceholders = false; + + /** + * Constructs a new Config. + * + * @param plugin the main plugin instance + */ + public Config(VotingPluginMain plugin) { + super(plugin, new File(plugin.getDataFolder(), "Config.yml")); + setIgnoreCase(true); + } + + /** + * Gets the black list. + * + * @return the black list + */ + @SuppressWarnings("unchecked") + public ArrayList getBlackList() { + return (ArrayList) getData().getList("BlackList", new ArrayList<>()); + } + + /** + * Gets the custom commands configuration section. + * + * @param ident the command identifier + * @return the configuration section + */ + public ConfigurationSection getCustomCommands(String ident) { + return getData().getConfigurationSection("CustomCommands." + ident); + } + + /** + * Gets the custom placeholder return keys. + * + * @param placeholder the placeholder name + * @return set of return keys + */ + public Set getCustomPlaceholderReturns(String placeholder) { + Set str = getData().getConfigurationSection("CustomPlaceholderReturns." + placeholder).getKeys(false); + if (str == null) { + str = new HashSet<>(); + } + return str; + } + + /** + * Gets a custom placeholder return value. + * + * @param placeholder the placeholder name + * @param returnString the return key + * @return the return value + */ + public String getCustomPlaceholderReturns(String placeholder, String returnString) { + return getData().getString("CustomPlaceholderReturns." + placeholder + "." + returnString, ""); + } + + /** + * Gets the commands vote party. + * + * @return the commands vote party + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteParty() { + ArrayList msg = new ArrayList<>(); + msg.add("&cCurrently at &6%Votes%&c, &6%NeededVotes% &cmore votes to go to reach &6%VotesRequired%"); + return (ArrayList) getData().getList("Format.Commands.Vote.Party", msg); + + } + + /** + * Gets the vote streak lines format. + * + * @return list of format lines + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteStreakLines() { + return (ArrayList) getData().getList("Format.Commands.Vote.Streak.Lines", new ArrayList<>()); + } + + /** + * Gets the commands vote text. + * + * @return the commands vote text + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteText() { + ArrayList str = new ArrayList<>(); + str.add("&4&lVote for our server!"); + return (ArrayList) getData().getList("Format.Commands.Vote.Text", str); + } + + /** + * Gets the vote total format lines. + * + * @return list of format lines + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteTotal() { + ArrayList list = (ArrayList) getData().getList("Format.Commands.Vote.Total", new ArrayList<>()); + if (list.isEmpty()) { + list.add("&3&l%player% Total Votes:"); + list.add("&3&lDaily Total: &6&l%DailyTotal%"); + list.add("&3&lWeekly Total: &6&l%WeeklyTotal%"); + list.add("&3&lMonthly Total: &6&l%MonthlyTotal%"); + list.add("&3&lAllTime Total: &6&l%AllTimeTotal%"); + } + return list; + } + + /** + * Gets the vote total all format lines. + * + * @return list of format lines + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteTotalAll() { + + ArrayList list = (ArrayList) getData().getList("Format.Commands.Vote.TotalAll", + new ArrayList<>()); + if (list.isEmpty()) { + list.add("&3&lServer Total Votes:"); + list.add("&3&lDaily Total: &6&l%DailyTotal%"); + list.add("&3&lWeekly Total: &6&l%WeeklyTotal%"); + list.add("&3&lMonthly Total: &6&l%MonthlyTotal%"); + list.add("&3&lAllTime Total: &6&l%AllTimeTotal%"); + } + return list; + } + + /** + * Gets the vote help. + * + * @return the vote help + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatVoteHelp() { + return (ArrayList) getData().getList("Format.Commands.Vote.Help.Lines", new ArrayList<>()); + } + + /** + * Checks if a top voter type should be loaded. + * + * @param top the top voter type + * @return true if should be loaded + */ + public boolean getLoadTopVoter(TopVoter top) { + switch (top) { + case AllTime: + return isLoadTopVoterAllTime(); + case Daily: + return isLoadTopVoterDaily(); + case Monthly: + return isLoadTopVoterMonthly(); + case Weekly: + return isLoadTopVoterWeekly(); + default: + return false; + } + } + + /** + * Gets the placeholder cache level. + * + * @return the cache level + */ + public PlaceholderCacheLevel getPlaceholderCacheLevel() { + return PlaceholderCacheLevel.getCache(getPlaceholderCacheLevelString()); + } + + @Override + public void loadValues() { + new AnnotationHandler().load(getData(), this); + } + + @Override + public void onFileCreation() { + getPlugin().saveResource("Config.yml", true); + } + +} 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 3c0f70f5ee..93d5685e26 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/ConfigVoteSites.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/ConfigVoteSites.java @@ -1,679 +1,674 @@ -package com.bencodez.votingplugin.config; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.concurrent.TimeUnit; - -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; -import org.bukkit.entity.Player; - -import com.bencodez.advancedcore.api.rewards.DirectlyDefinedReward; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.simpleapi.file.YMLFile; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.time.ParsedDuration; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.util.ServiceSiteValidator; -import com.bencodez.votingplugin.votesites.VoteSite; - -// TODO: Auto-generated Javadoc -/** - * The Class ConfigVoteSites. - */ -public class ConfigVoteSites extends YMLFile { - - private VotingPluginMain plugin; - - /** - * Constructs a new ConfigVoteSites. - * - * @param plugin the plugin instance - */ - public ConfigVoteSites(VotingPluginMain plugin) { - super(plugin, new File(plugin.getDataFolder(), "VoteSites.yml")); - setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles()); - this.plugin = plugin; - } - - /** - * Generate vote site. - * - * @param siteName the site name - */ - public void generateVoteSite(String siteName) { - tryGenerateVoteSite(siteName); - } - - /** - * Attempts to generate a vote site. - * - * @param siteName the site name - * @return {@code true} if the site was generated - */ - public boolean tryGenerateVoteSite(String siteName) { - if (plugin.getConfigFile().isAutoCreateVoteSites()) { - if (!ServiceSiteValidator.isValid(siteName)) { - plugin.getLogger().warning("Unable to generate vote site with unsupported name '" - + ServiceSiteValidator.sanitizeForLog(siteName) + "'"); - return false; - } - String org = siteName; - siteName = siteName.replaceAll("[\\.\\s]+", "_"); - - plugin.getLogger().warning("VoteSite " + siteName + " does not exist with the servicesite '" + org - + "', creating one, set AutoCreateVoteSites to false to prevent this"); - setEnabled(siteName, true); - setServiceSite(siteName, org); - setVoteURL(siteName, "VoteURL"); - setVoteDelay(siteName, "24h"); - 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(); - - plugin.addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteSites." + siteName + ".Rewards") { - - @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 + ".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") { - - @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); - } - }); - - for (Player p : Bukkit.getOnlinePlayers()) { - if (p.hasPermission("VotingPlugin.Admin.GenerateServiceSite") || p.isOp()) { - p.sendMessage(MessageAPI.colorize("&cGenerating votesite for service site " + siteName - + ", please check console for details")); - } - } - return true; - } - return false; - } - - /** - * Gets the data. - * - * @param siteName the site name - * @return the data - */ - public ConfigurationSection getData(String siteName) { - if (!getData().isConfigurationSection("VoteSites." + siteName)) { - plugin.getLogger().warning("VoteSites." + siteName + " is not a configuration section"); - } - return getData().getConfigurationSection("VoteSites." + siteName); - } - - /** - * Gets the display name for a site. - * - * @param site the site name - * @return the display name - */ - public String getDisplayName(String site) { - return getData(site).getString("Name"); - } - - /** - * Gets the path to the every site reward. - * - * @return the every site reward path - */ - public String getEverySiteRewardPath() { - return "EverySiteReward"; - } - - /** - * Gets the item configuration for a site. - * - * @param site the site name - * @return the item configuration - */ - public ConfigurationSection getItem(String site) { - if (getData(site).isConfigurationSection("DisplayItem")) { - return getData(site).getConfigurationSection("DisplayItem"); - } - return getData(site).getConfigurationSection("Item"); - } - - /** - * Gets the permission required to view a site. - * - * @param siteName the site name - * @return the permission to view - */ - public String getPermissionToView(String siteName) { - return getData(siteName).getString("PermissionToView", ""); - } - - /** - * Gets the priority. - * - * @param siteName the site name - * @return the priority - */ - public int getPriority(String siteName) { - return getData(siteName).getInt("Priority"); - } - - /** - * Gets the rewards. - * - * @param siteName the site name - * @return the rewards - */ - 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. - * - * @param siteName the site name - * @return the service site - */ - public String getServiceSite(String siteName) { - return getData(siteName).getString("ServiceSite"); - } - - /** - * Gets the vote delay for a site. - * - * @param site the site name - * @return the vote delay - */ - public ParsedDuration getVoteDelay(String site) { - ConfigurationSection sec = getData(site); - - // NEW FORMAT (string) - if (sec.isString("VoteDelay")) { - return ParsedDuration.parse(sec.getString("VoteDelay"), TimeUnit.HOURS); - } - - // LEGACY FORMAT (numbers) - double hours = sec.getDouble("VoteDelay", 0); - double minutes = sec.getDouble("VoteDelayMin", 0); - - long millis = (long) (hours * 60 * 60 * 1000) + (long) (minutes * 60 * 1000); - - return ParsedDuration.ofMillis(millis); - } - - /** - * Gets the vote delay daily hour for a site. - * - * @param siteName the site name - * @return the vote delay daily hour - */ - public int getVoteDelayDailyHour(String siteName) { - return getData(siteName).getInt("VoteDelayDailyHour", 0); - } - - /** - * Gets the vote site enabled. - * - * @param siteName the site name - * @return the vote site enabled - */ - public boolean getVoteSiteEnabled(String siteName) { - return getData(siteName).getBoolean("Enabled"); - } - - /** - * Gets the vote site file. - * - * @param siteName the site name - * @return the vote site file - */ - public File getVoteSiteFile(String siteName) { - File dFile = new File(plugin.getDataFolder() + File.separator + "VoteSites", siteName + ".yml"); - FileConfiguration data = YamlConfiguration.loadConfiguration(dFile); - if (!dFile.exists()) { - try { - data.save(dFile); - } catch (IOException e) { - plugin.getLogger().severe(ChatColor.RED + "Could not create VoteSites/" + siteName + ".yml!"); - - } - } - return dFile; - - } - - /** - * Gets whether to give rewards offline for a site. - * - * @param site the site name - * @return true if rewards should be given offline - */ - public boolean getVoteSiteGiveOffline(String site) { - return getData(site).getBoolean("ForceOffline", getData(site).getBoolean("GiveOffline")); - } - - /** - * Gets whether a site is hidden. - * - * @param siteName the site name - * @return true if the site is hidden - */ - public boolean getVoteSiteHidden(String siteName) { - return getData(siteName).getBoolean("Hidden"); - } - - /** - * Gets whether to ignore can vote check for a site. - * - * @param siteName the site name - * @return true if can vote check should be ignored - */ - public boolean getVoteSiteIgnoreCanVote(String siteName) { - return getData(siteName).getBoolean("IgnoreCanVote"); - } - - /** - * Gets whether vote delay resets daily for a site. - * - * @param siteName the site name - * @return true if vote delay resets daily - */ - public boolean getVoteSiteResetVoteDelayDaily(String siteName) { - return getData(siteName).getBoolean("VoteDelayDaily"); - } - - /** - * Gets the vote sites load. - * - * @return the vote sites load - */ - public ArrayList getVoteSitesLoad() { - ArrayList voteSites = new ArrayList<>(); - ArrayList voteSiteNames = getVoteSitesNames(true); - if (voteSiteNames != null) { - for (String site : voteSiteNames) { - if (getVoteSiteEnabled(site) && !site.equalsIgnoreCase("null")) { - if (!siteCheck(site)) { - plugin.getLogger().warning("Failed to load site " + site + ", see above"); - } else { - VoteSite voteSite = new VoteSite(plugin, site); - plugin.debug(voteSite.loadingDebug()); - voteSites.add(voteSite); - } - } - } - } - - Collections.sort(voteSites, new Comparator() { - @Override - public int compare(VoteSite v1, VoteSite v2) { - int v1P = v1.getPriority(); - int v2P = v2.getPriority(); - - if (v1P < v2P) { - return 1; - } - if (v1P > v2P) { - return -1; - } - - return 0; - } - }); - - return voteSites; - } - - /** - * Gets configured vote-site section keys without filtering by Enabled or - * validating the site's settings. - * - * @return the configured vote-site section keys - */ - public ArrayList getRawVoteSiteNames() { - ArrayList siteNames = new ArrayList<>(); - - if (!getData().isConfigurationSection("VoteSites")) { - return siteNames; - } - - siteNames = ArrayUtils.convert(getData().getConfigurationSection("VoteSites").getKeys(false)); - siteNames.removeIf(siteName -> !getData().isConfigurationSection("VoteSites." + siteName)); - return siteNames; - } - - /** - * Gets the names of vote sites. - * - * @param checkEnabled whether to check if sites are enabled - * @return the list of vote site names - */ - public ArrayList getVoteSitesNames(boolean checkEnabled) { - ArrayList siteNames = new ArrayList<>(); - - if (!getData().isConfigurationSection("VoteSites")) { - return siteNames; - } - - siteNames = ArrayUtils.convert(getData().getConfigurationSection("VoteSites").getKeys(false)); - - for (int i = siteNames.size() - 1; i >= 0; i--) { - String site = siteNames.get(i); - String path = "VoteSites." + site; - - if (!getData().isConfigurationSection(path)) { - plugin.getLogger().warning(path + " is not a configuration section, please remove"); - siteNames.remove(i); - continue; - } - - if (site.equalsIgnoreCase("null") || (!getVoteSiteEnabled(site) && checkEnabled) || !siteCheck(site)) { - siteNames.remove(i); - continue; - } - } - - return siteNames; - } - - /** - * Gets the vote URL. - * - * @param siteName the site name - * @return the vote URL - */ - public String getVoteURL(String siteName) { - return getData(siteName).getString("VoteURL", ""); - } - - /** - * Gets whether to wait until vote delay for a site. - * - * @param siteName the site name - * @return true if should wait until vote delay - */ - public boolean getWaitUntilVoteDelay(String siteName) { - return getData(siteName).getBoolean("WaitUntilVoteDelay", false); - } - - /** - * Checks if is service site good. - * - * @param siteName the site name - * @return true, if is service site good - */ - public boolean isServiceSiteGood(String siteName) { - if (getServiceSite(siteName) == null || getServiceSite(siteName).equals("")) { - return false; - } - return true; - } - - /** - * Checks if is vote URL good. - * - * @param siteName the site name - * @return true, if is vote URL good - */ - public boolean isVoteURLGood(String siteName) { - if (getVoteURL(siteName) == null || getVoteURL(siteName).equals("")) { - return false; - } - return true; - } - - @Override - public void onFileCreation() { - plugin.saveResource("VoteSites.yml", true); - - } - - /** - * Rename vote site. - * - * @param siteName the site name - * @param newName the new name - * @return true, if successful - */ - public boolean renameVoteSite(String siteName, String newName) { - return getVoteSiteFile(siteName) - .renameTo(new File(plugin.getDataFolder() + File.separator + "VoteSites", newName + ".yml")); - } - - /** - * Sets the. - * - * @param siteName the site name - * @param path the path - * @param value the value - */ - public void set(String siteName, String path, Object value) { - // String playerName = user.getPlayerName(); - ConfigurationSection data = getData(siteName); - if (data == null) { - getData().createSection("VoteSites." + siteName); - data = getData(siteName); - } - data.set(path, value); - saveData(); - } - - /** - * Sets the cumulative rewards. - * - * @param siteName the site name - * @param value the value - */ - public void setCumulativeRewards(String siteName, ArrayList value) { - set(siteName, "Cumulative.Rewards", value); - } - - /** - * Sets the cumulative votes for a site. - * - * @param siteName the site name - * @param value the value - */ - public void setCumulativeVotes(String siteName, int value) { - set(siteName, "Cumulative.Votes", value); - } - - /** - * Sets the display name for a site. - * - * @param siteName the site name - * @param value the value - */ - public void setDisplayName(String siteName, String value) { - set(siteName, "Name", value); - } - - /** - * Sets the enabled. - * - * @param siteName the site name - * @param disabled the disabled - */ - public void setEnabled(String siteName, boolean disabled) { - set(siteName, "Enabled", disabled); - } - - /** - * Sets whether to force offline for a site. - * - * @param siteName the site name - * @param value the value - */ - public void setForceOffline(String siteName, boolean value) { - set(siteName, "ForceOffline", value); - - } - - /** - * Sets the priority. - * - * @param siteName the site name - * @param value the value - */ - public void setPriority(String siteName, int value) { - set(siteName, "Priority", value); - } - - /** - * Sets the rewards. - * - * @param siteName the site name - * @param value the value - */ - public void setRewards(String siteName, ArrayList value) { - set(siteName, "Rewards", value); - } - - /** - * Sets the service site. - * - * @param siteName the site name - * @param serviceSite the service site - */ - public void setServiceSite(String siteName, String serviceSite) { - set(siteName, "ServiceSite", serviceSite); - } - - /** - * Sets the vote delay. - * - * @param siteName the site name - * @param voteDelay the vote delay - */ - public void setVoteDelay(String siteName, String voteDelay) { - set(siteName, "VoteDelay", voteDelay); - } - - /** - * Sets the vote URL. - * - * @param siteName the site name - * @param url the url - */ - public void setVoteURL(String siteName, String url) { - set(siteName, "VoteURL", url); - } - - /** - * Site check. - * - * @param siteName the site name - * @return true, if successful - */ - public boolean siteCheck(String siteName) { - boolean pass = true; - if (!isServiceSiteGood(siteName)) { - plugin.getLogger().warning("Issue with ServiceSite in site " + siteName + ", votes may not work properly"); - pass = false; - } - if (!isVoteURLGood(siteName)) { - plugin.getLogger().warning("Issue with VoteURL in site " + siteName); - } - return pass; - } - - /** - * Sets the vote delay daily hour for a site. - * - * @param siteName the site name - * @param intValue the value - */ - public void setVoteDelayDailyHour(String siteName, int intValue) { - set(siteName, "VoteDelayDailyHour", intValue); - } - - /** - * Sets whether vote delay is daily for a site. - * - * @param siteName the site name - * @param value the value - */ - public void setVoteDelayDaily(String siteName, boolean value) { - set(siteName, "VoteDelayDaily", value); - } - -} +package com.bencodez.votingplugin.config; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.concurrent.TimeUnit; + +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; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.rewards.DirectlyDefinedReward; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.simpleapi.file.YMLFile; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.simpleapi.time.ParsedDuration; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.util.ServiceSiteValidator; +import com.bencodez.votingplugin.votesites.VoteSite; +public class ConfigVoteSites extends YMLFile { + + private VotingPluginMain plugin; + + /** + * Constructs a new ConfigVoteSites. + * + * @param plugin the plugin instance + */ + public ConfigVoteSites(VotingPluginMain plugin) { + super(plugin, new File(plugin.getDataFolder(), "VoteSites.yml")); + setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles()); + this.plugin = plugin; + } + + /** + * Generate vote site. + * + * @param siteName the site name + */ + public void generateVoteSite(String siteName) { + tryGenerateVoteSite(siteName); + } + + /** + * Attempts to generate a vote site. + * + * @param siteName the site name + * @return {@code true} if the site was generated + */ + public boolean tryGenerateVoteSite(String siteName) { + if (plugin.getConfigFile().isAutoCreateVoteSites()) { + if (!ServiceSiteValidator.isValid(siteName)) { + plugin.getLogger().warning("Unable to generate vote site with unsupported name '" + + ServiceSiteValidator.sanitizeForLog(siteName) + "'"); + return false; + } + String org = siteName; + siteName = siteName.replaceAll("[\\.\\s]+", "_"); + + plugin.getLogger().warning("VoteSite " + siteName + " does not exist with the servicesite '" + org + + "', creating one, set AutoCreateVoteSites to false to prevent this"); + setEnabled(siteName, true); + setServiceSite(siteName, org); + setVoteURL(siteName, "VoteURL"); + setVoteDelay(siteName, "24h"); + 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(); + + plugin.addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteSites." + siteName + ".Rewards") { + + @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 + ".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") { + + @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); + } + }); + + for (Player p : Bukkit.getOnlinePlayers()) { + if (p.hasPermission("VotingPlugin.Admin.GenerateServiceSite") || p.isOp()) { + p.sendMessage(MessageAPI.colorize("&cGenerating votesite for service site " + siteName + + ", please check console for details")); + } + } + return true; + } + return false; + } + + /** + * Gets the data. + * + * @param siteName the site name + * @return the data + */ + public ConfigurationSection getData(String siteName) { + if (!getData().isConfigurationSection("VoteSites." + siteName)) { + plugin.getLogger().warning("VoteSites." + siteName + " is not a configuration section"); + } + return getData().getConfigurationSection("VoteSites." + siteName); + } + + /** + * Gets the display name for a site. + * + * @param site the site name + * @return the display name + */ + public String getDisplayName(String site) { + return getData(site).getString("Name"); + } + + /** + * Gets the path to the every site reward. + * + * @return the every site reward path + */ + public String getEverySiteRewardPath() { + return "EverySiteReward"; + } + + /** + * Gets the item configuration for a site. + * + * @param site the site name + * @return the item configuration + */ + public ConfigurationSection getItem(String site) { + if (getData(site).isConfigurationSection("DisplayItem")) { + return getData(site).getConfigurationSection("DisplayItem"); + } + return getData(site).getConfigurationSection("Item"); + } + + /** + * Gets the permission required to view a site. + * + * @param siteName the site name + * @return the permission to view + */ + public String getPermissionToView(String siteName) { + return getData(siteName).getString("PermissionToView", ""); + } + + /** + * Gets the priority. + * + * @param siteName the site name + * @return the priority + */ + public int getPriority(String siteName) { + return getData(siteName).getInt("Priority"); + } + + /** + * Gets the rewards. + * + * @param siteName the site name + * @return the rewards + */ + 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. + * + * @param siteName the site name + * @return the service site + */ + public String getServiceSite(String siteName) { + return getData(siteName).getString("ServiceSite"); + } + + /** + * Gets the vote delay for a site. + * + * @param site the site name + * @return the vote delay + */ + public ParsedDuration getVoteDelay(String site) { + ConfigurationSection sec = getData(site); + + // NEW FORMAT (string) + if (sec.isString("VoteDelay")) { + return ParsedDuration.parse(sec.getString("VoteDelay"), TimeUnit.HOURS); + } + + // LEGACY FORMAT (numbers) + double hours = sec.getDouble("VoteDelay", 0); + double minutes = sec.getDouble("VoteDelayMin", 0); + + long millis = (long) (hours * 60 * 60 * 1000) + (long) (minutes * 60 * 1000); + + return ParsedDuration.ofMillis(millis); + } + + /** + * Gets the vote delay daily hour for a site. + * + * @param siteName the site name + * @return the vote delay daily hour + */ + public int getVoteDelayDailyHour(String siteName) { + return getData(siteName).getInt("VoteDelayDailyHour", 0); + } + + /** + * Gets the vote site enabled. + * + * @param siteName the site name + * @return the vote site enabled + */ + public boolean getVoteSiteEnabled(String siteName) { + return getData(siteName).getBoolean("Enabled"); + } + + /** + * Gets the vote site file. + * + * @param siteName the site name + * @return the vote site file + */ + public File getVoteSiteFile(String siteName) { + File dFile = new File(plugin.getDataFolder() + File.separator + "VoteSites", siteName + ".yml"); + FileConfiguration data = YamlConfiguration.loadConfiguration(dFile); + if (!dFile.exists()) { + try { + data.save(dFile); + } catch (IOException e) { + plugin.getLogger().severe(ChatColor.RED + "Could not create VoteSites/" + siteName + ".yml!"); + + } + } + return dFile; + + } + + /** + * Gets whether to give rewards offline for a site. + * + * @param site the site name + * @return true if rewards should be given offline + */ + public boolean getVoteSiteGiveOffline(String site) { + return getData(site).getBoolean("ForceOffline", getData(site).getBoolean("GiveOffline")); + } + + /** + * Gets whether a site is hidden. + * + * @param siteName the site name + * @return true if the site is hidden + */ + public boolean getVoteSiteHidden(String siteName) { + return getData(siteName).getBoolean("Hidden"); + } + + /** + * Gets whether to ignore can vote check for a site. + * + * @param siteName the site name + * @return true if can vote check should be ignored + */ + public boolean getVoteSiteIgnoreCanVote(String siteName) { + return getData(siteName).getBoolean("IgnoreCanVote"); + } + + /** + * Gets whether vote delay resets daily for a site. + * + * @param siteName the site name + * @return true if vote delay resets daily + */ + public boolean getVoteSiteResetVoteDelayDaily(String siteName) { + return getData(siteName).getBoolean("VoteDelayDaily"); + } + + /** + * Gets the vote sites load. + * + * @return the vote sites load + */ + public ArrayList getVoteSitesLoad() { + ArrayList voteSites = new ArrayList<>(); + ArrayList voteSiteNames = getVoteSitesNames(true); + if (voteSiteNames != null) { + for (String site : voteSiteNames) { + if (getVoteSiteEnabled(site) && !site.equalsIgnoreCase("null")) { + if (!siteCheck(site)) { + plugin.getLogger().warning("Failed to load site " + site + ", see above"); + } else { + VoteSite voteSite = new VoteSite(plugin, site); + plugin.debug(voteSite.loadingDebug()); + voteSites.add(voteSite); + } + } + } + } + + Collections.sort(voteSites, new Comparator() { + @Override + public int compare(VoteSite v1, VoteSite v2) { + int v1P = v1.getPriority(); + int v2P = v2.getPriority(); + + if (v1P < v2P) { + return 1; + } + if (v1P > v2P) { + return -1; + } + + return 0; + } + }); + + return voteSites; + } + + /** + * Gets configured vote-site section keys without filtering by Enabled or + * validating the site's settings. + * + * @return the configured vote-site section keys + */ + public ArrayList getRawVoteSiteNames() { + ArrayList siteNames = new ArrayList<>(); + + if (!getData().isConfigurationSection("VoteSites")) { + return siteNames; + } + + siteNames = ArrayUtils.convert(getData().getConfigurationSection("VoteSites").getKeys(false)); + siteNames.removeIf(siteName -> !getData().isConfigurationSection("VoteSites." + siteName)); + return siteNames; + } + + /** + * Gets the names of vote sites. + * + * @param checkEnabled whether to check if sites are enabled + * @return the list of vote site names + */ + public ArrayList getVoteSitesNames(boolean checkEnabled) { + ArrayList siteNames = new ArrayList<>(); + + if (!getData().isConfigurationSection("VoteSites")) { + return siteNames; + } + + siteNames = ArrayUtils.convert(getData().getConfigurationSection("VoteSites").getKeys(false)); + + for (int i = siteNames.size() - 1; i >= 0; i--) { + String site = siteNames.get(i); + String path = "VoteSites." + site; + + if (!getData().isConfigurationSection(path)) { + plugin.getLogger().warning(path + " is not a configuration section, please remove"); + siteNames.remove(i); + continue; + } + + if (site.equalsIgnoreCase("null") || (!getVoteSiteEnabled(site) && checkEnabled) || !siteCheck(site)) { + siteNames.remove(i); + continue; + } + } + + return siteNames; + } + + /** + * Gets the vote URL. + * + * @param siteName the site name + * @return the vote URL + */ + public String getVoteURL(String siteName) { + return getData(siteName).getString("VoteURL", ""); + } + + /** + * Gets whether to wait until vote delay for a site. + * + * @param siteName the site name + * @return true if should wait until vote delay + */ + public boolean getWaitUntilVoteDelay(String siteName) { + return getData(siteName).getBoolean("WaitUntilVoteDelay", false); + } + + /** + * Checks if is service site good. + * + * @param siteName the site name + * @return true, if is service site good + */ + public boolean isServiceSiteGood(String siteName) { + if (getServiceSite(siteName) == null || getServiceSite(siteName).equals("")) { + return false; + } + return true; + } + + /** + * Checks if is vote URL good. + * + * @param siteName the site name + * @return true, if is vote URL good + */ + public boolean isVoteURLGood(String siteName) { + if (getVoteURL(siteName) == null || getVoteURL(siteName).equals("")) { + return false; + } + return true; + } + + @Override + public void onFileCreation() { + plugin.saveResource("VoteSites.yml", true); + + } + + /** + * Rename vote site. + * + * @param siteName the site name + * @param newName the new name + * @return true, if successful + */ + public boolean renameVoteSite(String siteName, String newName) { + return getVoteSiteFile(siteName) + .renameTo(new File(plugin.getDataFolder() + File.separator + "VoteSites", newName + ".yml")); + } + + /** + * Sets the. + * + * @param siteName the site name + * @param path the path + * @param value the value + */ + public void set(String siteName, String path, Object value) { + // String playerName = user.getPlayerName(); + ConfigurationSection data = getData(siteName); + if (data == null) { + getData().createSection("VoteSites." + siteName); + data = getData(siteName); + } + data.set(path, value); + saveData(); + } + + /** + * Sets the cumulative rewards. + * + * @param siteName the site name + * @param value the value + */ + public void setCumulativeRewards(String siteName, ArrayList value) { + set(siteName, "Cumulative.Rewards", value); + } + + /** + * Sets the cumulative votes for a site. + * + * @param siteName the site name + * @param value the value + */ + public void setCumulativeVotes(String siteName, int value) { + set(siteName, "Cumulative.Votes", value); + } + + /** + * Sets the display name for a site. + * + * @param siteName the site name + * @param value the value + */ + public void setDisplayName(String siteName, String value) { + set(siteName, "Name", value); + } + + /** + * Sets the enabled. + * + * @param siteName the site name + * @param disabled the disabled + */ + public void setEnabled(String siteName, boolean disabled) { + set(siteName, "Enabled", disabled); + } + + /** + * Sets whether to force offline for a site. + * + * @param siteName the site name + * @param value the value + */ + public void setForceOffline(String siteName, boolean value) { + set(siteName, "ForceOffline", value); + + } + + /** + * Sets the priority. + * + * @param siteName the site name + * @param value the value + */ + public void setPriority(String siteName, int value) { + set(siteName, "Priority", value); + } + + /** + * Sets the rewards. + * + * @param siteName the site name + * @param value the value + */ + public void setRewards(String siteName, ArrayList value) { + set(siteName, "Rewards", value); + } + + /** + * Sets the service site. + * + * @param siteName the site name + * @param serviceSite the service site + */ + public void setServiceSite(String siteName, String serviceSite) { + set(siteName, "ServiceSite", serviceSite); + } + + /** + * Sets the vote delay. + * + * @param siteName the site name + * @param voteDelay the vote delay + */ + public void setVoteDelay(String siteName, String voteDelay) { + set(siteName, "VoteDelay", voteDelay); + } + + /** + * Sets the vote URL. + * + * @param siteName the site name + * @param url the url + */ + public void setVoteURL(String siteName, String url) { + set(siteName, "VoteURL", url); + } + + /** + * Site check. + * + * @param siteName the site name + * @return true, if successful + */ + public boolean siteCheck(String siteName) { + boolean pass = true; + if (!isServiceSiteGood(siteName)) { + plugin.getLogger().warning("Issue with ServiceSite in site " + siteName + ", votes may not work properly"); + pass = false; + } + if (!isVoteURLGood(siteName)) { + plugin.getLogger().warning("Issue with VoteURL in site " + siteName); + } + return pass; + } + + /** + * Sets the vote delay daily hour for a site. + * + * @param siteName the site name + * @param intValue the value + */ + public void setVoteDelayDailyHour(String siteName, int intValue) { + set(siteName, "VoteDelayDailyHour", intValue); + } + + /** + * Sets whether vote delay is daily for a site. + * + * @param siteName the site name + * @param value the value + */ + public void setVoteDelayDaily(String siteName, boolean value) { + set(siteName, "VoteDelayDaily", value); + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/data/ServerData.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/data/ServerData.java index f4183c0687..ca9c74b6a6 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/data/ServerData.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/data/ServerData.java @@ -1,560 +1,555 @@ -package com.bencodez.votingplugin.data; - -import java.time.temporal.WeekFields; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; - -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.signs.SignHandler; -import com.bencodez.votingplugin.timequeue.VoteTimeQueue; -import com.bencodez.votingplugin.topvoter.TopVoter; - -// TODO: Auto-generated Javadoc -/** - * The Class ServerData. - */ -public class ServerData { - - private VotingPluginMain plugin = VotingPluginMain.plugin; - - /** - * Constructs a new ServerData. - * - * @param plugin the main plugin instance - */ - public ServerData(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * Adds an auto-cached placeholder. - * - * @param placeholder the placeholder to add - */ - public void addAutoCachedPlaceholder(String placeholder) { - List p = getAutoCachedPlaceholder(); - - if (!ArrayUtils.containsIgnoreCase(p, placeholder)) { - p.add(placeholder); - setAutoCachedPlaceholder(p); - } - } - - /** - * Adds a service site to the list. - * - * @param site the service site to add - */ - public synchronized void addServiceSite(String site) { - ArrayList l = getServiceSites(); - if (!getServiceSites().contains(site)) { - l.add(site); - } - setServiceSites(ArrayUtils.removeDuplicates(l)); - } - - /** - * Adds the sign. - * - * @param location the location - * @param data the data - * @param position the position - */ - public void addSign(Location location, String data, int position) { - - int count = nextSignNumber(); - - getData().set("Signs." + count + ".World", location.getWorld().getName()); - getData().set("Signs." + count + ".X", location.getBlockX()); - getData().set("Signs." + count + ".Y", location.getBlockY()); - getData().set("Signs." + count + ".Z", location.getBlockZ()); - getData().set("Signs." + count + ".Data", data); - getData().set("Signs." + count + ".Position", position); - saveData(); - plugin.getSigns().getSigns().add(new SignHandler(plugin, "" + count, getSignLocation("" + count), - getSignSkullLocation("" + count), getSignData("" + count), getSignPosition("" + count))); - } - - /** - * Adds a timed vote to the cache. - * - * @param num the vote number - * @param vote the vote time queue entry - */ - public void addTimeVoted(int num, VoteTimeQueue vote) { - getData().set("TimedVoteCache." + num + ".Name", vote.getName()); - getData().set("TimedVoteCache." + num + ".Service", vote.getService()); - getData().set("TimedVoteCache." + num + ".Time", vote.getTime()); - saveData(); - } - - /** - * Adds a vote shop purchase for the specified identifier. - * - * @param ident the vote shop identifier - */ - public void addVoteShopPurchase(String ident) { - setVoteShopPurchases(ident, (getVoteShopPurchases(ident) + 1)); - } - - /** - * Clears the timed vote cache. - */ - public void clearTimedVoteCache() { - getData().set("TimedVoteCache", null); - saveData(); - } - - /** - * Gets the auto cached placeholders. - * - * @return the auto cached placeholder list - */ - public List getAutoCachedPlaceholder() { - return getData().getStringList("AutoCachePlaceholders"); - } - - /** - * Gets the current bungee vote party count. - * - * @return the bungee vote party current count - */ - public int getBungeeVotePartyCurrent() { - return getData().getInt("BungeeVotePartyCurrent"); - } - - /** - * Gets the required votes for bungee vote party. - * - * @return the bungee vote party required votes - */ - public int getBungeeVotePartyRequired() { - return getData().getInt("BungeeVotePartyRequired"); - } - - /** - * Gets the data. - * - * @return the data - */ - public ConfigurationSection getData() { - ConfigurationSection data = plugin.getServerDataFile().getData().getConfigurationSection("VotingPlugin"); - if (data == null) { - plugin.getServerDataFile().getData().createSection("VotingPlugin"); - data = plugin.getServerDataFile().getData().getConfigurationSection("VotingPlugin"); - } - return data; - } - - /** - * Gets the list of disabled reminders. - * - * @return the disabled reminders - */ - public List getDisabledReminders() { - return getData().getStringList("DisabledReminders"); - } - - /** - * Gets the service sites list. - * - * @return the service sites - */ - @SuppressWarnings("unchecked") - public ArrayList getServiceSites() { - return (ArrayList) getData().getList("GottenServiceSites", new ArrayList<>()); - } - - /** - * Gets the sign data. - * - * @param sign the sign - * @return the sign data - */ - public String getSignData(String sign) { - return getData().getString("Signs." + sign + ".Data"); - } - - /** - * Gets the sign location. - * - * @param sign the sign - * @return the sign location - */ - public Location getSignLocation(String sign) { - return new Location(Bukkit.getWorld(getData().getString("Signs." + sign + ".World")), - getData().getDouble("Signs." + sign + ".X"), getData().getDouble("Signs." + sign + ".Y"), - getData().getDouble("Signs." + sign + ".Z")); - } - - /** - * Gets the sign position. - * - * @param sign the sign - * @return the sign position - */ - public int getSignPosition(String sign) { - return getData().getInt("Signs." + sign + ".Position"); - } - - /** - * Gets the signs. - * - * @return the signs - */ - public Set getSigns() { - try { - return getData().getConfigurationSection("Signs").getKeys(false); - } catch (Exception ex) { - return new HashSet<>(); - } - } - - /** - * Gets the sign location. - * - * @param sign the sign - * @return the sign location - */ - public Location getSignSkullLocation(String sign) { - if (getData().getString("Signs." + sign + ".Skull.World", "").isEmpty()) { - return null; - } - return new Location(Bukkit.getWorld(getData().getString("Signs." + sign + ".Skull.World")), - getData().getDouble("Signs." + sign + ".Skull.X"), getData().getDouble("Signs." + sign + ".Skull.Y"), - getData().getDouble("Signs." + sign + ".Skull.Z")); - } - - /** - * Gets the timed vote cache keys. - * - * @return the timed vote cache keys - */ - public Set getTimedVoteCacheKeys() { - if (getData().isConfigurationSection("TimedVoteCache")) { - return getData().getConfigurationSection("TimedVoteCache").getKeys(false); - } - return new HashSet<>(); - } - - /** - * Gets the timed vote cache section for the given number. - * - * @param num the cache entry number - * @return the timed vote cache section - */ - public ConfigurationSection getTimedVoteCacheSection(String num) { - return getData().getConfigurationSection("TimedVoteCache." + num); - } - - /** - * Gets the extra required votes for vote party. - * - * @return the vote party extra required votes - */ - public int getVotePartyExtraRequired() { - return getData().getInt("VotePartyExtraRequired", 0); - } - - /** - * Gets the number of purchases for a vote shop item. - * - * @param ident the vote shop identifier - * @return the vote shop purchases - */ - public int getVoteShopPurchases(String ident) { - return getData().getInt("VoteShopPurchases." + ident); - } - - /** - * Checks if the last vote party was on the same day. - * - * @return true if same day - */ - public boolean isLastVotePartySameDay() { - int num = getData().getInt("LastVoteParty", 0); - if (num == plugin.getTimeChecker().getTime().getDayOfYear()) { - return true; - } - return false; - } - - /** - * Checks if the last vote party was in the same week. - * - * @return true if same week - */ - public boolean isLastVotePartySameWeek() { - int num = getData().getInt("LastVotePartyWeek", -1); - if (num == plugin.getTimeChecker().getTime().get(WeekFields.of(Locale.getDefault()).weekOfYear()) - && num != -1) { - return true; - } - return false; - } - - /** - * Checks if the vote shop has been converted. - * - * @return true if converted - */ - public boolean isVoteShopConverted() { - return getData().getBoolean("VoteShopConverted"); - } - - /** - * Next sign number. - * - * @return the int - */ - public int nextSignNumber() { - Set signs = getSigns(); - - if (signs != null) { - for (int i = 0; i < 100000; i++) { - if (!signs.contains(Integer.toString(i))) { - return i; - } - } - } - return 0; - } - - /** - * Reload data. - */ - public void reloadData() { - plugin.getServerDataFile().reloadData(); - } - - /** - * Gets the Discord message ID for the top voter. - * - * @param top the top voter type - * @return the top voter message ID - */ - public long getTopVoterMessageId(TopVoter top) { - return getData().getLong("DiscordSRV.TopVoterMessageId." + top.toString(), 0); - } - - /** - * Sets the Discord message ID for the top voter. - * - * @param top the top voter type - * @param messageId the message ID - */ - public void setTopVoterMessageId(TopVoter top, long messageId) { - getData().set("DiscordSRV.TopVoterMessageId." + top.toString(), messageId); - saveData(); - } - - /** - * Removes the sign. - * - * @param sign the sign - */ - public void removeSign(String sign) { - getData().set("Signs." + sign + ".World", null); - getData().set("Signs." + sign + ".X", null); - getData().set("Signs." + sign + ".Y", null); - getData().set("Signs." + sign + ".Z", null); - getData().set("Signs." + sign + ".Data", null); - getData().set("Signs." + sign + ".Position", null); - getData().set("Signs." + sign, null); - getData().set("Signs." + sign + ".Skull.World", null); - getData().set("Signs." + sign + ".Skull.X", null); - getData().set("Signs." + sign + ".Skull.Y", null); - getData().set("Signs." + sign + ".Skull.Z", null); - saveData(); - } - - /** - * Save data. - */ - public synchronized void saveData() { - plugin.getServerDataFile().saveData(); - } - - /** - * Saves the disabled reminders list. - * - * @param disabledReminders the list of UUIDs with disabled reminders - */ - public void saveDisabledReminders(ArrayList disabledReminders) { - ArrayList uuids = new ArrayList<>(); - for (UUID uuid : disabledReminders) { - uuids.add(uuid.toString()); - } - getData().set("DisabledReminders", uuids); - saveData(); - } - - /** - * Sets the auto cached placeholders. - * - * @param placeholders the list of placeholders - */ - public void setAutoCachedPlaceholder(List placeholders) { - getData().set("AutoCachePlaceholders", placeholders); - saveData(); - } - - /** - * Sets the current bungee vote party count. - * - * @param current the current vote count - */ - public void setBungeeVotePartyCurrent(int current) { - getData().set("BungeeVotePartyCurrent", current); - saveData(); - } - - /** - * Sets the required votes for bungee vote party. - * - * @param required the required vote count - */ - public void setBungeeVotePartyRequired(int required) { - getData().set("BungeeVotePartyRequired", required); - saveData(); - } - - /** - * Sets the service sites list. - * - * @param list the service sites list - */ - public void setServiceSites(ArrayList list) { - getData().set("GottenServiceSites", list); - saveData(); - } - - /** - * Sets the vote shop converted status. - * - * @param value the converted status - */ - public void setShopConverted(boolean value) { - getData().set("VoteShopConverted", value); - saveData(); - } - - /** - * Sets sign data. - * - * @param count the sign count - * @param location the sign location - * @param skullLocation the skull location - * @param data the sign data - * @param position the sign position - */ - public void setSign(String count, Location location, Location skullLocation, String data, int position) { - - getData().set("Signs." + count + ".World", location.getWorld().getName()); - getData().set("Signs." + count + ".X", (int) location.getX()); - getData().set("Signs." + count + ".Y", (int) location.getY()); - getData().set("Signs." + count + ".Z", (int) location.getZ()); - getData().set("Signs." + count + ".Data", data); - getData().set("Signs." + count + ".Position", position); - if (skullLocation != null) { - getData().set("Signs." + count + ".Skull.World", skullLocation.getWorld().getName()); - getData().set("Signs." + count + ".Skull.X", (int) skullLocation.getX()); - getData().set("Signs." + count + ".Skull.Y", (int) skullLocation.getY()); - getData().set("Signs." + count + ".Skull.Z", (int) skullLocation.getZ()); - } - saveData(); - } - - /** - * Sets the skull location for a sign. - * - * @param count the sign count - * @param skullLocation the skull location - */ - public void setSkullLocation(String count, Location skullLocation) { - if (skullLocation != null) { - getData().set("Signs." + count + ".Skull.World", skullLocation.getWorld().getName()); - getData().set("Signs." + count + ".Skull.X", (int) skullLocation.getX()); - getData().set("Signs." + count + ".Skull.Y", (int) skullLocation.getY()); - getData().set("Signs." + count + ".Skull.Z", (int) skullLocation.getZ()); - } - } - - /** - * Sets the version. - */ - public void setVersion() { - getData().set("Version", Bukkit.getVersion()); - saveData(); - } - - /** - * Sets the extra required votes for vote party. - * - * @param value the extra required votes - */ - public void setVotePartyExtraRequired(int value) { - getData().set("VotePartyExtraRequired", value); - saveData(); - } - - /** - * Sets the number of purchases for a vote shop item. - * - * @param ident the vote shop identifier - * @param amount the purchase amount - */ - public void setVoteShopPurchases(String ident, int amount) { - getData().set("VoteShopPurchases." + ident, amount); - saveData(); - } - - /** - * Updates the last vote party timestamp to today. - */ - public void updateLastVoteParty() { - getData().set("LastVoteParty", plugin.getTimeChecker().getTime().getDayOfYear()); - saveData(); - } - - /** - * Updates the last vote party week timestamp to this week. - */ - public void updateLastVotePartyWeek() { - getData().set("LastVotePartyWeek", - plugin.getTimeChecker().getTime().get(WeekFields.of(Locale.getDefault()).weekOfYear())); - saveData(); - } - - /** - * Updates placeholders to lowercase format. - */ - public void updatePlaceholders() { - boolean data = getData().getBoolean("AutoCacheUpdated", false); - if (!data) { - List placeholders = getAutoCachedPlaceholder(); - for (int i = 0; i < placeholders.size(); i++) { - placeholders.set(i, placeholders.get(i).toLowerCase()); - } - setAutoCachedPlaceholder(placeholders); - getData().set("AutoCacheUpdated", true); - saveData(); - } - } - - /** - * Update values. - */ - public void updateValues() { - setVersion(); - } -} +package com.bencodez.votingplugin.data; + +import java.time.temporal.WeekFields; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.signs.SignHandler; +import com.bencodez.votingplugin.timequeue.VoteTimeQueue; +import com.bencodez.votingplugin.topvoter.TopVoter; +public class ServerData { + + private VotingPluginMain plugin = VotingPluginMain.plugin; + + /** + * Constructs a new ServerData. + * + * @param plugin the main plugin instance + */ + public ServerData(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * Adds an auto-cached placeholder. + * + * @param placeholder the placeholder to add + */ + public void addAutoCachedPlaceholder(String placeholder) { + List p = getAutoCachedPlaceholder(); + + if (!ArrayUtils.containsIgnoreCase(p, placeholder)) { + p.add(placeholder); + setAutoCachedPlaceholder(p); + } + } + + /** + * Adds a service site to the list. + * + * @param site the service site to add + */ + public synchronized void addServiceSite(String site) { + ArrayList l = getServiceSites(); + if (!getServiceSites().contains(site)) { + l.add(site); + } + setServiceSites(ArrayUtils.removeDuplicates(l)); + } + + /** + * Adds the sign. + * + * @param location the location + * @param data the data + * @param position the position + */ + public void addSign(Location location, String data, int position) { + + int count = nextSignNumber(); + + getData().set("Signs." + count + ".World", location.getWorld().getName()); + getData().set("Signs." + count + ".X", location.getBlockX()); + getData().set("Signs." + count + ".Y", location.getBlockY()); + getData().set("Signs." + count + ".Z", location.getBlockZ()); + getData().set("Signs." + count + ".Data", data); + getData().set("Signs." + count + ".Position", position); + saveData(); + plugin.getSigns().getSigns().add(new SignHandler(plugin, "" + count, getSignLocation("" + count), + getSignSkullLocation("" + count), getSignData("" + count), getSignPosition("" + count))); + } + + /** + * Adds a timed vote to the cache. + * + * @param num the vote number + * @param vote the vote time queue entry + */ + public void addTimeVoted(int num, VoteTimeQueue vote) { + getData().set("TimedVoteCache." + num + ".Name", vote.getName()); + getData().set("TimedVoteCache." + num + ".Service", vote.getService()); + getData().set("TimedVoteCache." + num + ".Time", vote.getTime()); + saveData(); + } + + /** + * Adds a vote shop purchase for the specified identifier. + * + * @param ident the vote shop identifier + */ + public void addVoteShopPurchase(String ident) { + setVoteShopPurchases(ident, (getVoteShopPurchases(ident) + 1)); + } + + /** + * Clears the timed vote cache. + */ + public void clearTimedVoteCache() { + getData().set("TimedVoteCache", null); + saveData(); + } + + /** + * Gets the auto cached placeholders. + * + * @return the auto cached placeholder list + */ + public List getAutoCachedPlaceholder() { + return getData().getStringList("AutoCachePlaceholders"); + } + + /** + * Gets the current bungee vote party count. + * + * @return the bungee vote party current count + */ + public int getBungeeVotePartyCurrent() { + return getData().getInt("BungeeVotePartyCurrent"); + } + + /** + * Gets the required votes for bungee vote party. + * + * @return the bungee vote party required votes + */ + public int getBungeeVotePartyRequired() { + return getData().getInt("BungeeVotePartyRequired"); + } + + /** + * Gets the data. + * + * @return the data + */ + public ConfigurationSection getData() { + ConfigurationSection data = plugin.getServerDataFile().getData().getConfigurationSection("VotingPlugin"); + if (data == null) { + plugin.getServerDataFile().getData().createSection("VotingPlugin"); + data = plugin.getServerDataFile().getData().getConfigurationSection("VotingPlugin"); + } + return data; + } + + /** + * Gets the list of disabled reminders. + * + * @return the disabled reminders + */ + public List getDisabledReminders() { + return getData().getStringList("DisabledReminders"); + } + + /** + * Gets the service sites list. + * + * @return the service sites + */ + @SuppressWarnings("unchecked") + public ArrayList getServiceSites() { + return (ArrayList) getData().getList("GottenServiceSites", new ArrayList<>()); + } + + /** + * Gets the sign data. + * + * @param sign the sign + * @return the sign data + */ + public String getSignData(String sign) { + return getData().getString("Signs." + sign + ".Data"); + } + + /** + * Gets the sign location. + * + * @param sign the sign + * @return the sign location + */ + public Location getSignLocation(String sign) { + return new Location(Bukkit.getWorld(getData().getString("Signs." + sign + ".World")), + getData().getDouble("Signs." + sign + ".X"), getData().getDouble("Signs." + sign + ".Y"), + getData().getDouble("Signs." + sign + ".Z")); + } + + /** + * Gets the sign position. + * + * @param sign the sign + * @return the sign position + */ + public int getSignPosition(String sign) { + return getData().getInt("Signs." + sign + ".Position"); + } + + /** + * Gets the signs. + * + * @return the signs + */ + public Set getSigns() { + try { + return getData().getConfigurationSection("Signs").getKeys(false); + } catch (Exception ex) { + return new HashSet<>(); + } + } + + /** + * Gets the sign location. + * + * @param sign the sign + * @return the sign location + */ + public Location getSignSkullLocation(String sign) { + if (getData().getString("Signs." + sign + ".Skull.World", "").isEmpty()) { + return null; + } + return new Location(Bukkit.getWorld(getData().getString("Signs." + sign + ".Skull.World")), + getData().getDouble("Signs." + sign + ".Skull.X"), getData().getDouble("Signs." + sign + ".Skull.Y"), + getData().getDouble("Signs." + sign + ".Skull.Z")); + } + + /** + * Gets the timed vote cache keys. + * + * @return the timed vote cache keys + */ + public Set getTimedVoteCacheKeys() { + if (getData().isConfigurationSection("TimedVoteCache")) { + return getData().getConfigurationSection("TimedVoteCache").getKeys(false); + } + return new HashSet<>(); + } + + /** + * Gets the timed vote cache section for the given number. + * + * @param num the cache entry number + * @return the timed vote cache section + */ + public ConfigurationSection getTimedVoteCacheSection(String num) { + return getData().getConfigurationSection("TimedVoteCache." + num); + } + + /** + * Gets the extra required votes for vote party. + * + * @return the vote party extra required votes + */ + public int getVotePartyExtraRequired() { + return getData().getInt("VotePartyExtraRequired", 0); + } + + /** + * Gets the number of purchases for a vote shop item. + * + * @param ident the vote shop identifier + * @return the vote shop purchases + */ + public int getVoteShopPurchases(String ident) { + return getData().getInt("VoteShopPurchases." + ident); + } + + /** + * Checks if the last vote party was on the same day. + * + * @return true if same day + */ + public boolean isLastVotePartySameDay() { + int num = getData().getInt("LastVoteParty", 0); + if (num == plugin.getTimeChecker().getTime().getDayOfYear()) { + return true; + } + return false; + } + + /** + * Checks if the last vote party was in the same week. + * + * @return true if same week + */ + public boolean isLastVotePartySameWeek() { + int num = getData().getInt("LastVotePartyWeek", -1); + if (num == plugin.getTimeChecker().getTime().get(WeekFields.of(Locale.getDefault()).weekOfYear()) + && num != -1) { + return true; + } + return false; + } + + /** + * Checks if the vote shop has been converted. + * + * @return true if converted + */ + public boolean isVoteShopConverted() { + return getData().getBoolean("VoteShopConverted"); + } + + /** + * Next sign number. + * + * @return the int + */ + public int nextSignNumber() { + Set signs = getSigns(); + + if (signs != null) { + for (int i = 0; i < 100000; i++) { + if (!signs.contains(Integer.toString(i))) { + return i; + } + } + } + return 0; + } + + /** + * Reload data. + */ + public void reloadData() { + plugin.getServerDataFile().reloadData(); + } + + /** + * Gets the Discord message ID for the top voter. + * + * @param top the top voter type + * @return the top voter message ID + */ + public long getTopVoterMessageId(TopVoter top) { + return getData().getLong("DiscordSRV.TopVoterMessageId." + top.toString(), 0); + } + + /** + * Sets the Discord message ID for the top voter. + * + * @param top the top voter type + * @param messageId the message ID + */ + public void setTopVoterMessageId(TopVoter top, long messageId) { + getData().set("DiscordSRV.TopVoterMessageId." + top.toString(), messageId); + saveData(); + } + + /** + * Removes the sign. + * + * @param sign the sign + */ + public void removeSign(String sign) { + getData().set("Signs." + sign + ".World", null); + getData().set("Signs." + sign + ".X", null); + getData().set("Signs." + sign + ".Y", null); + getData().set("Signs." + sign + ".Z", null); + getData().set("Signs." + sign + ".Data", null); + getData().set("Signs." + sign + ".Position", null); + getData().set("Signs." + sign, null); + getData().set("Signs." + sign + ".Skull.World", null); + getData().set("Signs." + sign + ".Skull.X", null); + getData().set("Signs." + sign + ".Skull.Y", null); + getData().set("Signs." + sign + ".Skull.Z", null); + saveData(); + } + + /** + * Save data. + */ + public synchronized void saveData() { + plugin.getServerDataFile().saveData(); + } + + /** + * Saves the disabled reminders list. + * + * @param disabledReminders the list of UUIDs with disabled reminders + */ + public void saveDisabledReminders(ArrayList disabledReminders) { + ArrayList uuids = new ArrayList<>(); + for (UUID uuid : disabledReminders) { + uuids.add(uuid.toString()); + } + getData().set("DisabledReminders", uuids); + saveData(); + } + + /** + * Sets the auto cached placeholders. + * + * @param placeholders the list of placeholders + */ + public void setAutoCachedPlaceholder(List placeholders) { + getData().set("AutoCachePlaceholders", placeholders); + saveData(); + } + + /** + * Sets the current bungee vote party count. + * + * @param current the current vote count + */ + public void setBungeeVotePartyCurrent(int current) { + getData().set("BungeeVotePartyCurrent", current); + saveData(); + } + + /** + * Sets the required votes for bungee vote party. + * + * @param required the required vote count + */ + public void setBungeeVotePartyRequired(int required) { + getData().set("BungeeVotePartyRequired", required); + saveData(); + } + + /** + * Sets the service sites list. + * + * @param list the service sites list + */ + public void setServiceSites(ArrayList list) { + getData().set("GottenServiceSites", list); + saveData(); + } + + /** + * Sets the vote shop converted status. + * + * @param value the converted status + */ + public void setShopConverted(boolean value) { + getData().set("VoteShopConverted", value); + saveData(); + } + + /** + * Sets sign data. + * + * @param count the sign count + * @param location the sign location + * @param skullLocation the skull location + * @param data the sign data + * @param position the sign position + */ + public void setSign(String count, Location location, Location skullLocation, String data, int position) { + + getData().set("Signs." + count + ".World", location.getWorld().getName()); + getData().set("Signs." + count + ".X", (int) location.getX()); + getData().set("Signs." + count + ".Y", (int) location.getY()); + getData().set("Signs." + count + ".Z", (int) location.getZ()); + getData().set("Signs." + count + ".Data", data); + getData().set("Signs." + count + ".Position", position); + if (skullLocation != null) { + getData().set("Signs." + count + ".Skull.World", skullLocation.getWorld().getName()); + getData().set("Signs." + count + ".Skull.X", (int) skullLocation.getX()); + getData().set("Signs." + count + ".Skull.Y", (int) skullLocation.getY()); + getData().set("Signs." + count + ".Skull.Z", (int) skullLocation.getZ()); + } + saveData(); + } + + /** + * Sets the skull location for a sign. + * + * @param count the sign count + * @param skullLocation the skull location + */ + public void setSkullLocation(String count, Location skullLocation) { + if (skullLocation != null) { + getData().set("Signs." + count + ".Skull.World", skullLocation.getWorld().getName()); + getData().set("Signs." + count + ".Skull.X", (int) skullLocation.getX()); + getData().set("Signs." + count + ".Skull.Y", (int) skullLocation.getY()); + getData().set("Signs." + count + ".Skull.Z", (int) skullLocation.getZ()); + } + } + + /** + * Sets the version. + */ + public void setVersion() { + getData().set("Version", Bukkit.getVersion()); + saveData(); + } + + /** + * Sets the extra required votes for vote party. + * + * @param value the extra required votes + */ + public void setVotePartyExtraRequired(int value) { + getData().set("VotePartyExtraRequired", value); + saveData(); + } + + /** + * Sets the number of purchases for a vote shop item. + * + * @param ident the vote shop identifier + * @param amount the purchase amount + */ + public void setVoteShopPurchases(String ident, int amount) { + getData().set("VoteShopPurchases." + ident, amount); + saveData(); + } + + /** + * Updates the last vote party timestamp to today. + */ + public void updateLastVoteParty() { + getData().set("LastVoteParty", plugin.getTimeChecker().getTime().getDayOfYear()); + saveData(); + } + + /** + * Updates the last vote party week timestamp to this week. + */ + public void updateLastVotePartyWeek() { + getData().set("LastVotePartyWeek", + plugin.getTimeChecker().getTime().get(WeekFields.of(Locale.getDefault()).weekOfYear())); + saveData(); + } + + /** + * Updates placeholders to lowercase format. + */ + public void updatePlaceholders() { + boolean data = getData().getBoolean("AutoCacheUpdated", false); + if (!data) { + List placeholders = getAutoCachedPlaceholder(); + for (int i = 0; i < placeholders.size(); i++) { + placeholders.set(i, placeholders.get(i).toLowerCase()); + } + setAutoCachedPlaceholder(placeholders); + getData().set("AutoCacheUpdated", true); + saveData(); + } + } + + /** + * Update values. + */ + public void updateValues() { + setVersion(); + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerPostVoteEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerPostVoteEvent.java index 7379cd196d..288db71051 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerPostVoteEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerPostVoteEvent.java @@ -1,123 +1,112 @@ -package com.bencodez.votingplugin.events; - -import java.util.UUID; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class PlayerVoteEvent. - */ -public class PlayerPostVoteEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean bungee = false; - - @Getter - @Setter - private VoteTotalsSnapshot bungeeTextTotals; - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private boolean forceBungee = false; - - @Getter - @Setter - private VotingPluginUser user; - - @Getter - @Setter - private boolean realVote = true; - - @Getter - @Setter - private VoteSite voteSite; - - @Getter - @Setter - private long voteTime = 0; - - @Getter - @Setter - private boolean cached; - - @Getter - @Setter - private String service; - - @Getter - @Setter - private UUID uuid; - @Getter - @Setter - private String playerName; - - @Getter - @Setter - private UUID voteUUID; - - /** - * Constructs a new PlayerPostVoteEvent. - * - * @param voteSite the vote site - * @param user the voting plugin user - * @param realVote whether this is a real vote - * @param forceBungee whether to force Bungee processing - * @param voteTime the vote timestamp - * @param cached whether the vote was cached - * @param service the service name - * @param uuid the player UUID - * @param playerName the player name - * @param voteUUID the vote UUID - */ - public PlayerPostVoteEvent(VoteSite voteSite, VotingPluginUser user, boolean realVote, boolean forceBungee, - long voteTime, boolean cached, String service, UUID uuid, String playerName, UUID voteUUID) { - super(true); - this.user = user; - this.voteSite = voteSite; - this.realVote = realVote; - this.forceBungee = forceBungee; - this.voteTime = voteTime; - this.cached = cached; - this.service = service; - this.uuid = uuid; - this.playerName = playerName; - this.voteUUID = voteUUID; - } - - /* - * (non-Javadoc) - * - * @see org.bukkit.event.Event#getHandlers() - */ - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import java.util.UUID; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +import lombok.Getter; +import lombok.Setter; +public class PlayerPostVoteEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean bungee = false; + + @Getter + @Setter + private VoteTotalsSnapshot bungeeTextTotals; + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private boolean forceBungee = false; + + @Getter + @Setter + private VotingPluginUser user; + + @Getter + @Setter + private boolean realVote = true; + + @Getter + @Setter + private VoteSite voteSite; + + @Getter + @Setter + private long voteTime = 0; + + @Getter + @Setter + private boolean cached; + + @Getter + @Setter + private String service; + + @Getter + @Setter + private UUID uuid; + @Getter + @Setter + private String playerName; + + @Getter + @Setter + private UUID voteUUID; + + /** + * Constructs a new PlayerPostVoteEvent. + * + * @param voteSite the vote site + * @param user the voting plugin user + * @param realVote whether this is a real vote + * @param forceBungee whether to force Bungee processing + * @param voteTime the vote timestamp + * @param cached whether the vote was cached + * @param service the service name + * @param uuid the player UUID + * @param playerName the player name + * @param voteUUID the vote UUID + */ + public PlayerPostVoteEvent(VoteSite voteSite, VotingPluginUser user, boolean realVote, boolean forceBungee, + long voteTime, boolean cached, String service, UUID uuid, String playerName, UUID voteUUID) { + super(true); + this.user = user; + this.voteSite = voteSite; + this.realVote = realVote; + this.forceBungee = forceBungee; + this.voteTime = voteTime; + this.cached = cached; + this.service = service; + this.uuid = uuid; + this.playerName = playerName; + this.voteUUID = voteUUID; + } + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerReceivePointsEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerReceivePointsEvent.java index 42e1284b31..96443aef81 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerReceivePointsEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerReceivePointsEvent.java @@ -1,67 +1,56 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.user.VotingPluginUser; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class PlayerVoteEvent. - */ -public class PlayerReceivePointsEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private VotingPluginUser player; - - @Getter - @Setter - private int points; - - @Getter - @Setter - private String serviceSite = ""; - - /** - * Constructs a new PlayerReceivePointsEvent. - * - * @param user the voting plugin user - * @param points the points received - */ - public PlayerReceivePointsEvent(VotingPluginUser user, int points) { - super(true); - this.player = user; - this.points = points; - } - - /* - * (non-Javadoc) - * - * @see org.bukkit.event.Event#getHandlers() - */ - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.user.VotingPluginUser; + +import lombok.Getter; +import lombok.Setter; +public class PlayerReceivePointsEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private VotingPluginUser player; + + @Getter + @Setter + private int points; + + @Getter + @Setter + private String serviceSite = ""; + + /** + * Constructs a new PlayerReceivePointsEvent. + * + * @param user the voting plugin user + * @param points the points received + */ + public PlayerReceivePointsEvent(VotingPluginUser user, int points) { + super(true); + this.player = user; + this.points = points; + } + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerSpecialRewardEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerSpecialRewardEvent.java index d39b80d4cd..b2690f3076 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerSpecialRewardEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerSpecialRewardEvent.java @@ -1,71 +1,60 @@ -package com.bencodez.votingplugin.events; - -import java.util.UUID; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.user.VotingPluginUser; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class PlayerVoteEvent. - */ -public class PlayerSpecialRewardEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private SpecialRewardType type; - - @Getter - @Setter - private VotingPluginUser user; - - @Getter - @Setter - private UUID voteUUID; - - /** - * Constructs a new PlayerSpecialRewardEvent. - * - * @param user the voting plugin user - * @param type the special reward type - * @param voteUUID the vote UUID - */ - public PlayerSpecialRewardEvent(VotingPluginUser user, SpecialRewardType type, UUID voteUUID) { - super(true); - this.type = type; - this.user = user; - this.voteUUID = voteUUID; - } - - /* - * (non-Javadoc) - * - * @see org.bukkit.event.Event#getHandlers() - */ - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import java.util.UUID; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.user.VotingPluginUser; + +import lombok.Getter; +import lombok.Setter; +public class PlayerSpecialRewardEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private SpecialRewardType type; + + @Getter + @Setter + private VotingPluginUser user; + + @Getter + @Setter + private UUID voteUUID; + + /** + * Constructs a new PlayerSpecialRewardEvent. + * + * @param user the voting plugin user + * @param type the special reward type + * @param voteUUID the vote UUID + */ + public PlayerSpecialRewardEvent(VotingPluginUser user, SpecialRewardType type, UUID voteUUID) { + super(true); + this.type = type; + this.user = user; + this.voteUUID = voteUUID; + } + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteCoolDownEndEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteCoolDownEndEvent.java index d43d06d712..1d7b2505f2 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteCoolDownEndEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteCoolDownEndEvent.java @@ -1,57 +1,46 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.user.VotingPluginUser; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class PlayerVoteEvent. - */ -public class PlayerVoteCoolDownEndEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private VotingPluginUser player; - - /** - * Constructs a new PlayerVoteCoolDownEndEvent. - * - * @param user the voting plugin user - */ - public PlayerVoteCoolDownEndEvent(VotingPluginUser user) { - super(true); - player = user; - } - - /* - * (non-Javadoc) - * - * @see org.bukkit.event.Event#getHandlers() - */ - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.user.VotingPluginUser; + +import lombok.Getter; +import lombok.Setter; +public class PlayerVoteCoolDownEndEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private VotingPluginUser player; + + /** + * Constructs a new PlayerVoteCoolDownEndEvent. + * + * @param user the voting plugin user + */ + public PlayerVoteCoolDownEndEvent(VotingPluginUser user) { + super(true); + player = user; + } + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteEvent.java index 209fa68bba..9606a471c9 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteEvent.java @@ -1,113 +1,102 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class PlayerVoteEvent. - */ -public class PlayerVoteEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean addTotals = true; - - @Getter - @Setter - private boolean bungee = false; - - @Getter - @Setter - private VoteTotalsSnapshot bungeeTextTotals; - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private boolean forceBungee = false; - - @Getter - @Setter - private String player; - - @Getter - @Setter - private boolean realVote = true; - - @Getter - @Setter - private String serviceSite = ""; - - @Getter - @Setter - private long time; - - @Getter - @Setter - private VoteSite voteSite; - - @Getter - @Setter - private VotingPluginUser votingPluginUser; - - @Getter - @Setter - private boolean wasOnline; - - @Getter - @Setter - private boolean broadcast = true; - - @Getter - @Setter - private int voteNumber = 1; - - /** - * Constructs a new PlayerVoteEvent. - * - * @param voteSite the vote site - * @param voteUsername the username of the voter - * @param serviceSite the service site name - * @param realVote whether this is a real vote - */ - public PlayerVoteEvent(VoteSite voteSite, String voteUsername, String serviceSite, boolean realVote) { - super(true); - this.player = voteUsername; - this.voteSite = voteSite; - this.realVote = realVote; - this.serviceSite = serviceSite; - } - - /* - * (non-Javadoc) - * - * @see org.bukkit.event.Event#getHandlers() - */ - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +import lombok.Getter; +import lombok.Setter; +public class PlayerVoteEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean addTotals = true; + + @Getter + @Setter + private boolean bungee = false; + + @Getter + @Setter + private VoteTotalsSnapshot bungeeTextTotals; + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private boolean forceBungee = false; + + @Getter + @Setter + private String player; + + @Getter + @Setter + private boolean realVote = true; + + @Getter + @Setter + private String serviceSite = ""; + + @Getter + @Setter + private long time; + + @Getter + @Setter + private VoteSite voteSite; + + @Getter + @Setter + private VotingPluginUser votingPluginUser; + + @Getter + @Setter + private boolean wasOnline; + + @Getter + @Setter + private boolean broadcast = true; + + @Getter + @Setter + private int voteNumber = 1; + + /** + * Constructs a new PlayerVoteEvent. + * + * @param voteSite the vote site + * @param voteUsername the username of the voter + * @param serviceSite the service site name + * @param realVote whether this is a real vote + */ + public PlayerVoteEvent(VoteSite voteSite, String voteUsername, String serviceSite, boolean realVote) { + super(true); + this.player = voteUsername; + this.voteSite = voteSite; + this.realVote = realVote; + this.serviceSite = serviceSite; + } + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteSiteCoolDownEndEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteSiteCoolDownEndEvent.java index 11b5149936..ac6f7644ec 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteSiteCoolDownEndEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteSiteCoolDownEndEvent.java @@ -1,64 +1,53 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class PlayerVoteEvent. - */ -public class PlayerVoteSiteCoolDownEndEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private VotingPluginUser player; - - @Getter - @Setter - private VoteSite site; - - /** - * Constructs a new PlayerVoteSiteCoolDownEndEvent. - * - * @param user the voting plugin user - * @param site the vote site - */ - public PlayerVoteSiteCoolDownEndEvent(VotingPluginUser user, VoteSite site) { - super(true); - player = user; - this.site = site; - } - - /* - * (non-Javadoc) - * - * @see org.bukkit.event.Event#getHandlers() - */ - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +import lombok.Getter; +import lombok.Setter; +public class PlayerVoteSiteCoolDownEndEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private VotingPluginUser player; + + @Getter + @Setter + private VoteSite site; + + /** + * Constructs a new PlayerVoteSiteCoolDownEndEvent. + * + * @param user the voting plugin user + * @param site the vote site + */ + public PlayerVoteSiteCoolDownEndEvent(VotingPluginUser user, VoteSite site) { + super(true); + player = user; + this.site = site; + } + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/VotePartyEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/VotePartyEvent.java index 76778dc05f..5b79b589c0 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/VotePartyEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/VotePartyEvent.java @@ -1,48 +1,37 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class PlayerVoteEvent. - */ -public class VotePartyEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - /** - * Constructs a new VotePartyEvent. - */ - public VotePartyEvent() { - super(true); - } - - /* - * (non-Javadoc) - * - * @see org.bukkit.event.Event#getHandlers() - */ - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import lombok.Getter; +import lombok.Setter; +public class VotePartyEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + /** + * Constructs a new VotePartyEvent. + */ + public VotePartyEvent() { + super(true); + } + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/BlockBreak.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/BlockBreak.java index 4758e66fb3..f80471e6eb 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/BlockBreak.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/BlockBreak.java @@ -1,57 +1,52 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.Location; -import org.bukkit.block.Sign; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; - -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.signs.SignHandler; - -// TODO: Auto-generated Javadoc -/** - * The Class BlockBreak. - */ -public class BlockBreak implements Listener { - - /** The plugin. */ - private VotingPluginMain plugin; - - /** - * Instantiates a new block break. - * - * @param plugin the plugin - */ - public BlockBreak(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On block break. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockBreak(BlockBreakEvent event) { - if (event.getBlock().getState() instanceof Sign) { - Sign s = (Sign) event.getBlock().getState(); - final Location loc = s.getLocation(); - plugin.getBukkitScheduler().runTaskAsynchronously(plugin, new Runnable() { - - @Override - public void run() { - for (SignHandler sign : plugin.getSigns().getSigns()) { - if (sign.getLocation().equals(loc)) { - sign.removeSign(); - sign.setValid(false); - } - } - } - }); - } - - } - -} +package com.bencodez.votingplugin.listeners; + +import org.bukkit.Location; +import org.bukkit.block.Sign; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.signs.SignHandler; +public class BlockBreak implements Listener { + + /** The plugin. */ + private VotingPluginMain plugin; + + /** + * Instantiates a new block break. + * + * @param plugin the plugin + */ + public BlockBreak(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On block break. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + if (event.getBlock().getState() instanceof Sign) { + Sign s = (Sign) event.getBlock().getState(); + final Location loc = s.getLocation(); + plugin.getBukkitScheduler().runTaskAsynchronously(plugin, new Runnable() { + + @Override + public void run() { + for (SignHandler sign : plugin.getSigns().getSigns()) { + if (sign.getLocation().equals(loc)) { + sign.removeSign(); + sign.setValid(false); + } + } + } + }); + } + + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerInteract.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerInteract.java index 4461505e48..0aa56835b3 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerInteract.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerInteract.java @@ -1,89 +1,84 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.block.Sign; -import org.bukkit.block.Skull; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.PlayerInteractEvent; - -import com.bencodez.advancedcore.api.misc.PlayerManager; -import com.bencodez.simpleapi.player.PlayerUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.signs.SignHandler; - -// TODO: Auto-generated Javadoc -/** - * The Class PlayerInteract. - */ -public class PlayerInteract implements Listener { - - /** The plugin. */ - private VotingPluginMain plugin; - - /** - * Instantiates a new player interact. - * - * @param plugin the plugin - */ - public PlayerInteract(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On player interact. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPlayerInteract(PlayerInteractEvent event) { - if (plugin.getConfigFile().isDisableInteractEvent()) { - return; - } - if (plugin.getSigns().getSigns().size() > 0) { - Player player = event.getPlayer(); - if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { - // plugin.debug("Checking for sign click"); - if (event.getClickedBlock().getState() instanceof Sign) { - // plugin.debug(player.getName() + " right clicked a sign"); - for (SignHandler sign : plugin.getSigns().getSigns()) { - if (sign.isLocationSame(event.getClickedBlock().getLocation())) { - // plugin.debug(player.getName() + - // " right clicked a top voter sign, sending message"); - plugin.getVotingPluginUserManager().getVotingPluginUser(player) - .sendMessage(sign.getRightClickMessage()); - - if (!sign.isSkullSet()) { - if (PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), - "VotingPlugin.Sign.Create") - || PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), - "VotingPlugin.Admin")) { - player.sendMessage("Skull not set, click to set skull"); - PlayerUtils.setPlayerMeta(plugin, player, "skullset", sign.getSign()); - } - } - } - } - - } else if (event.getClickedBlock().getState() instanceof Skull) { - Object ob = PlayerUtils.getPlayerMeta(plugin, player, "skullset"); - if (ob != null) { - String sign1 = (String) ob; - for (SignHandler sign : plugin.getSigns().getSigns()) { - if (sign.getSign().equals(sign1)) { - sign.setSkullLocation(event.getClickedBlock().getLocation()); - sign.storeSign(); - sign.checkSkulls(); - player.sendMessage("Skull set"); - } - } - PlayerUtils.setPlayerMeta(plugin, player, "skullset", null); - } - } - } - - } - } -} +package com.bencodez.votingplugin.listeners; + +import org.bukkit.block.Sign; +import org.bukkit.block.Skull; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +import com.bencodez.advancedcore.api.misc.PlayerManager; +import com.bencodez.simpleapi.player.PlayerUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.signs.SignHandler; +public class PlayerInteract implements Listener { + + /** The plugin. */ + private VotingPluginMain plugin; + + /** + * Instantiates a new player interact. + * + * @param plugin the plugin + */ + public PlayerInteract(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On player interact. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent event) { + if (plugin.getConfigFile().isDisableInteractEvent()) { + return; + } + if (plugin.getSigns().getSigns().size() > 0) { + Player player = event.getPlayer(); + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + // plugin.debug("Checking for sign click"); + if (event.getClickedBlock().getState() instanceof Sign) { + // plugin.debug(player.getName() + " right clicked a sign"); + for (SignHandler sign : plugin.getSigns().getSigns()) { + if (sign.isLocationSame(event.getClickedBlock().getLocation())) { + // plugin.debug(player.getName() + + // " right clicked a top voter sign, sending message"); + plugin.getVotingPluginUserManager().getVotingPluginUser(player) + .sendMessage(sign.getRightClickMessage()); + + if (!sign.isSkullSet()) { + if (PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), + "VotingPlugin.Sign.Create") + || PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), + "VotingPlugin.Admin")) { + player.sendMessage("Skull not set, click to set skull"); + PlayerUtils.setPlayerMeta(plugin, player, "skullset", sign.getSign()); + } + } + } + } + + } else if (event.getClickedBlock().getState() instanceof Skull) { + Object ob = PlayerUtils.getPlayerMeta(plugin, player, "skullset"); + if (ob != null) { + String sign1 = (String) ob; + for (SignHandler sign : plugin.getSigns().getSigns()) { + if (sign.getSign().equals(sign1)) { + sign.setSkullLocation(event.getClickedBlock().getLocation()); + sign.storeSign(); + sign.checkSkulls(); + player.sendMessage("Skull set"); + } + } + PlayerUtils.setPlayerMeta(plugin, player, "skullset", null); + } + } + } + + } + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerJoinEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerJoinEvent.java index bf6a9f6a30..d4455e8727 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerJoinEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerJoinEvent.java @@ -1,129 +1,125 @@ -package com.bencodez.votingplugin.listeners; - -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.PlayerQuitEvent; - -import com.bencodez.advancedcore.api.player.UuidLookup; -import com.bencodez.advancedcore.api.user.UserDataFetchMode; -import com.bencodez.advancedcore.listeners.AdvancedCoreLoginEvent; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.user.VotingPluginUser; - -/** - * The Class PlayerJoinEvent. - */ -public class PlayerJoinEvent implements Listener { - - /** The plugin. */ - private final VotingPluginMain plugin; - - /** - * Instantiates a new player join event. - * - * @param plugin the plugin - */ - public PlayerJoinEvent(VotingPluginMain plugin) { - this.plugin = plugin; - } - - private static boolean isBlank(String s) { - return s == null || s.trim().isEmpty() || "null".equalsIgnoreCase(s.trim()); - } - - /** - * On AdvancedCore login event (post-auth / delayed login). - * - * @param event the event - */ - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerLogin(AdvancedCoreLoginEvent event) { - if (event == null || !plugin.isMySQLOkay() || event.isCancelled() || event.getUser() == null) { - return; - } - - // UUID is authoritative here (String) - String uuid = event.getUuid(); - if (isBlank(uuid)) { - return; - } - - // "Has data" should come from AdvancedCore event (storage presence) - boolean hasData = event.isUserInStorage(); - - // Resolve VotingPluginUser by the storage UUID string (offline-mode - // name-derived UUID) - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid); - if (user == null) { - return; - } - - Player player = event.getPlayer(); - - if (player != null && player.isOp() && plugin.isYmlError()) { - user.sendMessage("&cVotingPlugin: Detected yml error, please check console for details"); - } - - if (hasData) { - // give offline vote (if they voted offline) - user.offVote(); - } else { - plugin.debug("No data detected for " + user.getUUID() + "/" + user.getPlayerName()); - } - - user.loginRewards(); - - plugin.getPlaceholders().onUpdate(user, true); - - if (plugin.getBungeeSettings().isUseBungeecoord()) { - plugin.getBackendProxyHandler().playerOnline(user.getPlayerName(), user.getUUID()); - } - } - - /** - * Handles player quit events. - * - * @param event the player quit event - */ - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerQuit(PlayerQuitEvent event) { - if (plugin == null || !plugin.isEnabled() || event == null) { - return; - } - - final Player player = event.getPlayer(); - if (player == null) { - return; - } - - if (plugin.getBungeeSettings().isUseBungeecoord()) { - plugin.getBackendProxyHandler().playerOffline(player.getName()); - } - - plugin.getLoginTimer().execute(new Runnable() { - - @Override - public void run() { - VotingPluginMain.plugin.getAdvancedTab().remove(player.getUniqueId()); - - // Use AdvancedCore UUIDLookup to derive the correct UUID (online/offline aware) - String uuid = UuidLookup.getInstance().getUUID(player.getName()); - if (isBlank(uuid)) { - // Fallback to online UUID if lookup fails - uuid = player.getUniqueId().toString(); - } - - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid); - if (user == null) { - return; - } - - user.userDataFetechMode(UserDataFetchMode.NO_CACHE); - user.logoutRewards(); - plugin.getPlaceholders().onLogout(user); - } - }); - } -} +package com.bencodez.votingplugin.listeners; + +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.PlayerQuitEvent; + +import com.bencodez.advancedcore.api.player.UuidLookup; +import com.bencodez.advancedcore.api.user.UserDataFetchMode; +import com.bencodez.advancedcore.listeners.AdvancedCoreLoginEvent; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.user.VotingPluginUser; +public class PlayerJoinEvent implements Listener { + + /** The plugin. */ + private final VotingPluginMain plugin; + + /** + * Instantiates a new player join event. + * + * @param plugin the plugin + */ + public PlayerJoinEvent(VotingPluginMain plugin) { + this.plugin = plugin; + } + + private static boolean isBlank(String s) { + return s == null || s.trim().isEmpty() || "null".equalsIgnoreCase(s.trim()); + } + + /** + * On AdvancedCore login event (post-auth / delayed login). + * + * @param event the event + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerLogin(AdvancedCoreLoginEvent event) { + if (event == null || !plugin.isMySQLOkay() || event.isCancelled() || event.getUser() == null) { + return; + } + + // UUID is authoritative here (String) + String uuid = event.getUuid(); + if (isBlank(uuid)) { + return; + } + + // "Has data" should come from AdvancedCore event (storage presence) + boolean hasData = event.isUserInStorage(); + + // Resolve VotingPluginUser by the storage UUID string (offline-mode + // name-derived UUID) + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid); + if (user == null) { + return; + } + + Player player = event.getPlayer(); + + if (player != null && player.isOp() && plugin.isYmlError()) { + user.sendMessage("&cVotingPlugin: Detected yml error, please check console for details"); + } + + if (hasData) { + // give offline vote (if they voted offline) + user.offVote(); + } else { + plugin.debug("No data detected for " + user.getUUID() + "/" + user.getPlayerName()); + } + + user.loginRewards(); + + plugin.getPlaceholders().onUpdate(user, true); + + if (plugin.getBungeeSettings().isUseBungeecoord()) { + plugin.getBackendProxyHandler().playerOnline(user.getPlayerName(), user.getUUID()); + } + } + + /** + * Handles player quit events. + * + * @param event the player quit event + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerQuit(PlayerQuitEvent event) { + if (plugin == null || !plugin.isEnabled() || event == null) { + return; + } + + final Player player = event.getPlayer(); + if (player == null) { + return; + } + + if (plugin.getBungeeSettings().isUseBungeecoord()) { + plugin.getBackendProxyHandler().playerOffline(player.getName()); + } + + plugin.getLoginTimer().execute(new Runnable() { + + @Override + public void run() { + VotingPluginMain.plugin.getAdvancedTab().remove(player.getUniqueId()); + + // Use AdvancedCore UUIDLookup to derive the correct UUID (online/offline aware) + String uuid = UuidLookup.getInstance().getUUID(player.getName()); + if (isBlank(uuid)) { + // Fallback to online UUID if lookup fails + uuid = player.getUniqueId().toString(); + } + + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid); + if (user == null) { + return; + } + + user.userDataFetechMode(UserDataFetchMode.NO_CACHE); + user.logoutRewards(); + plugin.getPlaceholders().onLogout(user); + } + }); + } +} 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 b6a47837e6..77f59dff0f 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerVoteListener.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerVoteListener.java @@ -1,80 +1,75 @@ -package com.bencodez.votingplugin.listeners; - -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.HashMap; -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.bedrock.BedrockNameResolver; -import com.bencodez.advancedcore.api.user.validation.UserValidationResult; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.events.PlayerPostVoteEvent; -import com.bencodez.votingplugin.events.PlayerVoteEvent; -import com.bencodez.votingplugin.topvoter.TopVoter; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -// TODO: Auto-generated Javadoc -/** - * The Class VotiferEvent. - */ -public class PlayerVoteListener implements Listener { - - private VotingPluginMain plugin; - - /** - * Instantiates a new votifer event. - * - * @param plugin the plugin - */ - public PlayerVoteListener(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On votifer event. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onplayerVote(PlayerVoteEvent event) { - if (!plugin.isEnabled()) { - plugin.getLogger().warning("Plugin disabled, ignoring vote"); - return; - } - String playerName = event.getPlayer(); - plugin.debug("Processing PlayerVoteEvent: " + playerName + "/" + event.getServiceSite()); - - // check for name casing - final String properName = plugin.getUserManager().getProperName(playerName); - - // Validate BEFORE full bedrock/db-backed resolution - boolean allowUnJoinedCheckServer = plugin.getConfigFile().isAllowUnJoinedCheckServer(); - UserValidationResult validationResult = plugin.getUserManager().getValidationService().validate(properName, - allowUnJoinedCheckServer); - - plugin.extraDebug("Vote validation result for " + properName + ": valid=" + validationResult.isValid() - + ", source=" + validationResult.getSource() + ", reason=" + validationResult.getReason() - + ", normalizedName=" + validationResult.getNormalizedName() + ", bedrock=" - + validationResult.isBedrock()); - - if (!validationResult.isValid() && !plugin.getConfigFile().isAllowUnjoined()) { - plugin.getLogger().warning("Player " + properName + " has not joined before, disregarding vote. " - + "Reason: " + validationResult.getReason() + ". Set AllowUnjoined to true to accept."); - if (event.isBungee() && plugin.getBungeeSettings().isRemoveInvalidUsers()) { - plugin.getVotingPluginUserManager().getVotingPluginUser(properName).remove(); - } - return; - } - +package com.bencodez.votingplugin.listeners; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.HashMap; +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.bedrock.BedrockNameResolver; +import com.bencodez.advancedcore.api.user.validation.UserValidationResult; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.events.PlayerPostVoteEvent; +import com.bencodez.votingplugin.events.PlayerVoteEvent; +import com.bencodez.votingplugin.topvoter.TopVoter; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; +public class PlayerVoteListener implements Listener { + + private VotingPluginMain plugin; + + /** + * Instantiates a new votifer event. + * + * @param plugin the plugin + */ + public PlayerVoteListener(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On votifer event. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onplayerVote(PlayerVoteEvent event) { + if (!plugin.isEnabled()) { + plugin.getLogger().warning("Plugin disabled, ignoring vote"); + return; + } + String playerName = event.getPlayer(); + plugin.debug("Processing PlayerVoteEvent: " + playerName + "/" + event.getServiceSite()); + + // check for name casing + final String properName = plugin.getUserManager().getProperName(playerName); + + // Validate BEFORE full bedrock/db-backed resolution + boolean allowUnJoinedCheckServer = plugin.getConfigFile().isAllowUnJoinedCheckServer(); + UserValidationResult validationResult = plugin.getUserManager().getValidationService().validate(properName, + allowUnJoinedCheckServer); + + plugin.extraDebug("Vote validation result for " + properName + ": valid=" + validationResult.isValid() + + ", source=" + validationResult.getSource() + ", reason=" + validationResult.getReason() + + ", normalizedName=" + validationResult.getNormalizedName() + ", bedrock=" + + validationResult.isBedrock()); + + if (!validationResult.isValid() && !plugin.getConfigFile().isAllowUnjoined()) { + plugin.getLogger().warning("Player " + properName + " has not joined before, disregarding vote. " + + "Reason: " + validationResult.getReason() + ". Set AllowUnjoined to true to accept."); + if (event.isBungee() && plugin.getBungeeSettings().isRemoveInvalidUsers()) { + plugin.getVotingPluginUserManager().getVotingPluginUser(properName).remove(); + } + return; + } + String creditedName; String resolutionRationale; if (validationResult.isValid()) { @@ -97,219 +92,219 @@ public void onplayerVote(PlayerVoteEvent event) { } plugin.debug("Vote name resolved: " + properName + " -> " + creditedName + " (" + resolutionRationale + ")"); - - // If we get here, use the resolved/possibly-prefixed name going forward - playerName = creditedName; - - if (playerName.isEmpty()) { - plugin.getLogger().warning("Empty player name from vote, ignoring"); - return; - } - - if (event.isBungee()) { - plugin.debug("BungeePlayerVote forcebungee: " + event.isForceBungee() + ", bungeetotals: " - + event.getBungeeTextTotals()); - - if (plugin.getBungeeSettings().isTriggerVotifierEvent()) { - try { - new ProxyVotifierEvent().send(plugin, event); - } catch (NoClassDefFoundError ex) { - plugin.getLogger().severe( - "Failed to trigger Votifier event for proxy vote. Either install Votifier or disable triggering the Votifier event"); - plugin.getLogger().severe("Error: " + ex.getMessage()); - plugin.debug(ex); - } - } - } - - VoteSite voteSite = event.getVoteSite(); - - if (voteSite == null) { - voteSite = plugin.getVoteSiteManager() - .getVoteSite(plugin.getVoteSiteManager().getVoteSiteName(true, event.getServiceSite()), true); - } - - // check valid service sites - if (voteSite == null) { - if (!plugin.getConfigFile().isDisableNoServiceSiteMessage()) { - plugin.getLogger().warning("No voting site with the service site: '" + event.getServiceSite() + "'"); - - ArrayList services = new ArrayList<>(); - for (VoteSite site : plugin.getVoteSiteManager().getVoteSites()) { - services.add(site.getServiceSite()); - } - plugin.getLogger().warning("Currently set service sites: " + ArrayUtils.makeStringList(services)); - } - return; - } - - if (!voteSite.isEnabled()) { - plugin.debug("Votesite: " + voteSite.getKey() + " is not enabled"); - return; - } - - VotingPluginUser user = null; - if (event.getVotingPluginUser() != null) { - user = event.getVotingPluginUser(); - } else { - Player p = Bukkit.getPlayerExact(playerName); - if (p != null) { - // player online - user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); - } else { - // attempt to get exact name from cache matching casing - user = plugin.getVotingPluginUserManager().getVotingPluginUser(playerName); - } - } - - boolean queuedProxyVoteAlreadyRecorded = ProxyVoteDelayCheck.isQueuedVoteAlreadyRecorded(event.isBungee(), - event.getTime(), user.getTime(voteSite)); - if (voteSite.isWaitUntilVoteDelay() && !queuedProxyVoteAlreadyRecorded && !user.canVoteSite(voteSite)) { - if (!event.isRealVote()) { - plugin.getLogger().info(user.getPlayerName() + " did a not real vote, bypassing WaitUntilVoteDelay"); - } 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() - .info(user.getPlayerName() + " has bypass permission for WaitUntilVoteDelay, bypassing"); - } - } - if (queuedProxyVoteAlreadyRecorded) { - plugin.debug("Allowing queued proxy vote for " + user.getPlayerName() + " on " + voteSite.getKey() - + "; proxy vote time already matches LastVotes: " + event.getTime()); - } - - UUID voteUUID = UUID.randomUUID(); - if (event.isBungee() && event.getBungeeTextTotals() != null) { - voteUUID = event.getBungeeTextTotals().getVoteUUID(); - if (voteUUID == null) { - voteUUID = UUID.randomUUID(); - } - } - - final String uuid = user.getUUID(); - - // reupdate cache - user.cache(); - - user.updateName(true); - - // vote party - plugin.getVoteParty().vote(user, event.isRealVote(), event.isForceBungee()); - - if (event.isBroadcast()) { - if (plugin.getBroadcastHandler() != null) { - boolean online = user.isOnline(); - if (event.isBungee()) { - online = event.isWasOnline(); - } - if (!user.isVanished()) { - plugin.getBroadcastHandler().broadcastVote(user.getJavaUUID(), playerName, - voteSite.getDisplayName(), online); - } else { - plugin.debug("Not broadcasting vote for vanished user: " + user.getPlayerName()); - } - } - } - - long voteTime = 0; - // update last vote time - if (event.getTime() != 0) { - user.setTime(voteSite, event.getTime()); - voteTime = event.getTime(); - } else { - user.setTime(voteSite); - voteTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); - } - - boolean cached = false; - // check if player has voted on all sites in one day - if (((user.isOnline() || voteSite.isGiveOffline()) && plugin.getOptions().isProcessRewards()) - || event.isBungee()) { - boolean online = true; - if (event.isBungee()) { - online = event.isWasOnline(); - } - user.playerVote(voteSite, online, event.isForceBungee()); - if (event.getVoteNumber() == 1) { - user.sendVoteEffects(online); - } - if (plugin.getConfigFile().isCloseInventoryOnVote()) { - user.closeInv(); - } - } else { - if (!plugin.getConfigFile().isOfflineVotesLimitEnabled() - || user.getNumberOfOfflineVotes(voteSite) <= plugin.getConfigFile().getOfflineVotesLimitAmount()) { - user.addOfflineVote(voteSite.getKey()); - cached = true; - plugin.debug( - "Offline vote set for " + playerName + " (" + user.getUUID() + ") on " + voteSite.getKey()); - } else { - plugin.debug("Not setting offline vote, offline vote limit reached"); - } - } - - // add to total votes - if ((plugin.getConfigFile().isCountFakeVotes() || event.isRealVote()) && event.isAddTotals()) { - if (plugin.getConfigFile().isAddTotals()) { - if (plugin.getConfigFile().isAddTotalsOffline() || user.isOnline()) { - user.addTotal(); - user.addTotalDaily(); - user.addTotalWeekly(); - } - } - user.addPoints(); - } - user.checkDayVoteStreak(event.isForceBungee()); - - if (plugin.getConfigFile().isLimitMonthlyVotes()) { - int value = 0; - if (event.isBungee()) { - value = event.getBungeeTextTotals().getMonthTotal(); - } else { - value = user.getTotal(TopVoter.Monthly); - } - LocalDateTime cTime = plugin.getTimeChecker().getTime(); - int days = cTime.getDayOfMonth(); - plugin.extraDebug("Current day of month: " + days + " Current total: " + value); - if (value >= days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()) { - plugin.debug("Detected higher month total, changing. Current Total: " + value + " Days: " + days - + " New Total: " + days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()); - user.setTotal(TopVoter.Monthly, days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()); - } - } - - plugin.getVoteMilestonesManager().handleVote(user, event.getBungeeTextTotals(), event.isForceBungee(), voteUUID, - new HashMap()); - - plugin.getCoolDownCheck().vote(user, voteSite); - - plugin.getVoteStreakHandler().processVote(user, voteTime, voteUUID); - - PlayerPostVoteEvent postVoteEvent = new PlayerPostVoteEvent(voteSite, user, event.isRealVote(), - event.isForceBungee(), voteTime, cached, voteSite.getServiceSite(), user.getJavaUUID(), playerName, - voteUUID); - plugin.getServer().getPluginManager().callEvent(postVoteEvent); - - if (user.isOnline() || plugin.getConfigFile().getPlaceholderCacheLevel().isCacheAlways()) { - plugin.getPlaceholders().onUpdate(user, true); - } - - if (!user.isOnline()) { - user.clearCache(); - } - plugin.setUpdate(true); - - plugin.extraDebug("Finished vote processing: " + playerName + "/" + uuid); - } - + + // If we get here, use the resolved/possibly-prefixed name going forward + playerName = creditedName; + + if (playerName.isEmpty()) { + plugin.getLogger().warning("Empty player name from vote, ignoring"); + return; + } + + if (event.isBungee()) { + plugin.debug("BungeePlayerVote forcebungee: " + event.isForceBungee() + ", bungeetotals: " + + event.getBungeeTextTotals()); + + if (plugin.getBungeeSettings().isTriggerVotifierEvent()) { + try { + new ProxyVotifierEvent().send(plugin, event); + } catch (NoClassDefFoundError ex) { + plugin.getLogger().severe( + "Failed to trigger Votifier event for proxy vote. Either install Votifier or disable triggering the Votifier event"); + plugin.getLogger().severe("Error: " + ex.getMessage()); + plugin.debug(ex); + } + } + } + + VoteSite voteSite = event.getVoteSite(); + + if (voteSite == null) { + voteSite = plugin.getVoteSiteManager() + .getVoteSite(plugin.getVoteSiteManager().getVoteSiteName(true, event.getServiceSite()), true); + } + + // check valid service sites + if (voteSite == null) { + if (!plugin.getConfigFile().isDisableNoServiceSiteMessage()) { + plugin.getLogger().warning("No voting site with the service site: '" + event.getServiceSite() + "'"); + + ArrayList services = new ArrayList<>(); + for (VoteSite site : plugin.getVoteSiteManager().getVoteSites()) { + services.add(site.getServiceSite()); + } + plugin.getLogger().warning("Currently set service sites: " + ArrayUtils.makeStringList(services)); + } + return; + } + + if (!voteSite.isEnabled()) { + plugin.debug("Votesite: " + voteSite.getKey() + " is not enabled"); + return; + } + + VotingPluginUser user = null; + if (event.getVotingPluginUser() != null) { + user = event.getVotingPluginUser(); + } else { + Player p = Bukkit.getPlayerExact(playerName); + if (p != null) { + // player online + user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); + } else { + // attempt to get exact name from cache matching casing + user = plugin.getVotingPluginUserManager().getVotingPluginUser(playerName); + } + } + + boolean queuedProxyVoteAlreadyRecorded = ProxyVoteDelayCheck.isQueuedVoteAlreadyRecorded(event.isBungee(), + event.getTime(), user.getTime(voteSite)); + if (voteSite.isWaitUntilVoteDelay() && !queuedProxyVoteAlreadyRecorded && !user.canVoteSite(voteSite)) { + if (!event.isRealVote()) { + plugin.getLogger().info(user.getPlayerName() + " did a not real vote, bypassing WaitUntilVoteDelay"); + } 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() + .info(user.getPlayerName() + " has bypass permission for WaitUntilVoteDelay, bypassing"); + } + } + if (queuedProxyVoteAlreadyRecorded) { + plugin.debug("Allowing queued proxy vote for " + user.getPlayerName() + " on " + voteSite.getKey() + + "; proxy vote time already matches LastVotes: " + event.getTime()); + } + + UUID voteUUID = UUID.randomUUID(); + if (event.isBungee() && event.getBungeeTextTotals() != null) { + voteUUID = event.getBungeeTextTotals().getVoteUUID(); + if (voteUUID == null) { + voteUUID = UUID.randomUUID(); + } + } + + final String uuid = user.getUUID(); + + // reupdate cache + user.cache(); + + user.updateName(true); + + // vote party + plugin.getVoteParty().vote(user, event.isRealVote(), event.isForceBungee()); + + if (event.isBroadcast()) { + if (plugin.getBroadcastHandler() != null) { + boolean online = user.isOnline(); + if (event.isBungee()) { + online = event.isWasOnline(); + } + if (!user.isVanished()) { + plugin.getBroadcastHandler().broadcastVote(user.getJavaUUID(), playerName, + voteSite.getDisplayName(), online); + } else { + plugin.debug("Not broadcasting vote for vanished user: " + user.getPlayerName()); + } + } + } + + long voteTime = 0; + // update last vote time + if (event.getTime() != 0) { + user.setTime(voteSite, event.getTime()); + voteTime = event.getTime(); + } else { + user.setTime(voteSite); + voteTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + } + + boolean cached = false; + // check if player has voted on all sites in one day + if (((user.isOnline() || voteSite.isGiveOffline()) && plugin.getOptions().isProcessRewards()) + || event.isBungee()) { + boolean online = true; + if (event.isBungee()) { + online = event.isWasOnline(); + } + user.playerVote(voteSite, online, event.isForceBungee()); + if (event.getVoteNumber() == 1) { + user.sendVoteEffects(online); + } + if (plugin.getConfigFile().isCloseInventoryOnVote()) { + user.closeInv(); + } + } else { + if (!plugin.getConfigFile().isOfflineVotesLimitEnabled() + || user.getNumberOfOfflineVotes(voteSite) <= plugin.getConfigFile().getOfflineVotesLimitAmount()) { + user.addOfflineVote(voteSite.getKey()); + cached = true; + plugin.debug( + "Offline vote set for " + playerName + " (" + user.getUUID() + ") on " + voteSite.getKey()); + } else { + plugin.debug("Not setting offline vote, offline vote limit reached"); + } + } + + // add to total votes + if ((plugin.getConfigFile().isCountFakeVotes() || event.isRealVote()) && event.isAddTotals()) { + if (plugin.getConfigFile().isAddTotals()) { + if (plugin.getConfigFile().isAddTotalsOffline() || user.isOnline()) { + user.addTotal(); + user.addTotalDaily(); + user.addTotalWeekly(); + } + } + user.addPoints(); + } + user.checkDayVoteStreak(event.isForceBungee()); + + if (plugin.getConfigFile().isLimitMonthlyVotes()) { + int value = 0; + if (event.isBungee()) { + value = event.getBungeeTextTotals().getMonthTotal(); + } else { + value = user.getTotal(TopVoter.Monthly); + } + LocalDateTime cTime = plugin.getTimeChecker().getTime(); + int days = cTime.getDayOfMonth(); + plugin.extraDebug("Current day of month: " + days + " Current total: " + value); + if (value >= days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()) { + plugin.debug("Detected higher month total, changing. Current Total: " + value + " Days: " + days + + " New Total: " + days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()); + user.setTotal(TopVoter.Monthly, days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()); + } + } + + plugin.getVoteMilestonesManager().handleVote(user, event.getBungeeTextTotals(), event.isForceBungee(), voteUUID, + new HashMap()); + + plugin.getCoolDownCheck().vote(user, voteSite); + + plugin.getVoteStreakHandler().processVote(user, voteTime, voteUUID); + + PlayerPostVoteEvent postVoteEvent = new PlayerPostVoteEvent(voteSite, user, event.isRealVote(), + event.isForceBungee(), voteTime, cached, voteSite.getServiceSite(), user.getJavaUUID(), playerName, + voteUUID); + plugin.getServer().getPluginManager().callEvent(postVoteEvent); + + if (user.isOnline() || plugin.getConfigFile().getPlaceholderCacheLevel().isCacheAlways()) { + plugin.getPlaceholders().onUpdate(user, true); + } + + if (!user.isOnline()) { + user.clearCache(); + } + plugin.setUpdate(true); + + plugin.extraDebug("Finished vote processing: " + playerName + "/" + uuid); + } + } diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/SignChange.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/SignChange.java index 41380cc521..62d0fe2461 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/SignChange.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/SignChange.java @@ -1,68 +1,63 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.SignChangeEvent; - -import com.bencodez.advancedcore.api.misc.PlayerManager; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.votingplugin.VotingPluginMain; - -// TODO: Auto-generated Javadoc -/** - * The Class SignChange. - */ -public class SignChange implements Listener { - - /** The plugin. */ - private VotingPluginMain plugin; - - /** - * Instantiates a new sign change. - * - * @param plugin the plugin - */ - public SignChange(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On sign change. - * - * @param event the event - */ - @EventHandler(ignoreCancelled = true) - public void onSignChange(SignChangeEvent event) { - if (event.getLine(0).equalsIgnoreCase("[VotingPlugin]")) { - if (PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), "VotingPlugin.Sign.Create") - || PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), - "VotingPlugin.Admin")) { - String data = event.getLine(2); - if (!data.equalsIgnoreCase("all") && !data.equalsIgnoreCase("monthly") - && !data.equalsIgnoreCase("weekly") && !data.equalsIgnoreCase("daily")) { - return; - } - try { - plugin.getServerData().addSign(event.getBlock().getLocation(), event.getLine(2), - Integer.parseInt(event.getLine(1))); - event.getPlayer().sendMessage(MessageAPI.colorize("&aAdded sign!")); - plugin.getBukkitScheduler().runTaskAsynchronously(plugin, new Runnable() { - - @Override - public void run() { - plugin.getSigns().updateSigns(); - plugin.getSigns().storeSigns(); - } - }); - } catch (Exception ex) { - event.getPlayer().sendMessage(MessageAPI.colorize("&cError on sign creation!")); - ex.printStackTrace(); - } - } else { - event.getPlayer().sendMessage(MessageAPI.colorize(plugin.getConfigFile().getFormatNoPerms())); - } - } - - } - +package com.bencodez.votingplugin.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.SignChangeEvent; + +import com.bencodez.advancedcore.api.misc.PlayerManager; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.votingplugin.VotingPluginMain; +public class SignChange implements Listener { + + /** The plugin. */ + private VotingPluginMain plugin; + + /** + * Instantiates a new sign change. + * + * @param plugin the plugin + */ + public SignChange(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On sign change. + * + * @param event the event + */ + @EventHandler(ignoreCancelled = true) + public void onSignChange(SignChangeEvent event) { + if (event.getLine(0).equalsIgnoreCase("[VotingPlugin]")) { + if (PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), "VotingPlugin.Sign.Create") + || PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), + "VotingPlugin.Admin")) { + String data = event.getLine(2); + if (!data.equalsIgnoreCase("all") && !data.equalsIgnoreCase("monthly") + && !data.equalsIgnoreCase("weekly") && !data.equalsIgnoreCase("daily")) { + return; + } + try { + plugin.getServerData().addSign(event.getBlock().getLocation(), event.getLine(2), + Integer.parseInt(event.getLine(1))); + event.getPlayer().sendMessage(MessageAPI.colorize("&aAdded sign!")); + plugin.getBukkitScheduler().runTaskAsynchronously(plugin, new Runnable() { + + @Override + public void run() { + plugin.getSigns().updateSigns(); + plugin.getSigns().storeSigns(); + } + }); + } catch (Exception ex) { + event.getPlayer().sendMessage(MessageAPI.colorize("&cError on sign creation!")); + ex.printStackTrace(); + } + } else { + event.getPlayer().sendMessage(MessageAPI.colorize(plugin.getConfigFile().getFormatNoPerms())); + } + } + + } + } \ No newline at end of file diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotiferEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotiferEvent.java index 81fb28c8a6..b1dade6003 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotiferEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotiferEvent.java @@ -1,136 +1,132 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; - -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.events.PlayerVoteEvent; -import com.bencodez.votingplugin.proxy.BungeeMethod; -import com.bencodez.votingplugin.util.MinecraftUsernameValidator; -import com.bencodez.votingplugin.util.ServiceSiteValidator; -import com.vexsoftware.votifier.model.Vote; -import com.vexsoftware.votifier.model.VotifierEvent; - -/** - * The Class VotiferEvent. - */ -public class VotiferEvent implements Listener { - - private VotingPluginMain plugin; - - /** - * Instantiates a new votifer event. - * - * @param plugin the plugin - */ - public VotiferEvent(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On votifer event. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onVotiferEvent(VotifierEvent event) { - - Vote vote = event.getVote(); - String str = vote.getServiceName(); - if (str == null || str.isEmpty()) { - str = "Empty"; - } - final String voteSite = str; - final String IP = vote.getAddress(); - final String voteUsername = vote.getUsername(); - if (IP.equals("VotingPlugin")) { - return; - } - if (!ServiceSiteValidator.isValid(voteSite)) { - plugin.getLogger().warning("Rejected vote with invalid service site '" - + ServiceSiteValidator.sanitizeForLog(voteSite) + "'"); - return; - } - - if (!MinecraftUsernameValidator.isValid(voteUsername, plugin.getOptions().getBedrockPlayerPrefix())) { - plugin.getLogger().warning("Rejected vote with invalid Minecraft username '" - + MinecraftUsernameValidator.sanitizeForLog(voteUsername) + "' from service '" - + MinecraftUsernameValidator.sanitizeForLog(voteSite) + "'"); - return; - } - - plugin.getLogger() - .info("Received a vote from service site '" + voteSite + "' by player '" + voteUsername + "'!"); - - plugin.debug("PlayerUsername: " + voteUsername); - plugin.debug("VoteSite: " + voteSite); - plugin.debug("IP: " + IP); - - plugin.getVoteTimer().submit(new Runnable() { - - @Override - public void run() { - try { - plugin.getServerData().addServiceSite(voteSite); - if (plugin.getBungeeSettings().isUseBungeecoord() && !plugin.getBungeeSettings().isVotifierBypass() - && (plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.PLUGINMESSAGING) - || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.SOCKETS) - || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.MQTT) - || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.REDIS))) { - plugin.getLogger().severe( - "Ignoring vote from votifier since pluginmessaging, socket, redis, or mqtt bungee method is enabled, this means you aren't setup correctly for those methods, please check: https://github.com/BenCodez/VotingPlugin/wiki/Bungeecord-Setups"); - return; - } - - String matchSite = ""; - if (plugin.getConfigFile().isAdvancedServiceSiteHandling()) { - if (plugin.getServiceSiteHandler() != null) { - matchSite = plugin.getServiceSiteHandler().matchReverse(voteSite); - } - } - - String voteSiteNameStr = plugin.getVoteSiteManager().getVoteSiteName(false, voteSite, matchSite); - boolean createSite = !plugin.getVoteSiteManager().hasVoteSite(voteSiteNameStr) - && !plugin.getVoteSiteManager().hasConfiguredVoteSite(voteSiteNameStr); - - String serviceSite = voteSite; - - if (plugin.getConfigFile().isAutoCreateVoteSites() && createSite) { - plugin.getLogger().warning("VoteSite with service site '" + voteSiteNameStr - + "' does not exist, attempting to generate..."); - if (plugin.getConfigVoteSites().tryGenerateVoteSite(voteSiteNameStr)) { - plugin.getLogger().info("Current known service sites: " - + ArrayUtils.makeStringList(plugin.getServerData().getServiceSites())); - } else { - plugin.getLogger().warning("Unable to generate VoteSite for service site '" - + ServiceSiteValidator.sanitizeForLog(voteSiteNameStr) + "'"); - } - } - - if (plugin.getTimeChecker().isActiveProcessing() - && plugin.getConfigFile().isQueueVotesDuringTimeChange()) { - plugin.debug("Adding vote to time queue " + voteUsername + "/" + voteSite); - plugin.getTimeQueueHandler().addVote(voteUsername, voteSite); - return; - } - - String voteSiteName = plugin.getVoteSiteManager().getVoteSiteName(true, serviceSite, matchSite); - - PlayerVoteEvent voteEvent = new PlayerVoteEvent( - plugin.getVoteSiteManager().getVoteSite(voteSiteName, true), voteUsername, voteSite, true); - plugin.getServer().getPluginManager().callEvent(voteEvent); - - if (voteEvent.isCancelled()) { - plugin.debug("Vote cancelled"); - return; - } - } catch (Exception e) { - plugin.getLogger().severe("Error occured during vote processing"); - e.printStackTrace(); - } - } - }); - } -} +package com.bencodez.votingplugin.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.events.PlayerVoteEvent; +import com.bencodez.votingplugin.proxy.BungeeMethod; +import com.bencodez.votingplugin.util.MinecraftUsernameValidator; +import com.bencodez.votingplugin.util.ServiceSiteValidator; +import com.vexsoftware.votifier.model.Vote; +import com.vexsoftware.votifier.model.VotifierEvent; +public class VotiferEvent implements Listener { + + private VotingPluginMain plugin; + + /** + * Instantiates a new votifer event. + * + * @param plugin the plugin + */ + public VotiferEvent(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On votifer event. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onVotiferEvent(VotifierEvent event) { + + Vote vote = event.getVote(); + String str = vote.getServiceName(); + if (str == null || str.isEmpty()) { + str = "Empty"; + } + final String voteSite = str; + final String IP = vote.getAddress(); + final String voteUsername = vote.getUsername(); + if (IP.equals("VotingPlugin")) { + return; + } + if (!ServiceSiteValidator.isValid(voteSite)) { + plugin.getLogger().warning("Rejected vote with invalid service site '" + + ServiceSiteValidator.sanitizeForLog(voteSite) + "'"); + return; + } + + if (!MinecraftUsernameValidator.isValid(voteUsername, plugin.getOptions().getBedrockPlayerPrefix())) { + plugin.getLogger().warning("Rejected vote with invalid Minecraft username '" + + MinecraftUsernameValidator.sanitizeForLog(voteUsername) + "' from service '" + + MinecraftUsernameValidator.sanitizeForLog(voteSite) + "'"); + return; + } + + plugin.getLogger() + .info("Received a vote from service site '" + voteSite + "' by player '" + voteUsername + "'!"); + + plugin.debug("PlayerUsername: " + voteUsername); + plugin.debug("VoteSite: " + voteSite); + plugin.debug("IP: " + IP); + + plugin.getVoteTimer().submit(new Runnable() { + + @Override + public void run() { + try { + plugin.getServerData().addServiceSite(voteSite); + if (plugin.getBungeeSettings().isUseBungeecoord() && !plugin.getBungeeSettings().isVotifierBypass() + && (plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.PLUGINMESSAGING) + || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.SOCKETS) + || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.MQTT) + || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.REDIS))) { + plugin.getLogger().severe( + "Ignoring vote from votifier since pluginmessaging, socket, redis, or mqtt bungee method is enabled, this means you aren't setup correctly for those methods, please check: https://github.com/BenCodez/VotingPlugin/wiki/Bungeecord-Setups"); + return; + } + + String matchSite = ""; + if (plugin.getConfigFile().isAdvancedServiceSiteHandling()) { + if (plugin.getServiceSiteHandler() != null) { + matchSite = plugin.getServiceSiteHandler().matchReverse(voteSite); + } + } + + String voteSiteNameStr = plugin.getVoteSiteManager().getVoteSiteName(false, voteSite, matchSite); + boolean createSite = !plugin.getVoteSiteManager().hasVoteSite(voteSiteNameStr) + && !plugin.getVoteSiteManager().hasConfiguredVoteSite(voteSiteNameStr); + + String serviceSite = voteSite; + + if (plugin.getConfigFile().isAutoCreateVoteSites() && createSite) { + plugin.getLogger().warning("VoteSite with service site '" + voteSiteNameStr + + "' does not exist, attempting to generate..."); + if (plugin.getConfigVoteSites().tryGenerateVoteSite(voteSiteNameStr)) { + plugin.getLogger().info("Current known service sites: " + + ArrayUtils.makeStringList(plugin.getServerData().getServiceSites())); + } else { + plugin.getLogger().warning("Unable to generate VoteSite for service site '" + + ServiceSiteValidator.sanitizeForLog(voteSiteNameStr) + "'"); + } + } + + if (plugin.getTimeChecker().isActiveProcessing() + && plugin.getConfigFile().isQueueVotesDuringTimeChange()) { + plugin.debug("Adding vote to time queue " + voteUsername + "/" + voteSite); + plugin.getTimeQueueHandler().addVote(voteUsername, voteSite); + return; + } + + String voteSiteName = plugin.getVoteSiteManager().getVoteSiteName(true, serviceSite, matchSite); + + PlayerVoteEvent voteEvent = new PlayerVoteEvent( + plugin.getVoteSiteManager().getVoteSite(voteSiteName, true), voteUsername, voteSite, true); + plugin.getServer().getPluginManager().callEvent(voteEvent); + + if (voteEvent.isCancelled()) { + plugin.debug("Vote cancelled"); + return; + } + } catch (Exception e) { + plugin.getLogger().severe("Error occured during vote processing"); + e.printStackTrace(); + } + } + }); + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotingPluginUpdateEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotingPluginUpdateEvent.java index 46883c09a5..0ddda92878 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotingPluginUpdateEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotingPluginUpdateEvent.java @@ -1,43 +1,38 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; - -import com.bencodez.advancedcore.listeners.PluginUpdateVersionEvent; -import com.bencodez.votingplugin.VotingPluginMain; - -// TODO: Auto-generated Javadoc -/** - * The Class AdvancedCoreUpdateEvent. - */ -public class VotingPluginUpdateEvent implements Listener { - - /** The plugin. */ - private VotingPluginMain plugin; - - /** - * Instantiates a new advanced core update event. - * - * @param plugin the plugin - */ - public VotingPluginUpdateEvent(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On plugin update. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPluginUpdate(PluginUpdateVersionEvent event) { - if (event.getPlugin().getName().equals(plugin.getDescription().getName())) { - if (!event.getOldVersion().equals("")) { - plugin.getLogger().info("VotingPlugin Updated to " + plugin.getDescription().getVersion() + " from " - + event.getOldVersion()); - } - } - } - +package com.bencodez.votingplugin.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import com.bencodez.advancedcore.listeners.PluginUpdateVersionEvent; +import com.bencodez.votingplugin.VotingPluginMain; +public class VotingPluginUpdateEvent implements Listener { + + /** The plugin. */ + private VotingPluginMain plugin; + + /** + * Instantiates a new advanced core update event. + * + * @param plugin the plugin + */ + public VotingPluginUpdateEvent(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On plugin update. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPluginUpdate(PluginUpdateVersionEvent event) { + if (event.getPlugin().getName().equals(plugin.getDescription().getName())) { + if (!event.getOldVersion().equals("")) { + plugin.getLogger().info("VotingPlugin Updated to " + plugin.getDescription().getVersion() + " from " + + event.getOldVersion()); + } + } + } + } \ No newline at end of file diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/MVdWPlaceholders.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/MVdWPlaceholders.java index 2f68ca7dd8..4740994633 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/MVdWPlaceholders.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/MVdWPlaceholders.java @@ -10,11 +10,6 @@ import be.maximvdw.placeholderapi.PlaceholderAPI; import be.maximvdw.placeholderapi.PlaceholderReplaceEvent; import be.maximvdw.placeholderapi.PlaceholderReplacer; - -// TODO: Auto-generated Javadoc -/** - * The Class PlaceHolders. - */ public class MVdWPlaceholders { /** The plugin. */ diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java index 1da84057b1..ea2bcb1b16 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java @@ -1,1325 +1,1320 @@ -package com.bencodez.votingplugin.placeholders; - -import java.text.NumberFormat; -import java.time.Duration; -import java.time.LocalDateTime; -import java.time.temporal.TemporalField; -import java.time.temporal.WeekFields; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import com.bencodez.advancedcore.api.messages.PlaceholderUtils; -import com.bencodez.advancedcore.api.placeholder.CalculatingPlaceholder; -import com.bencodez.advancedcore.api.placeholder.NonPlayerPlaceHolder; -import com.bencodez.advancedcore.api.placeholder.PlaceHolder; -import com.bencodez.advancedcore.api.user.AdvancedCoreUser; -import com.bencodez.advancedcore.api.user.UserDataChanged; -import com.bencodez.advancedcore.api.user.UserDataFetchMode; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestone; -import com.bencodez.votingplugin.topvoter.TopVoter; -import com.bencodez.votingplugin.topvoter.TopVoterPlayer; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -import lombok.Getter; - -// TODO: Auto-generated Javadoc -/** - * The Class PlaceHolders. - */ -public class PlaceHolders { - - @Getter - private ArrayList> nonPlayerPlaceholders = new ArrayList<>(); - - @Getter - private ArrayList> placeholders = new ArrayList<>(); - - private VotingPluginMain plugin; - - private ArrayList cachedPlaceholders = new ArrayList<>(); - - private ConcurrentLinkedQueue placeholdersToSetCacheOn = new ConcurrentLinkedQueue<>(); - - @Getter - private PlaceholderCacheLevel cacheLevel; - - /** - * Constructor for PlaceHolders. - * @param plugin the voting plugin instance - */ - public PlaceHolders(VotingPluginMain plugin) { - this.plugin = plugin; - cacheLevel = plugin.getConfigFile().getPlaceholderCacheLevel(); - } - - /** - * Check for placeholders that need caching. - */ - public void checkNonCachedPlaceholders() { - while (!placeholdersToSetCacheOn.isEmpty()) { - String toCache = placeholdersToSetCacheOn.poll().toLowerCase(); - if (toCache.startsWith("votingplugin")) { - toCache = toCache.substring("votingplugin_".length()); - } - /* - * for (NonPlayerPlaceHolder placeholder : - * nonPlayerPlaceholders) { if (placeholder.matches(toCache)) { - * placeholder.setUseCache(true, toCache); cachedPlaceholders.add(toCache); - * plugin.getServerData().addAutoCachedPlaceholder(toCache); - * plugin.extraDebug("Auto Caching placeholder " + toCache); } - * - * } - */ - for (PlaceHolder placeholder : placeholders) { - if (placeholder.matches(toCache)) { - placeholder.setUseCache(true, toCache); - cachedPlaceholders.add(toCache); - plugin.getServerData().addAutoCachedPlaceholder(toCache); - plugin.extraDebug("Auto Caching placeholder " + toCache); - } - } - - } - } - - /** - * Get placeholder value for offline player. - * @param p the offline player - * @param identifier the placeholder identifier - * @return the placeholder value - */ - public String getPlaceHolder(OfflinePlayer p, String identifier) { - return getPlaceHolder(p, identifier, true); - } - - /** - * Get placeholder value for offline player with javascript support. - * @param p the offline player - * @param identifier1 the placeholder identifier - * @param javascript enable javascript processing - * @return the placeholder value - */ - public String getPlaceHolder(OfflinePlayer p, String identifier1, boolean javascript) { - boolean forceProcess = false; - boolean useCache = true; - String identifier = identifier1.toLowerCase(); - boolean custom = false; - if (identifier.endsWith("_process") - || (!Bukkit.isPrimaryThread() && plugin.getConfigFile().isAlwaysProcessAsyncPlaceholders())) { - forceProcess = true; - identifier = identifier.replaceAll("_process", ""); - } - if (identifier.endsWith("_nocache")) { - useCache = false; - identifier = identifier.replaceAll("_nocache", ""); - } - if (getCacheLevel().equals(PlaceholderCacheLevel.NONE)) { - useCache = false; - } - - if (identifier.startsWith("custom_")) { - custom = true; - identifier = identifier.replaceAll("custom_", ""); - } - - if (!custom || !plugin.getConfigFile().getCustomPlaceholderReturns().contains(identifier)) { - return getPlaceholderValue(p, identifier, javascript, forceProcess, useCache); - } - String str = getPlaceholderValue(p, identifier, javascript, true, useCache); - String returnStr = plugin.getConfigFile().getCustomPlaceholderReturns(identifier, str); - if (!returnStr.isEmpty()) { - return returnStr; - } - return str; - - } - - /** - * Get placeholder value for online player. - * @param p the player - * @param identifier the placeholder identifier - * @return the placeholder value - */ - public String getPlaceHolder(Player p, String identifier) { - if (plugin.getConfigFile().isUseJavascriptPlaceholders()) { - identifier = PlaceholderUtils.replaceJavascript(p, identifier); - } - return getPlaceHolder(p, identifier, false); - } - - /** - * Get placeholder value with options. - * @param p the offline player - * @param identifier the placeholder identifier - * @param javascript enable javascript processing - * @param forceProcess force processing of placeholder - * @param useCache use cached value if available - * @return the placeholder value - */ - public String getPlaceholderValue(OfflinePlayer p, String identifier, boolean javascript, boolean forceProcess, - boolean useCache) { - if (plugin.getConfigFile().isUseJavascriptPlaceholders() && javascript && p != null) { - identifier = PlaceholderUtils.replaceJavascript(p, identifier); - } - - if (!identifier.toLowerCase().endsWith("position")) { - for (NonPlayerPlaceHolder placeholder : nonPlayerPlaceholders) { - if (placeholder.matches(identifier)) { - String str = placeholder.placeholderRequest(identifier); - if (str != null) { - return str; - } - } - } - } - - if (p == null) { - return "no player"; - } - - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); - if (useCache) { - if (!cachedPlaceholders.contains(identifier)) { - // not cached placeholder - if (!forceProcess) { - for (PlaceHolder placeholder : placeholders) { - if (placeholder.matches(identifier)) { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return ".."; - } - } - return "Not a valid placeholder"; - - } - } - } - - UUID uuid = user.getJavaUUID(); - - for (PlaceHolder placeholder : placeholders) { - try { - if (placeholder.matches(identifier)) { - if (placeholder instanceof CalculatingPlaceholder) { - if (!useCache) { - return placeholder.placeholderRequest(user, identifier); - } - CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; - if (placeholder.isUsesCache() && placeholder.isCached(identifier)) { - ConcurrentHashMap cache = placeholder.getCache().get(identifier); - if (cache.containsKey(uuid)) { - if (cPlaceholder.getCacheData().containsKey(uuid)) { - return cPlaceholder.placeholderRequest(user, identifier); - } - return cache.get(uuid); - } else if (!forceProcess) { - schedulePlaceholderCheck(user); - return "..."; - } - } - - if (forceProcess) { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier) - && !cachedPlaceholders.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return placeholder.placeholderRequest(user, identifier); - } else { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier) - && !cachedPlaceholders.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return "."; - } - } - if (!useCache) { - return placeholder.placeholderRequest(user, identifier); - } - if (placeholder.isUsesCache() && placeholder.isCached(identifier)) { - ConcurrentHashMap cache = placeholder.getCache().get(identifier); - - if (cache.containsKey(uuid)) { - return cache.get(uuid); - } else if (!forceProcess) { - schedulePlaceholderCheck(user); - return "..."; - } - } - - if (forceProcess) { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier) - && !cachedPlaceholders.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return placeholder.placeholderRequest(user, identifier); - } else { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier) - && !cachedPlaceholders.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return "."; - } - } - } catch (Exception e) { - plugin.debug(e); - return "Error"; - } - } - - return "Not a valid placeholder"; - } - - /** - * Load all placeholders. - */ - public void load() { - placeholders.clear(); - nonPlayerPlaceholders.clear(); - - // older placeholders, might be removed in the future - placeholders.add(new PlaceHolder("total") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getTotal(TopVoter.Monthly)); - } - }.withDescription("Month total").updateDataKey("MonthTotal")); - - placeholders.add(new PlaceHolder("alltimetotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getTotal(TopVoter.AllTime)); - } - }.withDescription("Alltime total").updateDataKey("AllTimeTotal")); - - placeholders.add(new PlaceHolder("lastmonthtotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getLastMonthTotal()); - } - }.withDescription("Last month total").updateDataKey("LastMonthTotal")); - - // end of older placeholders - - placeholders.add(new PlaceHolder("CanLike_NameMC") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return user.hasClaimedNameMCLikeReward() ? "Complete" : "Incomplete"; - } - }.withDescription("Return Complete/Incomplete depending on whether the player has liked the server on NameMC") - .updateDataKey("ClaimedNameMCLikeReward")); - - placeholders.add(new PlaceHolder("DisableBroadcast") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getDisableBroadcast(); - } - }.withDescription("Returns true/false if user has broadcast disabled").updateDataKey("DisableBroadcast")); - - /* - * placeholders.add(new PlaceHolder("DisableReminders") { - * - * @Override public String placeholderRequest(VotingPluginUser user, String - * identifier) { if - * (plugin.getVoteReminding().getRemindersEnabled().containsKey(user.getJavaUUID - * ())) { if - * (!plugin.getVoteReminding().getRemindersEnabled().get(user.getJavaUUID()). - * booleanValue()) { - * - * return "True"; } } return "False"; } - * }.withDescription("Returns true/false if user has reminders disabled")); - */ - - for (final String identifier : plugin.getShopFile().getShopIdentifiers()) { - if (plugin.getShopFile().getShopIdentifierLimit(identifier) > 0) { - placeholders.add(new PlaceHolder("VoteShopLimit_" + identifier) { - - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - return "" + user.getVoteShopIdentifierLimit(identifier); - } - }.withDescription("User voteshop limit for " + identifier).updateDataKey("VoteShopLimit" + identifier)); - } - } - - for (final TopVoter top : TopVoter.values()) { - placeholders.add(new PlaceHolder("Total_" + top.toString()) { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getTotal(top)); - } - }.withDescription("User total for " + top.getName()).updateDataKey(top.getColumnName())); - } - - placeholders.add(new PlaceHolder("BestDailyTotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getHighestDailyTotal()); - } - }.withDescription("Best daily total").updateDataKey("HighestDailyTotal")); - - placeholders.add(new PlaceHolder("BestWeeklyTotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getHighestWeeklyTotal()); - } - }.withDescription("Best weekly total").updateDataKey("HighestWeeklyTotal")); - - placeholders.add(new PlaceHolder("BestMonthlyTotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getHighestMonthlyTotal()); - } - }.withDescription("Best monthly total").updateDataKey("HighestMonthlyTotal")); - - placeholders.add(new PlaceHolder("DailyVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getDayVoteStreak()); - } - }.withDescription("Current daily votestreak").updateDataKey("DayVoteStreak")); - - placeholders.add(new PlaceHolder("WeeklyVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getWeekVoteStreak()); - } - }.withDescription("Current weekly votestreak").updateDataKey("WeekVoteStreak")); - - placeholders.add(new PlaceHolder("MonthVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getMonthVoteStreak()); - } - }.withDescription("Current month votestreak").updateDataKey("MonthVoteStreak")); - - placeholders.add(new PlaceHolder("BestDailyVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getBestDayVoteStreak()); - } - }.withDescription("Best daily votestreak").updateDataKey("BestDayVoteStreak")); - - placeholders.add(new PlaceHolder("BestWeeklyVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getBestWeekVoteStreak()); - } - }.withDescription("Best weekly votestreak").updateDataKey("BestWeekVoteStreak")); - - placeholders.add(new PlaceHolder("BestMonthVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getBestMonthVoteStreak()); - } - }.withDescription("Best month votestreak").updateDataKey("BestMonthVoteStreak")); - - placeholders.add(new PlaceHolder("Points") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getPoints()); - } - }.withDescription("User points").updateDataKey("Points")); - - placeholders.add(new PlaceHolder("Points_Format") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US); - return numberFormat.format(user.getPoints()); - } - }.withDescription("User points").updateDataKey("Points")); - - placeholders.add(new PlaceHolder("CanVote") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Boolean.toString(user.canVoteAll()); - } - }.withDescription("Return true/false if player can vote on all sites").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("CanVoteSites") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getSitesNotVotedOn(); - } - }.withDescription("Return number of votesites available").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("Next_AnySite") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - if (user.canVoteAny()) { - return plugin.getConfigFile().getFormatCommandsVoteNextInfoCanVote(); - } - long smallest = -1; - HashMap times = new HashMap<>(); - for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) { - long t = user.voteNextDurationTime(site); - if (smallest == -1) { - smallest = t; - } - if (t < smallest) { - smallest = t; - } - times.put(t, site); - } - for (Entry entry : times.entrySet()) { - if (entry.getKey().longValue() == smallest) { - return user.voteCommandNextInfo(entry.getValue()); - } - } - - return "Error"; - } - }.withDescription("How long until user can vote on anysite").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("SitesAvailable") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getSitesNotVotedOn(); - } - }.withDescription("Get number of sites available to be voted on").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("SitesAvailableTotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getTotalNumberOfSites(); - } - }.withDescription("Get total number of sites available to be voted on")); - - for (final VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) { - placeholders.add(new CalculatingPlaceholder("Next_" + voteSite.getKey()) { - - @Override - public String placeholderDataRequest(VotingPluginUser user, String identifier) { - long time = user.getTime(voteSite); - return "" + time; - } - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - if (getCacheData().containsKey(user.getJavaUUID())) { - String data = getCacheData().get(user.getJavaUUID()); - if (!data.isEmpty()) { - long time = Long.valueOf(data); - return user.voteCommandNextInfo(voteSite, time); - } - } - return user.voteCommandNextInfo(voteSite); - } - }.withDescription("How long until user can vote on " + voteSite.getKey()).updateDataKey("LastVotes")); - placeholders.add(new PlaceHolder("Last_" + voteSite.getKey()) { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return user.voteCommandLastDuration(voteSite); - } - }.withDescription("How long ago user voted on " + voteSite.getKey()).updateDataKey("LastVotes")); - placeholders.add(new PlaceHolder("CanVote_" + voteSite.getKey()) { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.canVoteSite(voteSite); - } - }.withDescription("Whether or not player can vote on " + voteSite.getKey()).updateDataKey("LastVotes")); - } - - placeholders.add(new PlaceHolder("Top_All_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user top voter position")); - - placeholders.add(new PlaceHolder("EnoughPoints_") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[1])) { - return "invalid"; - } - int number = Integer.parseInt(identifier.split("_")[1]); - if (user.getPoints() >= number) { - return "true"; - } - return "false"; - } - }.withDescription("Return true/false if player has said points").updateDataKey("Points").useStartsWith()); - - // VoteMilestones placeholders (explicit per group, like - // VoteShopLimit_) - // Base/default (no group suffix) - placeholders.add(new PlaceHolder("VoteMilestoneNext") { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - Long next = plugin.getVoteMilestonesManager().getNextMilestoneValue("default", user); - return next == null ? "none" : Long.toString(next); - } - }.withDescription("Next VoteMilestone value for default group").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("VoteMilestoneLast") { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - Long last = plugin.getVoteMilestonesManager().getLastMilestoneValue("default", user); - return last == null ? "none" : Long.toString(last); - } - }.withDescription("Last achieved VoteMilestone value for default group").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("VoteMilestoneVotesUntilNext") { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - return Long.toString(plugin.getVoteMilestonesManager().getVotesUntilNextMilestone("default", user)); - } - }.withDescription("Votes until next VoteMilestone for default group").updateDataKey("LastVotes")); - - Set groups = new HashSet<>(); - groups.add("default"); - - for (VoteMilestone m : plugin.getVoteMilestonesManager().getConfig().getMilestones().values()) { - String g = m.getGroupKey(); - if (g == null) - continue; - g = g.trim().toLowerCase(Locale.ROOT); - if (!g.isEmpty()) - groups.add(g); - } - - for (final String groupIdRaw : groups) { - final String groupId = (groupIdRaw == null || groupIdRaw.trim().isEmpty()) ? "default" : groupIdRaw.trim(); - - placeholders.add(new PlaceHolder("VoteMilestoneNext_" + groupId) { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - Long next = plugin.getVoteMilestonesManager().getNextMilestoneValue(groupId, user); - return next == null ? "none" : Long.toString(next); - } - }.withDescription("Next VoteMilestone value for group " + groupId).updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("VoteMilestoneLast_" + groupId) { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - Long last = plugin.getVoteMilestonesManager().getLastMilestoneValue(groupId, user); - return last == null ? "none" : Long.toString(last); - } - }.withDescription("Last achieved VoteMilestone value for group " + groupId).updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("VoteMilestoneVotesUntilNext_" + groupId) { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - return Long.toString(plugin.getVoteMilestonesManager().getVotesUntilNextMilestone(groupId, user)); - } - }.withDescription("Votes until next VoteMilestone for group " + groupId).updateDataKey("LastVotes")); - } - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_AllVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in top voter")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_All_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get username at postion in top voter")); - - placeholders.add(new PlaceHolder("Top_Month_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user's current top voter position")); - - if (plugin.getGui().isLastMonthGUI()) { - placeholders.add(new PlaceHolder("Top_LastMonth_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user top voter position for lastmonth")); - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_LastMonth_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user at position in last month top voter")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_LastMonthVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in last month top voter")); - - } - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Month_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get username at position in top voter")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_MonthVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in top voter")); - - placeholders.add(new PlaceHolder("Top_Week_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user top voter position")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Week_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get username at postion in top voter")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_WeekVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in top voter")); - - placeholders.add(new PlaceHolder("Top_Daily_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user top voter position")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Daily_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get username at postion in top voter")); - - placeholders.add(new PlaceHolder("VotePartyContributedVotes") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getVotePartyVotes(); - } - }.useStartsWith().withDescription("See vote party placeholders contributed").updateDataKey("VotePartyVotes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_DailyVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in top voter")); - - // non players - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesCurrent") { - - @Override - public String placeholderRequest(String identifier) { - return Integer.toString(plugin.getVoteParty().getTotalVotes()); - } - }.withDescription("Current amount of voteparty votes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesNeeded") { - - @Override - public String placeholderRequest(String identifier) { - return Integer.toString(plugin.getVoteParty().getNeededVotes()); - } - }.withDescription("Voteparty votes needed")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesRequired") { - - @Override - public String placeholderRequest(String identifier) { - return Integer.toString(plugin.getVoteParty().getVotesRequired()); - } - }.withDescription("Amount of votes needed for voteparty")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesCurrent") { - - @Override - public String placeholderRequest(String identifier) { - if (plugin.getBackendProxyHandler() != null) { - return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyCurrent()); - } - return "-1"; - } - }.withDescription("Current amount of bungee voteparty votes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesNeeded") { - - @Override - public String placeholderRequest(String identifier) { - if (plugin.getBackendProxyHandler() != null) { - return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyRequired() - - plugin.getBackendProxyHandler().getBungeeVotePartyCurrent()); - } - return "-1"; - } - }.withDescription("Voteparty bungee votes needed")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesRequired") { - - @Override - public String placeholderRequest(String identifier) { - if (plugin.getBackendProxyHandler() != null) { - return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyRequired()); - } - return "-1"; - } - }.withDescription("Amount of votes needed for bungee voteparty")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalMonthTotal") { - - @Override - public String placeholderRequest(String identifier) { - int total = 0; - for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Monthly).values()) { - total += num; - } - return Integer.toString(total); - } - }.withDescription("Global month total")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalAllTimeTotal") { - - @Override - public String placeholderRequest(String identifier) { - int total = 0; - for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.AllTime).values()) { - total += num; - } - return Integer.toString(total); - } - }.withDescription("Global alltime total")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalWeeklyTotal") { - - @Override - public String placeholderRequest(String identifier) { - int total = 0; - for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Weekly).values()) { - total += num; - } - return Integer.toString(total); - } - }.withDescription("Global weekly total")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalDailyTotal") { - - @Override - public String placeholderRequest(String identifier) { - int total = 0; - for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Daily).values()) { - total += num; - } - return Integer.toString(total); - } - }.withDescription("Global daily total")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilDayReset") { - - @Override - public String placeholderRequest(String identifier) { - LocalDateTime now = plugin.getTimeChecker().getTime(); - LocalDateTime offsetoclocktoday = plugin.getTimeChecker().getTime().withHour(0).withMinute(0); - LocalDateTime offsetoclocktomorrow = plugin.getTimeChecker().getTime().plusDays(1).withHour(0) - .withMinute(0); - - String timeMsg = "%hours% Hours %minutes% Minutes"; - Duration dur = null; - if (!now.isBefore(offsetoclocktoday)) { - dur = Duration.between(now, offsetoclocktomorrow); - - } else { - dur = Duration.between(now, offsetoclocktoday); - } - int diffHours = (int) (dur.getSeconds() / (60 * 60)); - long diffMinutes = dur.getSeconds() / 60 - diffHours * 60; - - if (diffHours < 0) { - diffHours = diffHours * -1; - } - if (diffHours >= 24) { - diffHours = diffHours - 24; - } - if (diffMinutes < 0) { - diffMinutes = diffMinutes * -1; - } - - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); - return timeMsg; - - } - }.withDescription("Time until plugin time day changes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilWeekReset") { - - @Override - public String placeholderRequest(String identifier) { - LocalDateTime now = plugin.getTimeChecker().getTime().plusDays(plugin.getOptions().getTimeWeekOffSet()); - LocalDateTime newWeek = plugin.getTimeChecker().getTime().withHour(0).withMinute(0); - - TemporalField woy = WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear(); - int weekNumber = newWeek.get(woy); - int newWeekNumber = weekNumber; - - while (weekNumber == newWeekNumber) { - newWeek = newWeek.plusDays(1); - newWeekNumber = newWeek.get(woy); - } - - String timeMsg = "%days% Days %hours% Hours %minutes% Minutes"; - Duration dur = Duration.between(now, newWeek); - - int diffDays = (int) (dur.getSeconds() / (60 * 60 * 24)); - int diffHours = (int) (dur.getSeconds() / (60 * 60) - diffDays * 24); - long diffMinutes = dur.getSeconds() / 60 - diffHours * 60 - diffDays * 24 * 60; - - if (diffHours < 0) { - diffHours = diffHours * -1; - } - if (diffHours >= 24) { - diffHours = diffHours - 24; - } - if (diffMinutes < 0) { - diffMinutes = diffMinutes * -1; - } - - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%days%", Integer.toString(diffDays)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); - return timeMsg; - - } - }.withDescription("Time until plugin time week changes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilMonthReset") { - - @Override - public String placeholderRequest(String identifier) { - LocalDateTime now = plugin.getTimeChecker().getTime(); - LocalDateTime newMonth = plugin.getTimeChecker().getTime().plusMonths(1).withDayOfMonth(1).withHour(0) - .withMinute(0); - - String timeMsg = "%days% Days %hours% Hours %minutes% Minutes"; - Duration dur = Duration.between(now, newMonth); - - int diffDays = (int) (dur.getSeconds() / (60 * 60 * 24)); - int diffHours = (int) (dur.getSeconds() / (60 * 60) - diffDays * 24); - long diffMinutes = dur.getSeconds() / 60 - diffHours * 60 - diffDays * 24 * 60; - - if (diffHours < 0) { - diffHours = diffHours * -1; - } - if (diffHours >= 24) { - diffHours = diffHours - 24; - } - if (diffMinutes < 0) { - diffMinutes = diffMinutes * -1; - } - - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%days%", Integer.toString(diffDays)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); - return timeMsg; - - } - }.withDescription("Time until plugin time month changes")); - - Set placeholdersSet = new HashSet<>(); - placeholdersSet.addAll(plugin.getConfigFile().getCachedPlaceholders()); - if (getCacheLevel().equals(PlaceholderCacheLevel.AUTO)) { - placeholdersSet.addAll(plugin.getServerData().getAutoCachedPlaceholder()); - } - - for (String toCache : placeholdersSet) { - if (toCache.startsWith("votingplugin")) { - toCache = toCache.substring("votingplugin_".length()); - } - for (NonPlayerPlaceHolder placeholder : nonPlayerPlaceholders) { - if (placeholder.matches(toCache)) { - placeholder.setUseCache(true, toCache); - cachedPlaceholders.add(toCache); - plugin.extraDebug("Caching placeholder " + toCache); - } - } - - for (PlaceHolder placeholder : placeholders) { - if (placeholder.matches(toCache)) { - placeholder.setUseCache(true, toCache); - cachedPlaceholders.add(toCache); - plugin.extraDebug("Caching placeholder " + toCache); - } - } - } - - plugin.getUserManager().getUserDataChange().add(new UserDataChanged() { - - @Override - public void onChange(AdvancedCoreUser user, String... keys) { - VotingPluginUser vpUser = plugin.getVotingPluginUserManager().getVotingPluginUser(user); - if (!vpUser.isCached()) { - vpUser.userDataFetechMode(UserDataFetchMode.NO_CACHE); - } - for (PlaceHolder placeholder : placeholders) { - if (placeholder.isUsesCache()) { - if (placeholder.isCached(placeholder.getIdentifier(), user.getJavaUUID()) - || !getCacheLevel().onlineOnly() || user.isOnline()) { - if (placeholder instanceof CalculatingPlaceholder) { - CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; - if (placeholder.isUsesCache()) { - for (String key : keys) { - if (placeholder.getUpdateDataKey().equalsIgnoreCase(key)) { - for (String ident : placeholder.getCache().keySet()) { - String value = placeholder.placeholderRequest(vpUser, ident); - cPlaceholder.getCacheData().put(user.getJavaUUID(), - cPlaceholder.placeholderDataRequest(vpUser, ident)); - placeholder.getCache().get(ident).put(vpUser.getJavaUUID(), value); - plugin.devDebug("Updated calculating placeholder cache for " - + vpUser.getUUID() + " on " + key + " with " + value); - } - } - } - } - } else { - if (placeholder.isUsesCache()) { - for (String key : keys) { - if (placeholder.getUpdateDataKey().equalsIgnoreCase(key)) { - for (String ident : placeholder.getCache().keySet()) { - String value = placeholder.placeholderRequest(vpUser, ident); - placeholder.getCache().get(ident).put(vpUser.getJavaUUID(), value); - plugin.devDebug("Updated placeholder cache for " + vpUser.getUUID() - + " on " + key + " with " + value); - - } - - } - } - } - } - } - } - } - } - }); - } - - /** - * Handle player logout. - * @param user the voting plugin user - */ - public void onLogout(VotingPluginUser user) { - if (plugin.getPlaceholders().getCacheLevel().onlineOnly()) { - for (PlaceHolder placeholder : placeholders) { - if (placeholder.isUsesCache()) { - placeholder.clearCachePlayer(user.getJavaUUID()); - } - } - } - } - - /** - * Update all placeholders. - */ - public void onUpdate() { - checkNonCachedPlaceholders(); - for (Player p : Bukkit.getOnlinePlayers()) { - onUpdate(plugin.getVotingPluginUserManager().getVotingPluginUser(p), true); - } - /* - * for (NonPlayerPlaceHolder placeholder : - * nonPlayerPlaceholders) { if (placeholder.isUsesCache()) { for (String ident : - * placeholder.getCache().keySet()) { if (ident != null) { String str = - * placeholder.placeholderRequest(ident); if (str != null) { - * placeholder.getCache().put(ident, str); } } else { - * plugin.debug("ident null: " + placeholder.getIdentifier()); } } } } - */ - - } - - /** - * Update placeholders for specific user. - * @param user the voting plugin user - * @param login whether this is a login update - */ - public void onUpdate(VotingPluginUser user, boolean login) { - for (PlaceHolder placeholder : placeholders) { - if (placeholder.isUsesCache()) { - if (placeholder.isCached(placeholder.getIdentifier(), user.getJavaUUID()) || login) { - if (placeholder instanceof CalculatingPlaceholder) { - - CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; - if (placeholder.isUsesCache()) { - for (String ident : placeholder.getCache().keySet()) { - cPlaceholder.getCacheData().put(user.getJavaUUID(), - cPlaceholder.placeholderDataRequest(user, ident)); - placeholder.getCache().get(ident).put(user.getJavaUUID(), - placeholder.placeholderRequest(user, ident)); - } - - } - } else { - if (placeholder.isUsesCache()) { - for (String ident : placeholder.getCache().keySet()) { - placeholder.getCache().get(ident).put(user.getJavaUUID(), - placeholder.placeholderRequest(user, ident)); - } - } - } - } - } - } - } - - /** - * Handle vote party update. - */ - public void onVotePartyUpdate() { - /* - * for (NonPlayerPlaceHolder placeholder : - * nonPlayerPlaceholders) { if (placeholder.isUsesCache()) { if - * (placeholder.getIdentifier().startsWith("VoteParty")) { for (String ident : - * placeholder.getCache().keySet()) { placeholder.getCache().put(ident, - * placeholder.placeholderRequest(ident)); } } } } - */ - } - - /** - * Reload placeholders. - */ - public void reload() { - cacheLevel = plugin.getConfigFile().getPlaceholderCacheLevel(); - onUpdate(); - if (!cacheLevel.equals(PlaceholderCacheLevel.NONE)) { - for (Player player : Bukkit.getOnlinePlayers()) { - onUpdate(plugin.getVotingPluginUserManager().getVotingPluginUser(player), player.isOnline()); - } - } - } - - /** - * Schedule placeholder check for user. - * @param user the voting plugin user - */ - public void schedulePlaceholderCheck(VotingPluginUser user) { - plugin.getTimer().execute(new Runnable() { - - @Override - public void run() { - checkNonCachedPlaceholders(); - onUpdate(user, user.isOnline()); - } - }); - } -} +package com.bencodez.votingplugin.placeholders; + +import java.text.NumberFormat; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.temporal.TemporalField; +import java.time.temporal.WeekFields; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.placeholder.CalculatingPlaceholder; +import com.bencodez.advancedcore.api.placeholder.NonPlayerPlaceHolder; +import com.bencodez.advancedcore.api.placeholder.PlaceHolder; +import com.bencodez.advancedcore.api.user.AdvancedCoreUser; +import com.bencodez.advancedcore.api.user.UserDataChanged; +import com.bencodez.advancedcore.api.user.UserDataFetchMode; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestone; +import com.bencodez.votingplugin.topvoter.TopVoter; +import com.bencodez.votingplugin.topvoter.TopVoterPlayer; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +import lombok.Getter; +public class PlaceHolders { + + @Getter + private ArrayList> nonPlayerPlaceholders = new ArrayList<>(); + + @Getter + private ArrayList> placeholders = new ArrayList<>(); + + private VotingPluginMain plugin; + + private ArrayList cachedPlaceholders = new ArrayList<>(); + + private ConcurrentLinkedQueue placeholdersToSetCacheOn = new ConcurrentLinkedQueue<>(); + + @Getter + private PlaceholderCacheLevel cacheLevel; + + /** + * Constructor for PlaceHolders. + * @param plugin the voting plugin instance + */ + public PlaceHolders(VotingPluginMain plugin) { + this.plugin = plugin; + cacheLevel = plugin.getConfigFile().getPlaceholderCacheLevel(); + } + + /** + * Check for placeholders that need caching. + */ + public void checkNonCachedPlaceholders() { + while (!placeholdersToSetCacheOn.isEmpty()) { + String toCache = placeholdersToSetCacheOn.poll().toLowerCase(); + if (toCache.startsWith("votingplugin")) { + toCache = toCache.substring("votingplugin_".length()); + } + /* + * for (NonPlayerPlaceHolder placeholder : + * nonPlayerPlaceholders) { if (placeholder.matches(toCache)) { + * placeholder.setUseCache(true, toCache); cachedPlaceholders.add(toCache); + * plugin.getServerData().addAutoCachedPlaceholder(toCache); + * plugin.extraDebug("Auto Caching placeholder " + toCache); } + * + * } + */ + for (PlaceHolder placeholder : placeholders) { + if (placeholder.matches(toCache)) { + placeholder.setUseCache(true, toCache); + cachedPlaceholders.add(toCache); + plugin.getServerData().addAutoCachedPlaceholder(toCache); + plugin.extraDebug("Auto Caching placeholder " + toCache); + } + } + + } + } + + /** + * Get placeholder value for offline player. + * @param p the offline player + * @param identifier the placeholder identifier + * @return the placeholder value + */ + public String getPlaceHolder(OfflinePlayer p, String identifier) { + return getPlaceHolder(p, identifier, true); + } + + /** + * Get placeholder value for offline player with javascript support. + * @param p the offline player + * @param identifier1 the placeholder identifier + * @param javascript enable javascript processing + * @return the placeholder value + */ + public String getPlaceHolder(OfflinePlayer p, String identifier1, boolean javascript) { + boolean forceProcess = false; + boolean useCache = true; + String identifier = identifier1.toLowerCase(); + boolean custom = false; + if (identifier.endsWith("_process") + || (!Bukkit.isPrimaryThread() && plugin.getConfigFile().isAlwaysProcessAsyncPlaceholders())) { + forceProcess = true; + identifier = identifier.replaceAll("_process", ""); + } + if (identifier.endsWith("_nocache")) { + useCache = false; + identifier = identifier.replaceAll("_nocache", ""); + } + if (getCacheLevel().equals(PlaceholderCacheLevel.NONE)) { + useCache = false; + } + + if (identifier.startsWith("custom_")) { + custom = true; + identifier = identifier.replaceAll("custom_", ""); + } + + if (!custom || !plugin.getConfigFile().getCustomPlaceholderReturns().contains(identifier)) { + return getPlaceholderValue(p, identifier, javascript, forceProcess, useCache); + } + String str = getPlaceholderValue(p, identifier, javascript, true, useCache); + String returnStr = plugin.getConfigFile().getCustomPlaceholderReturns(identifier, str); + if (!returnStr.isEmpty()) { + return returnStr; + } + return str; + + } + + /** + * Get placeholder value for online player. + * @param p the player + * @param identifier the placeholder identifier + * @return the placeholder value + */ + public String getPlaceHolder(Player p, String identifier) { + if (plugin.getConfigFile().isUseJavascriptPlaceholders()) { + identifier = PlaceholderUtils.replaceJavascript(p, identifier); + } + return getPlaceHolder(p, identifier, false); + } + + /** + * Get placeholder value with options. + * @param p the offline player + * @param identifier the placeholder identifier + * @param javascript enable javascript processing + * @param forceProcess force processing of placeholder + * @param useCache use cached value if available + * @return the placeholder value + */ + public String getPlaceholderValue(OfflinePlayer p, String identifier, boolean javascript, boolean forceProcess, + boolean useCache) { + if (plugin.getConfigFile().isUseJavascriptPlaceholders() && javascript && p != null) { + identifier = PlaceholderUtils.replaceJavascript(p, identifier); + } + + if (!identifier.toLowerCase().endsWith("position")) { + for (NonPlayerPlaceHolder placeholder : nonPlayerPlaceholders) { + if (placeholder.matches(identifier)) { + String str = placeholder.placeholderRequest(identifier); + if (str != null) { + return str; + } + } + } + } + + if (p == null) { + return "no player"; + } + + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); + if (useCache) { + if (!cachedPlaceholders.contains(identifier)) { + // not cached placeholder + if (!forceProcess) { + for (PlaceHolder placeholder : placeholders) { + if (placeholder.matches(identifier)) { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return ".."; + } + } + return "Not a valid placeholder"; + + } + } + } + + UUID uuid = user.getJavaUUID(); + + for (PlaceHolder placeholder : placeholders) { + try { + if (placeholder.matches(identifier)) { + if (placeholder instanceof CalculatingPlaceholder) { + if (!useCache) { + return placeholder.placeholderRequest(user, identifier); + } + CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; + if (placeholder.isUsesCache() && placeholder.isCached(identifier)) { + ConcurrentHashMap cache = placeholder.getCache().get(identifier); + if (cache.containsKey(uuid)) { + if (cPlaceholder.getCacheData().containsKey(uuid)) { + return cPlaceholder.placeholderRequest(user, identifier); + } + return cache.get(uuid); + } else if (!forceProcess) { + schedulePlaceholderCheck(user); + return "..."; + } + } + + if (forceProcess) { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier) + && !cachedPlaceholders.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return placeholder.placeholderRequest(user, identifier); + } else { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier) + && !cachedPlaceholders.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return "."; + } + } + if (!useCache) { + return placeholder.placeholderRequest(user, identifier); + } + if (placeholder.isUsesCache() && placeholder.isCached(identifier)) { + ConcurrentHashMap cache = placeholder.getCache().get(identifier); + + if (cache.containsKey(uuid)) { + return cache.get(uuid); + } else if (!forceProcess) { + schedulePlaceholderCheck(user); + return "..."; + } + } + + if (forceProcess) { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier) + && !cachedPlaceholders.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return placeholder.placeholderRequest(user, identifier); + } else { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier) + && !cachedPlaceholders.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return "."; + } + } + } catch (Exception e) { + plugin.debug(e); + return "Error"; + } + } + + return "Not a valid placeholder"; + } + + /** + * Load all placeholders. + */ + public void load() { + placeholders.clear(); + nonPlayerPlaceholders.clear(); + + // older placeholders, might be removed in the future + placeholders.add(new PlaceHolder("total") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getTotal(TopVoter.Monthly)); + } + }.withDescription("Month total").updateDataKey("MonthTotal")); + + placeholders.add(new PlaceHolder("alltimetotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getTotal(TopVoter.AllTime)); + } + }.withDescription("Alltime total").updateDataKey("AllTimeTotal")); + + placeholders.add(new PlaceHolder("lastmonthtotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getLastMonthTotal()); + } + }.withDescription("Last month total").updateDataKey("LastMonthTotal")); + + // end of older placeholders + + placeholders.add(new PlaceHolder("CanLike_NameMC") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return user.hasClaimedNameMCLikeReward() ? "Complete" : "Incomplete"; + } + }.withDescription("Return Complete/Incomplete depending on whether the player has liked the server on NameMC") + .updateDataKey("ClaimedNameMCLikeReward")); + + placeholders.add(new PlaceHolder("DisableBroadcast") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getDisableBroadcast(); + } + }.withDescription("Returns true/false if user has broadcast disabled").updateDataKey("DisableBroadcast")); + + /* + * placeholders.add(new PlaceHolder("DisableReminders") { + * + * @Override public String placeholderRequest(VotingPluginUser user, String + * identifier) { if + * (plugin.getVoteReminding().getRemindersEnabled().containsKey(user.getJavaUUID + * ())) { if + * (!plugin.getVoteReminding().getRemindersEnabled().get(user.getJavaUUID()). + * booleanValue()) { + * + * return "True"; } } return "False"; } + * }.withDescription("Returns true/false if user has reminders disabled")); + */ + + for (final String identifier : plugin.getShopFile().getShopIdentifiers()) { + if (plugin.getShopFile().getShopIdentifierLimit(identifier) > 0) { + placeholders.add(new PlaceHolder("VoteShopLimit_" + identifier) { + + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + return "" + user.getVoteShopIdentifierLimit(identifier); + } + }.withDescription("User voteshop limit for " + identifier).updateDataKey("VoteShopLimit" + identifier)); + } + } + + for (final TopVoter top : TopVoter.values()) { + placeholders.add(new PlaceHolder("Total_" + top.toString()) { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getTotal(top)); + } + }.withDescription("User total for " + top.getName()).updateDataKey(top.getColumnName())); + } + + placeholders.add(new PlaceHolder("BestDailyTotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getHighestDailyTotal()); + } + }.withDescription("Best daily total").updateDataKey("HighestDailyTotal")); + + placeholders.add(new PlaceHolder("BestWeeklyTotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getHighestWeeklyTotal()); + } + }.withDescription("Best weekly total").updateDataKey("HighestWeeklyTotal")); + + placeholders.add(new PlaceHolder("BestMonthlyTotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getHighestMonthlyTotal()); + } + }.withDescription("Best monthly total").updateDataKey("HighestMonthlyTotal")); + + placeholders.add(new PlaceHolder("DailyVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getDayVoteStreak()); + } + }.withDescription("Current daily votestreak").updateDataKey("DayVoteStreak")); + + placeholders.add(new PlaceHolder("WeeklyVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getWeekVoteStreak()); + } + }.withDescription("Current weekly votestreak").updateDataKey("WeekVoteStreak")); + + placeholders.add(new PlaceHolder("MonthVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getMonthVoteStreak()); + } + }.withDescription("Current month votestreak").updateDataKey("MonthVoteStreak")); + + placeholders.add(new PlaceHolder("BestDailyVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getBestDayVoteStreak()); + } + }.withDescription("Best daily votestreak").updateDataKey("BestDayVoteStreak")); + + placeholders.add(new PlaceHolder("BestWeeklyVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getBestWeekVoteStreak()); + } + }.withDescription("Best weekly votestreak").updateDataKey("BestWeekVoteStreak")); + + placeholders.add(new PlaceHolder("BestMonthVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getBestMonthVoteStreak()); + } + }.withDescription("Best month votestreak").updateDataKey("BestMonthVoteStreak")); + + placeholders.add(new PlaceHolder("Points") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getPoints()); + } + }.withDescription("User points").updateDataKey("Points")); + + placeholders.add(new PlaceHolder("Points_Format") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US); + return numberFormat.format(user.getPoints()); + } + }.withDescription("User points").updateDataKey("Points")); + + placeholders.add(new PlaceHolder("CanVote") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Boolean.toString(user.canVoteAll()); + } + }.withDescription("Return true/false if player can vote on all sites").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("CanVoteSites") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getSitesNotVotedOn(); + } + }.withDescription("Return number of votesites available").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("Next_AnySite") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + if (user.canVoteAny()) { + return plugin.getConfigFile().getFormatCommandsVoteNextInfoCanVote(); + } + long smallest = -1; + HashMap times = new HashMap<>(); + for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) { + long t = user.voteNextDurationTime(site); + if (smallest == -1) { + smallest = t; + } + if (t < smallest) { + smallest = t; + } + times.put(t, site); + } + for (Entry entry : times.entrySet()) { + if (entry.getKey().longValue() == smallest) { + return user.voteCommandNextInfo(entry.getValue()); + } + } + + return "Error"; + } + }.withDescription("How long until user can vote on anysite").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("SitesAvailable") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getSitesNotVotedOn(); + } + }.withDescription("Get number of sites available to be voted on").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("SitesAvailableTotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getTotalNumberOfSites(); + } + }.withDescription("Get total number of sites available to be voted on")); + + for (final VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) { + placeholders.add(new CalculatingPlaceholder("Next_" + voteSite.getKey()) { + + @Override + public String placeholderDataRequest(VotingPluginUser user, String identifier) { + long time = user.getTime(voteSite); + return "" + time; + } + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + if (getCacheData().containsKey(user.getJavaUUID())) { + String data = getCacheData().get(user.getJavaUUID()); + if (!data.isEmpty()) { + long time = Long.valueOf(data); + return user.voteCommandNextInfo(voteSite, time); + } + } + return user.voteCommandNextInfo(voteSite); + } + }.withDescription("How long until user can vote on " + voteSite.getKey()).updateDataKey("LastVotes")); + placeholders.add(new PlaceHolder("Last_" + voteSite.getKey()) { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return user.voteCommandLastDuration(voteSite); + } + }.withDescription("How long ago user voted on " + voteSite.getKey()).updateDataKey("LastVotes")); + placeholders.add(new PlaceHolder("CanVote_" + voteSite.getKey()) { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.canVoteSite(voteSite); + } + }.withDescription("Whether or not player can vote on " + voteSite.getKey()).updateDataKey("LastVotes")); + } + + placeholders.add(new PlaceHolder("Top_All_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user top voter position")); + + placeholders.add(new PlaceHolder("EnoughPoints_") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[1])) { + return "invalid"; + } + int number = Integer.parseInt(identifier.split("_")[1]); + if (user.getPoints() >= number) { + return "true"; + } + return "false"; + } + }.withDescription("Return true/false if player has said points").updateDataKey("Points").useStartsWith()); + + // VoteMilestones placeholders (explicit per group, like + // VoteShopLimit_) + // Base/default (no group suffix) + placeholders.add(new PlaceHolder("VoteMilestoneNext") { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + Long next = plugin.getVoteMilestonesManager().getNextMilestoneValue("default", user); + return next == null ? "none" : Long.toString(next); + } + }.withDescription("Next VoteMilestone value for default group").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("VoteMilestoneLast") { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + Long last = plugin.getVoteMilestonesManager().getLastMilestoneValue("default", user); + return last == null ? "none" : Long.toString(last); + } + }.withDescription("Last achieved VoteMilestone value for default group").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("VoteMilestoneVotesUntilNext") { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + return Long.toString(plugin.getVoteMilestonesManager().getVotesUntilNextMilestone("default", user)); + } + }.withDescription("Votes until next VoteMilestone for default group").updateDataKey("LastVotes")); + + Set groups = new HashSet<>(); + groups.add("default"); + + for (VoteMilestone m : plugin.getVoteMilestonesManager().getConfig().getMilestones().values()) { + String g = m.getGroupKey(); + if (g == null) + continue; + g = g.trim().toLowerCase(Locale.ROOT); + if (!g.isEmpty()) + groups.add(g); + } + + for (final String groupIdRaw : groups) { + final String groupId = (groupIdRaw == null || groupIdRaw.trim().isEmpty()) ? "default" : groupIdRaw.trim(); + + placeholders.add(new PlaceHolder("VoteMilestoneNext_" + groupId) { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + Long next = plugin.getVoteMilestonesManager().getNextMilestoneValue(groupId, user); + return next == null ? "none" : Long.toString(next); + } + }.withDescription("Next VoteMilestone value for group " + groupId).updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("VoteMilestoneLast_" + groupId) { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + Long last = plugin.getVoteMilestonesManager().getLastMilestoneValue(groupId, user); + return last == null ? "none" : Long.toString(last); + } + }.withDescription("Last achieved VoteMilestone value for group " + groupId).updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("VoteMilestoneVotesUntilNext_" + groupId) { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + return Long.toString(plugin.getVoteMilestonesManager().getVotesUntilNextMilestone(groupId, user)); + } + }.withDescription("Votes until next VoteMilestone for group " + groupId).updateDataKey("LastVotes")); + } + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_AllVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in top voter")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_All_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get username at postion in top voter")); + + placeholders.add(new PlaceHolder("Top_Month_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user's current top voter position")); + + if (plugin.getGui().isLastMonthGUI()) { + placeholders.add(new PlaceHolder("Top_LastMonth_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user top voter position for lastmonth")); + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_LastMonth_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user at position in last month top voter")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_LastMonthVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in last month top voter")); + + } + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Month_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get username at position in top voter")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_MonthVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in top voter")); + + placeholders.add(new PlaceHolder("Top_Week_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user top voter position")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Week_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get username at postion in top voter")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_WeekVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in top voter")); + + placeholders.add(new PlaceHolder("Top_Daily_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user top voter position")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Daily_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get username at postion in top voter")); + + placeholders.add(new PlaceHolder("VotePartyContributedVotes") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getVotePartyVotes(); + } + }.useStartsWith().withDescription("See vote party placeholders contributed").updateDataKey("VotePartyVotes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_DailyVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in top voter")); + + // non players + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesCurrent") { + + @Override + public String placeholderRequest(String identifier) { + return Integer.toString(plugin.getVoteParty().getTotalVotes()); + } + }.withDescription("Current amount of voteparty votes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesNeeded") { + + @Override + public String placeholderRequest(String identifier) { + return Integer.toString(plugin.getVoteParty().getNeededVotes()); + } + }.withDescription("Voteparty votes needed")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesRequired") { + + @Override + public String placeholderRequest(String identifier) { + return Integer.toString(plugin.getVoteParty().getVotesRequired()); + } + }.withDescription("Amount of votes needed for voteparty")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesCurrent") { + + @Override + public String placeholderRequest(String identifier) { + if (plugin.getBackendProxyHandler() != null) { + return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyCurrent()); + } + return "-1"; + } + }.withDescription("Current amount of bungee voteparty votes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesNeeded") { + + @Override + public String placeholderRequest(String identifier) { + if (plugin.getBackendProxyHandler() != null) { + return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyRequired() + - plugin.getBackendProxyHandler().getBungeeVotePartyCurrent()); + } + return "-1"; + } + }.withDescription("Voteparty bungee votes needed")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesRequired") { + + @Override + public String placeholderRequest(String identifier) { + if (plugin.getBackendProxyHandler() != null) { + return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyRequired()); + } + return "-1"; + } + }.withDescription("Amount of votes needed for bungee voteparty")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalMonthTotal") { + + @Override + public String placeholderRequest(String identifier) { + int total = 0; + for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Monthly).values()) { + total += num; + } + return Integer.toString(total); + } + }.withDescription("Global month total")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalAllTimeTotal") { + + @Override + public String placeholderRequest(String identifier) { + int total = 0; + for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.AllTime).values()) { + total += num; + } + return Integer.toString(total); + } + }.withDescription("Global alltime total")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalWeeklyTotal") { + + @Override + public String placeholderRequest(String identifier) { + int total = 0; + for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Weekly).values()) { + total += num; + } + return Integer.toString(total); + } + }.withDescription("Global weekly total")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalDailyTotal") { + + @Override + public String placeholderRequest(String identifier) { + int total = 0; + for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Daily).values()) { + total += num; + } + return Integer.toString(total); + } + }.withDescription("Global daily total")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilDayReset") { + + @Override + public String placeholderRequest(String identifier) { + LocalDateTime now = plugin.getTimeChecker().getTime(); + LocalDateTime offsetoclocktoday = plugin.getTimeChecker().getTime().withHour(0).withMinute(0); + LocalDateTime offsetoclocktomorrow = plugin.getTimeChecker().getTime().plusDays(1).withHour(0) + .withMinute(0); + + String timeMsg = "%hours% Hours %minutes% Minutes"; + Duration dur = null; + if (!now.isBefore(offsetoclocktoday)) { + dur = Duration.between(now, offsetoclocktomorrow); + + } else { + dur = Duration.between(now, offsetoclocktoday); + } + int diffHours = (int) (dur.getSeconds() / (60 * 60)); + long diffMinutes = dur.getSeconds() / 60 - diffHours * 60; + + if (diffHours < 0) { + diffHours = diffHours * -1; + } + if (diffHours >= 24) { + diffHours = diffHours - 24; + } + if (diffMinutes < 0) { + diffMinutes = diffMinutes * -1; + } + + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); + return timeMsg; + + } + }.withDescription("Time until plugin time day changes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilWeekReset") { + + @Override + public String placeholderRequest(String identifier) { + LocalDateTime now = plugin.getTimeChecker().getTime().plusDays(plugin.getOptions().getTimeWeekOffSet()); + LocalDateTime newWeek = plugin.getTimeChecker().getTime().withHour(0).withMinute(0); + + TemporalField woy = WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear(); + int weekNumber = newWeek.get(woy); + int newWeekNumber = weekNumber; + + while (weekNumber == newWeekNumber) { + newWeek = newWeek.plusDays(1); + newWeekNumber = newWeek.get(woy); + } + + String timeMsg = "%days% Days %hours% Hours %minutes% Minutes"; + Duration dur = Duration.between(now, newWeek); + + int diffDays = (int) (dur.getSeconds() / (60 * 60 * 24)); + int diffHours = (int) (dur.getSeconds() / (60 * 60) - diffDays * 24); + long diffMinutes = dur.getSeconds() / 60 - diffHours * 60 - diffDays * 24 * 60; + + if (diffHours < 0) { + diffHours = diffHours * -1; + } + if (diffHours >= 24) { + diffHours = diffHours - 24; + } + if (diffMinutes < 0) { + diffMinutes = diffMinutes * -1; + } + + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%days%", Integer.toString(diffDays)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); + return timeMsg; + + } + }.withDescription("Time until plugin time week changes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilMonthReset") { + + @Override + public String placeholderRequest(String identifier) { + LocalDateTime now = plugin.getTimeChecker().getTime(); + LocalDateTime newMonth = plugin.getTimeChecker().getTime().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0); + + String timeMsg = "%days% Days %hours% Hours %minutes% Minutes"; + Duration dur = Duration.between(now, newMonth); + + int diffDays = (int) (dur.getSeconds() / (60 * 60 * 24)); + int diffHours = (int) (dur.getSeconds() / (60 * 60) - diffDays * 24); + long diffMinutes = dur.getSeconds() / 60 - diffHours * 60 - diffDays * 24 * 60; + + if (diffHours < 0) { + diffHours = diffHours * -1; + } + if (diffHours >= 24) { + diffHours = diffHours - 24; + } + if (diffMinutes < 0) { + diffMinutes = diffMinutes * -1; + } + + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%days%", Integer.toString(diffDays)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); + return timeMsg; + + } + }.withDescription("Time until plugin time month changes")); + + Set placeholdersSet = new HashSet<>(); + placeholdersSet.addAll(plugin.getConfigFile().getCachedPlaceholders()); + if (getCacheLevel().equals(PlaceholderCacheLevel.AUTO)) { + placeholdersSet.addAll(plugin.getServerData().getAutoCachedPlaceholder()); + } + + for (String toCache : placeholdersSet) { + if (toCache.startsWith("votingplugin")) { + toCache = toCache.substring("votingplugin_".length()); + } + for (NonPlayerPlaceHolder placeholder : nonPlayerPlaceholders) { + if (placeholder.matches(toCache)) { + placeholder.setUseCache(true, toCache); + cachedPlaceholders.add(toCache); + plugin.extraDebug("Caching placeholder " + toCache); + } + } + + for (PlaceHolder placeholder : placeholders) { + if (placeholder.matches(toCache)) { + placeholder.setUseCache(true, toCache); + cachedPlaceholders.add(toCache); + plugin.extraDebug("Caching placeholder " + toCache); + } + } + } + + plugin.getUserManager().getUserDataChange().add(new UserDataChanged() { + + @Override + public void onChange(AdvancedCoreUser user, String... keys) { + VotingPluginUser vpUser = plugin.getVotingPluginUserManager().getVotingPluginUser(user); + if (!vpUser.isCached()) { + vpUser.userDataFetechMode(UserDataFetchMode.NO_CACHE); + } + for (PlaceHolder placeholder : placeholders) { + if (placeholder.isUsesCache()) { + if (placeholder.isCached(placeholder.getIdentifier(), user.getJavaUUID()) + || !getCacheLevel().onlineOnly() || user.isOnline()) { + if (placeholder instanceof CalculatingPlaceholder) { + CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; + if (placeholder.isUsesCache()) { + for (String key : keys) { + if (placeholder.getUpdateDataKey().equalsIgnoreCase(key)) { + for (String ident : placeholder.getCache().keySet()) { + String value = placeholder.placeholderRequest(vpUser, ident); + cPlaceholder.getCacheData().put(user.getJavaUUID(), + cPlaceholder.placeholderDataRequest(vpUser, ident)); + placeholder.getCache().get(ident).put(vpUser.getJavaUUID(), value); + plugin.devDebug("Updated calculating placeholder cache for " + + vpUser.getUUID() + " on " + key + " with " + value); + } + } + } + } + } else { + if (placeholder.isUsesCache()) { + for (String key : keys) { + if (placeholder.getUpdateDataKey().equalsIgnoreCase(key)) { + for (String ident : placeholder.getCache().keySet()) { + String value = placeholder.placeholderRequest(vpUser, ident); + placeholder.getCache().get(ident).put(vpUser.getJavaUUID(), value); + plugin.devDebug("Updated placeholder cache for " + vpUser.getUUID() + + " on " + key + " with " + value); + + } + + } + } + } + } + } + } + } + } + }); + } + + /** + * Handle player logout. + * @param user the voting plugin user + */ + public void onLogout(VotingPluginUser user) { + if (plugin.getPlaceholders().getCacheLevel().onlineOnly()) { + for (PlaceHolder placeholder : placeholders) { + if (placeholder.isUsesCache()) { + placeholder.clearCachePlayer(user.getJavaUUID()); + } + } + } + } + + /** + * Update all placeholders. + */ + public void onUpdate() { + checkNonCachedPlaceholders(); + for (Player p : Bukkit.getOnlinePlayers()) { + onUpdate(plugin.getVotingPluginUserManager().getVotingPluginUser(p), true); + } + /* + * for (NonPlayerPlaceHolder placeholder : + * nonPlayerPlaceholders) { if (placeholder.isUsesCache()) { for (String ident : + * placeholder.getCache().keySet()) { if (ident != null) { String str = + * placeholder.placeholderRequest(ident); if (str != null) { + * placeholder.getCache().put(ident, str); } } else { + * plugin.debug("ident null: " + placeholder.getIdentifier()); } } } } + */ + + } + + /** + * Update placeholders for specific user. + * @param user the voting plugin user + * @param login whether this is a login update + */ + public void onUpdate(VotingPluginUser user, boolean login) { + for (PlaceHolder placeholder : placeholders) { + if (placeholder.isUsesCache()) { + if (placeholder.isCached(placeholder.getIdentifier(), user.getJavaUUID()) || login) { + if (placeholder instanceof CalculatingPlaceholder) { + + CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; + if (placeholder.isUsesCache()) { + for (String ident : placeholder.getCache().keySet()) { + cPlaceholder.getCacheData().put(user.getJavaUUID(), + cPlaceholder.placeholderDataRequest(user, ident)); + placeholder.getCache().get(ident).put(user.getJavaUUID(), + placeholder.placeholderRequest(user, ident)); + } + + } + } else { + if (placeholder.isUsesCache()) { + for (String ident : placeholder.getCache().keySet()) { + placeholder.getCache().get(ident).put(user.getJavaUUID(), + placeholder.placeholderRequest(user, ident)); + } + } + } + } + } + } + } + + /** + * Handle vote party update. + */ + public void onVotePartyUpdate() { + /* + * for (NonPlayerPlaceHolder placeholder : + * nonPlayerPlaceholders) { if (placeholder.isUsesCache()) { if + * (placeholder.getIdentifier().startsWith("VoteParty")) { for (String ident : + * placeholder.getCache().keySet()) { placeholder.getCache().put(ident, + * placeholder.placeholderRequest(ident)); } } } } + */ + } + + /** + * Reload placeholders. + */ + public void reload() { + cacheLevel = plugin.getConfigFile().getPlaceholderCacheLevel(); + onUpdate(); + if (!cacheLevel.equals(PlaceholderCacheLevel.NONE)) { + for (Player player : Bukkit.getOnlinePlayers()) { + onUpdate(plugin.getVotingPluginUserManager().getVotingPluginUser(player), player.isOnline()); + } + } + } + + /** + * Schedule placeholder check for user. + * @param user the voting plugin user + */ + public void schedulePlaceholderCheck(VotingPluginUser user) { + plugin.getTimer().execute(new Runnable() { + + @Override + public void run() { + checkNonCachedPlaceholders(); + onUpdate(user, user.isOnline()); + } + }); + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java index 688eda03a1..1768edc18e 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java @@ -20,11 +20,6 @@ import lombok.Getter; import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class SignHandler. - */ public class SignHandler { @Getter diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/Signs.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/Signs.java index 6b1ab82794..6b39199cea 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/Signs.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/Signs.java @@ -1,92 +1,87 @@ -package com.bencodez.votingplugin.signs; - -import java.util.ArrayList; - -import org.bukkit.Location; - -import com.bencodez.votingplugin.VotingPluginMain; - -import lombok.Getter; -import lombok.Setter; - -// TODO: Auto-generated Javadoc -/** - * The Class Signs. - */ -public class Signs { - private VotingPluginMain plugin; - - @Getter - @Setter - private ArrayList signs; - - /** - * Constructs a new Signs manager. - * - * @param plugin the main plugin instance - */ - public Signs(VotingPluginMain plugin) { - this.plugin = plugin; - this.signs = new ArrayList<>(); - } - - /** - * Gets the sign from location. - * - * @param loc the loc - * @return the sign from location - */ - public String getSignFromLocation(Location loc) { - for (String sign : plugin.getServerData().getSigns()) { - if (plugin.getServerData().getSignLocation(sign).equals(loc)) { - return sign; - } - } - - return null; - } - - /** - * Load signs. - */ - public void loadSigns() { - setSigns(new ArrayList<>()); - for (String sign : plugin.getServerData().getSigns()) { - // plugin.getLogger().info("Loading sign " + sign); - getSigns().add(new SignHandler(plugin, sign, plugin.getServerData().getSignLocation(sign), - plugin.getServerData().getSignSkullLocation(sign), plugin.getServerData().getSignData(sign), - plugin.getServerData().getSignPosition(sign))); - } - } - - /** - * Store signs. - */ - public void storeSigns() { - for (SignHandler sign : getSigns()) { - sign.storeSign(); - } - } - - /** - * Update signs. - */ - public void updateSigns() { - int time = 0; - for (int i = getSigns().size() - 1; i >= 0; i--) { - if (!getSigns().get(i).isValid()) { - plugin.debug( - "Sign " + i + " invalid, removing from data: " + getSigns().get(i).getLocation().toString()); - getSigns().get(i).removeSign(); - getSigns().remove(i); - } else { - getSigns().get(i).updateLines(); - getSigns().get(i).updateSign(time); - time += 1; - } - } - - plugin.debug(getSigns().size() + " Signs updated"); - } - -} +package com.bencodez.votingplugin.signs; + +import java.util.ArrayList; + +import org.bukkit.Location; + +import com.bencodez.votingplugin.VotingPluginMain; + +import lombok.Getter; +import lombok.Setter; +public class Signs { + private VotingPluginMain plugin; + + @Getter + @Setter + private ArrayList signs; + + /** + * Constructs a new Signs manager. + * + * @param plugin the main plugin instance + */ + public Signs(VotingPluginMain plugin) { + this.plugin = plugin; + this.signs = new ArrayList<>(); + } + + /** + * Gets the sign from location. + * + * @param loc the loc + * @return the sign from location + */ + public String getSignFromLocation(Location loc) { + for (String sign : plugin.getServerData().getSigns()) { + if (plugin.getServerData().getSignLocation(sign).equals(loc)) { + return sign; + } + } + + return null; + } + + /** + * Load signs. + */ + public void loadSigns() { + setSigns(new ArrayList<>()); + for (String sign : plugin.getServerData().getSigns()) { + // plugin.getLogger().info("Loading sign " + sign); + getSigns().add(new SignHandler(plugin, sign, plugin.getServerData().getSignLocation(sign), + plugin.getServerData().getSignSkullLocation(sign), plugin.getServerData().getSignData(sign), + plugin.getServerData().getSignPosition(sign))); + } + } + + /** + * Store signs. + */ + public void storeSigns() { + for (SignHandler sign : getSigns()) { + sign.storeSign(); + } + } + + /** + * Update signs. + */ + public void updateSigns() { + int time = 0; + for (int i = getSigns().size() - 1; i >= 0; i--) { + if (!getSigns().get(i).isValid()) { + plugin.debug( + "Sign " + i + " invalid, removing from data: " + getSigns().get(i).getLocation().toString()); + getSigns().get(i).removeSign(); + getSigns().remove(i); + } else { + getSigns().get(i).updateLines(); + getSigns().get(i).updateSign(time); + time += 1; + } + } + + plugin.debug(getSigns().size() + " Signs updated"); + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewards.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewards.java index 54f7f515a3..f93a99ddf1 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewards.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewards.java @@ -1,121 +1,116 @@ -package com.bencodez.votingplugin.specialrewards; - -import java.util.Set; -import java.util.UUID; - -import org.bukkit.Bukkit; - -import com.bencodez.advancedcore.api.rewards.RewardBuilder; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.events.PlayerSpecialRewardEvent; -import com.bencodez.votingplugin.events.SpecialRewardType; -import com.bencodez.votingplugin.user.VotingPluginUser; - -// TODO: Auto-generated Javadoc -/** - * The Class OtherVoteReward. - */ -public class SpecialRewards { - - private VotingPluginMain plugin; - - /** - * Constructs a new SpecialRewards handler. - * - * @param plugin the main plugin instance - */ - public SpecialRewards(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * Checks and processes vote streak rewards for a user. - * - * @param voteUUID the vote UUID - * @param user the voting user - * @param type the streak type (day/week/month) - * @param forceBungee whether to force bungee mode - * @return true if a reward was given - */ - public boolean checkVoteStreak(UUID voteUUID, VotingPluginUser user, String type, boolean forceBungee) { - boolean gotReward = false; - - Set streaks = plugin.getSpecialRewardsConfig().getVoteStreakVotes(type); - for (String streak : streaks) { - boolean multiple = false; - if (streak.contains("-")) { - // multiple - multiple = true; - - } - String s = streak.replaceAll("-", ""); - - plugin.debug("Streak: " + streak + " multiple: " + multiple); - if (MessageAPI.isInt(s)) { - int streakRequired = Integer.parseInt(s); - if (streakRequired != 0) { - if (plugin.getSpecialRewardsConfig().getVoteStreakRewardEnabled(type, streak) - && plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(), - plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath(type, "" + streak))) { - int curStreak = 0; - if (type.equalsIgnoreCase("day")) { - curStreak = user.getDayVoteStreak(); - } else if (type.equalsIgnoreCase("week")) { - curStreak = user.getWeekVoteStreak(); - } else if (type.equalsIgnoreCase("month")) { - curStreak = user.getMonthVoteStreak(); - } - if (!multiple) { - if (curStreak == streakRequired) { - giveVoteStreakReward(voteUUID, user, user.isOnline(), type, "" + streakRequired, - curStreak, forceBungee); - gotReward = true; - plugin.debug( - user.getPlayerName() + " got VoteStreak " + streakRequired + " for " + type); - } - } else { - if (curStreak != 0 && curStreak % streakRequired == 0) { - giveVoteStreakReward(voteUUID, user, user.isOnline(), type, streak, curStreak, - forceBungee); - gotReward = true; - plugin.debug( - user.getPlayerName() + " got VoteStreak " + streakRequired + "* for " + type); - } - } - } - } - } - - } - - return gotReward; - - } - - /** - * Gives a vote streak reward to a user. - * - * @param voteUUID the vote UUID - * @param user the voting user - * @param online whether the user is online - * @param type the streak type - * @param string the streak value - * @param votes the current streak count - * @param forceBungee whether to force bungee mode - */ - public void giveVoteStreakReward(UUID voteUUID, VotingPluginUser user, boolean online, String type, String string, - int votes, boolean forceBungee) { - PlayerSpecialRewardEvent event = new PlayerSpecialRewardEvent(user, - SpecialRewardType.VOTESTREAK.setType(type).setAmount(votes), voteUUID); - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - return; - } - new RewardBuilder(plugin.getSpecialRewardsConfig().getData(), - plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath(type, string)).setOnline(online) - .withPlaceHolder("Type", type).setServer(forceBungee).withPlaceHolder("Streak", "" + votes).send(user); - } - -} +package com.bencodez.votingplugin.specialrewards; + +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; + +import com.bencodez.advancedcore.api.rewards.RewardBuilder; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.events.PlayerSpecialRewardEvent; +import com.bencodez.votingplugin.events.SpecialRewardType; +import com.bencodez.votingplugin.user.VotingPluginUser; +public class SpecialRewards { + + private VotingPluginMain plugin; + + /** + * Constructs a new SpecialRewards handler. + * + * @param plugin the main plugin instance + */ + public SpecialRewards(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * Checks and processes vote streak rewards for a user. + * + * @param voteUUID the vote UUID + * @param user the voting user + * @param type the streak type (day/week/month) + * @param forceBungee whether to force bungee mode + * @return true if a reward was given + */ + public boolean checkVoteStreak(UUID voteUUID, VotingPluginUser user, String type, boolean forceBungee) { + boolean gotReward = false; + + Set streaks = plugin.getSpecialRewardsConfig().getVoteStreakVotes(type); + for (String streak : streaks) { + boolean multiple = false; + if (streak.contains("-")) { + // multiple + multiple = true; + + } + String s = streak.replaceAll("-", ""); + + plugin.debug("Streak: " + streak + " multiple: " + multiple); + if (MessageAPI.isInt(s)) { + int streakRequired = Integer.parseInt(s); + if (streakRequired != 0) { + if (plugin.getSpecialRewardsConfig().getVoteStreakRewardEnabled(type, streak) + && plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(), + plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath(type, "" + streak))) { + int curStreak = 0; + if (type.equalsIgnoreCase("day")) { + curStreak = user.getDayVoteStreak(); + } else if (type.equalsIgnoreCase("week")) { + curStreak = user.getWeekVoteStreak(); + } else if (type.equalsIgnoreCase("month")) { + curStreak = user.getMonthVoteStreak(); + } + if (!multiple) { + if (curStreak == streakRequired) { + giveVoteStreakReward(voteUUID, user, user.isOnline(), type, "" + streakRequired, + curStreak, forceBungee); + gotReward = true; + plugin.debug( + user.getPlayerName() + " got VoteStreak " + streakRequired + " for " + type); + } + } else { + if (curStreak != 0 && curStreak % streakRequired == 0) { + giveVoteStreakReward(voteUUID, user, user.isOnline(), type, streak, curStreak, + forceBungee); + gotReward = true; + plugin.debug( + user.getPlayerName() + " got VoteStreak " + streakRequired + "* for " + type); + } + } + } + } + } + + } + + return gotReward; + + } + + /** + * Gives a vote streak reward to a user. + * + * @param voteUUID the vote UUID + * @param user the voting user + * @param online whether the user is online + * @param type the streak type + * @param string the streak value + * @param votes the current streak count + * @param forceBungee whether to force bungee mode + */ + public void giveVoteStreakReward(UUID voteUUID, VotingPluginUser user, boolean online, String type, String string, + int votes, boolean forceBungee) { + PlayerSpecialRewardEvent event = new PlayerSpecialRewardEvent(user, + SpecialRewardType.VOTESTREAK.setType(type).setAmount(votes), voteUUID); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + return; + } + new RewardBuilder(plugin.getSpecialRewardsConfig().getData(), + plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath(type, string)).setOnline(online) + .withPlaceHolder("Type", type).setServer(forceBungee).withPlaceHolder("Streak", "" + votes).send(user); + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/updater/CheckUpdate.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/updater/CheckUpdate.java index e745c8c74c..f9be83a629 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/updater/CheckUpdate.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/updater/CheckUpdate.java @@ -1,102 +1,97 @@ -package com.bencodez.votingplugin.updater; - -import java.util.Timer; -import java.util.TimerTask; - -import com.bencodez.simpleapi.updater.Updater; -import com.bencodez.votingplugin.VotingPluginMain; - -// TODO: Auto-generated Javadoc -/** - * The Class CheckUpdate. - */ -public class CheckUpdate { - - private VotingPluginMain plugin; - - /** - * Constructs a new CheckUpdate instance. - * - * @param plugin the main plugin instance - */ - public CheckUpdate(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * Check update. - */ - public void checkUpdate() { - if (plugin.getConfigFile().isDisableUpdateChecking() - || plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { - return; - } - plugin.setUpdater(new Updater(plugin, 15358, false)); - final Updater.UpdateResult result = plugin.getUpdater().getResult(); - switch (result) { - case FAIL_SPIGOT: { - plugin.getLogger().info("Failed to check for update for " + plugin.getName() + "!"); - break; - } - case NO_UPDATE: { - plugin.getLogger().info(plugin.getName() + " is up to date! Version: " + plugin.getUpdater().getVersion()); - break; - } - case UPDATE_AVAILABLE: { - plugin.getLogger().info(plugin.getName() + " has an update available! Your Version: " - + plugin.getDescription().getVersion() + " New Version: " + plugin.getUpdater().getVersion()); - break; - } - default: { - break; - } - } - } - - /** - * Performs a basic update check without downloading. - */ - public void checkUpdateBasic() { - if (plugin.getConfigFile().isDisableUpdateChecking()) { - return; - } - plugin.setUpdater(new Updater(plugin, 15358, false)); - final Updater.UpdateResult result = plugin.getUpdater().getResult(); - switch (result) { - case UPDATE_AVAILABLE: { - plugin.getLogger().info(plugin.getName() + " has an update available! Your Version: " - + plugin.getDescription().getVersion() + " New Version: " + plugin.getUpdater().getVersion()); - break; - } - default: { - break; - } - } - } - - /** - * Start up. - */ - public void startUp() { - if (plugin.getConfigFile().isDisableUpdateChecking() - || plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { - return; - } - plugin.getBukkitScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { - - @Override - public void run() { - checkUpdate(); - new Timer().schedule(new TimerTask() { - - @Override - public void run() { - checkUpdateBasic(); - } - }, 1000 * 60 * 1200, 1000 * 60 * 1200); - - } - }, 10); - } - -} +package com.bencodez.votingplugin.updater; + +import java.util.Timer; +import java.util.TimerTask; + +import com.bencodez.simpleapi.updater.Updater; +import com.bencodez.votingplugin.VotingPluginMain; +public class CheckUpdate { + + private VotingPluginMain plugin; + + /** + * Constructs a new CheckUpdate instance. + * + * @param plugin the main plugin instance + */ + public CheckUpdate(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * Check update. + */ + public void checkUpdate() { + if (plugin.getConfigFile().isDisableUpdateChecking() + || plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { + return; + } + plugin.setUpdater(new Updater(plugin, 15358, false)); + final Updater.UpdateResult result = plugin.getUpdater().getResult(); + switch (result) { + case FAIL_SPIGOT: { + plugin.getLogger().info("Failed to check for update for " + plugin.getName() + "!"); + break; + } + case NO_UPDATE: { + plugin.getLogger().info(plugin.getName() + " is up to date! Version: " + plugin.getUpdater().getVersion()); + break; + } + case UPDATE_AVAILABLE: { + plugin.getLogger().info(plugin.getName() + " has an update available! Your Version: " + + plugin.getDescription().getVersion() + " New Version: " + plugin.getUpdater().getVersion()); + break; + } + default: { + break; + } + } + } + + /** + * Performs a basic update check without downloading. + */ + public void checkUpdateBasic() { + if (plugin.getConfigFile().isDisableUpdateChecking()) { + return; + } + plugin.setUpdater(new Updater(plugin, 15358, false)); + final Updater.UpdateResult result = plugin.getUpdater().getResult(); + switch (result) { + case UPDATE_AVAILABLE: { + plugin.getLogger().info(plugin.getName() + " has an update available! Your Version: " + + plugin.getDescription().getVersion() + " New Version: " + plugin.getUpdater().getVersion()); + break; + } + default: { + break; + } + } + } + + /** + * Start up. + */ + public void startUp() { + if (plugin.getConfigFile().isDisableUpdateChecking() + || plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { + return; + } + plugin.getBukkitScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { + + @Override + public void run() { + checkUpdate(); + new Timer().schedule(new TimerTask() { + + @Override + public void run() { + checkUpdateBasic(); + } + }, 1000 * 60 * 1200, 1000 * 60 * 1200); + + } + }, 10); + } + +} 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 89ca8d2ce1..0fff9d62df 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSite.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSite.java @@ -1,206 +1,202 @@ -package com.bencodez.votingplugin.votesites; - -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; - -import com.bencodez.advancedcore.api.item.ItemBuilder; -import com.bencodez.advancedcore.api.messages.PlaceholderUtils; -import com.bencodez.advancedcore.api.rewards.RewardBuilder; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.time.ParsedDuration; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.user.VotingPluginUser; - -import lombok.Getter; -import lombok.Setter; - -/** - * The Class VoteSite. - */ -public class VoteSite { - @Getter - @Setter - private String displayName; - - @Getter - @Setter - private boolean enabled; - - @Getter - @Setter - private boolean giveOffline; - - @Getter - @Setter - private boolean hidden; - - @Getter - @Setter - private boolean ignoreCanVote; - - @Setter - private ConfigurationSection item; - - @Getter - @Setter - private String key; - - private VotingPluginMain plugin; - - @Getter - @Setter - private int priority; - - @Getter - @Setter - private String serviceSite; - - @Getter - @Setter - private int voteDelayDailyHour; - - @Getter - @Setter - private boolean voteDelayDaily; - - @Getter - private ParsedDuration voteDelay; - - @Setter - private String voteURL; - - @Getter - @Setter - private String permissionToView; - - @Getter - @Setter - private boolean waitUntilVoteDelay; - - public VoteSite(VotingPluginMain plugin, String siteName) { - this.plugin = plugin; - key = siteName.replace(".", "_"); - init(); - } - - /** - * @return the item - */ - public ItemBuilder getItem() { - if (item == null) { - plugin.getLogger().warning("Invalid display item section in site: " + key); - return new ItemBuilder(Material.STONE, 1).setName("&cInvalid display item for site: " + key) - .setLore("&cInvalid display item for site: " + key); - } - return new ItemBuilder(item); - } - - public ConfigurationSection getSiteData() { - return plugin.getConfigVoteSites().getData(key); - } - - public String getVoteURL() { - return getVoteURL(true); - } - - public String getVoteURL(boolean json) { - if (!plugin.getConfigFile().isFormatCommandsVoteForceLinks() || !json || MessageAPI.containsJson(voteURL)) { - return voteURL; - } - if (!voteURL.startsWith("http")) { - return "[Text=\"" + voteURL + "\",url=\"http://" + voteURL + "\"]"; - } - return "[Text=\"" + voteURL + "\",url=\"" + voteURL + "\"]"; - } - - public String getVoteURLJsonStrip() { - String url = ChatColor - .stripColor(MessageAPI.colorize(PlaceholderUtils.parseJson(getVoteURL(false)).toPlainText())); - if (!url.startsWith("http")) { - if (!url.startsWith("www.")) { - url = "https://www." + url; - } else { - url = "https://" + url; - } - } - return url; - } - - public void giveRewards(VotingPluginUser user, boolean online, boolean bungee) { - new RewardBuilder(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getEverySiteRewardPath()) - .setOnline(online).withPlaceHolder("ServiceSite", getServiceSite()) - .withPlaceHolder("SiteName", getDisplayName()).withPlaceHolder("VoteDelay", "" + getVoteDelay()) - .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); - - new RewardBuilder(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getRewardsPath(key)) - .setOnline(online).withPlaceHolder("ServiceSite", getServiceSite()) - .withPlaceHolder("SiteName", getDisplayName()).withPlaceHolder("VoteDelay", "" + getVoteDelay()) - .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); - - } - - /** - * 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)); - } - - /** - * Inits the. - */ - public void init() { - setVoteURL(plugin.getConfigVoteSites().getVoteURL(key)); - setServiceSite(plugin.getConfigVoteSites().getServiceSite(key)); - this.voteDelay = plugin.getConfigVoteSites().getVoteDelay(key); - setEnabled(plugin.getConfigVoteSites().getVoteSiteEnabled(key)); - setPriority(plugin.getConfigVoteSites().getPriority(key)); - displayName = plugin.getConfigVoteSites().getDisplayName(key); - if (displayName == null || displayName.equals("")) { - displayName = key; - } - item = plugin.getConfigVoteSites().getItem(key); - voteDelayDaily = plugin.getConfigVoteSites().getVoteSiteResetVoteDelayDaily(key); - giveOffline = plugin.getConfigVoteSites().getVoteSiteGiveOffline(key); - waitUntilVoteDelay = plugin.getConfigVoteSites().getWaitUntilVoteDelay(key); - voteDelayDailyHour = plugin.getConfigVoteSites().getVoteDelayDailyHour(key); - hidden = plugin.getConfigVoteSites().getVoteSiteHidden(key); - ignoreCanVote = plugin.getConfigVoteSites().getVoteSiteIgnoreCanVote(key); - permissionToView = plugin.getConfigVoteSites().getPermissionToView(key); - } - - public boolean isVaidServiceSite() { - return ArrayUtils.containsIgnoreCase(plugin.getServerData().getServiceSites(), getServiceSite()); - } - - public String loadingDebug() { - String str = "Loading votesite key: " + key; - str += ", Displayname: " + displayName; - str += ", VoteDelay: " + getVoteDelay(); - str += ", VoteDelayDaily: " + isVoteDelayDaily(); - str += ", IsWaitUntilVoteDelay: " + isWaitUntilVoteDelay(); - str += ", ServiceSite: " + getServiceSite(); - str += ", VoteDelayDailyHour:" + getVoteDelayDailyHour(); - str += ", Url: " + getVoteURL(); - str += ", IgnoreCanVote: " + isIgnoreCanVote(); - str += ", Hidden: " + isHidden(); - return str; - } - -} +package com.bencodez.votingplugin.votesites; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.advancedcore.api.item.ItemBuilder; +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.rewards.RewardBuilder; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.simpleapi.time.ParsedDuration; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.user.VotingPluginUser; + +import lombok.Getter; +import lombok.Setter; +public class VoteSite { + @Getter + @Setter + private String displayName; + + @Getter + @Setter + private boolean enabled; + + @Getter + @Setter + private boolean giveOffline; + + @Getter + @Setter + private boolean hidden; + + @Getter + @Setter + private boolean ignoreCanVote; + + @Setter + private ConfigurationSection item; + + @Getter + @Setter + private String key; + + private VotingPluginMain plugin; + + @Getter + @Setter + private int priority; + + @Getter + @Setter + private String serviceSite; + + @Getter + @Setter + private int voteDelayDailyHour; + + @Getter + @Setter + private boolean voteDelayDaily; + + @Getter + private ParsedDuration voteDelay; + + @Setter + private String voteURL; + + @Getter + @Setter + private String permissionToView; + + @Getter + @Setter + private boolean waitUntilVoteDelay; + + public VoteSite(VotingPluginMain plugin, String siteName) { + this.plugin = plugin; + key = siteName.replace(".", "_"); + init(); + } + + /** + * @return the item + */ + public ItemBuilder getItem() { + if (item == null) { + plugin.getLogger().warning("Invalid display item section in site: " + key); + return new ItemBuilder(Material.STONE, 1).setName("&cInvalid display item for site: " + key) + .setLore("&cInvalid display item for site: " + key); + } + return new ItemBuilder(item); + } + + public ConfigurationSection getSiteData() { + return plugin.getConfigVoteSites().getData(key); + } + + public String getVoteURL() { + return getVoteURL(true); + } + + public String getVoteURL(boolean json) { + if (!plugin.getConfigFile().isFormatCommandsVoteForceLinks() || !json || MessageAPI.containsJson(voteURL)) { + return voteURL; + } + if (!voteURL.startsWith("http")) { + return "[Text=\"" + voteURL + "\",url=\"http://" + voteURL + "\"]"; + } + return "[Text=\"" + voteURL + "\",url=\"" + voteURL + "\"]"; + } + + public String getVoteURLJsonStrip() { + String url = ChatColor + .stripColor(MessageAPI.colorize(PlaceholderUtils.parseJson(getVoteURL(false)).toPlainText())); + if (!url.startsWith("http")) { + if (!url.startsWith("www.")) { + url = "https://www." + url; + } else { + url = "https://" + url; + } + } + return url; + } + + public void giveRewards(VotingPluginUser user, boolean online, boolean bungee) { + new RewardBuilder(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getEverySiteRewardPath()) + .setOnline(online).withPlaceHolder("ServiceSite", getServiceSite()) + .withPlaceHolder("SiteName", getDisplayName()).withPlaceHolder("VoteDelay", "" + getVoteDelay()) + .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); + + new RewardBuilder(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getRewardsPath(key)) + .setOnline(online).withPlaceHolder("ServiceSite", getServiceSite()) + .withPlaceHolder("SiteName", getDisplayName()).withPlaceHolder("VoteDelay", "" + getVoteDelay()) + .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); + + } + + /** + * 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)); + } + + /** + * Inits the. + */ + public void init() { + setVoteURL(plugin.getConfigVoteSites().getVoteURL(key)); + setServiceSite(plugin.getConfigVoteSites().getServiceSite(key)); + this.voteDelay = plugin.getConfigVoteSites().getVoteDelay(key); + setEnabled(plugin.getConfigVoteSites().getVoteSiteEnabled(key)); + setPriority(plugin.getConfigVoteSites().getPriority(key)); + displayName = plugin.getConfigVoteSites().getDisplayName(key); + if (displayName == null || displayName.equals("")) { + displayName = key; + } + item = plugin.getConfigVoteSites().getItem(key); + voteDelayDaily = plugin.getConfigVoteSites().getVoteSiteResetVoteDelayDaily(key); + giveOffline = plugin.getConfigVoteSites().getVoteSiteGiveOffline(key); + waitUntilVoteDelay = plugin.getConfigVoteSites().getWaitUntilVoteDelay(key); + voteDelayDailyHour = plugin.getConfigVoteSites().getVoteDelayDailyHour(key); + hidden = plugin.getConfigVoteSites().getVoteSiteHidden(key); + ignoreCanVote = plugin.getConfigVoteSites().getVoteSiteIgnoreCanVote(key); + permissionToView = plugin.getConfigVoteSites().getPermissionToView(key); + } + + public boolean isVaidServiceSite() { + return ArrayUtils.containsIgnoreCase(plugin.getServerData().getServiceSites(), getServiceSite()); + } + + public String loadingDebug() { + String str = "Loading votesite key: " + key; + str += ", Displayname: " + displayName; + str += ", VoteDelay: " + getVoteDelay(); + str += ", VoteDelayDaily: " + isVoteDelayDaily(); + str += ", IsWaitUntilVoteDelay: " + isWaitUntilVoteDelay(); + str += ", ServiceSite: " + getServiceSite(); + str += ", VoteDelayDailyHour:" + getVoteDelayDailyHour(); + str += ", Url: " + getVoteURL(); + str += ", IgnoreCanVote: " + isIgnoreCanVote(); + str += ", Hidden: " + isHidden(); + return str; + } + +} From 67666caeead9ca6fab67219db78b034fc453cd79 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:21:20 +0000 Subject: [PATCH 68/71] Remove temporary comment cleanup workflow --- .../cleanup-generated-comments-round2.yml | 67 ------------------- 1 file changed, 67 deletions(-) delete mode 100644 .github/workflows/cleanup-generated-comments-round2.yml diff --git a/.github/workflows/cleanup-generated-comments-round2.yml b/.github/workflows/cleanup-generated-comments-round2.yml deleted file mode 100644 index 5513c778c2..0000000000 --- a/.github/workflows/cleanup-generated-comments-round2.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Clean generated comments round 2 - -on: - pull_request: - branches: - - master - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - cleanup: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: cleanup/generated-comments-round2 - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '21' - cache: maven - - name: Remove generated comment boilerplate - run: | - python - <<'PY' - from pathlib import Path - import re - - root = Path('VotingPlugin/src/main/java') - changed = [] - for path in root.rglob('*.java'): - text = path.read_text() - original = text - text = re.sub(r'(?m)^\s*// TODO: Auto-generated Javadoc\s*\n', '', text) - text = re.sub(r'(?ms)^\s*/\*\*\s*\n\s*\* The Class [^\n]+\.\s*\n\s*\*/\s*\n', '', text) - text = re.sub(r'(?ms)^\s*/\*\s*\n\s*\* \(non-Javadoc\).*?\*/\s*\n', '', text) - if text != original: - path.write_text(text) - changed.append(str(path)) - - if not changed: - raise SystemExit('No generated comment boilerplate found') - print('\n'.join(changed)) - PY - - name: Verify generated markers are gone - run: | - if grep -R --line-number --include='*.java' 'TODO: Auto-generated Javadoc\|(non-Javadoc)' VotingPlugin/src/main/java; then - echo 'Generated comment markers remain' - exit 1 - fi - - name: Build - run: mvn -B -f VotingPlugin/pom.xml package - - name: Commit cleanup - run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A VotingPlugin - git commit -m 'Remove remaining generated comment boilerplate' - git push origin HEAD:cleanup/generated-comments-round2 - - name: Remove temporary workflow - run: | - git pull --rebase origin cleanup/generated-comments-round2 - git rm .github/workflows/cleanup-generated-comments-round2.yml - git commit -m 'Remove temporary comment cleanup workflow' - git push origin HEAD:cleanup/generated-comments-round2 From ff205da59120a4cfb4ef97f4b403b8561b11d70e Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 24 Aug 2026 18:21:55 -0600 Subject: [PATCH 69/71] Preserve line endings in generated comment cleanup --- .../preserve-comment-cleanup-line-endings.yml | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .github/workflows/preserve-comment-cleanup-line-endings.yml diff --git a/.github/workflows/preserve-comment-cleanup-line-endings.yml b/.github/workflows/preserve-comment-cleanup-line-endings.yml new file mode 100644 index 0000000000..8fa0161f68 --- /dev/null +++ b/.github/workflows/preserve-comment-cleanup-line-endings.yml @@ -0,0 +1,61 @@ +name: Preserve comment cleanup line endings + +on: + pull_request: + branches: + - master + types: [opened, synchronize, reopened] + +permissions: + contents: write + +jobs: + cleanup: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: cleanup/generated-comments-round2 + fetch-depth: 0 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + - name: Reapply cleanup preserving line endings + run: | + git fetch origin refactor/voteparty-components + git checkout origin/refactor/voteparty-components -- VotingPlugin/src/main/java + python - <<'PY' + from pathlib import Path + import re + + root = Path('VotingPlugin/src/main/java') + for path in root.rglob('*.java'): + data = path.read_bytes() + original = data + data = re.sub(rb'(?m)^[ \t]*// TODO: Auto-generated Javadoc[ \t]*\r?\n', b'', data) + data = re.sub(rb'(?ms)^[ \t]*/\*\*[ \t]*\r?\n[ \t]*\* The Class [^\r\n]+\.[ \t]*\r?\n[ \t]*\*/[ \t]*\r?\n', b'', data) + data = re.sub(rb'(?ms)^[ \t]*/\*[ \t]*\r?\n[ \t]*\* \(non-Javadoc\).*?\*/[ \t]*\r?\n', b'', data) + if data != original: + path.write_bytes(data) + PY + if grep -R --line-number --include='*.java' 'TODO: Auto-generated Javadoc\|(non-Javadoc)' VotingPlugin/src/main/java; then + exit 1 + fi + - name: Build + run: mvn -B -f VotingPlugin/pom.xml package + - name: Commit clean diff + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A VotingPlugin/src/main/java + git commit -m 'Preserve line endings in comment cleanup' + git push origin HEAD:cleanup/generated-comments-round2 + - name: Remove temporary workflow + run: | + git pull --rebase origin cleanup/generated-comments-round2 + git rm .github/workflows/preserve-comment-cleanup-line-endings.yml + git commit -m 'Remove temporary line ending cleanup workflow' + git push origin HEAD:cleanup/generated-comments-round2 From 5f8d19658e5698a38cdfe538f3da174863d86437 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:22:40 +0000 Subject: [PATCH 70/71] Preserve line endings in comment cleanup --- .../votingplugin/VotingPluginMain.java | 1 + .../votingplugin/commands/CommandLoader.java | 1 + .../tabcompleter/AdminVoteTabCompleter.java | 2 + .../tabcompleter/AliasesTabCompleter.java | 2 + .../bencodez/votingplugin/config/Config.java | 1893 ++++++------ .../votingplugin/config/ConfigVoteSites.java | 1349 ++++----- .../votingplugin/data/ServerData.java | 1111 +++---- .../events/PlayerPostVoteEvent.java | 226 +- .../events/PlayerReceivePointsEvent.java | 114 +- .../events/PlayerSpecialRewardEvent.java | 122 +- .../events/PlayerVoteCoolDownEndEvent.java | 94 +- .../votingplugin/events/PlayerVoteEvent.java | 206 +- .../PlayerVoteSiteCoolDownEndEvent.java | 108 +- .../votingplugin/events/VotePartyEvent.java | 76 +- .../votingplugin/listeners/BlockBreak.java | 105 +- .../listeners/PlayerInteract.java | 169 +- .../listeners/PlayerJoinEvent.java | 251 +- .../listeners/PlayerVoteListener.java | 575 ++-- .../votingplugin/listeners/SignChange.java | 125 +- .../votingplugin/listeners/VotiferEvent.java | 265 +- .../listeners/VotingPluginUpdateEvent.java | 75 +- .../placeholders/MVdWPlaceholders.java | 1 + .../placeholders/PlaceHolders.java | 2641 +++++++++-------- .../votingplugin/signs/SignHandler.java | 1 + .../bencodez/votingplugin/signs/Signs.java | 175 +- .../specialrewards/SpecialRewards.java | 233 +- .../votingplugin/updater/CheckUpdate.java | 195 +- .../votingplugin/votesites/VoteSite.java | 405 +-- 28 files changed, 5279 insertions(+), 5242 deletions(-) diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java index dcc163bcb4..60c2fdaebe 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/VotingPluginMain.java @@ -129,6 +129,7 @@ import lombok.Getter; import lombok.Setter; + public class VotingPluginMain extends AdvancedCorePlugin { @Getter diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/CommandLoader.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/CommandLoader.java index fb4b46ec45..2089d592ce 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/CommandLoader.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/CommandLoader.java @@ -90,6 +90,7 @@ import com.bencodez.votingplugin.topvoter.TopVoter; import com.bencodez.votingplugin.user.VotingPluginUser; import com.bencodez.votingplugin.votesites.VoteSite; + public class CommandLoader { private String adminPerm = "VotingPlugin.Admin"; diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AdminVoteTabCompleter.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AdminVoteTabCompleter.java index 341ec79bbc..ec27b226c1 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AdminVoteTabCompleter.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AdminVoteTabCompleter.java @@ -13,10 +13,12 @@ import com.bencodez.advancedcore.api.command.AdvancedCoreTabCompleteHandler; import com.bencodez.simpleapi.messages.MessageAPI; import com.bencodez.votingplugin.VotingPluginMain; + public class AdminVoteTabCompleter implements TabCompleter { /** The plugin. */ VotingPluginMain plugin = VotingPluginMain.plugin; + @Override public List onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) { diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AliasesTabCompleter.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AliasesTabCompleter.java index 9e167575c4..953ede0fb4 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AliasesTabCompleter.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/commands/tabcompleter/AliasesTabCompleter.java @@ -16,6 +16,7 @@ import com.bencodez.simpleapi.command.TabCompleteHandler; import com.bencodez.simpleapi.messages.MessageAPI; import com.bencodez.votingplugin.VotingPluginMain; + public class AliasesTabCompleter implements TabCompleter { private boolean adminCommand; @@ -25,6 +26,7 @@ public class AliasesTabCompleter implements TabCompleter { /** The plugin. */ VotingPluginMain plugin = VotingPluginMain.plugin; + @Override public List onTabComplete(CommandSender sender, Command cmd, String alias, String[] argsIn) { ArrayList msgArray = new ArrayList<>(); diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/Config.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/Config.java index ad3835c19a..4e52787b2b 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/Config.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/Config.java @@ -1,81 +1,82 @@ -package com.bencodez.votingplugin.config; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -import org.bukkit.configuration.ConfigurationSection; - -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.simpleapi.file.YMLFile; -import com.bencodez.simpleapi.file.annotation.AnnotationHandler; -import com.bencodez.simpleapi.file.annotation.ConfigDataBoolean; -import com.bencodez.simpleapi.file.annotation.ConfigDataInt; -import com.bencodez.simpleapi.file.annotation.ConfigDataKeys; -import com.bencodez.simpleapi.file.annotation.ConfigDataListString; -import com.bencodez.simpleapi.file.annotation.ConfigDataLong; -import com.bencodez.simpleapi.file.annotation.ConfigDataString; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.placeholders.PlaceholderCacheLevel; -import com.bencodez.votingplugin.topvoter.TopVoter; - -import lombok.Getter; -public class Config extends YMLFile { - - @ConfigDataBoolean(path = "AddCustomCommands") - @Getter - private boolean addCustomCommands = false; - - @ConfigDataBoolean(path = "AddTotals") - @Getter - private boolean addTotals = true; - - @ConfigDataBoolean(path = "AddTotalsOffline") - @Getter - private boolean addTotalsOffline = true; - - @ConfigDataBoolean(path = "LoadInteralExpansion") - @Getter - private boolean loadInteralExpansion = true; - - @ConfigDataBoolean(path = "PerSiteCoolDownEvents") - @Getter - private boolean perSiteCoolDownEvents = false; - - @ConfigDataInt(path = "LimitVotePoints") - @Getter - private int limitVotePoints = -1; - - /** Whether YAML files should be case insensitive. */ - @ConfigDataBoolean(path = "CaseInsensitiveYMLFiles") - @Getter - public boolean caseInsensitiveYMLFiles = false; - - @ConfigDataBoolean(path = "QueueVotesDuringTimeChange") - @Getter - private boolean queueVotesDuringTimeChange = false; - - @ConfigDataBoolean(path = "AdvancedServiceSiteHandling") - @Getter - private boolean advancedServiceSiteHandling = false; - - @ConfigDataBoolean(path = "AllowUnjoined") - @Getter - private boolean allowUnjoined = false; - - @ConfigDataBoolean(path = "PreloadSkulls") - @Getter - private boolean preloadSkulls = false; - - @ConfigDataBoolean(path = "DiscordSRV.Enabled") - @Getter - private boolean discordSRVEnabled = false; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.Enabled") - @Getter - private boolean discordSRVTopVoterAllTimeEnabled = false; - +package com.bencodez.votingplugin.config; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.simpleapi.file.YMLFile; +import com.bencodez.simpleapi.file.annotation.AnnotationHandler; +import com.bencodez.simpleapi.file.annotation.ConfigDataBoolean; +import com.bencodez.simpleapi.file.annotation.ConfigDataInt; +import com.bencodez.simpleapi.file.annotation.ConfigDataKeys; +import com.bencodez.simpleapi.file.annotation.ConfigDataListString; +import com.bencodez.simpleapi.file.annotation.ConfigDataLong; +import com.bencodez.simpleapi.file.annotation.ConfigDataString; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.placeholders.PlaceholderCacheLevel; +import com.bencodez.votingplugin.topvoter.TopVoter; + +import lombok.Getter; + +public class Config extends YMLFile { + + @ConfigDataBoolean(path = "AddCustomCommands") + @Getter + private boolean addCustomCommands = false; + + @ConfigDataBoolean(path = "AddTotals") + @Getter + private boolean addTotals = true; + + @ConfigDataBoolean(path = "AddTotalsOffline") + @Getter + private boolean addTotalsOffline = true; + + @ConfigDataBoolean(path = "LoadInteralExpansion") + @Getter + private boolean loadInteralExpansion = true; + + @ConfigDataBoolean(path = "PerSiteCoolDownEvents") + @Getter + private boolean perSiteCoolDownEvents = false; + + @ConfigDataInt(path = "LimitVotePoints") + @Getter + private int limitVotePoints = -1; + + /** Whether YAML files should be case insensitive. */ + @ConfigDataBoolean(path = "CaseInsensitiveYMLFiles") + @Getter + public boolean caseInsensitiveYMLFiles = false; + + @ConfigDataBoolean(path = "QueueVotesDuringTimeChange") + @Getter + private boolean queueVotesDuringTimeChange = false; + + @ConfigDataBoolean(path = "AdvancedServiceSiteHandling") + @Getter + private boolean advancedServiceSiteHandling = false; + + @ConfigDataBoolean(path = "AllowUnjoined") + @Getter + private boolean allowUnjoined = false; + + @ConfigDataBoolean(path = "PreloadSkulls") + @Getter + private boolean preloadSkulls = false; + + @ConfigDataBoolean(path = "DiscordSRV.Enabled") + @Getter + private boolean discordSRVEnabled = false; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.Enabled") + @Getter + private boolean discordSRVTopVoterAllTimeEnabled = false; + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.NewMessageOnUpdate") @Getter private boolean discordSRVTopVoterAllTimeNewMessageOnUpdate = false; @@ -83,871 +84,871 @@ public class Config extends YMLFile { @ConfigDataBoolean(path = "DiscordSRV.TopVoter.AutoRecoverMessageOnFailure") @Getter private boolean discordSRVTopVoterAutoRecoverMessageOnFailure = true; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.NewMessageOnUpdate") - @Getter - private boolean discordSRVTopVoterMonthlyNewMessageOnUpdate = false; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.NewMessageOnUpdate") - @Getter - private boolean discordSRVTopVoterWeeklyNewMessageOnUpdate = false; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.NewMessageOnUpdate") - @Getter - private boolean discordSRVTopVoterDailyNewMessageOnUpdate = false; - - @ConfigDataLong(path = "DiscordSRV.TopVoter.AllTime.Channel") - @Getter - private long discordSRVTopVoterAllTimeChannel = 0; - - @ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.Title") - @Getter - private String discordSRVTopVoterAllTimeTitle = "All Time Top Voters"; - - @ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.RankDisplay") - @Getter - private String discordSRVTopVoterAllTimeRankDisplay = "%rank%: %player% - %votes% Votes"; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.Enabled") - @Getter - private boolean discordSRVTopVoterMonthlyEnabled = false; - - @ConfigDataLong(path = "DiscordSRV.TopVoter.Monthly.Channel") - @Getter - private long discordSRVTopVoterMonthlyChannel = 0; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.Title") - @Getter - private String discordSRVTopVoterMonthlyTitle = "Top Voters of the Month"; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.RankDisplay") - @Getter - private String discordSRVTopVoterMonthlyRankDisplay = "%rank%: %player% - %votes% Votes"; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.Enabled") - @Getter - private boolean discordSRVTopVoterWeeklyEnabled = false; - - @ConfigDataLong(path = "DiscordSRV.TopVoter.Weekly.Channel") - @Getter - private long discordSRVTopVoterWeeklyChannel = 0; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.Title") - @Getter - private String discordSRVTopVoterWeeklyTitle = "Top Voters of the Week"; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.RankDisplay") - @Getter - private String discordSRVTopVoterWeeklyRankDisplay = "%rank%: %player% - %votes% Votes"; - - @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.Enabled") - @Getter - private boolean discordSRVTopVoterDailyEnabled = false; - - @ConfigDataLong(path = "DiscordSRV.TopVoter.Daily.Channel") - @Getter - private long discordSRVTopVoterDailyChannel = 0; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Daily.Title") - @Getter - private String discordSRVTopVoterDailyTitle = "Top Voters of the Day"; - - @ConfigDataString(path = "DiscordSRV.TopVoter.Daily.RankDisplay") - @Getter - private String discordSRVTopVoterDailyRankDisplay = "%rank%: %player% - %votes% Votes"; - - // VoteLogging configuration section - minimal options mirror Config.yml - @ConfigDataBoolean(path = "VoteLogging.Enabled") - @Getter - private boolean voteLoggingEnabled = false; - - @ConfigDataInt(path = "VoteLogging.PurgeDays") - @Getter - private int voteLoggingPurgeDays = 30; - - @ConfigDataBoolean(path = "VoteLogging.UseMainMySQL") - @Getter - private boolean voteLoggingUseMainMySQL = true; - - /** - * Gets the vote logging configuration section. - * - * @return the vote logging configuration section - */ - public ConfigurationSection getVoteLoggingSection() { - if (!getData().isConfigurationSection("VoteLogging")) { - getData().createSection("VoteLogging"); - } - return getData().getConfigurationSection("VoteLogging"); - } - - /** - * Checks if DiscordSRV top voter is enabled. - * - * @param topVoter the top voter type - * @return true if enabled - */ - public boolean isDiscordSRVTopVoterEnabled(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return isDiscordSRVTopVoterAllTimeEnabled(); - case Monthly: - return isDiscordSRVTopVoterMonthlyEnabled(); - case Weekly: - return isDiscordSRVTopVoterWeeklyEnabled(); - case Daily: - return isDiscordSRVTopVoterDailyEnabled(); - default: - return false; - } - } - - /** - * Checks if DiscordSRV top voter should send a new message on update. - * - * @param topVoter the top voter type - * @return true if new message should be sent - */ - public boolean isDiscordSRVTopVoterNewMessageOnUpdate(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return isDiscordSRVTopVoterAllTimeNewMessageOnUpdate(); - case Monthly: - return isDiscordSRVTopVoterMonthlyNewMessageOnUpdate(); - case Weekly: - return isDiscordSRVTopVoterWeeklyNewMessageOnUpdate(); - case Daily: - return isDiscordSRVTopVoterDailyNewMessageOnUpdate(); - default: - return false; - } - } - - /** - * Gets the DiscordSRV top voter channel ID. - * - * @param topVoter the top voter type - * @return the channel ID - */ - public long getDiscordSRVTopVoterChannel(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return getDiscordSRVTopVoterAllTimeChannel(); - case Monthly: - return getDiscordSRVTopVoterMonthlyChannel(); - case Weekly: - return getDiscordSRVTopVoterWeeklyChannel(); - case Daily: - return getDiscordSRVTopVoterDailyChannel(); - default: - return 0; - } - } - - /** - * Gets the DiscordSRV top voter title. - * - * @param topVoter the top voter type - * @return the title - */ - public String getDiscordSRVTopVoterTitle(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return getDiscordSRVTopVoterAllTimeTitle(); - case Monthly: - return getDiscordSRVTopVoterMonthlyTitle(); - case Weekly: - return getDiscordSRVTopVoterWeeklyTitle(); - case Daily: - return getDiscordSRVTopVoterDailyTitle(); - default: - return ""; - } - } - - /** - * Gets the DiscordSRV top voter rank display format. - * - * @param topVoter the top voter type - * @return the rank display format - */ - public String getDiscordSRVTopVoterRankDisplay(TopVoter topVoter) { - switch (topVoter) { - case AllTime: - return getDiscordSRVTopVoterAllTimeRankDisplay(); - case Monthly: - return getDiscordSRVTopVoterMonthlyRankDisplay(); - case Weekly: - return getDiscordSRVTopVoterWeeklyRankDisplay(); - case Daily: - return getDiscordSRVTopVoterDailyRankDisplay(); - default: - return ""; - } - } - - @ConfigDataBoolean(path = "AllowUnJoinedCheckServer") - @Getter - private boolean allowUnJoinedCheckServer = true; - - @ConfigDataBoolean(path = "AllowVotePointTransfers") - @Getter - private boolean allowVotePointTransfers = false; - - @ConfigDataBoolean(path = "AlternateUUIDLookup") - @Getter - private boolean alternateUUIDLookup = false; - - @ConfigDataBoolean(path = "AlwaysCloseInventory") - @Getter - private boolean alwaysCloseInventory = false; - - @ConfigDataBoolean(path = "ExtraVoteShopCheck") - @Getter - private boolean extraVoteShopCheck = true; - - @ConfigDataBoolean(path = "AlwaysUpdate") - @Getter - private boolean alwaysUpdate = false; - - @ConfigDataBoolean(path = "AutoCreateVoteSites") - @Getter - private boolean autoCreateVoteSites = true; - - @ConfigDataBoolean(path = "CountFakeVotes") - @Getter - private boolean countFakeVotes = true; - - @ConfigDataString(path = "DelayBetweenUpdates") - @Getter - private String delayBetweenUpdates = "3m"; - - @ConfigDataBoolean(path = "DisableAdvancedTab") - @Getter - private boolean disableAdvancedTab = false; - - @ConfigDataBoolean(path = "DisableCoolDownCheck") - @Getter - private boolean disableCoolDownCheck = false; - - @ConfigDataListString(path = "DisabledCommands") - @Getter - private ArrayList disabledCommands = new ArrayList<>(); - - @ConfigDataListString(path = "DisabledDefaultPermissions") - @Getter - private ArrayList disabledDefaultPermissions = new ArrayList<>(); - - @ConfigDataListString(path = "CachedPlaceholders") - @Getter - private ArrayList cachedPlaceholders = new ArrayList<>(); - - @ConfigDataBoolean(path = "DisableInteractEvent") - @Getter - private boolean disableInteractEvent = false; - - @ConfigDataBoolean(path = "DisableNoServiceSiteMessage") - @Getter - private boolean disableNoServiceSiteMessage = false; - - @ConfigDataString(path = "Format.Commands.AdminVote.Points.PlayerRemoved") - @Getter - private String formatCommandsAdminVotePointsPlayerRemoved = "&c%amount% voting points have been removed from you"; - - @ConfigDataString(path = "Format.Commands.AdminVote.Points.PlayerGiven") - @Getter - private String formatCommandsAdminVotePointsPlayerGiven = "&cYou have been given %amount% voting points"; - - @ConfigDataBoolean(path = "DisableUpdateChecking") - @Getter - private boolean disableUpdateChecking = false; - - @ConfigDataBoolean(path = "ExtraAllSitesCheck") - @Getter - private boolean extraAllSitesCheck = false; - - @ConfigDataBoolean(path = "CloseInventoryOnVote") - @Getter - private boolean closeInventoryOnVote = true; - - @ConfigDataBoolean(path = "ExtraBackgroundUpdate") - @Getter - private boolean extraBackgroundUpdate = false; - - @ConfigDataBoolean(path = "Format.Commands.Vote.ForceLinks") - @Getter - private boolean formatCommandsVoteForceLinks = true; - - @ConfigDataString(path = "Format.Commands.Vote.Last.LastVoted") - @Getter - private String formatCommandsVoteLastLastVoted = "%times% ago"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NotEnoughPoints") - @Getter - private String formatCommandsVoteGivePointsNotEnoughPoints = "&cNot enough points"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NotJoinedServer") - @Getter - private String formatCommandsVoteGivePointsNotJoinedServer = "&c%player% has not joined the server"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NumberLowerThanZero") - @Getter - private String formatCommandsVoteGivePointsNumberLowerThanZero = "&cNumber of points needs to be greater than 0"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.TransferFrom") - @Getter - private String formatCommandsVoteGivePointsTransferFrom = "&c%transfer% points given to %touser%"; - - @ConfigDataString(path = "Format.Commands.Vote.GivePoints.TransferTo") - @Getter - private String formatCommandsVoteGivePointsTransferTo = "&cYou received %transfer points from %fromuser%"; - - @ConfigDataString(path = "Format.Commands.Vote.Last.Line", defaultValue = "&3%SiteName%: &6%timeSince% ago") - @Getter - private String formatCommandsVoteLastLine; - - @ConfigDataString(path = "Format.Commands.Vote.Last.NeverVoted", defaultValue = "Never voted") - @Getter - private String formatCommandsVoteLastNeverVoted; - - @ConfigDataBoolean(path = "Format.Commands.Vote.Last.IncludeSeconds") - @Getter - private boolean formatCommandsVoteLastIncludeSeconds = true; - - @ConfigDataString(path = "Format.Commands.Vote.Last.TimeFormat", defaultValue = "%amount% %TimeType%") - @Getter - private String formatCommandsVoteLastTimeFormat; - - @ConfigDataString(path = "Format.Commands.Vote.Today.Line") - @Getter - private String formatCommandsVoteTodayLine = "&6%player% : %VoteSite% : %Time%"; - - @ConfigDataListString(path = "Format.Commands.Vote.Today.Title") - @Getter - private ArrayList formatCommandsVoteTodayTitle = ArrayUtils - .convert(new String[] { "&cToday's Votes %page%/%maxpage%", "&cPlayerName : VoteSite : Time" }); - - @ConfigDataString(path = "Format.Commands.Vote.ToggleBroadcasts.Disabled") - @Getter - private String formatCommandsVoteToggleBroadcastDisabled = "&cYou will no longer see vote broadcasts"; - - @ConfigDataString(path = "Format.Commands.Vote.ToggleBroadcasts.Enabled") - @Getter - private String formatCommandsVoteToggleBroadcastEnabled = "&cYou will now see vote broadcasts"; - - @ConfigDataString(path = "Format.Commands.Vote.ToggleReminders.Disabled") - @Getter - private String formatCommandsVoteToggleRemindersDisabled = "&cVote reminders disabled"; - - @ConfigDataString(path = "Format.Commands.Vote.ToggleReminders.Enabled") - @Getter - private String formatCommandsVoteToggleRemindersEnabled = "&cVote reminders enabled"; - - @Getter - private int formatPageSize = 10; - - @ConfigDataString(path = "Format.TimeFormats.Day", defaultValue = "Day") - @Getter - private String formatTimeFormatsDay; - - @ConfigDataString(path = "Format.TimeFormats.Days", defaultValue = "Days") - @Getter - private String formatTimeFormatsDays; - - @ConfigDataString(path = "Format.TimeFormats.Hour", defaultValue = "Hour") - @Getter - private String formatTimeFormatsHour; - - @ConfigDataString(path = "Format.TimeFormats.Hours", defaultValue = "Hours") - @Getter - private String formatTimeFormatsHours; - - @ConfigDataString(path = "Format.TimeFormats.Minute", defaultValue = "Minute") - @Getter - private String formatTimeFormatsMinute; - - @ConfigDataString(path = "Format.TimeFormats.Minutes", defaultValue = "Minutes") - @Getter - private String formatTimeFormatsMinutes; - - @ConfigDataString(path = "Format.TimeFormats.Second", defaultValue = "Second") - @Getter - private String formatTimeFormatsSecond; - - @ConfigDataString(path = "Format.TimeFormats.Seconds", defaultValue = "Seconds") - @Getter - private String formatTimeFormatsSeconds; - - @ConfigDataBoolean(path = "LimitMonthlyVotes") - @Getter - private boolean limitMonthlyVotes = false; - - @ConfigDataBoolean(path = "LoadCommandAliases") - @Getter - private boolean loadCommandAliases = true; - - @ConfigDataInt(path = "MaxiumNumberOfTopVotersToLoad") - @Getter - private int MaxiumNumberOfTopVotersToLoad = 1000; - - @ConfigDataBoolean(path = "OverrideVersionDisable") - @Getter - private boolean overrideVersionDisable = false; - - @ConfigDataBoolean(path = "PreventRepeatMilestones") - @Getter - private boolean preventRepeatMilestones = false; - - @ConfigDataBoolean(path = "OfflineVotesLimit.Enabled") - @Getter - private boolean offlineVotesLimitEnabled = false; - - @ConfigDataInt(path = "OfflineVotesLimit.Amount") - @Getter - private int offlineVotesLimitAmount = 5; - - @ConfigDataBoolean(path = "UpdateWithPlayersOnlineOnly") - @Getter - private boolean updateWithPlayersOnlineOnly = false; - - @ConfigDataBoolean(path = "UseHighestTotals") - @Getter - private boolean useHighestTotals = true; - - @ConfigDataBoolean(path = "UseJavascriptPlaceholders") - @Getter - private boolean useJavascriptPlaceholders = false; - - @ConfigDataBoolean(path = "UseVoteGUIMainCommand") - @Getter - private boolean useVoteGUIMainCommand = false; - - @ConfigDataBoolean(path = "UseVoteStreaks") - @Getter - private boolean useVoteStreaks = true; - - @ConfigDataListString(path = "VotingBroadcastBlacklist") - @Getter - private ArrayList votingBroadcastBlacklist = new ArrayList<>(); - - @ConfigDataKeys(path = "CustomCommands") - @Getter - private Set customCommands = new HashSet<>(); - - @ConfigDataKeys(path = "CustomPlaceholderReturns") - @Getter - private Set customPlaceholderReturns = new HashSet<>(); - - @ConfigDataBoolean(path = "Format.Commands.Vote.AutoInputSites") - @Getter - private boolean formatCommandsVoteAutoInputSites = true; - - @ConfigDataBoolean(path = "Format.Commands.Vote.OnlyShowSitesToVote") - @Getter - private boolean formatCommandsVoteOnlyShowSitesToVote = false; - - @ConfigDataListString(path = "Format.Commands.Vote.Best.Lines") - @Getter - private ArrayList formatCommandsVoteBestLines = new ArrayList<>(); - - @ConfigDataString(path = "Format.Commands.Vote.Best.Title") - @Getter - private String formatCommandsVoteBestTitle = "&3&l%player% Best Votes"; - - @ConfigDataString(path = "Format.Commands.Vote.Help.HoverColor") - @Getter - private String formatCommandsVoteHelpHoverColor = "AQUA"; - - @ConfigDataString(path = "Format.Commands.Vote.Help.Line") - @Getter - private String formatCommandsVoteHelpLine = "&6%Command% - &6%HelpMessage%"; - - @ConfigDataBoolean(path = "Format.Commands.Vote.Help.RequirePermission") - @Getter - private boolean formatCommandsVoteHelpRequirePermission = false; - - @ConfigDataString(path = "Format.Commands.Vote.Help.Title") - @Getter - private String formatCommandsVoteHelpTitle = "&6Voting Player Help"; - - @ConfigDataString(path = "Format.Commands.Vote.Last.Title") - @Getter - private String formatCommandsVoteLastTitle = "&3&l%player% Last Vote Times:"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Info.CanVote") - @Getter - private String formatCommandsVoteNextInfoCanVote = "Go Vote!"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Info.Error") - @Getter - private String formatCommandsVoteNextInfoError = ""; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Info.TimeUntilVote") - @Getter - private String formatCommandsVoteNextInfoTime = "&cCould not caculate time until next vote!"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Info.VoteDelayDaily") - @Getter - private String formatCommandsVoteNextInfoVoteDelayDaily = "%hours% Hours and %minutes% Minutes"; - - @ConfigDataString(path = "PlaceholderCacheLevel", options = { "AUTO", "SPECIFIC", "NONE" }) - @Getter - private String placeholderCacheLevelString = "AUTO"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Layout") - @Getter - private String formatCommandsVoteNextLayout = "&3%SiteName%: &6%info%"; - - @ConfigDataString(path = "Format.Commands.Vote.Next.Title") - @Getter - private String formatCommandsVoteNextTitle = "&3&l%player% Next Votes:"; - - @ConfigDataString(path = "Format.Commands.Vote.Streak.Title") - @Getter - private String formatCommandsVoteStreakTitle = "&3&l%player% Vote Streak"; - - @ConfigDataString(path = "Format.Commands.Vote.Sites") - @Getter - private String formatCommandsVoteURLS = "&4%num%: &c&l%SiteName% - &c%url%"; - - @ConfigDataString(path = "Format.Commands.Vote.Points") - @Getter - private String formatCommandsVotePoints = "&a%Player% currently has &a&l%Points%&a Points!"; - - @ConfigDataString(path = "Format.Commands.Vote.Top.Line") - @Getter - private String formatCommandsVoteTopLine = "&c%num%: &6%player%, %votes%"; - - @ConfigDataString(path = "Format.Commands.Vote.Top.Title") - @Getter - private String formatCommandVoteTopTitle = "&3Top %Top% Voters %page%/%maxpages%"; - - @ConfigDataString(path = "Format.NextPage") - @Getter - private String formatNextPage = "&aNext Page"; - - @ConfigDataString(path = "Format.NoPerms") - @Getter - private String formatNoPerms = "&cYou do not have enough permission!"; - - @ConfigDataString(path = "Format.NotNumber") - @Getter - private String formatNotNumber = "&cError on &6%arg%&c, number expected!"; - - @ConfigDataString(path = "Format.PrevPage") - @Getter - private String formatPrevPage = "&aPrevious Page"; - - @ConfigDataString(path = "Format.ShopFailed") - @Getter - private String formatShopFailedMsg = "&cYou do not have %Points% points to purhcase this!"; - - @ConfigDataString(path = "Format.ShopNotPurchasable") - @Getter - private String formatShopNotPurchasable = "&cThis item is not buyable!"; - - @ConfigDataString(path = "Format.ShopPurchase") - @Getter - private String formatShopPurchaseMsg = "&aYou bought the %Identifier% for %Points% Points!"; - - @ConfigDataString(path = "Format.Signs.TopVoterSign.Line1") - @Getter - private String formatSignTopVoterSignLine1 = "TopVoter: %SiteName%"; - - @ConfigDataString(path = "Format.Signs.TopVoterSign.Line2") - @Getter - private String formatSignTopVoterSignLine2 = "#%position%"; - - @ConfigDataString(path = "Format.Signs.TopVoterSign.Line3") - @Getter - private String formatSignTopVoterSignLine3 = "%player%"; - - @ConfigDataString(path = "Format.Signs.TopVoterSign.Line4") - @Getter - private String formatSignTopVoterSignLine4 = "%votes% Votes"; - - @ConfigDataString(path = "Format.Signs.RightClickMessage") - @Getter - private String formatSignTopVoterSignRightClickMessage = "&c&l%player% &cis &c&l%position% &cwith &c&l%votes% &cin &c&l%SiteName%"; - - @ConfigDataString(path = "Format.TimeFormat") - @Getter - private String formatTimeFormat = "EEE, d MMM yyyy HH:mm"; - - @ConfigDataString(path = "Format.TopVoter.AllTime") - @Getter - private String formatTopVoterAllTime = "AllTime"; - - @ConfigDataString(path = "Format.TopVoter.Daily") - @Getter - private String formatTopVoterDaily = "Daily"; - - @ConfigDataString(path = "Format.TopVoter.Monthly") - @Getter - private String formatTopVoterMonthly = "Monthly"; - - @ConfigDataString(path = "Format.TopVoterAwardMsg") - @Getter - private String formatTopVoterRewardMsg = "&aYou came in %place% in top voters of the month! Here is an award!"; - - @ConfigDataString(path = "Format.TopVoter.Weekly") - @Getter - private String formatTopVoterWeekly = "Weekly"; - - @ConfigDataString(path = "Format.UserNotExist") - @Getter - private String formatUserNotExist = "&cUser does not exist: %player%"; - - @ConfigDataString(path = "Format.InvalidCommand.Vote") - @Getter - private String formatInvalidCommandVote = "&4No valid arguments, see /vote help!"; - @ConfigDataString(path = "Format.InvalidCommand.AdminVote") - @Getter - private String formatInvalidCommandAdminVote = "&4No valid arguments, see /adminvote help!"; - @ConfigDataBoolean(path = "GiveDefaultPermission") - @Getter - private boolean giveDefaultPermission = true; - - @ConfigDataBoolean(path = "LoadTopVoter.AllTime") - @Getter - private boolean loadTopVoterAllTime = true; - - @ConfigDataBoolean(path = "LoadTopVoter.Monthly") - @Getter - private boolean loadTopVoterMonthly = true; - - @ConfigDataBoolean(path = "LoadTopVoter.Daily") - @Getter - private boolean loadTopVoterDaily = false; - - @ConfigDataBoolean(path = "LoadTopVoter.Weekly") - @Getter - private boolean loadTopVoterWeekly = false; - - @ConfigDataInt(path = "PointsOnVote") - @Getter - private int pointsOnVote = 1; - - @ConfigDataBoolean(path = "PurgeNoDataOnStartup") - @Getter - private boolean purgeNoDataOnStartup = false; - - @ConfigDataBoolean(path = "StoreMonthTotalsWithDate") - @Getter - private boolean storeMonthTotalsWithDate = false; - - @ConfigDataBoolean(path = "UseMonthDateTotalsAsPrimaryTotal") - @Getter - private boolean useMonthDateTotalsAsPrimaryTotal = false; - - @ConfigDataString(path = "RequestAPI.DefaultMethod") - @Getter - private String requestAPIDefaultMethod = "ANVIL"; - - @ConfigDataListString(path = "RequestAPI.DisabledMethods") - @Getter - private ArrayList requestAPIDisabledMethods = new ArrayList<>(); - - @ConfigDataBoolean(path = "StoreTopVoters.Daily") - @Getter - private boolean storeTopVotersDaily = false; - - @ConfigDataBoolean(path = "StoreTopVoters.Weekly") - @Getter - private boolean storeTopVotersWeekly = false; - - @ConfigDataBoolean(path = "TopVoterAwardsTies") - @Getter - private boolean topVoterAwardsTies = true; - - @ConfigDataBoolean(path = "TopVoterIgnorePermission") - @Getter - private boolean topVoterIgnorePermission = false; - - @ConfigDataString(path = "VoteTopDefault") - @Getter - private String voteTopDefault = "Monthly"; - - @ConfigDataBoolean(path = "AlwaysProcessAsyncPlaceholders") - @Getter - private boolean alwaysProcessAsyncPlaceholders = false; - - /** - * Constructs a new Config. - * - * @param plugin the main plugin instance - */ - public Config(VotingPluginMain plugin) { - super(plugin, new File(plugin.getDataFolder(), "Config.yml")); - setIgnoreCase(true); - } - - /** - * Gets the black list. - * - * @return the black list - */ - @SuppressWarnings("unchecked") - public ArrayList getBlackList() { - return (ArrayList) getData().getList("BlackList", new ArrayList<>()); - } - - /** - * Gets the custom commands configuration section. - * - * @param ident the command identifier - * @return the configuration section - */ - public ConfigurationSection getCustomCommands(String ident) { - return getData().getConfigurationSection("CustomCommands." + ident); - } - - /** - * Gets the custom placeholder return keys. - * - * @param placeholder the placeholder name - * @return set of return keys - */ - public Set getCustomPlaceholderReturns(String placeholder) { - Set str = getData().getConfigurationSection("CustomPlaceholderReturns." + placeholder).getKeys(false); - if (str == null) { - str = new HashSet<>(); - } - return str; - } - - /** - * Gets a custom placeholder return value. - * - * @param placeholder the placeholder name - * @param returnString the return key - * @return the return value - */ - public String getCustomPlaceholderReturns(String placeholder, String returnString) { - return getData().getString("CustomPlaceholderReturns." + placeholder + "." + returnString, ""); - } - - /** - * Gets the commands vote party. - * - * @return the commands vote party - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteParty() { - ArrayList msg = new ArrayList<>(); - msg.add("&cCurrently at &6%Votes%&c, &6%NeededVotes% &cmore votes to go to reach &6%VotesRequired%"); - return (ArrayList) getData().getList("Format.Commands.Vote.Party", msg); - - } - - /** - * Gets the vote streak lines format. - * - * @return list of format lines - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteStreakLines() { - return (ArrayList) getData().getList("Format.Commands.Vote.Streak.Lines", new ArrayList<>()); - } - - /** - * Gets the commands vote text. - * - * @return the commands vote text - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteText() { - ArrayList str = new ArrayList<>(); - str.add("&4&lVote for our server!"); - return (ArrayList) getData().getList("Format.Commands.Vote.Text", str); - } - - /** - * Gets the vote total format lines. - * - * @return list of format lines - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteTotal() { - ArrayList list = (ArrayList) getData().getList("Format.Commands.Vote.Total", new ArrayList<>()); - if (list.isEmpty()) { - list.add("&3&l%player% Total Votes:"); - list.add("&3&lDaily Total: &6&l%DailyTotal%"); - list.add("&3&lWeekly Total: &6&l%WeeklyTotal%"); - list.add("&3&lMonthly Total: &6&l%MonthlyTotal%"); - list.add("&3&lAllTime Total: &6&l%AllTimeTotal%"); - } - return list; - } - - /** - * Gets the vote total all format lines. - * - * @return list of format lines - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatCommandsVoteTotalAll() { - - ArrayList list = (ArrayList) getData().getList("Format.Commands.Vote.TotalAll", - new ArrayList<>()); - if (list.isEmpty()) { - list.add("&3&lServer Total Votes:"); - list.add("&3&lDaily Total: &6&l%DailyTotal%"); - list.add("&3&lWeekly Total: &6&l%WeeklyTotal%"); - list.add("&3&lMonthly Total: &6&l%MonthlyTotal%"); - list.add("&3&lAllTime Total: &6&l%AllTimeTotal%"); - } - return list; - } - - /** - * Gets the vote help. - * - * @return the vote help - */ - @SuppressWarnings("unchecked") - public ArrayList getFormatVoteHelp() { - return (ArrayList) getData().getList("Format.Commands.Vote.Help.Lines", new ArrayList<>()); - } - - /** - * Checks if a top voter type should be loaded. - * - * @param top the top voter type - * @return true if should be loaded - */ - public boolean getLoadTopVoter(TopVoter top) { - switch (top) { - case AllTime: - return isLoadTopVoterAllTime(); - case Daily: - return isLoadTopVoterDaily(); - case Monthly: - return isLoadTopVoterMonthly(); - case Weekly: - return isLoadTopVoterWeekly(); - default: - return false; - } - } - - /** - * Gets the placeholder cache level. - * - * @return the cache level - */ - public PlaceholderCacheLevel getPlaceholderCacheLevel() { - return PlaceholderCacheLevel.getCache(getPlaceholderCacheLevelString()); - } - - @Override - public void loadValues() { - new AnnotationHandler().load(getData(), this); - } - - @Override - public void onFileCreation() { - getPlugin().saveResource("Config.yml", true); - } - -} + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.NewMessageOnUpdate") + @Getter + private boolean discordSRVTopVoterMonthlyNewMessageOnUpdate = false; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.NewMessageOnUpdate") + @Getter + private boolean discordSRVTopVoterWeeklyNewMessageOnUpdate = false; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.NewMessageOnUpdate") + @Getter + private boolean discordSRVTopVoterDailyNewMessageOnUpdate = false; + + @ConfigDataLong(path = "DiscordSRV.TopVoter.AllTime.Channel") + @Getter + private long discordSRVTopVoterAllTimeChannel = 0; + + @ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.Title") + @Getter + private String discordSRVTopVoterAllTimeTitle = "All Time Top Voters"; + + @ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.RankDisplay") + @Getter + private String discordSRVTopVoterAllTimeRankDisplay = "%rank%: %player% - %votes% Votes"; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.Enabled") + @Getter + private boolean discordSRVTopVoterMonthlyEnabled = false; + + @ConfigDataLong(path = "DiscordSRV.TopVoter.Monthly.Channel") + @Getter + private long discordSRVTopVoterMonthlyChannel = 0; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.Title") + @Getter + private String discordSRVTopVoterMonthlyTitle = "Top Voters of the Month"; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.RankDisplay") + @Getter + private String discordSRVTopVoterMonthlyRankDisplay = "%rank%: %player% - %votes% Votes"; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.Enabled") + @Getter + private boolean discordSRVTopVoterWeeklyEnabled = false; + + @ConfigDataLong(path = "DiscordSRV.TopVoter.Weekly.Channel") + @Getter + private long discordSRVTopVoterWeeklyChannel = 0; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.Title") + @Getter + private String discordSRVTopVoterWeeklyTitle = "Top Voters of the Week"; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.RankDisplay") + @Getter + private String discordSRVTopVoterWeeklyRankDisplay = "%rank%: %player% - %votes% Votes"; + + @ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.Enabled") + @Getter + private boolean discordSRVTopVoterDailyEnabled = false; + + @ConfigDataLong(path = "DiscordSRV.TopVoter.Daily.Channel") + @Getter + private long discordSRVTopVoterDailyChannel = 0; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Daily.Title") + @Getter + private String discordSRVTopVoterDailyTitle = "Top Voters of the Day"; + + @ConfigDataString(path = "DiscordSRV.TopVoter.Daily.RankDisplay") + @Getter + private String discordSRVTopVoterDailyRankDisplay = "%rank%: %player% - %votes% Votes"; + + // VoteLogging configuration section - minimal options mirror Config.yml + @ConfigDataBoolean(path = "VoteLogging.Enabled") + @Getter + private boolean voteLoggingEnabled = false; + + @ConfigDataInt(path = "VoteLogging.PurgeDays") + @Getter + private int voteLoggingPurgeDays = 30; + + @ConfigDataBoolean(path = "VoteLogging.UseMainMySQL") + @Getter + private boolean voteLoggingUseMainMySQL = true; + + /** + * Gets the vote logging configuration section. + * + * @return the vote logging configuration section + */ + public ConfigurationSection getVoteLoggingSection() { + if (!getData().isConfigurationSection("VoteLogging")) { + getData().createSection("VoteLogging"); + } + return getData().getConfigurationSection("VoteLogging"); + } + + /** + * Checks if DiscordSRV top voter is enabled. + * + * @param topVoter the top voter type + * @return true if enabled + */ + public boolean isDiscordSRVTopVoterEnabled(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return isDiscordSRVTopVoterAllTimeEnabled(); + case Monthly: + return isDiscordSRVTopVoterMonthlyEnabled(); + case Weekly: + return isDiscordSRVTopVoterWeeklyEnabled(); + case Daily: + return isDiscordSRVTopVoterDailyEnabled(); + default: + return false; + } + } + + /** + * Checks if DiscordSRV top voter should send a new message on update. + * + * @param topVoter the top voter type + * @return true if new message should be sent + */ + public boolean isDiscordSRVTopVoterNewMessageOnUpdate(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return isDiscordSRVTopVoterAllTimeNewMessageOnUpdate(); + case Monthly: + return isDiscordSRVTopVoterMonthlyNewMessageOnUpdate(); + case Weekly: + return isDiscordSRVTopVoterWeeklyNewMessageOnUpdate(); + case Daily: + return isDiscordSRVTopVoterDailyNewMessageOnUpdate(); + default: + return false; + } + } + + /** + * Gets the DiscordSRV top voter channel ID. + * + * @param topVoter the top voter type + * @return the channel ID + */ + public long getDiscordSRVTopVoterChannel(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return getDiscordSRVTopVoterAllTimeChannel(); + case Monthly: + return getDiscordSRVTopVoterMonthlyChannel(); + case Weekly: + return getDiscordSRVTopVoterWeeklyChannel(); + case Daily: + return getDiscordSRVTopVoterDailyChannel(); + default: + return 0; + } + } + + /** + * Gets the DiscordSRV top voter title. + * + * @param topVoter the top voter type + * @return the title + */ + public String getDiscordSRVTopVoterTitle(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return getDiscordSRVTopVoterAllTimeTitle(); + case Monthly: + return getDiscordSRVTopVoterMonthlyTitle(); + case Weekly: + return getDiscordSRVTopVoterWeeklyTitle(); + case Daily: + return getDiscordSRVTopVoterDailyTitle(); + default: + return ""; + } + } + + /** + * Gets the DiscordSRV top voter rank display format. + * + * @param topVoter the top voter type + * @return the rank display format + */ + public String getDiscordSRVTopVoterRankDisplay(TopVoter topVoter) { + switch (topVoter) { + case AllTime: + return getDiscordSRVTopVoterAllTimeRankDisplay(); + case Monthly: + return getDiscordSRVTopVoterMonthlyRankDisplay(); + case Weekly: + return getDiscordSRVTopVoterWeeklyRankDisplay(); + case Daily: + return getDiscordSRVTopVoterDailyRankDisplay(); + default: + return ""; + } + } + + @ConfigDataBoolean(path = "AllowUnJoinedCheckServer") + @Getter + private boolean allowUnJoinedCheckServer = true; + + @ConfigDataBoolean(path = "AllowVotePointTransfers") + @Getter + private boolean allowVotePointTransfers = false; + + @ConfigDataBoolean(path = "AlternateUUIDLookup") + @Getter + private boolean alternateUUIDLookup = false; + + @ConfigDataBoolean(path = "AlwaysCloseInventory") + @Getter + private boolean alwaysCloseInventory = false; + + @ConfigDataBoolean(path = "ExtraVoteShopCheck") + @Getter + private boolean extraVoteShopCheck = true; + + @ConfigDataBoolean(path = "AlwaysUpdate") + @Getter + private boolean alwaysUpdate = false; + + @ConfigDataBoolean(path = "AutoCreateVoteSites") + @Getter + private boolean autoCreateVoteSites = true; + + @ConfigDataBoolean(path = "CountFakeVotes") + @Getter + private boolean countFakeVotes = true; + + @ConfigDataString(path = "DelayBetweenUpdates") + @Getter + private String delayBetweenUpdates = "3m"; + + @ConfigDataBoolean(path = "DisableAdvancedTab") + @Getter + private boolean disableAdvancedTab = false; + + @ConfigDataBoolean(path = "DisableCoolDownCheck") + @Getter + private boolean disableCoolDownCheck = false; + + @ConfigDataListString(path = "DisabledCommands") + @Getter + private ArrayList disabledCommands = new ArrayList<>(); + + @ConfigDataListString(path = "DisabledDefaultPermissions") + @Getter + private ArrayList disabledDefaultPermissions = new ArrayList<>(); + + @ConfigDataListString(path = "CachedPlaceholders") + @Getter + private ArrayList cachedPlaceholders = new ArrayList<>(); + + @ConfigDataBoolean(path = "DisableInteractEvent") + @Getter + private boolean disableInteractEvent = false; + + @ConfigDataBoolean(path = "DisableNoServiceSiteMessage") + @Getter + private boolean disableNoServiceSiteMessage = false; + + @ConfigDataString(path = "Format.Commands.AdminVote.Points.PlayerRemoved") + @Getter + private String formatCommandsAdminVotePointsPlayerRemoved = "&c%amount% voting points have been removed from you"; + + @ConfigDataString(path = "Format.Commands.AdminVote.Points.PlayerGiven") + @Getter + private String formatCommandsAdminVotePointsPlayerGiven = "&cYou have been given %amount% voting points"; + + @ConfigDataBoolean(path = "DisableUpdateChecking") + @Getter + private boolean disableUpdateChecking = false; + + @ConfigDataBoolean(path = "ExtraAllSitesCheck") + @Getter + private boolean extraAllSitesCheck = false; + + @ConfigDataBoolean(path = "CloseInventoryOnVote") + @Getter + private boolean closeInventoryOnVote = true; + + @ConfigDataBoolean(path = "ExtraBackgroundUpdate") + @Getter + private boolean extraBackgroundUpdate = false; + + @ConfigDataBoolean(path = "Format.Commands.Vote.ForceLinks") + @Getter + private boolean formatCommandsVoteForceLinks = true; + + @ConfigDataString(path = "Format.Commands.Vote.Last.LastVoted") + @Getter + private String formatCommandsVoteLastLastVoted = "%times% ago"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NotEnoughPoints") + @Getter + private String formatCommandsVoteGivePointsNotEnoughPoints = "&cNot enough points"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NotJoinedServer") + @Getter + private String formatCommandsVoteGivePointsNotJoinedServer = "&c%player% has not joined the server"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.NumberLowerThanZero") + @Getter + private String formatCommandsVoteGivePointsNumberLowerThanZero = "&cNumber of points needs to be greater than 0"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.TransferFrom") + @Getter + private String formatCommandsVoteGivePointsTransferFrom = "&c%transfer% points given to %touser%"; + + @ConfigDataString(path = "Format.Commands.Vote.GivePoints.TransferTo") + @Getter + private String formatCommandsVoteGivePointsTransferTo = "&cYou received %transfer points from %fromuser%"; + + @ConfigDataString(path = "Format.Commands.Vote.Last.Line", defaultValue = "&3%SiteName%: &6%timeSince% ago") + @Getter + private String formatCommandsVoteLastLine; + + @ConfigDataString(path = "Format.Commands.Vote.Last.NeverVoted", defaultValue = "Never voted") + @Getter + private String formatCommandsVoteLastNeverVoted; + + @ConfigDataBoolean(path = "Format.Commands.Vote.Last.IncludeSeconds") + @Getter + private boolean formatCommandsVoteLastIncludeSeconds = true; + + @ConfigDataString(path = "Format.Commands.Vote.Last.TimeFormat", defaultValue = "%amount% %TimeType%") + @Getter + private String formatCommandsVoteLastTimeFormat; + + @ConfigDataString(path = "Format.Commands.Vote.Today.Line") + @Getter + private String formatCommandsVoteTodayLine = "&6%player% : %VoteSite% : %Time%"; + + @ConfigDataListString(path = "Format.Commands.Vote.Today.Title") + @Getter + private ArrayList formatCommandsVoteTodayTitle = ArrayUtils + .convert(new String[] { "&cToday's Votes %page%/%maxpage%", "&cPlayerName : VoteSite : Time" }); + + @ConfigDataString(path = "Format.Commands.Vote.ToggleBroadcasts.Disabled") + @Getter + private String formatCommandsVoteToggleBroadcastDisabled = "&cYou will no longer see vote broadcasts"; + + @ConfigDataString(path = "Format.Commands.Vote.ToggleBroadcasts.Enabled") + @Getter + private String formatCommandsVoteToggleBroadcastEnabled = "&cYou will now see vote broadcasts"; + + @ConfigDataString(path = "Format.Commands.Vote.ToggleReminders.Disabled") + @Getter + private String formatCommandsVoteToggleRemindersDisabled = "&cVote reminders disabled"; + + @ConfigDataString(path = "Format.Commands.Vote.ToggleReminders.Enabled") + @Getter + private String formatCommandsVoteToggleRemindersEnabled = "&cVote reminders enabled"; + + @Getter + private int formatPageSize = 10; + + @ConfigDataString(path = "Format.TimeFormats.Day", defaultValue = "Day") + @Getter + private String formatTimeFormatsDay; + + @ConfigDataString(path = "Format.TimeFormats.Days", defaultValue = "Days") + @Getter + private String formatTimeFormatsDays; + + @ConfigDataString(path = "Format.TimeFormats.Hour", defaultValue = "Hour") + @Getter + private String formatTimeFormatsHour; + + @ConfigDataString(path = "Format.TimeFormats.Hours", defaultValue = "Hours") + @Getter + private String formatTimeFormatsHours; + + @ConfigDataString(path = "Format.TimeFormats.Minute", defaultValue = "Minute") + @Getter + private String formatTimeFormatsMinute; + + @ConfigDataString(path = "Format.TimeFormats.Minutes", defaultValue = "Minutes") + @Getter + private String formatTimeFormatsMinutes; + + @ConfigDataString(path = "Format.TimeFormats.Second", defaultValue = "Second") + @Getter + private String formatTimeFormatsSecond; + + @ConfigDataString(path = "Format.TimeFormats.Seconds", defaultValue = "Seconds") + @Getter + private String formatTimeFormatsSeconds; + + @ConfigDataBoolean(path = "LimitMonthlyVotes") + @Getter + private boolean limitMonthlyVotes = false; + + @ConfigDataBoolean(path = "LoadCommandAliases") + @Getter + private boolean loadCommandAliases = true; + + @ConfigDataInt(path = "MaxiumNumberOfTopVotersToLoad") + @Getter + private int MaxiumNumberOfTopVotersToLoad = 1000; + + @ConfigDataBoolean(path = "OverrideVersionDisable") + @Getter + private boolean overrideVersionDisable = false; + + @ConfigDataBoolean(path = "PreventRepeatMilestones") + @Getter + private boolean preventRepeatMilestones = false; + + @ConfigDataBoolean(path = "OfflineVotesLimit.Enabled") + @Getter + private boolean offlineVotesLimitEnabled = false; + + @ConfigDataInt(path = "OfflineVotesLimit.Amount") + @Getter + private int offlineVotesLimitAmount = 5; + + @ConfigDataBoolean(path = "UpdateWithPlayersOnlineOnly") + @Getter + private boolean updateWithPlayersOnlineOnly = false; + + @ConfigDataBoolean(path = "UseHighestTotals") + @Getter + private boolean useHighestTotals = true; + + @ConfigDataBoolean(path = "UseJavascriptPlaceholders") + @Getter + private boolean useJavascriptPlaceholders = false; + + @ConfigDataBoolean(path = "UseVoteGUIMainCommand") + @Getter + private boolean useVoteGUIMainCommand = false; + + @ConfigDataBoolean(path = "UseVoteStreaks") + @Getter + private boolean useVoteStreaks = true; + + @ConfigDataListString(path = "VotingBroadcastBlacklist") + @Getter + private ArrayList votingBroadcastBlacklist = new ArrayList<>(); + + @ConfigDataKeys(path = "CustomCommands") + @Getter + private Set customCommands = new HashSet<>(); + + @ConfigDataKeys(path = "CustomPlaceholderReturns") + @Getter + private Set customPlaceholderReturns = new HashSet<>(); + + @ConfigDataBoolean(path = "Format.Commands.Vote.AutoInputSites") + @Getter + private boolean formatCommandsVoteAutoInputSites = true; + + @ConfigDataBoolean(path = "Format.Commands.Vote.OnlyShowSitesToVote") + @Getter + private boolean formatCommandsVoteOnlyShowSitesToVote = false; + + @ConfigDataListString(path = "Format.Commands.Vote.Best.Lines") + @Getter + private ArrayList formatCommandsVoteBestLines = new ArrayList<>(); + + @ConfigDataString(path = "Format.Commands.Vote.Best.Title") + @Getter + private String formatCommandsVoteBestTitle = "&3&l%player% Best Votes"; + + @ConfigDataString(path = "Format.Commands.Vote.Help.HoverColor") + @Getter + private String formatCommandsVoteHelpHoverColor = "AQUA"; + + @ConfigDataString(path = "Format.Commands.Vote.Help.Line") + @Getter + private String formatCommandsVoteHelpLine = "&6%Command% - &6%HelpMessage%"; + + @ConfigDataBoolean(path = "Format.Commands.Vote.Help.RequirePermission") + @Getter + private boolean formatCommandsVoteHelpRequirePermission = false; + + @ConfigDataString(path = "Format.Commands.Vote.Help.Title") + @Getter + private String formatCommandsVoteHelpTitle = "&6Voting Player Help"; + + @ConfigDataString(path = "Format.Commands.Vote.Last.Title") + @Getter + private String formatCommandsVoteLastTitle = "&3&l%player% Last Vote Times:"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Info.CanVote") + @Getter + private String formatCommandsVoteNextInfoCanVote = "Go Vote!"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Info.Error") + @Getter + private String formatCommandsVoteNextInfoError = ""; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Info.TimeUntilVote") + @Getter + private String formatCommandsVoteNextInfoTime = "&cCould not caculate time until next vote!"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Info.VoteDelayDaily") + @Getter + private String formatCommandsVoteNextInfoVoteDelayDaily = "%hours% Hours and %minutes% Minutes"; + + @ConfigDataString(path = "PlaceholderCacheLevel", options = { "AUTO", "SPECIFIC", "NONE" }) + @Getter + private String placeholderCacheLevelString = "AUTO"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Layout") + @Getter + private String formatCommandsVoteNextLayout = "&3%SiteName%: &6%info%"; + + @ConfigDataString(path = "Format.Commands.Vote.Next.Title") + @Getter + private String formatCommandsVoteNextTitle = "&3&l%player% Next Votes:"; + + @ConfigDataString(path = "Format.Commands.Vote.Streak.Title") + @Getter + private String formatCommandsVoteStreakTitle = "&3&l%player% Vote Streak"; + + @ConfigDataString(path = "Format.Commands.Vote.Sites") + @Getter + private String formatCommandsVoteURLS = "&4%num%: &c&l%SiteName% - &c%url%"; + + @ConfigDataString(path = "Format.Commands.Vote.Points") + @Getter + private String formatCommandsVotePoints = "&a%Player% currently has &a&l%Points%&a Points!"; + + @ConfigDataString(path = "Format.Commands.Vote.Top.Line") + @Getter + private String formatCommandsVoteTopLine = "&c%num%: &6%player%, %votes%"; + + @ConfigDataString(path = "Format.Commands.Vote.Top.Title") + @Getter + private String formatCommandVoteTopTitle = "&3Top %Top% Voters %page%/%maxpages%"; + + @ConfigDataString(path = "Format.NextPage") + @Getter + private String formatNextPage = "&aNext Page"; + + @ConfigDataString(path = "Format.NoPerms") + @Getter + private String formatNoPerms = "&cYou do not have enough permission!"; + + @ConfigDataString(path = "Format.NotNumber") + @Getter + private String formatNotNumber = "&cError on &6%arg%&c, number expected!"; + + @ConfigDataString(path = "Format.PrevPage") + @Getter + private String formatPrevPage = "&aPrevious Page"; + + @ConfigDataString(path = "Format.ShopFailed") + @Getter + private String formatShopFailedMsg = "&cYou do not have %Points% points to purhcase this!"; + + @ConfigDataString(path = "Format.ShopNotPurchasable") + @Getter + private String formatShopNotPurchasable = "&cThis item is not buyable!"; + + @ConfigDataString(path = "Format.ShopPurchase") + @Getter + private String formatShopPurchaseMsg = "&aYou bought the %Identifier% for %Points% Points!"; + + @ConfigDataString(path = "Format.Signs.TopVoterSign.Line1") + @Getter + private String formatSignTopVoterSignLine1 = "TopVoter: %SiteName%"; + + @ConfigDataString(path = "Format.Signs.TopVoterSign.Line2") + @Getter + private String formatSignTopVoterSignLine2 = "#%position%"; + + @ConfigDataString(path = "Format.Signs.TopVoterSign.Line3") + @Getter + private String formatSignTopVoterSignLine3 = "%player%"; + + @ConfigDataString(path = "Format.Signs.TopVoterSign.Line4") + @Getter + private String formatSignTopVoterSignLine4 = "%votes% Votes"; + + @ConfigDataString(path = "Format.Signs.RightClickMessage") + @Getter + private String formatSignTopVoterSignRightClickMessage = "&c&l%player% &cis &c&l%position% &cwith &c&l%votes% &cin &c&l%SiteName%"; + + @ConfigDataString(path = "Format.TimeFormat") + @Getter + private String formatTimeFormat = "EEE, d MMM yyyy HH:mm"; + + @ConfigDataString(path = "Format.TopVoter.AllTime") + @Getter + private String formatTopVoterAllTime = "AllTime"; + + @ConfigDataString(path = "Format.TopVoter.Daily") + @Getter + private String formatTopVoterDaily = "Daily"; + + @ConfigDataString(path = "Format.TopVoter.Monthly") + @Getter + private String formatTopVoterMonthly = "Monthly"; + + @ConfigDataString(path = "Format.TopVoterAwardMsg") + @Getter + private String formatTopVoterRewardMsg = "&aYou came in %place% in top voters of the month! Here is an award!"; + + @ConfigDataString(path = "Format.TopVoter.Weekly") + @Getter + private String formatTopVoterWeekly = "Weekly"; + + @ConfigDataString(path = "Format.UserNotExist") + @Getter + private String formatUserNotExist = "&cUser does not exist: %player%"; + + @ConfigDataString(path = "Format.InvalidCommand.Vote") + @Getter + private String formatInvalidCommandVote = "&4No valid arguments, see /vote help!"; + @ConfigDataString(path = "Format.InvalidCommand.AdminVote") + @Getter + private String formatInvalidCommandAdminVote = "&4No valid arguments, see /adminvote help!"; + @ConfigDataBoolean(path = "GiveDefaultPermission") + @Getter + private boolean giveDefaultPermission = true; + + @ConfigDataBoolean(path = "LoadTopVoter.AllTime") + @Getter + private boolean loadTopVoterAllTime = true; + + @ConfigDataBoolean(path = "LoadTopVoter.Monthly") + @Getter + private boolean loadTopVoterMonthly = true; + + @ConfigDataBoolean(path = "LoadTopVoter.Daily") + @Getter + private boolean loadTopVoterDaily = false; + + @ConfigDataBoolean(path = "LoadTopVoter.Weekly") + @Getter + private boolean loadTopVoterWeekly = false; + + @ConfigDataInt(path = "PointsOnVote") + @Getter + private int pointsOnVote = 1; + + @ConfigDataBoolean(path = "PurgeNoDataOnStartup") + @Getter + private boolean purgeNoDataOnStartup = false; + + @ConfigDataBoolean(path = "StoreMonthTotalsWithDate") + @Getter + private boolean storeMonthTotalsWithDate = false; + + @ConfigDataBoolean(path = "UseMonthDateTotalsAsPrimaryTotal") + @Getter + private boolean useMonthDateTotalsAsPrimaryTotal = false; + + @ConfigDataString(path = "RequestAPI.DefaultMethod") + @Getter + private String requestAPIDefaultMethod = "ANVIL"; + + @ConfigDataListString(path = "RequestAPI.DisabledMethods") + @Getter + private ArrayList requestAPIDisabledMethods = new ArrayList<>(); + + @ConfigDataBoolean(path = "StoreTopVoters.Daily") + @Getter + private boolean storeTopVotersDaily = false; + + @ConfigDataBoolean(path = "StoreTopVoters.Weekly") + @Getter + private boolean storeTopVotersWeekly = false; + + @ConfigDataBoolean(path = "TopVoterAwardsTies") + @Getter + private boolean topVoterAwardsTies = true; + + @ConfigDataBoolean(path = "TopVoterIgnorePermission") + @Getter + private boolean topVoterIgnorePermission = false; + + @ConfigDataString(path = "VoteTopDefault") + @Getter + private String voteTopDefault = "Monthly"; + + @ConfigDataBoolean(path = "AlwaysProcessAsyncPlaceholders") + @Getter + private boolean alwaysProcessAsyncPlaceholders = false; + + /** + * Constructs a new Config. + * + * @param plugin the main plugin instance + */ + public Config(VotingPluginMain plugin) { + super(plugin, new File(plugin.getDataFolder(), "Config.yml")); + setIgnoreCase(true); + } + + /** + * Gets the black list. + * + * @return the black list + */ + @SuppressWarnings("unchecked") + public ArrayList getBlackList() { + return (ArrayList) getData().getList("BlackList", new ArrayList<>()); + } + + /** + * Gets the custom commands configuration section. + * + * @param ident the command identifier + * @return the configuration section + */ + public ConfigurationSection getCustomCommands(String ident) { + return getData().getConfigurationSection("CustomCommands." + ident); + } + + /** + * Gets the custom placeholder return keys. + * + * @param placeholder the placeholder name + * @return set of return keys + */ + public Set getCustomPlaceholderReturns(String placeholder) { + Set str = getData().getConfigurationSection("CustomPlaceholderReturns." + placeholder).getKeys(false); + if (str == null) { + str = new HashSet<>(); + } + return str; + } + + /** + * Gets a custom placeholder return value. + * + * @param placeholder the placeholder name + * @param returnString the return key + * @return the return value + */ + public String getCustomPlaceholderReturns(String placeholder, String returnString) { + return getData().getString("CustomPlaceholderReturns." + placeholder + "." + returnString, ""); + } + + /** + * Gets the commands vote party. + * + * @return the commands vote party + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteParty() { + ArrayList msg = new ArrayList<>(); + msg.add("&cCurrently at &6%Votes%&c, &6%NeededVotes% &cmore votes to go to reach &6%VotesRequired%"); + return (ArrayList) getData().getList("Format.Commands.Vote.Party", msg); + + } + + /** + * Gets the vote streak lines format. + * + * @return list of format lines + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteStreakLines() { + return (ArrayList) getData().getList("Format.Commands.Vote.Streak.Lines", new ArrayList<>()); + } + + /** + * Gets the commands vote text. + * + * @return the commands vote text + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteText() { + ArrayList str = new ArrayList<>(); + str.add("&4&lVote for our server!"); + return (ArrayList) getData().getList("Format.Commands.Vote.Text", str); + } + + /** + * Gets the vote total format lines. + * + * @return list of format lines + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteTotal() { + ArrayList list = (ArrayList) getData().getList("Format.Commands.Vote.Total", new ArrayList<>()); + if (list.isEmpty()) { + list.add("&3&l%player% Total Votes:"); + list.add("&3&lDaily Total: &6&l%DailyTotal%"); + list.add("&3&lWeekly Total: &6&l%WeeklyTotal%"); + list.add("&3&lMonthly Total: &6&l%MonthlyTotal%"); + list.add("&3&lAllTime Total: &6&l%AllTimeTotal%"); + } + return list; + } + + /** + * Gets the vote total all format lines. + * + * @return list of format lines + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatCommandsVoteTotalAll() { + + ArrayList list = (ArrayList) getData().getList("Format.Commands.Vote.TotalAll", + new ArrayList<>()); + if (list.isEmpty()) { + list.add("&3&lServer Total Votes:"); + list.add("&3&lDaily Total: &6&l%DailyTotal%"); + list.add("&3&lWeekly Total: &6&l%WeeklyTotal%"); + list.add("&3&lMonthly Total: &6&l%MonthlyTotal%"); + list.add("&3&lAllTime Total: &6&l%AllTimeTotal%"); + } + return list; + } + + /** + * Gets the vote help. + * + * @return the vote help + */ + @SuppressWarnings("unchecked") + public ArrayList getFormatVoteHelp() { + return (ArrayList) getData().getList("Format.Commands.Vote.Help.Lines", new ArrayList<>()); + } + + /** + * Checks if a top voter type should be loaded. + * + * @param top the top voter type + * @return true if should be loaded + */ + public boolean getLoadTopVoter(TopVoter top) { + switch (top) { + case AllTime: + return isLoadTopVoterAllTime(); + case Daily: + return isLoadTopVoterDaily(); + case Monthly: + return isLoadTopVoterMonthly(); + case Weekly: + return isLoadTopVoterWeekly(); + default: + return false; + } + } + + /** + * Gets the placeholder cache level. + * + * @return the cache level + */ + public PlaceholderCacheLevel getPlaceholderCacheLevel() { + return PlaceholderCacheLevel.getCache(getPlaceholderCacheLevelString()); + } + + @Override + public void loadValues() { + new AnnotationHandler().load(getData(), this); + } + + @Override + public void onFileCreation() { + getPlugin().saveResource("Config.yml", true); + } + +} 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 93d5685e26..d8250e6cb0 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/ConfigVoteSites.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/config/ConfigVoteSites.java @@ -1,674 +1,675 @@ -package com.bencodez.votingplugin.config; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.concurrent.TimeUnit; - -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; -import org.bukkit.entity.Player; - -import com.bencodez.advancedcore.api.rewards.DirectlyDefinedReward; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.simpleapi.file.YMLFile; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.time.ParsedDuration; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.util.ServiceSiteValidator; -import com.bencodez.votingplugin.votesites.VoteSite; -public class ConfigVoteSites extends YMLFile { - - private VotingPluginMain plugin; - - /** - * Constructs a new ConfigVoteSites. - * - * @param plugin the plugin instance - */ - public ConfigVoteSites(VotingPluginMain plugin) { - super(plugin, new File(plugin.getDataFolder(), "VoteSites.yml")); - setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles()); - this.plugin = plugin; - } - - /** - * Generate vote site. - * - * @param siteName the site name - */ - public void generateVoteSite(String siteName) { - tryGenerateVoteSite(siteName); - } - - /** - * Attempts to generate a vote site. - * - * @param siteName the site name - * @return {@code true} if the site was generated - */ - public boolean tryGenerateVoteSite(String siteName) { - if (plugin.getConfigFile().isAutoCreateVoteSites()) { - if (!ServiceSiteValidator.isValid(siteName)) { - plugin.getLogger().warning("Unable to generate vote site with unsupported name '" - + ServiceSiteValidator.sanitizeForLog(siteName) + "'"); - return false; - } - String org = siteName; - siteName = siteName.replaceAll("[\\.\\s]+", "_"); - - plugin.getLogger().warning("VoteSite " + siteName + " does not exist with the servicesite '" + org - + "', creating one, set AutoCreateVoteSites to false to prevent this"); - setEnabled(siteName, true); - setServiceSite(siteName, org); - setVoteURL(siteName, "VoteURL"); - setVoteDelay(siteName, "24h"); - 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(); - - plugin.addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteSites." + siteName + ".Rewards") { - - @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 + ".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") { - - @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); - } - }); - - for (Player p : Bukkit.getOnlinePlayers()) { - if (p.hasPermission("VotingPlugin.Admin.GenerateServiceSite") || p.isOp()) { - p.sendMessage(MessageAPI.colorize("&cGenerating votesite for service site " + siteName - + ", please check console for details")); - } - } - return true; - } - return false; - } - - /** - * Gets the data. - * - * @param siteName the site name - * @return the data - */ - public ConfigurationSection getData(String siteName) { - if (!getData().isConfigurationSection("VoteSites." + siteName)) { - plugin.getLogger().warning("VoteSites." + siteName + " is not a configuration section"); - } - return getData().getConfigurationSection("VoteSites." + siteName); - } - - /** - * Gets the display name for a site. - * - * @param site the site name - * @return the display name - */ - public String getDisplayName(String site) { - return getData(site).getString("Name"); - } - - /** - * Gets the path to the every site reward. - * - * @return the every site reward path - */ - public String getEverySiteRewardPath() { - return "EverySiteReward"; - } - - /** - * Gets the item configuration for a site. - * - * @param site the site name - * @return the item configuration - */ - public ConfigurationSection getItem(String site) { - if (getData(site).isConfigurationSection("DisplayItem")) { - return getData(site).getConfigurationSection("DisplayItem"); - } - return getData(site).getConfigurationSection("Item"); - } - - /** - * Gets the permission required to view a site. - * - * @param siteName the site name - * @return the permission to view - */ - public String getPermissionToView(String siteName) { - return getData(siteName).getString("PermissionToView", ""); - } - - /** - * Gets the priority. - * - * @param siteName the site name - * @return the priority - */ - public int getPriority(String siteName) { - return getData(siteName).getInt("Priority"); - } - - /** - * Gets the rewards. - * - * @param siteName the site name - * @return the rewards - */ - 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. - * - * @param siteName the site name - * @return the service site - */ - public String getServiceSite(String siteName) { - return getData(siteName).getString("ServiceSite"); - } - - /** - * Gets the vote delay for a site. - * - * @param site the site name - * @return the vote delay - */ - public ParsedDuration getVoteDelay(String site) { - ConfigurationSection sec = getData(site); - - // NEW FORMAT (string) - if (sec.isString("VoteDelay")) { - return ParsedDuration.parse(sec.getString("VoteDelay"), TimeUnit.HOURS); - } - - // LEGACY FORMAT (numbers) - double hours = sec.getDouble("VoteDelay", 0); - double minutes = sec.getDouble("VoteDelayMin", 0); - - long millis = (long) (hours * 60 * 60 * 1000) + (long) (minutes * 60 * 1000); - - return ParsedDuration.ofMillis(millis); - } - - /** - * Gets the vote delay daily hour for a site. - * - * @param siteName the site name - * @return the vote delay daily hour - */ - public int getVoteDelayDailyHour(String siteName) { - return getData(siteName).getInt("VoteDelayDailyHour", 0); - } - - /** - * Gets the vote site enabled. - * - * @param siteName the site name - * @return the vote site enabled - */ - public boolean getVoteSiteEnabled(String siteName) { - return getData(siteName).getBoolean("Enabled"); - } - - /** - * Gets the vote site file. - * - * @param siteName the site name - * @return the vote site file - */ - public File getVoteSiteFile(String siteName) { - File dFile = new File(plugin.getDataFolder() + File.separator + "VoteSites", siteName + ".yml"); - FileConfiguration data = YamlConfiguration.loadConfiguration(dFile); - if (!dFile.exists()) { - try { - data.save(dFile); - } catch (IOException e) { - plugin.getLogger().severe(ChatColor.RED + "Could not create VoteSites/" + siteName + ".yml!"); - - } - } - return dFile; - - } - - /** - * Gets whether to give rewards offline for a site. - * - * @param site the site name - * @return true if rewards should be given offline - */ - public boolean getVoteSiteGiveOffline(String site) { - return getData(site).getBoolean("ForceOffline", getData(site).getBoolean("GiveOffline")); - } - - /** - * Gets whether a site is hidden. - * - * @param siteName the site name - * @return true if the site is hidden - */ - public boolean getVoteSiteHidden(String siteName) { - return getData(siteName).getBoolean("Hidden"); - } - - /** - * Gets whether to ignore can vote check for a site. - * - * @param siteName the site name - * @return true if can vote check should be ignored - */ - public boolean getVoteSiteIgnoreCanVote(String siteName) { - return getData(siteName).getBoolean("IgnoreCanVote"); - } - - /** - * Gets whether vote delay resets daily for a site. - * - * @param siteName the site name - * @return true if vote delay resets daily - */ - public boolean getVoteSiteResetVoteDelayDaily(String siteName) { - return getData(siteName).getBoolean("VoteDelayDaily"); - } - - /** - * Gets the vote sites load. - * - * @return the vote sites load - */ - public ArrayList getVoteSitesLoad() { - ArrayList voteSites = new ArrayList<>(); - ArrayList voteSiteNames = getVoteSitesNames(true); - if (voteSiteNames != null) { - for (String site : voteSiteNames) { - if (getVoteSiteEnabled(site) && !site.equalsIgnoreCase("null")) { - if (!siteCheck(site)) { - plugin.getLogger().warning("Failed to load site " + site + ", see above"); - } else { - VoteSite voteSite = new VoteSite(plugin, site); - plugin.debug(voteSite.loadingDebug()); - voteSites.add(voteSite); - } - } - } - } - - Collections.sort(voteSites, new Comparator() { - @Override - public int compare(VoteSite v1, VoteSite v2) { - int v1P = v1.getPriority(); - int v2P = v2.getPriority(); - - if (v1P < v2P) { - return 1; - } - if (v1P > v2P) { - return -1; - } - - return 0; - } - }); - - return voteSites; - } - - /** - * Gets configured vote-site section keys without filtering by Enabled or - * validating the site's settings. - * - * @return the configured vote-site section keys - */ - public ArrayList getRawVoteSiteNames() { - ArrayList siteNames = new ArrayList<>(); - - if (!getData().isConfigurationSection("VoteSites")) { - return siteNames; - } - - siteNames = ArrayUtils.convert(getData().getConfigurationSection("VoteSites").getKeys(false)); - siteNames.removeIf(siteName -> !getData().isConfigurationSection("VoteSites." + siteName)); - return siteNames; - } - - /** - * Gets the names of vote sites. - * - * @param checkEnabled whether to check if sites are enabled - * @return the list of vote site names - */ - public ArrayList getVoteSitesNames(boolean checkEnabled) { - ArrayList siteNames = new ArrayList<>(); - - if (!getData().isConfigurationSection("VoteSites")) { - return siteNames; - } - - siteNames = ArrayUtils.convert(getData().getConfigurationSection("VoteSites").getKeys(false)); - - for (int i = siteNames.size() - 1; i >= 0; i--) { - String site = siteNames.get(i); - String path = "VoteSites." + site; - - if (!getData().isConfigurationSection(path)) { - plugin.getLogger().warning(path + " is not a configuration section, please remove"); - siteNames.remove(i); - continue; - } - - if (site.equalsIgnoreCase("null") || (!getVoteSiteEnabled(site) && checkEnabled) || !siteCheck(site)) { - siteNames.remove(i); - continue; - } - } - - return siteNames; - } - - /** - * Gets the vote URL. - * - * @param siteName the site name - * @return the vote URL - */ - public String getVoteURL(String siteName) { - return getData(siteName).getString("VoteURL", ""); - } - - /** - * Gets whether to wait until vote delay for a site. - * - * @param siteName the site name - * @return true if should wait until vote delay - */ - public boolean getWaitUntilVoteDelay(String siteName) { - return getData(siteName).getBoolean("WaitUntilVoteDelay", false); - } - - /** - * Checks if is service site good. - * - * @param siteName the site name - * @return true, if is service site good - */ - public boolean isServiceSiteGood(String siteName) { - if (getServiceSite(siteName) == null || getServiceSite(siteName).equals("")) { - return false; - } - return true; - } - - /** - * Checks if is vote URL good. - * - * @param siteName the site name - * @return true, if is vote URL good - */ - public boolean isVoteURLGood(String siteName) { - if (getVoteURL(siteName) == null || getVoteURL(siteName).equals("")) { - return false; - } - return true; - } - - @Override - public void onFileCreation() { - plugin.saveResource("VoteSites.yml", true); - - } - - /** - * Rename vote site. - * - * @param siteName the site name - * @param newName the new name - * @return true, if successful - */ - public boolean renameVoteSite(String siteName, String newName) { - return getVoteSiteFile(siteName) - .renameTo(new File(plugin.getDataFolder() + File.separator + "VoteSites", newName + ".yml")); - } - - /** - * Sets the. - * - * @param siteName the site name - * @param path the path - * @param value the value - */ - public void set(String siteName, String path, Object value) { - // String playerName = user.getPlayerName(); - ConfigurationSection data = getData(siteName); - if (data == null) { - getData().createSection("VoteSites." + siteName); - data = getData(siteName); - } - data.set(path, value); - saveData(); - } - - /** - * Sets the cumulative rewards. - * - * @param siteName the site name - * @param value the value - */ - public void setCumulativeRewards(String siteName, ArrayList value) { - set(siteName, "Cumulative.Rewards", value); - } - - /** - * Sets the cumulative votes for a site. - * - * @param siteName the site name - * @param value the value - */ - public void setCumulativeVotes(String siteName, int value) { - set(siteName, "Cumulative.Votes", value); - } - - /** - * Sets the display name for a site. - * - * @param siteName the site name - * @param value the value - */ - public void setDisplayName(String siteName, String value) { - set(siteName, "Name", value); - } - - /** - * Sets the enabled. - * - * @param siteName the site name - * @param disabled the disabled - */ - public void setEnabled(String siteName, boolean disabled) { - set(siteName, "Enabled", disabled); - } - - /** - * Sets whether to force offline for a site. - * - * @param siteName the site name - * @param value the value - */ - public void setForceOffline(String siteName, boolean value) { - set(siteName, "ForceOffline", value); - - } - - /** - * Sets the priority. - * - * @param siteName the site name - * @param value the value - */ - public void setPriority(String siteName, int value) { - set(siteName, "Priority", value); - } - - /** - * Sets the rewards. - * - * @param siteName the site name - * @param value the value - */ - public void setRewards(String siteName, ArrayList value) { - set(siteName, "Rewards", value); - } - - /** - * Sets the service site. - * - * @param siteName the site name - * @param serviceSite the service site - */ - public void setServiceSite(String siteName, String serviceSite) { - set(siteName, "ServiceSite", serviceSite); - } - - /** - * Sets the vote delay. - * - * @param siteName the site name - * @param voteDelay the vote delay - */ - public void setVoteDelay(String siteName, String voteDelay) { - set(siteName, "VoteDelay", voteDelay); - } - - /** - * Sets the vote URL. - * - * @param siteName the site name - * @param url the url - */ - public void setVoteURL(String siteName, String url) { - set(siteName, "VoteURL", url); - } - - /** - * Site check. - * - * @param siteName the site name - * @return true, if successful - */ - public boolean siteCheck(String siteName) { - boolean pass = true; - if (!isServiceSiteGood(siteName)) { - plugin.getLogger().warning("Issue with ServiceSite in site " + siteName + ", votes may not work properly"); - pass = false; - } - if (!isVoteURLGood(siteName)) { - plugin.getLogger().warning("Issue with VoteURL in site " + siteName); - } - return pass; - } - - /** - * Sets the vote delay daily hour for a site. - * - * @param siteName the site name - * @param intValue the value - */ - public void setVoteDelayDailyHour(String siteName, int intValue) { - set(siteName, "VoteDelayDailyHour", intValue); - } - - /** - * Sets whether vote delay is daily for a site. - * - * @param siteName the site name - * @param value the value - */ - public void setVoteDelayDaily(String siteName, boolean value) { - set(siteName, "VoteDelayDaily", value); - } - -} +package com.bencodez.votingplugin.config; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.concurrent.TimeUnit; + +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; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.rewards.DirectlyDefinedReward; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.simpleapi.file.YMLFile; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.simpleapi.time.ParsedDuration; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.util.ServiceSiteValidator; +import com.bencodez.votingplugin.votesites.VoteSite; + +public class ConfigVoteSites extends YMLFile { + + private VotingPluginMain plugin; + + /** + * Constructs a new ConfigVoteSites. + * + * @param plugin the plugin instance + */ + public ConfigVoteSites(VotingPluginMain plugin) { + super(plugin, new File(plugin.getDataFolder(), "VoteSites.yml")); + setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles()); + this.plugin = plugin; + } + + /** + * Generate vote site. + * + * @param siteName the site name + */ + public void generateVoteSite(String siteName) { + tryGenerateVoteSite(siteName); + } + + /** + * Attempts to generate a vote site. + * + * @param siteName the site name + * @return {@code true} if the site was generated + */ + public boolean tryGenerateVoteSite(String siteName) { + if (plugin.getConfigFile().isAutoCreateVoteSites()) { + if (!ServiceSiteValidator.isValid(siteName)) { + plugin.getLogger().warning("Unable to generate vote site with unsupported name '" + + ServiceSiteValidator.sanitizeForLog(siteName) + "'"); + return false; + } + String org = siteName; + siteName = siteName.replaceAll("[\\.\\s]+", "_"); + + plugin.getLogger().warning("VoteSite " + siteName + " does not exist with the servicesite '" + org + + "', creating one, set AutoCreateVoteSites to false to prevent this"); + setEnabled(siteName, true); + setServiceSite(siteName, org); + setVoteURL(siteName, "VoteURL"); + setVoteDelay(siteName, "24h"); + 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(); + + plugin.addDirectlyDefinedRewards(new DirectlyDefinedReward("VoteSites." + siteName + ".Rewards") { + + @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 + ".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") { + + @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); + } + }); + + for (Player p : Bukkit.getOnlinePlayers()) { + if (p.hasPermission("VotingPlugin.Admin.GenerateServiceSite") || p.isOp()) { + p.sendMessage(MessageAPI.colorize("&cGenerating votesite for service site " + siteName + + ", please check console for details")); + } + } + return true; + } + return false; + } + + /** + * Gets the data. + * + * @param siteName the site name + * @return the data + */ + public ConfigurationSection getData(String siteName) { + if (!getData().isConfigurationSection("VoteSites." + siteName)) { + plugin.getLogger().warning("VoteSites." + siteName + " is not a configuration section"); + } + return getData().getConfigurationSection("VoteSites." + siteName); + } + + /** + * Gets the display name for a site. + * + * @param site the site name + * @return the display name + */ + public String getDisplayName(String site) { + return getData(site).getString("Name"); + } + + /** + * Gets the path to the every site reward. + * + * @return the every site reward path + */ + public String getEverySiteRewardPath() { + return "EverySiteReward"; + } + + /** + * Gets the item configuration for a site. + * + * @param site the site name + * @return the item configuration + */ + public ConfigurationSection getItem(String site) { + if (getData(site).isConfigurationSection("DisplayItem")) { + return getData(site).getConfigurationSection("DisplayItem"); + } + return getData(site).getConfigurationSection("Item"); + } + + /** + * Gets the permission required to view a site. + * + * @param siteName the site name + * @return the permission to view + */ + public String getPermissionToView(String siteName) { + return getData(siteName).getString("PermissionToView", ""); + } + + /** + * Gets the priority. + * + * @param siteName the site name + * @return the priority + */ + public int getPriority(String siteName) { + return getData(siteName).getInt("Priority"); + } + + /** + * Gets the rewards. + * + * @param siteName the site name + * @return the rewards + */ + 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. + * + * @param siteName the site name + * @return the service site + */ + public String getServiceSite(String siteName) { + return getData(siteName).getString("ServiceSite"); + } + + /** + * Gets the vote delay for a site. + * + * @param site the site name + * @return the vote delay + */ + public ParsedDuration getVoteDelay(String site) { + ConfigurationSection sec = getData(site); + + // NEW FORMAT (string) + if (sec.isString("VoteDelay")) { + return ParsedDuration.parse(sec.getString("VoteDelay"), TimeUnit.HOURS); + } + + // LEGACY FORMAT (numbers) + double hours = sec.getDouble("VoteDelay", 0); + double minutes = sec.getDouble("VoteDelayMin", 0); + + long millis = (long) (hours * 60 * 60 * 1000) + (long) (minutes * 60 * 1000); + + return ParsedDuration.ofMillis(millis); + } + + /** + * Gets the vote delay daily hour for a site. + * + * @param siteName the site name + * @return the vote delay daily hour + */ + public int getVoteDelayDailyHour(String siteName) { + return getData(siteName).getInt("VoteDelayDailyHour", 0); + } + + /** + * Gets the vote site enabled. + * + * @param siteName the site name + * @return the vote site enabled + */ + public boolean getVoteSiteEnabled(String siteName) { + return getData(siteName).getBoolean("Enabled"); + } + + /** + * Gets the vote site file. + * + * @param siteName the site name + * @return the vote site file + */ + public File getVoteSiteFile(String siteName) { + File dFile = new File(plugin.getDataFolder() + File.separator + "VoteSites", siteName + ".yml"); + FileConfiguration data = YamlConfiguration.loadConfiguration(dFile); + if (!dFile.exists()) { + try { + data.save(dFile); + } catch (IOException e) { + plugin.getLogger().severe(ChatColor.RED + "Could not create VoteSites/" + siteName + ".yml!"); + + } + } + return dFile; + + } + + /** + * Gets whether to give rewards offline for a site. + * + * @param site the site name + * @return true if rewards should be given offline + */ + public boolean getVoteSiteGiveOffline(String site) { + return getData(site).getBoolean("ForceOffline", getData(site).getBoolean("GiveOffline")); + } + + /** + * Gets whether a site is hidden. + * + * @param siteName the site name + * @return true if the site is hidden + */ + public boolean getVoteSiteHidden(String siteName) { + return getData(siteName).getBoolean("Hidden"); + } + + /** + * Gets whether to ignore can vote check for a site. + * + * @param siteName the site name + * @return true if can vote check should be ignored + */ + public boolean getVoteSiteIgnoreCanVote(String siteName) { + return getData(siteName).getBoolean("IgnoreCanVote"); + } + + /** + * Gets whether vote delay resets daily for a site. + * + * @param siteName the site name + * @return true if vote delay resets daily + */ + public boolean getVoteSiteResetVoteDelayDaily(String siteName) { + return getData(siteName).getBoolean("VoteDelayDaily"); + } + + /** + * Gets the vote sites load. + * + * @return the vote sites load + */ + public ArrayList getVoteSitesLoad() { + ArrayList voteSites = new ArrayList<>(); + ArrayList voteSiteNames = getVoteSitesNames(true); + if (voteSiteNames != null) { + for (String site : voteSiteNames) { + if (getVoteSiteEnabled(site) && !site.equalsIgnoreCase("null")) { + if (!siteCheck(site)) { + plugin.getLogger().warning("Failed to load site " + site + ", see above"); + } else { + VoteSite voteSite = new VoteSite(plugin, site); + plugin.debug(voteSite.loadingDebug()); + voteSites.add(voteSite); + } + } + } + } + + Collections.sort(voteSites, new Comparator() { + @Override + public int compare(VoteSite v1, VoteSite v2) { + int v1P = v1.getPriority(); + int v2P = v2.getPriority(); + + if (v1P < v2P) { + return 1; + } + if (v1P > v2P) { + return -1; + } + + return 0; + } + }); + + return voteSites; + } + + /** + * Gets configured vote-site section keys without filtering by Enabled or + * validating the site's settings. + * + * @return the configured vote-site section keys + */ + public ArrayList getRawVoteSiteNames() { + ArrayList siteNames = new ArrayList<>(); + + if (!getData().isConfigurationSection("VoteSites")) { + return siteNames; + } + + siteNames = ArrayUtils.convert(getData().getConfigurationSection("VoteSites").getKeys(false)); + siteNames.removeIf(siteName -> !getData().isConfigurationSection("VoteSites." + siteName)); + return siteNames; + } + + /** + * Gets the names of vote sites. + * + * @param checkEnabled whether to check if sites are enabled + * @return the list of vote site names + */ + public ArrayList getVoteSitesNames(boolean checkEnabled) { + ArrayList siteNames = new ArrayList<>(); + + if (!getData().isConfigurationSection("VoteSites")) { + return siteNames; + } + + siteNames = ArrayUtils.convert(getData().getConfigurationSection("VoteSites").getKeys(false)); + + for (int i = siteNames.size() - 1; i >= 0; i--) { + String site = siteNames.get(i); + String path = "VoteSites." + site; + + if (!getData().isConfigurationSection(path)) { + plugin.getLogger().warning(path + " is not a configuration section, please remove"); + siteNames.remove(i); + continue; + } + + if (site.equalsIgnoreCase("null") || (!getVoteSiteEnabled(site) && checkEnabled) || !siteCheck(site)) { + siteNames.remove(i); + continue; + } + } + + return siteNames; + } + + /** + * Gets the vote URL. + * + * @param siteName the site name + * @return the vote URL + */ + public String getVoteURL(String siteName) { + return getData(siteName).getString("VoteURL", ""); + } + + /** + * Gets whether to wait until vote delay for a site. + * + * @param siteName the site name + * @return true if should wait until vote delay + */ + public boolean getWaitUntilVoteDelay(String siteName) { + return getData(siteName).getBoolean("WaitUntilVoteDelay", false); + } + + /** + * Checks if is service site good. + * + * @param siteName the site name + * @return true, if is service site good + */ + public boolean isServiceSiteGood(String siteName) { + if (getServiceSite(siteName) == null || getServiceSite(siteName).equals("")) { + return false; + } + return true; + } + + /** + * Checks if is vote URL good. + * + * @param siteName the site name + * @return true, if is vote URL good + */ + public boolean isVoteURLGood(String siteName) { + if (getVoteURL(siteName) == null || getVoteURL(siteName).equals("")) { + return false; + } + return true; + } + + @Override + public void onFileCreation() { + plugin.saveResource("VoteSites.yml", true); + + } + + /** + * Rename vote site. + * + * @param siteName the site name + * @param newName the new name + * @return true, if successful + */ + public boolean renameVoteSite(String siteName, String newName) { + return getVoteSiteFile(siteName) + .renameTo(new File(plugin.getDataFolder() + File.separator + "VoteSites", newName + ".yml")); + } + + /** + * Sets the. + * + * @param siteName the site name + * @param path the path + * @param value the value + */ + public void set(String siteName, String path, Object value) { + // String playerName = user.getPlayerName(); + ConfigurationSection data = getData(siteName); + if (data == null) { + getData().createSection("VoteSites." + siteName); + data = getData(siteName); + } + data.set(path, value); + saveData(); + } + + /** + * Sets the cumulative rewards. + * + * @param siteName the site name + * @param value the value + */ + public void setCumulativeRewards(String siteName, ArrayList value) { + set(siteName, "Cumulative.Rewards", value); + } + + /** + * Sets the cumulative votes for a site. + * + * @param siteName the site name + * @param value the value + */ + public void setCumulativeVotes(String siteName, int value) { + set(siteName, "Cumulative.Votes", value); + } + + /** + * Sets the display name for a site. + * + * @param siteName the site name + * @param value the value + */ + public void setDisplayName(String siteName, String value) { + set(siteName, "Name", value); + } + + /** + * Sets the enabled. + * + * @param siteName the site name + * @param disabled the disabled + */ + public void setEnabled(String siteName, boolean disabled) { + set(siteName, "Enabled", disabled); + } + + /** + * Sets whether to force offline for a site. + * + * @param siteName the site name + * @param value the value + */ + public void setForceOffline(String siteName, boolean value) { + set(siteName, "ForceOffline", value); + + } + + /** + * Sets the priority. + * + * @param siteName the site name + * @param value the value + */ + public void setPriority(String siteName, int value) { + set(siteName, "Priority", value); + } + + /** + * Sets the rewards. + * + * @param siteName the site name + * @param value the value + */ + public void setRewards(String siteName, ArrayList value) { + set(siteName, "Rewards", value); + } + + /** + * Sets the service site. + * + * @param siteName the site name + * @param serviceSite the service site + */ + public void setServiceSite(String siteName, String serviceSite) { + set(siteName, "ServiceSite", serviceSite); + } + + /** + * Sets the vote delay. + * + * @param siteName the site name + * @param voteDelay the vote delay + */ + public void setVoteDelay(String siteName, String voteDelay) { + set(siteName, "VoteDelay", voteDelay); + } + + /** + * Sets the vote URL. + * + * @param siteName the site name + * @param url the url + */ + public void setVoteURL(String siteName, String url) { + set(siteName, "VoteURL", url); + } + + /** + * Site check. + * + * @param siteName the site name + * @return true, if successful + */ + public boolean siteCheck(String siteName) { + boolean pass = true; + if (!isServiceSiteGood(siteName)) { + plugin.getLogger().warning("Issue with ServiceSite in site " + siteName + ", votes may not work properly"); + pass = false; + } + if (!isVoteURLGood(siteName)) { + plugin.getLogger().warning("Issue with VoteURL in site " + siteName); + } + return pass; + } + + /** + * Sets the vote delay daily hour for a site. + * + * @param siteName the site name + * @param intValue the value + */ + public void setVoteDelayDailyHour(String siteName, int intValue) { + set(siteName, "VoteDelayDailyHour", intValue); + } + + /** + * Sets whether vote delay is daily for a site. + * + * @param siteName the site name + * @param value the value + */ + public void setVoteDelayDaily(String siteName, boolean value) { + set(siteName, "VoteDelayDaily", value); + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/data/ServerData.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/data/ServerData.java index ca9c74b6a6..603bd59b79 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/data/ServerData.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/data/ServerData.java @@ -1,555 +1,556 @@ -package com.bencodez.votingplugin.data; - -import java.time.temporal.WeekFields; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.UUID; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.configuration.ConfigurationSection; - -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.signs.SignHandler; -import com.bencodez.votingplugin.timequeue.VoteTimeQueue; -import com.bencodez.votingplugin.topvoter.TopVoter; -public class ServerData { - - private VotingPluginMain plugin = VotingPluginMain.plugin; - - /** - * Constructs a new ServerData. - * - * @param plugin the main plugin instance - */ - public ServerData(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * Adds an auto-cached placeholder. - * - * @param placeholder the placeholder to add - */ - public void addAutoCachedPlaceholder(String placeholder) { - List p = getAutoCachedPlaceholder(); - - if (!ArrayUtils.containsIgnoreCase(p, placeholder)) { - p.add(placeholder); - setAutoCachedPlaceholder(p); - } - } - - /** - * Adds a service site to the list. - * - * @param site the service site to add - */ - public synchronized void addServiceSite(String site) { - ArrayList l = getServiceSites(); - if (!getServiceSites().contains(site)) { - l.add(site); - } - setServiceSites(ArrayUtils.removeDuplicates(l)); - } - - /** - * Adds the sign. - * - * @param location the location - * @param data the data - * @param position the position - */ - public void addSign(Location location, String data, int position) { - - int count = nextSignNumber(); - - getData().set("Signs." + count + ".World", location.getWorld().getName()); - getData().set("Signs." + count + ".X", location.getBlockX()); - getData().set("Signs." + count + ".Y", location.getBlockY()); - getData().set("Signs." + count + ".Z", location.getBlockZ()); - getData().set("Signs." + count + ".Data", data); - getData().set("Signs." + count + ".Position", position); - saveData(); - plugin.getSigns().getSigns().add(new SignHandler(plugin, "" + count, getSignLocation("" + count), - getSignSkullLocation("" + count), getSignData("" + count), getSignPosition("" + count))); - } - - /** - * Adds a timed vote to the cache. - * - * @param num the vote number - * @param vote the vote time queue entry - */ - public void addTimeVoted(int num, VoteTimeQueue vote) { - getData().set("TimedVoteCache." + num + ".Name", vote.getName()); - getData().set("TimedVoteCache." + num + ".Service", vote.getService()); - getData().set("TimedVoteCache." + num + ".Time", vote.getTime()); - saveData(); - } - - /** - * Adds a vote shop purchase for the specified identifier. - * - * @param ident the vote shop identifier - */ - public void addVoteShopPurchase(String ident) { - setVoteShopPurchases(ident, (getVoteShopPurchases(ident) + 1)); - } - - /** - * Clears the timed vote cache. - */ - public void clearTimedVoteCache() { - getData().set("TimedVoteCache", null); - saveData(); - } - - /** - * Gets the auto cached placeholders. - * - * @return the auto cached placeholder list - */ - public List getAutoCachedPlaceholder() { - return getData().getStringList("AutoCachePlaceholders"); - } - - /** - * Gets the current bungee vote party count. - * - * @return the bungee vote party current count - */ - public int getBungeeVotePartyCurrent() { - return getData().getInt("BungeeVotePartyCurrent"); - } - - /** - * Gets the required votes for bungee vote party. - * - * @return the bungee vote party required votes - */ - public int getBungeeVotePartyRequired() { - return getData().getInt("BungeeVotePartyRequired"); - } - - /** - * Gets the data. - * - * @return the data - */ - public ConfigurationSection getData() { - ConfigurationSection data = plugin.getServerDataFile().getData().getConfigurationSection("VotingPlugin"); - if (data == null) { - plugin.getServerDataFile().getData().createSection("VotingPlugin"); - data = plugin.getServerDataFile().getData().getConfigurationSection("VotingPlugin"); - } - return data; - } - - /** - * Gets the list of disabled reminders. - * - * @return the disabled reminders - */ - public List getDisabledReminders() { - return getData().getStringList("DisabledReminders"); - } - - /** - * Gets the service sites list. - * - * @return the service sites - */ - @SuppressWarnings("unchecked") - public ArrayList getServiceSites() { - return (ArrayList) getData().getList("GottenServiceSites", new ArrayList<>()); - } - - /** - * Gets the sign data. - * - * @param sign the sign - * @return the sign data - */ - public String getSignData(String sign) { - return getData().getString("Signs." + sign + ".Data"); - } - - /** - * Gets the sign location. - * - * @param sign the sign - * @return the sign location - */ - public Location getSignLocation(String sign) { - return new Location(Bukkit.getWorld(getData().getString("Signs." + sign + ".World")), - getData().getDouble("Signs." + sign + ".X"), getData().getDouble("Signs." + sign + ".Y"), - getData().getDouble("Signs." + sign + ".Z")); - } - - /** - * Gets the sign position. - * - * @param sign the sign - * @return the sign position - */ - public int getSignPosition(String sign) { - return getData().getInt("Signs." + sign + ".Position"); - } - - /** - * Gets the signs. - * - * @return the signs - */ - public Set getSigns() { - try { - return getData().getConfigurationSection("Signs").getKeys(false); - } catch (Exception ex) { - return new HashSet<>(); - } - } - - /** - * Gets the sign location. - * - * @param sign the sign - * @return the sign location - */ - public Location getSignSkullLocation(String sign) { - if (getData().getString("Signs." + sign + ".Skull.World", "").isEmpty()) { - return null; - } - return new Location(Bukkit.getWorld(getData().getString("Signs." + sign + ".Skull.World")), - getData().getDouble("Signs." + sign + ".Skull.X"), getData().getDouble("Signs." + sign + ".Skull.Y"), - getData().getDouble("Signs." + sign + ".Skull.Z")); - } - - /** - * Gets the timed vote cache keys. - * - * @return the timed vote cache keys - */ - public Set getTimedVoteCacheKeys() { - if (getData().isConfigurationSection("TimedVoteCache")) { - return getData().getConfigurationSection("TimedVoteCache").getKeys(false); - } - return new HashSet<>(); - } - - /** - * Gets the timed vote cache section for the given number. - * - * @param num the cache entry number - * @return the timed vote cache section - */ - public ConfigurationSection getTimedVoteCacheSection(String num) { - return getData().getConfigurationSection("TimedVoteCache." + num); - } - - /** - * Gets the extra required votes for vote party. - * - * @return the vote party extra required votes - */ - public int getVotePartyExtraRequired() { - return getData().getInt("VotePartyExtraRequired", 0); - } - - /** - * Gets the number of purchases for a vote shop item. - * - * @param ident the vote shop identifier - * @return the vote shop purchases - */ - public int getVoteShopPurchases(String ident) { - return getData().getInt("VoteShopPurchases." + ident); - } - - /** - * Checks if the last vote party was on the same day. - * - * @return true if same day - */ - public boolean isLastVotePartySameDay() { - int num = getData().getInt("LastVoteParty", 0); - if (num == plugin.getTimeChecker().getTime().getDayOfYear()) { - return true; - } - return false; - } - - /** - * Checks if the last vote party was in the same week. - * - * @return true if same week - */ - public boolean isLastVotePartySameWeek() { - int num = getData().getInt("LastVotePartyWeek", -1); - if (num == plugin.getTimeChecker().getTime().get(WeekFields.of(Locale.getDefault()).weekOfYear()) - && num != -1) { - return true; - } - return false; - } - - /** - * Checks if the vote shop has been converted. - * - * @return true if converted - */ - public boolean isVoteShopConverted() { - return getData().getBoolean("VoteShopConverted"); - } - - /** - * Next sign number. - * - * @return the int - */ - public int nextSignNumber() { - Set signs = getSigns(); - - if (signs != null) { - for (int i = 0; i < 100000; i++) { - if (!signs.contains(Integer.toString(i))) { - return i; - } - } - } - return 0; - } - - /** - * Reload data. - */ - public void reloadData() { - plugin.getServerDataFile().reloadData(); - } - - /** - * Gets the Discord message ID for the top voter. - * - * @param top the top voter type - * @return the top voter message ID - */ - public long getTopVoterMessageId(TopVoter top) { - return getData().getLong("DiscordSRV.TopVoterMessageId." + top.toString(), 0); - } - - /** - * Sets the Discord message ID for the top voter. - * - * @param top the top voter type - * @param messageId the message ID - */ - public void setTopVoterMessageId(TopVoter top, long messageId) { - getData().set("DiscordSRV.TopVoterMessageId." + top.toString(), messageId); - saveData(); - } - - /** - * Removes the sign. - * - * @param sign the sign - */ - public void removeSign(String sign) { - getData().set("Signs." + sign + ".World", null); - getData().set("Signs." + sign + ".X", null); - getData().set("Signs." + sign + ".Y", null); - getData().set("Signs." + sign + ".Z", null); - getData().set("Signs." + sign + ".Data", null); - getData().set("Signs." + sign + ".Position", null); - getData().set("Signs." + sign, null); - getData().set("Signs." + sign + ".Skull.World", null); - getData().set("Signs." + sign + ".Skull.X", null); - getData().set("Signs." + sign + ".Skull.Y", null); - getData().set("Signs." + sign + ".Skull.Z", null); - saveData(); - } - - /** - * Save data. - */ - public synchronized void saveData() { - plugin.getServerDataFile().saveData(); - } - - /** - * Saves the disabled reminders list. - * - * @param disabledReminders the list of UUIDs with disabled reminders - */ - public void saveDisabledReminders(ArrayList disabledReminders) { - ArrayList uuids = new ArrayList<>(); - for (UUID uuid : disabledReminders) { - uuids.add(uuid.toString()); - } - getData().set("DisabledReminders", uuids); - saveData(); - } - - /** - * Sets the auto cached placeholders. - * - * @param placeholders the list of placeholders - */ - public void setAutoCachedPlaceholder(List placeholders) { - getData().set("AutoCachePlaceholders", placeholders); - saveData(); - } - - /** - * Sets the current bungee vote party count. - * - * @param current the current vote count - */ - public void setBungeeVotePartyCurrent(int current) { - getData().set("BungeeVotePartyCurrent", current); - saveData(); - } - - /** - * Sets the required votes for bungee vote party. - * - * @param required the required vote count - */ - public void setBungeeVotePartyRequired(int required) { - getData().set("BungeeVotePartyRequired", required); - saveData(); - } - - /** - * Sets the service sites list. - * - * @param list the service sites list - */ - public void setServiceSites(ArrayList list) { - getData().set("GottenServiceSites", list); - saveData(); - } - - /** - * Sets the vote shop converted status. - * - * @param value the converted status - */ - public void setShopConverted(boolean value) { - getData().set("VoteShopConverted", value); - saveData(); - } - - /** - * Sets sign data. - * - * @param count the sign count - * @param location the sign location - * @param skullLocation the skull location - * @param data the sign data - * @param position the sign position - */ - public void setSign(String count, Location location, Location skullLocation, String data, int position) { - - getData().set("Signs." + count + ".World", location.getWorld().getName()); - getData().set("Signs." + count + ".X", (int) location.getX()); - getData().set("Signs." + count + ".Y", (int) location.getY()); - getData().set("Signs." + count + ".Z", (int) location.getZ()); - getData().set("Signs." + count + ".Data", data); - getData().set("Signs." + count + ".Position", position); - if (skullLocation != null) { - getData().set("Signs." + count + ".Skull.World", skullLocation.getWorld().getName()); - getData().set("Signs." + count + ".Skull.X", (int) skullLocation.getX()); - getData().set("Signs." + count + ".Skull.Y", (int) skullLocation.getY()); - getData().set("Signs." + count + ".Skull.Z", (int) skullLocation.getZ()); - } - saveData(); - } - - /** - * Sets the skull location for a sign. - * - * @param count the sign count - * @param skullLocation the skull location - */ - public void setSkullLocation(String count, Location skullLocation) { - if (skullLocation != null) { - getData().set("Signs." + count + ".Skull.World", skullLocation.getWorld().getName()); - getData().set("Signs." + count + ".Skull.X", (int) skullLocation.getX()); - getData().set("Signs." + count + ".Skull.Y", (int) skullLocation.getY()); - getData().set("Signs." + count + ".Skull.Z", (int) skullLocation.getZ()); - } - } - - /** - * Sets the version. - */ - public void setVersion() { - getData().set("Version", Bukkit.getVersion()); - saveData(); - } - - /** - * Sets the extra required votes for vote party. - * - * @param value the extra required votes - */ - public void setVotePartyExtraRequired(int value) { - getData().set("VotePartyExtraRequired", value); - saveData(); - } - - /** - * Sets the number of purchases for a vote shop item. - * - * @param ident the vote shop identifier - * @param amount the purchase amount - */ - public void setVoteShopPurchases(String ident, int amount) { - getData().set("VoteShopPurchases." + ident, amount); - saveData(); - } - - /** - * Updates the last vote party timestamp to today. - */ - public void updateLastVoteParty() { - getData().set("LastVoteParty", plugin.getTimeChecker().getTime().getDayOfYear()); - saveData(); - } - - /** - * Updates the last vote party week timestamp to this week. - */ - public void updateLastVotePartyWeek() { - getData().set("LastVotePartyWeek", - plugin.getTimeChecker().getTime().get(WeekFields.of(Locale.getDefault()).weekOfYear())); - saveData(); - } - - /** - * Updates placeholders to lowercase format. - */ - public void updatePlaceholders() { - boolean data = getData().getBoolean("AutoCacheUpdated", false); - if (!data) { - List placeholders = getAutoCachedPlaceholder(); - for (int i = 0; i < placeholders.size(); i++) { - placeholders.set(i, placeholders.get(i).toLowerCase()); - } - setAutoCachedPlaceholder(placeholders); - getData().set("AutoCacheUpdated", true); - saveData(); - } - } - - /** - * Update values. - */ - public void updateValues() { - setVersion(); - } -} +package com.bencodez.votingplugin.data; + +import java.time.temporal.WeekFields; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.signs.SignHandler; +import com.bencodez.votingplugin.timequeue.VoteTimeQueue; +import com.bencodez.votingplugin.topvoter.TopVoter; + +public class ServerData { + + private VotingPluginMain plugin = VotingPluginMain.plugin; + + /** + * Constructs a new ServerData. + * + * @param plugin the main plugin instance + */ + public ServerData(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * Adds an auto-cached placeholder. + * + * @param placeholder the placeholder to add + */ + public void addAutoCachedPlaceholder(String placeholder) { + List p = getAutoCachedPlaceholder(); + + if (!ArrayUtils.containsIgnoreCase(p, placeholder)) { + p.add(placeholder); + setAutoCachedPlaceholder(p); + } + } + + /** + * Adds a service site to the list. + * + * @param site the service site to add + */ + public synchronized void addServiceSite(String site) { + ArrayList l = getServiceSites(); + if (!getServiceSites().contains(site)) { + l.add(site); + } + setServiceSites(ArrayUtils.removeDuplicates(l)); + } + + /** + * Adds the sign. + * + * @param location the location + * @param data the data + * @param position the position + */ + public void addSign(Location location, String data, int position) { + + int count = nextSignNumber(); + + getData().set("Signs." + count + ".World", location.getWorld().getName()); + getData().set("Signs." + count + ".X", location.getBlockX()); + getData().set("Signs." + count + ".Y", location.getBlockY()); + getData().set("Signs." + count + ".Z", location.getBlockZ()); + getData().set("Signs." + count + ".Data", data); + getData().set("Signs." + count + ".Position", position); + saveData(); + plugin.getSigns().getSigns().add(new SignHandler(plugin, "" + count, getSignLocation("" + count), + getSignSkullLocation("" + count), getSignData("" + count), getSignPosition("" + count))); + } + + /** + * Adds a timed vote to the cache. + * + * @param num the vote number + * @param vote the vote time queue entry + */ + public void addTimeVoted(int num, VoteTimeQueue vote) { + getData().set("TimedVoteCache." + num + ".Name", vote.getName()); + getData().set("TimedVoteCache." + num + ".Service", vote.getService()); + getData().set("TimedVoteCache." + num + ".Time", vote.getTime()); + saveData(); + } + + /** + * Adds a vote shop purchase for the specified identifier. + * + * @param ident the vote shop identifier + */ + public void addVoteShopPurchase(String ident) { + setVoteShopPurchases(ident, (getVoteShopPurchases(ident) + 1)); + } + + /** + * Clears the timed vote cache. + */ + public void clearTimedVoteCache() { + getData().set("TimedVoteCache", null); + saveData(); + } + + /** + * Gets the auto cached placeholders. + * + * @return the auto cached placeholder list + */ + public List getAutoCachedPlaceholder() { + return getData().getStringList("AutoCachePlaceholders"); + } + + /** + * Gets the current bungee vote party count. + * + * @return the bungee vote party current count + */ + public int getBungeeVotePartyCurrent() { + return getData().getInt("BungeeVotePartyCurrent"); + } + + /** + * Gets the required votes for bungee vote party. + * + * @return the bungee vote party required votes + */ + public int getBungeeVotePartyRequired() { + return getData().getInt("BungeeVotePartyRequired"); + } + + /** + * Gets the data. + * + * @return the data + */ + public ConfigurationSection getData() { + ConfigurationSection data = plugin.getServerDataFile().getData().getConfigurationSection("VotingPlugin"); + if (data == null) { + plugin.getServerDataFile().getData().createSection("VotingPlugin"); + data = plugin.getServerDataFile().getData().getConfigurationSection("VotingPlugin"); + } + return data; + } + + /** + * Gets the list of disabled reminders. + * + * @return the disabled reminders + */ + public List getDisabledReminders() { + return getData().getStringList("DisabledReminders"); + } + + /** + * Gets the service sites list. + * + * @return the service sites + */ + @SuppressWarnings("unchecked") + public ArrayList getServiceSites() { + return (ArrayList) getData().getList("GottenServiceSites", new ArrayList<>()); + } + + /** + * Gets the sign data. + * + * @param sign the sign + * @return the sign data + */ + public String getSignData(String sign) { + return getData().getString("Signs." + sign + ".Data"); + } + + /** + * Gets the sign location. + * + * @param sign the sign + * @return the sign location + */ + public Location getSignLocation(String sign) { + return new Location(Bukkit.getWorld(getData().getString("Signs." + sign + ".World")), + getData().getDouble("Signs." + sign + ".X"), getData().getDouble("Signs." + sign + ".Y"), + getData().getDouble("Signs." + sign + ".Z")); + } + + /** + * Gets the sign position. + * + * @param sign the sign + * @return the sign position + */ + public int getSignPosition(String sign) { + return getData().getInt("Signs." + sign + ".Position"); + } + + /** + * Gets the signs. + * + * @return the signs + */ + public Set getSigns() { + try { + return getData().getConfigurationSection("Signs").getKeys(false); + } catch (Exception ex) { + return new HashSet<>(); + } + } + + /** + * Gets the sign location. + * + * @param sign the sign + * @return the sign location + */ + public Location getSignSkullLocation(String sign) { + if (getData().getString("Signs." + sign + ".Skull.World", "").isEmpty()) { + return null; + } + return new Location(Bukkit.getWorld(getData().getString("Signs." + sign + ".Skull.World")), + getData().getDouble("Signs." + sign + ".Skull.X"), getData().getDouble("Signs." + sign + ".Skull.Y"), + getData().getDouble("Signs." + sign + ".Skull.Z")); + } + + /** + * Gets the timed vote cache keys. + * + * @return the timed vote cache keys + */ + public Set getTimedVoteCacheKeys() { + if (getData().isConfigurationSection("TimedVoteCache")) { + return getData().getConfigurationSection("TimedVoteCache").getKeys(false); + } + return new HashSet<>(); + } + + /** + * Gets the timed vote cache section for the given number. + * + * @param num the cache entry number + * @return the timed vote cache section + */ + public ConfigurationSection getTimedVoteCacheSection(String num) { + return getData().getConfigurationSection("TimedVoteCache." + num); + } + + /** + * Gets the extra required votes for vote party. + * + * @return the vote party extra required votes + */ + public int getVotePartyExtraRequired() { + return getData().getInt("VotePartyExtraRequired", 0); + } + + /** + * Gets the number of purchases for a vote shop item. + * + * @param ident the vote shop identifier + * @return the vote shop purchases + */ + public int getVoteShopPurchases(String ident) { + return getData().getInt("VoteShopPurchases." + ident); + } + + /** + * Checks if the last vote party was on the same day. + * + * @return true if same day + */ + public boolean isLastVotePartySameDay() { + int num = getData().getInt("LastVoteParty", 0); + if (num == plugin.getTimeChecker().getTime().getDayOfYear()) { + return true; + } + return false; + } + + /** + * Checks if the last vote party was in the same week. + * + * @return true if same week + */ + public boolean isLastVotePartySameWeek() { + int num = getData().getInt("LastVotePartyWeek", -1); + if (num == plugin.getTimeChecker().getTime().get(WeekFields.of(Locale.getDefault()).weekOfYear()) + && num != -1) { + return true; + } + return false; + } + + /** + * Checks if the vote shop has been converted. + * + * @return true if converted + */ + public boolean isVoteShopConverted() { + return getData().getBoolean("VoteShopConverted"); + } + + /** + * Next sign number. + * + * @return the int + */ + public int nextSignNumber() { + Set signs = getSigns(); + + if (signs != null) { + for (int i = 0; i < 100000; i++) { + if (!signs.contains(Integer.toString(i))) { + return i; + } + } + } + return 0; + } + + /** + * Reload data. + */ + public void reloadData() { + plugin.getServerDataFile().reloadData(); + } + + /** + * Gets the Discord message ID for the top voter. + * + * @param top the top voter type + * @return the top voter message ID + */ + public long getTopVoterMessageId(TopVoter top) { + return getData().getLong("DiscordSRV.TopVoterMessageId." + top.toString(), 0); + } + + /** + * Sets the Discord message ID for the top voter. + * + * @param top the top voter type + * @param messageId the message ID + */ + public void setTopVoterMessageId(TopVoter top, long messageId) { + getData().set("DiscordSRV.TopVoterMessageId." + top.toString(), messageId); + saveData(); + } + + /** + * Removes the sign. + * + * @param sign the sign + */ + public void removeSign(String sign) { + getData().set("Signs." + sign + ".World", null); + getData().set("Signs." + sign + ".X", null); + getData().set("Signs." + sign + ".Y", null); + getData().set("Signs." + sign + ".Z", null); + getData().set("Signs." + sign + ".Data", null); + getData().set("Signs." + sign + ".Position", null); + getData().set("Signs." + sign, null); + getData().set("Signs." + sign + ".Skull.World", null); + getData().set("Signs." + sign + ".Skull.X", null); + getData().set("Signs." + sign + ".Skull.Y", null); + getData().set("Signs." + sign + ".Skull.Z", null); + saveData(); + } + + /** + * Save data. + */ + public synchronized void saveData() { + plugin.getServerDataFile().saveData(); + } + + /** + * Saves the disabled reminders list. + * + * @param disabledReminders the list of UUIDs with disabled reminders + */ + public void saveDisabledReminders(ArrayList disabledReminders) { + ArrayList uuids = new ArrayList<>(); + for (UUID uuid : disabledReminders) { + uuids.add(uuid.toString()); + } + getData().set("DisabledReminders", uuids); + saveData(); + } + + /** + * Sets the auto cached placeholders. + * + * @param placeholders the list of placeholders + */ + public void setAutoCachedPlaceholder(List placeholders) { + getData().set("AutoCachePlaceholders", placeholders); + saveData(); + } + + /** + * Sets the current bungee vote party count. + * + * @param current the current vote count + */ + public void setBungeeVotePartyCurrent(int current) { + getData().set("BungeeVotePartyCurrent", current); + saveData(); + } + + /** + * Sets the required votes for bungee vote party. + * + * @param required the required vote count + */ + public void setBungeeVotePartyRequired(int required) { + getData().set("BungeeVotePartyRequired", required); + saveData(); + } + + /** + * Sets the service sites list. + * + * @param list the service sites list + */ + public void setServiceSites(ArrayList list) { + getData().set("GottenServiceSites", list); + saveData(); + } + + /** + * Sets the vote shop converted status. + * + * @param value the converted status + */ + public void setShopConverted(boolean value) { + getData().set("VoteShopConverted", value); + saveData(); + } + + /** + * Sets sign data. + * + * @param count the sign count + * @param location the sign location + * @param skullLocation the skull location + * @param data the sign data + * @param position the sign position + */ + public void setSign(String count, Location location, Location skullLocation, String data, int position) { + + getData().set("Signs." + count + ".World", location.getWorld().getName()); + getData().set("Signs." + count + ".X", (int) location.getX()); + getData().set("Signs." + count + ".Y", (int) location.getY()); + getData().set("Signs." + count + ".Z", (int) location.getZ()); + getData().set("Signs." + count + ".Data", data); + getData().set("Signs." + count + ".Position", position); + if (skullLocation != null) { + getData().set("Signs." + count + ".Skull.World", skullLocation.getWorld().getName()); + getData().set("Signs." + count + ".Skull.X", (int) skullLocation.getX()); + getData().set("Signs." + count + ".Skull.Y", (int) skullLocation.getY()); + getData().set("Signs." + count + ".Skull.Z", (int) skullLocation.getZ()); + } + saveData(); + } + + /** + * Sets the skull location for a sign. + * + * @param count the sign count + * @param skullLocation the skull location + */ + public void setSkullLocation(String count, Location skullLocation) { + if (skullLocation != null) { + getData().set("Signs." + count + ".Skull.World", skullLocation.getWorld().getName()); + getData().set("Signs." + count + ".Skull.X", (int) skullLocation.getX()); + getData().set("Signs." + count + ".Skull.Y", (int) skullLocation.getY()); + getData().set("Signs." + count + ".Skull.Z", (int) skullLocation.getZ()); + } + } + + /** + * Sets the version. + */ + public void setVersion() { + getData().set("Version", Bukkit.getVersion()); + saveData(); + } + + /** + * Sets the extra required votes for vote party. + * + * @param value the extra required votes + */ + public void setVotePartyExtraRequired(int value) { + getData().set("VotePartyExtraRequired", value); + saveData(); + } + + /** + * Sets the number of purchases for a vote shop item. + * + * @param ident the vote shop identifier + * @param amount the purchase amount + */ + public void setVoteShopPurchases(String ident, int amount) { + getData().set("VoteShopPurchases." + ident, amount); + saveData(); + } + + /** + * Updates the last vote party timestamp to today. + */ + public void updateLastVoteParty() { + getData().set("LastVoteParty", plugin.getTimeChecker().getTime().getDayOfYear()); + saveData(); + } + + /** + * Updates the last vote party week timestamp to this week. + */ + public void updateLastVotePartyWeek() { + getData().set("LastVotePartyWeek", + plugin.getTimeChecker().getTime().get(WeekFields.of(Locale.getDefault()).weekOfYear())); + saveData(); + } + + /** + * Updates placeholders to lowercase format. + */ + public void updatePlaceholders() { + boolean data = getData().getBoolean("AutoCacheUpdated", false); + if (!data) { + List placeholders = getAutoCachedPlaceholder(); + for (int i = 0; i < placeholders.size(); i++) { + placeholders.set(i, placeholders.get(i).toLowerCase()); + } + setAutoCachedPlaceholder(placeholders); + getData().set("AutoCacheUpdated", true); + saveData(); + } + } + + /** + * Update values. + */ + public void updateValues() { + setVersion(); + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerPostVoteEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerPostVoteEvent.java index 288db71051..4902564ead 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerPostVoteEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerPostVoteEvent.java @@ -1,112 +1,114 @@ -package com.bencodez.votingplugin.events; - -import java.util.UUID; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -import lombok.Getter; -import lombok.Setter; -public class PlayerPostVoteEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean bungee = false; - - @Getter - @Setter - private VoteTotalsSnapshot bungeeTextTotals; - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private boolean forceBungee = false; - - @Getter - @Setter - private VotingPluginUser user; - - @Getter - @Setter - private boolean realVote = true; - - @Getter - @Setter - private VoteSite voteSite; - - @Getter - @Setter - private long voteTime = 0; - - @Getter - @Setter - private boolean cached; - - @Getter - @Setter - private String service; - - @Getter - @Setter - private UUID uuid; - @Getter - @Setter - private String playerName; - - @Getter - @Setter - private UUID voteUUID; - - /** - * Constructs a new PlayerPostVoteEvent. - * - * @param voteSite the vote site - * @param user the voting plugin user - * @param realVote whether this is a real vote - * @param forceBungee whether to force Bungee processing - * @param voteTime the vote timestamp - * @param cached whether the vote was cached - * @param service the service name - * @param uuid the player UUID - * @param playerName the player name - * @param voteUUID the vote UUID - */ - public PlayerPostVoteEvent(VoteSite voteSite, VotingPluginUser user, boolean realVote, boolean forceBungee, - long voteTime, boolean cached, String service, UUID uuid, String playerName, UUID voteUUID) { - super(true); - this.user = user; - this.voteSite = voteSite; - this.realVote = realVote; - this.forceBungee = forceBungee; - this.voteTime = voteTime; - this.cached = cached; - this.service = service; - this.uuid = uuid; - this.playerName = playerName; - this.voteUUID = voteUUID; - } - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import java.util.UUID; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +import lombok.Getter; +import lombok.Setter; + +public class PlayerPostVoteEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean bungee = false; + + @Getter + @Setter + private VoteTotalsSnapshot bungeeTextTotals; + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private boolean forceBungee = false; + + @Getter + @Setter + private VotingPluginUser user; + + @Getter + @Setter + private boolean realVote = true; + + @Getter + @Setter + private VoteSite voteSite; + + @Getter + @Setter + private long voteTime = 0; + + @Getter + @Setter + private boolean cached; + + @Getter + @Setter + private String service; + + @Getter + @Setter + private UUID uuid; + @Getter + @Setter + private String playerName; + + @Getter + @Setter + private UUID voteUUID; + + /** + * Constructs a new PlayerPostVoteEvent. + * + * @param voteSite the vote site + * @param user the voting plugin user + * @param realVote whether this is a real vote + * @param forceBungee whether to force Bungee processing + * @param voteTime the vote timestamp + * @param cached whether the vote was cached + * @param service the service name + * @param uuid the player UUID + * @param playerName the player name + * @param voteUUID the vote UUID + */ + public PlayerPostVoteEvent(VoteSite voteSite, VotingPluginUser user, boolean realVote, boolean forceBungee, + long voteTime, boolean cached, String service, UUID uuid, String playerName, UUID voteUUID) { + super(true); + this.user = user; + this.voteSite = voteSite; + this.realVote = realVote; + this.forceBungee = forceBungee; + this.voteTime = voteTime; + this.cached = cached; + this.service = service; + this.uuid = uuid; + this.playerName = playerName; + this.voteUUID = voteUUID; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerReceivePointsEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerReceivePointsEvent.java index 96443aef81..65d6bde5fb 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerReceivePointsEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerReceivePointsEvent.java @@ -1,56 +1,58 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.user.VotingPluginUser; - -import lombok.Getter; -import lombok.Setter; -public class PlayerReceivePointsEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private VotingPluginUser player; - - @Getter - @Setter - private int points; - - @Getter - @Setter - private String serviceSite = ""; - - /** - * Constructs a new PlayerReceivePointsEvent. - * - * @param user the voting plugin user - * @param points the points received - */ - public PlayerReceivePointsEvent(VotingPluginUser user, int points) { - super(true); - this.player = user; - this.points = points; - } - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.user.VotingPluginUser; + +import lombok.Getter; +import lombok.Setter; + +public class PlayerReceivePointsEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private VotingPluginUser player; + + @Getter + @Setter + private int points; + + @Getter + @Setter + private String serviceSite = ""; + + /** + * Constructs a new PlayerReceivePointsEvent. + * + * @param user the voting plugin user + * @param points the points received + */ + public PlayerReceivePointsEvent(VotingPluginUser user, int points) { + super(true); + this.player = user; + this.points = points; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerSpecialRewardEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerSpecialRewardEvent.java index b2690f3076..66a8700c13 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerSpecialRewardEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerSpecialRewardEvent.java @@ -1,60 +1,62 @@ -package com.bencodez.votingplugin.events; - -import java.util.UUID; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.user.VotingPluginUser; - -import lombok.Getter; -import lombok.Setter; -public class PlayerSpecialRewardEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private SpecialRewardType type; - - @Getter - @Setter - private VotingPluginUser user; - - @Getter - @Setter - private UUID voteUUID; - - /** - * Constructs a new PlayerSpecialRewardEvent. - * - * @param user the voting plugin user - * @param type the special reward type - * @param voteUUID the vote UUID - */ - public PlayerSpecialRewardEvent(VotingPluginUser user, SpecialRewardType type, UUID voteUUID) { - super(true); - this.type = type; - this.user = user; - this.voteUUID = voteUUID; - } - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import java.util.UUID; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.user.VotingPluginUser; + +import lombok.Getter; +import lombok.Setter; + +public class PlayerSpecialRewardEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private SpecialRewardType type; + + @Getter + @Setter + private VotingPluginUser user; + + @Getter + @Setter + private UUID voteUUID; + + /** + * Constructs a new PlayerSpecialRewardEvent. + * + * @param user the voting plugin user + * @param type the special reward type + * @param voteUUID the vote UUID + */ + public PlayerSpecialRewardEvent(VotingPluginUser user, SpecialRewardType type, UUID voteUUID) { + super(true); + this.type = type; + this.user = user; + this.voteUUID = voteUUID; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteCoolDownEndEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteCoolDownEndEvent.java index 1d7b2505f2..481fbb8bdd 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteCoolDownEndEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteCoolDownEndEvent.java @@ -1,46 +1,48 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.user.VotingPluginUser; - -import lombok.Getter; -import lombok.Setter; -public class PlayerVoteCoolDownEndEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private VotingPluginUser player; - - /** - * Constructs a new PlayerVoteCoolDownEndEvent. - * - * @param user the voting plugin user - */ - public PlayerVoteCoolDownEndEvent(VotingPluginUser user) { - super(true); - player = user; - } - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.user.VotingPluginUser; + +import lombok.Getter; +import lombok.Setter; + +public class PlayerVoteCoolDownEndEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private VotingPluginUser player; + + /** + * Constructs a new PlayerVoteCoolDownEndEvent. + * + * @param user the voting plugin user + */ + public PlayerVoteCoolDownEndEvent(VotingPluginUser user) { + super(true); + player = user; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteEvent.java index 9606a471c9..d75f7bd1a6 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteEvent.java @@ -1,102 +1,104 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -import lombok.Getter; -import lombok.Setter; -public class PlayerVoteEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean addTotals = true; - - @Getter - @Setter - private boolean bungee = false; - - @Getter - @Setter - private VoteTotalsSnapshot bungeeTextTotals; - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private boolean forceBungee = false; - - @Getter - @Setter - private String player; - - @Getter - @Setter - private boolean realVote = true; - - @Getter - @Setter - private String serviceSite = ""; - - @Getter - @Setter - private long time; - - @Getter - @Setter - private VoteSite voteSite; - - @Getter - @Setter - private VotingPluginUser votingPluginUser; - - @Getter - @Setter - private boolean wasOnline; - - @Getter - @Setter - private boolean broadcast = true; - - @Getter - @Setter - private int voteNumber = 1; - - /** - * Constructs a new PlayerVoteEvent. - * - * @param voteSite the vote site - * @param voteUsername the username of the voter - * @param serviceSite the service site name - * @param realVote whether this is a real vote - */ - public PlayerVoteEvent(VoteSite voteSite, String voteUsername, String serviceSite, boolean realVote) { - super(true); - this.player = voteUsername; - this.voteSite = voteSite; - this.realVote = realVote; - this.serviceSite = serviceSite; - } - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +import lombok.Getter; +import lombok.Setter; + +public class PlayerVoteEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean addTotals = true; + + @Getter + @Setter + private boolean bungee = false; + + @Getter + @Setter + private VoteTotalsSnapshot bungeeTextTotals; + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private boolean forceBungee = false; + + @Getter + @Setter + private String player; + + @Getter + @Setter + private boolean realVote = true; + + @Getter + @Setter + private String serviceSite = ""; + + @Getter + @Setter + private long time; + + @Getter + @Setter + private VoteSite voteSite; + + @Getter + @Setter + private VotingPluginUser votingPluginUser; + + @Getter + @Setter + private boolean wasOnline; + + @Getter + @Setter + private boolean broadcast = true; + + @Getter + @Setter + private int voteNumber = 1; + + /** + * Constructs a new PlayerVoteEvent. + * + * @param voteSite the vote site + * @param voteUsername the username of the voter + * @param serviceSite the service site name + * @param realVote whether this is a real vote + */ + public PlayerVoteEvent(VoteSite voteSite, String voteUsername, String serviceSite, boolean realVote) { + super(true); + this.player = voteUsername; + this.voteSite = voteSite; + this.realVote = realVote; + this.serviceSite = serviceSite; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteSiteCoolDownEndEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteSiteCoolDownEndEvent.java index ac6f7644ec..3884bdf684 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteSiteCoolDownEndEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/PlayerVoteSiteCoolDownEndEvent.java @@ -1,53 +1,55 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -import lombok.Getter; -import lombok.Setter; -public class PlayerVoteSiteCoolDownEndEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - @Getter - @Setter - private VotingPluginUser player; - - @Getter - @Setter - private VoteSite site; - - /** - * Constructs a new PlayerVoteSiteCoolDownEndEvent. - * - * @param user the voting plugin user - * @param site the vote site - */ - public PlayerVoteSiteCoolDownEndEvent(VotingPluginUser user, VoteSite site) { - super(true); - player = user; - this.site = site; - } - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +import lombok.Getter; +import lombok.Setter; + +public class PlayerVoteSiteCoolDownEndEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + @Getter + @Setter + private VotingPluginUser player; + + @Getter + @Setter + private VoteSite site; + + /** + * Constructs a new PlayerVoteSiteCoolDownEndEvent. + * + * @param user the voting plugin user + * @param site the vote site + */ + public PlayerVoteSiteCoolDownEndEvent(VotingPluginUser user, VoteSite site) { + super(true); + player = user; + this.site = site; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/VotePartyEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/VotePartyEvent.java index 5b79b589c0..38514a64e2 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/VotePartyEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/events/VotePartyEvent.java @@ -1,37 +1,39 @@ -package com.bencodez.votingplugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -import lombok.Getter; -import lombok.Setter; -public class VotePartyEvent extends Event { - - /** The Constant handlers. */ - private static final HandlerList handlers = new HandlerList(); - - /** - * Gets the handler list. - * - * @return the handler list - */ - public static HandlerList getHandlerList() { - return handlers; - } - - @Getter - @Setter - private boolean cancelled; - - /** - * Constructs a new VotePartyEvent. - */ - public VotePartyEvent() { - super(true); - } - @Override - public HandlerList getHandlers() { - return handlers; - } - -} +package com.bencodez.votingplugin.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import lombok.Getter; +import lombok.Setter; + +public class VotePartyEvent extends Event { + + /** The Constant handlers. */ + private static final HandlerList handlers = new HandlerList(); + + /** + * Gets the handler list. + * + * @return the handler list + */ + public static HandlerList getHandlerList() { + return handlers; + } + + @Getter + @Setter + private boolean cancelled; + + /** + * Constructs a new VotePartyEvent. + */ + public VotePartyEvent() { + super(true); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/BlockBreak.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/BlockBreak.java index f80471e6eb..85e9481bd0 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/BlockBreak.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/BlockBreak.java @@ -1,52 +1,53 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.Location; -import org.bukkit.block.Sign; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; - -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.signs.SignHandler; -public class BlockBreak implements Listener { - - /** The plugin. */ - private VotingPluginMain plugin; - - /** - * Instantiates a new block break. - * - * @param plugin the plugin - */ - public BlockBreak(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On block break. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onBlockBreak(BlockBreakEvent event) { - if (event.getBlock().getState() instanceof Sign) { - Sign s = (Sign) event.getBlock().getState(); - final Location loc = s.getLocation(); - plugin.getBukkitScheduler().runTaskAsynchronously(plugin, new Runnable() { - - @Override - public void run() { - for (SignHandler sign : plugin.getSigns().getSigns()) { - if (sign.getLocation().equals(loc)) { - sign.removeSign(); - sign.setValid(false); - } - } - } - }); - } - - } - -} +package com.bencodez.votingplugin.listeners; + +import org.bukkit.Location; +import org.bukkit.block.Sign; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; + +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.signs.SignHandler; + +public class BlockBreak implements Listener { + + /** The plugin. */ + private VotingPluginMain plugin; + + /** + * Instantiates a new block break. + * + * @param plugin the plugin + */ + public BlockBreak(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On block break. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent event) { + if (event.getBlock().getState() instanceof Sign) { + Sign s = (Sign) event.getBlock().getState(); + final Location loc = s.getLocation(); + plugin.getBukkitScheduler().runTaskAsynchronously(plugin, new Runnable() { + + @Override + public void run() { + for (SignHandler sign : plugin.getSigns().getSigns()) { + if (sign.getLocation().equals(loc)) { + sign.removeSign(); + sign.setValid(false); + } + } + } + }); + } + + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerInteract.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerInteract.java index 0aa56835b3..158bb19a7a 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerInteract.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerInteract.java @@ -1,84 +1,85 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.block.Sign; -import org.bukkit.block.Skull; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.PlayerInteractEvent; - -import com.bencodez.advancedcore.api.misc.PlayerManager; -import com.bencodez.simpleapi.player.PlayerUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.signs.SignHandler; -public class PlayerInteract implements Listener { - - /** The plugin. */ - private VotingPluginMain plugin; - - /** - * Instantiates a new player interact. - * - * @param plugin the plugin - */ - public PlayerInteract(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On player interact. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) - public void onPlayerInteract(PlayerInteractEvent event) { - if (plugin.getConfigFile().isDisableInteractEvent()) { - return; - } - if (plugin.getSigns().getSigns().size() > 0) { - Player player = event.getPlayer(); - if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { - // plugin.debug("Checking for sign click"); - if (event.getClickedBlock().getState() instanceof Sign) { - // plugin.debug(player.getName() + " right clicked a sign"); - for (SignHandler sign : plugin.getSigns().getSigns()) { - if (sign.isLocationSame(event.getClickedBlock().getLocation())) { - // plugin.debug(player.getName() + - // " right clicked a top voter sign, sending message"); - plugin.getVotingPluginUserManager().getVotingPluginUser(player) - .sendMessage(sign.getRightClickMessage()); - - if (!sign.isSkullSet()) { - if (PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), - "VotingPlugin.Sign.Create") - || PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), - "VotingPlugin.Admin")) { - player.sendMessage("Skull not set, click to set skull"); - PlayerUtils.setPlayerMeta(plugin, player, "skullset", sign.getSign()); - } - } - } - } - - } else if (event.getClickedBlock().getState() instanceof Skull) { - Object ob = PlayerUtils.getPlayerMeta(plugin, player, "skullset"); - if (ob != null) { - String sign1 = (String) ob; - for (SignHandler sign : plugin.getSigns().getSigns()) { - if (sign.getSign().equals(sign1)) { - sign.setSkullLocation(event.getClickedBlock().getLocation()); - sign.storeSign(); - sign.checkSkulls(); - player.sendMessage("Skull set"); - } - } - PlayerUtils.setPlayerMeta(plugin, player, "skullset", null); - } - } - } - - } - } -} +package com.bencodez.votingplugin.listeners; + +import org.bukkit.block.Sign; +import org.bukkit.block.Skull; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +import com.bencodez.advancedcore.api.misc.PlayerManager; +import com.bencodez.simpleapi.player.PlayerUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.signs.SignHandler; + +public class PlayerInteract implements Listener { + + /** The plugin. */ + private VotingPluginMain plugin; + + /** + * Instantiates a new player interact. + * + * @param plugin the plugin + */ + public PlayerInteract(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On player interact. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onPlayerInteract(PlayerInteractEvent event) { + if (plugin.getConfigFile().isDisableInteractEvent()) { + return; + } + if (plugin.getSigns().getSigns().size() > 0) { + Player player = event.getPlayer(); + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + // plugin.debug("Checking for sign click"); + if (event.getClickedBlock().getState() instanceof Sign) { + // plugin.debug(player.getName() + " right clicked a sign"); + for (SignHandler sign : plugin.getSigns().getSigns()) { + if (sign.isLocationSame(event.getClickedBlock().getLocation())) { + // plugin.debug(player.getName() + + // " right clicked a top voter sign, sending message"); + plugin.getVotingPluginUserManager().getVotingPluginUser(player) + .sendMessage(sign.getRightClickMessage()); + + if (!sign.isSkullSet()) { + if (PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), + "VotingPlugin.Sign.Create") + || PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), + "VotingPlugin.Admin")) { + player.sendMessage("Skull not set, click to set skull"); + PlayerUtils.setPlayerMeta(plugin, player, "skullset", sign.getSign()); + } + } + } + } + + } else if (event.getClickedBlock().getState() instanceof Skull) { + Object ob = PlayerUtils.getPlayerMeta(plugin, player, "skullset"); + if (ob != null) { + String sign1 = (String) ob; + for (SignHandler sign : plugin.getSigns().getSigns()) { + if (sign.getSign().equals(sign1)) { + sign.setSkullLocation(event.getClickedBlock().getLocation()); + sign.storeSign(); + sign.checkSkulls(); + player.sendMessage("Skull set"); + } + } + PlayerUtils.setPlayerMeta(plugin, player, "skullset", null); + } + } + } + + } + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerJoinEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerJoinEvent.java index d4455e8727..8a2a216c98 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerJoinEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerJoinEvent.java @@ -1,125 +1,126 @@ -package com.bencodez.votingplugin.listeners; - -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.PlayerQuitEvent; - -import com.bencodez.advancedcore.api.player.UuidLookup; -import com.bencodez.advancedcore.api.user.UserDataFetchMode; -import com.bencodez.advancedcore.listeners.AdvancedCoreLoginEvent; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.user.VotingPluginUser; -public class PlayerJoinEvent implements Listener { - - /** The plugin. */ - private final VotingPluginMain plugin; - - /** - * Instantiates a new player join event. - * - * @param plugin the plugin - */ - public PlayerJoinEvent(VotingPluginMain plugin) { - this.plugin = plugin; - } - - private static boolean isBlank(String s) { - return s == null || s.trim().isEmpty() || "null".equalsIgnoreCase(s.trim()); - } - - /** - * On AdvancedCore login event (post-auth / delayed login). - * - * @param event the event - */ - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerLogin(AdvancedCoreLoginEvent event) { - if (event == null || !plugin.isMySQLOkay() || event.isCancelled() || event.getUser() == null) { - return; - } - - // UUID is authoritative here (String) - String uuid = event.getUuid(); - if (isBlank(uuid)) { - return; - } - - // "Has data" should come from AdvancedCore event (storage presence) - boolean hasData = event.isUserInStorage(); - - // Resolve VotingPluginUser by the storage UUID string (offline-mode - // name-derived UUID) - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid); - if (user == null) { - return; - } - - Player player = event.getPlayer(); - - if (player != null && player.isOp() && plugin.isYmlError()) { - user.sendMessage("&cVotingPlugin: Detected yml error, please check console for details"); - } - - if (hasData) { - // give offline vote (if they voted offline) - user.offVote(); - } else { - plugin.debug("No data detected for " + user.getUUID() + "/" + user.getPlayerName()); - } - - user.loginRewards(); - - plugin.getPlaceholders().onUpdate(user, true); - - if (plugin.getBungeeSettings().isUseBungeecoord()) { - plugin.getBackendProxyHandler().playerOnline(user.getPlayerName(), user.getUUID()); - } - } - - /** - * Handles player quit events. - * - * @param event the player quit event - */ - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerQuit(PlayerQuitEvent event) { - if (plugin == null || !plugin.isEnabled() || event == null) { - return; - } - - final Player player = event.getPlayer(); - if (player == null) { - return; - } - - if (plugin.getBungeeSettings().isUseBungeecoord()) { - plugin.getBackendProxyHandler().playerOffline(player.getName()); - } - - plugin.getLoginTimer().execute(new Runnable() { - - @Override - public void run() { - VotingPluginMain.plugin.getAdvancedTab().remove(player.getUniqueId()); - - // Use AdvancedCore UUIDLookup to derive the correct UUID (online/offline aware) - String uuid = UuidLookup.getInstance().getUUID(player.getName()); - if (isBlank(uuid)) { - // Fallback to online UUID if lookup fails - uuid = player.getUniqueId().toString(); - } - - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid); - if (user == null) { - return; - } - - user.userDataFetechMode(UserDataFetchMode.NO_CACHE); - user.logoutRewards(); - plugin.getPlaceholders().onLogout(user); - } - }); - } -} +package com.bencodez.votingplugin.listeners; + +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.PlayerQuitEvent; + +import com.bencodez.advancedcore.api.player.UuidLookup; +import com.bencodez.advancedcore.api.user.UserDataFetchMode; +import com.bencodez.advancedcore.listeners.AdvancedCoreLoginEvent; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.user.VotingPluginUser; + +public class PlayerJoinEvent implements Listener { + + /** The plugin. */ + private final VotingPluginMain plugin; + + /** + * Instantiates a new player join event. + * + * @param plugin the plugin + */ + public PlayerJoinEvent(VotingPluginMain plugin) { + this.plugin = plugin; + } + + private static boolean isBlank(String s) { + return s == null || s.trim().isEmpty() || "null".equalsIgnoreCase(s.trim()); + } + + /** + * On AdvancedCore login event (post-auth / delayed login). + * + * @param event the event + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerLogin(AdvancedCoreLoginEvent event) { + if (event == null || !plugin.isMySQLOkay() || event.isCancelled() || event.getUser() == null) { + return; + } + + // UUID is authoritative here (String) + String uuid = event.getUuid(); + if (isBlank(uuid)) { + return; + } + + // "Has data" should come from AdvancedCore event (storage presence) + boolean hasData = event.isUserInStorage(); + + // Resolve VotingPluginUser by the storage UUID string (offline-mode + // name-derived UUID) + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid); + if (user == null) { + return; + } + + Player player = event.getPlayer(); + + if (player != null && player.isOp() && plugin.isYmlError()) { + user.sendMessage("&cVotingPlugin: Detected yml error, please check console for details"); + } + + if (hasData) { + // give offline vote (if they voted offline) + user.offVote(); + } else { + plugin.debug("No data detected for " + user.getUUID() + "/" + user.getPlayerName()); + } + + user.loginRewards(); + + plugin.getPlaceholders().onUpdate(user, true); + + if (plugin.getBungeeSettings().isUseBungeecoord()) { + plugin.getBackendProxyHandler().playerOnline(user.getPlayerName(), user.getUUID()); + } + } + + /** + * Handles player quit events. + * + * @param event the player quit event + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerQuit(PlayerQuitEvent event) { + if (plugin == null || !plugin.isEnabled() || event == null) { + return; + } + + final Player player = event.getPlayer(); + if (player == null) { + return; + } + + if (plugin.getBungeeSettings().isUseBungeecoord()) { + plugin.getBackendProxyHandler().playerOffline(player.getName()); + } + + plugin.getLoginTimer().execute(new Runnable() { + + @Override + public void run() { + VotingPluginMain.plugin.getAdvancedTab().remove(player.getUniqueId()); + + // Use AdvancedCore UUIDLookup to derive the correct UUID (online/offline aware) + String uuid = UuidLookup.getInstance().getUUID(player.getName()); + if (isBlank(uuid)) { + // Fallback to online UUID if lookup fails + uuid = player.getUniqueId().toString(); + } + + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid); + if (user == null) { + return; + } + + user.userDataFetechMode(UserDataFetchMode.NO_CACHE); + user.logoutRewards(); + plugin.getPlaceholders().onLogout(user); + } + }); + } +} 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 77f59dff0f..d86873bff2 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerVoteListener.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/PlayerVoteListener.java @@ -1,75 +1,76 @@ -package com.bencodez.votingplugin.listeners; - -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.HashMap; -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.bedrock.BedrockNameResolver; -import com.bencodez.advancedcore.api.user.validation.UserValidationResult; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.events.PlayerPostVoteEvent; -import com.bencodez.votingplugin.events.PlayerVoteEvent; -import com.bencodez.votingplugin.topvoter.TopVoter; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; -public class PlayerVoteListener implements Listener { - - private VotingPluginMain plugin; - - /** - * Instantiates a new votifer event. - * - * @param plugin the plugin - */ - public PlayerVoteListener(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On votifer event. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onplayerVote(PlayerVoteEvent event) { - if (!plugin.isEnabled()) { - plugin.getLogger().warning("Plugin disabled, ignoring vote"); - return; - } - String playerName = event.getPlayer(); - plugin.debug("Processing PlayerVoteEvent: " + playerName + "/" + event.getServiceSite()); - - // check for name casing - final String properName = plugin.getUserManager().getProperName(playerName); - - // Validate BEFORE full bedrock/db-backed resolution - boolean allowUnJoinedCheckServer = plugin.getConfigFile().isAllowUnJoinedCheckServer(); - UserValidationResult validationResult = plugin.getUserManager().getValidationService().validate(properName, - allowUnJoinedCheckServer); - - plugin.extraDebug("Vote validation result for " + properName + ": valid=" + validationResult.isValid() - + ", source=" + validationResult.getSource() + ", reason=" + validationResult.getReason() - + ", normalizedName=" + validationResult.getNormalizedName() + ", bedrock=" - + validationResult.isBedrock()); - - if (!validationResult.isValid() && !plugin.getConfigFile().isAllowUnjoined()) { - plugin.getLogger().warning("Player " + properName + " has not joined before, disregarding vote. " - + "Reason: " + validationResult.getReason() + ". Set AllowUnjoined to true to accept."); - if (event.isBungee() && plugin.getBungeeSettings().isRemoveInvalidUsers()) { - plugin.getVotingPluginUserManager().getVotingPluginUser(properName).remove(); - } - return; - } - +package com.bencodez.votingplugin.listeners; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.HashMap; +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.bedrock.BedrockNameResolver; +import com.bencodez.advancedcore.api.user.validation.UserValidationResult; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.events.PlayerPostVoteEvent; +import com.bencodez.votingplugin.events.PlayerVoteEvent; +import com.bencodez.votingplugin.topvoter.TopVoter; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +public class PlayerVoteListener implements Listener { + + private VotingPluginMain plugin; + + /** + * Instantiates a new votifer event. + * + * @param plugin the plugin + */ + public PlayerVoteListener(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On votifer event. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onplayerVote(PlayerVoteEvent event) { + if (!plugin.isEnabled()) { + plugin.getLogger().warning("Plugin disabled, ignoring vote"); + return; + } + String playerName = event.getPlayer(); + plugin.debug("Processing PlayerVoteEvent: " + playerName + "/" + event.getServiceSite()); + + // check for name casing + final String properName = plugin.getUserManager().getProperName(playerName); + + // Validate BEFORE full bedrock/db-backed resolution + boolean allowUnJoinedCheckServer = plugin.getConfigFile().isAllowUnJoinedCheckServer(); + UserValidationResult validationResult = plugin.getUserManager().getValidationService().validate(properName, + allowUnJoinedCheckServer); + + plugin.extraDebug("Vote validation result for " + properName + ": valid=" + validationResult.isValid() + + ", source=" + validationResult.getSource() + ", reason=" + validationResult.getReason() + + ", normalizedName=" + validationResult.getNormalizedName() + ", bedrock=" + + validationResult.isBedrock()); + + if (!validationResult.isValid() && !plugin.getConfigFile().isAllowUnjoined()) { + plugin.getLogger().warning("Player " + properName + " has not joined before, disregarding vote. " + + "Reason: " + validationResult.getReason() + ". Set AllowUnjoined to true to accept."); + if (event.isBungee() && plugin.getBungeeSettings().isRemoveInvalidUsers()) { + plugin.getVotingPluginUserManager().getVotingPluginUser(properName).remove(); + } + return; + } + String creditedName; String resolutionRationale; if (validationResult.isValid()) { @@ -92,219 +93,219 @@ public void onplayerVote(PlayerVoteEvent event) { } plugin.debug("Vote name resolved: " + properName + " -> " + creditedName + " (" + resolutionRationale + ")"); - - // If we get here, use the resolved/possibly-prefixed name going forward - playerName = creditedName; - - if (playerName.isEmpty()) { - plugin.getLogger().warning("Empty player name from vote, ignoring"); - return; - } - - if (event.isBungee()) { - plugin.debug("BungeePlayerVote forcebungee: " + event.isForceBungee() + ", bungeetotals: " - + event.getBungeeTextTotals()); - - if (plugin.getBungeeSettings().isTriggerVotifierEvent()) { - try { - new ProxyVotifierEvent().send(plugin, event); - } catch (NoClassDefFoundError ex) { - plugin.getLogger().severe( - "Failed to trigger Votifier event for proxy vote. Either install Votifier or disable triggering the Votifier event"); - plugin.getLogger().severe("Error: " + ex.getMessage()); - plugin.debug(ex); - } - } - } - - VoteSite voteSite = event.getVoteSite(); - - if (voteSite == null) { - voteSite = plugin.getVoteSiteManager() - .getVoteSite(plugin.getVoteSiteManager().getVoteSiteName(true, event.getServiceSite()), true); - } - - // check valid service sites - if (voteSite == null) { - if (!plugin.getConfigFile().isDisableNoServiceSiteMessage()) { - plugin.getLogger().warning("No voting site with the service site: '" + event.getServiceSite() + "'"); - - ArrayList services = new ArrayList<>(); - for (VoteSite site : plugin.getVoteSiteManager().getVoteSites()) { - services.add(site.getServiceSite()); - } - plugin.getLogger().warning("Currently set service sites: " + ArrayUtils.makeStringList(services)); - } - return; - } - - if (!voteSite.isEnabled()) { - plugin.debug("Votesite: " + voteSite.getKey() + " is not enabled"); - return; - } - - VotingPluginUser user = null; - if (event.getVotingPluginUser() != null) { - user = event.getVotingPluginUser(); - } else { - Player p = Bukkit.getPlayerExact(playerName); - if (p != null) { - // player online - user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); - } else { - // attempt to get exact name from cache matching casing - user = plugin.getVotingPluginUserManager().getVotingPluginUser(playerName); - } - } - - boolean queuedProxyVoteAlreadyRecorded = ProxyVoteDelayCheck.isQueuedVoteAlreadyRecorded(event.isBungee(), - event.getTime(), user.getTime(voteSite)); - if (voteSite.isWaitUntilVoteDelay() && !queuedProxyVoteAlreadyRecorded && !user.canVoteSite(voteSite)) { - if (!event.isRealVote()) { - plugin.getLogger().info(user.getPlayerName() + " did a not real vote, bypassing WaitUntilVoteDelay"); - } 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() - .info(user.getPlayerName() + " has bypass permission for WaitUntilVoteDelay, bypassing"); - } - } - if (queuedProxyVoteAlreadyRecorded) { - plugin.debug("Allowing queued proxy vote for " + user.getPlayerName() + " on " + voteSite.getKey() - + "; proxy vote time already matches LastVotes: " + event.getTime()); - } - - UUID voteUUID = UUID.randomUUID(); - if (event.isBungee() && event.getBungeeTextTotals() != null) { - voteUUID = event.getBungeeTextTotals().getVoteUUID(); - if (voteUUID == null) { - voteUUID = UUID.randomUUID(); - } - } - - final String uuid = user.getUUID(); - - // reupdate cache - user.cache(); - - user.updateName(true); - - // vote party - plugin.getVoteParty().vote(user, event.isRealVote(), event.isForceBungee()); - - if (event.isBroadcast()) { - if (plugin.getBroadcastHandler() != null) { - boolean online = user.isOnline(); - if (event.isBungee()) { - online = event.isWasOnline(); - } - if (!user.isVanished()) { - plugin.getBroadcastHandler().broadcastVote(user.getJavaUUID(), playerName, - voteSite.getDisplayName(), online); - } else { - plugin.debug("Not broadcasting vote for vanished user: " + user.getPlayerName()); - } - } - } - - long voteTime = 0; - // update last vote time - if (event.getTime() != 0) { - user.setTime(voteSite, event.getTime()); - voteTime = event.getTime(); - } else { - user.setTime(voteSite); - voteTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); - } - - boolean cached = false; - // check if player has voted on all sites in one day - if (((user.isOnline() || voteSite.isGiveOffline()) && plugin.getOptions().isProcessRewards()) - || event.isBungee()) { - boolean online = true; - if (event.isBungee()) { - online = event.isWasOnline(); - } - user.playerVote(voteSite, online, event.isForceBungee()); - if (event.getVoteNumber() == 1) { - user.sendVoteEffects(online); - } - if (plugin.getConfigFile().isCloseInventoryOnVote()) { - user.closeInv(); - } - } else { - if (!plugin.getConfigFile().isOfflineVotesLimitEnabled() - || user.getNumberOfOfflineVotes(voteSite) <= plugin.getConfigFile().getOfflineVotesLimitAmount()) { - user.addOfflineVote(voteSite.getKey()); - cached = true; - plugin.debug( - "Offline vote set for " + playerName + " (" + user.getUUID() + ") on " + voteSite.getKey()); - } else { - plugin.debug("Not setting offline vote, offline vote limit reached"); - } - } - - // add to total votes - if ((plugin.getConfigFile().isCountFakeVotes() || event.isRealVote()) && event.isAddTotals()) { - if (plugin.getConfigFile().isAddTotals()) { - if (plugin.getConfigFile().isAddTotalsOffline() || user.isOnline()) { - user.addTotal(); - user.addTotalDaily(); - user.addTotalWeekly(); - } - } - user.addPoints(); - } - user.checkDayVoteStreak(event.isForceBungee()); - - if (plugin.getConfigFile().isLimitMonthlyVotes()) { - int value = 0; - if (event.isBungee()) { - value = event.getBungeeTextTotals().getMonthTotal(); - } else { - value = user.getTotal(TopVoter.Monthly); - } - LocalDateTime cTime = plugin.getTimeChecker().getTime(); - int days = cTime.getDayOfMonth(); - plugin.extraDebug("Current day of month: " + days + " Current total: " + value); - if (value >= days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()) { - plugin.debug("Detected higher month total, changing. Current Total: " + value + " Days: " + days - + " New Total: " + days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()); - user.setTotal(TopVoter.Monthly, days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()); - } - } - - plugin.getVoteMilestonesManager().handleVote(user, event.getBungeeTextTotals(), event.isForceBungee(), voteUUID, - new HashMap()); - - plugin.getCoolDownCheck().vote(user, voteSite); - - plugin.getVoteStreakHandler().processVote(user, voteTime, voteUUID); - - PlayerPostVoteEvent postVoteEvent = new PlayerPostVoteEvent(voteSite, user, event.isRealVote(), - event.isForceBungee(), voteTime, cached, voteSite.getServiceSite(), user.getJavaUUID(), playerName, - voteUUID); - plugin.getServer().getPluginManager().callEvent(postVoteEvent); - - if (user.isOnline() || plugin.getConfigFile().getPlaceholderCacheLevel().isCacheAlways()) { - plugin.getPlaceholders().onUpdate(user, true); - } - - if (!user.isOnline()) { - user.clearCache(); - } - plugin.setUpdate(true); - - plugin.extraDebug("Finished vote processing: " + playerName + "/" + uuid); - } - + + // If we get here, use the resolved/possibly-prefixed name going forward + playerName = creditedName; + + if (playerName.isEmpty()) { + plugin.getLogger().warning("Empty player name from vote, ignoring"); + return; + } + + if (event.isBungee()) { + plugin.debug("BungeePlayerVote forcebungee: " + event.isForceBungee() + ", bungeetotals: " + + event.getBungeeTextTotals()); + + if (plugin.getBungeeSettings().isTriggerVotifierEvent()) { + try { + new ProxyVotifierEvent().send(plugin, event); + } catch (NoClassDefFoundError ex) { + plugin.getLogger().severe( + "Failed to trigger Votifier event for proxy vote. Either install Votifier or disable triggering the Votifier event"); + plugin.getLogger().severe("Error: " + ex.getMessage()); + plugin.debug(ex); + } + } + } + + VoteSite voteSite = event.getVoteSite(); + + if (voteSite == null) { + voteSite = plugin.getVoteSiteManager() + .getVoteSite(plugin.getVoteSiteManager().getVoteSiteName(true, event.getServiceSite()), true); + } + + // check valid service sites + if (voteSite == null) { + if (!plugin.getConfigFile().isDisableNoServiceSiteMessage()) { + plugin.getLogger().warning("No voting site with the service site: '" + event.getServiceSite() + "'"); + + ArrayList services = new ArrayList<>(); + for (VoteSite site : plugin.getVoteSiteManager().getVoteSites()) { + services.add(site.getServiceSite()); + } + plugin.getLogger().warning("Currently set service sites: " + ArrayUtils.makeStringList(services)); + } + return; + } + + if (!voteSite.isEnabled()) { + plugin.debug("Votesite: " + voteSite.getKey() + " is not enabled"); + return; + } + + VotingPluginUser user = null; + if (event.getVotingPluginUser() != null) { + user = event.getVotingPluginUser(); + } else { + Player p = Bukkit.getPlayerExact(playerName); + if (p != null) { + // player online + user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); + } else { + // attempt to get exact name from cache matching casing + user = plugin.getVotingPluginUserManager().getVotingPluginUser(playerName); + } + } + + boolean queuedProxyVoteAlreadyRecorded = ProxyVoteDelayCheck.isQueuedVoteAlreadyRecorded(event.isBungee(), + event.getTime(), user.getTime(voteSite)); + if (voteSite.isWaitUntilVoteDelay() && !queuedProxyVoteAlreadyRecorded && !user.canVoteSite(voteSite)) { + if (!event.isRealVote()) { + plugin.getLogger().info(user.getPlayerName() + " did a not real vote, bypassing WaitUntilVoteDelay"); + } 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() + .info(user.getPlayerName() + " has bypass permission for WaitUntilVoteDelay, bypassing"); + } + } + if (queuedProxyVoteAlreadyRecorded) { + plugin.debug("Allowing queued proxy vote for " + user.getPlayerName() + " on " + voteSite.getKey() + + "; proxy vote time already matches LastVotes: " + event.getTime()); + } + + UUID voteUUID = UUID.randomUUID(); + if (event.isBungee() && event.getBungeeTextTotals() != null) { + voteUUID = event.getBungeeTextTotals().getVoteUUID(); + if (voteUUID == null) { + voteUUID = UUID.randomUUID(); + } + } + + final String uuid = user.getUUID(); + + // reupdate cache + user.cache(); + + user.updateName(true); + + // vote party + plugin.getVoteParty().vote(user, event.isRealVote(), event.isForceBungee()); + + if (event.isBroadcast()) { + if (plugin.getBroadcastHandler() != null) { + boolean online = user.isOnline(); + if (event.isBungee()) { + online = event.isWasOnline(); + } + if (!user.isVanished()) { + plugin.getBroadcastHandler().broadcastVote(user.getJavaUUID(), playerName, + voteSite.getDisplayName(), online); + } else { + plugin.debug("Not broadcasting vote for vanished user: " + user.getPlayerName()); + } + } + } + + long voteTime = 0; + // update last vote time + if (event.getTime() != 0) { + user.setTime(voteSite, event.getTime()); + voteTime = event.getTime(); + } else { + user.setTime(voteSite); + voteTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + } + + boolean cached = false; + // check if player has voted on all sites in one day + if (((user.isOnline() || voteSite.isGiveOffline()) && plugin.getOptions().isProcessRewards()) + || event.isBungee()) { + boolean online = true; + if (event.isBungee()) { + online = event.isWasOnline(); + } + user.playerVote(voteSite, online, event.isForceBungee()); + if (event.getVoteNumber() == 1) { + user.sendVoteEffects(online); + } + if (plugin.getConfigFile().isCloseInventoryOnVote()) { + user.closeInv(); + } + } else { + if (!plugin.getConfigFile().isOfflineVotesLimitEnabled() + || user.getNumberOfOfflineVotes(voteSite) <= plugin.getConfigFile().getOfflineVotesLimitAmount()) { + user.addOfflineVote(voteSite.getKey()); + cached = true; + plugin.debug( + "Offline vote set for " + playerName + " (" + user.getUUID() + ") on " + voteSite.getKey()); + } else { + plugin.debug("Not setting offline vote, offline vote limit reached"); + } + } + + // add to total votes + if ((plugin.getConfigFile().isCountFakeVotes() || event.isRealVote()) && event.isAddTotals()) { + if (plugin.getConfigFile().isAddTotals()) { + if (plugin.getConfigFile().isAddTotalsOffline() || user.isOnline()) { + user.addTotal(); + user.addTotalDaily(); + user.addTotalWeekly(); + } + } + user.addPoints(); + } + user.checkDayVoteStreak(event.isForceBungee()); + + if (plugin.getConfigFile().isLimitMonthlyVotes()) { + int value = 0; + if (event.isBungee()) { + value = event.getBungeeTextTotals().getMonthTotal(); + } else { + value = user.getTotal(TopVoter.Monthly); + } + LocalDateTime cTime = plugin.getTimeChecker().getTime(); + int days = cTime.getDayOfMonth(); + plugin.extraDebug("Current day of month: " + days + " Current total: " + value); + if (value >= days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()) { + plugin.debug("Detected higher month total, changing. Current Total: " + value + " Days: " + days + + " New Total: " + days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()); + user.setTotal(TopVoter.Monthly, days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()); + } + } + + plugin.getVoteMilestonesManager().handleVote(user, event.getBungeeTextTotals(), event.isForceBungee(), voteUUID, + new HashMap()); + + plugin.getCoolDownCheck().vote(user, voteSite); + + plugin.getVoteStreakHandler().processVote(user, voteTime, voteUUID); + + PlayerPostVoteEvent postVoteEvent = new PlayerPostVoteEvent(voteSite, user, event.isRealVote(), + event.isForceBungee(), voteTime, cached, voteSite.getServiceSite(), user.getJavaUUID(), playerName, + voteUUID); + plugin.getServer().getPluginManager().callEvent(postVoteEvent); + + if (user.isOnline() || plugin.getConfigFile().getPlaceholderCacheLevel().isCacheAlways()) { + plugin.getPlaceholders().onUpdate(user, true); + } + + if (!user.isOnline()) { + user.clearCache(); + } + plugin.setUpdate(true); + + plugin.extraDebug("Finished vote processing: " + playerName + "/" + uuid); + } + } diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/SignChange.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/SignChange.java index 62d0fe2461..3f17bba4de 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/SignChange.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/SignChange.java @@ -1,63 +1,64 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.SignChangeEvent; - -import com.bencodez.advancedcore.api.misc.PlayerManager; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.votingplugin.VotingPluginMain; -public class SignChange implements Listener { - - /** The plugin. */ - private VotingPluginMain plugin; - - /** - * Instantiates a new sign change. - * - * @param plugin the plugin - */ - public SignChange(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On sign change. - * - * @param event the event - */ - @EventHandler(ignoreCancelled = true) - public void onSignChange(SignChangeEvent event) { - if (event.getLine(0).equalsIgnoreCase("[VotingPlugin]")) { - if (PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), "VotingPlugin.Sign.Create") - || PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), - "VotingPlugin.Admin")) { - String data = event.getLine(2); - if (!data.equalsIgnoreCase("all") && !data.equalsIgnoreCase("monthly") - && !data.equalsIgnoreCase("weekly") && !data.equalsIgnoreCase("daily")) { - return; - } - try { - plugin.getServerData().addSign(event.getBlock().getLocation(), event.getLine(2), - Integer.parseInt(event.getLine(1))); - event.getPlayer().sendMessage(MessageAPI.colorize("&aAdded sign!")); - plugin.getBukkitScheduler().runTaskAsynchronously(plugin, new Runnable() { - - @Override - public void run() { - plugin.getSigns().updateSigns(); - plugin.getSigns().storeSigns(); - } - }); - } catch (Exception ex) { - event.getPlayer().sendMessage(MessageAPI.colorize("&cError on sign creation!")); - ex.printStackTrace(); - } - } else { - event.getPlayer().sendMessage(MessageAPI.colorize(plugin.getConfigFile().getFormatNoPerms())); - } - } - - } - +package com.bencodez.votingplugin.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.SignChangeEvent; + +import com.bencodez.advancedcore.api.misc.PlayerManager; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.votingplugin.VotingPluginMain; + +public class SignChange implements Listener { + + /** The plugin. */ + private VotingPluginMain plugin; + + /** + * Instantiates a new sign change. + * + * @param plugin the plugin + */ + public SignChange(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On sign change. + * + * @param event the event + */ + @EventHandler(ignoreCancelled = true) + public void onSignChange(SignChangeEvent event) { + if (event.getLine(0).equalsIgnoreCase("[VotingPlugin]")) { + if (PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), "VotingPlugin.Sign.Create") + || PlayerManager.getInstance().hasServerPermission(event.getPlayer().getName(), + "VotingPlugin.Admin")) { + String data = event.getLine(2); + if (!data.equalsIgnoreCase("all") && !data.equalsIgnoreCase("monthly") + && !data.equalsIgnoreCase("weekly") && !data.equalsIgnoreCase("daily")) { + return; + } + try { + plugin.getServerData().addSign(event.getBlock().getLocation(), event.getLine(2), + Integer.parseInt(event.getLine(1))); + event.getPlayer().sendMessage(MessageAPI.colorize("&aAdded sign!")); + plugin.getBukkitScheduler().runTaskAsynchronously(plugin, new Runnable() { + + @Override + public void run() { + plugin.getSigns().updateSigns(); + plugin.getSigns().storeSigns(); + } + }); + } catch (Exception ex) { + event.getPlayer().sendMessage(MessageAPI.colorize("&cError on sign creation!")); + ex.printStackTrace(); + } + } else { + event.getPlayer().sendMessage(MessageAPI.colorize(plugin.getConfigFile().getFormatNoPerms())); + } + } + + } + } \ No newline at end of file diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotiferEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotiferEvent.java index b1dade6003..390a9aec88 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotiferEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotiferEvent.java @@ -1,132 +1,133 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; - -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.events.PlayerVoteEvent; -import com.bencodez.votingplugin.proxy.BungeeMethod; -import com.bencodez.votingplugin.util.MinecraftUsernameValidator; -import com.bencodez.votingplugin.util.ServiceSiteValidator; -import com.vexsoftware.votifier.model.Vote; -import com.vexsoftware.votifier.model.VotifierEvent; -public class VotiferEvent implements Listener { - - private VotingPluginMain plugin; - - /** - * Instantiates a new votifer event. - * - * @param plugin the plugin - */ - public VotiferEvent(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On votifer event. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onVotiferEvent(VotifierEvent event) { - - Vote vote = event.getVote(); - String str = vote.getServiceName(); - if (str == null || str.isEmpty()) { - str = "Empty"; - } - final String voteSite = str; - final String IP = vote.getAddress(); - final String voteUsername = vote.getUsername(); - if (IP.equals("VotingPlugin")) { - return; - } - if (!ServiceSiteValidator.isValid(voteSite)) { - plugin.getLogger().warning("Rejected vote with invalid service site '" - + ServiceSiteValidator.sanitizeForLog(voteSite) + "'"); - return; - } - - if (!MinecraftUsernameValidator.isValid(voteUsername, plugin.getOptions().getBedrockPlayerPrefix())) { - plugin.getLogger().warning("Rejected vote with invalid Minecraft username '" - + MinecraftUsernameValidator.sanitizeForLog(voteUsername) + "' from service '" - + MinecraftUsernameValidator.sanitizeForLog(voteSite) + "'"); - return; - } - - plugin.getLogger() - .info("Received a vote from service site '" + voteSite + "' by player '" + voteUsername + "'!"); - - plugin.debug("PlayerUsername: " + voteUsername); - plugin.debug("VoteSite: " + voteSite); - plugin.debug("IP: " + IP); - - plugin.getVoteTimer().submit(new Runnable() { - - @Override - public void run() { - try { - plugin.getServerData().addServiceSite(voteSite); - if (plugin.getBungeeSettings().isUseBungeecoord() && !plugin.getBungeeSettings().isVotifierBypass() - && (plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.PLUGINMESSAGING) - || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.SOCKETS) - || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.MQTT) - || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.REDIS))) { - plugin.getLogger().severe( - "Ignoring vote from votifier since pluginmessaging, socket, redis, or mqtt bungee method is enabled, this means you aren't setup correctly for those methods, please check: https://github.com/BenCodez/VotingPlugin/wiki/Bungeecord-Setups"); - return; - } - - String matchSite = ""; - if (plugin.getConfigFile().isAdvancedServiceSiteHandling()) { - if (plugin.getServiceSiteHandler() != null) { - matchSite = plugin.getServiceSiteHandler().matchReverse(voteSite); - } - } - - String voteSiteNameStr = plugin.getVoteSiteManager().getVoteSiteName(false, voteSite, matchSite); - boolean createSite = !plugin.getVoteSiteManager().hasVoteSite(voteSiteNameStr) - && !plugin.getVoteSiteManager().hasConfiguredVoteSite(voteSiteNameStr); - - String serviceSite = voteSite; - - if (plugin.getConfigFile().isAutoCreateVoteSites() && createSite) { - plugin.getLogger().warning("VoteSite with service site '" + voteSiteNameStr - + "' does not exist, attempting to generate..."); - if (plugin.getConfigVoteSites().tryGenerateVoteSite(voteSiteNameStr)) { - plugin.getLogger().info("Current known service sites: " - + ArrayUtils.makeStringList(plugin.getServerData().getServiceSites())); - } else { - plugin.getLogger().warning("Unable to generate VoteSite for service site '" - + ServiceSiteValidator.sanitizeForLog(voteSiteNameStr) + "'"); - } - } - - if (plugin.getTimeChecker().isActiveProcessing() - && plugin.getConfigFile().isQueueVotesDuringTimeChange()) { - plugin.debug("Adding vote to time queue " + voteUsername + "/" + voteSite); - plugin.getTimeQueueHandler().addVote(voteUsername, voteSite); - return; - } - - String voteSiteName = plugin.getVoteSiteManager().getVoteSiteName(true, serviceSite, matchSite); - - PlayerVoteEvent voteEvent = new PlayerVoteEvent( - plugin.getVoteSiteManager().getVoteSite(voteSiteName, true), voteUsername, voteSite, true); - plugin.getServer().getPluginManager().callEvent(voteEvent); - - if (voteEvent.isCancelled()) { - plugin.debug("Vote cancelled"); - return; - } - } catch (Exception e) { - plugin.getLogger().severe("Error occured during vote processing"); - e.printStackTrace(); - } - } - }); - } -} +package com.bencodez.votingplugin.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.events.PlayerVoteEvent; +import com.bencodez.votingplugin.proxy.BungeeMethod; +import com.bencodez.votingplugin.util.MinecraftUsernameValidator; +import com.bencodez.votingplugin.util.ServiceSiteValidator; +import com.vexsoftware.votifier.model.Vote; +import com.vexsoftware.votifier.model.VotifierEvent; + +public class VotiferEvent implements Listener { + + private VotingPluginMain plugin; + + /** + * Instantiates a new votifer event. + * + * @param plugin the plugin + */ + public VotiferEvent(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On votifer event. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onVotiferEvent(VotifierEvent event) { + + Vote vote = event.getVote(); + String str = vote.getServiceName(); + if (str == null || str.isEmpty()) { + str = "Empty"; + } + final String voteSite = str; + final String IP = vote.getAddress(); + final String voteUsername = vote.getUsername(); + if (IP.equals("VotingPlugin")) { + return; + } + if (!ServiceSiteValidator.isValid(voteSite)) { + plugin.getLogger().warning("Rejected vote with invalid service site '" + + ServiceSiteValidator.sanitizeForLog(voteSite) + "'"); + return; + } + + if (!MinecraftUsernameValidator.isValid(voteUsername, plugin.getOptions().getBedrockPlayerPrefix())) { + plugin.getLogger().warning("Rejected vote with invalid Minecraft username '" + + MinecraftUsernameValidator.sanitizeForLog(voteUsername) + "' from service '" + + MinecraftUsernameValidator.sanitizeForLog(voteSite) + "'"); + return; + } + + plugin.getLogger() + .info("Received a vote from service site '" + voteSite + "' by player '" + voteUsername + "'!"); + + plugin.debug("PlayerUsername: " + voteUsername); + plugin.debug("VoteSite: " + voteSite); + plugin.debug("IP: " + IP); + + plugin.getVoteTimer().submit(new Runnable() { + + @Override + public void run() { + try { + plugin.getServerData().addServiceSite(voteSite); + if (plugin.getBungeeSettings().isUseBungeecoord() && !plugin.getBungeeSettings().isVotifierBypass() + && (plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.PLUGINMESSAGING) + || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.SOCKETS) + || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.MQTT) + || plugin.getBackendProxyHandler().getMethod().equals(BungeeMethod.REDIS))) { + plugin.getLogger().severe( + "Ignoring vote from votifier since pluginmessaging, socket, redis, or mqtt bungee method is enabled, this means you aren't setup correctly for those methods, please check: https://github.com/BenCodez/VotingPlugin/wiki/Bungeecord-Setups"); + return; + } + + String matchSite = ""; + if (plugin.getConfigFile().isAdvancedServiceSiteHandling()) { + if (plugin.getServiceSiteHandler() != null) { + matchSite = plugin.getServiceSiteHandler().matchReverse(voteSite); + } + } + + String voteSiteNameStr = plugin.getVoteSiteManager().getVoteSiteName(false, voteSite, matchSite); + boolean createSite = !plugin.getVoteSiteManager().hasVoteSite(voteSiteNameStr) + && !plugin.getVoteSiteManager().hasConfiguredVoteSite(voteSiteNameStr); + + String serviceSite = voteSite; + + if (plugin.getConfigFile().isAutoCreateVoteSites() && createSite) { + plugin.getLogger().warning("VoteSite with service site '" + voteSiteNameStr + + "' does not exist, attempting to generate..."); + if (plugin.getConfigVoteSites().tryGenerateVoteSite(voteSiteNameStr)) { + plugin.getLogger().info("Current known service sites: " + + ArrayUtils.makeStringList(plugin.getServerData().getServiceSites())); + } else { + plugin.getLogger().warning("Unable to generate VoteSite for service site '" + + ServiceSiteValidator.sanitizeForLog(voteSiteNameStr) + "'"); + } + } + + if (plugin.getTimeChecker().isActiveProcessing() + && plugin.getConfigFile().isQueueVotesDuringTimeChange()) { + plugin.debug("Adding vote to time queue " + voteUsername + "/" + voteSite); + plugin.getTimeQueueHandler().addVote(voteUsername, voteSite); + return; + } + + String voteSiteName = plugin.getVoteSiteManager().getVoteSiteName(true, serviceSite, matchSite); + + PlayerVoteEvent voteEvent = new PlayerVoteEvent( + plugin.getVoteSiteManager().getVoteSite(voteSiteName, true), voteUsername, voteSite, true); + plugin.getServer().getPluginManager().callEvent(voteEvent); + + if (voteEvent.isCancelled()) { + plugin.debug("Vote cancelled"); + return; + } + } catch (Exception e) { + plugin.getLogger().severe("Error occured during vote processing"); + e.printStackTrace(); + } + } + }); + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotingPluginUpdateEvent.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotingPluginUpdateEvent.java index 0ddda92878..cd975ed333 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotingPluginUpdateEvent.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/listeners/VotingPluginUpdateEvent.java @@ -1,38 +1,39 @@ -package com.bencodez.votingplugin.listeners; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; - -import com.bencodez.advancedcore.listeners.PluginUpdateVersionEvent; -import com.bencodez.votingplugin.VotingPluginMain; -public class VotingPluginUpdateEvent implements Listener { - - /** The plugin. */ - private VotingPluginMain plugin; - - /** - * Instantiates a new advanced core update event. - * - * @param plugin the plugin - */ - public VotingPluginUpdateEvent(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * On plugin update. - * - * @param event the event - */ - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPluginUpdate(PluginUpdateVersionEvent event) { - if (event.getPlugin().getName().equals(plugin.getDescription().getName())) { - if (!event.getOldVersion().equals("")) { - plugin.getLogger().info("VotingPlugin Updated to " + plugin.getDescription().getVersion() + " from " - + event.getOldVersion()); - } - } - } - +package com.bencodez.votingplugin.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import com.bencodez.advancedcore.listeners.PluginUpdateVersionEvent; +import com.bencodez.votingplugin.VotingPluginMain; + +public class VotingPluginUpdateEvent implements Listener { + + /** The plugin. */ + private VotingPluginMain plugin; + + /** + * Instantiates a new advanced core update event. + * + * @param plugin the plugin + */ + public VotingPluginUpdateEvent(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * On plugin update. + * + * @param event the event + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPluginUpdate(PluginUpdateVersionEvent event) { + if (event.getPlugin().getName().equals(plugin.getDescription().getName())) { + if (!event.getOldVersion().equals("")) { + plugin.getLogger().info("VotingPlugin Updated to " + plugin.getDescription().getVersion() + " from " + + event.getOldVersion()); + } + } + } + } \ No newline at end of file diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/MVdWPlaceholders.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/MVdWPlaceholders.java index 4740994633..9159867cdf 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/MVdWPlaceholders.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/MVdWPlaceholders.java @@ -10,6 +10,7 @@ import be.maximvdw.placeholderapi.PlaceholderAPI; import be.maximvdw.placeholderapi.PlaceholderReplaceEvent; import be.maximvdw.placeholderapi.PlaceholderReplacer; + public class MVdWPlaceholders { /** The plugin. */ diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java index ea2bcb1b16..6cbf043827 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/placeholders/PlaceHolders.java @@ -1,1320 +1,1321 @@ -package com.bencodez.votingplugin.placeholders; - -import java.text.NumberFormat; -import java.time.Duration; -import java.time.LocalDateTime; -import java.time.temporal.TemporalField; -import java.time.temporal.WeekFields; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import com.bencodez.advancedcore.api.messages.PlaceholderUtils; -import com.bencodez.advancedcore.api.placeholder.CalculatingPlaceholder; -import com.bencodez.advancedcore.api.placeholder.NonPlayerPlaceHolder; -import com.bencodez.advancedcore.api.placeholder.PlaceHolder; -import com.bencodez.advancedcore.api.user.AdvancedCoreUser; -import com.bencodez.advancedcore.api.user.UserDataChanged; -import com.bencodez.advancedcore.api.user.UserDataFetchMode; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestone; -import com.bencodez.votingplugin.topvoter.TopVoter; -import com.bencodez.votingplugin.topvoter.TopVoterPlayer; -import com.bencodez.votingplugin.user.VotingPluginUser; -import com.bencodez.votingplugin.votesites.VoteSite; - -import lombok.Getter; -public class PlaceHolders { - - @Getter - private ArrayList> nonPlayerPlaceholders = new ArrayList<>(); - - @Getter - private ArrayList> placeholders = new ArrayList<>(); - - private VotingPluginMain plugin; - - private ArrayList cachedPlaceholders = new ArrayList<>(); - - private ConcurrentLinkedQueue placeholdersToSetCacheOn = new ConcurrentLinkedQueue<>(); - - @Getter - private PlaceholderCacheLevel cacheLevel; - - /** - * Constructor for PlaceHolders. - * @param plugin the voting plugin instance - */ - public PlaceHolders(VotingPluginMain plugin) { - this.plugin = plugin; - cacheLevel = plugin.getConfigFile().getPlaceholderCacheLevel(); - } - - /** - * Check for placeholders that need caching. - */ - public void checkNonCachedPlaceholders() { - while (!placeholdersToSetCacheOn.isEmpty()) { - String toCache = placeholdersToSetCacheOn.poll().toLowerCase(); - if (toCache.startsWith("votingplugin")) { - toCache = toCache.substring("votingplugin_".length()); - } - /* - * for (NonPlayerPlaceHolder placeholder : - * nonPlayerPlaceholders) { if (placeholder.matches(toCache)) { - * placeholder.setUseCache(true, toCache); cachedPlaceholders.add(toCache); - * plugin.getServerData().addAutoCachedPlaceholder(toCache); - * plugin.extraDebug("Auto Caching placeholder " + toCache); } - * - * } - */ - for (PlaceHolder placeholder : placeholders) { - if (placeholder.matches(toCache)) { - placeholder.setUseCache(true, toCache); - cachedPlaceholders.add(toCache); - plugin.getServerData().addAutoCachedPlaceholder(toCache); - plugin.extraDebug("Auto Caching placeholder " + toCache); - } - } - - } - } - - /** - * Get placeholder value for offline player. - * @param p the offline player - * @param identifier the placeholder identifier - * @return the placeholder value - */ - public String getPlaceHolder(OfflinePlayer p, String identifier) { - return getPlaceHolder(p, identifier, true); - } - - /** - * Get placeholder value for offline player with javascript support. - * @param p the offline player - * @param identifier1 the placeholder identifier - * @param javascript enable javascript processing - * @return the placeholder value - */ - public String getPlaceHolder(OfflinePlayer p, String identifier1, boolean javascript) { - boolean forceProcess = false; - boolean useCache = true; - String identifier = identifier1.toLowerCase(); - boolean custom = false; - if (identifier.endsWith("_process") - || (!Bukkit.isPrimaryThread() && plugin.getConfigFile().isAlwaysProcessAsyncPlaceholders())) { - forceProcess = true; - identifier = identifier.replaceAll("_process", ""); - } - if (identifier.endsWith("_nocache")) { - useCache = false; - identifier = identifier.replaceAll("_nocache", ""); - } - if (getCacheLevel().equals(PlaceholderCacheLevel.NONE)) { - useCache = false; - } - - if (identifier.startsWith("custom_")) { - custom = true; - identifier = identifier.replaceAll("custom_", ""); - } - - if (!custom || !plugin.getConfigFile().getCustomPlaceholderReturns().contains(identifier)) { - return getPlaceholderValue(p, identifier, javascript, forceProcess, useCache); - } - String str = getPlaceholderValue(p, identifier, javascript, true, useCache); - String returnStr = plugin.getConfigFile().getCustomPlaceholderReturns(identifier, str); - if (!returnStr.isEmpty()) { - return returnStr; - } - return str; - - } - - /** - * Get placeholder value for online player. - * @param p the player - * @param identifier the placeholder identifier - * @return the placeholder value - */ - public String getPlaceHolder(Player p, String identifier) { - if (plugin.getConfigFile().isUseJavascriptPlaceholders()) { - identifier = PlaceholderUtils.replaceJavascript(p, identifier); - } - return getPlaceHolder(p, identifier, false); - } - - /** - * Get placeholder value with options. - * @param p the offline player - * @param identifier the placeholder identifier - * @param javascript enable javascript processing - * @param forceProcess force processing of placeholder - * @param useCache use cached value if available - * @return the placeholder value - */ - public String getPlaceholderValue(OfflinePlayer p, String identifier, boolean javascript, boolean forceProcess, - boolean useCache) { - if (plugin.getConfigFile().isUseJavascriptPlaceholders() && javascript && p != null) { - identifier = PlaceholderUtils.replaceJavascript(p, identifier); - } - - if (!identifier.toLowerCase().endsWith("position")) { - for (NonPlayerPlaceHolder placeholder : nonPlayerPlaceholders) { - if (placeholder.matches(identifier)) { - String str = placeholder.placeholderRequest(identifier); - if (str != null) { - return str; - } - } - } - } - - if (p == null) { - return "no player"; - } - - VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); - if (useCache) { - if (!cachedPlaceholders.contains(identifier)) { - // not cached placeholder - if (!forceProcess) { - for (PlaceHolder placeholder : placeholders) { - if (placeholder.matches(identifier)) { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return ".."; - } - } - return "Not a valid placeholder"; - - } - } - } - - UUID uuid = user.getJavaUUID(); - - for (PlaceHolder placeholder : placeholders) { - try { - if (placeholder.matches(identifier)) { - if (placeholder instanceof CalculatingPlaceholder) { - if (!useCache) { - return placeholder.placeholderRequest(user, identifier); - } - CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; - if (placeholder.isUsesCache() && placeholder.isCached(identifier)) { - ConcurrentHashMap cache = placeholder.getCache().get(identifier); - if (cache.containsKey(uuid)) { - if (cPlaceholder.getCacheData().containsKey(uuid)) { - return cPlaceholder.placeholderRequest(user, identifier); - } - return cache.get(uuid); - } else if (!forceProcess) { - schedulePlaceholderCheck(user); - return "..."; - } - } - - if (forceProcess) { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier) - && !cachedPlaceholders.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return placeholder.placeholderRequest(user, identifier); - } else { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier) - && !cachedPlaceholders.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return "."; - } - } - if (!useCache) { - return placeholder.placeholderRequest(user, identifier); - } - if (placeholder.isUsesCache() && placeholder.isCached(identifier)) { - ConcurrentHashMap cache = placeholder.getCache().get(identifier); - - if (cache.containsKey(uuid)) { - return cache.get(uuid); - } else if (!forceProcess) { - schedulePlaceholderCheck(user); - return "..."; - } - } - - if (forceProcess) { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier) - && !cachedPlaceholders.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return placeholder.placeholderRequest(user, identifier); - } else { - if (getCacheLevel().shouldCache()) { - if (!placeholdersToSetCacheOn.contains(identifier) - && !cachedPlaceholders.contains(identifier)) { - placeholdersToSetCacheOn.add(identifier); - schedulePlaceholderCheck(user); - } - } - return "."; - } - } - } catch (Exception e) { - plugin.debug(e); - return "Error"; - } - } - - return "Not a valid placeholder"; - } - - /** - * Load all placeholders. - */ - public void load() { - placeholders.clear(); - nonPlayerPlaceholders.clear(); - - // older placeholders, might be removed in the future - placeholders.add(new PlaceHolder("total") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getTotal(TopVoter.Monthly)); - } - }.withDescription("Month total").updateDataKey("MonthTotal")); - - placeholders.add(new PlaceHolder("alltimetotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getTotal(TopVoter.AllTime)); - } - }.withDescription("Alltime total").updateDataKey("AllTimeTotal")); - - placeholders.add(new PlaceHolder("lastmonthtotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getLastMonthTotal()); - } - }.withDescription("Last month total").updateDataKey("LastMonthTotal")); - - // end of older placeholders - - placeholders.add(new PlaceHolder("CanLike_NameMC") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return user.hasClaimedNameMCLikeReward() ? "Complete" : "Incomplete"; - } - }.withDescription("Return Complete/Incomplete depending on whether the player has liked the server on NameMC") - .updateDataKey("ClaimedNameMCLikeReward")); - - placeholders.add(new PlaceHolder("DisableBroadcast") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getDisableBroadcast(); - } - }.withDescription("Returns true/false if user has broadcast disabled").updateDataKey("DisableBroadcast")); - - /* - * placeholders.add(new PlaceHolder("DisableReminders") { - * - * @Override public String placeholderRequest(VotingPluginUser user, String - * identifier) { if - * (plugin.getVoteReminding().getRemindersEnabled().containsKey(user.getJavaUUID - * ())) { if - * (!plugin.getVoteReminding().getRemindersEnabled().get(user.getJavaUUID()). - * booleanValue()) { - * - * return "True"; } } return "False"; } - * }.withDescription("Returns true/false if user has reminders disabled")); - */ - - for (final String identifier : plugin.getShopFile().getShopIdentifiers()) { - if (plugin.getShopFile().getShopIdentifierLimit(identifier) > 0) { - placeholders.add(new PlaceHolder("VoteShopLimit_" + identifier) { - - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - return "" + user.getVoteShopIdentifierLimit(identifier); - } - }.withDescription("User voteshop limit for " + identifier).updateDataKey("VoteShopLimit" + identifier)); - } - } - - for (final TopVoter top : TopVoter.values()) { - placeholders.add(new PlaceHolder("Total_" + top.toString()) { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getTotal(top)); - } - }.withDescription("User total for " + top.getName()).updateDataKey(top.getColumnName())); - } - - placeholders.add(new PlaceHolder("BestDailyTotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getHighestDailyTotal()); - } - }.withDescription("Best daily total").updateDataKey("HighestDailyTotal")); - - placeholders.add(new PlaceHolder("BestWeeklyTotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getHighestWeeklyTotal()); - } - }.withDescription("Best weekly total").updateDataKey("HighestWeeklyTotal")); - - placeholders.add(new PlaceHolder("BestMonthlyTotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getHighestMonthlyTotal()); - } - }.withDescription("Best monthly total").updateDataKey("HighestMonthlyTotal")); - - placeholders.add(new PlaceHolder("DailyVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getDayVoteStreak()); - } - }.withDescription("Current daily votestreak").updateDataKey("DayVoteStreak")); - - placeholders.add(new PlaceHolder("WeeklyVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getWeekVoteStreak()); - } - }.withDescription("Current weekly votestreak").updateDataKey("WeekVoteStreak")); - - placeholders.add(new PlaceHolder("MonthVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getMonthVoteStreak()); - } - }.withDescription("Current month votestreak").updateDataKey("MonthVoteStreak")); - - placeholders.add(new PlaceHolder("BestDailyVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getBestDayVoteStreak()); - } - }.withDescription("Best daily votestreak").updateDataKey("BestDayVoteStreak")); - - placeholders.add(new PlaceHolder("BestWeeklyVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getBestWeekVoteStreak()); - } - }.withDescription("Best weekly votestreak").updateDataKey("BestWeekVoteStreak")); - - placeholders.add(new PlaceHolder("BestMonthVoteStreak") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getBestMonthVoteStreak()); - } - }.withDescription("Best month votestreak").updateDataKey("BestMonthVoteStreak")); - - placeholders.add(new PlaceHolder("Points") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Integer.toString(user.getPoints()); - } - }.withDescription("User points").updateDataKey("Points")); - - placeholders.add(new PlaceHolder("Points_Format") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US); - return numberFormat.format(user.getPoints()); - } - }.withDescription("User points").updateDataKey("Points")); - - placeholders.add(new PlaceHolder("CanVote") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return Boolean.toString(user.canVoteAll()); - } - }.withDescription("Return true/false if player can vote on all sites").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("CanVoteSites") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getSitesNotVotedOn(); - } - }.withDescription("Return number of votesites available").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("Next_AnySite") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - if (user.canVoteAny()) { - return plugin.getConfigFile().getFormatCommandsVoteNextInfoCanVote(); - } - long smallest = -1; - HashMap times = new HashMap<>(); - for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) { - long t = user.voteNextDurationTime(site); - if (smallest == -1) { - smallest = t; - } - if (t < smallest) { - smallest = t; - } - times.put(t, site); - } - for (Entry entry : times.entrySet()) { - if (entry.getKey().longValue() == smallest) { - return user.voteCommandNextInfo(entry.getValue()); - } - } - - return "Error"; - } - }.withDescription("How long until user can vote on anysite").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("SitesAvailable") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getSitesNotVotedOn(); - } - }.withDescription("Get number of sites available to be voted on").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("SitesAvailableTotal") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getTotalNumberOfSites(); - } - }.withDescription("Get total number of sites available to be voted on")); - - for (final VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) { - placeholders.add(new CalculatingPlaceholder("Next_" + voteSite.getKey()) { - - @Override - public String placeholderDataRequest(VotingPluginUser user, String identifier) { - long time = user.getTime(voteSite); - return "" + time; - } - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - if (getCacheData().containsKey(user.getJavaUUID())) { - String data = getCacheData().get(user.getJavaUUID()); - if (!data.isEmpty()) { - long time = Long.valueOf(data); - return user.voteCommandNextInfo(voteSite, time); - } - } - return user.voteCommandNextInfo(voteSite); - } - }.withDescription("How long until user can vote on " + voteSite.getKey()).updateDataKey("LastVotes")); - placeholders.add(new PlaceHolder("Last_" + voteSite.getKey()) { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return user.voteCommandLastDuration(voteSite); - } - }.withDescription("How long ago user voted on " + voteSite.getKey()).updateDataKey("LastVotes")); - placeholders.add(new PlaceHolder("CanVote_" + voteSite.getKey()) { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.canVoteSite(voteSite); - } - }.withDescription("Whether or not player can vote on " + voteSite.getKey()).updateDataKey("LastVotes")); - } - - placeholders.add(new PlaceHolder("Top_All_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user top voter position")); - - placeholders.add(new PlaceHolder("EnoughPoints_") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[1])) { - return "invalid"; - } - int number = Integer.parseInt(identifier.split("_")[1]); - if (user.getPoints() >= number) { - return "true"; - } - return "false"; - } - }.withDescription("Return true/false if player has said points").updateDataKey("Points").useStartsWith()); - - // VoteMilestones placeholders (explicit per group, like - // VoteShopLimit_) - // Base/default (no group suffix) - placeholders.add(new PlaceHolder("VoteMilestoneNext") { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - Long next = plugin.getVoteMilestonesManager().getNextMilestoneValue("default", user); - return next == null ? "none" : Long.toString(next); - } - }.withDescription("Next VoteMilestone value for default group").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("VoteMilestoneLast") { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - Long last = plugin.getVoteMilestonesManager().getLastMilestoneValue("default", user); - return last == null ? "none" : Long.toString(last); - } - }.withDescription("Last achieved VoteMilestone value for default group").updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("VoteMilestoneVotesUntilNext") { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - return Long.toString(plugin.getVoteMilestonesManager().getVotesUntilNextMilestone("default", user)); - } - }.withDescription("Votes until next VoteMilestone for default group").updateDataKey("LastVotes")); - - Set groups = new HashSet<>(); - groups.add("default"); - - for (VoteMilestone m : plugin.getVoteMilestonesManager().getConfig().getMilestones().values()) { - String g = m.getGroupKey(); - if (g == null) - continue; - g = g.trim().toLowerCase(Locale.ROOT); - if (!g.isEmpty()) - groups.add(g); - } - - for (final String groupIdRaw : groups) { - final String groupId = (groupIdRaw == null || groupIdRaw.trim().isEmpty()) ? "default" : groupIdRaw.trim(); - - placeholders.add(new PlaceHolder("VoteMilestoneNext_" + groupId) { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - Long next = plugin.getVoteMilestonesManager().getNextMilestoneValue(groupId, user); - return next == null ? "none" : Long.toString(next); - } - }.withDescription("Next VoteMilestone value for group " + groupId).updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("VoteMilestoneLast_" + groupId) { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - Long last = plugin.getVoteMilestonesManager().getLastMilestoneValue(groupId, user); - return last == null ? "none" : Long.toString(last); - } - }.withDescription("Last achieved VoteMilestone value for group " + groupId).updateDataKey("LastVotes")); - - placeholders.add(new PlaceHolder("VoteMilestoneVotesUntilNext_" + groupId) { - @Override - public String placeholderRequest(VotingPluginUser user, String ident) { - return Long.toString(plugin.getVoteMilestonesManager().getVotesUntilNextMilestone(groupId, user)); - } - }.withDescription("Votes until next VoteMilestone for group " + groupId).updateDataKey("LastVotes")); - } - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_AllVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in top voter")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_All_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get username at postion in top voter")); - - placeholders.add(new PlaceHolder("Top_Month_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user's current top voter position")); - - if (plugin.getGui().isLastMonthGUI()) { - placeholders.add(new PlaceHolder("Top_LastMonth_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user top voter position for lastmonth")); - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_LastMonth_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user at position in last month top voter")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_LastMonthVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in last month top voter")); - - } - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Month_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get username at position in top voter")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_MonthVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in top voter")); - - placeholders.add(new PlaceHolder("Top_Week_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user top voter position")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Week_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get username at postion in top voter")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_WeekVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in top voter")); - - placeholders.add(new PlaceHolder("Top_Daily_Position") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - int num = 1; - UUID toMatch = UUID.fromString(user.getUUID()); - for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { - if (entry.getKey().getUuid().equals(toMatch)) { - return "" + num; - } - num++; - } - return ""; - } - }.withDescription("Get user top voter position")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Daily_") { - - @Override - public String placeholderRequest(String identifier) { - if (!MessageAPI.isInt(identifier.split("_")[2])) { - return "invalid"; - } - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { - if (num == number) { - return entry.getKey().getPlayerName(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get username at postion in top voter")); - - placeholders.add(new PlaceHolder("VotePartyContributedVotes") { - - @Override - public String placeholderRequest(VotingPluginUser user, String identifier) { - return "" + user.getVotePartyVotes(); - } - }.useStartsWith().withDescription("See vote party placeholders contributed").updateDataKey("VotePartyVotes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_DailyVotes_") { - - @Override - public String placeholderRequest(String identifier) { - int num = 1; - int number = Integer.parseInt(identifier.split("_")[2]); - for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { - if (num == number) { - return "" + entry.getValue().intValue(); - } - num++; - } - return ""; - } - }.useStartsWith().withDescription("Get user votes at position in top voter")); - - // non players - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesCurrent") { - - @Override - public String placeholderRequest(String identifier) { - return Integer.toString(plugin.getVoteParty().getTotalVotes()); - } - }.withDescription("Current amount of voteparty votes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesNeeded") { - - @Override - public String placeholderRequest(String identifier) { - return Integer.toString(plugin.getVoteParty().getNeededVotes()); - } - }.withDescription("Voteparty votes needed")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesRequired") { - - @Override - public String placeholderRequest(String identifier) { - return Integer.toString(plugin.getVoteParty().getVotesRequired()); - } - }.withDescription("Amount of votes needed for voteparty")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesCurrent") { - - @Override - public String placeholderRequest(String identifier) { - if (plugin.getBackendProxyHandler() != null) { - return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyCurrent()); - } - return "-1"; - } - }.withDescription("Current amount of bungee voteparty votes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesNeeded") { - - @Override - public String placeholderRequest(String identifier) { - if (plugin.getBackendProxyHandler() != null) { - return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyRequired() - - plugin.getBackendProxyHandler().getBungeeVotePartyCurrent()); - } - return "-1"; - } - }.withDescription("Voteparty bungee votes needed")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesRequired") { - - @Override - public String placeholderRequest(String identifier) { - if (plugin.getBackendProxyHandler() != null) { - return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyRequired()); - } - return "-1"; - } - }.withDescription("Amount of votes needed for bungee voteparty")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalMonthTotal") { - - @Override - public String placeholderRequest(String identifier) { - int total = 0; - for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Monthly).values()) { - total += num; - } - return Integer.toString(total); - } - }.withDescription("Global month total")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalAllTimeTotal") { - - @Override - public String placeholderRequest(String identifier) { - int total = 0; - for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.AllTime).values()) { - total += num; - } - return Integer.toString(total); - } - }.withDescription("Global alltime total")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalWeeklyTotal") { - - @Override - public String placeholderRequest(String identifier) { - int total = 0; - for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Weekly).values()) { - total += num; - } - return Integer.toString(total); - } - }.withDescription("Global weekly total")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalDailyTotal") { - - @Override - public String placeholderRequest(String identifier) { - int total = 0; - for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Daily).values()) { - total += num; - } - return Integer.toString(total); - } - }.withDescription("Global daily total")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilDayReset") { - - @Override - public String placeholderRequest(String identifier) { - LocalDateTime now = plugin.getTimeChecker().getTime(); - LocalDateTime offsetoclocktoday = plugin.getTimeChecker().getTime().withHour(0).withMinute(0); - LocalDateTime offsetoclocktomorrow = plugin.getTimeChecker().getTime().plusDays(1).withHour(0) - .withMinute(0); - - String timeMsg = "%hours% Hours %minutes% Minutes"; - Duration dur = null; - if (!now.isBefore(offsetoclocktoday)) { - dur = Duration.between(now, offsetoclocktomorrow); - - } else { - dur = Duration.between(now, offsetoclocktoday); - } - int diffHours = (int) (dur.getSeconds() / (60 * 60)); - long diffMinutes = dur.getSeconds() / 60 - diffHours * 60; - - if (diffHours < 0) { - diffHours = diffHours * -1; - } - if (diffHours >= 24) { - diffHours = diffHours - 24; - } - if (diffMinutes < 0) { - diffMinutes = diffMinutes * -1; - } - - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); - return timeMsg; - - } - }.withDescription("Time until plugin time day changes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilWeekReset") { - - @Override - public String placeholderRequest(String identifier) { - LocalDateTime now = plugin.getTimeChecker().getTime().plusDays(plugin.getOptions().getTimeWeekOffSet()); - LocalDateTime newWeek = plugin.getTimeChecker().getTime().withHour(0).withMinute(0); - - TemporalField woy = WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear(); - int weekNumber = newWeek.get(woy); - int newWeekNumber = weekNumber; - - while (weekNumber == newWeekNumber) { - newWeek = newWeek.plusDays(1); - newWeekNumber = newWeek.get(woy); - } - - String timeMsg = "%days% Days %hours% Hours %minutes% Minutes"; - Duration dur = Duration.between(now, newWeek); - - int diffDays = (int) (dur.getSeconds() / (60 * 60 * 24)); - int diffHours = (int) (dur.getSeconds() / (60 * 60) - diffDays * 24); - long diffMinutes = dur.getSeconds() / 60 - diffHours * 60 - diffDays * 24 * 60; - - if (diffHours < 0) { - diffHours = diffHours * -1; - } - if (diffHours >= 24) { - diffHours = diffHours - 24; - } - if (diffMinutes < 0) { - diffMinutes = diffMinutes * -1; - } - - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%days%", Integer.toString(diffDays)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); - return timeMsg; - - } - }.withDescription("Time until plugin time week changes")); - - nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilMonthReset") { - - @Override - public String placeholderRequest(String identifier) { - LocalDateTime now = plugin.getTimeChecker().getTime(); - LocalDateTime newMonth = plugin.getTimeChecker().getTime().plusMonths(1).withDayOfMonth(1).withHour(0) - .withMinute(0); - - String timeMsg = "%days% Days %hours% Hours %minutes% Minutes"; - Duration dur = Duration.between(now, newMonth); - - int diffDays = (int) (dur.getSeconds() / (60 * 60 * 24)); - int diffHours = (int) (dur.getSeconds() / (60 * 60) - diffDays * 24); - long diffMinutes = dur.getSeconds() / 60 - diffHours * 60 - diffDays * 24 * 60; - - if (diffHours < 0) { - diffHours = diffHours * -1; - } - if (diffHours >= 24) { - diffHours = diffHours - 24; - } - if (diffMinutes < 0) { - diffMinutes = diffMinutes * -1; - } - - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%days%", Integer.toString(diffDays)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); - timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); - return timeMsg; - - } - }.withDescription("Time until plugin time month changes")); - - Set placeholdersSet = new HashSet<>(); - placeholdersSet.addAll(plugin.getConfigFile().getCachedPlaceholders()); - if (getCacheLevel().equals(PlaceholderCacheLevel.AUTO)) { - placeholdersSet.addAll(plugin.getServerData().getAutoCachedPlaceholder()); - } - - for (String toCache : placeholdersSet) { - if (toCache.startsWith("votingplugin")) { - toCache = toCache.substring("votingplugin_".length()); - } - for (NonPlayerPlaceHolder placeholder : nonPlayerPlaceholders) { - if (placeholder.matches(toCache)) { - placeholder.setUseCache(true, toCache); - cachedPlaceholders.add(toCache); - plugin.extraDebug("Caching placeholder " + toCache); - } - } - - for (PlaceHolder placeholder : placeholders) { - if (placeholder.matches(toCache)) { - placeholder.setUseCache(true, toCache); - cachedPlaceholders.add(toCache); - plugin.extraDebug("Caching placeholder " + toCache); - } - } - } - - plugin.getUserManager().getUserDataChange().add(new UserDataChanged() { - - @Override - public void onChange(AdvancedCoreUser user, String... keys) { - VotingPluginUser vpUser = plugin.getVotingPluginUserManager().getVotingPluginUser(user); - if (!vpUser.isCached()) { - vpUser.userDataFetechMode(UserDataFetchMode.NO_CACHE); - } - for (PlaceHolder placeholder : placeholders) { - if (placeholder.isUsesCache()) { - if (placeholder.isCached(placeholder.getIdentifier(), user.getJavaUUID()) - || !getCacheLevel().onlineOnly() || user.isOnline()) { - if (placeholder instanceof CalculatingPlaceholder) { - CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; - if (placeholder.isUsesCache()) { - for (String key : keys) { - if (placeholder.getUpdateDataKey().equalsIgnoreCase(key)) { - for (String ident : placeholder.getCache().keySet()) { - String value = placeholder.placeholderRequest(vpUser, ident); - cPlaceholder.getCacheData().put(user.getJavaUUID(), - cPlaceholder.placeholderDataRequest(vpUser, ident)); - placeholder.getCache().get(ident).put(vpUser.getJavaUUID(), value); - plugin.devDebug("Updated calculating placeholder cache for " - + vpUser.getUUID() + " on " + key + " with " + value); - } - } - } - } - } else { - if (placeholder.isUsesCache()) { - for (String key : keys) { - if (placeholder.getUpdateDataKey().equalsIgnoreCase(key)) { - for (String ident : placeholder.getCache().keySet()) { - String value = placeholder.placeholderRequest(vpUser, ident); - placeholder.getCache().get(ident).put(vpUser.getJavaUUID(), value); - plugin.devDebug("Updated placeholder cache for " + vpUser.getUUID() - + " on " + key + " with " + value); - - } - - } - } - } - } - } - } - } - } - }); - } - - /** - * Handle player logout. - * @param user the voting plugin user - */ - public void onLogout(VotingPluginUser user) { - if (plugin.getPlaceholders().getCacheLevel().onlineOnly()) { - for (PlaceHolder placeholder : placeholders) { - if (placeholder.isUsesCache()) { - placeholder.clearCachePlayer(user.getJavaUUID()); - } - } - } - } - - /** - * Update all placeholders. - */ - public void onUpdate() { - checkNonCachedPlaceholders(); - for (Player p : Bukkit.getOnlinePlayers()) { - onUpdate(plugin.getVotingPluginUserManager().getVotingPluginUser(p), true); - } - /* - * for (NonPlayerPlaceHolder placeholder : - * nonPlayerPlaceholders) { if (placeholder.isUsesCache()) { for (String ident : - * placeholder.getCache().keySet()) { if (ident != null) { String str = - * placeholder.placeholderRequest(ident); if (str != null) { - * placeholder.getCache().put(ident, str); } } else { - * plugin.debug("ident null: " + placeholder.getIdentifier()); } } } } - */ - - } - - /** - * Update placeholders for specific user. - * @param user the voting plugin user - * @param login whether this is a login update - */ - public void onUpdate(VotingPluginUser user, boolean login) { - for (PlaceHolder placeholder : placeholders) { - if (placeholder.isUsesCache()) { - if (placeholder.isCached(placeholder.getIdentifier(), user.getJavaUUID()) || login) { - if (placeholder instanceof CalculatingPlaceholder) { - - CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; - if (placeholder.isUsesCache()) { - for (String ident : placeholder.getCache().keySet()) { - cPlaceholder.getCacheData().put(user.getJavaUUID(), - cPlaceholder.placeholderDataRequest(user, ident)); - placeholder.getCache().get(ident).put(user.getJavaUUID(), - placeholder.placeholderRequest(user, ident)); - } - - } - } else { - if (placeholder.isUsesCache()) { - for (String ident : placeholder.getCache().keySet()) { - placeholder.getCache().get(ident).put(user.getJavaUUID(), - placeholder.placeholderRequest(user, ident)); - } - } - } - } - } - } - } - - /** - * Handle vote party update. - */ - public void onVotePartyUpdate() { - /* - * for (NonPlayerPlaceHolder placeholder : - * nonPlayerPlaceholders) { if (placeholder.isUsesCache()) { if - * (placeholder.getIdentifier().startsWith("VoteParty")) { for (String ident : - * placeholder.getCache().keySet()) { placeholder.getCache().put(ident, - * placeholder.placeholderRequest(ident)); } } } } - */ - } - - /** - * Reload placeholders. - */ - public void reload() { - cacheLevel = plugin.getConfigFile().getPlaceholderCacheLevel(); - onUpdate(); - if (!cacheLevel.equals(PlaceholderCacheLevel.NONE)) { - for (Player player : Bukkit.getOnlinePlayers()) { - onUpdate(plugin.getVotingPluginUserManager().getVotingPluginUser(player), player.isOnline()); - } - } - } - - /** - * Schedule placeholder check for user. - * @param user the voting plugin user - */ - public void schedulePlaceholderCheck(VotingPluginUser user) { - plugin.getTimer().execute(new Runnable() { - - @Override - public void run() { - checkNonCachedPlaceholders(); - onUpdate(user, user.isOnline()); - } - }); - } -} +package com.bencodez.votingplugin.placeholders; + +import java.text.NumberFormat; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.temporal.TemporalField; +import java.time.temporal.WeekFields; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.placeholder.CalculatingPlaceholder; +import com.bencodez.advancedcore.api.placeholder.NonPlayerPlaceHolder; +import com.bencodez.advancedcore.api.placeholder.PlaceHolder; +import com.bencodez.advancedcore.api.user.AdvancedCoreUser; +import com.bencodez.advancedcore.api.user.UserDataChanged; +import com.bencodez.advancedcore.api.user.UserDataFetchMode; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestone; +import com.bencodez.votingplugin.topvoter.TopVoter; +import com.bencodez.votingplugin.topvoter.TopVoterPlayer; +import com.bencodez.votingplugin.user.VotingPluginUser; +import com.bencodez.votingplugin.votesites.VoteSite; + +import lombok.Getter; + +public class PlaceHolders { + + @Getter + private ArrayList> nonPlayerPlaceholders = new ArrayList<>(); + + @Getter + private ArrayList> placeholders = new ArrayList<>(); + + private VotingPluginMain plugin; + + private ArrayList cachedPlaceholders = new ArrayList<>(); + + private ConcurrentLinkedQueue placeholdersToSetCacheOn = new ConcurrentLinkedQueue<>(); + + @Getter + private PlaceholderCacheLevel cacheLevel; + + /** + * Constructor for PlaceHolders. + * @param plugin the voting plugin instance + */ + public PlaceHolders(VotingPluginMain plugin) { + this.plugin = plugin; + cacheLevel = plugin.getConfigFile().getPlaceholderCacheLevel(); + } + + /** + * Check for placeholders that need caching. + */ + public void checkNonCachedPlaceholders() { + while (!placeholdersToSetCacheOn.isEmpty()) { + String toCache = placeholdersToSetCacheOn.poll().toLowerCase(); + if (toCache.startsWith("votingplugin")) { + toCache = toCache.substring("votingplugin_".length()); + } + /* + * for (NonPlayerPlaceHolder placeholder : + * nonPlayerPlaceholders) { if (placeholder.matches(toCache)) { + * placeholder.setUseCache(true, toCache); cachedPlaceholders.add(toCache); + * plugin.getServerData().addAutoCachedPlaceholder(toCache); + * plugin.extraDebug("Auto Caching placeholder " + toCache); } + * + * } + */ + for (PlaceHolder placeholder : placeholders) { + if (placeholder.matches(toCache)) { + placeholder.setUseCache(true, toCache); + cachedPlaceholders.add(toCache); + plugin.getServerData().addAutoCachedPlaceholder(toCache); + plugin.extraDebug("Auto Caching placeholder " + toCache); + } + } + + } + } + + /** + * Get placeholder value for offline player. + * @param p the offline player + * @param identifier the placeholder identifier + * @return the placeholder value + */ + public String getPlaceHolder(OfflinePlayer p, String identifier) { + return getPlaceHolder(p, identifier, true); + } + + /** + * Get placeholder value for offline player with javascript support. + * @param p the offline player + * @param identifier1 the placeholder identifier + * @param javascript enable javascript processing + * @return the placeholder value + */ + public String getPlaceHolder(OfflinePlayer p, String identifier1, boolean javascript) { + boolean forceProcess = false; + boolean useCache = true; + String identifier = identifier1.toLowerCase(); + boolean custom = false; + if (identifier.endsWith("_process") + || (!Bukkit.isPrimaryThread() && plugin.getConfigFile().isAlwaysProcessAsyncPlaceholders())) { + forceProcess = true; + identifier = identifier.replaceAll("_process", ""); + } + if (identifier.endsWith("_nocache")) { + useCache = false; + identifier = identifier.replaceAll("_nocache", ""); + } + if (getCacheLevel().equals(PlaceholderCacheLevel.NONE)) { + useCache = false; + } + + if (identifier.startsWith("custom_")) { + custom = true; + identifier = identifier.replaceAll("custom_", ""); + } + + if (!custom || !plugin.getConfigFile().getCustomPlaceholderReturns().contains(identifier)) { + return getPlaceholderValue(p, identifier, javascript, forceProcess, useCache); + } + String str = getPlaceholderValue(p, identifier, javascript, true, useCache); + String returnStr = plugin.getConfigFile().getCustomPlaceholderReturns(identifier, str); + if (!returnStr.isEmpty()) { + return returnStr; + } + return str; + + } + + /** + * Get placeholder value for online player. + * @param p the player + * @param identifier the placeholder identifier + * @return the placeholder value + */ + public String getPlaceHolder(Player p, String identifier) { + if (plugin.getConfigFile().isUseJavascriptPlaceholders()) { + identifier = PlaceholderUtils.replaceJavascript(p, identifier); + } + return getPlaceHolder(p, identifier, false); + } + + /** + * Get placeholder value with options. + * @param p the offline player + * @param identifier the placeholder identifier + * @param javascript enable javascript processing + * @param forceProcess force processing of placeholder + * @param useCache use cached value if available + * @return the placeholder value + */ + public String getPlaceholderValue(OfflinePlayer p, String identifier, boolean javascript, boolean forceProcess, + boolean useCache) { + if (plugin.getConfigFile().isUseJavascriptPlaceholders() && javascript && p != null) { + identifier = PlaceholderUtils.replaceJavascript(p, identifier); + } + + if (!identifier.toLowerCase().endsWith("position")) { + for (NonPlayerPlaceHolder placeholder : nonPlayerPlaceholders) { + if (placeholder.matches(identifier)) { + String str = placeholder.placeholderRequest(identifier); + if (str != null) { + return str; + } + } + } + } + + if (p == null) { + return "no player"; + } + + VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(p); + if (useCache) { + if (!cachedPlaceholders.contains(identifier)) { + // not cached placeholder + if (!forceProcess) { + for (PlaceHolder placeholder : placeholders) { + if (placeholder.matches(identifier)) { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return ".."; + } + } + return "Not a valid placeholder"; + + } + } + } + + UUID uuid = user.getJavaUUID(); + + for (PlaceHolder placeholder : placeholders) { + try { + if (placeholder.matches(identifier)) { + if (placeholder instanceof CalculatingPlaceholder) { + if (!useCache) { + return placeholder.placeholderRequest(user, identifier); + } + CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; + if (placeholder.isUsesCache() && placeholder.isCached(identifier)) { + ConcurrentHashMap cache = placeholder.getCache().get(identifier); + if (cache.containsKey(uuid)) { + if (cPlaceholder.getCacheData().containsKey(uuid)) { + return cPlaceholder.placeholderRequest(user, identifier); + } + return cache.get(uuid); + } else if (!forceProcess) { + schedulePlaceholderCheck(user); + return "..."; + } + } + + if (forceProcess) { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier) + && !cachedPlaceholders.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return placeholder.placeholderRequest(user, identifier); + } else { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier) + && !cachedPlaceholders.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return "."; + } + } + if (!useCache) { + return placeholder.placeholderRequest(user, identifier); + } + if (placeholder.isUsesCache() && placeholder.isCached(identifier)) { + ConcurrentHashMap cache = placeholder.getCache().get(identifier); + + if (cache.containsKey(uuid)) { + return cache.get(uuid); + } else if (!forceProcess) { + schedulePlaceholderCheck(user); + return "..."; + } + } + + if (forceProcess) { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier) + && !cachedPlaceholders.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return placeholder.placeholderRequest(user, identifier); + } else { + if (getCacheLevel().shouldCache()) { + if (!placeholdersToSetCacheOn.contains(identifier) + && !cachedPlaceholders.contains(identifier)) { + placeholdersToSetCacheOn.add(identifier); + schedulePlaceholderCheck(user); + } + } + return "."; + } + } + } catch (Exception e) { + plugin.debug(e); + return "Error"; + } + } + + return "Not a valid placeholder"; + } + + /** + * Load all placeholders. + */ + public void load() { + placeholders.clear(); + nonPlayerPlaceholders.clear(); + + // older placeholders, might be removed in the future + placeholders.add(new PlaceHolder("total") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getTotal(TopVoter.Monthly)); + } + }.withDescription("Month total").updateDataKey("MonthTotal")); + + placeholders.add(new PlaceHolder("alltimetotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getTotal(TopVoter.AllTime)); + } + }.withDescription("Alltime total").updateDataKey("AllTimeTotal")); + + placeholders.add(new PlaceHolder("lastmonthtotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getLastMonthTotal()); + } + }.withDescription("Last month total").updateDataKey("LastMonthTotal")); + + // end of older placeholders + + placeholders.add(new PlaceHolder("CanLike_NameMC") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return user.hasClaimedNameMCLikeReward() ? "Complete" : "Incomplete"; + } + }.withDescription("Return Complete/Incomplete depending on whether the player has liked the server on NameMC") + .updateDataKey("ClaimedNameMCLikeReward")); + + placeholders.add(new PlaceHolder("DisableBroadcast") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getDisableBroadcast(); + } + }.withDescription("Returns true/false if user has broadcast disabled").updateDataKey("DisableBroadcast")); + + /* + * placeholders.add(new PlaceHolder("DisableReminders") { + * + * @Override public String placeholderRequest(VotingPluginUser user, String + * identifier) { if + * (plugin.getVoteReminding().getRemindersEnabled().containsKey(user.getJavaUUID + * ())) { if + * (!plugin.getVoteReminding().getRemindersEnabled().get(user.getJavaUUID()). + * booleanValue()) { + * + * return "True"; } } return "False"; } + * }.withDescription("Returns true/false if user has reminders disabled")); + */ + + for (final String identifier : plugin.getShopFile().getShopIdentifiers()) { + if (plugin.getShopFile().getShopIdentifierLimit(identifier) > 0) { + placeholders.add(new PlaceHolder("VoteShopLimit_" + identifier) { + + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + return "" + user.getVoteShopIdentifierLimit(identifier); + } + }.withDescription("User voteshop limit for " + identifier).updateDataKey("VoteShopLimit" + identifier)); + } + } + + for (final TopVoter top : TopVoter.values()) { + placeholders.add(new PlaceHolder("Total_" + top.toString()) { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getTotal(top)); + } + }.withDescription("User total for " + top.getName()).updateDataKey(top.getColumnName())); + } + + placeholders.add(new PlaceHolder("BestDailyTotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getHighestDailyTotal()); + } + }.withDescription("Best daily total").updateDataKey("HighestDailyTotal")); + + placeholders.add(new PlaceHolder("BestWeeklyTotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getHighestWeeklyTotal()); + } + }.withDescription("Best weekly total").updateDataKey("HighestWeeklyTotal")); + + placeholders.add(new PlaceHolder("BestMonthlyTotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getHighestMonthlyTotal()); + } + }.withDescription("Best monthly total").updateDataKey("HighestMonthlyTotal")); + + placeholders.add(new PlaceHolder("DailyVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getDayVoteStreak()); + } + }.withDescription("Current daily votestreak").updateDataKey("DayVoteStreak")); + + placeholders.add(new PlaceHolder("WeeklyVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getWeekVoteStreak()); + } + }.withDescription("Current weekly votestreak").updateDataKey("WeekVoteStreak")); + + placeholders.add(new PlaceHolder("MonthVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getMonthVoteStreak()); + } + }.withDescription("Current month votestreak").updateDataKey("MonthVoteStreak")); + + placeholders.add(new PlaceHolder("BestDailyVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getBestDayVoteStreak()); + } + }.withDescription("Best daily votestreak").updateDataKey("BestDayVoteStreak")); + + placeholders.add(new PlaceHolder("BestWeeklyVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getBestWeekVoteStreak()); + } + }.withDescription("Best weekly votestreak").updateDataKey("BestWeekVoteStreak")); + + placeholders.add(new PlaceHolder("BestMonthVoteStreak") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getBestMonthVoteStreak()); + } + }.withDescription("Best month votestreak").updateDataKey("BestMonthVoteStreak")); + + placeholders.add(new PlaceHolder("Points") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Integer.toString(user.getPoints()); + } + }.withDescription("User points").updateDataKey("Points")); + + placeholders.add(new PlaceHolder("Points_Format") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US); + return numberFormat.format(user.getPoints()); + } + }.withDescription("User points").updateDataKey("Points")); + + placeholders.add(new PlaceHolder("CanVote") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return Boolean.toString(user.canVoteAll()); + } + }.withDescription("Return true/false if player can vote on all sites").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("CanVoteSites") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getSitesNotVotedOn(); + } + }.withDescription("Return number of votesites available").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("Next_AnySite") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + if (user.canVoteAny()) { + return plugin.getConfigFile().getFormatCommandsVoteNextInfoCanVote(); + } + long smallest = -1; + HashMap times = new HashMap<>(); + for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) { + long t = user.voteNextDurationTime(site); + if (smallest == -1) { + smallest = t; + } + if (t < smallest) { + smallest = t; + } + times.put(t, site); + } + for (Entry entry : times.entrySet()) { + if (entry.getKey().longValue() == smallest) { + return user.voteCommandNextInfo(entry.getValue()); + } + } + + return "Error"; + } + }.withDescription("How long until user can vote on anysite").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("SitesAvailable") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getSitesNotVotedOn(); + } + }.withDescription("Get number of sites available to be voted on").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("SitesAvailableTotal") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getTotalNumberOfSites(); + } + }.withDescription("Get total number of sites available to be voted on")); + + for (final VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) { + placeholders.add(new CalculatingPlaceholder("Next_" + voteSite.getKey()) { + + @Override + public String placeholderDataRequest(VotingPluginUser user, String identifier) { + long time = user.getTime(voteSite); + return "" + time; + } + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + if (getCacheData().containsKey(user.getJavaUUID())) { + String data = getCacheData().get(user.getJavaUUID()); + if (!data.isEmpty()) { + long time = Long.valueOf(data); + return user.voteCommandNextInfo(voteSite, time); + } + } + return user.voteCommandNextInfo(voteSite); + } + }.withDescription("How long until user can vote on " + voteSite.getKey()).updateDataKey("LastVotes")); + placeholders.add(new PlaceHolder("Last_" + voteSite.getKey()) { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return user.voteCommandLastDuration(voteSite); + } + }.withDescription("How long ago user voted on " + voteSite.getKey()).updateDataKey("LastVotes")); + placeholders.add(new PlaceHolder("CanVote_" + voteSite.getKey()) { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.canVoteSite(voteSite); + } + }.withDescription("Whether or not player can vote on " + voteSite.getKey()).updateDataKey("LastVotes")); + } + + placeholders.add(new PlaceHolder("Top_All_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user top voter position")); + + placeholders.add(new PlaceHolder("EnoughPoints_") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[1])) { + return "invalid"; + } + int number = Integer.parseInt(identifier.split("_")[1]); + if (user.getPoints() >= number) { + return "true"; + } + return "false"; + } + }.withDescription("Return true/false if player has said points").updateDataKey("Points").useStartsWith()); + + // VoteMilestones placeholders (explicit per group, like + // VoteShopLimit_) + // Base/default (no group suffix) + placeholders.add(new PlaceHolder("VoteMilestoneNext") { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + Long next = plugin.getVoteMilestonesManager().getNextMilestoneValue("default", user); + return next == null ? "none" : Long.toString(next); + } + }.withDescription("Next VoteMilestone value for default group").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("VoteMilestoneLast") { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + Long last = plugin.getVoteMilestonesManager().getLastMilestoneValue("default", user); + return last == null ? "none" : Long.toString(last); + } + }.withDescription("Last achieved VoteMilestone value for default group").updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("VoteMilestoneVotesUntilNext") { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + return Long.toString(plugin.getVoteMilestonesManager().getVotesUntilNextMilestone("default", user)); + } + }.withDescription("Votes until next VoteMilestone for default group").updateDataKey("LastVotes")); + + Set groups = new HashSet<>(); + groups.add("default"); + + for (VoteMilestone m : plugin.getVoteMilestonesManager().getConfig().getMilestones().values()) { + String g = m.getGroupKey(); + if (g == null) + continue; + g = g.trim().toLowerCase(Locale.ROOT); + if (!g.isEmpty()) + groups.add(g); + } + + for (final String groupIdRaw : groups) { + final String groupId = (groupIdRaw == null || groupIdRaw.trim().isEmpty()) ? "default" : groupIdRaw.trim(); + + placeholders.add(new PlaceHolder("VoteMilestoneNext_" + groupId) { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + Long next = plugin.getVoteMilestonesManager().getNextMilestoneValue(groupId, user); + return next == null ? "none" : Long.toString(next); + } + }.withDescription("Next VoteMilestone value for group " + groupId).updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("VoteMilestoneLast_" + groupId) { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + Long last = plugin.getVoteMilestonesManager().getLastMilestoneValue(groupId, user); + return last == null ? "none" : Long.toString(last); + } + }.withDescription("Last achieved VoteMilestone value for group " + groupId).updateDataKey("LastVotes")); + + placeholders.add(new PlaceHolder("VoteMilestoneVotesUntilNext_" + groupId) { + @Override + public String placeholderRequest(VotingPluginUser user, String ident) { + return Long.toString(plugin.getVoteMilestonesManager().getVotesUntilNextMilestone(groupId, user)); + } + }.withDescription("Votes until next VoteMilestone for group " + groupId).updateDataKey("LastVotes")); + } + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_AllVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in top voter")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_All_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.AllTime).entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get username at postion in top voter")); + + placeholders.add(new PlaceHolder("Top_Month_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user's current top voter position")); + + if (plugin.getGui().isLastMonthGUI()) { + placeholders.add(new PlaceHolder("Top_LastMonth_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user top voter position for lastmonth")); + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_LastMonth_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user at position in last month top voter")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_LastMonthVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getLastMonthTopVoter().entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in last month top voter")); + + } + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Month_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get username at position in top voter")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_MonthVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Monthly).entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in top voter")); + + placeholders.add(new PlaceHolder("Top_Week_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user top voter position")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Week_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get username at postion in top voter")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_WeekVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Weekly).entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in top voter")); + + placeholders.add(new PlaceHolder("Top_Daily_Position") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + int num = 1; + UUID toMatch = UUID.fromString(user.getUUID()); + for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { + if (entry.getKey().getUuid().equals(toMatch)) { + return "" + num; + } + num++; + } + return ""; + } + }.withDescription("Get user top voter position")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_Daily_") { + + @Override + public String placeholderRequest(String identifier) { + if (!MessageAPI.isInt(identifier.split("_")[2])) { + return "invalid"; + } + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { + if (num == number) { + return entry.getKey().getPlayerName(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get username at postion in top voter")); + + placeholders.add(new PlaceHolder("VotePartyContributedVotes") { + + @Override + public String placeholderRequest(VotingPluginUser user, String identifier) { + return "" + user.getVotePartyVotes(); + } + }.useStartsWith().withDescription("See vote party placeholders contributed").updateDataKey("VotePartyVotes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("Top_DailyVotes_") { + + @Override + public String placeholderRequest(String identifier) { + int num = 1; + int number = Integer.parseInt(identifier.split("_")[2]); + for (Entry entry : plugin.getTopVoter(TopVoter.Daily).entrySet()) { + if (num == number) { + return "" + entry.getValue().intValue(); + } + num++; + } + return ""; + } + }.useStartsWith().withDescription("Get user votes at position in top voter")); + + // non players + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesCurrent") { + + @Override + public String placeholderRequest(String identifier) { + return Integer.toString(plugin.getVoteParty().getTotalVotes()); + } + }.withDescription("Current amount of voteparty votes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesNeeded") { + + @Override + public String placeholderRequest(String identifier) { + return Integer.toString(plugin.getVoteParty().getNeededVotes()); + } + }.withDescription("Voteparty votes needed")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("VotePartyVotesRequired") { + + @Override + public String placeholderRequest(String identifier) { + return Integer.toString(plugin.getVoteParty().getVotesRequired()); + } + }.withDescription("Amount of votes needed for voteparty")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesCurrent") { + + @Override + public String placeholderRequest(String identifier) { + if (plugin.getBackendProxyHandler() != null) { + return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyCurrent()); + } + return "-1"; + } + }.withDescription("Current amount of bungee voteparty votes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesNeeded") { + + @Override + public String placeholderRequest(String identifier) { + if (plugin.getBackendProxyHandler() != null) { + return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyRequired() + - plugin.getBackendProxyHandler().getBungeeVotePartyCurrent()); + } + return "-1"; + } + }.withDescription("Voteparty bungee votes needed")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("BungeeVotePartyVotesRequired") { + + @Override + public String placeholderRequest(String identifier) { + if (plugin.getBackendProxyHandler() != null) { + return Integer.toString(plugin.getBackendProxyHandler().getBungeeVotePartyRequired()); + } + return "-1"; + } + }.withDescription("Amount of votes needed for bungee voteparty")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalMonthTotal") { + + @Override + public String placeholderRequest(String identifier) { + int total = 0; + for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Monthly).values()) { + total += num; + } + return Integer.toString(total); + } + }.withDescription("Global month total")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalAllTimeTotal") { + + @Override + public String placeholderRequest(String identifier) { + int total = 0; + for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.AllTime).values()) { + total += num; + } + return Integer.toString(total); + } + }.withDescription("Global alltime total")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalWeeklyTotal") { + + @Override + public String placeholderRequest(String identifier) { + int total = 0; + for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Weekly).values()) { + total += num; + } + return Integer.toString(total); + } + }.withDescription("Global weekly total")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("GlobalDailyTotal") { + + @Override + public String placeholderRequest(String identifier) { + int total = 0; + for (int num : VotingPluginMain.plugin.getTopVoter(TopVoter.Daily).values()) { + total += num; + } + return Integer.toString(total); + } + }.withDescription("Global daily total")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilDayReset") { + + @Override + public String placeholderRequest(String identifier) { + LocalDateTime now = plugin.getTimeChecker().getTime(); + LocalDateTime offsetoclocktoday = plugin.getTimeChecker().getTime().withHour(0).withMinute(0); + LocalDateTime offsetoclocktomorrow = plugin.getTimeChecker().getTime().plusDays(1).withHour(0) + .withMinute(0); + + String timeMsg = "%hours% Hours %minutes% Minutes"; + Duration dur = null; + if (!now.isBefore(offsetoclocktoday)) { + dur = Duration.between(now, offsetoclocktomorrow); + + } else { + dur = Duration.between(now, offsetoclocktoday); + } + int diffHours = (int) (dur.getSeconds() / (60 * 60)); + long diffMinutes = dur.getSeconds() / 60 - diffHours * 60; + + if (diffHours < 0) { + diffHours = diffHours * -1; + } + if (diffHours >= 24) { + diffHours = diffHours - 24; + } + if (diffMinutes < 0) { + diffMinutes = diffMinutes * -1; + } + + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); + return timeMsg; + + } + }.withDescription("Time until plugin time day changes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilWeekReset") { + + @Override + public String placeholderRequest(String identifier) { + LocalDateTime now = plugin.getTimeChecker().getTime().plusDays(plugin.getOptions().getTimeWeekOffSet()); + LocalDateTime newWeek = plugin.getTimeChecker().getTime().withHour(0).withMinute(0); + + TemporalField woy = WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear(); + int weekNumber = newWeek.get(woy); + int newWeekNumber = weekNumber; + + while (weekNumber == newWeekNumber) { + newWeek = newWeek.plusDays(1); + newWeekNumber = newWeek.get(woy); + } + + String timeMsg = "%days% Days %hours% Hours %minutes% Minutes"; + Duration dur = Duration.between(now, newWeek); + + int diffDays = (int) (dur.getSeconds() / (60 * 60 * 24)); + int diffHours = (int) (dur.getSeconds() / (60 * 60) - diffDays * 24); + long diffMinutes = dur.getSeconds() / 60 - diffHours * 60 - diffDays * 24 * 60; + + if (diffHours < 0) { + diffHours = diffHours * -1; + } + if (diffHours >= 24) { + diffHours = diffHours - 24; + } + if (diffMinutes < 0) { + diffMinutes = diffMinutes * -1; + } + + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%days%", Integer.toString(diffDays)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); + return timeMsg; + + } + }.withDescription("Time until plugin time week changes")); + + nonPlayerPlaceholders.add(new NonPlayerPlaceHolder("TimeUntilMonthReset") { + + @Override + public String placeholderRequest(String identifier) { + LocalDateTime now = plugin.getTimeChecker().getTime(); + LocalDateTime newMonth = plugin.getTimeChecker().getTime().plusMonths(1).withDayOfMonth(1).withHour(0) + .withMinute(0); + + String timeMsg = "%days% Days %hours% Hours %minutes% Minutes"; + Duration dur = Duration.between(now, newMonth); + + int diffDays = (int) (dur.getSeconds() / (60 * 60 * 24)); + int diffHours = (int) (dur.getSeconds() / (60 * 60) - diffDays * 24); + long diffMinutes = dur.getSeconds() / 60 - diffHours * 60 - diffDays * 24 * 60; + + if (diffHours < 0) { + diffHours = diffHours * -1; + } + if (diffHours >= 24) { + diffHours = diffHours - 24; + } + if (diffMinutes < 0) { + diffMinutes = diffMinutes * -1; + } + + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%days%", Integer.toString(diffDays)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%hours%", Integer.toString(diffHours)); + timeMsg = MessageAPI.replaceIgnoreCase(timeMsg, "%minutes%", Long.toString(diffMinutes)); + return timeMsg; + + } + }.withDescription("Time until plugin time month changes")); + + Set placeholdersSet = new HashSet<>(); + placeholdersSet.addAll(plugin.getConfigFile().getCachedPlaceholders()); + if (getCacheLevel().equals(PlaceholderCacheLevel.AUTO)) { + placeholdersSet.addAll(plugin.getServerData().getAutoCachedPlaceholder()); + } + + for (String toCache : placeholdersSet) { + if (toCache.startsWith("votingplugin")) { + toCache = toCache.substring("votingplugin_".length()); + } + for (NonPlayerPlaceHolder placeholder : nonPlayerPlaceholders) { + if (placeholder.matches(toCache)) { + placeholder.setUseCache(true, toCache); + cachedPlaceholders.add(toCache); + plugin.extraDebug("Caching placeholder " + toCache); + } + } + + for (PlaceHolder placeholder : placeholders) { + if (placeholder.matches(toCache)) { + placeholder.setUseCache(true, toCache); + cachedPlaceholders.add(toCache); + plugin.extraDebug("Caching placeholder " + toCache); + } + } + } + + plugin.getUserManager().getUserDataChange().add(new UserDataChanged() { + + @Override + public void onChange(AdvancedCoreUser user, String... keys) { + VotingPluginUser vpUser = plugin.getVotingPluginUserManager().getVotingPluginUser(user); + if (!vpUser.isCached()) { + vpUser.userDataFetechMode(UserDataFetchMode.NO_CACHE); + } + for (PlaceHolder placeholder : placeholders) { + if (placeholder.isUsesCache()) { + if (placeholder.isCached(placeholder.getIdentifier(), user.getJavaUUID()) + || !getCacheLevel().onlineOnly() || user.isOnline()) { + if (placeholder instanceof CalculatingPlaceholder) { + CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; + if (placeholder.isUsesCache()) { + for (String key : keys) { + if (placeholder.getUpdateDataKey().equalsIgnoreCase(key)) { + for (String ident : placeholder.getCache().keySet()) { + String value = placeholder.placeholderRequest(vpUser, ident); + cPlaceholder.getCacheData().put(user.getJavaUUID(), + cPlaceholder.placeholderDataRequest(vpUser, ident)); + placeholder.getCache().get(ident).put(vpUser.getJavaUUID(), value); + plugin.devDebug("Updated calculating placeholder cache for " + + vpUser.getUUID() + " on " + key + " with " + value); + } + } + } + } + } else { + if (placeholder.isUsesCache()) { + for (String key : keys) { + if (placeholder.getUpdateDataKey().equalsIgnoreCase(key)) { + for (String ident : placeholder.getCache().keySet()) { + String value = placeholder.placeholderRequest(vpUser, ident); + placeholder.getCache().get(ident).put(vpUser.getJavaUUID(), value); + plugin.devDebug("Updated placeholder cache for " + vpUser.getUUID() + + " on " + key + " with " + value); + + } + + } + } + } + } + } + } + } + } + }); + } + + /** + * Handle player logout. + * @param user the voting plugin user + */ + public void onLogout(VotingPluginUser user) { + if (plugin.getPlaceholders().getCacheLevel().onlineOnly()) { + for (PlaceHolder placeholder : placeholders) { + if (placeholder.isUsesCache()) { + placeholder.clearCachePlayer(user.getJavaUUID()); + } + } + } + } + + /** + * Update all placeholders. + */ + public void onUpdate() { + checkNonCachedPlaceholders(); + for (Player p : Bukkit.getOnlinePlayers()) { + onUpdate(plugin.getVotingPluginUserManager().getVotingPluginUser(p), true); + } + /* + * for (NonPlayerPlaceHolder placeholder : + * nonPlayerPlaceholders) { if (placeholder.isUsesCache()) { for (String ident : + * placeholder.getCache().keySet()) { if (ident != null) { String str = + * placeholder.placeholderRequest(ident); if (str != null) { + * placeholder.getCache().put(ident, str); } } else { + * plugin.debug("ident null: " + placeholder.getIdentifier()); } } } } + */ + + } + + /** + * Update placeholders for specific user. + * @param user the voting plugin user + * @param login whether this is a login update + */ + public void onUpdate(VotingPluginUser user, boolean login) { + for (PlaceHolder placeholder : placeholders) { + if (placeholder.isUsesCache()) { + if (placeholder.isCached(placeholder.getIdentifier(), user.getJavaUUID()) || login) { + if (placeholder instanceof CalculatingPlaceholder) { + + CalculatingPlaceholder cPlaceholder = (CalculatingPlaceholder) placeholder; + if (placeholder.isUsesCache()) { + for (String ident : placeholder.getCache().keySet()) { + cPlaceholder.getCacheData().put(user.getJavaUUID(), + cPlaceholder.placeholderDataRequest(user, ident)); + placeholder.getCache().get(ident).put(user.getJavaUUID(), + placeholder.placeholderRequest(user, ident)); + } + + } + } else { + if (placeholder.isUsesCache()) { + for (String ident : placeholder.getCache().keySet()) { + placeholder.getCache().get(ident).put(user.getJavaUUID(), + placeholder.placeholderRequest(user, ident)); + } + } + } + } + } + } + } + + /** + * Handle vote party update. + */ + public void onVotePartyUpdate() { + /* + * for (NonPlayerPlaceHolder placeholder : + * nonPlayerPlaceholders) { if (placeholder.isUsesCache()) { if + * (placeholder.getIdentifier().startsWith("VoteParty")) { for (String ident : + * placeholder.getCache().keySet()) { placeholder.getCache().put(ident, + * placeholder.placeholderRequest(ident)); } } } } + */ + } + + /** + * Reload placeholders. + */ + public void reload() { + cacheLevel = plugin.getConfigFile().getPlaceholderCacheLevel(); + onUpdate(); + if (!cacheLevel.equals(PlaceholderCacheLevel.NONE)) { + for (Player player : Bukkit.getOnlinePlayers()) { + onUpdate(plugin.getVotingPluginUserManager().getVotingPluginUser(player), player.isOnline()); + } + } + } + + /** + * Schedule placeholder check for user. + * @param user the voting plugin user + */ + public void schedulePlaceholderCheck(VotingPluginUser user) { + plugin.getTimer().execute(new Runnable() { + + @Override + public void run() { + checkNonCachedPlaceholders(); + onUpdate(user, user.isOnline()); + } + }); + } +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java index 1768edc18e..950c66d932 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/SignHandler.java @@ -20,6 +20,7 @@ import lombok.Getter; import lombok.Setter; + public class SignHandler { @Getter diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/Signs.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/Signs.java index 6b39199cea..7d540bab40 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/Signs.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/signs/Signs.java @@ -1,87 +1,88 @@ -package com.bencodez.votingplugin.signs; - -import java.util.ArrayList; - -import org.bukkit.Location; - -import com.bencodez.votingplugin.VotingPluginMain; - -import lombok.Getter; -import lombok.Setter; -public class Signs { - private VotingPluginMain plugin; - - @Getter - @Setter - private ArrayList signs; - - /** - * Constructs a new Signs manager. - * - * @param plugin the main plugin instance - */ - public Signs(VotingPluginMain plugin) { - this.plugin = plugin; - this.signs = new ArrayList<>(); - } - - /** - * Gets the sign from location. - * - * @param loc the loc - * @return the sign from location - */ - public String getSignFromLocation(Location loc) { - for (String sign : plugin.getServerData().getSigns()) { - if (plugin.getServerData().getSignLocation(sign).equals(loc)) { - return sign; - } - } - - return null; - } - - /** - * Load signs. - */ - public void loadSigns() { - setSigns(new ArrayList<>()); - for (String sign : plugin.getServerData().getSigns()) { - // plugin.getLogger().info("Loading sign " + sign); - getSigns().add(new SignHandler(plugin, sign, plugin.getServerData().getSignLocation(sign), - plugin.getServerData().getSignSkullLocation(sign), plugin.getServerData().getSignData(sign), - plugin.getServerData().getSignPosition(sign))); - } - } - - /** - * Store signs. - */ - public void storeSigns() { - for (SignHandler sign : getSigns()) { - sign.storeSign(); - } - } - - /** - * Update signs. - */ - public void updateSigns() { - int time = 0; - for (int i = getSigns().size() - 1; i >= 0; i--) { - if (!getSigns().get(i).isValid()) { - plugin.debug( - "Sign " + i + " invalid, removing from data: " + getSigns().get(i).getLocation().toString()); - getSigns().get(i).removeSign(); - getSigns().remove(i); - } else { - getSigns().get(i).updateLines(); - getSigns().get(i).updateSign(time); - time += 1; - } - } - - plugin.debug(getSigns().size() + " Signs updated"); - } - -} +package com.bencodez.votingplugin.signs; + +import java.util.ArrayList; + +import org.bukkit.Location; + +import com.bencodez.votingplugin.VotingPluginMain; + +import lombok.Getter; +import lombok.Setter; + +public class Signs { + private VotingPluginMain plugin; + + @Getter + @Setter + private ArrayList signs; + + /** + * Constructs a new Signs manager. + * + * @param plugin the main plugin instance + */ + public Signs(VotingPluginMain plugin) { + this.plugin = plugin; + this.signs = new ArrayList<>(); + } + + /** + * Gets the sign from location. + * + * @param loc the loc + * @return the sign from location + */ + public String getSignFromLocation(Location loc) { + for (String sign : plugin.getServerData().getSigns()) { + if (plugin.getServerData().getSignLocation(sign).equals(loc)) { + return sign; + } + } + + return null; + } + + /** + * Load signs. + */ + public void loadSigns() { + setSigns(new ArrayList<>()); + for (String sign : plugin.getServerData().getSigns()) { + // plugin.getLogger().info("Loading sign " + sign); + getSigns().add(new SignHandler(plugin, sign, plugin.getServerData().getSignLocation(sign), + plugin.getServerData().getSignSkullLocation(sign), plugin.getServerData().getSignData(sign), + plugin.getServerData().getSignPosition(sign))); + } + } + + /** + * Store signs. + */ + public void storeSigns() { + for (SignHandler sign : getSigns()) { + sign.storeSign(); + } + } + + /** + * Update signs. + */ + public void updateSigns() { + int time = 0; + for (int i = getSigns().size() - 1; i >= 0; i--) { + if (!getSigns().get(i).isValid()) { + plugin.debug( + "Sign " + i + " invalid, removing from data: " + getSigns().get(i).getLocation().toString()); + getSigns().get(i).removeSign(); + getSigns().remove(i); + } else { + getSigns().get(i).updateLines(); + getSigns().get(i).updateSign(time); + time += 1; + } + } + + plugin.debug(getSigns().size() + " Signs updated"); + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewards.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewards.java index f93a99ddf1..ed50217205 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewards.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/specialrewards/SpecialRewards.java @@ -1,116 +1,117 @@ -package com.bencodez.votingplugin.specialrewards; - -import java.util.Set; -import java.util.UUID; - -import org.bukkit.Bukkit; - -import com.bencodez.advancedcore.api.rewards.RewardBuilder; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.events.PlayerSpecialRewardEvent; -import com.bencodez.votingplugin.events.SpecialRewardType; -import com.bencodez.votingplugin.user.VotingPluginUser; -public class SpecialRewards { - - private VotingPluginMain plugin; - - /** - * Constructs a new SpecialRewards handler. - * - * @param plugin the main plugin instance - */ - public SpecialRewards(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * Checks and processes vote streak rewards for a user. - * - * @param voteUUID the vote UUID - * @param user the voting user - * @param type the streak type (day/week/month) - * @param forceBungee whether to force bungee mode - * @return true if a reward was given - */ - public boolean checkVoteStreak(UUID voteUUID, VotingPluginUser user, String type, boolean forceBungee) { - boolean gotReward = false; - - Set streaks = plugin.getSpecialRewardsConfig().getVoteStreakVotes(type); - for (String streak : streaks) { - boolean multiple = false; - if (streak.contains("-")) { - // multiple - multiple = true; - - } - String s = streak.replaceAll("-", ""); - - plugin.debug("Streak: " + streak + " multiple: " + multiple); - if (MessageAPI.isInt(s)) { - int streakRequired = Integer.parseInt(s); - if (streakRequired != 0) { - if (plugin.getSpecialRewardsConfig().getVoteStreakRewardEnabled(type, streak) - && plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(), - plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath(type, "" + streak))) { - int curStreak = 0; - if (type.equalsIgnoreCase("day")) { - curStreak = user.getDayVoteStreak(); - } else if (type.equalsIgnoreCase("week")) { - curStreak = user.getWeekVoteStreak(); - } else if (type.equalsIgnoreCase("month")) { - curStreak = user.getMonthVoteStreak(); - } - if (!multiple) { - if (curStreak == streakRequired) { - giveVoteStreakReward(voteUUID, user, user.isOnline(), type, "" + streakRequired, - curStreak, forceBungee); - gotReward = true; - plugin.debug( - user.getPlayerName() + " got VoteStreak " + streakRequired + " for " + type); - } - } else { - if (curStreak != 0 && curStreak % streakRequired == 0) { - giveVoteStreakReward(voteUUID, user, user.isOnline(), type, streak, curStreak, - forceBungee); - gotReward = true; - plugin.debug( - user.getPlayerName() + " got VoteStreak " + streakRequired + "* for " + type); - } - } - } - } - } - - } - - return gotReward; - - } - - /** - * Gives a vote streak reward to a user. - * - * @param voteUUID the vote UUID - * @param user the voting user - * @param online whether the user is online - * @param type the streak type - * @param string the streak value - * @param votes the current streak count - * @param forceBungee whether to force bungee mode - */ - public void giveVoteStreakReward(UUID voteUUID, VotingPluginUser user, boolean online, String type, String string, - int votes, boolean forceBungee) { - PlayerSpecialRewardEvent event = new PlayerSpecialRewardEvent(user, - SpecialRewardType.VOTESTREAK.setType(type).setAmount(votes), voteUUID); - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - return; - } - new RewardBuilder(plugin.getSpecialRewardsConfig().getData(), - plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath(type, string)).setOnline(online) - .withPlaceHolder("Type", type).setServer(forceBungee).withPlaceHolder("Streak", "" + votes).send(user); - } - -} +package com.bencodez.votingplugin.specialrewards; + +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; + +import com.bencodez.advancedcore.api.rewards.RewardBuilder; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.events.PlayerSpecialRewardEvent; +import com.bencodez.votingplugin.events.SpecialRewardType; +import com.bencodez.votingplugin.user.VotingPluginUser; + +public class SpecialRewards { + + private VotingPluginMain plugin; + + /** + * Constructs a new SpecialRewards handler. + * + * @param plugin the main plugin instance + */ + public SpecialRewards(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * Checks and processes vote streak rewards for a user. + * + * @param voteUUID the vote UUID + * @param user the voting user + * @param type the streak type (day/week/month) + * @param forceBungee whether to force bungee mode + * @return true if a reward was given + */ + public boolean checkVoteStreak(UUID voteUUID, VotingPluginUser user, String type, boolean forceBungee) { + boolean gotReward = false; + + Set streaks = plugin.getSpecialRewardsConfig().getVoteStreakVotes(type); + for (String streak : streaks) { + boolean multiple = false; + if (streak.contains("-")) { + // multiple + multiple = true; + + } + String s = streak.replaceAll("-", ""); + + plugin.debug("Streak: " + streak + " multiple: " + multiple); + if (MessageAPI.isInt(s)) { + int streakRequired = Integer.parseInt(s); + if (streakRequired != 0) { + if (plugin.getSpecialRewardsConfig().getVoteStreakRewardEnabled(type, streak) + && plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(), + plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath(type, "" + streak))) { + int curStreak = 0; + if (type.equalsIgnoreCase("day")) { + curStreak = user.getDayVoteStreak(); + } else if (type.equalsIgnoreCase("week")) { + curStreak = user.getWeekVoteStreak(); + } else if (type.equalsIgnoreCase("month")) { + curStreak = user.getMonthVoteStreak(); + } + if (!multiple) { + if (curStreak == streakRequired) { + giveVoteStreakReward(voteUUID, user, user.isOnline(), type, "" + streakRequired, + curStreak, forceBungee); + gotReward = true; + plugin.debug( + user.getPlayerName() + " got VoteStreak " + streakRequired + " for " + type); + } + } else { + if (curStreak != 0 && curStreak % streakRequired == 0) { + giveVoteStreakReward(voteUUID, user, user.isOnline(), type, streak, curStreak, + forceBungee); + gotReward = true; + plugin.debug( + user.getPlayerName() + " got VoteStreak " + streakRequired + "* for " + type); + } + } + } + } + } + + } + + return gotReward; + + } + + /** + * Gives a vote streak reward to a user. + * + * @param voteUUID the vote UUID + * @param user the voting user + * @param online whether the user is online + * @param type the streak type + * @param string the streak value + * @param votes the current streak count + * @param forceBungee whether to force bungee mode + */ + public void giveVoteStreakReward(UUID voteUUID, VotingPluginUser user, boolean online, String type, String string, + int votes, boolean forceBungee) { + PlayerSpecialRewardEvent event = new PlayerSpecialRewardEvent(user, + SpecialRewardType.VOTESTREAK.setType(type).setAmount(votes), voteUUID); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + return; + } + new RewardBuilder(plugin.getSpecialRewardsConfig().getData(), + plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath(type, string)).setOnline(online) + .withPlaceHolder("Type", type).setServer(forceBungee).withPlaceHolder("Streak", "" + votes).send(user); + } + +} diff --git a/VotingPlugin/src/main/java/com/bencodez/votingplugin/updater/CheckUpdate.java b/VotingPlugin/src/main/java/com/bencodez/votingplugin/updater/CheckUpdate.java index f9be83a629..1f592a9dc7 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/updater/CheckUpdate.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/updater/CheckUpdate.java @@ -1,97 +1,98 @@ -package com.bencodez.votingplugin.updater; - -import java.util.Timer; -import java.util.TimerTask; - -import com.bencodez.simpleapi.updater.Updater; -import com.bencodez.votingplugin.VotingPluginMain; -public class CheckUpdate { - - private VotingPluginMain plugin; - - /** - * Constructs a new CheckUpdate instance. - * - * @param plugin the main plugin instance - */ - public CheckUpdate(VotingPluginMain plugin) { - this.plugin = plugin; - } - - /** - * Check update. - */ - public void checkUpdate() { - if (plugin.getConfigFile().isDisableUpdateChecking() - || plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { - return; - } - plugin.setUpdater(new Updater(plugin, 15358, false)); - final Updater.UpdateResult result = plugin.getUpdater().getResult(); - switch (result) { - case FAIL_SPIGOT: { - plugin.getLogger().info("Failed to check for update for " + plugin.getName() + "!"); - break; - } - case NO_UPDATE: { - plugin.getLogger().info(plugin.getName() + " is up to date! Version: " + plugin.getUpdater().getVersion()); - break; - } - case UPDATE_AVAILABLE: { - plugin.getLogger().info(plugin.getName() + " has an update available! Your Version: " - + plugin.getDescription().getVersion() + " New Version: " + plugin.getUpdater().getVersion()); - break; - } - default: { - break; - } - } - } - - /** - * Performs a basic update check without downloading. - */ - public void checkUpdateBasic() { - if (plugin.getConfigFile().isDisableUpdateChecking()) { - return; - } - plugin.setUpdater(new Updater(plugin, 15358, false)); - final Updater.UpdateResult result = plugin.getUpdater().getResult(); - switch (result) { - case UPDATE_AVAILABLE: { - plugin.getLogger().info(plugin.getName() + " has an update available! Your Version: " - + plugin.getDescription().getVersion() + " New Version: " + plugin.getUpdater().getVersion()); - break; - } - default: { - break; - } - } - } - - /** - * Start up. - */ - public void startUp() { - if (plugin.getConfigFile().isDisableUpdateChecking() - || plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { - return; - } - plugin.getBukkitScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { - - @Override - public void run() { - checkUpdate(); - new Timer().schedule(new TimerTask() { - - @Override - public void run() { - checkUpdateBasic(); - } - }, 1000 * 60 * 1200, 1000 * 60 * 1200); - - } - }, 10); - } - -} +package com.bencodez.votingplugin.updater; + +import java.util.Timer; +import java.util.TimerTask; + +import com.bencodez.simpleapi.updater.Updater; +import com.bencodez.votingplugin.VotingPluginMain; + +public class CheckUpdate { + + private VotingPluginMain plugin; + + /** + * Constructs a new CheckUpdate instance. + * + * @param plugin the main plugin instance + */ + public CheckUpdate(VotingPluginMain plugin) { + this.plugin = plugin; + } + + /** + * Check update. + */ + public void checkUpdate() { + if (plugin.getConfigFile().isDisableUpdateChecking() + || plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { + return; + } + plugin.setUpdater(new Updater(plugin, 15358, false)); + final Updater.UpdateResult result = plugin.getUpdater().getResult(); + switch (result) { + case FAIL_SPIGOT: { + plugin.getLogger().info("Failed to check for update for " + plugin.getName() + "!"); + break; + } + case NO_UPDATE: { + plugin.getLogger().info(plugin.getName() + " is up to date! Version: " + plugin.getUpdater().getVersion()); + break; + } + case UPDATE_AVAILABLE: { + plugin.getLogger().info(plugin.getName() + " has an update available! Your Version: " + + plugin.getDescription().getVersion() + " New Version: " + plugin.getUpdater().getVersion()); + break; + } + default: { + break; + } + } + } + + /** + * Performs a basic update check without downloading. + */ + public void checkUpdateBasic() { + if (plugin.getConfigFile().isDisableUpdateChecking()) { + return; + } + plugin.setUpdater(new Updater(plugin, 15358, false)); + final Updater.UpdateResult result = plugin.getUpdater().getResult(); + switch (result) { + case UPDATE_AVAILABLE: { + plugin.getLogger().info(plugin.getName() + " has an update available! Your Version: " + + plugin.getDescription().getVersion() + " New Version: " + plugin.getUpdater().getVersion()); + break; + } + default: { + break; + } + } + } + + /** + * Start up. + */ + public void startUp() { + if (plugin.getConfigFile().isDisableUpdateChecking() + || plugin.getDescription().getVersion().endsWith("SNAPSHOT")) { + return; + } + plugin.getBukkitScheduler().runTaskLaterAsynchronously(plugin, new Runnable() { + + @Override + public void run() { + checkUpdate(); + new Timer().schedule(new TimerTask() { + + @Override + public void run() { + checkUpdateBasic(); + } + }, 1000 * 60 * 1200, 1000 * 60 * 1200); + + } + }, 10); + } + +} 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 0fff9d62df..d67ec83cad 100644 --- a/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSite.java +++ b/VotingPlugin/src/main/java/com/bencodez/votingplugin/votesites/VoteSite.java @@ -1,202 +1,203 @@ -package com.bencodez.votingplugin.votesites; - -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; - -import com.bencodez.advancedcore.api.item.ItemBuilder; -import com.bencodez.advancedcore.api.messages.PlaceholderUtils; -import com.bencodez.advancedcore.api.rewards.RewardBuilder; -import com.bencodez.simpleapi.array.ArrayUtils; -import com.bencodez.simpleapi.messages.MessageAPI; -import com.bencodez.simpleapi.time.ParsedDuration; -import com.bencodez.votingplugin.VotingPluginMain; -import com.bencodez.votingplugin.user.VotingPluginUser; - -import lombok.Getter; -import lombok.Setter; -public class VoteSite { - @Getter - @Setter - private String displayName; - - @Getter - @Setter - private boolean enabled; - - @Getter - @Setter - private boolean giveOffline; - - @Getter - @Setter - private boolean hidden; - - @Getter - @Setter - private boolean ignoreCanVote; - - @Setter - private ConfigurationSection item; - - @Getter - @Setter - private String key; - - private VotingPluginMain plugin; - - @Getter - @Setter - private int priority; - - @Getter - @Setter - private String serviceSite; - - @Getter - @Setter - private int voteDelayDailyHour; - - @Getter - @Setter - private boolean voteDelayDaily; - - @Getter - private ParsedDuration voteDelay; - - @Setter - private String voteURL; - - @Getter - @Setter - private String permissionToView; - - @Getter - @Setter - private boolean waitUntilVoteDelay; - - public VoteSite(VotingPluginMain plugin, String siteName) { - this.plugin = plugin; - key = siteName.replace(".", "_"); - init(); - } - - /** - * @return the item - */ - public ItemBuilder getItem() { - if (item == null) { - plugin.getLogger().warning("Invalid display item section in site: " + key); - return new ItemBuilder(Material.STONE, 1).setName("&cInvalid display item for site: " + key) - .setLore("&cInvalid display item for site: " + key); - } - return new ItemBuilder(item); - } - - public ConfigurationSection getSiteData() { - return plugin.getConfigVoteSites().getData(key); - } - - public String getVoteURL() { - return getVoteURL(true); - } - - public String getVoteURL(boolean json) { - if (!plugin.getConfigFile().isFormatCommandsVoteForceLinks() || !json || MessageAPI.containsJson(voteURL)) { - return voteURL; - } - if (!voteURL.startsWith("http")) { - return "[Text=\"" + voteURL + "\",url=\"http://" + voteURL + "\"]"; - } - return "[Text=\"" + voteURL + "\",url=\"" + voteURL + "\"]"; - } - - public String getVoteURLJsonStrip() { - String url = ChatColor - .stripColor(MessageAPI.colorize(PlaceholderUtils.parseJson(getVoteURL(false)).toPlainText())); - if (!url.startsWith("http")) { - if (!url.startsWith("www.")) { - url = "https://www." + url; - } else { - url = "https://" + url; - } - } - return url; - } - - public void giveRewards(VotingPluginUser user, boolean online, boolean bungee) { - new RewardBuilder(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getEverySiteRewardPath()) - .setOnline(online).withPlaceHolder("ServiceSite", getServiceSite()) - .withPlaceHolder("SiteName", getDisplayName()).withPlaceHolder("VoteDelay", "" + getVoteDelay()) - .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); - - new RewardBuilder(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getRewardsPath(key)) - .setOnline(online).withPlaceHolder("ServiceSite", getServiceSite()) - .withPlaceHolder("SiteName", getDisplayName()).withPlaceHolder("VoteDelay", "" + getVoteDelay()) - .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); - - } - - /** - * 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)); - } - - /** - * Inits the. - */ - public void init() { - setVoteURL(plugin.getConfigVoteSites().getVoteURL(key)); - setServiceSite(plugin.getConfigVoteSites().getServiceSite(key)); - this.voteDelay = plugin.getConfigVoteSites().getVoteDelay(key); - setEnabled(plugin.getConfigVoteSites().getVoteSiteEnabled(key)); - setPriority(plugin.getConfigVoteSites().getPriority(key)); - displayName = plugin.getConfigVoteSites().getDisplayName(key); - if (displayName == null || displayName.equals("")) { - displayName = key; - } - item = plugin.getConfigVoteSites().getItem(key); - voteDelayDaily = plugin.getConfigVoteSites().getVoteSiteResetVoteDelayDaily(key); - giveOffline = plugin.getConfigVoteSites().getVoteSiteGiveOffline(key); - waitUntilVoteDelay = plugin.getConfigVoteSites().getWaitUntilVoteDelay(key); - voteDelayDailyHour = plugin.getConfigVoteSites().getVoteDelayDailyHour(key); - hidden = plugin.getConfigVoteSites().getVoteSiteHidden(key); - ignoreCanVote = plugin.getConfigVoteSites().getVoteSiteIgnoreCanVote(key); - permissionToView = plugin.getConfigVoteSites().getPermissionToView(key); - } - - public boolean isVaidServiceSite() { - return ArrayUtils.containsIgnoreCase(plugin.getServerData().getServiceSites(), getServiceSite()); - } - - public String loadingDebug() { - String str = "Loading votesite key: " + key; - str += ", Displayname: " + displayName; - str += ", VoteDelay: " + getVoteDelay(); - str += ", VoteDelayDaily: " + isVoteDelayDaily(); - str += ", IsWaitUntilVoteDelay: " + isWaitUntilVoteDelay(); - str += ", ServiceSite: " + getServiceSite(); - str += ", VoteDelayDailyHour:" + getVoteDelayDailyHour(); - str += ", Url: " + getVoteURL(); - str += ", IgnoreCanVote: " + isIgnoreCanVote(); - str += ", Hidden: " + isHidden(); - return str; - } - -} +package com.bencodez.votingplugin.votesites; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; + +import com.bencodez.advancedcore.api.item.ItemBuilder; +import com.bencodez.advancedcore.api.messages.PlaceholderUtils; +import com.bencodez.advancedcore.api.rewards.RewardBuilder; +import com.bencodez.simpleapi.array.ArrayUtils; +import com.bencodez.simpleapi.messages.MessageAPI; +import com.bencodez.simpleapi.time.ParsedDuration; +import com.bencodez.votingplugin.VotingPluginMain; +import com.bencodez.votingplugin.user.VotingPluginUser; + +import lombok.Getter; +import lombok.Setter; + +public class VoteSite { + @Getter + @Setter + private String displayName; + + @Getter + @Setter + private boolean enabled; + + @Getter + @Setter + private boolean giveOffline; + + @Getter + @Setter + private boolean hidden; + + @Getter + @Setter + private boolean ignoreCanVote; + + @Setter + private ConfigurationSection item; + + @Getter + @Setter + private String key; + + private VotingPluginMain plugin; + + @Getter + @Setter + private int priority; + + @Getter + @Setter + private String serviceSite; + + @Getter + @Setter + private int voteDelayDailyHour; + + @Getter + @Setter + private boolean voteDelayDaily; + + @Getter + private ParsedDuration voteDelay; + + @Setter + private String voteURL; + + @Getter + @Setter + private String permissionToView; + + @Getter + @Setter + private boolean waitUntilVoteDelay; + + public VoteSite(VotingPluginMain plugin, String siteName) { + this.plugin = plugin; + key = siteName.replace(".", "_"); + init(); + } + + /** + * @return the item + */ + public ItemBuilder getItem() { + if (item == null) { + plugin.getLogger().warning("Invalid display item section in site: " + key); + return new ItemBuilder(Material.STONE, 1).setName("&cInvalid display item for site: " + key) + .setLore("&cInvalid display item for site: " + key); + } + return new ItemBuilder(item); + } + + public ConfigurationSection getSiteData() { + return plugin.getConfigVoteSites().getData(key); + } + + public String getVoteURL() { + return getVoteURL(true); + } + + public String getVoteURL(boolean json) { + if (!plugin.getConfigFile().isFormatCommandsVoteForceLinks() || !json || MessageAPI.containsJson(voteURL)) { + return voteURL; + } + if (!voteURL.startsWith("http")) { + return "[Text=\"" + voteURL + "\",url=\"http://" + voteURL + "\"]"; + } + return "[Text=\"" + voteURL + "\",url=\"" + voteURL + "\"]"; + } + + public String getVoteURLJsonStrip() { + String url = ChatColor + .stripColor(MessageAPI.colorize(PlaceholderUtils.parseJson(getVoteURL(false)).toPlainText())); + if (!url.startsWith("http")) { + if (!url.startsWith("www.")) { + url = "https://www." + url; + } else { + url = "https://" + url; + } + } + return url; + } + + public void giveRewards(VotingPluginUser user, boolean online, boolean bungee) { + new RewardBuilder(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getEverySiteRewardPath()) + .setOnline(online).withPlaceHolder("ServiceSite", getServiceSite()) + .withPlaceHolder("SiteName", getDisplayName()).withPlaceHolder("VoteDelay", "" + getVoteDelay()) + .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); + + new RewardBuilder(plugin.getConfigVoteSites().getData(), plugin.getConfigVoteSites().getRewardsPath(key)) + .setOnline(online).withPlaceHolder("ServiceSite", getServiceSite()) + .withPlaceHolder("SiteName", getDisplayName()).withPlaceHolder("VoteDelay", "" + getVoteDelay()) + .withPlaceHolder("VoteURL", getVoteURL()).setServer(bungee).send(user); + + } + + /** + * 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)); + } + + /** + * Inits the. + */ + public void init() { + setVoteURL(plugin.getConfigVoteSites().getVoteURL(key)); + setServiceSite(plugin.getConfigVoteSites().getServiceSite(key)); + this.voteDelay = plugin.getConfigVoteSites().getVoteDelay(key); + setEnabled(plugin.getConfigVoteSites().getVoteSiteEnabled(key)); + setPriority(plugin.getConfigVoteSites().getPriority(key)); + displayName = plugin.getConfigVoteSites().getDisplayName(key); + if (displayName == null || displayName.equals("")) { + displayName = key; + } + item = plugin.getConfigVoteSites().getItem(key); + voteDelayDaily = plugin.getConfigVoteSites().getVoteSiteResetVoteDelayDaily(key); + giveOffline = plugin.getConfigVoteSites().getVoteSiteGiveOffline(key); + waitUntilVoteDelay = plugin.getConfigVoteSites().getWaitUntilVoteDelay(key); + voteDelayDailyHour = plugin.getConfigVoteSites().getVoteDelayDailyHour(key); + hidden = plugin.getConfigVoteSites().getVoteSiteHidden(key); + ignoreCanVote = plugin.getConfigVoteSites().getVoteSiteIgnoreCanVote(key); + permissionToView = plugin.getConfigVoteSites().getPermissionToView(key); + } + + public boolean isVaidServiceSite() { + return ArrayUtils.containsIgnoreCase(plugin.getServerData().getServiceSites(), getServiceSite()); + } + + public String loadingDebug() { + String str = "Loading votesite key: " + key; + str += ", Displayname: " + displayName; + str += ", VoteDelay: " + getVoteDelay(); + str += ", VoteDelayDaily: " + isVoteDelayDaily(); + str += ", IsWaitUntilVoteDelay: " + isWaitUntilVoteDelay(); + str += ", ServiceSite: " + getServiceSite(); + str += ", VoteDelayDailyHour:" + getVoteDelayDailyHour(); + str += ", Url: " + getVoteURL(); + str += ", IgnoreCanVote: " + isIgnoreCanVote(); + str += ", Hidden: " + isHidden(); + return str; + } + +} From 09db997e35aa4fb73b15381272b00aefb4d7b6bc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:22:41 +0000 Subject: [PATCH 71/71] Remove temporary line ending cleanup workflow --- .../preserve-comment-cleanup-line-endings.yml | 61 ------------------- 1 file changed, 61 deletions(-) delete mode 100644 .github/workflows/preserve-comment-cleanup-line-endings.yml diff --git a/.github/workflows/preserve-comment-cleanup-line-endings.yml b/.github/workflows/preserve-comment-cleanup-line-endings.yml deleted file mode 100644 index 8fa0161f68..0000000000 --- a/.github/workflows/preserve-comment-cleanup-line-endings.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Preserve comment cleanup line endings - -on: - pull_request: - branches: - - master - types: [opened, synchronize, reopened] - -permissions: - contents: write - -jobs: - cleanup: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: cleanup/generated-comments-round2 - fetch-depth: 0 - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: '21' - cache: maven - - name: Reapply cleanup preserving line endings - run: | - git fetch origin refactor/voteparty-components - git checkout origin/refactor/voteparty-components -- VotingPlugin/src/main/java - python - <<'PY' - from pathlib import Path - import re - - root = Path('VotingPlugin/src/main/java') - for path in root.rglob('*.java'): - data = path.read_bytes() - original = data - data = re.sub(rb'(?m)^[ \t]*// TODO: Auto-generated Javadoc[ \t]*\r?\n', b'', data) - data = re.sub(rb'(?ms)^[ \t]*/\*\*[ \t]*\r?\n[ \t]*\* The Class [^\r\n]+\.[ \t]*\r?\n[ \t]*\*/[ \t]*\r?\n', b'', data) - data = re.sub(rb'(?ms)^[ \t]*/\*[ \t]*\r?\n[ \t]*\* \(non-Javadoc\).*?\*/[ \t]*\r?\n', b'', data) - if data != original: - path.write_bytes(data) - PY - if grep -R --line-number --include='*.java' 'TODO: Auto-generated Javadoc\|(non-Javadoc)' VotingPlugin/src/main/java; then - exit 1 - fi - - name: Build - run: mvn -B -f VotingPlugin/pom.xml package - - name: Commit clean diff - run: | - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A VotingPlugin/src/main/java - git commit -m 'Preserve line endings in comment cleanup' - git push origin HEAD:cleanup/generated-comments-round2 - - name: Remove temporary workflow - run: | - git pull --rebase origin cleanup/generated-comments-round2 - git rm .github/workflows/preserve-comment-cleanup-line-endings.yml - git commit -m 'Remove temporary line ending cleanup workflow' - git push origin HEAD:cleanup/generated-comments-round2