mirror of
https://github.com/BenCodez/VotingPlugin.git
synced 2026-11-04 17:10:03 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
300f9fd928 | ||
|
|
cc035116e3 | ||
|
|
583b510636 | ||
|
|
bfd3d69704 | ||
|
|
8af2dc75cd | ||
|
|
d85640ec3c | ||
|
|
a1def65f2d | ||
|
|
d7387a7182 | ||
|
|
6d389c0408 | ||
|
|
3a419b5250 | ||
|
|
6f828b6928 | ||
|
|
c43eb697e3 | ||
|
|
9917c85de4 | ||
|
|
5796e0401b | ||
|
|
3cc643e501 | ||
|
|
99935133e1 | ||
|
|
cb90e607aa | ||
|
|
0887810ce1 | ||
|
|
eef95ceea5 | ||
|
|
1611fc6cd2 | ||
|
|
6591f3a625 | ||
|
|
b74820d1a8 | ||
|
|
3a1fdf1f35 | ||
|
|
00875b7e6f | ||
|
|
0bd2801825 | ||
|
|
71e7f5c753 | ||
|
|
7392da2c04 | ||
|
|
e49c3f2476 | ||
|
|
e9e964ca7f | ||
|
|
5f51ccb749 | ||
|
|
ce7ee1da3b | ||
|
|
a8c57e1b78 | ||
|
|
6c2ab687bf | ||
|
|
3af59056a7 | ||
|
|
dd3bcae15f | ||
|
|
499e4c9bd9 | ||
|
|
59bd7895d1 | ||
|
|
be78d4a717 | ||
|
|
16fce5f132 | ||
|
|
0b1c192315 | ||
|
|
139122be62 | ||
|
|
de0f511e9e | ||
|
|
73bba25977 | ||
|
|
83ca134649 | ||
|
|
06a74371e7 | ||
|
|
365f08861f | ||
|
|
9fa553e417 | ||
|
|
8b2d3b7f63 | ||
|
|
0f1ccea630 | ||
|
|
d116fa11f7 | ||
|
|
de75dff8df | ||
|
|
1a5f8cdc0f | ||
|
|
9674921fe3 | ||
|
|
ff21a233fe | ||
|
|
e19a50e64a | ||
|
|
d69d08461d | ||
|
|
d9aaeda303 | ||
|
|
b3cc94965a | ||
|
|
a1033555fb | ||
|
|
8ef8aa26ff | ||
|
|
ad8699cf15 | ||
|
|
84705f29f5 | ||
|
|
058fbdfd9e | ||
|
|
c3b7747cbc | ||
|
|
2230bd45b9 | ||
|
|
d7a35d845a | ||
|
|
0e48aae457 | ||
|
|
0c94ba89a5 | ||
|
|
0b8ddaccdc | ||
|
|
68ee77eab3 | ||
|
|
3c38932feb | ||
|
|
8594f0f51d | ||
|
|
c77fdb1b69 | ||
|
|
236812bcac | ||
|
|
0bb6d57494 | ||
|
|
5e5988d0b3 | ||
|
|
77a190574d | ||
|
|
a8bf92786f | ||
|
|
7510981f60 | ||
|
|
5dfd9481bc | ||
|
|
403579d7bf | ||
|
|
d019e54860 | ||
|
|
34b5b34a2f | ||
|
|
535e2201d5 | ||
|
|
e305e6c97c | ||
|
|
564de3d653 | ||
|
|
88050c903e | ||
|
|
901d900932 | ||
|
|
d33063dd50 | ||
|
|
a5d85f4cbc | ||
|
|
8e03f6e9c0 | ||
|
|
d761238eab | ||
|
|
7a4a7ec1b5 | ||
|
|
fdb3793145 | ||
|
|
8c758a3410 | ||
|
|
9564e00460 | ||
|
|
28d4f5482d | ||
|
|
5fe9bd1377 | ||
|
|
474553b4fe | ||
|
|
609e31c16c | ||
|
|
71ed79b819 | ||
|
|
7f1e1e1e72 | ||
|
|
e22b1885ab | ||
|
|
c3291e4f46 | ||
|
|
60a1428496 | ||
|
|
17c098f1ee | ||
|
|
fb78dc1313 | ||
|
|
382bba9990 | ||
|
|
8594cb8238 | ||
|
|
1f3a4b84a1 | ||
|
|
17574f6c50 | ||
|
|
60377deb44 | ||
|
|
34614e13fa | ||
|
|
bc98630388 | ||
|
|
302cc980d8 | ||
|
|
4342fc5458 | ||
|
|
90b981af7b | ||
|
|
32879956ec | ||
|
|
2b166c7760 | ||
|
|
9848172a49 | ||
|
|
9775d06ba9 | ||
|
|
9584bc0e66 | ||
|
|
00ec202140 | ||
|
|
bd57f003dd | ||
|
|
23788be684 | ||
|
|
9b33b1cde7 | ||
|
|
02fb353dac | ||
|
|
a4c470887f | ||
|
|
e844a1eb63 | ||
|
|
1787595ea2 | ||
|
|
79bea20039 | ||
|
|
63905004b6 | ||
|
|
f326e2cbbb | ||
|
|
9f6edca531 | ||
|
|
3e277a4a76 | ||
|
|
3b33e5e4a7 | ||
|
|
b5f35038fa | ||
|
|
b937d30213 | ||
|
|
d43cf53276 | ||
|
|
6a7b677322 | ||
|
|
b309537f97 | ||
|
|
7e34dd89b8 | ||
|
|
5dcc0a1b33 | ||
|
|
36f8b3fbe8 | ||
|
|
df298fd66c | ||
|
|
c93aff6c20 |
No files matched your search
@@ -0,0 +1,41 @@
|
||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
|
||||
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support documentation.
|
||||
|
||||
name: Java CI with Maven
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
permissions:
|
||||
contents: write # required for dependency submission
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
cache: maven
|
||||
|
||||
- name: Build with Maven
|
||||
run: mvn -B -f VotingPlugin/pom.xml package
|
||||
|
||||
# Only submit dependency snapshot on push (not on pull_request)
|
||||
- name: Submit Dependency Snapshot
|
||||
if: github.event_name == 'push'
|
||||
uses: advanced-security/maven-dependency-submission-action@v5
|
||||
with:
|
||||
directory: VotingPlugin # path to pom.xml
|
||||
# optional: maven-args: "-DskipTests"
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
description: Describe what this custom agent does and when to use it.
|
||||
tools: []
|
||||
---
|
||||
Write instructions for this custom agent. These will guide Copilot on how to respond when this mode is selected.
|
||||
+656
-610
File diff suppressed because it is too large.
Load diff
@@ -1,16 +1,16 @@
|
||||
// File: com/bencodez/votingplugin/BungeeHandler.java
|
||||
package com.bencodez.votingplugin;
|
||||
|
||||
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.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -23,15 +23,13 @@ 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.array.ArrayUtils;
|
||||
import com.bencodez.simpleapi.encryption.EncryptionHandler;
|
||||
import com.bencodez.simpleapi.messages.MessageAPI;
|
||||
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.MqttHandler.MessageHandler;
|
||||
import com.bencodez.simpleapi.servercomm.mqtt.MqttServerComm;
|
||||
import com.bencodez.simpleapi.servercomm.mysql.BackendMessenger;
|
||||
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;
|
||||
@@ -41,11 +39,11 @@ 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.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.proxy.BungeeMessageData;
|
||||
import com.bencodez.votingplugin.proxy.BungeeMethod;
|
||||
import com.bencodez.votingplugin.proxy.BungeeVersion;
|
||||
import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot;
|
||||
import com.bencodez.votingplugin.proxy.VotingPluginWire;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -83,7 +81,10 @@ public class BungeeHandler implements Listener {
|
||||
private Thread redisThread;
|
||||
|
||||
@Getter
|
||||
private BackendMessenger backendMysqlMessenger;
|
||||
private MySqlMessenger backendMysqlMessenger;
|
||||
|
||||
@Getter
|
||||
private MqttHandler mqttHandler;
|
||||
|
||||
public BungeeHandler(VotingPluginMain plugin) {
|
||||
this.plugin = plugin;
|
||||
@@ -91,7 +92,6 @@ public class BungeeHandler implements Listener {
|
||||
|
||||
public void checkGlobalData() {
|
||||
HashMap<String, DataValue> data = globalDataHandler.getExact(plugin.getBungeeSettings().getServer());
|
||||
// plugin.debug(data.toString());
|
||||
|
||||
if (data.containsKey("ForceUpdate")) {
|
||||
boolean b = checkGlobalDataTimeValue(data.get("ForceUpdate"));
|
||||
@@ -126,15 +126,6 @@ public class BungeeHandler implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @EventHandler public void onDateChange(DateChangedEvent event) { if
|
||||
* (method.equals(BungeeMethod.PLUGINMESSAGING)) {
|
||||
* plugin.getPluginMessaging().sendPluginMessage("timeupdate",
|
||||
* plugin.getServerDataFile().getPrevMonth() + "//" +
|
||||
* plugin.getServerDataFile().getPrevDay() + "//" +
|
||||
* plugin.getServerDataFile().getPrevWeekDay()); } }
|
||||
*/
|
||||
|
||||
public boolean checkGlobalDataTime(TimeType type, HashMap<String, DataValue> data) {
|
||||
boolean isProcessing = false;
|
||||
if (data.containsKey(type.toString())) {
|
||||
@@ -157,8 +148,10 @@ public class BungeeHandler implements Listener {
|
||||
plugin.debug("Detected time change from bungee: " + type.toString());
|
||||
plugin.getTimeChecker().forceChanged(type, false, true, true);
|
||||
globalDataHandler.setBoolean(plugin.getBungeeSettings().getServer(), type.toString(), false);
|
||||
getGlobalMessageHandler().sendMessage("TimeChangeFinished",
|
||||
"" + plugin.getBungeeSettings().getServer());
|
||||
|
||||
HashMap<String, Object> fields = new HashMap<>();
|
||||
fields.put("server", plugin.getBungeeSettings().getServer());
|
||||
sendSubChannel("TimeChangeFinished", fields);
|
||||
}
|
||||
}
|
||||
return isProcessing;
|
||||
@@ -199,339 +192,192 @@ public class BungeeHandler implements Listener {
|
||||
loadGlobalMysql();
|
||||
|
||||
globalMessageHandler = new GlobalMessageHandler() {
|
||||
|
||||
@Override
|
||||
public void sendMessage(String subChannel, String... messageData) {
|
||||
public void sendMessage(JsonEnvelope envelope) {
|
||||
if (method.equals(BungeeMethod.MYSQL)) {
|
||||
// plugin.getPluginMessaging().sendPluginMessage(subChannel, messageData);
|
||||
|
||||
try {
|
||||
backendMysqlMessenger.sendToProxy(subChannel + "%l%" + String.join("%l%", messageData));
|
||||
backendMysqlMessenger.sendToProxy(envelope);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else if (method.equals(BungeeMethod.PLUGINMESSAGING)) {
|
||||
plugin.getPluginMessaging().sendPluginMessage(subChannel, messageData);
|
||||
plugin.getPluginMessaging().sendEnvelope(envelope);
|
||||
} else if (method.equals(BungeeMethod.SOCKETS)) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
list.add(subChannel);
|
||||
list.addAll(ArrayUtils.convert(messageData));
|
||||
sendData(ArrayUtils.convert(list));
|
||||
sendEnvelopeSocket(envelope);
|
||||
} else if (method.equals(BungeeMethod.REDIS)) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
list.add(subChannel);
|
||||
list.addAll(ArrayUtils.convert(messageData));
|
||||
redisHandler.sendMessage(plugin.getBungeeSettings().getRedisPrefix() + "VotingPlugin",
|
||||
ArrayUtils.convert(list));
|
||||
redisHandler.publishEnvelope(plugin.getBungeeSettings().getRedisPrefix() + "VotingPlugin",
|
||||
envelope);
|
||||
} else if (method.equals(BungeeMethod.MQTT)) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
list.add(subChannel);
|
||||
list.addAll(ArrayUtils.convert(messageData));
|
||||
try {
|
||||
mqttHandler.publish(plugin.getBungeeSettings().getMqttPrefix() + "votingplugin/servers/proxy",
|
||||
String.join(":", list));
|
||||
mqttHandler.publishEnvelope(
|
||||
plugin.getBungeeSettings().getMqttPrefix() + "votingplugin/servers/proxy", envelope);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("Vote") {
|
||||
// ==========================
|
||||
// Vote / VoteOnline (wire decode)
|
||||
// ==========================
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE) {
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
if (args.size() > 8) {
|
||||
int bungeeVersion = Integer.parseInt(args.get(8));
|
||||
if (bungeeVersion != BungeeVersion.getPluginMessageVersion()) {
|
||||
plugin.getLogger().warning("Incompatible version with bungee, please update all servers"
|
||||
+ bungeeVersion + ":" + BungeeVersion.getPluginMessageVersion());
|
||||
return;
|
||||
}
|
||||
|
||||
String player = args.get(0);
|
||||
String uuid = args.get(1);
|
||||
String service = args.get(2);
|
||||
long time = Long.parseLong(args.get(3));
|
||||
plugin.debug("pluginmessaging vote received from " + player + "/" + uuid + " on " + service);
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(UUID.fromString(uuid), player);
|
||||
|
||||
boolean wasOnline = Boolean.valueOf(args.get(4));
|
||||
|
||||
BungeeMessageData text = new BungeeMessageData(args.get(6));
|
||||
|
||||
bungeeVotePartyCurrent = text.getVotePartyCurrent();
|
||||
bungeeVotePartyRequired = text.getVotePartyRequired();
|
||||
plugin.getPlaceholders().onBungeeVotePartyUpdate();
|
||||
plugin.getServerData().setBungeeVotePartyCurrent(bungeeVotePartyCurrent);
|
||||
plugin.getServerData().setBungeeVotePartyRequired(bungeeVotePartyRequired);
|
||||
|
||||
boolean setTotals = Boolean.valueOf(args.get(7));
|
||||
|
||||
user.cache();
|
||||
|
||||
boolean broadcast = true;
|
||||
boolean bungeeBroadcast = false;
|
||||
|
||||
if (args.size() > 9) {
|
||||
bungeeBroadcast = Boolean.valueOf(args.get(9));
|
||||
}
|
||||
|
||||
int num = 1;
|
||||
if (args.size() > 10) {
|
||||
num = Integer.valueOf(args.get(10));
|
||||
}
|
||||
int numberOfVotes = 1;
|
||||
if (args.size() > 11) {
|
||||
numberOfVotes = Integer.valueOf(args.get(11));
|
||||
}
|
||||
|
||||
if (!bungeeBroadcast) {
|
||||
if (!plugin.getBungeeSettings().isBungeeBroadcast()
|
||||
&& !plugin.getBungeeSettings().isDisableBroadcast()) {
|
||||
if (wasOnline || plugin.getBungeeSettings().isBungeeBroadcastAlways()) {
|
||||
if (plugin.getConfigFile().isFormatOnlyOneOfflineBroadcast() && !wasOnline) {
|
||||
if (num == 1) {
|
||||
user.offlineBroadcast(user, plugin.getBungeeSettings().isUseBungeecoord(),
|
||||
numberOfVotes);
|
||||
}
|
||||
} else {
|
||||
VoteSite site = plugin.getVoteSite(service, true);
|
||||
if (site != null) {
|
||||
site.broadcastVote(user, false);
|
||||
broadcast = false;
|
||||
} else {
|
||||
plugin.getLogger().warning("No votesite for " + service);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
broadcast = false;
|
||||
}
|
||||
|
||||
user.bungeeVotePluginMessaging(service, time, text, !setTotals, wasOnline, broadcast, num);
|
||||
if (plugin.getBungeeSettings().isPerServerPoints()) {
|
||||
user.addPoints(plugin.getConfigFile().getPointsOnVote());
|
||||
}
|
||||
|
||||
plugin.getSpecialRewards().bungeeAllSitesCheck(user, numberOfVotes, num);
|
||||
|
||||
if (Boolean.valueOf(args.get(5))) {
|
||||
plugin.getServerData().addServiceSite(service);
|
||||
}
|
||||
} else {
|
||||
plugin.getLogger().warning("Incompatible version with bungee, please update all servers");
|
||||
}
|
||||
public void onReceive(JsonEnvelope msg) {
|
||||
handleWireVote(msg);
|
||||
}
|
||||
});
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("VoteOnline") {
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_ONLINE) {
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
if (args.size() > 8) {
|
||||
int bungeeVersion = Integer.parseInt(args.get(8));
|
||||
if (bungeeVersion != BungeeVersion.getPluginMessageVersion()) {
|
||||
plugin.getLogger().warning("Incompatible version with bungee, please update all servers");
|
||||
return;
|
||||
}
|
||||
String player = args.get(0);
|
||||
String uuid = args.get(1);
|
||||
String service = args.get(2);
|
||||
long time = Long.parseLong(args.get(3));
|
||||
BungeeMessageData text = new BungeeMessageData(args.get(6));
|
||||
|
||||
bungeeVotePartyCurrent = text.getVotePartyCurrent();
|
||||
bungeeVotePartyRequired = text.getVotePartyRequired();
|
||||
plugin.getPlaceholders().onBungeeVotePartyUpdate();
|
||||
plugin.getServerData().setBungeeVotePartyCurrent(bungeeVotePartyCurrent);
|
||||
plugin.getServerData().setBungeeVotePartyRequired(bungeeVotePartyRequired);
|
||||
|
||||
plugin.debug("pluginmessaging voteonline received from " + player + "/" + uuid + " on " + service);
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(UUID.fromString(uuid), player);
|
||||
user.cache();
|
||||
|
||||
boolean setTotals = Boolean.valueOf(args.get(7));
|
||||
|
||||
boolean wasOnline = Boolean.valueOf(args.get(4));
|
||||
|
||||
boolean broadcast = true;
|
||||
boolean bungeeBroadcast = false;
|
||||
|
||||
if (args.size() > 9) {
|
||||
bungeeBroadcast = Boolean.valueOf(args.get(9));
|
||||
}
|
||||
|
||||
int num = 1;
|
||||
if (args.size() > 10) {
|
||||
num = Integer.valueOf(args.get(10));
|
||||
}
|
||||
|
||||
int numberOfVotes = 1;
|
||||
if (args.size() > 11) {
|
||||
numberOfVotes = Integer.valueOf(args.get(11));
|
||||
}
|
||||
|
||||
if (!bungeeBroadcast) {
|
||||
if (!plugin.getBungeeSettings().isBungeeBroadcast()
|
||||
&& !plugin.getBungeeSettings().isDisableBroadcast()) {
|
||||
if (wasOnline || plugin.getBungeeSettings().isBungeeBroadcastAlways()) {
|
||||
if (plugin.getConfigFile().isFormatOnlyOneOfflineBroadcast() && !wasOnline) {
|
||||
if (num == 1) {
|
||||
user.offlineBroadcast(user, plugin.getBungeeSettings().isUseBungeecoord(),
|
||||
numberOfVotes);
|
||||
}
|
||||
} else {
|
||||
VoteSite site = plugin.getVoteSite(service, true);
|
||||
if (site != null) {
|
||||
site.broadcastVote(user, false);
|
||||
broadcast = false;
|
||||
} else {
|
||||
plugin.getLogger().warning("No votesite for " + service);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
broadcast = false;
|
||||
}
|
||||
|
||||
user.bungeeVotePluginMessaging(service, time, text, !setTotals, wasOnline, broadcast, num);
|
||||
if (plugin.getBungeeSettings().isPerServerPoints()) {
|
||||
user.addPoints(plugin.getConfigFile().getPointsOnVote());
|
||||
}
|
||||
|
||||
plugin.getSpecialRewards().bungeeAllSitesCheck(user, numberOfVotes, num);
|
||||
|
||||
if (Boolean.valueOf(args.get(5))) {
|
||||
plugin.getServerData().addServiceSite(service);
|
||||
}
|
||||
} else {
|
||||
plugin.getLogger().warning("Incompatible version with bungee, please update all servers");
|
||||
}
|
||||
|
||||
public void onReceive(JsonEnvelope msg) {
|
||||
handleWireVote(msg);
|
||||
}
|
||||
});
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("VoteUpdate") {
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_UPDATE) {
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
String player = args.get(0);
|
||||
plugin.debug("pluginmessaging voteupdate received for " + player);
|
||||
public void onReceive(JsonEnvelope msg) {
|
||||
// Wire decode
|
||||
VotingPluginWire.VoteUpdate v = VotingPluginWire.readVoteUpdate(msg);
|
||||
|
||||
String playerUuid = v.uuid;
|
||||
if (playerUuid == null || playerUuid.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.debug("pluginmessaging voteupdate received for " + playerUuid);
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(UUID.fromString(player));
|
||||
.getVotingPluginUser(UUID.fromString(playerUuid));
|
||||
user.cache();
|
||||
|
||||
user.offVote();
|
||||
|
||||
if (args.size() > 2) {
|
||||
bungeeVotePartyCurrent = Integer.parseInt(args.get(1));
|
||||
bungeeVotePartyRequired = Integer.parseInt(args.get(2));
|
||||
plugin.getServerData().setBungeeVotePartyCurrent(bungeeVotePartyCurrent);
|
||||
plugin.getServerData().setBungeeVotePartyRequired(bungeeVotePartyRequired);
|
||||
// Vote party cache update
|
||||
if (v.votePartyCurrent != 0 || bungeeVotePartyCurrent == -2) {
|
||||
bungeeVotePartyCurrent = v.votePartyCurrent;
|
||||
}
|
||||
|
||||
if (args.size() > 3 && plugin.getBungeeSettings().isPerServerMilestones()) {
|
||||
BungeeMessageData text = new BungeeMessageData(args.get(3));
|
||||
plugin.getSpecialRewards().checkMilestone(user, text, true);
|
||||
if (v.votePartyRequired != 0 || bungeeVotePartyRequired == -2) {
|
||||
bungeeVotePartyRequired = v.votePartyRequired;
|
||||
}
|
||||
plugin.getServerData().setBungeeVotePartyCurrent(bungeeVotePartyCurrent);
|
||||
plugin.getServerData().setBungeeVotePartyRequired(bungeeVotePartyRequired);
|
||||
|
||||
if (args.size() > 5) {
|
||||
String service = args.get(4);
|
||||
String data = args.get(5);
|
||||
if (MessageAPI.isLong(data)) {
|
||||
long time = Long.valueOf(data);
|
||||
if (time > 0) {
|
||||
user.setTime(plugin.getVoteSite(service, true), time);
|
||||
} else {
|
||||
if (plugin.getBungeeSettings().isBungeeDebug()) {
|
||||
plugin.debug("Invalid last vote time received from bungee: " + time);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Optional: update last vote time for a service
|
||||
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("BungeeTimeChange") {
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_BUNGEE_TIME_CHANGE) {
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
public void onReceive(JsonEnvelope msg) {
|
||||
checkGlobalData();
|
||||
}
|
||||
});
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("VoteBroadcast") {
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener(VotingPluginWire.SUB_VOTE_BROADCAST) {
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
if (args.size() > 2) {
|
||||
String uuid = args.get(0);
|
||||
String service = args.get(2);
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(UUID.fromString(uuid), args.get(1));
|
||||
VoteSite site = plugin.getVoteSite(service, true);
|
||||
if (site != null) {
|
||||
site.broadcastVote(user, false);
|
||||
} else {
|
||||
plugin.getLogger().warning("No votesite for " + service);
|
||||
}
|
||||
public void onReceive(JsonEnvelope msg) {
|
||||
Map<String, String> 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;
|
||||
}
|
||||
|
||||
// New fields (May use later)
|
||||
@SuppressWarnings("unused")
|
||||
final long time = readLongSafe(f.get(VotingPluginWire.K_TIME), 0L);
|
||||
@SuppressWarnings("unused")
|
||||
final String totals = nvl(f.get(VotingPluginWire.K_TOTALS));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Same user retrieval strategy: UUID + (possibly empty) name
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(javaUuid,
|
||||
playerNameRaw);
|
||||
|
||||
// Keep cache/name current like normal vote path does
|
||||
user.cache();
|
||||
user.updateName(true);
|
||||
|
||||
// Same broadcast logic as PlayerVoteListener
|
||||
if (plugin.getBroadcastHandler() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.isVanished()) {
|
||||
plugin.debug("Not broadcasting vote for vanished user: " + user.getPlayerName());
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean online = user.isOnline(); // same behavior as non-bungee vote path
|
||||
plugin.getBroadcastHandler().broadcastVote(user.getJavaUUID(), user.getPlayerName(),
|
||||
voteSite.getDisplayName(), online);
|
||||
}
|
||||
});
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("VoteBroadcastOffline") {
|
||||
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
if (args.size() > 2) {
|
||||
String uuid = args.get(0);
|
||||
String votes = args.get(2);
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(UUID.fromString(uuid), args.get(1));
|
||||
user.offlineBroadcast(user, false, Integer.parseInt(votes));
|
||||
}
|
||||
}
|
||||
});
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("Status") {
|
||||
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
String server = args.get(0);
|
||||
sendMessage(globalMessageHandler, "statusokay", server);
|
||||
public void onReceive(JsonEnvelope msg) {
|
||||
String server = nvl(msg.getFields().get("server"));
|
||||
HashMap<String, Object> out = new HashMap<>();
|
||||
out.put("server", server);
|
||||
sendSubChannel("statusokay", out);
|
||||
}
|
||||
});
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("ServerName") {
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("ServerName") {
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
String server = args.get(0);
|
||||
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") {
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("VotePartyBungee") {
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
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()) {
|
||||
@@ -539,11 +385,11 @@ public class BungeeHandler implements Listener {
|
||||
}
|
||||
}
|
||||
});
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("VotePartyBroadcast") {
|
||||
|
||||
globalMessageHandler.addListener(new GlobalMessageListener("VotePartyBroadcast") {
|
||||
@Override
|
||||
public void onReceive(ArrayList<String> args) {
|
||||
String broadcast = args.get(0);
|
||||
public void onReceive(JsonEnvelope msg) {
|
||||
String broadcast = nvl(msg.getFields().get("broadcast"));
|
||||
MiscUtils.getInstance().broadcast(broadcast);
|
||||
}
|
||||
});
|
||||
@@ -552,29 +398,22 @@ public class BungeeHandler implements Listener {
|
||||
plugin.registerBungeeChannels(plugin.getBungeeSettings().getPluginMessagingChannel());
|
||||
|
||||
try {
|
||||
backendMysqlMessenger = new BackendMessenger("VotingPlugin",
|
||||
backendMysqlMessenger = new MySqlMessenger("VotingPlugin",
|
||||
plugin.getMysql().getMysql().getConnectionManager().getDataSource(),
|
||||
plugin.getOptions().getServer(), msg -> {
|
||||
plugin.debug("Proxy sent: " + msg.payload);
|
||||
|
||||
String[] message = msg.payload.split(Pattern.quote("%l%"));
|
||||
if (message.length > 0) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
for (int i = 1; i < message.length; i++) {
|
||||
list.add(message[i]);
|
||||
}
|
||||
globalMessageHandler.onMessage(message[0], list);
|
||||
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().getRedisPassword(), plugin.getBungeeSettings().getRedisdbindex()) {
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
@@ -582,29 +421,17 @@ public class BungeeHandler implements Listener {
|
||||
plugin.debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMessage(String channel, String[] message) {
|
||||
if (plugin.getBungeeSettings().isBungeeDebug()) {
|
||||
plugin.debug(channel + " " + ArrayUtils.makeStringList(ArrayUtils.convert(message)));
|
||||
}
|
||||
if (message.length > 0) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
for (int i = 1; i < message.length; i++) {
|
||||
list.add(message[i]);
|
||||
}
|
||||
globalMessageHandler.onMessage(message[0], list);
|
||||
}
|
||||
}
|
||||
};
|
||||
redisThread = new Thread(new Runnable() {
|
||||
|
||||
redisThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (plugin.isEnabled()) {
|
||||
redisHandler.loadListener(
|
||||
new RedisListener(redisHandler, plugin.getBungeeSettings().getRedisPrefix()
|
||||
+ "VotingPlugin_" + plugin.getBungeeSettings().getServer()));
|
||||
RedisListener listener = redisHandler.createEnvelopeListener(
|
||||
plugin.getBungeeSettings().getRedisPrefix() + "VotingPlugin_"
|
||||
+ plugin.getBungeeSettings().getServer(),
|
||||
(ch, env) -> globalMessageHandler.onMessage(env));
|
||||
redisHandler.loadListener(listener);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -623,9 +450,8 @@ public class BungeeHandler implements Listener {
|
||||
|
||||
plugin.getPluginMessaging().add(new PluginMessageHandler() {
|
||||
@Override
|
||||
public void onRecieve(String subChannel, ArrayList<String> args) {
|
||||
globalMessageHandler.onMessage(subChannel, args);
|
||||
|
||||
public void onReceive(JsonEnvelope envelope) {
|
||||
globalMessageHandler.onMessage(envelope);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -637,7 +463,7 @@ public class BungeeHandler implements Listener {
|
||||
plugin.getBungeeSettings().getBungeeServerPort(), encryptionHandler,
|
||||
plugin.getBungeeSettings().isBungeeDebug());
|
||||
|
||||
socketHandler = new SocketHandler(plugin.getVersion(), plugin.getBungeeSettings().getSpigotServerHost(),
|
||||
socketHandler = new SocketHandler("vp-socket", plugin.getBungeeSettings().getSpigotServerHost(),
|
||||
plugin.getBungeeSettings().getSpigotServerPort(), encryptionHandler,
|
||||
plugin.getBungeeSettings().isBungeeDebug()) {
|
||||
|
||||
@@ -648,10 +474,9 @@ public class BungeeHandler implements Listener {
|
||||
};
|
||||
|
||||
socketHandler.add(new SocketReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(String[] data) {
|
||||
globalMessageHandler.onMessage(data[0], ArrayUtils.convertAndRemoveFirst(data));
|
||||
public void onReceiveEnvelope(JsonEnvelope envelope) {
|
||||
globalMessageHandler.onMessage(envelope);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -661,26 +486,17 @@ public class BungeeHandler implements Listener {
|
||||
if (id.isEmpty()) {
|
||||
id = plugin.getOptions().getServer();
|
||||
}
|
||||
mqttHandler = new MqttHandler(new MqttServerComm(plugin.getBungeeSettings().getMqttClientID(),
|
||||
plugin.getBungeeSettings().getMqttBrokerURL(), plugin.getBungeeSettings().getMqttUsername(),
|
||||
plugin.getBungeeSettings().getMqttPassword()), 2);
|
||||
mqttHandler.subscribe(plugin.getBungeeSettings().getMqttPrefix() + "votingplugin/servers/"
|
||||
+ plugin.getOptions().getServer(), new MessageHandler() {
|
||||
mqttHandler = new MqttHandler(new MqttServerComm(id, plugin.getBungeeSettings().getMqttBrokerURL(),
|
||||
plugin.getBungeeSettings().getMqttUsername(), plugin.getBungeeSettings().getMqttPassword()), 2);
|
||||
|
||||
@Override
|
||||
public void onMessage(String topic, String payload) {
|
||||
String[] message = payload.split(":");
|
||||
mqttHandler.subscribeEnvelopes(
|
||||
plugin.getBungeeSettings().getMqttPrefix() + "votingplugin/servers/"
|
||||
+ plugin.getOptions().getServer(),
|
||||
(topic, envelope) -> globalMessageHandler.onMessage(envelope));
|
||||
|
||||
if (message.length > 0) {
|
||||
globalMessageHandler.onMessage(message[0],
|
||||
ArrayUtils.convertAndRemoveFirst(message));
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (MqttException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -693,8 +509,72 @@ public class BungeeHandler implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
private MqttHandler mqttHandler;
|
||||
private static long readLongSafe(String v, long def) {
|
||||
if (v == null)
|
||||
return def;
|
||||
try {
|
||||
return Long.parseLong(v);
|
||||
} catch (Exception ignored) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wire vote handler (Vote + VoteOnline).
|
||||
*/
|
||||
private void handleWireVote(JsonEnvelope msg) {
|
||||
// Strict schema check (wire uses envelope schema, not a "bungeeVersion" field)
|
||||
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;
|
||||
}
|
||||
|
||||
plugin.debug("wire vote received from " + player + "/" + uuidStr + " on " + service);
|
||||
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(UUID.fromString(uuidStr),
|
||||
player);
|
||||
|
||||
VoteTotalsSnapshot text = VoteTotalsSnapshot.parseStorage(v.totals == null ? "" : v.totals);
|
||||
|
||||
bungeeVotePartyCurrent = text.getVotePartyCurrent();
|
||||
bungeeVotePartyRequired = text.getVotePartyRequired();
|
||||
plugin.getPlaceholders().onBungeeVotePartyUpdate();
|
||||
plugin.getServerData().setBungeeVotePartyCurrent(bungeeVotePartyCurrent);
|
||||
plugin.getServerData().setBungeeVotePartyRequired(bungeeVotePartyRequired);
|
||||
|
||||
user.cache();
|
||||
|
||||
boolean bungeeBroadcast = v.broadcast;
|
||||
|
||||
// Wire has no "setTotals" flag; treat as always true (so doNotSetTotals =
|
||||
// false)
|
||||
boolean doNotSetTotals = false;
|
||||
|
||||
user.bungeeVotePluginMessaging(service, v.time, text, doNotSetTotals, v.wasOnline, bungeeBroadcast, v.num);
|
||||
|
||||
if (plugin.getBungeeSettings().isPerServerPoints()) {
|
||||
user.addPoints(plugin.getConfigFile().getPointsOnVote());
|
||||
}
|
||||
|
||||
if (v.manageTotals) {
|
||||
plugin.getServerData().addServiceSite(service);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
int _ignored = v.numberOfVotes;
|
||||
}
|
||||
|
||||
public void loadGlobalMysql() {
|
||||
if (plugin.getBungeeSettings().isGloblalDataEnabled()) {
|
||||
@@ -709,28 +589,27 @@ public class BungeeHandler implements Listener {
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -760,7 +639,6 @@ public class BungeeHandler implements Listener {
|
||||
globalDataHandler = new GlobalDataHandler(
|
||||
new GlobalMySQL("VotingPlugin_GlobalData", new MysqlConfigSpigot(
|
||||
plugin.getBungeeSettings().getData().getConfigurationSection("GlobalData"))) {
|
||||
|
||||
@Override
|
||||
public void debugEx(Exception e) {
|
||||
plugin.debug(e);
|
||||
@@ -787,6 +665,7 @@ public class BungeeHandler implements Listener {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
globalDataHandler.getGlobalMysql().alterColumnType("IgnoreTime", "VARCHAR(5)");
|
||||
globalDataHandler.getGlobalMysql().alterColumnType("MONTH", "VARCHAR(5)");
|
||||
globalDataHandler.getGlobalMysql().alterColumnType("WEEK", "VARCHAR(5)");
|
||||
@@ -799,7 +678,23 @@ public class BungeeHandler implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendData(String... strings) {
|
||||
clientHandler.sendMessage(strings);
|
||||
private void sendEnvelopeSocket(JsonEnvelope envelope) {
|
||||
if (clientHandler != null) {
|
||||
clientHandler.sendEnvelope(envelope);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendSubChannel(String subChannel, HashMap<String, Object> fields) {
|
||||
JsonEnvelope.Builder b = JsonEnvelope.builder(subChannel).schema(VotingPluginWire.SCHEMA_VERSION);
|
||||
if (fields != null) {
|
||||
for (Map.Entry<String, Object> e : fields.entrySet()) {
|
||||
b.put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
globalMessageHandler.sendMessage(b.build());
|
||||
}
|
||||
|
||||
private static String nvl(String s) {
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -2,24 +2,36 @@ package com.bencodez.votingplugin;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import com.bencodez.simpleapi.metrics.BStatsMetrics;
|
||||
|
||||
/**
|
||||
* Registers bStats charts for VotingPlugin.
|
||||
* <p>
|
||||
* Updated for VotingPlugin 7.0:
|
||||
* <ul>
|
||||
* <li>Broadcast: Always logs broadcast_type if VoteBroadcast.Type exists. If Type == NONE, ignores other broadcast
|
||||
* settings.</li>
|
||||
* <li>VoteLogging: Only logs VoteLogging charts when VoteLogging.Enabled is true.</li>
|
||||
* <li>No "Unknown" values are emitted; charts are only registered when their data exists.</li>
|
||||
* <li>VoteMilestones chart is bucketed to reduce cardinality.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class VotingPluginMetrics {
|
||||
|
||||
public void load(VotingPluginMain plugin) {
|
||||
BStatsMetrics metrics = new BStatsMetrics(plugin, 38);
|
||||
/**
|
||||
* Register bStats metrics.
|
||||
*
|
||||
* @param plugin VotingPlugin main instance
|
||||
*/
|
||||
public void load(final VotingPluginMain plugin) {
|
||||
if (plugin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_firstvote", new Callable<String>() {
|
||||
final BStatsMetrics metrics = new BStatsMetrics(plugin, 38);
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
if (plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(),
|
||||
plugin.getSpecialRewardsConfig().getFirstVoteRewardsPath())) {
|
||||
return "True";
|
||||
}
|
||||
return "False";
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_everysite", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -31,32 +43,7 @@ public class VotingPluginMetrics {
|
||||
return "False";
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_allsites", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
if (plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(),
|
||||
plugin.getSpecialRewardsConfig().getAllSitesRewardPath())) {
|
||||
return "True";
|
||||
}
|
||||
return "False";
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_cumulative", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
if (plugin.getSpecialRewardsConfig().getCumulativeVotes().size() == 0) {
|
||||
return "False";
|
||||
}
|
||||
for (String cum : plugin.getSpecialRewardsConfig().getCumulativeVotes()) {
|
||||
if (plugin.getSpecialRewardsConfig().getCumulativeRewardEnabled(Integer.parseInt(cum))) {
|
||||
return "True";
|
||||
}
|
||||
}
|
||||
return "False";
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_voteparty", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -67,6 +54,7 @@ public class VotingPluginMetrics {
|
||||
return "True";
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("placeholder_cache_level", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -74,21 +62,16 @@ public class VotingPluginMetrics {
|
||||
return plugin.getPlaceholders().getCacheLevel().toString();
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_milestone", new Callable<String>() {
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_votemilestones", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
if (plugin.getSpecialRewardsConfig().getMilestoneVotes().size() == 0) {
|
||||
return "False";
|
||||
}
|
||||
for (String milestone : plugin.getSpecialRewardsConfig().getMilestoneVotes()) {
|
||||
if (plugin.getSpecialRewardsConfig().getMilestoneRewardEnabled(Integer.parseInt(milestone))) {
|
||||
return "True";
|
||||
}
|
||||
}
|
||||
return "False";
|
||||
int size = plugin.getVoteMilestonesManager().getConfig().getMilestones().size();
|
||||
return bucketCount(size);
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_anysitereward", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -100,63 +83,15 @@ public class VotingPluginMetrics {
|
||||
return "False";
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_votestreakday", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
for (String s : plugin.getSpecialRewardsConfig().getVoteStreakVotes("Day")) {
|
||||
|
||||
if (plugin.getSpecialRewardsConfig().getVoteStreakRewardEnabled("Day", s)
|
||||
&& plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(),
|
||||
plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath("Day", s))) {
|
||||
return "True";
|
||||
}
|
||||
|
||||
}
|
||||
return "False";
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_votestreakweek", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
for (String s : plugin.getSpecialRewardsConfig().getVoteStreakVotes("Week")) {
|
||||
|
||||
if (plugin.getSpecialRewardsConfig().getVoteStreakRewardEnabled("Week", s)
|
||||
&& plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(),
|
||||
plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath("Week", s))) {
|
||||
return "True";
|
||||
}
|
||||
}
|
||||
|
||||
return "False";
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("extrarewards_votestreakmonth", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
for (String s : plugin.getSpecialRewardsConfig().getVoteStreakVotes("Month")) {
|
||||
|
||||
if (plugin.getSpecialRewardsConfig().getVoteStreakRewardEnabled("Month", s)
|
||||
&& plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(),
|
||||
plugin.getSpecialRewardsConfig().getVoteStreakRewardsPath("Month", s))) {
|
||||
return "True";
|
||||
}
|
||||
}
|
||||
|
||||
return "False";
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("numberofsites", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return "" + plugin.getVoteSitesEnabled().size();
|
||||
return "" + plugin.getVoteSiteManager().getVoteSitesEnabled().size();
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("numberofrewards", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -164,6 +99,7 @@ public class VotingPluginMetrics {
|
||||
return "" + plugin.getRewardHandler().getRewards().size();
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("autocreatevotesites", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -172,6 +108,14 @@ public class VotingPluginMetrics {
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("config_onlinemode", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return "" + plugin.getOptions().isOnlineMode();
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("numberofusers", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -209,6 +153,7 @@ public class VotingPluginMetrics {
|
||||
return plugin.getOptions().getStorageType().toString();
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("DisableCheckOnWorldChange", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -216,13 +161,7 @@ public class VotingPluginMetrics {
|
||||
return "" + plugin.getOptions().isDisableCheckOnWorldChange();
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("votereminding_enabled", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return "" + plugin.getConfigFile().isVoteRemindingEnabled();
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("LoadTopVoter_Monthly", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -230,6 +169,7 @@ public class VotingPluginMetrics {
|
||||
return "" + plugin.getConfigFile().isLoadTopVoterMonthly();
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("LoadTopVoter_Weekly", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -237,6 +177,7 @@ public class VotingPluginMetrics {
|
||||
return "" + plugin.getConfigFile().isLoadTopVoterWeekly();
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("LoadTopVoter_Daily", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -244,6 +185,7 @@ public class VotingPluginMetrics {
|
||||
return "" + plugin.getConfigFile().isLoadTopVoterDaily();
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("bungeemethod", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -254,22 +196,8 @@ public class VotingPluginMetrics {
|
||||
return "Disabled";
|
||||
}
|
||||
}));
|
||||
|
||||
if (plugin.getBungeeSettings().isUseBungeecoord()) {
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("bungeebroadcast", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return "" + plugin.getBungeeSettings().isBungeeBroadcast();
|
||||
}
|
||||
}));
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("bungeebroadcastalways", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return "" + plugin.getBungeeSettings().isBungeeBroadcastAlways();
|
||||
}
|
||||
}));
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("perserverrewards", new Callable<String>() {
|
||||
|
||||
@Override
|
||||
@@ -368,5 +296,188 @@ public class VotingPluginMetrics {
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
* Broadcast metrics:
|
||||
* - Always log broadcast_type if VoteBroadcast.Type exists (even if NONE)
|
||||
* - If Type == NONE, ignore the rest of the broadcast settings
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
final ConfigurationSection root = safeConfig(plugin);
|
||||
final ConfigurationSection voteBroadcast = getSection(root, "VoteBroadcast");
|
||||
if (voteBroadcast != null && voteBroadcast.isString("Type")) {
|
||||
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("broadcast_type", new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return voteBroadcast.getString("Type");
|
||||
}
|
||||
}));
|
||||
|
||||
final String type = voteBroadcast.getString("Type", null);
|
||||
if (type != null && !"NONE".equalsIgnoreCase(type)) {
|
||||
|
||||
if (voteBroadcast.isString("Duration")) {
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("broadcast_duration", new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return voteBroadcast.getString("Duration");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
if (voteBroadcast.isInt("MaxSitesListed")) {
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("broadcast_max_sites_listed",
|
||||
new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return bucketMaxSites(voteBroadcast.getInt("MaxSitesListed"));
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
* VoteLogging metrics:
|
||||
* - Only log when VoteLogging.Enabled is true
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
final ConfigurationSection voteLogging = getSection(root, "VoteLogging");
|
||||
if (voteLogging != null && voteLogging.getBoolean("Enabled", false)) {
|
||||
|
||||
if (voteLogging.isInt("PurgeDays")) {
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("votelogging_purgedays", new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return bucketPurgeDays(voteLogging.getInt("PurgeDays"));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
if (voteLogging.isBoolean("UseMainMySQL")) {
|
||||
metrics.addCustomChart(new BStatsMetrics.SimplePie("votelogging_usemainmysql", new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return "" + voteLogging.getBoolean("UseMainMySQL");
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely gets the root configuration section.
|
||||
*
|
||||
* @param plugin plugin instance
|
||||
* @return root config section, or null if inaccessible
|
||||
*/
|
||||
private ConfigurationSection safeConfig(final VotingPluginMain plugin) {
|
||||
try {
|
||||
return plugin.getConfigFile().getData();
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a child section safely.
|
||||
*
|
||||
* @param root root section
|
||||
* @param key child key
|
||||
* @return child section or null
|
||||
*/
|
||||
private ConfigurationSection getSection(final ConfigurationSection root, final String key) {
|
||||
if (root == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return root.getConfigurationSection(key);
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Buckets a milestone count to reduce bStats cardinality.
|
||||
*
|
||||
* @param count count
|
||||
* @return bucket string
|
||||
*/
|
||||
private String bucketCount(final int count) {
|
||||
if (count <= 0) {
|
||||
return "0";
|
||||
}
|
||||
if (count == 1) {
|
||||
return "1";
|
||||
}
|
||||
if (count <= 5) {
|
||||
return "2-5";
|
||||
}
|
||||
if (count <= 10) {
|
||||
return "6-10";
|
||||
}
|
||||
if (count <= 25) {
|
||||
return "11-25";
|
||||
}
|
||||
if (count <= 50) {
|
||||
return "26-50";
|
||||
}
|
||||
if (count <= 100) {
|
||||
return "51-100";
|
||||
}
|
||||
return ">100";
|
||||
}
|
||||
|
||||
/**
|
||||
* Buckets MaxSitesListed to reduce bStats cardinality.
|
||||
*
|
||||
* @param maxSites max sites listed
|
||||
* @return bucket string
|
||||
*/
|
||||
private String bucketMaxSites(final int maxSites) {
|
||||
if (maxSites <= 0) {
|
||||
return "0";
|
||||
}
|
||||
if (maxSites <= 5) {
|
||||
return "1-5";
|
||||
}
|
||||
if (maxSites <= 10) {
|
||||
return "6-10";
|
||||
}
|
||||
if (maxSites <= 25) {
|
||||
return "11-25";
|
||||
}
|
||||
return ">25";
|
||||
}
|
||||
|
||||
/**
|
||||
* Buckets purge days to reduce bStats cardinality.
|
||||
*
|
||||
* @param purgeDays purge days
|
||||
* @return bucket string
|
||||
*/
|
||||
private String bucketPurgeDays(final int purgeDays) {
|
||||
if (purgeDays < 0) {
|
||||
return "disabled";
|
||||
}
|
||||
if (purgeDays == 0) {
|
||||
return "0";
|
||||
}
|
||||
if (purgeDays <= 7) {
|
||||
return "1-7";
|
||||
}
|
||||
if (purgeDays <= 30) {
|
||||
return "8-30";
|
||||
}
|
||||
if (purgeDays <= 90) {
|
||||
return "31-90";
|
||||
}
|
||||
if (purgeDays <= 365) {
|
||||
return "91-365";
|
||||
}
|
||||
return ">365";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.bencodez.votingplugin.broadcast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Defines HOW vote broadcasts are rendered.
|
||||
*
|
||||
* Terminology:
|
||||
* - BroadcastMsg : used when EXACTLY ONE item exists (single-site vote)
|
||||
* - Header : used ONCE when MULTIPLE items exist (batch/interval)
|
||||
* - ListLine : used ONCE PER ITEM when MULTIPLE items exist
|
||||
*
|
||||
* Placeholders (always available):
|
||||
* - %player% : player name (or "Server" for interval summaries)
|
||||
* - %site% : the current site/item for this line
|
||||
* - %sites_count% : number of items in the list
|
||||
* - %sites% : csv of items in the list
|
||||
* - %reason% : internal reason string ("vote", "batch", "interval", etc)
|
||||
*
|
||||
* Extra context placeholders (INTERVAL_SUMMARY_GLOBAL):
|
||||
* - %players% / %numberofplayers%
|
||||
* - %sites% / %numberofsites% (note: %sites% is csv; %numberofsites% is count)
|
||||
*/
|
||||
public final class BroadcastFormat {
|
||||
|
||||
private final String broadcastMsg;
|
||||
private final String header;
|
||||
private final String listLine;
|
||||
|
||||
public BroadcastFormat(String broadcastMsg, String header, String listLine) {
|
||||
this.broadcastMsg = broadcastMsg == null ? "" : broadcastMsg;
|
||||
this.header = header == null ? "" : header;
|
||||
this.listLine = listLine == null ? "" : listLine;
|
||||
}
|
||||
|
||||
public List<String> render(String playerName, List<String> items, String reason) {
|
||||
return render(playerName, items, reason, Collections.<String, String>emptyMap());
|
||||
}
|
||||
|
||||
public List<String> render(String playerName, List<String> items, String reason, Map<String, String> context) {
|
||||
List<String> output = new ArrayList<String>();
|
||||
int count = items == null ? 0 : items.size();
|
||||
|
||||
String csv = "";
|
||||
if (count > 0) {
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
for (String s : items) {
|
||||
if (s != null && !s.isEmpty()) {
|
||||
joiner.add(s);
|
||||
}
|
||||
}
|
||||
csv = joiner.toString();
|
||||
}
|
||||
|
||||
// SINGLE ITEM → BroadcastMsg
|
||||
if (count == 1 && !broadcastMsg.isEmpty()) {
|
||||
output.add(apply(broadcastMsg, playerName, items.get(0), count, csv, reason, context));
|
||||
return output;
|
||||
}
|
||||
|
||||
// MULTI ITEM → Header + ListLine per item
|
||||
if (!header.isEmpty()) {
|
||||
output.add(apply(header, playerName, "", count, csv, reason, context));
|
||||
}
|
||||
|
||||
if (count > 0 && !listLine.isEmpty()) {
|
||||
for (String s : items) {
|
||||
output.add(apply(listLine, playerName, s, count, csv, reason, context));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private String apply(String template,
|
||||
String player,
|
||||
String item,
|
||||
int count,
|
||||
String csv,
|
||||
String reason,
|
||||
Map<String, String> context) {
|
||||
|
||||
String out = template
|
||||
.replace("%player%", player == null ? "" : player)
|
||||
.replace("%site%", item == null ? "" : item)
|
||||
.replace("%sites_count%", String.valueOf(count))
|
||||
.replace("%sites%", csv == null ? "" : csv)
|
||||
.replace("%reason%", reason == null ? "" : reason);
|
||||
|
||||
if (context != null && !context.isEmpty()) {
|
||||
for (Map.Entry<String, String> e : context.entrySet()) {
|
||||
out = out.replace("%" + e.getKey() + "%", e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
+400
-46
@@ -1,76 +1,430 @@
|
||||
package com.bencodez.votingplugin.broadcast;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import com.bencodez.advancedcore.api.messages.PlaceholderUtils;
|
||||
import com.bencodez.advancedcore.api.misc.MiscUtils;
|
||||
import com.bencodez.simpleapi.messages.MessageAPI;
|
||||
import com.bencodez.simpleapi.time.ParsedDuration;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
|
||||
public class BroadcastHandler {
|
||||
private VotingPluginMain plugin;
|
||||
private ScheduledExecutorService timer;
|
||||
ConcurrentLinkedQueue<String> votedPlayers = new ConcurrentLinkedQueue<>();
|
||||
/**
|
||||
* Core broadcast logic.
|
||||
*
|
||||
* Decides WHEN to broadcast and builds lines/messages. Uses your existing
|
||||
* "eligible online players" behavior (disable broadcast respected).
|
||||
*
|
||||
* NOTE: Backend servers only.
|
||||
*/
|
||||
public final class BroadcastHandler {
|
||||
|
||||
public BroadcastHandler(VotingPluginMain plugin, int delay) {
|
||||
private final VotingPluginMain plugin;
|
||||
|
||||
/**
|
||||
* Only used for day-boundary logic (FIRST_VOTE_OF_DAY).
|
||||
*/
|
||||
private final ZoneId zoneId;
|
||||
|
||||
private volatile BroadcastSettings settings;
|
||||
|
||||
// Per-player cooldown tracking
|
||||
private final ConcurrentHashMap<UUID, Instant> lastBroadcastAt = new ConcurrentHashMap<UUID, Instant>();
|
||||
|
||||
// Batch window tracking
|
||||
private final ConcurrentHashMap<UUID, LinkedHashSet<String>> pendingSites = new ConcurrentHashMap<UUID, LinkedHashSet<String>>();
|
||||
private final ConcurrentHashMap<UUID, BukkitTask> pendingFlush = new ConcurrentHashMap<UUID, BukkitTask>();
|
||||
|
||||
// First vote of day tracking
|
||||
private final ConcurrentHashMap<UUID, LocalDate> firstVoteDay = new ConcurrentHashMap<UUID, LocalDate>();
|
||||
|
||||
// Interval summary tracking (uuid -> set of sites during interval)
|
||||
private final ConcurrentHashMap<UUID, LinkedHashSet<String>> intervalSites = new ConcurrentHashMap<UUID, LinkedHashSet<String>>();
|
||||
private volatile BukkitTask intervalTask;
|
||||
|
||||
public BroadcastHandler(VotingPluginMain plugin, BroadcastSettings settings, ZoneId zoneId) {
|
||||
this.plugin = plugin;
|
||||
schedule(delay);
|
||||
this.settings = settings;
|
||||
this.zoneId = zoneId == null ? ZoneId.systemDefault() : zoneId;
|
||||
|
||||
rescheduleIntervalIfNeeded();
|
||||
}
|
||||
|
||||
public void check() {
|
||||
int size = votedPlayers.size();
|
||||
if (size > 0) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
votedPlayers.poll();
|
||||
public void setSettings(BroadcastSettings settings) {
|
||||
this.settings = settings;
|
||||
rescheduleIntervalIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call whenever a vote is received.
|
||||
*
|
||||
* @param uuid player's uuid
|
||||
* @param playerName player name (optional; if null/empty, resolved from Bukkit)
|
||||
* @param siteName vote site name (display name)
|
||||
*/
|
||||
public void broadcastVote(UUID uuid, String playerName, String siteName, boolean wasOnline) {
|
||||
BroadcastSettings s = settings;
|
||||
if (s == null || s.isDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always collect for interval summaries (even if Type isn't interval right
|
||||
// now).
|
||||
recordInterval(uuid, siteName);
|
||||
|
||||
String name = playerName == null || playerName.isEmpty() ? resolveName(uuid) : playerName;
|
||||
|
||||
VoteBroadcastType type = s.getType();
|
||||
|
||||
// New: types that only broadcast if the voting player is online
|
||||
if (type == VoteBroadcastType.EVERY_VOTE_ONLINE_ONLY) {
|
||||
if (!wasOnline) {
|
||||
return;
|
||||
}
|
||||
String bc = MessageAPI.colorize(plugin.getConfigFile().getFormatAlternateBroadcastBroadcast());
|
||||
String playersText = "";
|
||||
while (!votedPlayers.isEmpty()) {
|
||||
playersText += votedPlayers.remove();
|
||||
if (!votedPlayers.isEmpty()) {
|
||||
playersText += ", ";
|
||||
}
|
||||
}
|
||||
HashMap<String, String> placeholders = new HashMap<>();
|
||||
placeholders.put("numberofplayers", "" + size);
|
||||
placeholders.put("players", playersText);
|
||||
bc = PlaceholderUtils.replacePlaceHolder(bc, placeholders);
|
||||
ArrayList<Player> players = new ArrayList<>();
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (!plugin.getVotingPluginUserManager().getVotingPluginUser(p).getDisableBroadcast()) {
|
||||
players.add(p);
|
||||
}
|
||||
broadcastNow(name, single(siteName), "vote_online_only", null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == VoteBroadcastType.EVERY_VOTE) {
|
||||
broadcastNow(name, single(siteName), "vote", null);
|
||||
|
||||
} else if (type == VoteBroadcastType.COOLDOWN_PER_PLAYER) {
|
||||
if (checkAndMarkCooldown(uuid, s.getDuration())) {
|
||||
broadcastNow(name, single(siteName), "cooldown", null);
|
||||
}
|
||||
|
||||
MiscUtils.getInstance().broadcast(bc, players);
|
||||
} else if (type == VoteBroadcastType.BATCH_WINDOW_PER_PLAYER) {
|
||||
bufferBatch(uuid, name, siteName, s.getDuration());
|
||||
|
||||
} else if (type == VoteBroadcastType.FIRST_VOTE_OF_DAY) {
|
||||
if (markFirstVoteOfDay(uuid)) {
|
||||
broadcastNow(name, single(siteName), "first_day", null);
|
||||
}
|
||||
|
||||
} else if (type == VoteBroadcastType.INTERVAL_SUMMARY_GLOBAL) {
|
||||
// handled by scheduled task
|
||||
}
|
||||
}
|
||||
|
||||
public void onVote(String player) {
|
||||
votedPlayers.add(player);
|
||||
}
|
||||
/*
|
||||
* ======================= Broadcast helpers =======================
|
||||
*/
|
||||
|
||||
public void schedule(int delay) {
|
||||
if (timer != null) {
|
||||
timer.shutdownNow();
|
||||
timer = Executors.newScheduledThreadPool(1);
|
||||
private void broadcastNow(String playerName, List<String> sites, String reason, Map<String, String> extraContext) {
|
||||
BroadcastSettings s = settings;
|
||||
if (s == null || s.isDisabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> cleaned = applyMaxSites(sites, s);
|
||||
cleaned.sort(new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String a, String b) {
|
||||
String aa = a == null ? "" : a.toLowerCase(Locale.ROOT);
|
||||
String bb = b == null ? "" : b.toLowerCase(Locale.ROOT);
|
||||
return aa.compareTo(bb);
|
||||
}
|
||||
});
|
||||
|
||||
List<String> lines;
|
||||
if (extraContext == null) {
|
||||
lines = s.getFormat().render(playerName, cleaned, reason);
|
||||
} else {
|
||||
timer = Executors.newScheduledThreadPool(1);
|
||||
lines = s.getFormat().render(playerName, cleaned, reason, extraContext);
|
||||
}
|
||||
timer.scheduleWithFixedDelay(new Runnable() {
|
||||
|
||||
for (String line : lines) {
|
||||
broadcastToEligiblePlayers(line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Your reliable broadcast style: - only sends to online players - respects
|
||||
* per-player disable broadcast toggle - runs PlaceholderAPI style per-player
|
||||
* placeholders (if your PlaceholderUtils does) - supports %newline% / %NewLine%
|
||||
* splitting
|
||||
*/
|
||||
private void broadcastToEligiblePlayers(String broadcastMsg) {
|
||||
if (broadcastMsg == null || broadcastMsg.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<Player> players = new ArrayList<Player>();
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
VotingPluginUser u = plugin.getVotingPluginUserManager().getVotingPluginUser(p);
|
||||
if (u != null && !u.getDisableBroadcast()) {
|
||||
players.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
// If you prefer your manual loop, keep it here (not in main)
|
||||
MiscUtils.getInstance().broadcast(broadcastMsg, players);
|
||||
|
||||
Bukkit.getServer().getConsoleSender().sendMessage(MessageAPI.colorize(broadcastMsg));
|
||||
}
|
||||
|
||||
/*
|
||||
* ======================= Cooldown logic (fixed millis) =======================
|
||||
*/
|
||||
|
||||
private boolean checkAndMarkCooldown(UUID uuid, ParsedDuration cooldown) {
|
||||
if (cooldown == null || cooldown.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant last = lastBroadcastAt.get(uuid);
|
||||
|
||||
if (last == null) {
|
||||
lastBroadcastAt.put(uuid, now);
|
||||
return true;
|
||||
}
|
||||
|
||||
Instant next = cooldown.addTo(last);
|
||||
if (!now.isBefore(next)) {
|
||||
lastBroadcastAt.put(uuid, now);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* ======================= Batch window logic (fixed millis)
|
||||
* =======================
|
||||
*/
|
||||
|
||||
private void bufferBatch(UUID uuid, String playerName, String siteName, ParsedDuration window) {
|
||||
if (siteName != null && !siteName.isEmpty()) {
|
||||
LinkedHashSet<String> set = pendingSites.get(uuid);
|
||||
if (set == null) {
|
||||
LinkedHashSet<String> created = new LinkedHashSet<String>();
|
||||
set = pendingSites.putIfAbsent(uuid, created);
|
||||
if (set == null) {
|
||||
set = created;
|
||||
}
|
||||
}
|
||||
synchronized (set) {
|
||||
set.add(siteName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pendingFlush.containsKey(uuid)) {
|
||||
BukkitTask task = scheduleBatchFlush(uuid, playerName, window);
|
||||
BukkitTask prev = pendingFlush.putIfAbsent(uuid, task);
|
||||
if (prev != null) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BukkitTask scheduleBatchFlush(final UUID uuid, final String playerName, ParsedDuration window) {
|
||||
long delayMs = window == null ? 1L : window.delayMillisFromNow();
|
||||
long ticks = Math.max(1L, delayMs / 50L);
|
||||
|
||||
return Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
check();
|
||||
try {
|
||||
flushBatch(uuid, playerName);
|
||||
} finally {
|
||||
pendingFlush.remove(uuid);
|
||||
}
|
||||
}
|
||||
}, 60, 60 * delay, TimeUnit.SECONDS);
|
||||
}, ticks);
|
||||
}
|
||||
|
||||
private void flushBatch(UUID uuid, String playerName) {
|
||||
Set<String> set = pendingSites.remove(uuid);
|
||||
if (set == null || set.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> list;
|
||||
synchronized (set) {
|
||||
list = new ArrayList<String>(set);
|
||||
}
|
||||
broadcastNow(playerName, list, "batch", null);
|
||||
}
|
||||
|
||||
/*
|
||||
* ======================= First vote of day (calendar) =======================
|
||||
*/
|
||||
|
||||
private boolean markFirstVoteOfDay(UUID uuid) {
|
||||
LocalDate today = LocalDate.now(zoneId);
|
||||
LocalDate last = firstVoteDay.putIfAbsent(uuid, today);
|
||||
|
||||
if (last == null) {
|
||||
return true;
|
||||
}
|
||||
if (!last.equals(today)) {
|
||||
firstVoteDay.put(uuid, today);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* ======================= Interval summary =======================
|
||||
*/
|
||||
|
||||
private void rescheduleIntervalIfNeeded() {
|
||||
if (intervalTask != null) {
|
||||
intervalTask.cancel();
|
||||
intervalTask = null;
|
||||
}
|
||||
|
||||
BroadcastSettings s = settings;
|
||||
if (s == null || s.getType() != VoteBroadcastType.INTERVAL_SUMMARY_GLOBAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
long delayMs = s.getDuration() == null ? 1L : s.getDuration().delayMillisFromNow();
|
||||
long ticks = Math.max(1L, delayMs / 50L);
|
||||
|
||||
intervalTask = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
broadcastIntervalSummary();
|
||||
}
|
||||
}, ticks, ticks);
|
||||
}
|
||||
|
||||
private void recordInterval(UUID uuid, String siteName) {
|
||||
if (siteName == null || siteName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LinkedHashSet<String> set = intervalSites.get(uuid);
|
||||
if (set == null) {
|
||||
LinkedHashSet<String> created = new LinkedHashSet<String>();
|
||||
set = intervalSites.putIfAbsent(uuid, created);
|
||||
if (set == null) {
|
||||
set = created;
|
||||
}
|
||||
}
|
||||
synchronized (set) {
|
||||
set.add(siteName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interval summary supports extra context placeholders: - %players% /
|
||||
* %numberofplayers% - %sites% / %numberofsites%
|
||||
*/
|
||||
private void broadcastIntervalSummary() {
|
||||
BroadcastSettings s = settings;
|
||||
if (s == null || s.isDisabled() || s.getType() != VoteBroadcastType.INTERVAL_SUMMARY_GLOBAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConcurrentHashMap<UUID, LinkedHashSet<String>> snapshot = new ConcurrentHashMap<UUID, LinkedHashSet<String>>(
|
||||
intervalSites);
|
||||
intervalSites.clear();
|
||||
|
||||
if (snapshot.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> entries = new ArrayList<String>();
|
||||
List<String> players = new ArrayList<String>();
|
||||
LinkedHashSet<String> uniqueSites = new LinkedHashSet<String>();
|
||||
|
||||
for (Map.Entry<UUID, LinkedHashSet<String>> entry : snapshot.entrySet()) {
|
||||
LinkedHashSet<String> siteSet = entry.getValue();
|
||||
if (siteSet == null || siteSet.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = resolveName(entry.getKey());
|
||||
players.add(name);
|
||||
|
||||
int siteCount;
|
||||
synchronized (siteSet) {
|
||||
siteCount = siteSet.size();
|
||||
for (String site : siteSet) {
|
||||
if (site != null && !site.isEmpty()) {
|
||||
uniqueSites.add(site);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entries.add(name + " (" + siteCount + ")");
|
||||
}
|
||||
|
||||
if (entries.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String playersCsv = join(players);
|
||||
String sitesCsv = join(new ArrayList<String>(uniqueSites));
|
||||
|
||||
ConcurrentHashMap<String, String> context = new ConcurrentHashMap<String, String>();
|
||||
context.put("players", playersCsv);
|
||||
context.put("numberofplayers", String.valueOf(players.size()));
|
||||
context.put("sites", sitesCsv);
|
||||
context.put("numberofsites", String.valueOf(uniqueSites.size()));
|
||||
|
||||
broadcastNow("Server", entries, "interval", context);
|
||||
}
|
||||
|
||||
/*
|
||||
* ======================= Utilities =======================
|
||||
*/
|
||||
|
||||
private List<String> single(String site) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
if (site != null && !site.isEmpty()) {
|
||||
list.add(site);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<String> applyMaxSites(List<String> sites, BroadcastSettings s) {
|
||||
if (sites == null) {
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
int max = s.getMaxSitesListed();
|
||||
if (max <= 0 || sites.size() <= max) {
|
||||
return new ArrayList<String>(sites);
|
||||
}
|
||||
return new ArrayList<String>(sites.subList(0, max));
|
||||
}
|
||||
|
||||
private String resolveName(UUID uuid) {
|
||||
try {
|
||||
OfflinePlayer op = Bukkit.getOfflinePlayer(uuid);
|
||||
String name = op == null ? null : op.getName();
|
||||
return name == null || name.isEmpty() ? "Player" : name;
|
||||
} catch (Exception e) {
|
||||
return "Player";
|
||||
}
|
||||
}
|
||||
|
||||
private String join(List<String> list) {
|
||||
StringJoiner joiner = new StringJoiner(", ");
|
||||
for (String s : list) {
|
||||
if (s != null && !s.isEmpty()) {
|
||||
joiner.add(s);
|
||||
}
|
||||
}
|
||||
return joiner.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.bencodez.votingplugin.broadcast;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import com.bencodez.simpleapi.time.ParsedDuration;
|
||||
|
||||
/**
|
||||
* Immutable broadcast configuration.
|
||||
*
|
||||
* Type: NONE disables broadcasting.
|
||||
*/
|
||||
public final class BroadcastSettings {
|
||||
|
||||
private final VoteBroadcastType type;
|
||||
private final ParsedDuration duration;
|
||||
private final int maxSitesListed;
|
||||
private final BroadcastFormat format;
|
||||
|
||||
public BroadcastSettings(VoteBroadcastType type, ParsedDuration duration, int maxSitesListed,
|
||||
BroadcastFormat format) {
|
||||
this.type = type == null ? VoteBroadcastType.NONE : type;
|
||||
this.duration = duration == null ? ParsedDuration.empty() : duration;
|
||||
this.maxSitesListed = Math.max(0, maxSitesListed);
|
||||
this.format = format == null ? new BroadcastFormat("", "", "") : format;
|
||||
}
|
||||
|
||||
public VoteBroadcastType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public ParsedDuration getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public int getMaxSitesListed() {
|
||||
return maxSitesListed;
|
||||
}
|
||||
|
||||
public BroadcastFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public boolean isDisabled() {
|
||||
return type == VoteBroadcastType.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads VoteBroadcast settings from config.yml.
|
||||
*
|
||||
* Expected structure: VoteBroadcast: Type: EVERY_VOTE Duration: 2m
|
||||
* MaxSitesListed: 0 Format: BroadcastMsg: '...' Header: '...' ListLine: '...'
|
||||
*/
|
||||
public static BroadcastSettings load(ConfigurationSection sec) {
|
||||
VoteBroadcastType type = VoteBroadcastType.parse(sec == null ? null : sec.getString("Type"),
|
||||
VoteBroadcastType.NONE);
|
||||
|
||||
ParsedDuration duration = ParsedDuration.parse(sec == null ? "2m" : sec.getString("Duration", "2m"),
|
||||
TimeUnit.MINUTES);
|
||||
|
||||
int maxSites = sec == null ? 0 : sec.getInt("MaxSitesListed", 0);
|
||||
|
||||
ConfigurationSection fmt = sec == null ? null : sec.getConfigurationSection("Format");
|
||||
|
||||
String broadcastMsg = fmt == null ? "&6[Vote] &aThanks &e%player% &afor voting on &e%site%&a!"
|
||||
: fmt.getString("BroadcastMsg", "&6[Vote] &aThanks &e%player% &afor voting on &e%site%&a!");
|
||||
|
||||
String header = fmt == null ? "&6[Vote] &a%player% voted! &7(%sites_count%)"
|
||||
: fmt.getString("Header", "&6[Vote] &a%player% voted! &7(%sites_count%)");
|
||||
|
||||
String listLine = fmt == null ? " &7- &e%site%" : fmt.getString("ListLine", " &7- &e%site%");
|
||||
|
||||
return new BroadcastSettings(type, duration, maxSites, new BroadcastFormat(broadcastMsg, header, listLine));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.bencodez.votingplugin.broadcast;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Defines WHEN vote broadcasts occur.
|
||||
*
|
||||
* Set Type: NONE to disable broadcasting entirely.
|
||||
*/
|
||||
public enum VoteBroadcastType {
|
||||
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Broadcast on every vote (even if the player is offline). Uses
|
||||
* Format.BroadcastMsg (+ optional header/list if you choose).
|
||||
*/
|
||||
EVERY_VOTE,
|
||||
|
||||
/**
|
||||
* Broadcast on every vote ONLY if the voting player is online. Useful when
|
||||
* processing offline votes but you don't want global spam for them.
|
||||
*/
|
||||
EVERY_VOTE_ONLINE_ONLY,
|
||||
|
||||
/**
|
||||
* Broadcast at most once per Duration per player. (Even if they vote multiple
|
||||
* sites inside the cooldown.)
|
||||
*/
|
||||
COOLDOWN_PER_PLAYER,
|
||||
|
||||
/**
|
||||
* Batch sites per player for Duration, then broadcast one message listing
|
||||
* sites.
|
||||
*/
|
||||
BATCH_WINDOW_PER_PLAYER,
|
||||
|
||||
/**
|
||||
* Broadcast only the first vote of the day per player (calendar day).
|
||||
*/
|
||||
FIRST_VOTE_OF_DAY,
|
||||
|
||||
/**
|
||||
* Every Duration, broadcast a global summary of who voted and how many sites.
|
||||
* Uses context placeholders: %players%, %numberofplayers%, %sites%,
|
||||
* %numberofsites%.
|
||||
*/
|
||||
INTERVAL_SUMMARY_GLOBAL;
|
||||
|
||||
public static VoteBroadcastType parse(String s, VoteBroadcastType def) {
|
||||
if (s == null || s.trim().isEmpty()) {
|
||||
return def;
|
||||
}
|
||||
try {
|
||||
return VoteBroadcastType.valueOf(s.trim().toUpperCase(Locale.ROOT));
|
||||
} catch (Exception ignored) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
+894
-441
File diff suppressed because it is too large.
Load diff
@@ -29,11 +29,10 @@ import com.bencodez.simpleapi.array.ArrayUtils;
|
||||
import com.bencodez.simpleapi.player.PlayerUtils;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.commands.gui.admin.AdminVoteVoteParty;
|
||||
import com.bencodez.votingplugin.commands.gui.admin.cumulative.AdminVoteCumulative;
|
||||
import com.bencodez.votingplugin.commands.gui.admin.milestones.AdminVoteMilestones;
|
||||
import com.bencodez.votingplugin.commands.gui.admin.milestones.AdminVoteVoteMilestones;
|
||||
import com.bencodez.votingplugin.commands.gui.admin.voteshop.AdminVoteVoteShop;
|
||||
import com.bencodez.votingplugin.events.PlayerVoteEvent;
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
public class AdminGUI {
|
||||
|
||||
@@ -65,7 +64,7 @@ public class AdminGUI {
|
||||
plugin.getConfigVoteSites().generateVoteSite(value);
|
||||
player.sendMessage("Generated site");
|
||||
plugin.reload();
|
||||
openAdminGUIVoteSiteSite(player, plugin.getVoteSite(value, true));
|
||||
openAdminGUIVoteSiteSite(player, plugin.getVoteSiteManager().getVoteSite(value, true));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -82,19 +81,11 @@ public class AdminGUI {
|
||||
}
|
||||
});
|
||||
|
||||
buttons.add(new BInventoryButton(new ItemBuilder(Material.DIAMOND_BLOCK, 1).setName("&cEdit Milestones")) {
|
||||
buttons.add(new BInventoryButton(new ItemBuilder(Material.DIAMOND_BLOCK, 1).setName("&cEdit VoteMilestones")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteMilestones(plugin, clickEvent.getPlayer()).open(GUIMethod.CHEST);
|
||||
}
|
||||
});
|
||||
|
||||
buttons.add(new BInventoryButton(new ItemBuilder(Material.COBBLESTONE, 1).setName("&cEdit Cumulative")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteCumulative(plugin, clickEvent.getPlayer()).open(GUIMethod.CHEST);
|
||||
new AdminVoteVoteMilestones(plugin, clickEvent.getPlayer()).open(GUIMethod.CHEST);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -240,7 +231,7 @@ public class AdminGUI {
|
||||
public void openAdminGUIVoteSites(Player player) {
|
||||
BInventory inv = new BInventory("VoteSites");
|
||||
int count = 0;
|
||||
for (VoteSite voteSite : plugin.getVoteSites()) {
|
||||
for (VoteSite voteSite : plugin.getVoteSiteManager().getVoteSites()) {
|
||||
ArrayList<String> lore = new ArrayList<>();
|
||||
lore.add("Enabled: " + voteSite.isEnabled());
|
||||
lore.add("Priority: " + voteSite.getPriority());
|
||||
@@ -249,7 +240,6 @@ public class AdminGUI {
|
||||
lore.add("ServiceSite: " + voteSite.getServiceSite());
|
||||
lore.add("VoteURL: " + voteSite.getVoteURL());
|
||||
lore.add("VoteDelay: " + voteSite.getVoteDelay());
|
||||
lore.add("VoteDelayMin: " + voteSite.getVoteDelayMin());
|
||||
|
||||
inv.addButton(count,
|
||||
new BInventoryButton(voteSite.getKey(), ArrayUtils.convert(lore), new ItemStack(Material.STONE)) {
|
||||
@@ -349,24 +339,13 @@ public class AdminGUI {
|
||||
}
|
||||
}));
|
||||
|
||||
inv.addButton(new EditGUIButton(new EditGUIValueNumber("VoteDelay", voteSite.getVoteDelay()) {
|
||||
inv.addButton(new EditGUIButton(new EditGUIValueString("VoteDelay", voteSite.getVoteDelay()) {
|
||||
|
||||
@Override
|
||||
public void setValue(Player player, Number num) {
|
||||
public void setValue(Player player, String value) {
|
||||
VoteSite voteSite = (VoteSite) getInv().getMeta(player, "VoteSite");
|
||||
String siteName = voteSite.getKey();
|
||||
plugin.getConfigVoteSites().setVoteDelay(siteName, num.intValue());
|
||||
plugin.reload();
|
||||
}
|
||||
}));
|
||||
|
||||
inv.addButton(new EditGUIButton(new EditGUIValueNumber("VoteDelayMin", voteSite.getVoteDelay()) {
|
||||
|
||||
@Override
|
||||
public void setValue(Player player, Number num) {
|
||||
VoteSite voteSite = (VoteSite) getInv().getMeta(player, "VoteSite");
|
||||
String siteName = voteSite.getKey();
|
||||
plugin.getConfigVoteSites().setVoteDelay(siteName, num.intValue());
|
||||
plugin.getConfigVoteSites().setVoteDelay(siteName, value);
|
||||
plugin.reload();
|
||||
}
|
||||
}));
|
||||
@@ -377,7 +356,7 @@ public class AdminGUI {
|
||||
public void setValue(Player player, Number num) {
|
||||
VoteSite voteSite = (VoteSite) getInv().getMeta(player, "VoteSite");
|
||||
String siteName = voteSite.getKey();
|
||||
plugin.getConfigVoteSites().setVoteDelay(siteName, num.intValue());
|
||||
plugin.getConfigVoteSites().setVoteDelayDailyHour(siteName, num.intValue());
|
||||
plugin.reload();
|
||||
}
|
||||
}));
|
||||
|
||||
-3
@@ -73,9 +73,6 @@ public class AdminVotePlaceholdersPlayer extends GUIHandler {
|
||||
ArrayList<String> msg = new ArrayList<>();
|
||||
msg.add("&cPlaceholders:");
|
||||
VotingPluginUser placeholderUser = user;
|
||||
if (plugin.getConfigFile().isUsePrimaryAccountForPlaceholders() && user.hasPrimaryAccount()) {
|
||||
placeholderUser = plugin.getVotingPluginUserManager().getVotingPluginUser(user.getPrimaryAccount());
|
||||
}
|
||||
for (PlaceHolder<VotingPluginUser> placeholder : plugin.getPlaceholders().getPlaceholders()) {
|
||||
String identifier = placeholder.getIdentifier().toLowerCase();
|
||||
if (identifier.endsWith("_")) {
|
||||
|
||||
+2
-1
@@ -21,6 +21,7 @@ import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.advancedcore.api.rewards.RewardBuilder;
|
||||
import com.bencodez.advancedcore.api.user.UserDataFetchMode;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.commands.gui.player.VoteGUI;
|
||||
import com.bencodez.votingplugin.topvoter.TopVoterPlayer;
|
||||
@@ -63,7 +64,7 @@ public class AdminVoteTopPoints extends GUIHandler {
|
||||
for (String uuid : plugin.getVotingPluginUserManager().getAllUUIDs()) {
|
||||
VotingPluginUser vpUser = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(UUID.fromString(uuid));
|
||||
vpUser.dontCache();
|
||||
vpUser.userDataFetechMode(UserDataFetchMode.NO_CACHE);
|
||||
int points = vpUser.getPoints();
|
||||
if (points > 0) {
|
||||
topPoints1.put(vpUser.getTopVoterPlayer(), points);
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.inventory.editgui.EditGUI;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.events.PlayerVoteEvent;
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
public class AdminVoteVotePlayer extends GUIHandler {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class AdminVoteVotePlayer extends GUIHandler {
|
||||
EditGUI inv = new EditGUI("Trigger vote for " + playerName);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.Vote|VotingPlugin.Admin");
|
||||
|
||||
for (VoteSite site : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
inv.addButton(new BInventoryButton(site.getItem().setName(site.getKey())) {
|
||||
|
||||
@Override
|
||||
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.cumulative;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.advancedcore.api.valuerequest.InputMethod;
|
||||
import com.bencodez.advancedcore.api.valuerequest.ValueRequest;
|
||||
import com.bencodez.advancedcore.api.valuerequest.ValueRequestBuilder;
|
||||
import com.bencodez.advancedcore.api.valuerequest.listeners.NumberListener;
|
||||
import com.bencodez.advancedcore.command.gui.RewardEditGUI;
|
||||
import com.bencodez.simpleapi.messages.MessageAPI;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
|
||||
public class AdminVoteCumulative extends GUIHandler {
|
||||
|
||||
private VotingPluginMain plugin;
|
||||
|
||||
public AdminVoteCumulative(VotingPluginMain plugin, CommandSender player) {
|
||||
super(plugin, player);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
BInventory inv = new BInventory("Edit Cumulative");
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.Edit.Cumulative");
|
||||
inv.addButton(
|
||||
new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&cEdit existing cumulative rewards")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
ArrayList<Integer> nums = new ArrayList<>();
|
||||
for (String num : plugin.getSpecialRewardsConfig().getCumulativeVotes()) {
|
||||
if (MessageAPI.isInt(num)) {
|
||||
nums.add(Integer.parseInt(num));
|
||||
}
|
||||
}
|
||||
Number[] options = new Number[nums.size()];
|
||||
for (int i = 0; i < nums.size(); i++) {
|
||||
options[i] = nums.get(i);
|
||||
}
|
||||
new ValueRequestBuilder(new NumberListener() {
|
||||
|
||||
@Override
|
||||
public void onInput(Player player, Number value) {
|
||||
RewardEditGUI.getInstance().openRewardGUI(clickEvent.getPlayer(),
|
||||
plugin.getRewardHandler()
|
||||
.getDirectlyDefined("Cumulative." + value.intValue() + ".Rewards"));
|
||||
}
|
||||
}, options).allowCustomOption(false).usingMethod(InputMethod.INVENTORY)
|
||||
.request(clickEvent.getPlayer());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.EMERALD_BLOCK).setName("&aAdd cumulative reward")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new ValueRequest().requestNumber(player, new NumberListener() {
|
||||
|
||||
@Override
|
||||
public void onInput(Player player, Number value) {
|
||||
plugin.getSpecialRewardsConfig().setCumulative(value.intValue());
|
||||
plugin.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.REDSTONE_BLOCK).setName("&cRemove cumulative")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteCumulativeRemove(plugin, clickEvent.getPlayer()).open();
|
||||
}
|
||||
});
|
||||
inv.openInventory(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.cumulative;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.commands.gui.admin.AdminVoteConfirmation;
|
||||
|
||||
public class AdminVoteCumulativeRemove extends GUIHandler {
|
||||
|
||||
private VotingPluginMain plugin;
|
||||
|
||||
public AdminVoteCumulativeRemove(VotingPluginMain plugin, CommandSender player) {
|
||||
super(plugin, player);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
BInventory inv = new BInventory("Remove cumulative");
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.Edit.Cumulative");
|
||||
for (final String votes : plugin.getSpecialRewardsConfig().getCumulativeVotes()) {
|
||||
inv.addButton(new BInventoryButton(
|
||||
new ItemBuilder(Material.PAPER, 1).setName(votes).addLoreLine("&c&lClick to remove")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteConfirmation(plugin, clickEvent.getPlayer(), "Remove cumulative " + votes + "?") {
|
||||
|
||||
@Override
|
||||
public void onConfirm(Player p) {
|
||||
plugin.getSpecialRewardsConfig().removeCumulative(votes);
|
||||
p.sendMessage("Removed cumulative " + votes);
|
||||
plugin.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeny(Player p) {
|
||||
new AdminVoteCumulative(plugin, p);
|
||||
}
|
||||
}.open();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
inv.openInventory(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
|
||||
}
|
||||
+7
-7
@@ -15,11 +15,11 @@ import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.commands.gui.admin.AdminVoteConfirmation;
|
||||
|
||||
public class AdminVoteMilestoneRemove extends GUIHandler {
|
||||
public class AdminVoteVoteMilestoneRemove extends GUIHandler {
|
||||
|
||||
private VotingPluginMain plugin;
|
||||
|
||||
public AdminVoteMilestoneRemove(VotingPluginMain plugin, CommandSender player) {
|
||||
public AdminVoteVoteMilestoneRemove(VotingPluginMain plugin, CommandSender player) {
|
||||
super(plugin, player);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
@@ -40,9 +40,9 @@ public class AdminVoteMilestoneRemove extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
BInventory inv = new BInventory("Remove milestones");
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.Edit.MileStones");
|
||||
for (final String votes : plugin.getSpecialRewardsConfig().getMilestoneVotes()) {
|
||||
BInventory inv = new BInventory("Remove VoteMilestones");
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.Edit.VoteMilestones");
|
||||
for (final String votes : plugin.getVoteMilestonesManager().getConfig().getMilestones().keySet()) {
|
||||
inv.addButton(new BInventoryButton(
|
||||
new ItemBuilder(Material.PAPER, 1).setName(votes).addLoreLine("&c&lClick to remove")) {
|
||||
|
||||
@@ -52,14 +52,14 @@ public class AdminVoteMilestoneRemove extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onConfirm(Player p) {
|
||||
plugin.getSpecialRewardsConfig().removeMilestone(votes);
|
||||
plugin.getSpecialRewardsConfig().removeVoteMilestone(votes);
|
||||
p.sendMessage("Removed milestone " + votes);
|
||||
plugin.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeny(Player p) {
|
||||
new AdminVoteMilestones(plugin, p);
|
||||
new AdminVoteVoteMilestones(plugin, p);
|
||||
}
|
||||
}.open();
|
||||
|
||||
+29
-32
@@ -1,6 +1,7 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.milestones;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -16,15 +17,16 @@ import com.bencodez.advancedcore.api.valuerequest.InputMethod;
|
||||
import com.bencodez.advancedcore.api.valuerequest.ValueRequest;
|
||||
import com.bencodez.advancedcore.api.valuerequest.ValueRequestBuilder;
|
||||
import com.bencodez.advancedcore.api.valuerequest.listeners.NumberListener;
|
||||
import com.bencodez.advancedcore.api.valuerequest.listeners.StringListener;
|
||||
import com.bencodez.advancedcore.command.gui.RewardEditGUI;
|
||||
import com.bencodez.simpleapi.messages.MessageAPI;
|
||||
import com.bencodez.simpleapi.array.ArrayUtils;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
|
||||
public class AdminVoteMilestones extends GUIHandler {
|
||||
public class AdminVoteVoteMilestones extends GUIHandler {
|
||||
|
||||
private VotingPluginMain plugin;
|
||||
|
||||
public AdminVoteMilestones(VotingPluginMain plugin, CommandSender player) {
|
||||
public AdminVoteVoteMilestones(VotingPluginMain plugin, CommandSender player) {
|
||||
super(plugin, player);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
@@ -45,36 +47,31 @@ public class AdminVoteMilestones extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
BInventory inv = new BInventory("Edit MileStones");
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.Edit.MileStones");
|
||||
inv.addButton(
|
||||
new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&cEdit existing milestone rewards")) {
|
||||
BInventory inv = new BInventory("Edit VoteMilestones");
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.Edit.VoteMilestones");
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER)
|
||||
.setName("&cEdit existing vote milestone rewards (Legacy milestones not included)")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
Set<String> keys = plugin.getVoteMilestonesManager().getConfig().getMilestones().keySet();
|
||||
for (String key : keys) {
|
||||
if (key.startsWith("Legacy_")) {
|
||||
keys.remove(key);
|
||||
}
|
||||
}
|
||||
new ValueRequestBuilder(new StringListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
ArrayList<Integer> nums = new ArrayList<>();
|
||||
for (String num : plugin.getSpecialRewardsConfig().getMilestoneVotes()) {
|
||||
if (MessageAPI.isInt(num)) {
|
||||
nums.add(Integer.parseInt(num));
|
||||
}
|
||||
}
|
||||
Number[] options = new Number[nums.size()];
|
||||
for (int i = 0; i < nums.size(); i++) {
|
||||
options[i] = nums.get(i);
|
||||
}
|
||||
new ValueRequestBuilder(new NumberListener() {
|
||||
|
||||
@Override
|
||||
public void onInput(Player player, Number value) {
|
||||
RewardEditGUI.getInstance().openRewardGUI(clickEvent.getPlayer(),
|
||||
plugin.getRewardHandler()
|
||||
.getDirectlyDefined("MileStones." + value.intValue() + ".Rewards"));
|
||||
}
|
||||
}, options).allowCustomOption(false).usingMethod(InputMethod.INVENTORY)
|
||||
.request(clickEvent.getPlayer());
|
||||
|
||||
public void onInput(Player player, String value) {
|
||||
RewardEditGUI.getInstance().openRewardGUI(clickEvent.getPlayer(),
|
||||
plugin.getRewardHandler().getDirectlyDefined("VoteMilestones." + value + ".Rewards"));
|
||||
}
|
||||
});
|
||||
}, ArrayUtils.convertSet(keys)).allowCustomOption(false).usingMethod(InputMethod.INVENTORY)
|
||||
.request(clickEvent.getPlayer());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.EMERALD_BLOCK).setName("&aAdd milestone")) {
|
||||
|
||||
@@ -84,7 +81,7 @@ public class AdminVoteMilestones extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onInput(Player player, Number value) {
|
||||
plugin.getSpecialRewardsConfig().setMilestone(value.intValue());
|
||||
plugin.getSpecialRewardsConfig().setVoteMilestone(value.intValue());
|
||||
plugin.reload();
|
||||
}
|
||||
});
|
||||
@@ -95,7 +92,7 @@ public class AdminVoteMilestones extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteMilestoneRemove(plugin, clickEvent.getPlayer()).open();
|
||||
new AdminVoteVoteMilestoneRemove(plugin, clickEvent.getPlayer()).open();
|
||||
}
|
||||
});
|
||||
inv.openInventory(player);
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: Select an event filter, then open AdminVoteLogRecent (filtered).
|
||||
*/
|
||||
public class AdminVoteLogEventSelect extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int days;
|
||||
private final int page;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogEventSelect(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days) {
|
||||
this(plugin, sender, table, user, days, 0);
|
||||
}
|
||||
|
||||
public AdminVoteLogEventSelect(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
this.days = days;
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Events";
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
List<VoteLogMysqlTable.VoteLogEvent> events = Arrays.asList(VoteLogMysqlTable.VoteLogEvent.values());
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(events.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= events.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo events")
|
||||
.addLoreLine("&7No events on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
VoteLogMysqlTable.VoteLogEvent ev = events.get(i);
|
||||
inv.addButton(makeEventButton(ev));
|
||||
}
|
||||
}
|
||||
|
||||
// back button
|
||||
if (user != null && plugin.getGui().isChestVoteTopBackButton()) {
|
||||
inv.getPageButtons().add(plugin.getCommandLoader().getBackButton(user).setSlot(7));
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makeEventButton(VoteLogMysqlTable.VoteLogEvent ev) {
|
||||
ItemBuilder item = new ItemBuilder(Material.BOOK).setName("&a" + ev.name())
|
||||
.addLoreLine("&7Click to view recent logs filtered by this event")
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time");
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogRecent(plugin, clickEvent.getPlayer(), table, user, 0, days, ev).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
public class AdminVoteLogHelpers {
|
||||
public static Material getMaterialForEvent(VoteLogMysqlTable.VoteLogEvent event, String status) {
|
||||
// Cached entries still override to chest (keeps your current behavior)
|
||||
if ("CACHED".equalsIgnoreCase(status)) {
|
||||
return Material.CHEST;
|
||||
}
|
||||
|
||||
if (event == null) {
|
||||
return Material.PAPER;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case VOTE_RECEIVED:
|
||||
return Material.EMERALD;
|
||||
|
||||
case VOTEMILESTONE:
|
||||
return Material.ANVIL;
|
||||
|
||||
case VOTE_STREAK_REWARD:
|
||||
return Material.FIREWORK_ROCKET;
|
||||
|
||||
case TOP_VOTER_REWARD:
|
||||
return Material.GOLD_BLOCK;
|
||||
|
||||
default:
|
||||
return Material.PAPER;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getEventColor(VoteLogMysqlTable.VoteLogEvent event) {
|
||||
if (event == null) {
|
||||
return "&7";
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case VOTE_RECEIVED:
|
||||
return "&a";
|
||||
case VOTEMILESTONE:
|
||||
return "&6";
|
||||
|
||||
case VOTE_STREAK_REWARD:
|
||||
return "&d";
|
||||
|
||||
case TOP_VOTER_REWARD:
|
||||
return "&c";
|
||||
|
||||
default:
|
||||
return "&7";
|
||||
}
|
||||
}
|
||||
|
||||
public static String safe(String s) {
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
|
||||
public static boolean notEmpty(String s) {
|
||||
return s != null && !s.trim().isEmpty();
|
||||
}
|
||||
|
||||
public static String formatTime(long millis) {
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(new Date(millis));
|
||||
} catch (Exception e) {
|
||||
return String.valueOf(millis);
|
||||
}
|
||||
}
|
||||
|
||||
public static String shortUuid(String uuid) {
|
||||
if (uuid == null || uuid.isEmpty()) {
|
||||
return "unknown";
|
||||
}
|
||||
return uuid.length() > 8 ? uuid.substring(0, 8) : uuid;
|
||||
}
|
||||
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
public class AdminVoteLogMenu extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int days; // window used by selectors/stats (0 = all time)
|
||||
|
||||
// Default to "voting" (Vote received)
|
||||
private final VoteLogMysqlTable.VoteLogEvent defaultEvent = VoteLogMysqlTable.VoteLogEvent.VOTE_RECEIVED;
|
||||
|
||||
public AdminVoteLogMenu(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table, int days) {
|
||||
this(plugin, sender, table, null, days);
|
||||
}
|
||||
|
||||
public AdminVoteLogMenu(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
this.days = Math.max(0, days);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Admin";
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.NAME_TAG).setName("&aVotes by Player")
|
||||
.addLoreLine("&7List stored player names")
|
||||
.addLoreLine("&7Click a player to view their votelog")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogPlayerSelect(plugin, clickEvent.getPlayer(), table, user, days, 0).open();
|
||||
}
|
||||
});
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.NAME_TAG).setName("&aVotes by Player (Online)")
|
||||
.addLoreLine("&7List online players")
|
||||
.addLoreLine("&7Click a player to view their votelog")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogPlayerSelectOnline(plugin, clickEvent.getPlayer(), table, user, days, 0).open();
|
||||
}
|
||||
});
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&aVotes by Service")
|
||||
.addLoreLine("&7List all services found")
|
||||
.addLoreLine("&7Click a service to view votelog")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogServiceSelect(plugin, clickEvent.getPlayer(), table, user, days, 0).open();
|
||||
}
|
||||
});
|
||||
|
||||
// NEW: Votes by Server
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.COMPASS).setName("&aVotes by Server")
|
||||
.addLoreLine("&7List all servers found")
|
||||
.addLoreLine("&7Click a server to view votelog")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogServerSelect(plugin, clickEvent.getPlayer(), table, user, days, 0).open();
|
||||
}
|
||||
});
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.MAP).setName("&aStats")
|
||||
.addLoreLine("&7Overview counts/uniques/top services")
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogStats(plugin, clickEvent.getPlayer(), table, user, days, 10).open();
|
||||
}
|
||||
});
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.CLOCK).setName("&aRecent Logs")
|
||||
.addLoreLine("&7Recent logs filtered by event")
|
||||
.addLoreLine("&7Default: &f" + defaultEvent.name())
|
||||
.addLoreLine("&8(Use bottom buttons to switch event)")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// Open recent with default event filter
|
||||
new AdminVoteLogRecent(plugin, clickEvent.getPlayer(), table, user, 0, days, defaultEvent).open();
|
||||
}
|
||||
});
|
||||
|
||||
addEventSwitchButtons(inv);
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void addEventSwitchButtons(BInventory inv) {
|
||||
inv.getPageButtons().add(new BInventoryButton(new ItemBuilder(Material.LIME_DYE)
|
||||
.setName("&aEvent: &fVOTE_RECEIVED").addLoreLine("&7Show recent vote received events")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogRecent(plugin, clickEvent.getPlayer(), table, user, 0, days,
|
||||
VoteLogMysqlTable.VoteLogEvent.VOTE_RECEIVED).open();
|
||||
}
|
||||
}.setSlot(3));
|
||||
|
||||
// More... (open selector)
|
||||
inv.getPageButtons().add(new BInventoryButton(
|
||||
new ItemBuilder(Material.BOOK).setName("&aEvent: &fMore...").addLoreLine("&7Pick any event filter")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogEventSelect(plugin, clickEvent.getPlayer(), table, user, days).open();
|
||||
}
|
||||
}.setSlot(4));
|
||||
|
||||
// All events
|
||||
inv.getPageButtons().add(new BInventoryButton(new ItemBuilder(Material.GRAY_DYE).setName("&aEvent: &fALL")
|
||||
.addLoreLine("&7Show recent logs for all events")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogRecent(plugin, clickEvent.getPlayer(), table, user, 0, days, null).open();
|
||||
}
|
||||
}.setSlot(5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: VoteLog entries for a given player (paged).
|
||||
*
|
||||
* Uses VoteLogMysqlTable instance passed in from CommandLoader.
|
||||
*
|
||||
* Supports input as player name OR uuid string (you decide in CommandLoader
|
||||
* which constructor to call).
|
||||
*/
|
||||
public class AdminVoteLogPlayer extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private final int page;
|
||||
|
||||
private final String playerName;
|
||||
|
||||
private final int days;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogPlayer(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table, String playerName,
|
||||
int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.playerName = playerName;
|
||||
this.days = days;
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Player";
|
||||
if (playerName != null && !playerName.isEmpty()) {
|
||||
title += " &7(" + playerName + ")";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
int needed = (page + 1) * PAGE_SIZE;
|
||||
|
||||
List<VoteLogMysqlTable.VoteLogEntry> rows = table.getByPlayerName(playerName, days, needed);
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(rows.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= rows.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo entries")
|
||||
.addLoreLine("&7No vote log entries on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
inv.addButton(makeEntryButton(rows.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makeEntryButton(final VoteLogMysqlTable.VoteLogEntry entry) {
|
||||
Material mat = "CACHED".equalsIgnoreCase(entry.status) ? Material.CHEST : Material.EMERALD;
|
||||
|
||||
String timeStr = AdminVoteLogHelpers.formatTime(entry.voteTime);
|
||||
String uuidShort = AdminVoteLogHelpers.shortUuid(entry.playerUuid);
|
||||
String voteShort = AdminVoteLogHelpers.shortUuid(entry.voteId);
|
||||
|
||||
// keep same name/lore layout you already have
|
||||
ItemBuilder item = new ItemBuilder(mat)
|
||||
.setName("&a" + AdminVoteLogHelpers.safe(entry.event) + " &7(" + voteShort + ")");
|
||||
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.playerName) || AdminVoteLogHelpers.notEmpty(entry.playerUuid)) {
|
||||
item.addLoreLine("&7Player: &f" + AdminVoteLogHelpers.safe(entry.playerName) + " &7(" + uuidShort + ")");
|
||||
}
|
||||
if (entry.voteTime > 0) {
|
||||
item.addLoreLine("&7Time: &f" + timeStr);
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.service)) {
|
||||
item.addLoreLine("&7Service: &f" + AdminVoteLogHelpers.safe(entry.service));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.context)) {
|
||||
item.addLoreLine("&7Context: &f" + AdminVoteLogHelpers.safe(entry.context));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.status)) {
|
||||
item.addLoreLine("&7Status: &f" + AdminVoteLogHelpers.safe(entry.status));
|
||||
}
|
||||
if (entry.proxyCachedTotal != 0) {
|
||||
item.addLoreLine("&7Cached Total: &f" + entry.proxyCachedTotal);
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.voteId)) {
|
||||
item.addLoreLine("&7VoteId: &f" + AdminVoteLogHelpers.safe(entry.voteId));
|
||||
}
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// vote_id is now the correlation id entry.voteId
|
||||
new AdminVoteLogVoteId(plugin, clickEvent.getPlayer(), table, entry.voteId, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: Select an ONLINE player, then open AdminVoteLogPlayer.
|
||||
*/
|
||||
public class AdminVoteLogPlayerSelect extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int days;
|
||||
private final int page;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogPlayerSelect(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
this.days = Math.max(0, days);
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Players";
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Player> online = new ArrayList<>(Bukkit.getOnlinePlayers());
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(online.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= online.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo players")
|
||||
.addLoreLine("&7No online players on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
Player p = online.get(i);
|
||||
inv.addButton(makePlayerButton(p));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makePlayerButton(final Player target) {
|
||||
String name = target.getName();
|
||||
|
||||
ItemBuilder item = new ItemBuilder(Material.NAME_TAG).setName("&a" + name)
|
||||
.addLoreLine("&7Click to open votelog for this player")
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time");
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogPlayer(plugin, clickEvent.getPlayer(), table, name, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: Select an ONLINE player, then open AdminVoteLogPlayer.
|
||||
*/
|
||||
public class AdminVoteLogPlayerSelectOnline extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int days;
|
||||
private final int page;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogPlayerSelectOnline(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
this.days = days;
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Players";
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
}
|
||||
});
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Player> online = new ArrayList<>(Bukkit.getOnlinePlayers());
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(online.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= online.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo players")
|
||||
.addLoreLine("&7No online players on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
Player p = online.get(i);
|
||||
inv.addButton(makePlayerButton(p));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makePlayerButton(Player target) {
|
||||
String name = target.getName();
|
||||
|
||||
ItemBuilder item = new ItemBuilder(Material.NAME_TAG).setName("&a" + name)
|
||||
.addLoreLine("&7Click to open votelog for this player")
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time");
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogPlayer(plugin, clickEvent.getPlayer(), table, name, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: Recent VoteLog entries (paged).
|
||||
*
|
||||
* Now supports optional event filter + days window.
|
||||
*/
|
||||
public class AdminVoteLogRecent extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int page;
|
||||
|
||||
private final int days; // 0 = all time
|
||||
private final VoteLogMysqlTable.VoteLogEvent event; // null = all events
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogRecent(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table, int page) {
|
||||
this(plugin, sender, table, null, page, 0, null);
|
||||
}
|
||||
|
||||
public AdminVoteLogRecent(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int page) {
|
||||
this(plugin, sender, table, user, page, 0, null);
|
||||
}
|
||||
|
||||
// NEW constructor used by Menu/EventSelect
|
||||
public AdminVoteLogRecent(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int page, int days, VoteLogMysqlTable.VoteLogEvent event) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
this.page = Math.max(0, page);
|
||||
this.days = Math.max(0, days);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Recent";
|
||||
if (event != null) {
|
||||
title += " &7(" + event.name() + ")";
|
||||
}
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
int needed = (page + 1) * PAGE_SIZE;
|
||||
|
||||
List<VoteLogMysqlTable.VoteLogEntry> rows;
|
||||
if (event == null) {
|
||||
rows = (days > 0) ? table.getRecentAll(days, needed) : table.getRecent(needed);
|
||||
} else {
|
||||
rows = table.getRecentByEvent(event, days, needed);
|
||||
}
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(rows.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= rows.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo entries")
|
||||
.addLoreLine("&7No vote log entries on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
inv.addButton(makeEntryButton(rows.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
addEventSwitchButtons(inv);
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void addEventSwitchButtons(BInventory inv) {
|
||||
inv.getPageButtons().add(new BInventoryButton(new ItemBuilder(Material.LIME_DYE)
|
||||
.setName("&aEvent: &fVOTE_RECEIVED").addLoreLine("&7Show recent vote received events")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogRecent(plugin, clickEvent.getPlayer(), table, user, 0, days,
|
||||
VoteLogMysqlTable.VoteLogEvent.VOTE_RECEIVED).open();
|
||||
}
|
||||
}.setSlot(3));
|
||||
|
||||
// More... (open selector)
|
||||
inv.getPageButtons().add(new BInventoryButton(
|
||||
new ItemBuilder(Material.BOOK).setName("&aEvent: &fMore...").addLoreLine("&7Pick any event filter")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogEventSelect(plugin, clickEvent.getPlayer(), table, user, days).open();
|
||||
}
|
||||
}.setSlot(4));
|
||||
|
||||
// All events
|
||||
inv.getPageButtons().add(new BInventoryButton(new ItemBuilder(Material.GRAY_DYE).setName("&aEvent: &fALL")
|
||||
.addLoreLine("&7Show recent logs for all events")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogRecent(plugin, clickEvent.getPlayer(), table, user, 0, days, null).open();
|
||||
}
|
||||
}.setSlot(5));
|
||||
}
|
||||
|
||||
private BInventoryButton makeEntryButton(final VoteLogMysqlTable.VoteLogEntry entry) {
|
||||
VoteLogMysqlTable.VoteLogEvent event = entry.event != null ? VoteLogMysqlTable.VoteLogEvent.valueOf(entry.event)
|
||||
: null;
|
||||
|
||||
Material mat = AdminVoteLogHelpers.getMaterialForEvent(event, entry.status);
|
||||
|
||||
String eventColor = AdminVoteLogHelpers.getEventColor(event);
|
||||
|
||||
String timeStr = AdminVoteLogHelpers.formatTime(entry.voteTime);
|
||||
String uuidShort = AdminVoteLogHelpers.shortUuid(entry.playerUuid);
|
||||
String voteShort = AdminVoteLogHelpers.shortUuid(entry.voteId);
|
||||
|
||||
ItemBuilder item = new ItemBuilder(mat)
|
||||
.setName(eventColor + AdminVoteLogHelpers.safe(entry.event) + " &7(" + voteShort + ")");
|
||||
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.playerName) || AdminVoteLogHelpers.notEmpty(entry.playerUuid)) {
|
||||
item.addLoreLine("&7Player: &f" + AdminVoteLogHelpers.safe(entry.playerName) + " &7(" + uuidShort + ")");
|
||||
}
|
||||
if (entry.voteTime > 0) {
|
||||
item.addLoreLine("&7Time: &f" + timeStr);
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.service)) {
|
||||
item.addLoreLine("&7Service: &f" + AdminVoteLogHelpers.safe(entry.service));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.context)) {
|
||||
item.addLoreLine("&7Context: &f" + AdminVoteLogHelpers.safe(entry.context));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.status)) {
|
||||
item.addLoreLine("&7Status: &f" + AdminVoteLogHelpers.safe(entry.status));
|
||||
}
|
||||
if (entry.proxyCachedTotal != 0) {
|
||||
item.addLoreLine("&7Cached Total: &f" + entry.proxyCachedTotal);
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.voteId)) {
|
||||
item.addLoreLine("&7VoteId: &f" + AdminVoteLogHelpers.safe(entry.voteId));
|
||||
}
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogVoteId(plugin, clickEvent.getPlayer(), table, entry.voteId, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: VoteLog entries for a given server (paged).
|
||||
*
|
||||
* Uses VoteLogMysqlTable instance passed in from CommandLoader.
|
||||
*/
|
||||
public class AdminVoteLogServer extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
private final int page;
|
||||
|
||||
private final String server;
|
||||
private final int days;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogServer(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table, String server,
|
||||
int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.server = server;
|
||||
this.days = Math.max(0, days);
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
public AdminVoteLogServer(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, String server, int days, int page) {
|
||||
this(plugin, sender, table, server, days, page);
|
||||
this.user = user;
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
BInventory inv = new BInventory("&aVoteLog - Server &7(" + AdminVoteLogHelpers.safe(server) + ")");
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
int needed = (page + 1) * PAGE_SIZE;
|
||||
List<VoteLogMysqlTable.VoteLogEntry> rows = table.getByServer(server, days, needed);
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(rows.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= rows.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo entries")
|
||||
.addLoreLine("&7No vote log entries on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
inv.addButton(makeEntryButton(rows.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makeEntryButton(final VoteLogMysqlTable.VoteLogEntry entry) {
|
||||
VoteLogMysqlTable.VoteLogEvent event =
|
||||
entry.event != null ? VoteLogMysqlTable.VoteLogEvent.valueOf(entry.event) : null;
|
||||
|
||||
Material mat = AdminVoteLogHelpers.getMaterialForEvent(event, entry.status);
|
||||
String eventColor = AdminVoteLogHelpers.getEventColor(event);
|
||||
|
||||
String timeStr = AdminVoteLogHelpers.formatTime(entry.voteTime);
|
||||
String uuidShort = AdminVoteLogHelpers.shortUuid(entry.playerUuid);
|
||||
String voteShort = AdminVoteLogHelpers.shortUuid(entry.voteId);
|
||||
|
||||
ItemBuilder item = new ItemBuilder(mat)
|
||||
.setName(eventColor + AdminVoteLogHelpers.safe(entry.event) + " &7(" + voteShort + ")");
|
||||
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.playerName) || AdminVoteLogHelpers.notEmpty(entry.playerUuid)) {
|
||||
item.addLoreLine("&7Player: &f" + AdminVoteLogHelpers.safe(entry.playerName) + " &7(" + uuidShort + ")");
|
||||
}
|
||||
if (entry.voteTime > 0) {
|
||||
item.addLoreLine("&7Time: &f" + timeStr);
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.server)) {
|
||||
item.addLoreLine("&7Server: &f" + AdminVoteLogHelpers.safe(entry.server));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.service)) {
|
||||
item.addLoreLine("&7Service: &f" + AdminVoteLogHelpers.safe(entry.service));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.context)) {
|
||||
item.addLoreLine("&7Context: &f" + AdminVoteLogHelpers.safe(entry.context));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.status)) {
|
||||
item.addLoreLine("&7Status: &f" + AdminVoteLogHelpers.safe(entry.status));
|
||||
}
|
||||
if (entry.proxyCachedTotal != 0) {
|
||||
item.addLoreLine("&7Cached Total: &f" + entry.proxyCachedTotal);
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.voteId)) {
|
||||
item.addLoreLine("&7VoteId: &f" + AdminVoteLogHelpers.safe(entry.voteId));
|
||||
}
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// vote_id is the correlation id
|
||||
new AdminVoteLogVoteId(plugin, clickEvent.getPlayer(), table, entry.voteId, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: Select a server (distinct list), then open AdminVoteLogServer.
|
||||
*/
|
||||
public class AdminVoteLogServerSelect extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int days;
|
||||
private final int page;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogServerSelect(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
this.days = Math.max(0, days);
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Servers";
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
int needed = (page + 1) * PAGE_SIZE;
|
||||
List<String> servers = table.getDistinctServers(days, needed);
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(servers.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= servers.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo servers")
|
||||
.addLoreLine("&7No servers on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
String srv = servers.get(i);
|
||||
inv.addButton(makeServerButton(srv));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makeServerButton(final String server) {
|
||||
ItemBuilder item = new ItemBuilder(Material.PAPER).setName("&a" + AdminVoteLogHelpers.safe(server))
|
||||
.addLoreLine("&7Click to open votelog for this server")
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time");
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogServer(plugin, clickEvent.getPlayer(), table, server, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: VoteLog entries for a given service/site (paged).
|
||||
*
|
||||
* Uses VoteLogMysqlTable instance passed in from CommandLoader.
|
||||
*/
|
||||
public class AdminVoteLogService extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
private final int page;
|
||||
|
||||
private final String service;
|
||||
private final int days;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogService(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table, String service,
|
||||
int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.service = service;
|
||||
this.days = days;
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
public AdminVoteLogService(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, String service, int days, int page) {
|
||||
this(plugin, sender, table, service, days, page);
|
||||
this.user = user;
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
BInventory inv = new BInventory("&aVoteLog - Service &7(" + AdminVoteLogHelpers.safe(service) + ")");
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
int needed = (page + 1) * PAGE_SIZE;
|
||||
List<VoteLogMysqlTable.VoteLogEntry> rows = table.getByService(service, days, needed);
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(rows.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= rows.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo entries")
|
||||
.addLoreLine("&7No vote log entries on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
inv.addButton(makeEntryButton(rows.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makeEntryButton(final VoteLogMysqlTable.VoteLogEntry entry) {
|
||||
VoteLogMysqlTable.VoteLogEvent event =
|
||||
entry.event != null ? VoteLogMysqlTable.VoteLogEvent.valueOf(entry.event) : null;
|
||||
|
||||
Material mat = AdminVoteLogHelpers.getMaterialForEvent(event, entry.status);
|
||||
|
||||
String eventColor = AdminVoteLogHelpers.getEventColor(event);
|
||||
|
||||
String timeStr = AdminVoteLogHelpers.formatTime(entry.voteTime);
|
||||
String uuidShort = AdminVoteLogHelpers.shortUuid(entry.playerUuid);
|
||||
String voteShort = AdminVoteLogHelpers.shortUuid(entry.voteId);
|
||||
|
||||
ItemBuilder item = new ItemBuilder(mat)
|
||||
.setName(eventColor + AdminVoteLogHelpers.safe(entry.event) + " &7(" + voteShort + ")");
|
||||
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.playerName) || AdminVoteLogHelpers.notEmpty(entry.playerUuid)) {
|
||||
item.addLoreLine("&7Player: &f" + AdminVoteLogHelpers.safe(entry.playerName) + " &7(" + uuidShort + ")");
|
||||
}
|
||||
if (entry.voteTime > 0) {
|
||||
item.addLoreLine("&7Time: &f" + timeStr);
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.service)) {
|
||||
item.addLoreLine("&7Service: &f" + AdminVoteLogHelpers.safe(entry.service));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.context)) {
|
||||
item.addLoreLine("&7Context: &f" + AdminVoteLogHelpers.safe(entry.context));
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.status)) {
|
||||
item.addLoreLine("&7Status: &f" + AdminVoteLogHelpers.safe(entry.status));
|
||||
}
|
||||
if (entry.proxyCachedTotal != 0) {
|
||||
item.addLoreLine("&7Cached Total: &f" + entry.proxyCachedTotal);
|
||||
}
|
||||
if (AdminVoteLogHelpers.notEmpty(entry.voteId)) {
|
||||
item.addLoreLine("&7VoteId: &f" + AdminVoteLogHelpers.safe(entry.voteId));
|
||||
}
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// vote_id is the correlation id
|
||||
new AdminVoteLogVoteId(plugin, clickEvent.getPlayer(), table, entry.voteId, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: Select a service (distinct list), then open AdminVoteLogService.
|
||||
*/
|
||||
public class AdminVoteLogServiceSelect extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int days;
|
||||
private final int page;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogServiceSelect(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
this.days = Math.max(0, days);
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Services";
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
int needed = (page + 1) * PAGE_SIZE;
|
||||
List<String> services = table.getDistinctServices(days, needed);
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(services.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= services.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo services")
|
||||
.addLoreLine("&7No services on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
String svc = services.get(i);
|
||||
inv.addButton(makeServiceButton(svc));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makeServiceButton(final String service) {
|
||||
ItemBuilder item = new ItemBuilder(Material.PAPER).setName("&a" + AdminVoteLogHelpers.safe(service))
|
||||
.addLoreLine("&7Click to open votelog for this service")
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time");
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogService(plugin, clickEvent.getPlayer(), table, service, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: Select a service from DB (distinct services), then open
|
||||
* AdminVoteLogService.
|
||||
*/
|
||||
public class AdminVoteLogServiceSelectAll extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int days;
|
||||
private final int page;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogServiceSelectAll(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
this.days = days;
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Services";
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
}
|
||||
});
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
int needed = (page + 1) * PAGE_SIZE;
|
||||
List<String> services = table.getDistinctServices(days, needed);
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(services.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= services.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo services")
|
||||
.addLoreLine("&7No services on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
String svc = services.get(i);
|
||||
inv.addButton(makeServiceButton(svc));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makeServiceButton(String service) {
|
||||
ItemBuilder item = new ItemBuilder(Material.PAPER).setName("&a" + AdminVoteLogHelpers.safe(service))
|
||||
.addLoreLine("&7Click to open votelog for this service")
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time");
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new AdminVoteLogService(plugin, clickEvent.getPlayer(), table, service, days, 0).open();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: VoteLog stats overview.
|
||||
*
|
||||
* Uses VoteLogMysqlTable instance passed in from CommandLoader.
|
||||
*
|
||||
* Shows:
|
||||
* - total / immediate / cached counts (VoteLogCounts)
|
||||
* - unique voters
|
||||
* - top services
|
||||
* - top servers
|
||||
*/
|
||||
public class AdminVoteLogStats extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
|
||||
private final int days;
|
||||
|
||||
private final int topServicesLimit;
|
||||
private final int topServersLimit;
|
||||
|
||||
public AdminVoteLogStats(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table, int days) {
|
||||
this(plugin, sender, table, null, days, 10, 10);
|
||||
}
|
||||
|
||||
public AdminVoteLogStats(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days, int topServicesLimit) {
|
||||
this(plugin, sender, table, user, days, topServicesLimit, 10);
|
||||
}
|
||||
|
||||
public AdminVoteLogStats(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, int days, int topServicesLimit, int topServersLimit) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.user = user;
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
this.days = Math.max(0, days);
|
||||
this.topServicesLimit = topServicesLimit <= 0 ? 10 : topServicesLimit;
|
||||
this.topServersLimit = topServersLimit <= 0 ? 10 : topServersLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - Stats";
|
||||
if (days > 0) {
|
||||
title += " &7(" + days + "d)";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// counts
|
||||
VoteLogMysqlTable.VoteLogCounts counts = table.getCounts(days);
|
||||
long uniques = table.getUniqueVoters(days);
|
||||
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BOOK).setName("&aOverview")
|
||||
.addLoreLine("&7Total Votes: &f" + counts.total)
|
||||
.addLoreLine("&7Immediate: &f" + counts.immediate)
|
||||
.addLoreLine("&7Cached: &f" + counts.cached)
|
||||
.addLoreLine("&7Unique Voters: &f" + uniques)
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
// top services header
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.MAP).setName("&aTop Services")
|
||||
.addLoreLine("&7Top " + topServicesLimit + " services/sites:")
|
||||
.addLoreLine("&8(Click does nothing)")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
int shownServices = 0;
|
||||
for (VoteLogMysqlTable.ServiceCount sc : table.getTopServices(days, topServicesLimit)) {
|
||||
shownServices++;
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER)
|
||||
.setName("&a#" + shownServices + " &f" + AdminVoteLogHelpers.safe(sc.service))
|
||||
.addLoreLine("&7Votes: &f" + sc.votes)
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op (could open AdminVoteLogService in future)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (shownServices == 0) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo service data")
|
||||
.addLoreLine("&7No services found in the log.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// top servers header
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.COMPASS).setName("&aTop Servers")
|
||||
.addLoreLine("&7Top " + topServersLimit + " servers:")
|
||||
.addLoreLine("&8(Click does nothing)")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
int shownServers = 0;
|
||||
for (VoteLogMysqlTable.ServerCount sc : table.getTopServers(days, topServersLimit)) {
|
||||
shownServers++;
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER)
|
||||
.setName("&a#" + shownServers + " &f" + AdminVoteLogHelpers.safe(sc.server))
|
||||
.addLoreLine("&7Votes: &f" + sc.votes)
|
||||
.addLoreLine(days > 0 ? "&7Window: &fLast " + days + " days" : "&7Window: &fAll time")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op (could open AdminVoteLogServer in future)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (shownServers == 0) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo server data")
|
||||
.addLoreLine("&7No servers found in the log.")) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
package com.bencodez.votingplugin.commands.gui.admin.votelog;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.bencodez.advancedcore.api.gui.GUIHandler;
|
||||
import com.bencodez.advancedcore.api.gui.GUIMethod;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventory.ClickEvent;
|
||||
import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votelog.VoteLogMysqlTable;
|
||||
|
||||
/**
|
||||
* Admin GUI: VoteLog entries for a given voteId (paged).
|
||||
*
|
||||
* vote_id is NOT unique; this shows ALL rows for the correlation id.
|
||||
*/
|
||||
public class AdminVoteLogVoteId extends GUIHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
private final VoteLogMysqlTable table;
|
||||
private VotingPluginUser user;
|
||||
private final int page;
|
||||
|
||||
private final String voteId;
|
||||
private final int days;
|
||||
|
||||
private static final int PAGE_SIZE = 45;
|
||||
|
||||
public AdminVoteLogVoteId(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table, String voteId,
|
||||
int days, int page) {
|
||||
super(plugin, sender);
|
||||
this.plugin = plugin;
|
||||
this.table = table;
|
||||
this.voteId = voteId;
|
||||
this.days = days;
|
||||
this.page = Math.max(0, page);
|
||||
|
||||
if (sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
public AdminVoteLogVoteId(VotingPluginMain plugin, CommandSender sender, VoteLogMysqlTable table,
|
||||
VotingPluginUser user, String voteId, int days, int page) {
|
||||
this(plugin, sender, table, voteId, days, page);
|
||||
this.user = user;
|
||||
if (this.user == null && sender instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) sender);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<String> getChat(CommandSender sender) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBook(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChat(CommandSender sender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
try {
|
||||
String title = "&aVoteLog - VoteId";
|
||||
if (voteId != null && !voteId.isEmpty()) {
|
||||
title += " &7(" + shortId(voteId) + ")";
|
||||
}
|
||||
|
||||
BInventory inv = new BInventory(title);
|
||||
inv.requirePermission("VotingPlugin.Commands.AdminVote.VoteLog");
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
if (table == null) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.BARRIER).setName("&cVoteLog unavailable")
|
||||
.addLoreLine("&7VoteLog MySQL table is not loaded/enabled.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (voteId == null || voteId.isEmpty()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo voteId provided")
|
||||
.addLoreLine("&7Missing voteId.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
int needed = (page + 1) * PAGE_SIZE;
|
||||
|
||||
// vote_id is not unique -> show ALL rows for it (paged)
|
||||
List<VoteLogMysqlTable.VoteLogEntry> rows = table.getByVoteIdAll(voteId, days, needed);
|
||||
|
||||
int start = page * PAGE_SIZE;
|
||||
int end = Math.min(rows.size(), start + PAGE_SIZE);
|
||||
|
||||
if (start >= rows.size()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(Material.PAPER).setName("&eNo entries")
|
||||
.addLoreLine("&7No vote log entries on this page.").addLoreLine("&7Try going back a page.")) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// no-op
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (int i = start; i < end; i++) {
|
||||
inv.addButton(makeEntryButton(rows.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
inv.setPages(true);
|
||||
inv.setMaxInvSize(54);
|
||||
inv.openInventory(player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private BInventoryButton makeEntryButton(VoteLogMysqlTable.VoteLogEntry entry) {
|
||||
VoteLogMysqlTable.VoteLogEvent event = entry.event != null ? VoteLogMysqlTable.VoteLogEvent.valueOf(entry.event)
|
||||
: null;
|
||||
|
||||
Material mat = AdminVoteLogHelpers.getMaterialForEvent(event, entry.status);
|
||||
|
||||
String eventColor = AdminVoteLogHelpers.getEventColor(event);
|
||||
|
||||
String timeStr = formatTime(entry.voteTime);
|
||||
String uuidShort = shortId(entry.playerUuid);
|
||||
String voteShort = shortId(entry.voteId);
|
||||
|
||||
ItemBuilder item = new ItemBuilder(mat)
|
||||
.setName(eventColor + AdminVoteLogHelpers.safe(entry.event) + " &7(" + voteShort + ")");
|
||||
|
||||
// Only add lore lines when the value is actually set / meaningful
|
||||
// (prevents blank/0/default noise)
|
||||
if (notEmpty(entry.playerName) || notEmpty(entry.playerUuid)) {
|
||||
item.addLoreLine("&7Player: &f" + safe(entry.playerName) + " &7(" + uuidShort + ")");
|
||||
}
|
||||
|
||||
if (entry.voteTime > 0) {
|
||||
item.addLoreLine("&7Time: &f" + timeStr);
|
||||
}
|
||||
|
||||
if (notEmpty(entry.service)) {
|
||||
item.addLoreLine("&7Service: &f" + safe(entry.service));
|
||||
}
|
||||
|
||||
if (notEmpty(entry.context)) {
|
||||
item.addLoreLine("&7Context: &f" + safe(entry.context));
|
||||
}
|
||||
|
||||
if (notEmpty(entry.status)) {
|
||||
item.addLoreLine("&7Status: &f" + safe(entry.status));
|
||||
}
|
||||
|
||||
if (entry.proxyCachedTotal != 0) {
|
||||
item.addLoreLine("&7Cached Total: &f" + entry.proxyCachedTotal);
|
||||
}
|
||||
|
||||
if (notEmpty(entry.voteId)) {
|
||||
item.addLoreLine("&7VoteId: &f" + safe(entry.voteId));
|
||||
}
|
||||
|
||||
return new BInventoryButton(item) {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
// read-only
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private String formatTime(long millis) {
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(new Date(millis));
|
||||
} catch (Exception e) {
|
||||
return String.valueOf(millis);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean notEmpty(String s) {
|
||||
return s != null && !s.trim().isEmpty();
|
||||
}
|
||||
|
||||
private String shortId(String s) {
|
||||
if (s == null || s.isEmpty()) {
|
||||
return "unknown";
|
||||
}
|
||||
return s.length() > 8 ? s.substring(0, 8) : s;
|
||||
}
|
||||
|
||||
private String safe(String s) {
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
open(GUIMethod.CHEST);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -17,8 +17,8 @@ import com.bencodez.advancedcore.api.rewards.RewardBuilder;
|
||||
import com.bencodez.simpleapi.array.ArrayUtils;
|
||||
import com.bencodez.simpleapi.messages.MessageAPI;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
public class VoteLast extends GUIHandler {
|
||||
|
||||
@@ -40,7 +40,7 @@ public class VoteLast extends GUIHandler {
|
||||
msg.add(MessageAPI.replaceIgnoreCase(plugin.getConfigFile().getFormatCommandsVoteLastTitle(), "%player%",
|
||||
playerName));
|
||||
|
||||
for (VoteSite voteSite : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (!voteSite.isHidden()) {
|
||||
msg.add(user.voteCommandLastLine(voteSite));
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class VoteLast extends GUIHandler {
|
||||
public void onChest(Player player) {
|
||||
BInventory inv = new BInventory(plugin.getGui().getChestVoteLastName());
|
||||
inv.addPlaceholder("player", user.getPlayerName());
|
||||
for (VoteSite site : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (!site.isHidden()) {
|
||||
inv.addButton(inv.getNextSlot(),
|
||||
new UpdatingBInventoryButton(plugin, site.getItem().setName(site.getDisplayName())
|
||||
|
||||
+4
-4
@@ -19,8 +19,8 @@ import com.bencodez.advancedcore.api.messages.PlaceholderUtils;
|
||||
import com.bencodez.advancedcore.api.rewards.RewardBuilder;
|
||||
import com.bencodez.simpleapi.messages.MessageAPI;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
import xyz.upperlevel.spigot.book.BookUtil;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class VoteNext extends GUIHandler {
|
||||
msg.add(MessageAPI.colorize(MessageAPI
|
||||
.replaceIgnoreCase(plugin.getConfigFile().getFormatCommandsVoteNextTitle(), "%player%", playerName)));
|
||||
|
||||
for (VoteSite voteSite : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (!voteSite.isHidden()) {
|
||||
String msgLine = plugin.getConfigFile().getFormatCommandsVoteNextLayout();
|
||||
|
||||
@@ -62,7 +62,7 @@ public class VoteNext extends GUIHandler {
|
||||
BookWrapper book = new BookWrapper(plugin.getGui().getBookVoteURLBookGUITitle());
|
||||
|
||||
// add colors/config options
|
||||
for (VoteSite site : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (!site.isHidden()) {
|
||||
Layout nextLayout = new Layout(new ArrayList<>(Arrays.asList("[Json]")));
|
||||
nextLayout.replaceTextComponent("[Json]",
|
||||
@@ -86,7 +86,7 @@ public class VoteNext extends GUIHandler {
|
||||
public void onChest(Player player) {
|
||||
BInventory inv = new BInventory(plugin.getGui().getChestVoteNextName());
|
||||
inv.addPlaceholder("player", user.getPlayerName());
|
||||
for (VoteSite site : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (!site.isHidden()) {
|
||||
String siteNameDisplay = plugin.getGui().getChestVoteNextCustomSiteNamesDisplays(site.getKey());
|
||||
if (siteNameDisplay.isEmpty()) {
|
||||
|
||||
+8
-3
@@ -3,6 +3,7 @@ package com.bencodez.votingplugin.commands.gui.player;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -17,6 +18,7 @@ import com.bencodez.advancedcore.api.rewards.RewardBuilder;
|
||||
import com.bencodez.advancedcore.api.rewards.RewardOptions;
|
||||
import com.bencodez.simpleapi.messages.MessageAPI;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.events.VoteShopPurchaseEvent;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
|
||||
public class VoteShop extends GUIHandler {
|
||||
@@ -135,9 +137,6 @@ public class VoteShop extends GUIHandler {
|
||||
if (user.removePoints(points, true)) {
|
||||
plugin.getLogger().info("VoteShop: " + user.getPlayerName() + "/"
|
||||
+ user.getUUID() + " bought " + identifier + " for " + points);
|
||||
if (plugin.getConfigFile().isTrackShopPurchases()) {
|
||||
plugin.getServerData().addVoteShopPurchase(identifier);
|
||||
}
|
||||
|
||||
plugin.getRewardHandler().giveReward(user, plugin.getShopFile().getData(),
|
||||
plugin.getShopFile().getShopIdentifierRewardsPath(identifier),
|
||||
@@ -146,6 +145,12 @@ public class VoteShop extends GUIHandler {
|
||||
user.sendMessage(PlaceholderUtils.replacePlaceHolder(
|
||||
plugin.getShopFile().getVoteShopPurchase(identifier),
|
||||
placeholders));
|
||||
|
||||
VoteShopPurchaseEvent purcahseEvent = new VoteShopPurchaseEvent(
|
||||
player.getUniqueId(), player.getName(), user, identifier, points);
|
||||
|
||||
Bukkit.getPluginManager().callEvent(purcahseEvent);
|
||||
|
||||
if (limit > 0) {
|
||||
user.setVoteShopIdentifierLimit(identifier,
|
||||
user.getVoteShopIdentifierLimit(identifier) + 1);
|
||||
|
||||
+7
-3
@@ -3,6 +3,7 @@ package com.bencodez.votingplugin.commands.gui.player;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -16,6 +17,7 @@ import com.bencodez.advancedcore.api.messages.PlaceholderUtils;
|
||||
import com.bencodez.advancedcore.api.rewards.RewardOptions;
|
||||
import com.bencodez.simpleapi.player.PlayerUtils;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.events.VoteShopPurchaseEvent;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
|
||||
public class VoteShopConfirm extends GUIHandler {
|
||||
@@ -63,9 +65,6 @@ public class VoteShopConfirm extends GUIHandler {
|
||||
if (user.removePoints(points, true)) {
|
||||
plugin.getLogger().info("VoteShop: " + user.getPlayerName() + "/" + user.getUUID() + " bought "
|
||||
+ identifier + " for " + points);
|
||||
if (plugin.getConfigFile().isTrackShopPurchases()) {
|
||||
plugin.getServerData().addVoteShopPurchase(identifier);
|
||||
}
|
||||
|
||||
plugin.getRewardHandler().giveReward(user, plugin.getShopFile().getData(),
|
||||
plugin.getShopFile().getShopIdentifierRewardsPath(identifier),
|
||||
@@ -73,6 +72,11 @@ public class VoteShopConfirm extends GUIHandler {
|
||||
|
||||
user.sendMessage(PlaceholderUtils
|
||||
.replacePlaceHolder(plugin.getShopFile().getVoteShopPurchase(identifier), placeholders));
|
||||
|
||||
VoteShopPurchaseEvent purcahseEvent = new VoteShopPurchaseEvent(player.getUniqueId(),
|
||||
player.getName(), user, identifier, points);
|
||||
|
||||
Bukkit.getPluginManager().callEvent(purcahseEvent);
|
||||
if (limit > 0) {
|
||||
user.setVoteShopIdentifierLimit(identifier, user.getVoteShopIdentifierLimit(identifier) + 1);
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,9 +21,9 @@ import com.bencodez.advancedcore.api.rewards.RewardBuilder;
|
||||
import com.bencodez.simpleapi.array.ArrayUtils;
|
||||
import com.bencodez.simpleapi.nms.NMSManager;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.topvoter.TopVoterPlayer;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
public class VoteToday extends GUIHandler {
|
||||
|
||||
|
||||
+4
-9
@@ -23,9 +23,9 @@ import com.bencodez.advancedcore.api.messages.PlaceholderUtils;
|
||||
import com.bencodez.advancedcore.api.rewards.RewardBuilder;
|
||||
import com.bencodez.simpleapi.array.ArrayUtils;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.topvoter.TopVoter;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
import xyz.upperlevel.spigot.book.BookUtil;
|
||||
|
||||
@@ -43,11 +43,6 @@ public class VoteURL extends GUIHandler {
|
||||
if (user == null && player instanceof Player) {
|
||||
this.user = plugin.getVotingPluginUserManager().getVotingPluginUser((Player) player);
|
||||
}
|
||||
if (player != null && user != null && player.getName().equals(user.getPlayerName())) {
|
||||
if (plugin.getConfigFile().isUsePrimaryAccountForPlaceholders() && user.hasPrimaryAccount()) {
|
||||
user = plugin.getVotingPluginUserManager().getVotingPluginUser(user.getPrimaryAccount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,7 +59,7 @@ public class VoteURL extends GUIHandler {
|
||||
}
|
||||
if (plugin.getConfigFile().isFormatCommandsVoteAutoInputSites()) {
|
||||
int counter = 0;
|
||||
for (VoteSite voteSite : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (!voteSite.isHidden()) {
|
||||
if (voteSite.getPermissionToView().isEmpty()
|
||||
|| sender.hasPermission(voteSite.getPermissionToView())) {
|
||||
@@ -154,7 +149,7 @@ public class VoteURL extends GUIHandler {
|
||||
book.addLayout(layout);
|
||||
}
|
||||
int i = 1;
|
||||
for (VoteSite site : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (!site.isHidden()) {
|
||||
if (site.getPermissionToView().isEmpty() || player.hasPermission(site.getPermissionToView())) {
|
||||
Layout layout = new Layout(plugin.getGui().getBookVoteURLBookGUILayout())
|
||||
@@ -232,7 +227,7 @@ public class VoteURL extends GUIHandler {
|
||||
}
|
||||
|
||||
int startSlot = plugin.getGui().getChestVoteURLAllUrlsButtonStartSlot();
|
||||
for (final VoteSite voteSite : plugin.getVoteSitesEnabled()) {
|
||||
for (final VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (!voteSite.isHidden()) {
|
||||
if (voteSite.getPermissionToView().isEmpty() || player.hasPermission(voteSite.getPermissionToView())) {
|
||||
ItemBuilder builder = getItemVoteSite(voteSite);
|
||||
|
||||
+3
-3
@@ -14,8 +14,8 @@ import com.bencodez.advancedcore.api.inventory.BInventoryButton;
|
||||
import com.bencodez.advancedcore.api.inventory.UpdatingBInventoryButton;
|
||||
import com.bencodez.advancedcore.api.item.ItemBuilder;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
public class VoteURLVoteSite extends GUIHandler {
|
||||
|
||||
@@ -47,11 +47,11 @@ public class VoteURLVoteSite extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
if (!plugin.isVoteSite(voteSite)) {
|
||||
if (!plugin.getVoteSiteManager().isVoteSite(voteSite)) {
|
||||
player.sendMessage("Not a valid votesite");
|
||||
return;
|
||||
}
|
||||
VoteSite site = plugin.getVoteSite(voteSite, true);
|
||||
VoteSite site = plugin.getVoteSiteManager().getVoteSite(voteSite, true);
|
||||
BInventory inv = new BInventory(plugin.getGui().getChestVoteURLSiteName());
|
||||
inv.addPlaceholder("site", site.getDisplayName());
|
||||
inv.setMeta(player, "VoteSite", site);
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package com.bencodez.votingplugin.commands.tabcompleter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandSendEvent;
|
||||
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
|
||||
/**
|
||||
* Filters VotingPlugin command aliases from tab completion when aliases are
|
||||
* disabled.
|
||||
* <p>
|
||||
* This listener ONLY hides aliases that are explicitly listed in VotingPlugin's
|
||||
* plugin.yml under the "aliases:" section for the "vote" and "adminvote"
|
||||
* commands.
|
||||
* <p>
|
||||
* It will NOT hide unrelated commands such as "/votechallenge" unless that
|
||||
* exact command name is an alias defined in VotingPlugin's plugin.yml.
|
||||
*/
|
||||
public class AliasCommandFilterListener implements Listener {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
|
||||
/**
|
||||
* Cached lowercase alias names (without '/') that should be hidden when alias
|
||||
* loading is disabled.
|
||||
*/
|
||||
private final Set<String> aliasesToHide;
|
||||
|
||||
/**
|
||||
* Creates a new listener and caches aliases from VotingPlugin's plugin.yml.
|
||||
*
|
||||
* @param plugin VotingPlugin main instance
|
||||
*/
|
||||
public AliasCommandFilterListener(VotingPluginMain plugin) {
|
||||
this.plugin = plugin;
|
||||
this.aliasesToHide = buildAliasesToHide(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes VotingPlugin aliases from the player's available command list when
|
||||
* alias loading is disabled.
|
||||
*
|
||||
* @param event Bukkit command send event
|
||||
*/
|
||||
@EventHandler
|
||||
public void onPlayerCommandSend(PlayerCommandSendEvent event) {
|
||||
// Only hide when aliases feature is disabled
|
||||
if (plugin.getConfigFile().isLoadCommandAliases()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove ONLY exact alias command names (not "vote*" prefixes)
|
||||
event.getCommands().removeIf(this::shouldHideCommand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a specific command should be hidden.
|
||||
*
|
||||
* @param cmd Command name (without '/'), possibly namespaced (e.g.
|
||||
* "otherplugin:vote")
|
||||
* @return true if the command should be hidden
|
||||
*/
|
||||
private boolean shouldHideCommand(String cmd) {
|
||||
String name = cmd.toLowerCase(Locale.ROOT);
|
||||
|
||||
// Never touch namespaced commands (otherplugin:vote)
|
||||
if (name.contains(":")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always keep the primary commands visible
|
||||
if (name.equals("vote") || name.equals("adminvote")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hide only exact aliases defined in VotingPlugin plugin.yml
|
||||
return aliasesToHide.contains(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the set of aliases to hide from VotingPlugin's plugin.yml.
|
||||
* <p>
|
||||
* Bukkit exposes the plugin.yml "commands" section via
|
||||
* {@code plugin.getDescription().getCommands()}. Each command entry is a map
|
||||
* that may contain an "aliases" key.
|
||||
*
|
||||
* @param plugin VotingPlugin main instance
|
||||
* @return a lowercase set of alias command names
|
||||
*/
|
||||
private Set<String> buildAliasesToHide(VotingPluginMain plugin) {
|
||||
Set<String> aliases = new HashSet<>();
|
||||
|
||||
Map<String, Map<String, Object>> commands = plugin.getDescription().getCommands();
|
||||
if (commands == null || commands.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
// Only consider aliases for these main commands
|
||||
addAliasesFor(commands, "vote", aliases);
|
||||
addAliasesFor(commands, "adminvote", aliases);
|
||||
|
||||
return Collections.unmodifiableSet(aliases);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds aliases for a given command from the plugin.yml commands map into the
|
||||
* provided set.
|
||||
*
|
||||
* @param commandsMap full commands map from PluginDescriptionFile
|
||||
* @param commandName the primary command to read aliases for (e.g. "vote")
|
||||
* @param out output set to add lowercase alias names into
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void addAliasesFor(Map<String, Map<String, Object>> commandsMap, String commandName,
|
||||
Set<String> out) {
|
||||
Map<String, Object> cmdInfo = commandsMap.get(commandName);
|
||||
if (cmdInfo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object aliasesObj = cmdInfo.get("aliases");
|
||||
if (aliasesObj instanceof String) {
|
||||
// plugin.yml also allows a single alias as a string
|
||||
out.add(((String) aliasesObj).toLowerCase(Locale.ROOT));
|
||||
} else if (aliasesObj instanceof Collection) {
|
||||
for (Object o : (Collection<Object>) aliasesObj) {
|
||||
if (o != null) {
|
||||
out.add(o.toString().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,14 +15,6 @@ import lombok.Getter;
|
||||
|
||||
public class BungeeSettings extends YMLFile {
|
||||
|
||||
@ConfigDataBoolean(path = "BungeeBroadcast")
|
||||
@Getter
|
||||
private boolean bungeeBroadcast = false;
|
||||
|
||||
@ConfigDataBoolean(path = "BungeeBroadcastAlways")
|
||||
@Getter
|
||||
private boolean bungeeBroadcastAlways = false;
|
||||
|
||||
@ConfigDataBoolean(path = "BungeeDebug")
|
||||
@Getter
|
||||
private boolean bungeeDebug = false;
|
||||
@@ -33,32 +25,36 @@ public class BungeeSettings extends YMLFile {
|
||||
|
||||
@ConfigDataString(path = "Redis.Host")
|
||||
@Getter
|
||||
private String RedisHost = "";
|
||||
private String redisHost = "";
|
||||
|
||||
@ConfigDataString(path = "Redis.Username")
|
||||
@Getter
|
||||
private String RedisUsername = "";
|
||||
private String redisUsername = "";
|
||||
|
||||
@ConfigDataInt(path = "Redis.Db-Index")
|
||||
@Getter
|
||||
private int redisdbindex = 0;
|
||||
|
||||
@ConfigDataString(path = "PluginMessageChannel")
|
||||
@Getter
|
||||
private String pluginMessagingChannel = "vp:vp";
|
||||
|
||||
|
||||
@ConfigDataBoolean(path = "PluginMessageEncryption")
|
||||
@Getter
|
||||
private boolean pluginMessageEncryption = false;
|
||||
|
||||
@ConfigDataString(path = "Redis.Prefix")
|
||||
@Getter
|
||||
private String RedisPrefix = "";
|
||||
private String redisPrefix = "";
|
||||
|
||||
@ConfigDataString(path = "Redis.Password")
|
||||
@Getter
|
||||
private String RedisPassword = "";
|
||||
private String redisPassword = "";
|
||||
|
||||
@ConfigDataInt(path = "Redis.Port")
|
||||
@Getter
|
||||
private int RedisPort = 6379;
|
||||
|
||||
private int redisPort = 6379;
|
||||
|
||||
@ConfigDataString(path = "MQTT.ClientID")
|
||||
@Getter
|
||||
private String mqttClientID = "";
|
||||
@@ -91,10 +87,6 @@ public class BungeeSettings extends YMLFile {
|
||||
@Getter
|
||||
private boolean perServerPoints = false;
|
||||
|
||||
@ConfigDataBoolean(path = "PerServerMilestones")
|
||||
@Getter
|
||||
private boolean perServerMilestones = false;
|
||||
|
||||
@ConfigDataBoolean(path = "GiveExtraAllSitesRewards")
|
||||
@Getter
|
||||
private boolean giveExtraAllSitesRewards = false;
|
||||
@@ -131,10 +123,6 @@ public class BungeeSettings extends YMLFile {
|
||||
@Getter
|
||||
private boolean votifierBypass = false;
|
||||
|
||||
@ConfigDataBoolean(path = "DisableBroadcast")
|
||||
@Getter
|
||||
private boolean disableBroadcast = false;
|
||||
|
||||
@ConfigDataBoolean(path = "GlobalData.UseMainMySQL")
|
||||
@Getter
|
||||
private boolean globlalDataUseMainMySQL = true;
|
||||
@@ -149,6 +137,7 @@ public class BungeeSettings extends YMLFile {
|
||||
|
||||
public BungeeSettings(VotingPluginMain plugin) {
|
||||
super(plugin, new File(plugin.getDataFolder(), "BungeeSettings.yml"));
|
||||
setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles());
|
||||
}
|
||||
|
||||
public String getServerNameStorage() {
|
||||
|
||||
@@ -52,6 +52,10 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private int limitVotePoints = -1;
|
||||
|
||||
@ConfigDataBoolean(path = "CaseInsensitiveYMLFiles")
|
||||
@Getter
|
||||
public boolean caseInsensitiveYMLFiles = false;
|
||||
|
||||
@ConfigDataBoolean(path = "QueueVotesDuringTimeChange")
|
||||
@Getter
|
||||
private boolean queueVotesDuringTimeChange = false;
|
||||
@@ -76,6 +80,22 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterAllTimeEnabled = false;
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.NewMessageOnUpdate")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterAllTimeNewMessageOnUpdate = false;
|
||||
|
||||
@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;
|
||||
@@ -86,7 +106,7 @@ public class Config extends YMLFile {
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.RankDisplay")
|
||||
@Getter
|
||||
private String discordSRVTopVoterAllTimeRankDisplay = "%rank%: &6%player% - %votes% Votes";
|
||||
private String discordSRVTopVoterAllTimeRankDisplay = "%rank%: %player% - %votes% Votes";
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.Enabled")
|
||||
@Getter
|
||||
@@ -102,7 +122,7 @@ public class Config extends YMLFile {
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.RankDisplay")
|
||||
@Getter
|
||||
private String discordSRVTopVoterMonthlyRankDisplay = "%rank%: &6%player% - %votes% Votes";
|
||||
private String discordSRVTopVoterMonthlyRankDisplay = "%rank%: %player% - %votes% Votes";
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.Enabled")
|
||||
@Getter
|
||||
@@ -118,7 +138,7 @@ public class Config extends YMLFile {
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.RankDisplay")
|
||||
@Getter
|
||||
private String discordSRVTopVoterWeeklyRankDisplay = "%rank%: &6%player% - %votes% Votes";
|
||||
private String discordSRVTopVoterWeeklyRankDisplay = "%rank%: %player% - %votes% Votes";
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.Enabled")
|
||||
@Getter
|
||||
@@ -134,7 +154,27 @@ public class Config extends YMLFile {
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Daily.RankDisplay")
|
||||
@Getter
|
||||
private String discordSRVTopVoterDailyRankDisplay = "%rank%: &6%player% - %votes% Votes";
|
||||
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;
|
||||
|
||||
public ConfigurationSection getVoteLoggingSection() {
|
||||
if (!getData().isConfigurationSection("VoteLogging")) {
|
||||
getData().createSection("VoteLogging");
|
||||
}
|
||||
return getData().getConfigurationSection("VoteLogging");
|
||||
}
|
||||
|
||||
public boolean isDiscordSRVTopVoterEnabled(TopVoter topVoter) {
|
||||
switch (topVoter) {
|
||||
@@ -151,6 +191,21 @@ public class Config extends YMLFile {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public long getDiscordSRVTopVoterChannel(TopVoter topVoter) {
|
||||
switch (topVoter) {
|
||||
case AllTime:
|
||||
@@ -216,10 +271,6 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private boolean extraVoteShopCheck = true;
|
||||
|
||||
@ConfigDataBoolean(path = "TrackShopPurchases")
|
||||
@Getter
|
||||
private boolean trackShopPurchases = false;
|
||||
|
||||
@ConfigDataBoolean(path = "AlwaysUpdate")
|
||||
@Getter
|
||||
private boolean alwaysUpdate = false;
|
||||
@@ -228,17 +279,13 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private boolean autoCreateVoteSites = true;
|
||||
|
||||
@ConfigDataBoolean(path = "Format.BroadcastVote")
|
||||
@Getter
|
||||
private boolean broadcastVotesEnabled = true;
|
||||
|
||||
@ConfigDataBoolean(path = "CountFakeVotes")
|
||||
@Getter
|
||||
private boolean countFakeVotes = true;
|
||||
|
||||
@ConfigDataInt(path = "DelayBetweenUpdates")
|
||||
@ConfigDataString(path = "DelayBetweenUpdates")
|
||||
@Getter
|
||||
private int delayBetweenUpdates = 3;
|
||||
private String delayBetweenUpdates = "3m";
|
||||
|
||||
@ConfigDataBoolean(path = "DisableAdvancedTab")
|
||||
@Getter
|
||||
@@ -268,6 +315,14 @@ public class Config extends YMLFile {
|
||||
@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;
|
||||
@@ -284,26 +339,6 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private boolean extraBackgroundUpdate = false;
|
||||
|
||||
@ConfigDataString(path = "Format.AlternateBroadcast.Broadcast")
|
||||
@Getter
|
||||
private String formatAlternateBroadcastBroadcast = "&6[&4Broadcast&6] &2%numberofplayers% voted in the last half hour! /vote";
|
||||
|
||||
@ConfigDataInt(path = "Format.AlternateBroadcast.Delay")
|
||||
@Getter
|
||||
private int formatAlternateBroadcastDelay = 30;
|
||||
|
||||
@ConfigDataBoolean(path = "Format.AlternateBroadcast.Enabled")
|
||||
@Getter
|
||||
private boolean formatAlternateBroadcastEnabled = false;
|
||||
|
||||
@ConfigDataBoolean(path = "Format.OnlyOneOfflineBroadcast")
|
||||
@Getter
|
||||
private boolean formatOnlyOneOfflineBroadcast = false;
|
||||
|
||||
@ConfigDataString(path = "Format.OfflineBroadcast")
|
||||
@Getter
|
||||
private String formatOfflineBroadcast = "&6[&4Broadcast&6] &2Thanks &c%player% &2for voting on %numberofvotes% times!";
|
||||
|
||||
@ConfigDataBoolean(path = "Format.Commands.Vote.ForceLinks")
|
||||
@Getter
|
||||
private boolean formatCommandsVoteForceLinks = true;
|
||||
@@ -416,10 +451,6 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private boolean loadCommandAliases = true;
|
||||
|
||||
@ConfigDataBoolean(path = "LogVotesToFile")
|
||||
@Getter
|
||||
private boolean logVotesToFile = false;
|
||||
|
||||
@ConfigDataInt(path = "MaxiumNumberOfTopVotersToLoad")
|
||||
@Getter
|
||||
private int MaxiumNumberOfTopVotersToLoad = 1000;
|
||||
@@ -452,10 +483,6 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private boolean useJavascriptPlaceholders = false;
|
||||
|
||||
@ConfigDataBoolean(path = "UsePrimaryAccountForPlaceholders")
|
||||
@Getter
|
||||
private boolean usePrimaryAccountForPlaceholders = false;
|
||||
|
||||
@ConfigDataBoolean(path = "UseVoteGUIMainCommand")
|
||||
@Getter
|
||||
private boolean useVoteGUIMainCommand = false;
|
||||
@@ -476,14 +503,6 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private Set<String> customPlaceholderReturns = new HashSet<>();
|
||||
|
||||
@ConfigDataString(path = "Format.BroadcastMsg")
|
||||
@Getter
|
||||
private String formatBroadCastMsg = "&6[&4Broadcast&6] &2Thanks &c%player% &2for voting on %SiteName%";
|
||||
|
||||
@ConfigDataBoolean(path = "Format.BroadcastWhenOnline")
|
||||
@Getter
|
||||
private boolean formatBroadcastWhenOnline = false;
|
||||
|
||||
@ConfigDataBoolean(path = "Format.Commands.Vote.AutoInputSites")
|
||||
@Getter
|
||||
private boolean formatCommandsVoteAutoInputSites = true;
|
||||
@@ -710,28 +729,17 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private boolean topVoterIgnorePermission = false;
|
||||
|
||||
@ConfigDataBoolean(path = "VoteReminding.Enabled")
|
||||
@Getter
|
||||
private boolean voteRemindingEnabled = true;
|
||||
|
||||
@ConfigDataInt(path = "VoteReminding.RemindDelay")
|
||||
@Getter
|
||||
private int voteRemindingRemindDelay = 30;
|
||||
|
||||
@ConfigDataBoolean(path = "VoteReminding.RemindOnLogin")
|
||||
@Getter
|
||||
private boolean voteRemindingRemindOnLogin = false;
|
||||
|
||||
@ConfigDataBoolean(path = "VoteReminding.RemindOnlyOnce")
|
||||
@Getter
|
||||
private boolean voteRemindingRemindOnlyOnce = false;
|
||||
|
||||
@ConfigDataString(path = "VoteTopDefault")
|
||||
@Getter
|
||||
private String voteTopDefault = "Monthly";
|
||||
|
||||
@ConfigDataBoolean(path = "AlwaysProcessAsyncPlaceholders")
|
||||
@Getter
|
||||
private boolean alwaysProcessAsyncPlaceholders = false;
|
||||
|
||||
public Config(VotingPluginMain plugin) {
|
||||
super(plugin, new File(plugin.getDataFolder(), "Config.yml"));
|
||||
setIgnoreCase(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -847,15 +855,6 @@ public class Config extends YMLFile {
|
||||
return PlaceholderCacheLevel.getCache(getPlaceholderCacheLevelString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rewards.
|
||||
*
|
||||
* @return the rewards
|
||||
*/
|
||||
public String getVoteRemindingRewardsPath() {
|
||||
return "VoteReminding.Rewards";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadValues() {
|
||||
new AnnotationHandler().load(getData(), this);
|
||||
|
||||
@@ -5,6 +5,7 @@ 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;
|
||||
@@ -17,8 +18,9 @@ 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.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
@@ -30,6 +32,7 @@ public class ConfigVoteSites extends YMLFile {
|
||||
|
||||
public ConfigVoteSites(VotingPluginMain plugin) {
|
||||
super(plugin, new File(plugin.getDataFolder(), "VoteSites.yml"));
|
||||
setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles());
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@@ -47,7 +50,7 @@ public class ConfigVoteSites extends YMLFile {
|
||||
setEnabled(siteName, true);
|
||||
setServiceSite(siteName, org);
|
||||
setVoteURL(siteName, "VoteURL");
|
||||
setVoteDelay(siteName, 24);
|
||||
setVoteDelay(siteName, "24h");
|
||||
set(siteName, "DisplayItem.Material", "STONE");
|
||||
set(siteName, "DisplayItem.Amount", 1);
|
||||
set(siteName, "Rewards.Messages.Player", "&aThanks for voting on %ServiceSite%!");
|
||||
@@ -172,24 +175,27 @@ public class ConfigVoteSites extends YMLFile {
|
||||
return getData(siteName).getString("ServiceSite");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the vote delay.
|
||||
*
|
||||
* @param siteName the site name
|
||||
* @return the vote delay
|
||||
*/
|
||||
public double getVoteDelay(String siteName) {
|
||||
return getData(siteName).getDouble("VoteDelay", 24);
|
||||
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);
|
||||
}
|
||||
|
||||
public int getVoteDelayDailyHour(String siteName) {
|
||||
return getData(siteName).getInt("VoteDelayDailyHour", 0);
|
||||
}
|
||||
|
||||
public double getVoteDelayMin(String siteName) {
|
||||
return getData(siteName).getDouble("VoteDelayMin", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the vote site enabled.
|
||||
*
|
||||
@@ -447,14 +453,10 @@ public class ConfigVoteSites extends YMLFile {
|
||||
* @param siteName the site name
|
||||
* @param voteDelay the vote delay
|
||||
*/
|
||||
public void setVoteDelay(String siteName, double voteDelay) {
|
||||
public void setVoteDelay(String siteName, String voteDelay) {
|
||||
set(siteName, "VoteDelay", voteDelay);
|
||||
}
|
||||
|
||||
public void setVoteDelayDaily(String siteName, boolean value) {
|
||||
set(siteName, "VoteDelayDaily", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vote URL.
|
||||
*
|
||||
@@ -483,4 +485,12 @@ public class ConfigVoteSites extends YMLFile {
|
||||
return pass;
|
||||
}
|
||||
|
||||
public void setVoteDelayDailyHour(String siteName, int intValue) {
|
||||
set(siteName, "VoteDelayDailyHour", intValue);
|
||||
}
|
||||
|
||||
public void setVoteDelayDaily(String siteName, boolean value) {
|
||||
set(siteName, "VoteDelayDaily", value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -360,6 +360,7 @@ public class GUI extends YMLFile {
|
||||
|
||||
public GUI(VotingPluginMain plugin) {
|
||||
super(plugin, new File(plugin.getDataFolder(), "GUI.yml"));
|
||||
setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles());
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ public class ShopFile extends YMLFile {
|
||||
|
||||
public ShopFile(VotingPluginMain plugin) {
|
||||
super(plugin, new File(plugin.getDataFolder(), "Shop.yml"));
|
||||
setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles());
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
+7
-115
@@ -3,7 +3,6 @@ package com.bencodez.votingplugin.config;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.bencodez.simpleapi.file.YMLFile;
|
||||
@@ -16,18 +15,11 @@ import com.bencodez.simpleapi.file.annotation.ConfigDataListInt;
|
||||
import com.bencodez.simpleapi.file.annotation.ConfigDataListString;
|
||||
import com.bencodez.simpleapi.file.annotation.ConfigDataString;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.topvoter.TopVoter;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public class SpecialRewardsConfig extends YMLFile {
|
||||
|
||||
@Getter
|
||||
private String allSitesRewardPath = "AllSites";
|
||||
|
||||
@Getter
|
||||
private String almostAllSitesRewardPath = "AlmostAllSites";
|
||||
|
||||
@Getter
|
||||
private String anySiteRewardsPath = "AnySiteRewards";
|
||||
|
||||
@@ -43,16 +35,6 @@ public class SpecialRewardsConfig extends YMLFile {
|
||||
@Getter
|
||||
private boolean enableWeeklyAwards = false;
|
||||
|
||||
@ConfigDataBoolean(path = "OnlyOneCumulative")
|
||||
@Getter
|
||||
private boolean onlyOneCumulative = false;
|
||||
|
||||
@Getter
|
||||
private String firstVoteRewardsPath = "FirstVote";
|
||||
|
||||
@Getter
|
||||
private String firstVoteTodayRewardsPath = "FirstVoteToday";
|
||||
|
||||
/** The plugin. */
|
||||
private VotingPluginMain plugin;
|
||||
|
||||
@@ -103,22 +85,10 @@ public class SpecialRewardsConfig extends YMLFile {
|
||||
@Getter
|
||||
private double voteStreakRequirementWeek = 50;
|
||||
|
||||
@ConfigDataKeys(path = "Cumulative")
|
||||
@Getter
|
||||
private Set<String> cumulativeVotes = new HashSet<>();
|
||||
|
||||
@ConfigDataKeys(path = "DailyAwards")
|
||||
@Getter
|
||||
private Set<String> dailyPossibleRewardPlaces = new HashSet<>();
|
||||
|
||||
@ConfigDataKeys(path = "MileStones")
|
||||
@Getter
|
||||
private Set<String> milestoneVotes = new HashSet<>();
|
||||
|
||||
@ConfigDataBoolean(path = "ResetMilestonesMonthly")
|
||||
@Getter
|
||||
private boolean resetMilestonesMonthly = false;
|
||||
|
||||
@ConfigDataString(path = "VoteParty.Broadcast")
|
||||
@Getter
|
||||
private String votePartyBroadcast = "";
|
||||
@@ -185,80 +155,14 @@ public class SpecialRewardsConfig extends YMLFile {
|
||||
|
||||
public SpecialRewardsConfig(VotingPluginMain plugin) {
|
||||
super(plugin, new File(plugin.getDataFolder(), "SpecialRewards.yml"));
|
||||
setIgnoreCase(plugin.getConfigFile().isCaseInsensitiveYMLFiles());
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public List<Integer> getCumulativeBlackList(int cumulative) {
|
||||
return getData().getIntegerList("Cumulative." + cumulative + ".BlackList");
|
||||
}
|
||||
|
||||
public boolean getCumulativeRecurring(int cumulative) {
|
||||
return getData().getBoolean("Cumulative." + cumulative + ".Recurring", true);
|
||||
}
|
||||
|
||||
public boolean getCumulativeRewardEnabled(int cumulative) {
|
||||
return getData().getBoolean("Cumulative." + cumulative + ".Enabled");
|
||||
}
|
||||
|
||||
public String getCumulativeRewardsPath(int cumulative) {
|
||||
return "Cumulative." + cumulative + ".Rewards";
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean getCumulativeVotesInSameDay(int cumulative) {
|
||||
return getData().getBoolean("Cumulative." + cumulative + ".VotesInSameDay");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean getCumulativeVotesInSameMonth(int cumulative) {
|
||||
return getData().getBoolean("Cumulative." + cumulative + ".VotesInSameMonth");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean getCumulativeVotesInSameWeek(int cumulative) {
|
||||
return getData().getBoolean("Cumulative." + cumulative + ".VotesInSameWeek");
|
||||
}
|
||||
|
||||
public String getCumulativeVotesTotal(int cumulative) {
|
||||
String str = getData().getString("Cumulative." + cumulative + ".TotalToUse", "");
|
||||
if (str.isEmpty()) {
|
||||
if (getCumulativeVotesInSameMonth(cumulative)) {
|
||||
return TopVoter.Monthly.toString();
|
||||
}
|
||||
if (getCumulativeVotesInSameWeek(cumulative)) {
|
||||
return TopVoter.Weekly.toString();
|
||||
}
|
||||
if (getCumulativeVotesInSameDay(cumulative)) {
|
||||
return TopVoter.Daily.toString();
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public String getDailyAwardRewardsPath(String path) {
|
||||
return "DailyAwards." + path + ".Rewards";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the milestone reward enabled.
|
||||
*
|
||||
* @param milestones the milestones
|
||||
* @return the milestone reward enabled
|
||||
*/
|
||||
public boolean getMilestoneRewardEnabled(int milestones) {
|
||||
return getData().getBoolean("MileStones." + milestones + ".Enabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the milestone rewards.
|
||||
*
|
||||
* @param milestones the milestones
|
||||
* @return the milestone rewards
|
||||
*/
|
||||
public String getMilestoneRewardsPath(int milestones) {
|
||||
return "MileStones." + milestones + ".Rewards";
|
||||
}
|
||||
|
||||
public String getMonthlyAwardRewardsPath(String path) {
|
||||
return "MonthlyAwards." + path + ".Rewards";
|
||||
}
|
||||
@@ -318,27 +222,15 @@ public class SpecialRewardsConfig extends YMLFile {
|
||||
plugin.saveResource("SpecialRewards.yml", true);
|
||||
}
|
||||
|
||||
public void removeCumulative(String votes) {
|
||||
getData().set("Cumulative." + votes, null);
|
||||
public void removeVoteMilestone(String votes) {
|
||||
getData().set("VoteMilestones." + votes, null);
|
||||
saveData();
|
||||
}
|
||||
|
||||
public void removeMilestone(String votes) {
|
||||
getData().set("MileStones." + votes, null);
|
||||
saveData();
|
||||
}
|
||||
|
||||
public void setCumulative(int intValue) {
|
||||
getData().set("Cumulative." + intValue + ".Enabled", true);
|
||||
getData().set("Cumulative." + intValue + ".TotalToUse", "AllTime");
|
||||
getData().set("Cumulative." + intValue + ".Rewards.Messages.Player",
|
||||
"&aYou got %cumulative% cumulative votes!");
|
||||
saveData();
|
||||
}
|
||||
|
||||
public void setMilestone(int intValue) {
|
||||
getData().set("MileStones." + intValue + ".Enabled", true);
|
||||
getData().set("MileStones." + intValue + ".Rewards.Messages.Player", "&aYou got %milestone% milestone votes!");
|
||||
public void setVoteMilestone(int intValue) {
|
||||
getData().set("VoteMilestones." + intValue + ".Enabled", true);
|
||||
getData().set("VoteMilestones." + intValue + ".Rewards.Messages.Player",
|
||||
"&aYou got %milestone% milestone votes!");
|
||||
saveData();
|
||||
}
|
||||
}
|
||||
+255
-126
@@ -2,11 +2,13 @@ package com.bencodez.votingplugin.cooldown;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -15,120 +17,190 @@ import org.bukkit.event.Listener;
|
||||
|
||||
import com.bencodez.advancedcore.api.rewards.RewardOptions;
|
||||
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.sql.Column;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.events.PlayerVoteCoolDownEndEvent;
|
||||
import com.bencodez.votingplugin.events.PlayerVoteSiteCoolDownEndEvent;
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.NextSite;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public class CoolDownCheck implements Listener {
|
||||
|
||||
private VotingPluginMain plugin;
|
||||
private final VotingPluginMain plugin;
|
||||
|
||||
private HashMap<UUID, ScheduledFuture<?>> perSiteTasks = new HashMap<>();
|
||||
|
||||
private HashMap<UUID, ScheduledFuture<?>> allSiteTasks = new HashMap<>();
|
||||
private final Map<UUID, ScheduledFuture<?>> perSiteTasks = new ConcurrentHashMap<>();
|
||||
private final Map<UUID, ScheduledFuture<?>> allSiteTasks = new ConcurrentHashMap<>();
|
||||
|
||||
@Getter
|
||||
private ScheduledExecutorService timer;
|
||||
private final ScheduledExecutorService timer;
|
||||
|
||||
private boolean cooldownCheckEnabled = false;
|
||||
private volatile boolean cooldownCheckEnabled = false;
|
||||
|
||||
public CoolDownCheck(VotingPluginMain plugin) {
|
||||
this.plugin = plugin;
|
||||
this.timer = Executors.newScheduledThreadPool(1);
|
||||
|
||||
// Better behavior when you cancel+reschedule a lot (removes cancelled tasks from queue)
|
||||
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
|
||||
exec.setRemoveOnCancelPolicy(true);
|
||||
this.timer = exec;
|
||||
}
|
||||
|
||||
public void check(UUID uuid) {
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid);
|
||||
if (!user.isOnline()) {
|
||||
user.dontCache();
|
||||
user.userDataFetechMode(UserDataFetchMode.NO_CACHE);
|
||||
}
|
||||
check(user);
|
||||
}
|
||||
|
||||
public synchronized void check(VotingPluginUser user) {
|
||||
boolean coolDownCheck = user.getCoolDownCheck();
|
||||
if (coolDownCheck) {
|
||||
if (user.canVoteAll()) {
|
||||
user.setCoolDownCheck(false);
|
||||
PlayerVoteCoolDownEndEvent event = new PlayerVoteCoolDownEndEvent(user);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
allSiteTasks.remove(user.getJavaUUID());
|
||||
} else {
|
||||
schedulePerSite(user, false);
|
||||
public void shutdown() {
|
||||
timer.shutdownNow();
|
||||
|
||||
for (ScheduledFuture<?> f : perSiteTasks.values()) {
|
||||
if (f != null) {
|
||||
f.cancel(false);
|
||||
}
|
||||
}
|
||||
for (ScheduledFuture<?> f : allSiteTasks.values()) {
|
||||
if (f != null) {
|
||||
f.cancel(false);
|
||||
}
|
||||
}
|
||||
|
||||
perSiteTasks.clear();
|
||||
allSiteTasks.clear();
|
||||
}
|
||||
|
||||
public void checkAllVoteSite(VoteSite site) {
|
||||
plugin.getLogger().info("Checking vote cooldown rewards for all players: " + site.getKey());
|
||||
HashMap<UUID, ArrayList<Column>> cols = plugin.getUserManager().getAllKeys();
|
||||
for (Entry<UUID, ArrayList<Column>> playerData : cols.entrySet()) {
|
||||
|
||||
String uuid = playerData.getKey().toString();
|
||||
if (plugin != null && plugin.isEnabled()) {
|
||||
if (uuid != null && !uuid.isEmpty()) {
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(UUID.fromString(uuid), false);
|
||||
user.dontCache();
|
||||
user.updateTempCacheWithColumns(playerData.getValue());
|
||||
cols.put(playerData.getKey(), null);
|
||||
checkPerSite(user);
|
||||
user.clearTempCache();
|
||||
user = null;
|
||||
}
|
||||
}
|
||||
public synchronized void check(VotingPluginUser user) {
|
||||
if (!user.getCoolDownCheck()) {
|
||||
return;
|
||||
}
|
||||
cols.clear();
|
||||
cols = null;
|
||||
|
||||
plugin.getLogger().info("Finished checking vote cooldown rewards for all players: " + site.getKey());
|
||||
if (user.canVoteAll()) {
|
||||
user.setCoolDownCheck(false);
|
||||
|
||||
PlayerVoteCoolDownEndEvent event = new PlayerVoteCoolDownEndEvent(user);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
ScheduledFuture<?> f = allSiteTasks.remove(user.getJavaUUID());
|
||||
if (f != null) {
|
||||
f.cancel(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep per-site scheduling going while waiting for "all sites available"
|
||||
schedulePerSite(user, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check ONLY a specific votesite for all users (uses streaming keys/cols).
|
||||
*/
|
||||
public void checkAllVoteSite(VoteSite site) {
|
||||
if (site == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.getLogger().info("Checking vote cooldown rewards for all players: " + site.getKey());
|
||||
|
||||
plugin.getUserManager().forEachUserKeys((uuid, cols) -> {
|
||||
if (!plugin.isEnabled() || uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false);
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY);
|
||||
|
||||
try {
|
||||
if (cols != null) {
|
||||
user.updateTempCacheWithColumns(cols);
|
||||
cols.clear(); // help GC (only useful if reused)
|
||||
}
|
||||
|
||||
checkPerSite(site, user);
|
||||
} finally {
|
||||
user.clearTempCache();
|
||||
}
|
||||
}, (count) -> plugin.getLogger().info("Finished checking vote cooldown rewards for all players: " + site.getKey()
|
||||
+ " (processed: " + count + ")"));
|
||||
}
|
||||
|
||||
public void checkEnabled() {
|
||||
if (!plugin.getConfigFile().isDisableCoolDownCheck() && plugin.getRewardHandler()
|
||||
.hasRewards(plugin.getSpecialRewardsConfig().getData(), "VoteCoolDownEndedReward")) {
|
||||
cooldownCheckEnabled = true;
|
||||
} else {
|
||||
cooldownCheckEnabled = false;
|
||||
}
|
||||
cooldownCheckEnabled = !plugin.getConfigFile().isDisableCoolDownCheck()
|
||||
&& plugin.getRewardHandler().hasRewards(plugin.getSpecialRewardsConfig().getData(),
|
||||
"VoteCoolDownEndedReward");
|
||||
}
|
||||
|
||||
public void checkPerSite(UUID uuid) {
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid);
|
||||
if (!user.isOnline()) {
|
||||
user.dontCache();
|
||||
user.userDataFetechMode(UserDataFetchMode.NO_CACHE);
|
||||
}
|
||||
checkPerSite(user);
|
||||
}
|
||||
|
||||
public synchronized void checkPerSite(VotingPluginUser user) {
|
||||
if (plugin.getConfigFile().isPerSiteCoolDownEvents()) {
|
||||
HashMap<String, Boolean> coolDownChecks = user.getCoolDownCheckSiteList();
|
||||
boolean changed = false;
|
||||
for (VoteSite site : plugin.getVoteSitesEnabled()) {
|
||||
if (!coolDownChecks.containsKey(site.getKey()) || !coolDownChecks.get(site.getKey()).booleanValue()) {
|
||||
if (user.canVoteSite(site)) {
|
||||
coolDownChecks.put(site.getKey(), Boolean.TRUE);
|
||||
changed = true;
|
||||
plugin.extraDebug("Triggering votesitecooldownend event for " + user.getUUID());
|
||||
PlayerVoteSiteCoolDownEndEvent event = new PlayerVoteSiteCoolDownEndEvent(user, site);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
user.setCoolDownCheckSite(coolDownChecks);
|
||||
}
|
||||
|
||||
schedulePerSite(user, false);
|
||||
if (!plugin.getConfigFile().isPerSiteCoolDownEvents()) {
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<String, Boolean> coolDownChecks = user.getCoolDownCheckSiteList();
|
||||
boolean changed = false;
|
||||
|
||||
for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
if (site == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Boolean.TRUE.equals(coolDownChecks.get(site.getKey()))) {
|
||||
if (user.canVoteSite(site)) {
|
||||
coolDownChecks.put(site.getKey(), Boolean.TRUE);
|
||||
changed = true;
|
||||
|
||||
plugin.extraDebug("Triggering votesitecooldownend event for " + user.getUUID());
|
||||
PlayerVoteSiteCoolDownEndEvent event = new PlayerVoteSiteCoolDownEndEvent(user, site);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
user.setCoolDownCheckSite(coolDownChecks);
|
||||
}
|
||||
|
||||
schedulePerSite(user, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Site-specific version used by batch checks / checkAllVoteSite.
|
||||
*/
|
||||
private void checkPerSite(VoteSite site, VotingPluginUser user) {
|
||||
if (!plugin.getConfigFile().isPerSiteCoolDownEvents() || site == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<String, Boolean> coolDownChecks = user.getCoolDownCheckSiteList();
|
||||
if (Boolean.TRUE.equals(coolDownChecks.get(site.getKey()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.canVoteSite(site)) {
|
||||
coolDownChecks.put(site.getKey(), Boolean.TRUE);
|
||||
user.setCoolDownCheckSite(coolDownChecks);
|
||||
|
||||
plugin.extraDebug(
|
||||
"Triggering votesitecooldownend event on site " + site.getKey() + " for " + user.getUUID());
|
||||
PlayerVoteSiteCoolDownEndEvent event = new PlayerVoteSiteCoolDownEndEvent(user, site);
|
||||
plugin.getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
public void load() {
|
||||
@@ -136,27 +208,17 @@ public class CoolDownCheck implements Listener {
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
|
||||
checkAllVoteSites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartUp(AdvancedCoreUser advancedcoreUser) {
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(advancedcoreUser);
|
||||
user.dontCache();
|
||||
if (cooldownCheckEnabled) {
|
||||
check(user);
|
||||
}
|
||||
if (plugin.getConfigFile().isPerSiteCoolDownEvents()) {
|
||||
checkPerSite(user);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
@@ -168,61 +230,77 @@ public class CoolDownCheck implements Listener {
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onCoolDownEnd(PlayerVoteSiteCoolDownEndEvent event) {
|
||||
plugin.getRewardHandler().giveReward(event.getPlayer(), event.getSite().getSiteData(), "CoolDownEndRewards",
|
||||
new RewardOptions().addPlaceholder("sitename", event.getSite().getDisplayName()).addPlaceholder("url",
|
||||
event.getSite().getVoteURL(false)));
|
||||
new RewardOptions().addPlaceholder("sitename", event.getSite().getDisplayName())
|
||||
.addPlaceholder("url", event.getSite().getVoteURL(false)));
|
||||
}
|
||||
|
||||
public void schedule(VotingPluginUser user, boolean force) {
|
||||
if (user.getSitesVotedOn() > 0 || force) {
|
||||
final UUID uuid = UUID.fromString(user.getUUID());
|
||||
long time = user.getNextTimeAllSitesAvailable();
|
||||
if (allSiteTasks.containsKey(uuid)) {
|
||||
allSiteTasks.get(uuid).cancel(false);
|
||||
allSiteTasks.remove(uuid);
|
||||
}
|
||||
if (time > 0) {
|
||||
user.setCoolDownCheck(true);
|
||||
ScheduledFuture<?> scheduledFuture = timer.schedule(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (plugin != null && plugin.isEnabled()) {
|
||||
check(uuid);
|
||||
}
|
||||
}
|
||||
}, time + 2, TimeUnit.SECONDS);
|
||||
allSiteTasks.put(uuid, scheduledFuture);
|
||||
} else {
|
||||
plugin.extraDebug(user.getUUID() + "/" + user.getPlayerName() + " not scheduling cooldown check");
|
||||
}
|
||||
if (user.getSitesVotedOn() <= 0 && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
final UUID uuid = user.getJavaUUID();
|
||||
final long time = user.getNextTimeAllSitesAvailable();
|
||||
|
||||
allSiteTasks.compute(uuid, (k, existing) -> {
|
||||
if (existing != null) {
|
||||
existing.cancel(false);
|
||||
}
|
||||
|
||||
if (time <= 0) {
|
||||
plugin.extraDebug(user.getUUID() + "/" + user.getPlayerName() + " not scheduling cooldown check");
|
||||
return null; // remove entry
|
||||
}
|
||||
|
||||
user.setCoolDownCheck(true);
|
||||
|
||||
return timer.schedule(() -> {
|
||||
if (plugin.isEnabled()) {
|
||||
check(uuid);
|
||||
}
|
||||
}, time + 2, TimeUnit.SECONDS);
|
||||
});
|
||||
}
|
||||
|
||||
public void schedulePerSite(VotingPluginUser user, boolean force) {
|
||||
if (user.getSitesVotedOn() > 0 || force) {
|
||||
final UUID uuid = UUID.fromString(user.getUUID());
|
||||
long time = user.getNextTimeFirstSiteAvailable();
|
||||
if (perSiteTasks.containsKey(uuid)) {
|
||||
perSiteTasks.get(uuid).cancel(false);
|
||||
perSiteTasks.remove(uuid);
|
||||
}
|
||||
if (time > 0) {
|
||||
plugin.devDebug("PerSiteCoolDownEvent schedule time: " + time + " seconds");
|
||||
ScheduledFuture<?> scheduledFuture = timer.schedule(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (plugin != null && plugin.isEnabled()) {
|
||||
checkPerSite(uuid);
|
||||
}
|
||||
}
|
||||
}, time + 2, TimeUnit.SECONDS);
|
||||
perSiteTasks.put(uuid, scheduledFuture);
|
||||
} else {
|
||||
plugin.extraDebug(user.getUUID() + "/" + user.getPlayerName() + " not scheduling cooldown check");
|
||||
}
|
||||
if (!plugin.getConfigFile().isPerSiteCoolDownEvents()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.getSitesVotedOn() <= 0 && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
final UUID uuid = user.getJavaUUID();
|
||||
|
||||
final NextSite next = user.getNextSiteAvailable();
|
||||
|
||||
perSiteTasks.compute(uuid, (k, existing) -> {
|
||||
if (existing != null) {
|
||||
existing.cancel(false);
|
||||
}
|
||||
|
||||
if (next == null || next.getSite() == null || next.getSecondsUntilAvailable() <= 0) {
|
||||
plugin.extraDebug(user.getUUID() + "/" + user.getPlayerName() + " not scheduling per-site cooldown check");
|
||||
return null; // remove entry
|
||||
}
|
||||
|
||||
plugin.devDebug("PerSiteCoolDownEvent schedule: site=" + next.getSite().getKey() + " time="
|
||||
+ next.getSecondsUntilAvailable() + " seconds");
|
||||
|
||||
return timer.schedule(() -> {
|
||||
if (!plugin.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only check the next site; this will set the cooldown-end flag + fire event if ready
|
||||
checkPerSite(next.getSite(), user);
|
||||
|
||||
// Schedule the following site (if any)
|
||||
schedulePerSite(user, false);
|
||||
|
||||
}, next.getSecondsUntilAvailable() + 2, TimeUnit.SECONDS);
|
||||
});
|
||||
}
|
||||
|
||||
public void vote(VotingPluginUser user, VoteSite site) {
|
||||
@@ -236,4 +314,55 @@ public class CoolDownCheck implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performance-optimized: scan users ONCE, process all daily-delay sites.
|
||||
*/
|
||||
public void checkAllVoteSites() {
|
||||
final List<VoteSite> sites = plugin.getVoteSiteManager().getVoteSites();
|
||||
if (sites == null || sites.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ArrayList<VoteSite> dailySites = new ArrayList<>();
|
||||
for (int i = 0; i < sites.size(); i++) {
|
||||
VoteSite site = sites.get(i);
|
||||
if (site != null && site.isVoteDelayDaily()) {
|
||||
dailySites.add(site);
|
||||
}
|
||||
}
|
||||
|
||||
if (dailySites.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.debug("Checking vote cooldown rewards for all players across " + dailySites.size() + " sites...");
|
||||
|
||||
plugin.getUserManager().forEachUserKeys((uuid, cols) -> {
|
||||
if (!plugin.isEnabled() || uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(uuid, false);
|
||||
if (user == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
user.userDataFetechMode(UserDataFetchMode.TEMP_ONLY);
|
||||
|
||||
try {
|
||||
if (cols != null) {
|
||||
user.updateTempCacheWithColumns(cols);
|
||||
cols.clear();
|
||||
}
|
||||
|
||||
for (int i = 0; i < dailySites.size(); i++) {
|
||||
checkPerSite(dailySites.get(i), user);
|
||||
}
|
||||
|
||||
check(user);
|
||||
} finally {
|
||||
user.clearTempCache();
|
||||
}
|
||||
}, (count) -> plugin.debug("Finished checking vote cooldown rewards (processed: " + count + " users)"));
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@@ -12,6 +13,8 @@ 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.advancedcore.api.user.AdvancedCoreUser;
|
||||
import com.bencodez.advancedcore.api.user.UserStartup;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.topvoter.TopVoter;
|
||||
import com.bencodez.votingplugin.topvoter.TopVoterPlayer;
|
||||
@@ -65,6 +68,37 @@ public class DiscordHandler {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
plugin.addUserStartup(new UserStartup() {
|
||||
|
||||
@Override
|
||||
public void onStartUp(AdvancedCoreUser user) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostFinish() {
|
||||
|
||||
plugin.getTimer().scheduleAtFixedRate(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
updateDiscordLeaderboard();
|
||||
}
|
||||
}, 130, 60 * 60, TimeUnit.SECONDS); // 10-minute interval
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/** Fired once JDA is fully initialized */
|
||||
@@ -93,45 +127,64 @@ public class DiscordHandler {
|
||||
}
|
||||
|
||||
public void updateTopVoterMessageId(TopVoter top) {
|
||||
plugin.extraDebug("Updating Discord Top Voter message for: " + top);
|
||||
|
||||
long channelId = plugin.getConfigFile().getDiscordSRVTopVoterChannel(top);
|
||||
LinkedHashMap<TopVoterPlayer, Integer> topVoters = plugin.getTopVoter(top);
|
||||
|
||||
String title = plugin.getConfigFile().getDiscordSRVTopVoterTitle(top);
|
||||
String rankDisplay = plugin.getConfigFile().getDiscordSRVTopVoterRankDisplay(top);
|
||||
boolean newMessage = plugin.getConfigFile().isDiscordSRVTopVoterNewMessageOnUpdate(top);
|
||||
|
||||
EmbedBuilder eb = new EmbedBuilder().setTitle(title).setColor(Color.CYAN).setTimestamp(Instant.now());
|
||||
|
||||
int rank = 1;
|
||||
for (Entry<TopVoterPlayer, Integer> entry : topVoters.entrySet()) {
|
||||
if (rank > 10)
|
||||
break;
|
||||
String line = rankDisplay.replace("%rank%", String.valueOf(rank))
|
||||
.replace("%player%", entry.getKey().getPlayerName())
|
||||
.replace("%votes%", String.valueOf(entry.getValue()));
|
||||
eb.addField("", line, false);
|
||||
rank++;
|
||||
if (topVoters == null || topVoters.isEmpty()) {
|
||||
eb.setDescription("No votes recorded yet.");
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("```");
|
||||
int rank = 1;
|
||||
|
||||
for (Entry<TopVoterPlayer, Integer> entry : topVoters.entrySet()) {
|
||||
if (rank > 10)
|
||||
break;
|
||||
|
||||
String prefix = rank <= 3 ? new String[] { "🥇", "🥈", "🥉" }[rank - 1] : rank + ".";
|
||||
|
||||
String player = entry.getKey().getPlayerName();
|
||||
int votes = entry.getValue();
|
||||
|
||||
// simple alignment: trim long names, pad to 16 chars
|
||||
if (player.length() > 16)
|
||||
player = player.substring(0, 16);
|
||||
|
||||
sb.append(String.format("%-3s %-16s %4d votes%n", prefix, player, votes));
|
||||
rank++;
|
||||
}
|
||||
sb.append("```");
|
||||
|
||||
eb.setDescription(sb.toString()).setFooter("Top 10 • Updated");
|
||||
}
|
||||
|
||||
TextChannel channel = DiscordUtil.getJda().getTextChannelById(channelId);
|
||||
if (channel == null) {
|
||||
plugin.getLogger().warning("Discord channel ID " + channelId + " not found: " + top.toString());
|
||||
plugin.getLogger().warning("Discord channel ID " + channelId + " not found: " + top);
|
||||
return;
|
||||
}
|
||||
|
||||
if (topVoterMessageIds.get(top) <= 0) {
|
||||
long existingId = topVoterMessageIds.getOrDefault(top, 0L);
|
||||
|
||||
if (existingId <= 0 || newMessage) {
|
||||
channel.sendMessageEmbeds(eb.build()).queue(msg -> {
|
||||
long newId = msg.getIdLong();
|
||||
topVoterMessageIds.put(top, newId);
|
||||
plugin.getServerData().setTopVoterMessageId(top, newId);
|
||||
plugin.getLogger().info("Posted new Top Voters " + top.toString() + " (ID: " + newId + ")");
|
||||
}, err -> plugin.getLogger()
|
||||
.warning("Error sending Top Voters " + top.toString() + ": " + err.getMessage()));
|
||||
if (!newMessage)
|
||||
plugin.getServerData().setTopVoterMessageId(top, newId);
|
||||
plugin.debug("Posted new Top Voters " + top + " (ID: " + newId + ")");
|
||||
}, err -> plugin.getLogger().warning("Error sending Top Voters " + top + ": " + err.getMessage()));
|
||||
} else {
|
||||
channel.editMessageEmbedsById(topVoterMessageIds.get(top), eb.build())
|
||||
.queue(m -> plugin.getLogger()
|
||||
.info("Edited Top Voters " + top.toString() + " (ID: " + topVoterMessageIds.get(top) + ")"),
|
||||
err -> plugin.getLogger()
|
||||
.warning("Error editing Top Voters" + top.toString() + ": " + err.getMessage()));
|
||||
channel.editMessageEmbedsById(existingId, eb.build()).queue(
|
||||
m -> plugin.debug("Edited Top Voters " + top + " (ID: " + existingId + ")"),
|
||||
err -> plugin.getLogger().warning("Error editing Top Voters " + top + ": " + err.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-5
@@ -1,11 +1,13 @@
|
||||
package com.bencodez.votingplugin.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.proxy.BungeeMessageData;
|
||||
import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -34,7 +36,7 @@ public class PlayerPostVoteEvent extends Event {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private BungeeMessageData bungeeTextTotals;
|
||||
private VoteTotalsSnapshot bungeeTextTotals;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@@ -62,16 +64,36 @@ public class PlayerPostVoteEvent extends Event {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private VotingPluginUser votingPluginUser;
|
||||
private boolean cached;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String service;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private UUID uuid;
|
||||
@Getter
|
||||
@Setter
|
||||
private String playerName;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private UUID voteUUID;
|
||||
|
||||
public PlayerPostVoteEvent(VoteSite voteSite, VotingPluginUser user, boolean realVote, boolean forceBungee,
|
||||
long voteTime) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+8
-1
@@ -1,5 +1,7 @@
|
||||
package com.bencodez.votingplugin.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
@@ -38,10 +40,15 @@ public class PlayerSpecialRewardEvent extends Event {
|
||||
@Setter
|
||||
private VotingPluginUser user;
|
||||
|
||||
public PlayerSpecialRewardEvent(VotingPluginUser user, SpecialRewardType type) {
|
||||
@Getter
|
||||
@Setter
|
||||
private UUID voteUUID;
|
||||
|
||||
public PlayerSpecialRewardEvent(VotingPluginUser user, SpecialRewardType type, UUID voteUUID) {
|
||||
super(true);
|
||||
this.type = type;
|
||||
this.user = user;
|
||||
this.voteUUID = voteUUID;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -3,9 +3,9 @@ package com.bencodez.votingplugin.events;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.proxy.BungeeMessageData;
|
||||
import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -38,7 +38,7 @@ public class PlayerVoteEvent extends Event {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private BungeeMessageData bungeeTextTotals;
|
||||
private VoteTotalsSnapshot bungeeTextTotals;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
|
||||
+1
-1
@@ -3,8 +3,8 @@ package com.bencodez.votingplugin.events;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.bencodez.votingplugin.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@@ -3,7 +3,13 @@ package com.bencodez.votingplugin.events;
|
||||
import lombok.Getter;
|
||||
|
||||
public enum SpecialRewardType {
|
||||
ALLSITE, CUMMULATIVE, FIRSTVOTE, FIRSTVOTETODAY, MILESTONE, VOTESTREAK, ALMOSTALLSITES;
|
||||
@Deprecated
|
||||
ALLSITE, @Deprecated
|
||||
CUMMULATIVE, @Deprecated
|
||||
FIRSTVOTE, @Deprecated
|
||||
FIRSTVOTETODAY, @Deprecated
|
||||
MILESTONE, VOTESTREAK, @Deprecated
|
||||
ALMOSTALLSITES, TOPVOTER, VOTESTREAKS;
|
||||
|
||||
@Getter
|
||||
private int amount = -1;
|
||||
@@ -21,4 +27,26 @@ public enum SpecialRewardType {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(name());
|
||||
|
||||
if (amount >= 0) {
|
||||
sb.append("(amount=").append(amount);
|
||||
}
|
||||
|
||||
if (type != null && !type.isEmpty()) {
|
||||
if (amount >= 0) {
|
||||
sb.append(", ");
|
||||
} else {
|
||||
sb.append("(");
|
||||
}
|
||||
sb.append("type=").append(type).append(")");
|
||||
} else if (amount >= 0) {
|
||||
sb.append(")");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package com.bencodez.votingplugin.events;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.bencodez.votingplugin.specialrewards.votemilestones.VoteMilestone;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Fired after a VoteMilestone reward has been executed successfully.
|
||||
*/
|
||||
public class VoteMilestoneRewardEvent extends Event {
|
||||
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private final VotingPluginUser user;
|
||||
private final UUID uuid;
|
||||
private final String playerName;
|
||||
|
||||
private final VoteMilestone milestone;
|
||||
private final long value;
|
||||
|
||||
private final String groupId;
|
||||
private final String rewardPath;
|
||||
@Getter
|
||||
private final UUID voteUUID;
|
||||
private final Map<String, String> placeholders;
|
||||
|
||||
/**
|
||||
* Constructs a new VoteMilestoneRewardEvent.
|
||||
*
|
||||
* @param user VotingPluginUser who received the reward
|
||||
* @param milestone milestone that triggered
|
||||
* @param value resolved total value used for matching
|
||||
* @param groupId resolved group id used for selection
|
||||
* @param rewardPath path used to execute rewards
|
||||
* @param placeholders placeholders passed to the reward handler
|
||||
* @param voteUUID UUID of the vote that triggered this reward (may be null)
|
||||
*/
|
||||
public VoteMilestoneRewardEvent(VotingPluginUser user, VoteMilestone milestone, long value, String groupId,
|
||||
String rewardPath, Map<String, String> placeholders, UUID voteUUID) {
|
||||
super(true);
|
||||
this.user = user;
|
||||
this.uuid = user == null ? null : user.getJavaUUID();
|
||||
this.playerName = user == null ? null : user.getPlayerName();
|
||||
this.milestone = milestone;
|
||||
this.value = value;
|
||||
this.groupId = groupId;
|
||||
this.rewardPath = rewardPath;
|
||||
this.voteUUID = voteUUID;
|
||||
if (placeholders == null || placeholders.isEmpty()) {
|
||||
this.placeholders = Collections.emptyMap();
|
||||
} else {
|
||||
this.placeholders = Collections.unmodifiableMap(new HashMap<>(placeholders));
|
||||
}
|
||||
}
|
||||
|
||||
public VotingPluginUser getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return playerName;
|
||||
}
|
||||
|
||||
public VoteMilestone getMilestone() {
|
||||
return milestone;
|
||||
}
|
||||
|
||||
public String getMilestoneId() {
|
||||
return milestone == null ? null : milestone.getId();
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public String getRewardPath() {
|
||||
return rewardPath;
|
||||
}
|
||||
|
||||
public Map<String, String> getPlaceholders() {
|
||||
return placeholders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Fired when a player attempts to purchase an item from VotingPlugin's
|
||||
* VoteShop.
|
||||
*/
|
||||
public class VoteShopPurchaseEvent extends Event {
|
||||
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
@Getter
|
||||
private UUID playerUuid;
|
||||
@Getter
|
||||
private String playerName;
|
||||
@Getter
|
||||
private VotingPluginUser user;
|
||||
|
||||
@Getter
|
||||
private String identifier;
|
||||
|
||||
@Getter
|
||||
private int cost;
|
||||
|
||||
public VoteShopPurchaseEvent(UUID playerUUID, String playerName, VotingPluginUser user, String identifier,
|
||||
int cost) {
|
||||
super(true);
|
||||
this.playerName = playerName;
|
||||
this.user = user;
|
||||
this.playerUuid = playerUUID;
|
||||
this.identifier = identifier;
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
+74
-43
@@ -6,18 +6,20 @@ 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.proxy.VotingPluginWire;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
* The Class PlayerJoinEvent.
|
||||
*/
|
||||
public class PlayerJoinEvent implements Listener {
|
||||
|
||||
/** The plugin. */
|
||||
private VotingPluginMain plugin;
|
||||
private final VotingPluginMain plugin;
|
||||
|
||||
/**
|
||||
* Instantiates a new player join event.
|
||||
@@ -28,21 +30,48 @@ public class PlayerJoinEvent implements Listener {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
private void login(Player player) {
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(player);
|
||||
if (player.isOp() && plugin.isYmlError()) {
|
||||
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");
|
||||
}
|
||||
|
||||
boolean data = user.getData().hasData();
|
||||
// run remind
|
||||
user.loginMessage();
|
||||
|
||||
if (data) {
|
||||
if (hasData) {
|
||||
// give offline vote (if they voted offline)
|
||||
user.offVote();
|
||||
} else {
|
||||
plugin.debug("No data detected for " + player.getUniqueId().toString() + "/" + player.getName());
|
||||
plugin.debug("No data detected for " + user.getUUID() + "/" + user.getPlayerName());
|
||||
}
|
||||
|
||||
user.loginRewards();
|
||||
@@ -50,42 +79,44 @@ public class PlayerJoinEvent implements Listener {
|
||||
plugin.getPlaceholders().onUpdate(user, true);
|
||||
|
||||
if (plugin.getBungeeSettings().isUseBungeecoord()) {
|
||||
plugin.getBungeeHandler().getGlobalMessageHandler().sendMessage("Login", user.getPlayerName(),
|
||||
user.getUUID(), plugin.getBungeeSettings().getServer());
|
||||
plugin.getBungeeHandler().getGlobalMessageHandler().sendMessage(VotingPluginWire.login(user.getPlayerName(),
|
||||
user.getUUID(), plugin.getBungeeSettings().getServer()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On player login.
|
||||
*
|
||||
* @param event the event
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onPlayerLogin(AdvancedCoreLoginEvent event) {
|
||||
if (event.getPlayer() == null || !plugin.isMySQLOkay()) {
|
||||
return;
|
||||
}
|
||||
|
||||
login(event.getPlayer());
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
if (plugin != null && plugin.isEnabled()) {
|
||||
final Player player = event.getPlayer();
|
||||
plugin.getLoginTimer().execute(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
VotingPluginMain.plugin.getAdvancedTab().remove(player.getUniqueId());
|
||||
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(player);
|
||||
user.dontCache();
|
||||
user.logoutRewards();
|
||||
plugin.getPlaceholders().onLogout(user);
|
||||
}
|
||||
});
|
||||
if (plugin == null || !plugin.isEnabled() || event == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Player player = event.getPlayer();
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+69
-70
@@ -3,7 +3,8 @@ package com.bencodez.votingplugin.listeners;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -11,14 +12,15 @@ 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.misc.PlayerManager;
|
||||
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.objects.VoteSite;
|
||||
import com.bencodez.votingplugin.topvoter.TopVoter;
|
||||
import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
import com.bencodez.votingplugin.votesites.VoteSite;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
@@ -51,34 +53,34 @@ public class PlayerVoteListener implements Listener {
|
||||
String playerName = event.getPlayer();
|
||||
plugin.debug("Processing PlayerVoteEvent: " + playerName + "/" + event.getServiceSite());
|
||||
|
||||
boolean notValid = false;
|
||||
if (!PlayerManager.getInstance().isValidUser(playerName, plugin.getConfigFile().isAllowUnJoinedCheckServer())) {
|
||||
if (!playerName.startsWith(plugin.getOptions().getBedrockPlayerPrefix())
|
||||
&& !plugin.getOptions().getBedrockPlayerPrefix().isEmpty()) {
|
||||
if (!event.isBungee() && PlayerManager.getInstance().isValidUser(
|
||||
plugin.getOptions().getBedrockPlayerPrefix() + playerName,
|
||||
plugin.getConfigFile().isAllowUnJoinedCheckServer())) {
|
||||
plugin.debug("Detected a bedrock user without bedrock prefix, adjusting");
|
||||
playerName = plugin.getOptions().getBedrockPlayerPrefix() + playerName;
|
||||
} else {
|
||||
notValid = true;
|
||||
}
|
||||
} else {
|
||||
notValid = true;
|
||||
}
|
||||
}
|
||||
// check for name casing
|
||||
final String properName = plugin.getUserManager().getProperName(playerName);
|
||||
|
||||
if (notValid) {
|
||||
// Resolve Bedrock/Java + add prefix only when appropriate
|
||||
BedrockNameResolver.Result rn = plugin.getBedrockHandle().resolve(properName);
|
||||
String creditedName = rn.finalName;
|
||||
|
||||
plugin.debug("Vote name resolved: " + properName + " -> " + creditedName + " (" + rn.rationale + ")");
|
||||
|
||||
// Single validity check on the final name
|
||||
boolean allowUnJoinedCheckServer = plugin.getConfigFile().isAllowUnJoinedCheckServer();
|
||||
boolean isValid = PlayerManager.getInstance().isValidUser(creditedName, allowUnJoinedCheckServer);
|
||||
|
||||
// Handle not-valid the same way you did before
|
||||
if (!isValid) {
|
||||
if (!plugin.getConfigFile().isAllowUnjoined()) {
|
||||
plugin.getLogger().warning("Player " + playerName
|
||||
+ " has not joined before, disregarding vote, set AllowUnjoined to true to prevent this");
|
||||
plugin.getLogger().warning("Player " + creditedName + " has not joined before, disregarding vote. "
|
||||
+ "Set AllowUnjoined to true to accept.");
|
||||
if (event.isBungee() && plugin.getBungeeSettings().isRemoveInvalidUsers()) {
|
||||
plugin.getVotingPluginUserManager().getVotingPluginUser(playerName).remove();
|
||||
plugin.getVotingPluginUserManager().getVotingPluginUser(creditedName).remove();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
@@ -96,7 +98,8 @@ public class PlayerVoteListener implements Listener {
|
||||
VoteSite voteSite = event.getVoteSite();
|
||||
|
||||
if (voteSite == null) {
|
||||
voteSite = plugin.getVoteSite(plugin.getVoteSiteName(true, event.getServiceSite()), true);
|
||||
voteSite = plugin.getVoteSiteManager()
|
||||
.getVoteSite(plugin.getVoteSiteManager().getVoteSiteName(true, event.getServiceSite()), true);
|
||||
}
|
||||
|
||||
// check valid service sites
|
||||
@@ -105,7 +108,7 @@ public class PlayerVoteListener implements Listener {
|
||||
plugin.getLogger().warning("No voting site with the service site: '" + event.getServiceSite() + "'");
|
||||
|
||||
ArrayList<String> services = new ArrayList<>();
|
||||
for (VoteSite site : plugin.getVoteSites()) {
|
||||
for (VoteSite site : plugin.getVoteSiteManager().getVoteSites()) {
|
||||
services.add(site.getServiceSite());
|
||||
}
|
||||
plugin.getLogger().warning("Currently set service sites: " + ArrayUtils.makeStringList(services));
|
||||
@@ -128,14 +131,6 @@ public class PlayerVoteListener implements Listener {
|
||||
user = plugin.getVotingPluginUserManager().getVotingPluginUser(p);
|
||||
} else {
|
||||
// attempt to get exact name from cache matching casing
|
||||
if (!plugin.getOptions().isOnlineMode()) {
|
||||
for (Entry<String, String> entry : plugin.getUuidNameCache().entrySet()) {
|
||||
if (entry.getValue().equalsIgnoreCase(playerName)) {
|
||||
playerName = entry.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
user = plugin.getVotingPluginUserManager().getVotingPluginUser(playerName);
|
||||
}
|
||||
}
|
||||
@@ -153,6 +148,14 @@ public class PlayerVoteListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -163,20 +166,21 @@ public class PlayerVoteListener implements Listener {
|
||||
// vote party
|
||||
plugin.getVoteParty().vote(user, event.isRealVote(), event.isForceBungee());
|
||||
|
||||
if (event.isBroadcast() && !plugin.getBungeeSettings().isDisableBroadcast()) {
|
||||
// broadcast vote if enabled in config
|
||||
if (plugin.getConfigFile().isBroadcastVotesEnabled()
|
||||
&& (plugin.getBungeeSettings().isBungeeBroadcast() || !event.isBungee())) {
|
||||
if (!plugin.getConfigFile().isFormatBroadcastWhenOnline() || user.isOnline()) {
|
||||
voteSite.broadcastVote(user);
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plugin.getBroadcastHandler() != null) {
|
||||
plugin.getBroadcastHandler().onVote(playerName);
|
||||
}
|
||||
|
||||
long voteTime = 0;
|
||||
// update last vote time
|
||||
if (event.getTime() != 0) {
|
||||
@@ -187,24 +191,7 @@ public class PlayerVoteListener implements Listener {
|
||||
voteTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
// try logging to file
|
||||
if (plugin.getConfigFile().isLogVotesToFile()) {
|
||||
try {
|
||||
plugin.logVote(LocalDateTime.now().atZone(ZoneId.systemDefault()).toLocalDateTime(), playerName,
|
||||
voteSite.getKey());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// check first vote rewards
|
||||
plugin.getSpecialRewards().checkFirstVote(user, event.isForceBungee());
|
||||
plugin.getSpecialRewards().checkFirstVoteToday(user, event.isForceBungee());
|
||||
|
||||
if (user.isReminded() && plugin.getConfigFile().isVoteRemindingRemindOnlyOnce()) {
|
||||
user.setReminded(false);
|
||||
}
|
||||
|
||||
boolean cached = false;
|
||||
// check if player has voted on all sites in one day
|
||||
if (((user.isOnline() || voteSite.isGiveOffline()) && plugin.getOptions().isProcessRewards())
|
||||
|| event.isBungee()) {
|
||||
@@ -212,7 +199,7 @@ public class PlayerVoteListener implements Listener {
|
||||
if (event.isBungee()) {
|
||||
online = event.isWasOnline();
|
||||
}
|
||||
user.playerVote(voteSite, online, false, event.isForceBungee());
|
||||
user.playerVote(voteSite, online, event.isForceBungee());
|
||||
if (event.getVoteNumber() == 1) {
|
||||
user.sendVoteEffects(online);
|
||||
}
|
||||
@@ -223,6 +210,7 @@ public class PlayerVoteListener implements Listener {
|
||||
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 {
|
||||
@@ -253,25 +241,36 @@ public class PlayerVoteListener implements Listener {
|
||||
LocalDateTime cTime = plugin.getTimeChecker().getTime();
|
||||
int days = cTime.getDayOfMonth();
|
||||
plugin.extraDebug("Current day of month: " + days + " Current total: " + value);
|
||||
if (value >= days * plugin.getVoteSitesEnabled().size()) {
|
||||
if (value >= days * plugin.getVoteSiteManager().getVoteSitesEnabled().size()) {
|
||||
plugin.debug("Detected higher month total, changing. Current Total: " + value + " Days: " + days
|
||||
+ " New Total: " + days * plugin.getVoteSitesEnabled().size());
|
||||
user.setTotal(TopVoter.Monthly, days * plugin.getVoteSitesEnabled().size());
|
||||
+ " 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<String, String>());
|
||||
|
||||
// other rewards
|
||||
plugin.getSpecialRewards().checkAllSites(user, event.isForceBungee());
|
||||
plugin.getSpecialRewards().checkAlmostAllSites(user, event.isForceBungee());
|
||||
plugin.getSpecialRewards().checkCumualativeVotes(user, event.getBungeeTextTotals(), event.isForceBungee());
|
||||
plugin.getSpecialRewards().checkMilestone(user, event.getBungeeTextTotals(), event.isForceBungee());
|
||||
// plugin.getSpecialRewards().checkAllSites(voteUUID, user,
|
||||
// event.isForceBungee());
|
||||
// plugin.getSpecialRewards().checkAlmostAllSites(voteUUID, user,
|
||||
// event.isForceBungee());
|
||||
// plugin.getSpecialRewards().checkCumualativeVotes(voteUUID, user,
|
||||
// event.getBungeeTextTotals(),
|
||||
// event.isForceBungee());
|
||||
// plugin.getSpecialRewards().checkMilestone(voteUUID, user,
|
||||
// event.getBungeeTextTotals(), event.isForceBungee());
|
||||
plugin.getCoolDownCheck().vote(user, voteSite);
|
||||
|
||||
plugin.getVoteStreakHandler().processVote(user, voteTime, voteUUID);
|
||||
|
||||
PlayerPostVoteEvent postVoteEvent = new PlayerPostVoteEvent(voteSite, user, event.isRealVote(),
|
||||
event.isForceBungee(), voteTime);
|
||||
event.isForceBungee(), voteTime, cached, voteSite.getServiceSite(), user.getJavaUUID(), playerName,
|
||||
voteUUID);
|
||||
plugin.getServer().getPluginManager().callEvent(postVoteEvent);
|
||||
|
||||
if (user.isOnline()) {
|
||||
if (user.isOnline() || plugin.getConfigFile().getPlaceholderCacheLevel().isCacheAlways()) {
|
||||
plugin.getPlaceholders().onUpdate(user, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ public class VotiferEvent implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
String voteSiteNameStr = plugin.getVoteSiteName(false, voteSite, matchSite);
|
||||
String voteSiteNameStr = plugin.getVoteSiteManager().getVoteSiteName(false, voteSite, matchSite);
|
||||
|
||||
ArrayList<String> sites = plugin.getConfigVoteSites().getVoteSitesNames(false);
|
||||
boolean createSite = false;
|
||||
@@ -118,9 +118,9 @@ public class VotiferEvent implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
String voteSiteName = plugin.getVoteSiteName(true, serviceSite, matchSite);
|
||||
String voteSiteName = plugin.getVoteSiteManager().getVoteSiteName(true, serviceSite, matchSite);
|
||||
|
||||
PlayerVoteEvent voteEvent = new PlayerVoteEvent(plugin.getVoteSite(voteSiteName, true),
|
||||
PlayerVoteEvent voteEvent = new PlayerVoteEvent(plugin.getVoteSiteManager().getVoteSite(voteSiteName, true),
|
||||
voteUsername, voteSite, true);
|
||||
plugin.getServer().getPluginManager().callEvent(voteEvent);
|
||||
|
||||
|
||||
+1
-5
@@ -42,11 +42,7 @@ public class MVdWPlaceholders {
|
||||
public String onPlaceholderReplace(PlaceholderReplaceEvent event) {
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(event.getOfflinePlayer());
|
||||
if (plugin.getConfigFile().isUsePrimaryAccountForPlaceholders()
|
||||
&& user.hasPrimaryAccount()) {
|
||||
user = plugin.getVotingPluginUserManager()
|
||||
.getVotingPluginUser(user.getPrimaryAccount());
|
||||
}
|
||||
|
||||
return place.placeholderRequest(user,
|
||||
event.getPlaceholder().substring("VotingPlugin_".length()));
|
||||
}
|
||||
|
||||
+87
-85
@@ -25,12 +25,14 @@ 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.objects.VoteSite;
|
||||
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;
|
||||
|
||||
@@ -96,7 +98,8 @@ public class PlaceHolders {
|
||||
boolean useCache = true;
|
||||
String identifier = identifier1.toLowerCase();
|
||||
boolean custom = false;
|
||||
if (identifier.endsWith("_process")) {
|
||||
if (identifier.endsWith("_process")
|
||||
|| (!Bukkit.isPrimaryThread() && plugin.getConfigFile().isAlwaysProcessAsyncPlaceholders())) {
|
||||
forceProcess = true;
|
||||
identifier = identifier.replaceAll("_process", "");
|
||||
}
|
||||
@@ -174,11 +177,6 @@ public class PlaceHolders {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (plugin.getConfigFile().isUsePrimaryAccountForPlaceholders()) {
|
||||
if (user.hasPrimaryAccount()) {
|
||||
user = plugin.getVotingPluginUserManager().getVotingPluginUser(user.getPrimaryAccount());
|
||||
}
|
||||
}
|
||||
|
||||
UUID uuid = user.getJavaUUID();
|
||||
|
||||
@@ -305,80 +303,19 @@ public class PlaceHolders {
|
||||
}
|
||||
}.withDescription("Returns true/false if user has broadcast disabled").updateDataKey("DisableBroadcast"));
|
||||
|
||||
placeholders.add(new PlaceHolder<VotingPluginUser>("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"));
|
||||
|
||||
placeholders.add(new PlaceHolder<VotingPluginUser>("MilestoneCount") {
|
||||
|
||||
@Override
|
||||
public String placeholderRequest(VotingPluginUser user, String identifier) {
|
||||
return "" + user.getMilestoneCount();
|
||||
}
|
||||
}.withDescription("User milestonecount").updateDataKey("MilestoneCount"));
|
||||
|
||||
Set<String> mVotes = plugin.getSpecialRewardsConfig().getMilestoneVotes();
|
||||
for (String vote : mVotes) {
|
||||
if (MessageAPI.isInt(vote)) {
|
||||
|
||||
final int num = Integer.parseInt(vote);
|
||||
if (plugin.getSpecialRewardsConfig().getMilestoneRewardEnabled(num)) {
|
||||
placeholders.add(new PlaceHolder<VotingPluginUser>("milestone_numberofvotesuntil_" + num) {
|
||||
|
||||
@Override
|
||||
public String placeholderRequest(VotingPluginUser user, String identifier) {
|
||||
int toGo = num - user.getMilestoneCount();
|
||||
if (toGo >= 0) {
|
||||
return "" + toGo;
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
}.withDescription("Get number of votes until milestone").updateDataKey("MilestoneCount"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
placeholders.add(new PlaceHolder<VotingPluginUser>("nextmilestone_votes_required") {
|
||||
|
||||
@Override
|
||||
public String placeholderRequest(VotingPluginUser user, String identifier) {
|
||||
return "" + user.getNextAvailableMileStone();
|
||||
}
|
||||
}.withDescription("Get number of votes required for next available milestone").updateDataKey("MilestoneCount"));
|
||||
|
||||
placeholders.add(new PlaceHolder<VotingPluginUser>("nextmilestone_votes_until") {
|
||||
|
||||
@Override
|
||||
public String placeholderRequest(VotingPluginUser user, String identifier) {
|
||||
int toGo = user.getNextAvailableMileStone() - user.getMilestoneCount();
|
||||
if (toGo >= 0) {
|
||||
return "" + toGo;
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
}.withDescription("Get number of votes until next available milestone").updateDataKey("MilestoneCount"));
|
||||
|
||||
placeholders.add(new PlaceHolder<VotingPluginUser>("lastmilestone_votes_since") {
|
||||
|
||||
@Override
|
||||
public String placeholderRequest(VotingPluginUser user, String identifier) {
|
||||
int toGo = user.getMilestoneCount() - user.getLastGottenMilestone();
|
||||
if (toGo >= 0) {
|
||||
return "" + toGo;
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
}.withDescription("Get number of votes since last milestone").updateDataKey("MilestoneCount"));
|
||||
/*
|
||||
* placeholders.add(new PlaceHolder<VotingPluginUser>("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) {
|
||||
@@ -516,7 +453,7 @@ public class PlaceHolders {
|
||||
}
|
||||
long smallest = -1;
|
||||
HashMap<Long, VoteSite> times = new HashMap<>();
|
||||
for (VoteSite site : plugin.getVoteSitesEnabled()) {
|
||||
for (VoteSite site : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
long t = user.voteNextDurationTime(site);
|
||||
if (smallest == -1) {
|
||||
smallest = t;
|
||||
@@ -552,7 +489,7 @@ public class PlaceHolders {
|
||||
}
|
||||
}.withDescription("Get total number of sites available to be voted on"));
|
||||
|
||||
for (final VoteSite voteSite : plugin.getVoteSitesEnabled()) {
|
||||
for (final VoteSite voteSite : plugin.getVoteSiteManager().getVoteSitesEnabled()) {
|
||||
placeholders.add(new CalculatingPlaceholder<VotingPluginUser>("Next_" + voteSite.getKey()) {
|
||||
|
||||
@Override
|
||||
@@ -620,6 +557,71 @@ public class PlaceHolders {
|
||||
}
|
||||
}.withDescription("Return true/false if player has said points").updateDataKey("Points").useStartsWith());
|
||||
|
||||
// VoteMilestones placeholders (explicit per group, like
|
||||
// VoteShopLimit_<identifier>)
|
||||
// Base/default (no group suffix)
|
||||
placeholders.add(new PlaceHolder<VotingPluginUser>("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<VotingPluginUser>("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<VotingPluginUser>("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<String> 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<VotingPluginUser>("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<VotingPluginUser>("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<VotingPluginUser>("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<VotingPluginUser>("Top_AllVotes_") {
|
||||
|
||||
@Override
|
||||
@@ -1018,7 +1020,7 @@ public class PlaceHolders {
|
||||
|
||||
@Override
|
||||
public String placeholderRequest(String identifier) {
|
||||
LocalDateTime now = plugin.getTimeChecker().getTime();
|
||||
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();
|
||||
@@ -1121,7 +1123,7 @@ public class PlaceHolders {
|
||||
public void onChange(AdvancedCoreUser user, String... keys) {
|
||||
VotingPluginUser vpUser = plugin.getVotingPluginUserManager().getVotingPluginUser(user);
|
||||
if (!vpUser.isCached()) {
|
||||
vpUser.dontCache();
|
||||
vpUser.userDataFetechMode(UserDataFetchMode.NO_CACHE);
|
||||
}
|
||||
for (PlaceHolder<VotingPluginUser> placeholder : placeholders) {
|
||||
if (placeholder.isUsesCache()) {
|
||||
|
||||
+7
@@ -36,4 +36,11 @@ public enum PlaceholderCacheLevel {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCacheAlways() {
|
||||
if ((this == AUTOALL) || (this == SPECIFICALL)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class BungeeMessageData {
|
||||
|
||||
// Message string
|
||||
// alltimetotal//monthtotal//weeklytotal//dailytotal//points//milestonecount//votepartycurrent//votepartyrequired//datemonthtotal
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int allTimeTotal = 0;
|
||||
@Getter
|
||||
@Setter
|
||||
private int dailyTotal = 0;
|
||||
@Getter
|
||||
@Setter
|
||||
private int milestoneCount = 0;
|
||||
@Getter
|
||||
@Setter
|
||||
private int monthTotal = 0;
|
||||
@Getter
|
||||
@Setter
|
||||
private int dateMonthTotal = 0;
|
||||
@Getter
|
||||
@Setter
|
||||
private int points = 0;
|
||||
@Getter
|
||||
@Setter
|
||||
private int weeklyTotal = 0;
|
||||
@Getter
|
||||
@Setter
|
||||
private int votePartyCurrent = 0;
|
||||
@Getter
|
||||
@Setter
|
||||
private int votePartyRequired = 0;
|
||||
|
||||
public BungeeMessageData(int allTimeTotal, int monthTotal, int weeklyTotal, int dailyTotal, int points,
|
||||
int milestoneCount, int votePartyCurrent, int votePartyRequired, int dateMonthTotal) {
|
||||
this.allTimeTotal = allTimeTotal;
|
||||
this.monthTotal = monthTotal;
|
||||
this.weeklyTotal = weeklyTotal;
|
||||
this.dailyTotal = dailyTotal;
|
||||
this.points = points;
|
||||
this.milestoneCount = milestoneCount;
|
||||
this.votePartyCurrent = votePartyCurrent;
|
||||
this.votePartyRequired = votePartyRequired;
|
||||
this.dateMonthTotal = dateMonthTotal;
|
||||
}
|
||||
|
||||
public BungeeMessageData(String str) {
|
||||
String[] data = str.split(Pattern.quote("//"));
|
||||
if (data.length >= 6) {
|
||||
allTimeTotal = Integer.parseInt(data[0]);
|
||||
monthTotal = Integer.parseInt(data[1]);
|
||||
weeklyTotal = Integer.parseInt(data[2]);
|
||||
dailyTotal = Integer.parseInt(data[3]);
|
||||
points = Integer.parseInt(data[4]);
|
||||
milestoneCount = Integer.parseInt(data[5]);
|
||||
}
|
||||
if (data.length >= 8) {
|
||||
votePartyCurrent = Integer.parseInt(data[6]);
|
||||
votePartyRequired = Integer.parseInt(data[7]);
|
||||
}
|
||||
if (data.length >= 9) {
|
||||
dateMonthTotal = Integer.parseInt(data[8]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return allTimeTotal + "//" + monthTotal + "//" + weeklyTotal + "//" + dailyTotal + "//" + points + "//"
|
||||
+ milestoneCount + "//" + votePartyCurrent + "//" + votePartyRequired;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
public class BungeeVersion {
|
||||
public static int getPluginMessageVersion() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@@ -18,19 +20,39 @@ public class OfflineBungeeVote {
|
||||
private long time;
|
||||
@Getter
|
||||
private String uuid;
|
||||
@Getter
|
||||
private UUID voteId;
|
||||
|
||||
public OfflineBungeeVote(String playerName, String uuid, String service, long time, boolean realVote, String text) {
|
||||
public OfflineBungeeVote(UUID voteId, String playerName, String uuid, String service, long time, boolean realVote,
|
||||
String text) {
|
||||
this.playerName = playerName;
|
||||
this.uuid = uuid;
|
||||
this.service = service;
|
||||
this.time = time;
|
||||
this.realVote = realVote;
|
||||
this.text = text;
|
||||
this.voteId = voteId;
|
||||
}
|
||||
|
||||
public OfflineBungeeVote(String voteId, String playerName, String uuid, String service, long time, boolean realVote,
|
||||
String text) {
|
||||
this.playerName = playerName;
|
||||
this.uuid = uuid;
|
||||
this.service = service;
|
||||
this.time = time;
|
||||
this.realVote = realVote;
|
||||
this.text = text;
|
||||
if (voteId != null && !voteId.isEmpty()) {
|
||||
this.voteId = UUID.fromString(voteId);
|
||||
} else {
|
||||
this.voteId = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VoteCache:" + playerName + "/" + uuid + "/" + service + "/" + time + "/" + realVote + "/" + text;
|
||||
return "VoteCache:" + playerName + "/" + uuid + "/" + service + "/" + time + "/" + realVote + "/" + text + "/"
|
||||
+ voteId;
|
||||
}
|
||||
|
||||
}
|
||||
+326
-391
@@ -6,8 +6,6 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@@ -18,140 +16,113 @@ import com.bencodez.simpleapi.sql.DataType;
|
||||
import com.bencodez.simpleapi.sql.data.DataValue;
|
||||
import com.bencodez.simpleapi.sql.data.DataValueInt;
|
||||
import com.bencodez.simpleapi.sql.data.DataValueString;
|
||||
import com.bencodez.simpleapi.sql.mysql.AbstractSqlTable;
|
||||
import com.bencodez.simpleapi.sql.mysql.DbType;
|
||||
import com.bencodez.simpleapi.sql.mysql.MySQL;
|
||||
import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig;
|
||||
import com.bencodez.simpleapi.sql.mysql.queries.Query;
|
||||
|
||||
import lombok.Getter;
|
||||
public abstract class ProxyMysqlUserTable extends AbstractSqlTable {
|
||||
|
||||
public abstract class ProxyMysqlUserTable {
|
||||
private List<String> columns = Collections.synchronizedList(new ArrayList<String>());
|
||||
// Keep this so existing callers relying on getName() still work
|
||||
private final String name;
|
||||
|
||||
private List<String> intColumns = new ArrayList<>();
|
||||
// For int-vs-string decode in getExactQuery (same pattern as before)
|
||||
private final List<String> intColumns = new ArrayList<>();
|
||||
|
||||
// private HashMap<String, ArrayList<Column>> table;
|
||||
// Backwards-compat wrapper (your old code expects getUuids())
|
||||
private final Set<String> uuidsView;
|
||||
|
||||
// ConcurrentMap<String, ArrayList<Column>> table = new
|
||||
// ConcurrentHashMap<String, ArrayList<Column>>();
|
||||
// ---- Required subclass hooks ----
|
||||
|
||||
@Getter
|
||||
private com.bencodez.simpleapi.sql.mysql.MySQL mysql;
|
||||
@Override
|
||||
public String getPrimaryKeyColumn() {
|
||||
return "uuid";
|
||||
}
|
||||
|
||||
private String name;
|
||||
@Override
|
||||
public String buildCreateTableSql(DbType dbType) {
|
||||
// NOTE: AbstractSqlTable.qi(...) already quotes identifiers properly for
|
||||
// DbType.
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("CREATE TABLE IF NOT EXISTS ").append(qi(getTableName())).append(" (");
|
||||
|
||||
private Object object2 = new Object();
|
||||
// Best-case uuid type:
|
||||
// - Postgres: UUID
|
||||
// - MySQL/MariaDB: VARCHAR(37) (matches existing behavior)
|
||||
sb.append(qi("uuid")).append(" ").append(bestUuidType()).append(", ");
|
||||
sb.append("PRIMARY KEY ( ").append(qi("uuid")).append(" )");
|
||||
sb.append(");");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private Object object3 = new Object();
|
||||
// ---- Logging hooks required by AbstractSqlTable ----
|
||||
|
||||
private Object object4 = new Object();
|
||||
@Override
|
||||
public abstract void logSevere(String msg);
|
||||
|
||||
private Set<String> uuids = Collections.synchronizedSet(new HashSet<String>());
|
||||
@Override
|
||||
public abstract void logInfo(String msg);
|
||||
|
||||
public abstract void logSevere(String string);
|
||||
@Override
|
||||
public abstract void debug(Throwable t);
|
||||
|
||||
public abstract void logInfo(String string);
|
||||
// Keep these existing abstract methods for compatibility with your old
|
||||
// subclasses
|
||||
public abstract void debug(SQLException e);
|
||||
|
||||
// ---- Constructors ----
|
||||
|
||||
public ProxyMysqlUserTable(String tableName, MysqlConfig config, boolean debug) {
|
||||
super(tableName, config, debug);
|
||||
|
||||
if (config.hasTableNameSet()) {
|
||||
tableName = config.getTableName();
|
||||
}
|
||||
name = tableName;
|
||||
if (config.getTablePrefix() != null) {
|
||||
name = config.getTablePrefix() + tableName;
|
||||
}
|
||||
mysql = new com.bencodez.simpleapi.sql.mysql.MySQL(config.getMaxThreads()) {
|
||||
this.name = super.getTableName();
|
||||
|
||||
@Override
|
||||
public void debug(SQLException e) {
|
||||
if (debug) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// keep uuids view
|
||||
this.uuidsView = super.getPrimaryKeys();
|
||||
|
||||
@Override
|
||||
public void severe(String string) {
|
||||
logSevere(string);
|
||||
}
|
||||
// keep old "uuid column type tweak" behavior (but now uses base helper)
|
||||
alterColumnType("uuid", bestUuidType());
|
||||
|
||||
@Override
|
||||
public void debug(String msg) {
|
||||
if (debug) {
|
||||
logInfo("MYSQL DEBUG: " + msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!mysql.connect(config)) {
|
||||
|
||||
}
|
||||
try {
|
||||
Query q = new Query(mysql, "USE `" + config.getDatabase() + "`;");
|
||||
q.executeUpdateAsync();
|
||||
} catch (SQLException e) {
|
||||
severe("Failed to send use database query: " + config.getDatabase() + " Error: " + e.getMessage());
|
||||
debug(e);
|
||||
}
|
||||
String sql = "CREATE TABLE IF NOT EXISTS " + getName() + " (";
|
||||
sql += "uuid VARCHAR(37),";
|
||||
sql += "PRIMARY KEY ( uuid )";
|
||||
sql += ");";
|
||||
Query query;
|
||||
try {
|
||||
query = new Query(mysql, sql);
|
||||
|
||||
query.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
loadData();
|
||||
|
||||
// tempoary to improve performance from old tables
|
||||
// addToQue("ALTER TABLE " + getName() + " MODIFY uuid VARCHAR(37);");
|
||||
alterColumnType("uuid", "VARCHAR(37)");
|
||||
// load intColumns behavior if you rely on it elsewhere
|
||||
// (no-op: it's only used if you add to it)
|
||||
}
|
||||
|
||||
public void addColumn(String column, DataType dataType) {
|
||||
synchronized (object3) {
|
||||
String sql = "ALTER TABLE " + getName() + " ADD COLUMN `" + column + "` text" + ";";
|
||||
try {
|
||||
Query query = new Query(mysql, sql);
|
||||
query.executeUpdate();
|
||||
/**
|
||||
* Use an already-connected pool (shared).
|
||||
*/
|
||||
public ProxyMysqlUserTable(String tableName, MySQL existingMysql, boolean debug) {
|
||||
super(tableName, existingMysql, debug);
|
||||
|
||||
getColumns().add(column);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.name = super.getTableName();
|
||||
this.uuidsView = super.getPrimaryKeys();
|
||||
|
||||
}
|
||||
alterColumnType("uuid", bestUuidType());
|
||||
}
|
||||
|
||||
public void alterColumnType(String column, String newType) {
|
||||
checkColumn(column, DataType.STRING);
|
||||
|
||||
try {
|
||||
new Query(mysql, "ALTER TABLE " + getName() + " MODIFY `" + column + "` " + newType + ";")
|
||||
.executeUpdateAsync();
|
||||
} catch (SQLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (newType.contains("INT")) {
|
||||
if (!intColumns.contains(column)) {
|
||||
intColumns.add(column);
|
||||
}
|
||||
}
|
||||
// ---- Backwards-compatible API ----
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void checkColumn(String column, DataType dataType) {
|
||||
synchronized (object4) {
|
||||
if (!getColumns().contains(column)) {
|
||||
if (!getColumnsQueury().contains(column)) {
|
||||
addColumn(column, dataType);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Keep old method name and behavior.
|
||||
*/
|
||||
public Set<String> getUuids() {
|
||||
return getPrimaryKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep old behavior: query uuids fresh.
|
||||
*/
|
||||
public ArrayList<String> getUuidsQuery() {
|
||||
return new ArrayList<>(getPrimaryKeysQuery());
|
||||
}
|
||||
|
||||
public void loadData() {
|
||||
// old name -> new behavior
|
||||
loadBasicCaches();
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
@@ -159,176 +130,71 @@ public abstract class ProxyMysqlUserTable {
|
||||
}
|
||||
|
||||
public void clearCacheBasic() {
|
||||
columns.clear();
|
||||
columns.addAll(getColumnsQueury());
|
||||
uuids.clear();
|
||||
uuids.addAll(getUuidsQuery());
|
||||
clearCaches();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mysql.disconnect();
|
||||
public void shutdown() {
|
||||
close();
|
||||
}
|
||||
|
||||
// Keep old containsKeyQuery signature
|
||||
public boolean containsKeyQuery(String index) {
|
||||
String sqlStr = "SELECT uuid FROM " + getName() + ";";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement sql = conn.prepareStatement(sqlStr)) {
|
||||
ResultSet rs = sql.executeQuery();
|
||||
/*
|
||||
* Query query = new Query(mysql, sql); ResultSet rs = query.executeQuery();
|
||||
*/
|
||||
while (rs.next()) {
|
||||
if (rs.getString("uuid").equals(index)) {
|
||||
rs.close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
return super.containsKeyQuery(index);
|
||||
}
|
||||
|
||||
public void copyColumnData(String columnFromName, String columnToName) {
|
||||
checkColumn(columnFromName, DataType.STRING);
|
||||
checkColumn(columnToName, DataType.STRING);
|
||||
String sql = "UPDATE `" + getName() + "` SET `" + columnToName + "` = `" + columnFromName + "`;";
|
||||
try {
|
||||
Query query = new Query(mysql, sql);
|
||||
query.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void debug(SQLException e);
|
||||
|
||||
public List<String> getColumns() {
|
||||
if (columns == null || columns.size() == 0) {
|
||||
loadData();
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
// ---- Required old utility methods (kept) ----
|
||||
|
||||
public ArrayList<String> getColumnsQueury() {
|
||||
ArrayList<String> columns = new ArrayList<>();
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement sql = conn.prepareStatement("SHOW COLUMNS FROM `" + getName() + "`;")) {
|
||||
ResultSet rs = sql.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
String columnName = rs.getString(1);
|
||||
columns.add(columnName);
|
||||
|
||||
}
|
||||
|
||||
rs.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
public ArrayList<Column> getExactQuery(Column column) {
|
||||
ArrayList<Column> result = new ArrayList<>();
|
||||
String query = "SELECT * FROM " + getName() + " WHERE `" + column.getName() + "`='"
|
||||
+ column.getValue().getString() + "';";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement sql = conn.prepareStatement(query)) {
|
||||
ResultSet rs = sql.executeQuery();
|
||||
|
||||
/*
|
||||
* Query sql = new Query(mysql, query); sql.setParameter(1,
|
||||
* column.getValue().toString()); ResultSet rs = sql.executeQuery();
|
||||
*/
|
||||
if (rs.next()) {
|
||||
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
|
||||
String columnName = rs.getMetaData().getColumnLabel(i);
|
||||
Column rCol = null;
|
||||
if (intColumns.contains(columnName)) {
|
||||
rCol = new Column(columnName, DataType.INTEGER);
|
||||
rCol.setValue(new DataValueInt(rs.getInt(i)));
|
||||
} else {
|
||||
rCol = new Column(columnName, DataType.STRING);
|
||||
rCol.setValue(new DataValueString(rs.getString(i)));
|
||||
}
|
||||
result.add(rCol);
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
}
|
||||
|
||||
for (String col : getColumns()) {
|
||||
result.add(new Column(col, DataType.STRING));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ArrayList<String> getNamesQuery() {
|
||||
ArrayList<String> uuids = new ArrayList<>();
|
||||
|
||||
checkColumn("PlayerName", DataType.STRING);
|
||||
ArrayList<Column> rows = getRowsNameQuery();
|
||||
if (rows != null) {
|
||||
for (Column c : rows) {
|
||||
if (c.getValue().isString()) {
|
||||
uuids.add(c.getValue().getString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uuids;
|
||||
return new ArrayList<>(getColumnsQuery());
|
||||
}
|
||||
|
||||
public ArrayList<Column> getRowsNameQuery() {
|
||||
ArrayList<Column> result = new ArrayList<>();
|
||||
String sqlStr = "SELECT PlayerName FROM " + getName() + ";";
|
||||
checkColumn("PlayerName", DataType.STRING);
|
||||
|
||||
String sqlStr = "SELECT " + qi("PlayerName") + " FROM " + qi(getTableName()) + ";";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement sql = conn.prepareStatement(sqlStr)) {
|
||||
ResultSet rs = sql.executeQuery();
|
||||
/*
|
||||
* Query query = new Query(mysql, sql); ResultSet rs = query.executeQuery();
|
||||
*/
|
||||
PreparedStatement ps = conn.prepareStatement(sqlStr);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
|
||||
while (rs.next()) {
|
||||
Column rCol = new Column("PlayerName", new DataValueString(rs.getString("PlayerName")));
|
||||
result.add(rCol);
|
||||
result.add(new Column("PlayerName", new DataValueString(rs.getString(1))));
|
||||
}
|
||||
sql.close();
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
} catch (SQLException ignored) {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ArrayList<String> getNamesQuery() {
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
checkColumn("PlayerName", DataType.STRING);
|
||||
|
||||
ArrayList<Column> rows = getRowsNameQuery();
|
||||
if (rows != null) {
|
||||
for (Column c : rows) {
|
||||
if (c.getValue() != null && c.getValue().isString()) {
|
||||
String v = c.getValue().getString();
|
||||
if (v != null) {
|
||||
names.add(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
public ArrayList<Column> getRowsQuery() {
|
||||
ArrayList<Column> result = new ArrayList<>();
|
||||
String sqlStr = "SELECT uuid FROM " + getName() + ";";
|
||||
String sqlStr = "SELECT " + qi("uuid") + " FROM " + qi(getTableName()) + ";";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement sql = conn.prepareStatement(sqlStr)) {
|
||||
ResultSet rs = sql.executeQuery();
|
||||
/*
|
||||
* Query query = new Query(mysql, sql); ResultSet rs = query.executeQuery();
|
||||
*/
|
||||
PreparedStatement ps = conn.prepareStatement(sqlStr);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
|
||||
while (rs.next()) {
|
||||
Column rCol = new Column("uuid", new DataValueString(rs.getString("uuid")));
|
||||
result.add(rCol);
|
||||
result.add(new Column("uuid", new DataValueString(rs.getString(1))));
|
||||
}
|
||||
rs.close();
|
||||
} catch (SQLException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -338,212 +204,281 @@ public abstract class ProxyMysqlUserTable {
|
||||
|
||||
public ConcurrentHashMap<UUID, String> getRowsUUIDNameQuery() {
|
||||
ConcurrentHashMap<UUID, String> uuidNames = new ConcurrentHashMap<>();
|
||||
String sqlStr = "SELECT UUID, PlayerName FROM " + getName() + ";";
|
||||
|
||||
checkColumn("PlayerName", DataType.STRING);
|
||||
|
||||
String sqlStr = "SELECT " + qi("uuid") + ", " + qi("PlayerName") + " FROM " + qi(getTableName()) + ";";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement sql = conn.prepareStatement(sqlStr)) {
|
||||
ResultSet rs = sql.executeQuery();
|
||||
/*
|
||||
* Query query = new Query(mysql, sql); ResultSet rs = query.executeQuery();
|
||||
*/
|
||||
PreparedStatement ps = conn.prepareStatement(sqlStr);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
|
||||
while (rs.next()) {
|
||||
String uuid = rs.getString("uuid");
|
||||
String playerName = rs.getString("PlayerName");
|
||||
if (uuid != null && !uuid.isEmpty() && !uuid.equals("null") && playerName != null) {
|
||||
uuidNames.put(UUID.fromString(uuid), playerName);
|
||||
String uuidStr = rs.getString(1);
|
||||
String playerName = rs.getString(2);
|
||||
|
||||
if (uuidStr != null && !uuidStr.isEmpty() && !"null".equalsIgnoreCase(uuidStr) && playerName != null) {
|
||||
try {
|
||||
uuidNames.put(UUID.fromString(uuidStr), playerName);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
sql.close();
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
} catch (SQLException ignored) {
|
||||
}
|
||||
|
||||
return uuidNames;
|
||||
}
|
||||
|
||||
public String getUUID(String playerName) {
|
||||
String query = "SELECT uuid FROM " + getName() + " WHERE " + "PlayerName" + "='" + playerName + "';";
|
||||
checkColumn("PlayerName", DataType.STRING);
|
||||
|
||||
String query = "SELECT " + qi("uuid") + " FROM " + qi(getTableName()) + " WHERE " + qi("PlayerName") + " = ?;";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement sql = conn.prepareStatement(query)) {
|
||||
ResultSet rs = sql.executeQuery();
|
||||
/*
|
||||
* Query sql = new Query(mysql, query); ResultSet rs = sql.executeQuery();
|
||||
*/
|
||||
if (rs.next()) {
|
||||
String uuid = rs.getString("uuid");
|
||||
if (uuid != null && !uuid.isEmpty()) {
|
||||
rs.close();
|
||||
return uuid;
|
||||
PreparedStatement ps = conn.prepareStatement(query)) {
|
||||
|
||||
ps.setString(1, playerName);
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
String uuid = rs.getString(1);
|
||||
if (uuid != null && !uuid.isEmpty()) {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
debug(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<String> getUuids() {
|
||||
if (uuids == null || uuids.size() == 0) {
|
||||
uuids.clear();
|
||||
uuids.addAll(getUuidsQuery());
|
||||
return uuids;
|
||||
}
|
||||
return uuids;
|
||||
}
|
||||
public ArrayList<Column> getExactQuery(Column column) {
|
||||
ArrayList<Column> result = new ArrayList<>();
|
||||
|
||||
public ArrayList<String> getUuidsQuery() {
|
||||
ArrayList<String> uuids = new ArrayList<>();
|
||||
String query = "SELECT * FROM " + qi(getTableName()) + " WHERE " + qi(column.getName()) + " = ?;";
|
||||
|
||||
ArrayList<Column> rows = getRowsQuery();
|
||||
for (Column c : rows) {
|
||||
if (c.getValue().isString()) {
|
||||
uuids.add(c.getValue().getString());
|
||||
}
|
||||
}
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(query)) {
|
||||
|
||||
return uuids;
|
||||
}
|
||||
|
||||
public void insert(String index, String column, DataValue value) {
|
||||
insertQuery(index, Arrays.asList(new Column(column, value)));
|
||||
}
|
||||
|
||||
public void insertQuery(String index, List<Column> cols) {
|
||||
String query = "INSERT IGNORE " + getName() + " ";
|
||||
|
||||
query += "set uuid='" + index + "', ";
|
||||
|
||||
for (int i = 0; i < cols.size(); i++) {
|
||||
Column col = cols.get(i);
|
||||
if (i == cols.size() - 1) {
|
||||
if (col.getValue().isString()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getString() + "';";
|
||||
} else if (col.getValue().isBoolean()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getBoolean() + "';";
|
||||
} else if (col.getValue().isInt()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getInt() + "';";
|
||||
}
|
||||
String v = column.getValue() == null ? null : column.getValue().getString();
|
||||
if (getDbType() == DbType.POSTGRESQL && "uuid".equalsIgnoreCase(column.getName()) && v != null) {
|
||||
ps.setObject(1, UUID.fromString(v));
|
||||
} else {
|
||||
if (col.getValue().isString()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getString() + "', ";
|
||||
} else if (col.getValue().isBoolean()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getBoolean() + "', ";
|
||||
} else if (col.getValue().isInt()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getInt() + "', ";
|
||||
}
|
||||
ps.setString(1, v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
uuids.add(index);
|
||||
new Query(mysql, query).executeUpdateAsync();
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
|
||||
String columnName = rs.getMetaData().getColumnLabel(i);
|
||||
Column rCol;
|
||||
if (intColumns.contains(columnName)) {
|
||||
rCol = new Column(columnName, DataType.INTEGER);
|
||||
rCol.setValue(new DataValueInt(rs.getInt(i)));
|
||||
} else {
|
||||
rCol = new Column(columnName, DataType.STRING);
|
||||
rCol.setValue(new DataValueString(rs.getString(i)));
|
||||
}
|
||||
result.add(rCol);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
debug(e);
|
||||
} catch (ArrayIndexOutOfBoundsException ignored) {
|
||||
}
|
||||
|
||||
for (String col : getColumns()) {
|
||||
result.add(new Column(col, DataType.STRING));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isIntColumn(String key) {
|
||||
return intColumns.contains(key);
|
||||
}
|
||||
|
||||
public void loadData() {
|
||||
columns = getColumnsQueury();
|
||||
// ---- INSERT/UPDATE/WIPE (kept similar to your existing behavior) ----
|
||||
|
||||
public void insert(String index, String column, DataValue value) {
|
||||
insertQuery(index, Arrays.asList(new Column(column, value)));
|
||||
}
|
||||
|
||||
public abstract void severe(String str);
|
||||
public void insertQuery(String index, List<Column> cols) {
|
||||
for (Column c : cols) {
|
||||
checkColumn(c.getName(), c.getDataType());
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
mysql.disconnect();
|
||||
// Keep your previous cross-db behavior:
|
||||
// - Postgres: ON CONFLICT upsert
|
||||
// - MySQL/MariaDB: INSERT IGNORE ... SET ...
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("INSERT INTO ").append(qi(getTableName())).append(" (").append(qi("uuid"));
|
||||
|
||||
for (Column col : cols) {
|
||||
sb.append(", ").append(qi(col.getName()));
|
||||
}
|
||||
sb.append(") VALUES (?");
|
||||
|
||||
for (int i = 0; i < cols.size(); i++) {
|
||||
sb.append(", ?");
|
||||
}
|
||||
sb.append(") ON CONFLICT (").append(qi("uuid")).append(") DO UPDATE SET ");
|
||||
|
||||
for (int i = 0; i < cols.size(); i++) {
|
||||
Column col = cols.get(i);
|
||||
String c = qi(col.getName());
|
||||
sb.append(c).append(" = EXCLUDED.").append(c);
|
||||
if (i != cols.size() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(";");
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sb.toString())) {
|
||||
|
||||
ps.setObject(1, UUID.fromString(index));
|
||||
int p = 2;
|
||||
for (Column col : cols) {
|
||||
ps.setString(p++, col.getValue().toString());
|
||||
}
|
||||
ps.executeUpdate();
|
||||
uuidsView.add(index);
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder query = new StringBuilder();
|
||||
query.append("INSERT IGNORE ").append(qi(getTableName())).append(" SET ").append(qi("uuid")).append("=?, ");
|
||||
|
||||
for (int i = 0; i < cols.size(); i++) {
|
||||
Column col = cols.get(i);
|
||||
query.append(qi(col.getName())).append("=?");
|
||||
query.append(i == cols.size() - 1 ? ";" : ", ");
|
||||
}
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(query.toString())) {
|
||||
|
||||
ps.setString(1, index);
|
||||
int p = 2;
|
||||
for (Column col : cols) {
|
||||
ps.setString(p++, col.getValue().toString());
|
||||
}
|
||||
ps.executeUpdate();
|
||||
uuidsView.add(index);
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(String index, List<Column> cols) {
|
||||
for (Column col : cols) {
|
||||
checkColumn(col.getName(), col.getDataType());
|
||||
}
|
||||
if (getUuids().contains(index)) {
|
||||
synchronized (object2) {
|
||||
|
||||
String query = "UPDATE " + getName() + " SET ";
|
||||
// keep old behavior: if missing, insert
|
||||
if (!getUuids().contains(index) && !containsKeyQuery(index)) {
|
||||
insertQuery(index, cols);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cols.size(); i++) {
|
||||
Column col = cols.get(i);
|
||||
if (i == cols.size() - 1) {
|
||||
if (col.getValue().isString()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getString() + "'";
|
||||
} else if (col.getValue().isBoolean()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getBoolean() + "'";
|
||||
} else if (col.getValue().isInt()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getInt() + "'";
|
||||
}
|
||||
} else {
|
||||
if (col.getValue().isString()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getString() + "', ";
|
||||
} else if (col.getValue().isBoolean()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getBoolean() + "', ";
|
||||
} else if (col.getValue().isInt()) {
|
||||
query += "`" + col.getName() + "`='" + col.getValue().getInt() + "', ";
|
||||
}
|
||||
}
|
||||
}
|
||||
query += " WHERE `uuid`=";
|
||||
query += "'" + index + "';";
|
||||
synchronized (updateLock) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("UPDATE ").append(qi(getTableName())).append(" SET ");
|
||||
|
||||
try {
|
||||
Query q = new Query(mysql, query);
|
||||
q.executeUpdateAsync();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
for (int i = 0; i < cols.size(); i++) {
|
||||
Column col = cols.get(i);
|
||||
sb.append(qi(col.getName())).append("=?");
|
||||
if (i != cols.size() - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
insertQuery(index, cols);
|
||||
|
||||
sb.append(" WHERE ").append(qi("uuid")).append("=?;");
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sb.toString())) {
|
||||
|
||||
int p = 1;
|
||||
for (Column col : cols) {
|
||||
bindValue(ps, p++, col);
|
||||
}
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(p, UUID.fromString(index));
|
||||
} else {
|
||||
ps.setString(p, index);
|
||||
}
|
||||
|
||||
int updated = ps.executeUpdate();
|
||||
if (updated == 0) {
|
||||
// row missing (wiped) even though uuid cache thought it existed
|
||||
insertQuery(index, cols);
|
||||
}
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bindValue(PreparedStatement ps, int index, Column col) throws SQLException {
|
||||
DataValue v = col.getValue();
|
||||
if (getDbType() == DbType.POSTGRESQL && v != null && v.isInt()) {
|
||||
ps.setInt(index, v.getInt());
|
||||
return;
|
||||
}
|
||||
ps.setString(index, v == null ? null : v.toString());
|
||||
}
|
||||
|
||||
public void update(String index, String column, DataValue value) {
|
||||
checkColumn(column, value.getType());
|
||||
if (getUuids().contains(index)) {
|
||||
synchronized (object2) {
|
||||
String query = "UPDATE " + getName() + " SET ";
|
||||
|
||||
if (value.isString()) {
|
||||
query += column + "='" + value.getString() + "'";
|
||||
} else if (value.isBoolean()) {
|
||||
query += column + "='" + value.getBoolean() + "'";
|
||||
} else if (value.isInt()) {
|
||||
query += column + "='" + value.getInt() + "'";
|
||||
}
|
||||
query += " WHERE `uuid`=";
|
||||
query += "'" + index + "';";
|
||||
|
||||
try {
|
||||
Query q = new Query(mysql, query);
|
||||
q.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!getUuids().contains(index) && !containsKeyQuery(index)) {
|
||||
insert(index, column, value);
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (updateLock) {
|
||||
String sql = "UPDATE " + qi(getTableName()) + " SET " + qi(column) + "=? WHERE " + qi("uuid") + "=?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL && value != null && value.isInt()) {
|
||||
ps.setInt(1, value.getInt());
|
||||
} else {
|
||||
ps.setString(1, value == null ? null : value.toString());
|
||||
}
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(2, UUID.fromString(index));
|
||||
} else {
|
||||
ps.setString(2, index);
|
||||
}
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void wipeColumnData(String columnName, DataType dataType) {
|
||||
checkColumn(columnName, dataType);
|
||||
String sql = "UPDATE " + getName() + " SET " + columnName + " = " + dataType.getNoValue() + ";";
|
||||
try {
|
||||
Query query = new Query(mysql, sql);
|
||||
query.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String sql = "UPDATE " + qi(getTableName()) + " SET " + qi(columnName) + " = " + dataType.getNoValue() + ";";
|
||||
try {
|
||||
new Query(mysql, sql).executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class VoteTotalsSnapshot {
|
||||
|
||||
private static final String SEP = "//";
|
||||
private static final Pattern SEP_PATTERN = Pattern.compile(Pattern.quote(SEP));
|
||||
|
||||
// Current storage version
|
||||
private static final int CURRENT_VERSION = 2;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int allTimeTotal;
|
||||
@Getter
|
||||
@Setter
|
||||
private int monthTotal;
|
||||
@Getter
|
||||
@Setter
|
||||
private int weeklyTotal;
|
||||
@Getter
|
||||
@Setter
|
||||
private int dailyTotal;
|
||||
@Getter
|
||||
@Setter
|
||||
private int points;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int votePartyCurrent;
|
||||
@Getter
|
||||
@Setter
|
||||
private int votePartyRequired;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int dateMonthTotal;
|
||||
@Getter
|
||||
@Setter
|
||||
private UUID voteUUID;
|
||||
|
||||
public VoteTotalsSnapshot() {
|
||||
}
|
||||
|
||||
public VoteTotalsSnapshot(int allTimeTotal, int monthTotal, int weeklyTotal, int dailyTotal, int points,
|
||||
int votePartyCurrent, int votePartyRequired, int dateMonthTotal, UUID voteUUID) {
|
||||
this.allTimeTotal = allTimeTotal;
|
||||
this.monthTotal = monthTotal;
|
||||
this.weeklyTotal = weeklyTotal;
|
||||
this.dailyTotal = dailyTotal;
|
||||
this.points = points;
|
||||
this.votePartyCurrent = votePartyCurrent;
|
||||
this.votePartyRequired = votePartyRequired;
|
||||
this.dateMonthTotal = dateMonthTotal;
|
||||
this.voteUUID = voteUUID;
|
||||
}
|
||||
|
||||
public static VoteTotalsSnapshot parseStorage(String raw) {
|
||||
VoteTotalsSnapshot out = new VoteTotalsSnapshot();
|
||||
if (raw == null || raw.isEmpty()) {
|
||||
return out;
|
||||
}
|
||||
|
||||
String[] t = SEP_PATTERN.split(raw, -1);
|
||||
if (t.length < 5) {
|
||||
return out;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
int version = 1; // legacy default
|
||||
|
||||
// Versioned?
|
||||
if (t[0].startsWith("v")) {
|
||||
version = parseInt(t[0].substring(1), 1);
|
||||
idx = 1;
|
||||
}
|
||||
|
||||
switch (version) {
|
||||
case 1:
|
||||
parseV1(out, t, idx);
|
||||
break;
|
||||
case 2:
|
||||
parseV2(out, t, idx);
|
||||
break;
|
||||
default:
|
||||
// Unknown future version → best-effort using v2 layout
|
||||
parseV2(out, t, idx);
|
||||
break;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* ========================= Writers (always v2) =========================
|
||||
*/
|
||||
|
||||
public String toStorageString() {
|
||||
return "v" + CURRENT_VERSION + SEP + allTimeTotal + SEP + monthTotal + SEP + weeklyTotal + SEP + dailyTotal
|
||||
+ SEP + points + SEP + votePartyCurrent + SEP + votePartyRequired + SEP + dateMonthTotal + SEP
|
||||
+ (voteUUID != null ? voteUUID.toString() : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStorageString();
|
||||
}
|
||||
|
||||
// Legacy (milestoneCount exists, but ignored)
|
||||
private static void parseV1(VoteTotalsSnapshot out, String[] t, int i) {
|
||||
out.allTimeTotal = parseInt(t, i++, 0);
|
||||
out.monthTotal = parseInt(t, i++, 0);
|
||||
out.weeklyTotal = parseInt(t, i++, 0);
|
||||
out.dailyTotal = parseInt(t, i++, 0);
|
||||
out.points = parseInt(t, i++, 0);
|
||||
|
||||
i++; // skip milestoneCount
|
||||
|
||||
out.votePartyCurrent = parseInt(t, i++, 0);
|
||||
out.votePartyRequired = parseInt(t, i++, 0);
|
||||
out.dateMonthTotal = parseInt(t, i++, 0);
|
||||
out.voteUUID = parseUUID(t, i);
|
||||
}
|
||||
|
||||
// Current (no milestoneCount)
|
||||
private static void parseV2(VoteTotalsSnapshot out, String[] t, int i) {
|
||||
out.allTimeTotal = parseInt(t, i++, 0);
|
||||
out.monthTotal = parseInt(t, i++, 0);
|
||||
out.weeklyTotal = parseInt(t, i++, 0);
|
||||
out.dailyTotal = parseInt(t, i++, 0);
|
||||
out.points = parseInt(t, i++, 0);
|
||||
|
||||
out.votePartyCurrent = parseInt(t, i++, 0);
|
||||
out.votePartyRequired = parseInt(t, i++, 0);
|
||||
out.dateMonthTotal = parseInt(t, i++, 0);
|
||||
out.voteUUID = parseUUID(t, i);
|
||||
}
|
||||
|
||||
/*
|
||||
* ========================= Helpers =========================
|
||||
*/
|
||||
|
||||
private static int parseInt(String[] t, int idx, int def) {
|
||||
if (idx < 0 || idx >= t.length)
|
||||
return def;
|
||||
try {
|
||||
return Integer.parseInt(t[idx].trim());
|
||||
} catch (Exception e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
private static int parseInt(String s, int def) {
|
||||
try {
|
||||
return Integer.parseInt(s);
|
||||
} catch (Exception e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
private static UUID parseUUID(String[] t, int idx) {
|
||||
if (idx < 0 || idx >= t.length)
|
||||
return null;
|
||||
String s = t[idx].trim();
|
||||
if (s.isEmpty() || "null".equalsIgnoreCase(s))
|
||||
return null;
|
||||
try {
|
||||
return UUID.fromString(s);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+766
-369
File diff suppressed because it is too large.
Load diff
+7
-19
@@ -22,11 +22,11 @@ public class VotingPluginProxyCommand {
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "reload":
|
||||
plugin.reloadCore(false);
|
||||
return "&aReloading VotingPlugin";
|
||||
return "&aReloading VotingPluginProxy (basic settings)";
|
||||
|
||||
case "reloadmysql":
|
||||
case "reloadall":
|
||||
plugin.reloadCore(true);
|
||||
return "&aReloading VotingPlugin including MySQL";
|
||||
return "&aReloading VotingPluginProxy (full reload incl. MySQL/GlobalData)";
|
||||
|
||||
case "vote":
|
||||
if (args.length >= 3) {
|
||||
@@ -48,7 +48,7 @@ public class VotingPluginProxyCommand {
|
||||
return handleStatusCommand();
|
||||
|
||||
case "multiproxystatus":
|
||||
plugin.getMultiProxyHandler().sendMultiProxyServerMessage("Status");
|
||||
plugin.getMultiProxyHandler().sendStatus();
|
||||
return "&aSent status message across multi-proxy";
|
||||
|
||||
case "help":
|
||||
@@ -64,21 +64,9 @@ public class VotingPluginProxyCommand {
|
||||
|
||||
private String handleStatusCommand() {
|
||||
BungeeMethod method = plugin.getMethod();
|
||||
switch (method) {
|
||||
case SOCKETS:
|
||||
plugin.status();
|
||||
return "&aChecking status via sockets. Check console for details.";
|
||||
|
||||
case PLUGINMESSAGING:
|
||||
case MYSQL:
|
||||
case REDIS:
|
||||
plugin.status();
|
||||
plugin.sendServerNameMessage();
|
||||
return "&aChecking status with method: " + method.toString().toLowerCase();
|
||||
|
||||
default:
|
||||
return "&cStatus command unavailable for the current connection method.";
|
||||
}
|
||||
plugin.status();
|
||||
plugin.sendServerNameMessage();
|
||||
return "&aChecking status with method: " + method.toString().toLowerCase();
|
||||
}
|
||||
|
||||
private String handleVotePartyCommand(String[] args) {
|
||||
|
||||
+62
-4
@@ -1,19 +1,57 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface VotingPluginProxyConfig {
|
||||
|
||||
default boolean getProxyBroadcastEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing scope mode.
|
||||
*
|
||||
* Expected values: PLAYER_SERVER | ALL_SERVERS | SERVERS | ALL_EXCEPT
|
||||
*/
|
||||
default String getProxyBroadcastScopeMode() {
|
||||
return "ALL_SERVERS";
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional server list used by scope modes SERVERS and ALL_EXCEPT.
|
||||
*/
|
||||
default List<String> getProxyBroadcastScopeServers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* What to do when the voting player is offline and scope is PLAYER_SERVER.
|
||||
*
|
||||
* Expected values: NONE | QUEUE | FORWARD
|
||||
*/
|
||||
default String getProxyBroadcastOfflineMode() {
|
||||
return "QUEUE";
|
||||
}
|
||||
|
||||
/**
|
||||
* Backend server list used when OfflineMode is FORWARD and Scope.Mode is
|
||||
* PLAYER_SERVER.
|
||||
*
|
||||
* Ignored when Scope.Mode is ALL_SERVERS or ALL_EXCEPT.
|
||||
*/
|
||||
default List<String> getProxyBroadcastOfflineForwardServers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public boolean getAllowUnJoined();
|
||||
|
||||
public String getBedrockPlayerPrefix();
|
||||
|
||||
public List<String> getBlockedServers();
|
||||
|
||||
public boolean getBroadcast();
|
||||
|
||||
public String getBungeeHost();
|
||||
|
||||
public boolean getBungeeManageTotals();
|
||||
@@ -28,6 +66,14 @@ public interface VotingPluginProxyConfig {
|
||||
|
||||
public boolean getDebug();
|
||||
|
||||
public boolean getVoteCacheUseMySQL();
|
||||
|
||||
public boolean getVoteCacheUseMainMySQL();
|
||||
|
||||
public boolean getNonVotedCacheUseMySQL();
|
||||
|
||||
public boolean getNonVotedCacheUseMainMySQL();
|
||||
|
||||
public String getMqttClientID();
|
||||
|
||||
public String getMqttBrokerURL();
|
||||
@@ -88,6 +134,8 @@ public interface VotingPluginProxyConfig {
|
||||
|
||||
public int getRedisPort();
|
||||
|
||||
public int getRedisDbIndex();
|
||||
|
||||
public String getRedisPrefix();
|
||||
|
||||
public String getRedisUsername();
|
||||
@@ -104,6 +152,8 @@ public interface VotingPluginProxyConfig {
|
||||
|
||||
public int getTimeHourOffSet();
|
||||
|
||||
public int getTimeWeekOffSet();
|
||||
|
||||
public String getTimeZone();
|
||||
|
||||
public boolean getUseMonthDateTotalsAsPrimaryTotal();
|
||||
@@ -137,8 +187,6 @@ public interface VotingPluginProxyConfig {
|
||||
public int getWaitUntilVoteDelayVoteDelay(String site);
|
||||
|
||||
public int getWaitUntilVoteDelayVoteDelayMin(String site);
|
||||
|
||||
public boolean getResetMilestonesMonthly();
|
||||
|
||||
public int getWaitUntilVoteDelayVoteDelayHour(String site);
|
||||
|
||||
@@ -148,4 +196,14 @@ public interface VotingPluginProxyConfig {
|
||||
|
||||
public void save();
|
||||
|
||||
public boolean getVoteLoggingEnabled();
|
||||
|
||||
public int getVoteLoggingPurgeDays();
|
||||
|
||||
public boolean getVoteLoggingUseMainMySQL();
|
||||
|
||||
public boolean hasDatabaseConfigured();
|
||||
|
||||
public int getMultiProxyRedisDbIndex();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
// File: com/bencodez/votingplugin/proxy/VotingPluginWire.java
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope;
|
||||
|
||||
/**
|
||||
* Canonical wire format for proxy - backend messages.
|
||||
*
|
||||
* Rules: - Only JsonEnvelope is sent over the wire (no legacy String[] /
|
||||
* delimiters). - All fields are named keys (no numeric indices). - Versioning
|
||||
* uses the JsonEnvelope schema as the source of truth. - A "bungeeVersion"
|
||||
* field is also included for legacy compatibility checks. - Values are written
|
||||
* as native types where possible, but readers tolerate Strings.
|
||||
*
|
||||
* Note: Some keys are public because other classes (e.g. MultiProxyHandler)
|
||||
* reference them directly.
|
||||
*/
|
||||
public final class VotingPluginWire {
|
||||
|
||||
private VotingPluginWire() {
|
||||
}
|
||||
|
||||
public static final int SCHEMA_VERSION = 1;
|
||||
|
||||
// =========================
|
||||
// Subchannels (canonical)
|
||||
// =========================
|
||||
public static final String SUB_VOTE = "Vote";
|
||||
public static final String SUB_VOTE_ONLINE = "VoteOnline";
|
||||
public static final String SUB_VOTE_UPDATE = "VoteUpdate";
|
||||
public static final String SUB_VOTE_BROADCAST = "VoteBroadcast";
|
||||
public static final String SUB_BUNGEE_TIME_CHANGE = "BungeeTimeChange";
|
||||
|
||||
public static final String SUB_STATUS = "Status";
|
||||
public static final String SUB_STATUS_OKAY = "statusokay";
|
||||
public static final String SUB_SERVER_NAME = "ServerName";
|
||||
|
||||
public static final String SUB_VOTE_PARTY = "VotePartyBungee";
|
||||
|
||||
public static final String SUB_LOGIN = "login";
|
||||
public static final String SUB_VOTEUPDATE_RELAY = "voteupdate";
|
||||
|
||||
// =========================
|
||||
// Multi-proxy subchannels (REQUIRED by MultiProxyHandler)
|
||||
// =========================
|
||||
public static final String SUB_CLEAR_VOTE = "ClearVote";
|
||||
public static final String SUB_CLEAR_VOTE_PRIMARY = "ClearVotePrimary";
|
||||
|
||||
// =========================
|
||||
// Field keys (public where referenced externally)
|
||||
// =========================
|
||||
public static final String K_VERSION = "version";
|
||||
|
||||
public static final String K_PLAYER = "player";
|
||||
public static final String K_UUID = "uuid";
|
||||
public static final String K_SERVER = "server";
|
||||
public static final String K_SERVICE = "service";
|
||||
public static final String K_TIME = "time";
|
||||
|
||||
// Vote/VoteOnline extras
|
||||
public static final String K_WAS_ONLINE = "wasOnline";
|
||||
public static final String K_REAL_VOTE = "realVote";
|
||||
public static final String K_TOTALS = "totals";
|
||||
public static final String K_SET_TOTALS = "setTotals";
|
||||
public static final String K_MANAGE_TOTALS = "manageTotals";
|
||||
public static final String K_BUNGEE_BROADCAST = "bungeeBroadcast";
|
||||
public static final String K_NUM = "num";
|
||||
public static final String K_NUMBER_OF_VOTES = "numberOfVotes";
|
||||
|
||||
// VoteUpdate extras
|
||||
public static final String K_PLAYER_UUID = "playerUuid";
|
||||
public static final String K_VOTE_PARTY_CURRENT = "votePartyCurrent";
|
||||
public static final String K_VOTE_PARTY_REQUIRED = "votePartyRequired";
|
||||
public static final String K_LAST_VOTE_TIME = "lastVoteTime";
|
||||
|
||||
// =========================
|
||||
// Builders
|
||||
// =========================
|
||||
|
||||
public static JsonEnvelope bungeeTimeChange() {
|
||||
return base(SUB_BUNGEE_TIME_CHANGE).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope vote(String player, String uuid, String service, long time, boolean wasOnline,
|
||||
boolean realVote, String totals, boolean manageTotals, boolean bungeeBroadcast, int num,
|
||||
int numberOfVotes) {
|
||||
|
||||
return base(SUB_VOTE).put(K_PLAYER, safe(player)).put(K_UUID, safe(uuid)).put(K_SERVICE, safe(service))
|
||||
.put(K_TIME, time).put(K_WAS_ONLINE, wasOnline).put(K_REAL_VOTE, realVote).put(K_TOTALS, safe(totals))
|
||||
.put(K_SET_TOTALS, true) // backend historically defaulted to true
|
||||
.put(K_MANAGE_TOTALS, manageTotals).put(K_BUNGEE_BROADCAST, bungeeBroadcast).put(K_NUM, num)
|
||||
.put(K_NUMBER_OF_VOTES, numberOfVotes).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope voteOnline(String player, String uuid, String service, long time, boolean wasOnline,
|
||||
boolean realVote, String totals, boolean manageTotals, boolean bungeeBroadcast, int num,
|
||||
int numberOfVotes) {
|
||||
|
||||
return base(SUB_VOTE_ONLINE).put(K_PLAYER, safe(player)).put(K_UUID, safe(uuid)).put(K_SERVICE, safe(service))
|
||||
.put(K_TIME, time).put(K_WAS_ONLINE, wasOnline).put(K_REAL_VOTE, realVote).put(K_TOTALS, safe(totals))
|
||||
.put(K_SET_TOTALS, true).put(K_MANAGE_TOTALS, manageTotals).put(K_BUNGEE_BROADCAST, bungeeBroadcast)
|
||||
.put(K_NUM, num).put(K_NUMBER_OF_VOTES, numberOfVotes).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope voteBroadcast(String uuid, String player, String service, long time, String totals) {
|
||||
return base(SUB_VOTE_BROADCAST).put(K_UUID, safe(uuid)).put(K_PLAYER, safe(player))
|
||||
.put(K_SERVICE, safe(service)).put(K_TIME, time).put(K_TOTALS, safe(totals)).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope voteUpdate(String playerUuid, int votePartyCurrent, int votePartyRequired,
|
||||
String service, long lastVoteTime, String totals) {
|
||||
|
||||
final String u = safe(playerUuid);
|
||||
return base(SUB_VOTE_UPDATE).put(K_PLAYER_UUID, u).put(K_PLAYER, u) // legacy fallback key used by older
|
||||
// handlers
|
||||
.put(K_VOTE_PARTY_CURRENT, votePartyCurrent).put(K_VOTE_PARTY_REQUIRED, votePartyRequired)
|
||||
.put(K_SERVICE, safe(service)).put(K_LAST_VOTE_TIME, lastVoteTime).put(K_TOTALS, safe(totals)).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope votePartyBungee() {
|
||||
return base(SUB_VOTE_PARTY).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope status(String server) {
|
||||
return base(SUB_STATUS).put(K_SERVER, safe(server)).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope statusOkay(String server) {
|
||||
return base(SUB_STATUS_OKAY).put(K_SERVER, safe(server)).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope serverName(String server) {
|
||||
return base(SUB_SERVER_NAME).put(K_SERVER, safe(server)).build();
|
||||
}
|
||||
|
||||
public static JsonEnvelope login(String player, String uuid, String server) {
|
||||
return base(SUB_LOGIN).put(K_PLAYER, safe(player)).put(K_UUID, safe(uuid)).put(K_SERVER, safe(server)).build();
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Multi-proxy builders (REQUIRED by MultiProxyHandler)
|
||||
// =========================
|
||||
|
||||
/**
|
||||
* Sent by non-primary servers to ask the primary to clear vote state. Primary
|
||||
* responds by broadcasting ClearVotePrimary.
|
||||
*/
|
||||
public static JsonEnvelope clearVote(String uuid, String player, String server) {
|
||||
return base(SUB_CLEAR_VOTE).put(K_UUID, safe(uuid)).put(K_PLAYER, safe(player)).put(K_SERVER, safe(server))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast by the primary server so all proxies clear vote state.
|
||||
*/
|
||||
public static JsonEnvelope clearVotePrimary(String uuid, String player, String server) {
|
||||
return base(SUB_CLEAR_VOTE_PRIMARY).put(K_UUID, safe(uuid)).put(K_PLAYER, safe(player))
|
||||
.put(K_SERVER, safe(server)).build();
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Readers (decode)
|
||||
// =========================
|
||||
|
||||
public static final class Vote {
|
||||
public final String subChannel;
|
||||
public final String player;
|
||||
public final String uuid;
|
||||
public final String service;
|
||||
public final long time;
|
||||
|
||||
public final boolean wasOnline;
|
||||
public final boolean realVote;
|
||||
public final String totals;
|
||||
|
||||
public final boolean setTotals;
|
||||
public final boolean manageTotals;
|
||||
public final boolean broadcast; // historically bungeeBroadcast
|
||||
public final int num;
|
||||
public final int numberOfVotes;
|
||||
|
||||
private Vote(String subChannel, String player, String uuid, String service, long time, boolean wasOnline,
|
||||
boolean realVote, String totals, boolean setTotals, boolean manageTotals, boolean broadcast, int num,
|
||||
int numberOfVotes) {
|
||||
this.subChannel = subChannel;
|
||||
this.player = player;
|
||||
this.uuid = uuid;
|
||||
this.service = service;
|
||||
this.time = time;
|
||||
this.wasOnline = wasOnline;
|
||||
this.realVote = realVote;
|
||||
this.totals = totals;
|
||||
this.setTotals = setTotals;
|
||||
this.manageTotals = manageTotals;
|
||||
this.broadcast = broadcast;
|
||||
this.num = num;
|
||||
this.numberOfVotes = numberOfVotes;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vote readVote(JsonEnvelope env) {
|
||||
Map<String, String> f = env.getFields();
|
||||
|
||||
final String sub = safe(env.getSubChannel());
|
||||
final String player = safe(f.get(K_PLAYER));
|
||||
final String uuid = safe(f.get(K_UUID));
|
||||
final String service = safe(f.get(K_SERVICE));
|
||||
final long time = readLong(f, K_TIME, 0L);
|
||||
|
||||
final boolean wasOnline = readBool(f, K_WAS_ONLINE, false);
|
||||
final boolean realVote = readBool(f, K_REAL_VOTE, false);
|
||||
final String totals = safe(f.get(K_TOTALS));
|
||||
|
||||
final boolean setTotals = readBool(f, K_SET_TOTALS, true);
|
||||
final boolean manageTotals = readBool(f, K_MANAGE_TOTALS, false);
|
||||
|
||||
final boolean broadcast = readBool(f, K_BUNGEE_BROADCAST, false);
|
||||
|
||||
final int num = readInt(f, K_NUM, 1);
|
||||
final int numberOfVotes = readInt(f, K_NUMBER_OF_VOTES, 1);
|
||||
|
||||
return new Vote(sub, player, uuid, service, time, wasOnline, realVote, totals, setTotals, manageTotals,
|
||||
broadcast, num, numberOfVotes);
|
||||
}
|
||||
|
||||
public static final class VoteUpdate {
|
||||
public final String uuid;
|
||||
public final int votePartyCurrent;
|
||||
public final int votePartyRequired;
|
||||
public final String service;
|
||||
public final long time; // lastVoteTime
|
||||
|
||||
private VoteUpdate(String uuid, int votePartyCurrent, int votePartyRequired, String service, long time) {
|
||||
this.uuid = uuid;
|
||||
this.votePartyCurrent = votePartyCurrent;
|
||||
this.votePartyRequired = votePartyRequired;
|
||||
this.service = service;
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
|
||||
public static VoteUpdate readVoteUpdate(JsonEnvelope env) {
|
||||
Map<String, String> f = env.getFields();
|
||||
|
||||
String uuid = safe(f.get(K_PLAYER_UUID));
|
||||
if (uuid.isEmpty()) {
|
||||
uuid = safe(f.get(K_PLAYER));
|
||||
}
|
||||
|
||||
int cur = readInt(f, K_VOTE_PARTY_CURRENT, 0);
|
||||
int req = readInt(f, K_VOTE_PARTY_REQUIRED, 0);
|
||||
String service = safe(f.get(K_SERVICE));
|
||||
|
||||
long t = readLong(f, K_LAST_VOTE_TIME, 0L);
|
||||
if (t == 0L) {
|
||||
t = readLong(f, K_TIME, 0L);
|
||||
}
|
||||
|
||||
return new VoteUpdate(uuid, cur, req, service, t);
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Internals
|
||||
// =========================
|
||||
|
||||
private static JsonEnvelope.Builder base(String subChannel) {
|
||||
int ver = SCHEMA_VERSION;
|
||||
return JsonEnvelope.builder(subChannel).schema(ver);
|
||||
}
|
||||
|
||||
private static String safe(String s) {
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
|
||||
private static boolean readBool(Map<String, String> f, String key, boolean def) {
|
||||
String v = f.get(key);
|
||||
if (v == null) {
|
||||
return def;
|
||||
}
|
||||
return Boolean.parseBoolean(v);
|
||||
}
|
||||
|
||||
private static int readInt(Map<String, String> f, String key, int def) {
|
||||
String v = f.get(key);
|
||||
if (v == null) {
|
||||
return def;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(v);
|
||||
} catch (Exception ignored) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
private static long readLong(Map<String, String> f, String key, long def) {
|
||||
String v = f.get(key);
|
||||
if (v == null) {
|
||||
return def;
|
||||
}
|
||||
try {
|
||||
return Long.parseLong(v);
|
||||
} catch (Exception ignored) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.bencodez.votingplugin.proxy.broadcast;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum OfflineMode {
|
||||
NONE, QUEUE, FORWARD;
|
||||
|
||||
public static OfflineMode parse(String value, OfflineMode def) {
|
||||
if (value == null)
|
||||
return def;
|
||||
String v = value.trim();
|
||||
if (v.isEmpty())
|
||||
return def;
|
||||
try {
|
||||
return OfflineMode.valueOf(v.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
package com.bencodez.votingplugin.proxy.broadcast;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.bencodez.votingplugin.proxy.VotingPluginProxyConfig;
|
||||
|
||||
/**
|
||||
* Decides where vote broadcasts should execute (proxy-side routing only).
|
||||
*
|
||||
* Backend servers still decide WHAT to broadcast (VoteBroadcast.Type/Format).
|
||||
*
|
||||
* QUEUE behavior:
|
||||
* - This class returns no immediate targets when player is offline and OfflineMode=QUEUE.
|
||||
* - The "queue" is the existing online vote cache (addOnlineVote + checkOnlineVotes on login).
|
||||
*/
|
||||
public final class ProxyBroadcastDecider {
|
||||
|
||||
private final Supplier<VotingPluginProxyConfig> config;
|
||||
private final Supplier<Set<String>> allServers;
|
||||
private final Predicate<String> isServerValid;
|
||||
private final Predicate<String> isBlockedServer;
|
||||
|
||||
public ProxyBroadcastDecider(Supplier<VotingPluginProxyConfig> config,
|
||||
Supplier<Set<String>> allServers,
|
||||
Predicate<String> isServerValid,
|
||||
Predicate<String> isBlockedServer) {
|
||||
this.config = config;
|
||||
this.allServers = allServers;
|
||||
this.isServerValid = isServerValid;
|
||||
this.isBlockedServer = isBlockedServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute which backend servers should broadcast for this vote.
|
||||
*
|
||||
* @param playerOnline whether the voting player is currently online
|
||||
* @param currentPlayerServer the server the player is on (only used when playerOnline=true)
|
||||
*/
|
||||
public Set<String> resolveTargets(boolean playerOnline, String currentPlayerServer) {
|
||||
VotingPluginProxyConfig cfg = config.get();
|
||||
if (cfg == null || !cfg.getProxyBroadcastEnabled()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
ScopeMode scope = ScopeMode.parse(cfg.getProxyBroadcastScopeMode(), ScopeMode.ALL_SERVERS);
|
||||
List<String> scopeServers = cfg.getProxyBroadcastScopeServers();
|
||||
|
||||
Set<String> eligible = eligibleServers();
|
||||
|
||||
switch (scope) {
|
||||
case ALL_SERVERS:
|
||||
return eligible;
|
||||
|
||||
case SERVERS:
|
||||
return intersect(scopeServers, eligible);
|
||||
|
||||
case ALL_EXCEPT:
|
||||
return subtract(scopeServers, eligible);
|
||||
|
||||
case PLAYER_SERVER:
|
||||
default:
|
||||
if (playerOnline) {
|
||||
if (currentPlayerServer != null && eligible.contains(currentPlayerServer)) {
|
||||
Set<String> out = new LinkedHashSet<>();
|
||||
out.add(currentPlayerServer);
|
||||
return out;
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
// player offline + PLAYER_SERVER scope
|
||||
OfflineMode offlineMode = OfflineMode.parse(cfg.getProxyBroadcastOfflineMode(), OfflineMode.QUEUE);
|
||||
|
||||
if (offlineMode == OfflineMode.FORWARD) {
|
||||
// FORWARD uses OfflineForward.Servers (list only; mode is implicit SERVERS)
|
||||
return intersect(cfg.getProxyBroadcastOfflineForwardServers(), eligible);
|
||||
}
|
||||
|
||||
// NONE or QUEUE => no immediate targets
|
||||
// QUEUE is handled by existing vote cache + checkOnlineVotes() on login
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience check for "should this specific server broadcast?"
|
||||
*/
|
||||
public boolean shouldBroadcast(String server, Set<String> targets) {
|
||||
return targets != null && server != null && targets.contains(server);
|
||||
}
|
||||
|
||||
private Set<String> eligibleServers() {
|
||||
Set<String> out = new LinkedHashSet<>();
|
||||
for (String s : allServers.get()) {
|
||||
if (s == null || s.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!isServerValid.test(s)) {
|
||||
continue;
|
||||
}
|
||||
if (isBlockedServer.test(s)) {
|
||||
continue;
|
||||
}
|
||||
out.add(s);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static Set<String> intersect(List<String> list, Set<String> eligible) {
|
||||
if (list == null || list.isEmpty() || eligible.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<String> out = new LinkedHashSet<>();
|
||||
for (String s : list) {
|
||||
if (s == null) {
|
||||
continue;
|
||||
}
|
||||
String v = s.trim();
|
||||
if (!v.isEmpty() && eligible.contains(v)) {
|
||||
out.add(v);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static Set<String> subtract(List<String> list, Set<String> eligible) {
|
||||
if (eligible.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<String> out = new LinkedHashSet<>(eligible);
|
||||
if (list == null || list.isEmpty()) {
|
||||
return out;
|
||||
}
|
||||
for (String s : list) {
|
||||
if (s == null) {
|
||||
continue;
|
||||
}
|
||||
String v = s.trim();
|
||||
if (!v.isEmpty()) {
|
||||
out.remove(v);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.bencodez.votingplugin.proxy.broadcast;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Proxy-side routing scope for broadcast triggers.
|
||||
*/
|
||||
public enum ScopeMode {
|
||||
/**
|
||||
* Send only to the backend server the player is currently on.
|
||||
*/
|
||||
PLAYER_SERVER,
|
||||
|
||||
/**
|
||||
* Send to all connected backend servers.
|
||||
*/
|
||||
ALL_SERVERS,
|
||||
|
||||
/**
|
||||
* Send only to the configured server list.
|
||||
*/
|
||||
SERVERS,
|
||||
|
||||
/**
|
||||
* Send to all servers except the configured server list.
|
||||
*/
|
||||
ALL_EXCEPT;
|
||||
|
||||
public static ScopeMode parse(String value, ScopeMode def) {
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
String v = value.trim();
|
||||
if (v.isEmpty()) {
|
||||
return def;
|
||||
}
|
||||
v = v.toUpperCase(Locale.ROOT);
|
||||
|
||||
// allow a couple common aliases
|
||||
if (v.equals("ALL")) {
|
||||
return ALL_SERVERS;
|
||||
}
|
||||
if (v.equals("PLAYER")) {
|
||||
return PLAYER_SERVER;
|
||||
}
|
||||
|
||||
try {
|
||||
return ScopeMode.valueOf(v);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
public static ScopeMode parse(String value) {
|
||||
return parse(value, ALL_SERVERS);
|
||||
}
|
||||
}
|
||||
-1
@@ -622,7 +622,6 @@ public class BStatsMetricsBungee {
|
||||
*
|
||||
* @return The server specific data.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private JsonObject getServerData() {
|
||||
// Minecraft specific data
|
||||
int playerAmount = Math.min(plugin.getProxy().getOnlineCount(), 500);
|
||||
|
||||
+96
-9
@@ -5,6 +5,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -16,12 +17,12 @@ import net.md_5.bungee.config.Configuration;
|
||||
import net.md_5.bungee.config.ConfigurationProvider;
|
||||
import net.md_5.bungee.config.YamlConfiguration;
|
||||
|
||||
public class Config implements VotingPluginProxyConfig {
|
||||
public class BungeeConfig implements VotingPluginProxyConfig {
|
||||
private VotingPluginBungee bungee;
|
||||
@Getter
|
||||
private Configuration data;
|
||||
|
||||
public Config(VotingPluginBungee bungee) {
|
||||
public BungeeConfig(VotingPluginBungee bungee) {
|
||||
this.bungee = bungee;
|
||||
}
|
||||
|
||||
@@ -33,6 +34,34 @@ public class Config implements VotingPluginProxyConfig {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getProxyBroadcastEnabled() {
|
||||
return getData().getBoolean("ProxyBroadcast.Enabled", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProxyBroadcastScopeMode() {
|
||||
return getData().getString("ProxyBroadcast.Scope.Mode", "ALL_SERVERS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getProxyBroadcastScopeServers() {
|
||||
List<String> list = getData().getStringList("ProxyBroadcast.Scope.Servers");
|
||||
return list != null ? list : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProxyBroadcastOfflineMode() {
|
||||
return getData().getString("ProxyBroadcast.OfflineMode", "QUEUE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getProxyBroadcastOfflineForwardServers() {
|
||||
List<String> list = getData().getStringList("ProxyBroadcast.OfflineForward.Servers");
|
||||
return list != null ? list : Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getAllowUnJoined() {
|
||||
return getData().getBoolean("AllowUnJoined", false);
|
||||
@@ -48,11 +77,6 @@ public class Config implements VotingPluginProxyConfig {
|
||||
return getData().getStringList("BlockedServers");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBroadcast() {
|
||||
return getData().getBoolean("Broadcast", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBungeeHost() {
|
||||
return getData().getString("BungeeServer.Host", "");
|
||||
@@ -128,6 +152,11 @@ public class Config implements VotingPluginProxyConfig {
|
||||
return getData().getInt("MultiProxyRedis.Port", 6379);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMultiProxyRedisDbIndex() {
|
||||
return getData().getInt("MultiProxyRedis.Db-Index", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getMultiProxyRedisUseExistingConnection() {
|
||||
return getData().getBoolean("MultiProxyRedis.UseExistingConnection", false);
|
||||
@@ -203,6 +232,11 @@ public class Config implements VotingPluginProxyConfig {
|
||||
return getData().getInt("Redis.Port", 6379);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRedisDbIndex() {
|
||||
return getData().getInt("Redis.Db-Index", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedisPrefix() {
|
||||
return getData().getString("Redis.Prefix", "");
|
||||
@@ -405,8 +439,61 @@ public class Config implements VotingPluginProxyConfig {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getResetMilestonesMonthly() {
|
||||
return getData().getBoolean("ResetMilestonesMonthly", false);
|
||||
public boolean getVoteCacheUseMySQL() {
|
||||
return getData().getBoolean("VoteCache.UseMySQL", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVoteCacheUseMainMySQL() {
|
||||
return getData().getBoolean("VoteCache.UseMainMySQL", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeWeekOffSet() {
|
||||
return getData().getInt("TimeWeekOffSet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getNonVotedCacheUseMySQL() {
|
||||
return getData().getBoolean("NonVotedCache.UseMySQL", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getNonVotedCacheUseMainMySQL() {
|
||||
return getData().getBoolean("NonVotedCache.UseMainMySQL", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVoteLoggingEnabled() {
|
||||
return getData().getBoolean("VoteLogging.Enabled", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVoteLoggingPurgeDays() {
|
||||
return getData().getInt("VoteLogging.PurgeDays", 30);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVoteLoggingUseMainMySQL() {
|
||||
return getData().getBoolean("VoteLogging.UseMainMySQL", true);
|
||||
}
|
||||
|
||||
public Configuration sectionOrNull(Configuration root, String key) {
|
||||
Object v = root.get(key);
|
||||
return (v instanceof Configuration) ? (Configuration) v : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDatabaseConfigured() {
|
||||
// New-style: Database: { Host: ..., ... }
|
||||
Configuration db = sectionOrNull(data, "Database");
|
||||
if (db != null) {
|
||||
return db.getString("Host", "") != null && !db.getString("Host", "").isEmpty();
|
||||
}
|
||||
|
||||
// Legacy-style: Host/Port/... at root
|
||||
String host = data.getString("Host", "");
|
||||
return host != null && !host.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.bencodez.votingplugin.proxy.bungee;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.bencodez.simpleapi.file.BungeeJsonFile;
|
||||
import com.bencodez.votingplugin.proxy.cache.nonvoted.INonVotedPlayersStorage;
|
||||
|
||||
public class BungeeJsonNonVotedPlayersCache extends BungeeJsonFile
|
||||
implements INonVotedPlayersStorage {
|
||||
|
||||
public BungeeJsonNonVotedPlayersCache(File file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upsertPlayer(String uuid, String playerName, long lastTime) {
|
||||
setString("NonVotedPlayers." + playerName + ".UUID", uuid);
|
||||
setLong("NonVotedPlayers." + playerName + ".LastTime", lastTime);
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuidByPlayerName(String playerName) {
|
||||
String uuid = getString("NonVotedPlayers." + playerName + ".UUID", "");
|
||||
return uuid != null ? uuid : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByPlayerName(String playerName) {
|
||||
remove("NonVotedPlayers." + playerName);
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<NonVotedPlayerEntry> consumer) {
|
||||
for (String player : getKeys("NonVotedPlayers")) {
|
||||
long time = getLong("NonVotedPlayers." + player + ".LastTime", 0);
|
||||
String uuid = getString("NonVotedPlayers." + player + ".UUID", "");
|
||||
consumer.accept(new NonVotedPlayerEntry(player, uuid, time));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
package com.bencodez.votingplugin.proxy.bungee;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.bencodez.simpleapi.file.BungeeJsonFile;
|
||||
import com.bencodez.votingplugin.proxy.OfflineBungeeVote;
|
||||
import com.bencodez.votingplugin.proxy.cache.DataNode;
|
||||
import com.bencodez.votingplugin.proxy.cache.GsonDataNode;
|
||||
import com.bencodez.votingplugin.proxy.cache.IVoteCache;
|
||||
import com.bencodez.votingplugin.timequeue.VoteTimeQueue;
|
||||
|
||||
public class BungeeJsonVoteCache extends BungeeJsonFile implements IVoteCache {
|
||||
private VotingPluginBungee bungee;
|
||||
|
||||
public BungeeJsonVoteCache(VotingPluginBungee bungee) {
|
||||
super(new File(bungee.getDataFolder(), "votecache.json"));
|
||||
this.bungee = bungee;
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if (!bungee.getDataFolder().exists()) {
|
||||
bungee.getDataFolder().mkdir();
|
||||
}
|
||||
// Reload the JSON file to ensure latest data
|
||||
reload();
|
||||
}
|
||||
|
||||
public void addTimedVote(int num, VoteTimeQueue voteTimedQueue) {
|
||||
String path = "TimedVoteCache." + num;
|
||||
setString(path + ".Name", voteTimedQueue.getName());
|
||||
setString(path + ".Service", voteTimedQueue.getService());
|
||||
setLong(path + ".Time", voteTimedQueue.getTime());
|
||||
}
|
||||
|
||||
public void addVote(String server, int num, OfflineBungeeVote voteData) {
|
||||
String path = "VoteCache." + server + "." + num;
|
||||
setString(path + ".Name", voteData.getPlayerName());
|
||||
setString(path + ".Service", voteData.getService());
|
||||
setString(path + ".UUID", voteData.getUuid());
|
||||
setLong(path + ".Time", voteData.getTime());
|
||||
setBoolean(path + ".Real", voteData.isRealVote());
|
||||
setString(path + ".Text", voteData.getText());
|
||||
setString(path + ".VoteID", voteData.getVoteId() != null ? voteData.getVoteId().toString() : null);
|
||||
}
|
||||
|
||||
public void addVoteOnline(String player, int num, OfflineBungeeVote voteData) {
|
||||
String path = "OnlineCache." + player + "." + num;
|
||||
setString(path + ".Name", voteData.getPlayerName());
|
||||
setString(path + ".Service", voteData.getService());
|
||||
setString(path + ".UUID", voteData.getUuid());
|
||||
setLong(path + ".Time", voteData.getTime());
|
||||
setBoolean(path + ".Real", voteData.isRealVote());
|
||||
setString(path + ".Text", voteData.getText());
|
||||
setString(path + ".VoteID", voteData.getVoteId() != null ? voteData.getVoteId().toString() : null);
|
||||
}
|
||||
|
||||
public void clearData() {
|
||||
setString("VoteCache", null);
|
||||
setString("OnlineCache", null);
|
||||
setString("TimedVoteCache", null);
|
||||
save();
|
||||
}
|
||||
|
||||
public Collection<String> getOnlineVotes(String name) {
|
||||
return getKeys("OnlineCache." + name);
|
||||
}
|
||||
|
||||
public GsonDataNode getOnlineVotes(String name, String num) {
|
||||
return new GsonDataNode(getNode("OnlineCache." + name + "." + num));
|
||||
}
|
||||
|
||||
public Collection<String> getPlayers() {
|
||||
return getKeys("OnlineCache");
|
||||
}
|
||||
|
||||
public Collection<String> getServers() {
|
||||
return getKeys("VoteCache");
|
||||
}
|
||||
|
||||
public Collection<String> getServerVotes(String server) {
|
||||
return getKeys("VoteCache." + server);
|
||||
}
|
||||
|
||||
public GsonDataNode getServerVotes(String server, String num) {
|
||||
return new GsonDataNode(getNode("VoteCache." + server + "." + num));
|
||||
}
|
||||
|
||||
public Collection<String> getTimedVoteCache() {
|
||||
return getKeys("TimedVoteCache");
|
||||
}
|
||||
|
||||
public DataNode getTimedVoteCache(String key) {
|
||||
return new GsonDataNode(getNode("TimedVoteCache." + key));
|
||||
}
|
||||
|
||||
public int getVotePartyCache(String server) {
|
||||
return getInt("VoteParty.Cache." + server, 0);
|
||||
}
|
||||
|
||||
public int getVotePartyCurrentVotes() {
|
||||
return getInt("VoteParty.CurrentVotes", 0);
|
||||
}
|
||||
|
||||
public int getVotePartyInreaseVotesRequired() {
|
||||
return getInt("VoteParty.IncreaseVotes", 0);
|
||||
}
|
||||
|
||||
public void setVotePartyCache(String server, int amount) {
|
||||
setInt("VoteParty.Cache." + server, amount);
|
||||
}
|
||||
|
||||
public void setVotePartyCurrentVotes(int amount) {
|
||||
setInt("VoteParty.CurrentVotes", amount);
|
||||
}
|
||||
|
||||
public void setVotePartyInreaseVotesRequired(int amount) {
|
||||
setInt("VoteParty.IncreaseVotes", amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
super.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOnlineVotes(String player) {
|
||||
setString("OnlineCache." + player, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeServerVotes(String server) {
|
||||
setString("VoteCache." + server, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeServerVote(String server, String uuid) {
|
||||
Collection<String> votes = getServerVotes(server);
|
||||
if (votes == null) {
|
||||
return;
|
||||
}
|
||||
// search for vote with uuid and remove it
|
||||
for (String num : votes) {
|
||||
GsonDataNode node = getServerVotes(server, num);
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
DataNode uuidNode = node.get("UUID");
|
||||
if (uuidNode == null) {
|
||||
continue;
|
||||
}
|
||||
String nodeUuid = uuidNode.asString();
|
||||
if (nodeUuid != null && nodeUuid.equals(uuid)) {
|
||||
setString("VoteCache." + server + "." + num, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVote(String server, OfflineBungeeVote vote) {
|
||||
Collection<String> votes = getServerVotes(server);
|
||||
if (votes == null) {
|
||||
return;
|
||||
}
|
||||
for (String num : votes) {
|
||||
GsonDataNode node = getServerVotes(server, num);
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
DataNode uuidNode = node.get("UUID");
|
||||
DataNode serviceNode = node.get("Service");
|
||||
DataNode timeNode = node.get("Time");
|
||||
if (uuidNode == null || serviceNode == null || timeNode == null) {
|
||||
continue;
|
||||
}
|
||||
String nodeUuid = uuidNode.asString();
|
||||
String nodeService = serviceNode.asString();
|
||||
Long nodeTime = timeNode.asLong();
|
||||
if (nodeUuid != null && nodeService != null && nodeTime != null && nodeUuid.equals(vote.getUuid())
|
||||
&& nodeService.equals(vote.getService()) && nodeTime.longValue() == vote.getTime()) {
|
||||
setString("VoteCache." + server + "." + num, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOnlineVote(OfflineBungeeVote vote) {
|
||||
Collection<String> players = getPlayers();
|
||||
if (players == null) {
|
||||
return;
|
||||
}
|
||||
for (String player : players) {
|
||||
Collection<String> onlineVotes = getOnlineVotes(player);
|
||||
if (onlineVotes == null) {
|
||||
continue;
|
||||
}
|
||||
for (String num : onlineVotes) {
|
||||
GsonDataNode node = getOnlineVotes(player, num);
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
DataNode uuidNode = node.get("UUID");
|
||||
DataNode serviceNode = node.get("Service");
|
||||
DataNode timeNode = node.get("Time");
|
||||
if (uuidNode == null || serviceNode == null || timeNode == null) {
|
||||
continue;
|
||||
}
|
||||
String nodeUuid = uuidNode.asString();
|
||||
String nodeService = serviceNode.asString();
|
||||
Long nodeTime = timeNode.asLong();
|
||||
if (nodeUuid != null && nodeService != null && nodeTime != null && nodeUuid.equals(vote.getUuid())
|
||||
&& nodeService.equals(vote.getService()) && nodeTime.longValue() == vote.getTime()) {
|
||||
setString("OnlineCache." + player + "." + num, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
package com.bencodez.votingplugin.proxy.bungee;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.bencodez.simpleapi.file.BungeeJsonFile;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
|
||||
public class NonVotedPlayersCache extends BungeeJsonFile {
|
||||
private VotingPluginBungee plugin;
|
||||
@Getter
|
||||
private Configuration data;
|
||||
|
||||
public NonVotedPlayersCache(VotingPluginBungee plugin) {
|
||||
super(new File(plugin.getDataFolder(), "nonvotedplayerscache.json"));
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void addPlayer(Player player) {
|
||||
if (!plugin.getVotingPluginProxy().getProxyMySQL().containsKeyQuery(player.getUniqueId().toString())) {
|
||||
addPlayer(player.getUniqueId().toString(), player.getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
public void addPlayer(String uuid, String playerName) {
|
||||
setString("NonVotedPlayers." + playerName + ".UUID", uuid);
|
||||
setLong("NonVotedPlayers." + playerName + ".LastTime", System.currentTimeMillis());
|
||||
save();
|
||||
}
|
||||
|
||||
public void addPlayerCheck(String uuid, String playerName) {
|
||||
if (!plugin.getVotingPluginProxy().getProxyMySQL().containsKeyQuery(uuid)) {
|
||||
addPlayer(uuid, playerName);
|
||||
}
|
||||
}
|
||||
|
||||
public void check() {
|
||||
for (String player : getKeys("NonVotedPlayers")) {
|
||||
long time = getLong("NonVotedPlayers." + player + ".LastTime", 0);
|
||||
if ((System.currentTimeMillis() - time) > 1000 * 60 * 60 * 24 * 5) {
|
||||
removePlayer(player);
|
||||
} else {
|
||||
String uuid = getString("NonVotedPlayers." + player + ".UUID", "");
|
||||
if (!uuid.isEmpty()) {
|
||||
if (plugin.getVotingPluginProxy().getProxyMySQL().containsKeyQuery(uuid)) {
|
||||
removePlayer(player);
|
||||
}
|
||||
} else {
|
||||
removePlayer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
public String playerExists(String playerName) {
|
||||
String uuid = getString("NonVotedPlayers." + playerName + ".UUID", "");
|
||||
if (!uuid.isEmpty()) {
|
||||
return uuid;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private void removePlayer(String player) {
|
||||
plugin.debug("Removing nonvotedplayer: " + player);
|
||||
remove("NonVotedPlayers." + player);
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package com.bencodez.votingplugin.proxy.bungee;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.bencodez.simpleapi.file.BungeeJsonFile;
|
||||
import com.bencodez.votingplugin.proxy.OfflineBungeeVote;
|
||||
import com.bencodez.votingplugin.timequeue.VoteTimeQueue;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
public class VoteCache extends BungeeJsonFile {
|
||||
private VotingPluginBungee bungee;
|
||||
|
||||
public VoteCache(VotingPluginBungee bungee) {
|
||||
super(new File(bungee.getDataFolder(), "votecache.json"));
|
||||
this.bungee = bungee;
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if (!bungee.getDataFolder().exists()) {
|
||||
bungee.getDataFolder().mkdir();
|
||||
}
|
||||
// Reload the JSON file to ensure latest data
|
||||
reload();
|
||||
}
|
||||
|
||||
public void addTimedVote(int num, VoteTimeQueue voteTimedQueue) {
|
||||
String path = "TimedVoteCache." + num;
|
||||
setString(path + ".Name", voteTimedQueue.getName());
|
||||
setString(path + ".Service", voteTimedQueue.getService());
|
||||
setLong(path + ".Time", voteTimedQueue.getTime());
|
||||
}
|
||||
|
||||
public void addVote(String server, int num, OfflineBungeeVote voteData) {
|
||||
String path = "VoteCache." + server + "." + num;
|
||||
setString(path + ".Name", voteData.getPlayerName());
|
||||
setString(path + ".Service", voteData.getService());
|
||||
setString(path + ".UUID", voteData.getUuid());
|
||||
setLong(path + ".Time", voteData.getTime());
|
||||
setBoolean(path + ".Real", voteData.isRealVote());
|
||||
setString(path + ".Text", voteData.getText());
|
||||
}
|
||||
|
||||
public void addVoteOnline(String player, int num, OfflineBungeeVote voteData) {
|
||||
String path = "OnlineCache." + player + "." + num;
|
||||
setString(path + ".Name", voteData.getPlayerName());
|
||||
setString(path + ".Service", voteData.getService());
|
||||
setString(path + ".UUID", voteData.getUuid());
|
||||
setLong(path + ".Time", voteData.getTime());
|
||||
setBoolean(path + ".Real", voteData.isRealVote());
|
||||
setString(path + ".Text", voteData.getText());
|
||||
}
|
||||
|
||||
public void clearData() {
|
||||
setString("VoteCache", null);
|
||||
setString("OnlineCache", null);
|
||||
setString("TimedVoteCache", null);
|
||||
save();
|
||||
}
|
||||
|
||||
public Collection<String> getOnlineVotes(String name) {
|
||||
return getKeys("OnlineCache." + name);
|
||||
}
|
||||
|
||||
public JsonElement getOnlineVotes(String name, String num) {
|
||||
return getNode("OnlineCache." + name + "." + num);
|
||||
}
|
||||
|
||||
public Collection<String> getPlayers() {
|
||||
return getKeys("OnlineCache");
|
||||
}
|
||||
|
||||
public Collection<String> getServers() {
|
||||
return getKeys("VoteCache");
|
||||
}
|
||||
|
||||
public Collection<String> getServerVotes(String server) {
|
||||
return getKeys("VoteCache." + server);
|
||||
}
|
||||
|
||||
public JsonElement getServerVotes(String server, String num) {
|
||||
return getNode("VoteCache." + server + "." + num);
|
||||
}
|
||||
|
||||
public Collection<String> getTimedVoteCache() {
|
||||
return getKeys("TimedVoteCache");
|
||||
}
|
||||
|
||||
public JsonElement getTimedVoteCache(String key) {
|
||||
return getNode("TimedVoteCache." + key);
|
||||
}
|
||||
|
||||
public int getVotePartyCache(String server) {
|
||||
return getInt("VoteParty.Cache." + server, 0);
|
||||
}
|
||||
|
||||
public int getVotePartyCurrentVotes() {
|
||||
return getInt("VoteParty.CurrentVotes", 0);
|
||||
}
|
||||
|
||||
public int getVotePartyInreaseVotesRequired() {
|
||||
return getInt("VoteParty.IncreaseVotes", 0);
|
||||
}
|
||||
|
||||
public void setVotePartyCache(String server, int amount) {
|
||||
setInt("VoteParty.Cache." + server, amount);
|
||||
}
|
||||
|
||||
public void setVotePartyCurrentVotes(int amount) {
|
||||
setInt("VoteParty.CurrentVotes", amount);
|
||||
}
|
||||
|
||||
public void setVotePartyInreaseVotesRequired(int amount) {
|
||||
setInt("VoteParty.IncreaseVotes", amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
super.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
super.reload();
|
||||
}
|
||||
}
|
||||
+537
-543
File diff suppressed because it is too large.
Load diff
+6
-4
@@ -2,6 +2,7 @@ package com.bencodez.votingplugin.proxy.bungee;
|
||||
|
||||
import com.bencodez.votingplugin.proxy.VotingPluginProxyCommand;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
@@ -10,19 +11,20 @@ public class VotingPluginBungeeCommand extends Command {
|
||||
private VotingPluginBungee bungee;
|
||||
|
||||
public VotingPluginBungeeCommand(VotingPluginBungee bungee) {
|
||||
super("votingpluginbungee", "votingplugin.admin");
|
||||
super("votingpluginproxy", "votingpluginproxy.admin");
|
||||
this.bungee = bungee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
if (sender.hasPermission("votingplugin.admin")) {
|
||||
if (sender.hasPermission("votingpluginproxy.admin")) {
|
||||
String result = new VotingPluginProxyCommand(bungee.getVotingPluginProxy()).execute(args);
|
||||
if (result != null) {
|
||||
sender.sendMessage(new TextComponent(result.replace("&", "§")));
|
||||
sender.sendMessage(new TextComponent(result.replace("&", "" + ChatColor.COLOR_CHAR)));
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage(new TextComponent("&cYou do not have permission to do this!".replace("&", "§")));
|
||||
sender.sendMessage(new TextComponent(
|
||||
"&cYou do not have permission to do this!".replace("&", "" + ChatColor.COLOR_CHAR)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package com.bencodez.votingplugin.proxy.cache;
|
||||
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
||||
public class ConfigDataNode implements DataNode {
|
||||
|
||||
private final ConfigurationNode node;
|
||||
|
||||
public ConfigDataNode(ConfigurationNode node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObject() {
|
||||
return node.isMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArray() {
|
||||
return node.isList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitive() {
|
||||
return !isObject() && !isArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataNode get(String key) {
|
||||
return new ConfigDataNode(node.node((Object) key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asLong() {
|
||||
return node.getLong();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean has(String key) {
|
||||
ConfigurationNode child = node.node((Object) key);
|
||||
return child != null && child.raw() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(int index) {
|
||||
ConfigurationNode child = node.node(index);
|
||||
return child != null && child.raw() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataNode get(int index) {
|
||||
return new ConfigDataNode(node.node(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String key, Object value) {
|
||||
try {
|
||||
node.node((Object) key).set(value);
|
||||
} catch (SerializationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Object value) {
|
||||
try {
|
||||
node.node(index).set(value);
|
||||
} catch (SerializationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asPrimitive() {
|
||||
return node.raw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return node.getString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int asInt() {
|
||||
return node.getInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean asBoolean() {
|
||||
return node.getBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toInternal() {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.bencodez.votingplugin.proxy.cache;
|
||||
|
||||
public interface DataNode {
|
||||
boolean isObject();
|
||||
|
||||
boolean isArray();
|
||||
|
||||
boolean isPrimitive();
|
||||
|
||||
DataNode get(String key);
|
||||
|
||||
DataNode get(int index);
|
||||
|
||||
void set(String key, Object value);
|
||||
|
||||
void set(int index, Object value);
|
||||
|
||||
Object asPrimitive();
|
||||
|
||||
String asString();
|
||||
|
||||
long asLong();
|
||||
|
||||
boolean has(String key);
|
||||
boolean has(int index);
|
||||
|
||||
int asInt();
|
||||
|
||||
boolean asBoolean();
|
||||
|
||||
Object toInternal(); // Returns either JsonElement or ConfigurationNode
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
package com.bencodez.votingplugin.proxy.cache;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
public class GsonDataNode implements DataNode {
|
||||
|
||||
private final JsonElement element;
|
||||
|
||||
public GsonDataNode(JsonElement element) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObject() {
|
||||
return element.isJsonObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArray() {
|
||||
return element.isJsonArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitive() {
|
||||
return element.isJsonPrimitive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataNode get(String key) {
|
||||
if (!isObject())
|
||||
return null;
|
||||
return new GsonDataNode(element.getAsJsonObject().get(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataNode get(int index) {
|
||||
if (!isArray())
|
||||
return null;
|
||||
return new GsonDataNode(element.getAsJsonArray().get(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String key, Object value) {
|
||||
if (!isObject())
|
||||
return;
|
||||
element.getAsJsonObject().add(key, new Gson().toJsonTree(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, Object value) {
|
||||
if (!isArray())
|
||||
return;
|
||||
element.getAsJsonArray().set(index, new Gson().toJsonTree(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asLong() {
|
||||
if (element == null || !element.isJsonPrimitive())
|
||||
return 0L;
|
||||
|
||||
JsonPrimitive prim = element.getAsJsonPrimitive();
|
||||
|
||||
if (prim.isNumber()) {
|
||||
return prim.getAsLong();
|
||||
}
|
||||
|
||||
// Try parsing from string if it's not a number
|
||||
try {
|
||||
return Long.parseLong(prim.getAsString());
|
||||
} catch (NumberFormatException e) {
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object asPrimitive() {
|
||||
if (!isPrimitive())
|
||||
return null;
|
||||
JsonPrimitive prim = element.getAsJsonPrimitive();
|
||||
if (prim.isBoolean())
|
||||
return prim.getAsBoolean();
|
||||
if (prim.isNumber())
|
||||
return prim.getAsNumber();
|
||||
return prim.getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String key) {
|
||||
return isObject() && element.getAsJsonObject().has(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(int index) {
|
||||
return isArray() && index >= 0 && index < element.getAsJsonArray().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return element.getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int asInt() {
|
||||
return element.getAsInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean asBoolean() {
|
||||
return element.getAsBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object toInternal() {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package com.bencodez.votingplugin.proxy.cache;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.bencodez.votingplugin.proxy.OfflineBungeeVote;
|
||||
import com.bencodez.votingplugin.timequeue.VoteTimeQueue;
|
||||
|
||||
public interface IVoteCache {
|
||||
|
||||
void addTimedVote(int num, VoteTimeQueue voteTimedQueue);
|
||||
|
||||
void addVote(String server, int num, OfflineBungeeVote voteData);
|
||||
|
||||
void addVoteOnline(String player, int num, OfflineBungeeVote voteData);
|
||||
|
||||
void clearData();
|
||||
|
||||
Collection<String> getOnlineVotes(String name);
|
||||
|
||||
DataNode getOnlineVotes(String name, String num);
|
||||
|
||||
Collection<String> getPlayers();
|
||||
|
||||
Collection<String> getServers();
|
||||
|
||||
Collection<String> getServerVotes(String server);
|
||||
|
||||
DataNode getServerVotes(String server, String num);
|
||||
|
||||
Collection<String> getTimedVoteCache();
|
||||
|
||||
DataNode getTimedVoteCache(String key);
|
||||
|
||||
int getVotePartyCache(String server);
|
||||
|
||||
int getVotePartyCurrentVotes();
|
||||
|
||||
int getVotePartyInreaseVotesRequired();
|
||||
|
||||
void setVotePartyCache(String server, int amount);
|
||||
|
||||
void setVotePartyCurrentVotes(int amount);
|
||||
|
||||
void setVotePartyInreaseVotesRequired(int amount);
|
||||
|
||||
void save();
|
||||
|
||||
void reload();
|
||||
|
||||
void removeOnlineVotes(String player);
|
||||
|
||||
void removeServerVotes(String server);
|
||||
|
||||
void removeServerVote(String server, String uuid);
|
||||
|
||||
void removeVote(String server, OfflineBungeeVote vote);
|
||||
|
||||
void removeOnlineVote(OfflineBungeeVote vote);
|
||||
}
|
||||
Vendored
+359
@@ -0,0 +1,359 @@
|
||||
package com.bencodez.votingplugin.proxy.cache;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement; // NEW
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set; // NEW
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap; // NEW
|
||||
|
||||
import com.bencodez.simpleapi.sql.mysql.AbstractSqlTable;
|
||||
import com.bencodez.simpleapi.sql.mysql.DbType;
|
||||
import com.bencodez.simpleapi.sql.mysql.MySQL;
|
||||
import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig;
|
||||
import com.bencodez.simpleapi.sql.mysql.queries.Query;
|
||||
import com.bencodez.votingplugin.proxy.OfflineBungeeVote;
|
||||
|
||||
public abstract class ProxyOnlineVoteCacheTable extends AbstractSqlTable {
|
||||
|
||||
// Prevent repeated startup DDL across multiple instances/subclasses
|
||||
private static final Set<String> MIGRATED_VOTEID = ConcurrentHashMap.newKeySet();
|
||||
private static final Set<String> ENSURED_INDEXES = ConcurrentHashMap.newKeySet();
|
||||
|
||||
@Override
|
||||
public String getPrimaryKeyColumn() {
|
||||
return "id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCreateTableSql(DbType dbType) {
|
||||
if (dbType == DbType.POSTGRESQL) {
|
||||
return "CREATE TABLE IF NOT EXISTS " + qi(getTableName()) + " (" + qi("id") + " BIGSERIAL PRIMARY KEY, "
|
||||
+ qi("uuid") + " " + bestUuidType() + ", " + qi("voteid") + " VARCHAR(36), " + qi("playerName")
|
||||
+ " VARCHAR(100), " + qi("service") + " VARCHAR(100), " + qi("time") + " BIGINT, " + qi("realVote")
|
||||
+ " BOOLEAN, " + qi("text") + " TEXT" + ");";
|
||||
}
|
||||
|
||||
return "CREATE TABLE IF NOT EXISTS " + qi(getTableName()) + " (" + qi("id") + " INT AUTO_INCREMENT PRIMARY KEY,"
|
||||
+ qi("uuid") + " VARCHAR(37)," + qi("voteid") + " VARCHAR(36)," + qi("playerName") + " VARCHAR(100),"
|
||||
+ qi("service") + " VARCHAR(100)," + qi("time") + " BIGINT," + qi("realVote") + " TINYINT(1),"
|
||||
+ qi("text") + " TEXT," + "INDEX idx_uuid (" + qi("uuid") + ")," + "INDEX idx_time (" + qi("time") + ")"
|
||||
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
}
|
||||
|
||||
public void removeVotesByUuid(String uuid) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("uuid") + " = ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(1, UUID.fromString(uuid));
|
||||
} else {
|
||||
ps.setString(1, uuid);
|
||||
}
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void logSevere(String msg);
|
||||
|
||||
@Override
|
||||
public abstract void logInfo(String msg);
|
||||
|
||||
@Override
|
||||
public abstract void debug(Throwable t);
|
||||
|
||||
public ProxyOnlineVoteCacheTable(MySQL existingMysql, String tablePrefix, boolean debug) {
|
||||
super((tablePrefix != null ? tablePrefix : "") + "votingplugin_onlinevotecache", existingMysql, debug);
|
||||
|
||||
// best-effort migrations (no nested connections)
|
||||
alterColumnType("uuid", bestUuidType());
|
||||
addVoteIdColumnIfMissingOnce();
|
||||
ensureIndexesOnce();
|
||||
}
|
||||
|
||||
public ProxyOnlineVoteCacheTable(MysqlConfig config, boolean debug) {
|
||||
super("votingplugin_onlinevotecache", config, debug);
|
||||
|
||||
alterColumnType("uuid", bestUuidType());
|
||||
addVoteIdColumnIfMissingOnce();
|
||||
ensureIndexesOnce();
|
||||
}
|
||||
|
||||
public void updateVoteText(OfflineBungeeVote vote, String newText) {
|
||||
if (vote == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String sql = "UPDATE " + qi(getTableName()) + " SET " + qi("text") + " = ?" + " WHERE " + qi("uuid")
|
||||
+ " = ? AND " + qi("service") + " = ? AND " + qi("time") + " = ?;";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
ps.setString(1, newText);
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(2, UUID.fromString(vote.getUuid()));
|
||||
} else {
|
||||
ps.setString(2, vote.getUuid());
|
||||
}
|
||||
|
||||
ps.setString(3, vote.getService());
|
||||
ps.setLong(4, vote.getTime());
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureIndexesOnce() {
|
||||
if (getDbType() != DbType.POSTGRESQL) {
|
||||
return;
|
||||
}
|
||||
|
||||
String key = getDbType() + ":" + getTableName() + ":indexes";
|
||||
if (!ENSURED_INDEXES.add(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use ONE connection for all index DDL to avoid pool starvation (pool=1 safe)
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection(); Statement st = conn.createStatement()) {
|
||||
|
||||
st.executeUpdate("CREATE INDEX IF NOT EXISTS idx_uuid ON " + qi(getTableName()) + " (" + qi("uuid") + ");");
|
||||
st.executeUpdate("CREATE INDEX IF NOT EXISTS idx_time ON " + qi(getTableName()) + " (" + qi("time") + ");");
|
||||
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addVoteIdColumnIfMissingOnce() {
|
||||
String key = getDbType() + ":" + getTableName() + ":voteid";
|
||||
if (!MIGRATED_VOTEID.add(key)) {
|
||||
return;
|
||||
}
|
||||
addVoteIdColumnIfMissing();
|
||||
}
|
||||
|
||||
private void addVoteIdColumnIfMissing() {
|
||||
final boolean pg = getDbType() == DbType.POSTGRESQL;
|
||||
|
||||
final String schemaFilter = pg ? "table_schema = current_schema()" : "TABLE_SCHEMA = DATABASE()";
|
||||
|
||||
// Lowercase compare avoids casing issues on some setups
|
||||
final String checkSql = "SELECT 1 FROM information_schema.columns WHERE " + schemaFilter
|
||||
+ " AND LOWER(table_name) = LOWER(?) AND LOWER(column_name) = LOWER(?) LIMIT 1;";
|
||||
|
||||
// IMPORTANT: do check + alter on SAME connection to avoid deadlock when
|
||||
// poolSize=1
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(checkSql)) {
|
||||
|
||||
ps.setString(1, getTableName());
|
||||
ps.setString(2, "voteid");
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
return; // exists
|
||||
}
|
||||
}
|
||||
|
||||
String alter = "ALTER TABLE " + qi(getTableName()) + " ADD COLUMN " + qi("voteid") + " VARCHAR(36);";
|
||||
try (Statement st = conn.createStatement()) {
|
||||
st.executeUpdate(alter);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
logSevere("Failed to add voteid column to " + getTableName() + ": " + e.getMessage());
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
// --- INSERT ---
|
||||
|
||||
public void insertVote(UUID voteId, String uuid, String playerName, String service, long time, boolean real,
|
||||
String text) {
|
||||
|
||||
String sql = "INSERT INTO " + qi(getTableName()) + " (" + qi("uuid") + ", " + qi("voteid") + ", "
|
||||
+ qi("playerName") + ", " + qi("service") + ", " + qi("time") + ", " + qi("realVote") + ", "
|
||||
+ qi("text") + ") VALUES (?, ?, ?, ?, ?, ?, ?);";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(1, UUID.fromString(uuid));
|
||||
} else {
|
||||
ps.setString(1, uuid);
|
||||
}
|
||||
|
||||
ps.setString(2, voteId != null ? voteId.toString() : null);
|
||||
ps.setString(3, playerName);
|
||||
ps.setString(4, service);
|
||||
ps.setLong(5, time);
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setBoolean(6, real);
|
||||
} else {
|
||||
ps.setInt(6, real ? 1 : 0);
|
||||
}
|
||||
|
||||
ps.setString(7, text);
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
// --- GET ---
|
||||
|
||||
public List<VoteRow> getAllVotes() {
|
||||
return selectVotes("SELECT * FROM " + qi(getTableName()) + ";", null);
|
||||
}
|
||||
|
||||
public List<VoteRow> getVotesByUUID(String uuid) {
|
||||
String sql = "SELECT * FROM " + qi(getTableName()) + " WHERE " + qi("uuid") + " = ?;";
|
||||
Object param = (getDbType() == DbType.POSTGRESQL) ? UUID.fromString(uuid) : uuid;
|
||||
return selectVotes(sql, new Object[] { param });
|
||||
}
|
||||
|
||||
// --- DELETE ---
|
||||
|
||||
public void removeVoteById(int id) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("id") + " = ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setInt(1, id);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVote(OfflineBungeeVote vote) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("uuid") + " = ? AND " + qi("service")
|
||||
+ " = ? AND " + qi("time") + " = ?;";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(1, UUID.fromString(vote.getUuid()));
|
||||
} else {
|
||||
ps.setString(1, vote.getUuid());
|
||||
}
|
||||
|
||||
ps.setString(2, vote.getService());
|
||||
ps.setLong(3, vote.getTime());
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearTable() {
|
||||
try {
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
new Query(mysql, "TRUNCATE TABLE " + qi(getTableName()) + " RESTART IDENTITY;").executeUpdate();
|
||||
} else {
|
||||
new Query(mysql, "TRUNCATE TABLE " + qi(getTableName()) + ";").executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Internals ---
|
||||
|
||||
private List<VoteRow> selectVotes(String sql, Object[] params) {
|
||||
List<VoteRow> list = new ArrayList<>();
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (params != null) {
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
ps.setObject(i + 1, params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
list.add(new VoteRow(rs.getInt("id"), rs.getString("voteid"), rs.getString("uuid"),
|
||||
rs.getString("playerName"), rs.getString("service"), rs.getLong("time"),
|
||||
(getDbType() == DbType.POSTGRESQL ? rs.getBoolean("realVote") : rs.getInt("realVote") == 1),
|
||||
rs.getString("text")));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static class VoteRow {
|
||||
private final int id;
|
||||
private final String voteId;
|
||||
private final String uuid;
|
||||
private final String playerName;
|
||||
private final String service;
|
||||
private final long time;
|
||||
private final boolean realVote;
|
||||
private final String text;
|
||||
|
||||
public VoteRow(int id, String voteId, String uuid, String playerName, String service, long time,
|
||||
boolean realVote, String text) {
|
||||
this.id = id;
|
||||
this.voteId = voteId;
|
||||
this.uuid = uuid;
|
||||
this.playerName = playerName;
|
||||
this.service = service;
|
||||
this.time = time;
|
||||
this.realVote = realVote;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getVoteId() {
|
||||
return voteId;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return playerName;
|
||||
}
|
||||
|
||||
public String getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public boolean isRealVote() {
|
||||
return realVote;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+191
@@ -0,0 +1,191 @@
|
||||
package com.bencodez.votingplugin.proxy.cache;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bencodez.simpleapi.sql.mysql.AbstractSqlTable;
|
||||
import com.bencodez.simpleapi.sql.mysql.DbType;
|
||||
import com.bencodez.simpleapi.sql.mysql.MySQL;
|
||||
import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig;
|
||||
import com.bencodez.simpleapi.sql.mysql.queries.Query;
|
||||
|
||||
public abstract class ProxyTimedVoteCacheTable extends AbstractSqlTable {
|
||||
|
||||
@Override
|
||||
public String getPrimaryKeyColumn() {
|
||||
return "id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCreateTableSql(DbType dbType) {
|
||||
if (dbType == DbType.POSTGRESQL) {
|
||||
return "CREATE TABLE IF NOT EXISTS " + qi(getTableName()) + " ("
|
||||
+ qi("id") + " BIGSERIAL PRIMARY KEY, "
|
||||
+ qi("playerName") + " VARCHAR(100), "
|
||||
+ qi("service") + " VARCHAR(100), "
|
||||
+ qi("time") + " BIGINT"
|
||||
+ ");";
|
||||
}
|
||||
|
||||
return "CREATE TABLE IF NOT EXISTS " + qi(getTableName()) + " ("
|
||||
+ qi("id") + " INT AUTO_INCREMENT PRIMARY KEY,"
|
||||
+ qi("playerName") + " VARCHAR(100),"
|
||||
+ qi("service") + " VARCHAR(100),"
|
||||
+ qi("time") + " BIGINT,"
|
||||
+ "INDEX idx_time (" + qi("time") + ")"
|
||||
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void logSevere(String msg);
|
||||
|
||||
@Override
|
||||
public abstract void logInfo(String msg);
|
||||
|
||||
@Override
|
||||
public abstract void debug(Throwable t);
|
||||
|
||||
public ProxyTimedVoteCacheTable(MySQL existingMysql, String tablePrefix, boolean debug) {
|
||||
super((tablePrefix != null ? tablePrefix : "") + "votingplugin_timedvotecache",
|
||||
existingMysql,
|
||||
debug);
|
||||
ensureIndexes();
|
||||
}
|
||||
|
||||
public ProxyTimedVoteCacheTable(MysqlConfig config, boolean debug) {
|
||||
super("votingplugin_timedvotecache", config, debug);
|
||||
ensureIndexes();
|
||||
}
|
||||
|
||||
private void ensureIndexes() {
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
try {
|
||||
new Query(mysql, "CREATE INDEX IF NOT EXISTS idx_time ON " + qi(getTableName()) + " (" + qi("time")
|
||||
+ ");").executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- INSERT ---
|
||||
public void insertTimedVote(String playerName, String service, long time) {
|
||||
String sql = "INSERT INTO " + qi(getTableName()) + " (" + qi("playerName") + ", " + qi("service") + ", "
|
||||
+ qi("time") + ") VALUES (?, ?, ?);";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
ps.setString(2, service);
|
||||
ps.setLong(3, time);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
// --- GET ---
|
||||
public List<TimedVoteRow> getAllVotes() {
|
||||
return selectVotes("SELECT * FROM " + qi(getTableName()) + ";", null);
|
||||
}
|
||||
|
||||
public List<TimedVoteRow> getExpiredVotes(long now) {
|
||||
return selectVotes("SELECT * FROM " + qi(getTableName()) + " WHERE " + qi("time") + " <= ?;",
|
||||
new Object[] { now });
|
||||
}
|
||||
|
||||
// --- DELETE ---
|
||||
public void removeVoteById(int id) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("id") + " = ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setInt(1, id);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeExpiredVotes(long now) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("time") + " <= ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setLong(1, now);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearTable() {
|
||||
try {
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
new Query(mysql, "TRUNCATE TABLE " + qi(getTableName()) + " RESTART IDENTITY;").executeUpdate();
|
||||
} else {
|
||||
new Query(mysql, "TRUNCATE TABLE " + qi(getTableName()) + ";").executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<TimedVoteRow> selectVotes(String sql, Object[] params) {
|
||||
List<TimedVoteRow> list = new ArrayList<>();
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (params != null) {
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
ps.setObject(i + 1, params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
list.add(new TimedVoteRow(
|
||||
rs.getInt("id"),
|
||||
rs.getString("playerName"),
|
||||
rs.getString("service"),
|
||||
rs.getLong("time")
|
||||
));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static class TimedVoteRow {
|
||||
private final int id;
|
||||
private final String playerName;
|
||||
private final String service;
|
||||
private final long time;
|
||||
|
||||
public TimedVoteRow(int id, String playerName, String service, long time) {
|
||||
this.id = id;
|
||||
this.playerName = playerName;
|
||||
this.service = service;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return playerName;
|
||||
}
|
||||
|
||||
public String getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
}
|
||||
+453
@@ -0,0 +1,453 @@
|
||||
package com.bencodez.votingplugin.proxy.cache;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.bencodez.simpleapi.sql.mysql.AbstractSqlTable;
|
||||
import com.bencodez.simpleapi.sql.mysql.DbType;
|
||||
import com.bencodez.simpleapi.sql.mysql.MySQL;
|
||||
import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig;
|
||||
import com.bencodez.simpleapi.sql.mysql.queries.Query;
|
||||
import com.bencodez.votingplugin.proxy.OfflineBungeeVote;
|
||||
|
||||
/**
|
||||
* Proxy vote cache (per-server cached votes).
|
||||
*
|
||||
* Columns: - id (auto increment primary key) - uuid (player uuid) - voteid
|
||||
* (vote uuid, nullable) - playerName - service - time (millis) - realVote
|
||||
* (bool) - text (payload) - server
|
||||
*
|
||||
* Indexes: - server - uuid - time
|
||||
*/
|
||||
public abstract class ProxyVoteCacheTable extends AbstractSqlTable {
|
||||
|
||||
// Ensure we don't run the same migration repeatedly during startup (or for each
|
||||
// subclass).
|
||||
private static final Set<String> MIGRATED_VOTEID = ConcurrentHashMap.newKeySet();
|
||||
private static final Set<String> ENSURED_INDEXES = ConcurrentHashMap.newKeySet();
|
||||
|
||||
// ---- Required hooks ----
|
||||
|
||||
@Override
|
||||
public String getPrimaryKeyColumn() {
|
||||
// This table's actual PK is numeric id; AbstractSqlTable caches keys as
|
||||
// Strings.
|
||||
return "id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCreateTableSql(DbType dbType) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (dbType == DbType.POSTGRESQL) {
|
||||
sb.append("CREATE TABLE IF NOT EXISTS ").append(qi(getTableName())).append(" (").append(qi("id"))
|
||||
.append(" BIGSERIAL PRIMARY KEY, ").append(qi("uuid")).append(" ").append(bestUuidType())
|
||||
.append(", ").append(qi("voteid")).append(" VARCHAR(36), ").append(qi("playerName"))
|
||||
.append(" VARCHAR(100), ").append(qi("service")).append(" VARCHAR(100), ").append(qi("time"))
|
||||
.append(" BIGINT, ").append(qi("realVote")).append(" BOOLEAN, ").append(qi("text"))
|
||||
.append(" TEXT, ").append(qi("server")).append(" VARCHAR(100)").append(");");
|
||||
} else {
|
||||
sb.append("CREATE TABLE IF NOT EXISTS ").append(qi(getTableName())).append(" (").append(qi("id"))
|
||||
.append(" INT AUTO_INCREMENT PRIMARY KEY,").append(qi("uuid")).append(" VARCHAR(37),")
|
||||
.append(qi("voteid")).append(" VARCHAR(36),").append(qi("playerName")).append(" VARCHAR(100),")
|
||||
.append(qi("service")).append(" VARCHAR(100),").append(qi("time")).append(" BIGINT,")
|
||||
.append(qi("realVote")).append(" TINYINT(1),").append(qi("text")).append(" TEXT,")
|
||||
.append(qi("server")).append(" VARCHAR(100),").append("INDEX idx_server (").append(qi("server"))
|
||||
.append("),").append("INDEX idx_uuid (").append(qi("uuid")).append("),").append("INDEX idx_time (")
|
||||
.append(qi("time")).append(")").append(") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void updateVoteText(OfflineBungeeVote vote, String server, String newText) {
|
||||
if (vote == null || server == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String sql = "UPDATE " + qi(getTableName()) + " SET " + qi("text") + " = ?" + " WHERE " + qi("uuid")
|
||||
+ " = ? AND " + qi("service") + " = ? AND " + qi("time") + " = ? AND " + qi("server") + " = ?;";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
ps.setString(1, newText);
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(2, UUID.fromString(vote.getUuid()));
|
||||
} else {
|
||||
ps.setString(2, vote.getUuid());
|
||||
}
|
||||
|
||||
ps.setString(3, vote.getService());
|
||||
ps.setLong(4, vote.getTime());
|
||||
ps.setString(5, server);
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void logSevere(String msg);
|
||||
|
||||
@Override
|
||||
public abstract void logInfo(String msg);
|
||||
|
||||
@Override
|
||||
public abstract void debug(Throwable t);
|
||||
|
||||
// ---- Constructors ----
|
||||
|
||||
public ProxyVoteCacheTable(MySQL existingMysql, String tablePrefix, boolean debug) {
|
||||
super((tablePrefix != null ? tablePrefix : "") + "votingplugin_votecache", existingMysql, debug);
|
||||
|
||||
// best-effort migrations (safe for pool size 1; no nested connections)
|
||||
alterColumnType("uuid", bestUuidType());
|
||||
addVoteIdColumnIfMissingOnce();
|
||||
ensureIndexesOnce();
|
||||
}
|
||||
|
||||
public ProxyVoteCacheTable(MysqlConfig config, boolean debug) {
|
||||
super("votingplugin_votecache", config, debug);
|
||||
|
||||
alterColumnType("uuid", bestUuidType());
|
||||
addVoteIdColumnIfMissingOnce();
|
||||
ensureIndexesOnce();
|
||||
}
|
||||
|
||||
// ---- Migrations / indexes ----
|
||||
|
||||
private void ensureIndexesOnce() {
|
||||
if (getDbType() != DbType.POSTGRESQL) {
|
||||
return; // MySQL indexes are already in CREATE TABLE
|
||||
}
|
||||
|
||||
final String key = getDbType() + ":" + getTableName();
|
||||
if (!ENSURED_INDEXES.add(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use ONE connection for all index statements (no pool churn).
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection(); Statement st = conn.createStatement()) {
|
||||
|
||||
st.executeUpdate(
|
||||
"CREATE INDEX IF NOT EXISTS idx_server ON " + qi(getTableName()) + " (" + qi("server") + ");");
|
||||
st.executeUpdate("CREATE INDEX IF NOT EXISTS idx_uuid ON " + qi(getTableName()) + " (" + qi("uuid") + ");");
|
||||
st.executeUpdate("CREATE INDEX IF NOT EXISTS idx_time ON " + qi(getTableName()) + " (" + qi("time") + ");");
|
||||
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addVoteIdColumnIfMissingOnce() {
|
||||
final String key = getDbType() + ":" + getTableName() + ":voteid";
|
||||
if (!MIGRATED_VOTEID.add(key)) {
|
||||
return;
|
||||
}
|
||||
addVoteIdColumnIfMissing();
|
||||
}
|
||||
|
||||
private void addVoteIdColumnIfMissing() {
|
||||
// Avoid nested connections: do check + alter using the SAME connection.
|
||||
final boolean pg = getDbType() == DbType.POSTGRESQL;
|
||||
|
||||
final String schemaFilter = pg ? "table_schema = current_schema()" : "TABLE_SCHEMA = DATABASE()";
|
||||
|
||||
// Case-insensitive match helps with MySQL lower_case_table_names / quoting
|
||||
// differences.
|
||||
final String checkSql = "SELECT 1 FROM information_schema.columns WHERE " + schemaFilter
|
||||
+ " AND LOWER(table_name) = LOWER(?) AND LOWER(column_name) = LOWER(?) LIMIT 1;";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(checkSql)) {
|
||||
|
||||
ps.setString(1, getTableName());
|
||||
ps.setString(2, "voteid");
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
return; // exists
|
||||
}
|
||||
}
|
||||
|
||||
// Execute ALTER using same connection to avoid deadlock when pool size is
|
||||
// small.
|
||||
final String alter = "ALTER TABLE " + qi(getTableName()) + " ADD COLUMN " + qi("voteid") + " VARCHAR(36);";
|
||||
|
||||
try (Statement st = conn.createStatement()) {
|
||||
st.executeUpdate(alter);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
// don't hard fail startup
|
||||
logSevere("Failed to add voteid column to " + getTableName() + ": " + e.getMessage());
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- INSERT ----
|
||||
|
||||
public void insertVote(UUID voteId, String uuid, String playerName, String service, long time, boolean real,
|
||||
String text, String server) {
|
||||
|
||||
String sql = "INSERT INTO " + qi(getTableName()) + " (" + qi("uuid") + ", " + qi("voteid") + ", "
|
||||
+ qi("playerName") + ", " + qi("service") + ", " + qi("time") + ", " + qi("realVote") + ", "
|
||||
+ qi("text") + ", " + qi("server") + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?);";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(1, UUID.fromString(uuid));
|
||||
} else {
|
||||
ps.setString(1, uuid);
|
||||
}
|
||||
|
||||
ps.setString(2, voteId != null ? voteId.toString() : null);
|
||||
ps.setString(3, playerName);
|
||||
ps.setString(4, service);
|
||||
ps.setLong(5, time);
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setBoolean(6, real);
|
||||
} else {
|
||||
ps.setInt(6, real ? 1 : 0);
|
||||
}
|
||||
|
||||
ps.setString(7, text);
|
||||
ps.setString(8, server);
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- GET ----
|
||||
|
||||
public List<VoteRow> getAllVotes() {
|
||||
return selectVotes("SELECT * FROM " + qi(getTableName()) + ";", null);
|
||||
}
|
||||
|
||||
public List<VoteRow> getVotesForServer(String server) {
|
||||
return selectVotes("SELECT * FROM " + qi(getTableName()) + " WHERE " + qi("server") + " = ?;",
|
||||
new Object[] { server });
|
||||
}
|
||||
|
||||
public VoteRow getVoteById(int id) {
|
||||
List<VoteRow> list = selectVotes("SELECT * FROM " + qi(getTableName()) + " WHERE " + qi("id") + " = ?;",
|
||||
new Object[] { id });
|
||||
return list.isEmpty() ? null : list.get(0);
|
||||
}
|
||||
|
||||
public List<VoteRow> getVotesByUUID(String uuid) {
|
||||
String sql = "SELECT * FROM " + qi(getTableName()) + " WHERE " + qi("uuid") + " = ?;";
|
||||
Object[] params = (getDbType() == DbType.POSTGRESQL) ? new Object[] { UUID.fromString(uuid) }
|
||||
: new Object[] { uuid };
|
||||
return selectVotes(sql, params);
|
||||
}
|
||||
|
||||
public List<VoteRow> getVotesByPlayerName(String playerName) {
|
||||
return selectVotes("SELECT * FROM " + qi(getTableName()) + " WHERE " + qi("playerName") + " = ?;",
|
||||
new Object[] { playerName });
|
||||
}
|
||||
|
||||
public Set<String> getServers() {
|
||||
Set<String> servers = new HashSet<>();
|
||||
String sql = "SELECT DISTINCT " + qi("server") + " FROM " + qi(getTableName()) + " WHERE " + qi("server")
|
||||
+ " IS NOT NULL;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
|
||||
while (rs.next()) {
|
||||
String s = rs.getString(1);
|
||||
if (s != null) {
|
||||
servers.add(s);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
return servers;
|
||||
}
|
||||
|
||||
// ---- DELETE ----
|
||||
|
||||
public void removeVoteById(int id) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("id") + " = ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setInt(1, id);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVotesByServerAndUUID(String server, String uuid) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("server") + " = ? AND " + qi("uuid")
|
||||
+ " = ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
ps.setString(1, server);
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(2, UUID.fromString(uuid));
|
||||
} else {
|
||||
ps.setString(2, uuid);
|
||||
}
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVote(OfflineBungeeVote vote, String server) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("uuid") + " = ? AND " + qi("service")
|
||||
+ " = ? AND " + qi("time") + " = ? AND " + qi("server") + " = ?;";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
ps.setObject(1, UUID.fromString(vote.getUuid()));
|
||||
} else {
|
||||
ps.setString(1, vote.getUuid());
|
||||
}
|
||||
|
||||
ps.setString(2, vote.getService());
|
||||
ps.setLong(3, vote.getTime());
|
||||
ps.setString(4, server);
|
||||
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException | IllegalArgumentException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVotesByServer(String server) {
|
||||
String sql = "DELETE FROM " + qi(getTableName()) + " WHERE " + qi("server") + " = ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, server);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearTable() {
|
||||
try {
|
||||
if (getDbType() == DbType.POSTGRESQL) {
|
||||
new Query(mysql, "TRUNCATE TABLE " + qi(getTableName()) + " RESTART IDENTITY;").executeUpdate();
|
||||
} else {
|
||||
new Query(mysql, "TRUNCATE TABLE " + qi(getTableName()) + ";").executeUpdate();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Internals ----
|
||||
|
||||
private List<VoteRow> selectVotes(String sql, Object[] params) {
|
||||
List<VoteRow> list = new ArrayList<>();
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
|
||||
if (params != null) {
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
ps.setObject(i + 1, params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
VoteRow v = new VoteRow(rs.getInt("id"), rs.getString("voteid"), rs.getString("uuid"),
|
||||
rs.getString("playerName"), rs.getString("service"), rs.getLong("time"),
|
||||
(getDbType() == DbType.POSTGRESQL ? rs.getBoolean("realVote") : rs.getInt("realVote") == 1),
|
||||
rs.getString("text"), rs.getString("server"));
|
||||
list.add(v);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static class VoteRow {
|
||||
private final int id;
|
||||
private final String voteId;
|
||||
private final String uuid;
|
||||
private final String playerName;
|
||||
private final String service;
|
||||
private final long time;
|
||||
private final boolean realVote;
|
||||
private final String text;
|
||||
private final String server;
|
||||
|
||||
public VoteRow(int id, String voteId, String uuid, String playerName, String service, long time,
|
||||
boolean realVote, String text, String server) {
|
||||
this.id = id;
|
||||
this.voteId = voteId;
|
||||
this.uuid = uuid;
|
||||
this.playerName = playerName;
|
||||
this.service = service;
|
||||
this.time = time;
|
||||
this.realVote = realVote;
|
||||
this.text = text;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getVoteId() {
|
||||
return voteId;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return playerName;
|
||||
}
|
||||
|
||||
public String getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public boolean isRealVote() {
|
||||
return realVote;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
}
|
||||
}
|
||||
+522
@@ -0,0 +1,522 @@
|
||||
package com.bencodez.votingplugin.proxy.cache;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import com.bencodez.simpleapi.sql.mysql.MySQL;
|
||||
import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig;
|
||||
import com.bencodez.votingplugin.proxy.OfflineBungeeVote;
|
||||
import com.bencodez.votingplugin.timequeue.VoteTimeQueue;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public abstract class VoteCacheHandler {
|
||||
|
||||
@Getter
|
||||
private Queue<VoteTimeQueue> timeChangeQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
// uuid based
|
||||
private ConcurrentHashMap<String, ArrayList<OfflineBungeeVote>> cachedOnlineVotes = new ConcurrentHashMap<>();
|
||||
|
||||
// server based
|
||||
private ConcurrentHashMap<String, ArrayList<OfflineBungeeVote>> cachedVotes = new ConcurrentHashMap<>();
|
||||
|
||||
public boolean hasVotes(String server) {
|
||||
return cachedVotes.containsKey(server);
|
||||
}
|
||||
|
||||
public ArrayList<OfflineBungeeVote> getVotes(String server) {
|
||||
return cachedVotes.getOrDefault(server, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total cached votes for a UUID across: - UUID-based online vote cache -
|
||||
* Server-based vote cache
|
||||
*
|
||||
* @param uuid player UUID (string form)
|
||||
* @return total cached votes across all proxy caches
|
||||
*/
|
||||
public int getProxyCachedTotal(String uuid) {
|
||||
if (uuid == null || uuid.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
int total = 0;
|
||||
|
||||
// 1) UUID-based cache (fast lookup)
|
||||
ArrayList<OfflineBungeeVote> onlineVotes = cachedOnlineVotes.get(uuid);
|
||||
if (onlineVotes != null) {
|
||||
total += onlineVotes.size();
|
||||
}
|
||||
|
||||
// 2) Server-based caches (scan)
|
||||
for (ArrayList<OfflineBungeeVote> serverVotes : cachedVotes.values()) {
|
||||
for (OfflineBungeeVote vote : serverVotes) {
|
||||
if (vote != null && vote.getUuid() != null && vote.getUuid().equalsIgnoreCase(uuid)) {
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
public void addServerVote(String server, OfflineBungeeVote vote) {
|
||||
cachedVotes.putIfAbsent(server, new ArrayList<>());
|
||||
cachedVotes.get(server).add(vote);
|
||||
|
||||
if (useMySQL) {
|
||||
voteCacheTable.insertVote(vote.getVoteId(), vote.getUuid(), vote.getPlayerName(), vote.getService(),
|
||||
vote.getTime(), vote.isRealVote(), vote.getText(), server);
|
||||
} else {
|
||||
// IMPORTANT: index must come from JSON, not from cachedVotes (cache can be out
|
||||
// of sync with JSON)
|
||||
int idx = jsonStorage.getServerVotes(server).size();
|
||||
jsonStorage.addVote(server, idx, vote);
|
||||
jsonStorage.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVote(String server, String uuid) {
|
||||
if (cachedVotes.containsKey(server)) {
|
||||
ArrayList<OfflineBungeeVote> votes = cachedVotes.get(server);
|
||||
votes.removeIf(vote -> vote.getUuid().equals(uuid));
|
||||
|
||||
if (useMySQL) {
|
||||
voteCacheTable.removeVotesByServerAndUUID(server, uuid);
|
||||
} else {
|
||||
jsonStorage.removeServerVote(server, uuid);
|
||||
jsonStorage.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeVotes(String server) {
|
||||
cachedVotes.remove(server);
|
||||
if (useMySQL) {
|
||||
voteCacheTable.removeVotesByServer(server);
|
||||
} else {
|
||||
jsonStorage.removeServerVotes(server);
|
||||
jsonStorage.save();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasOnlineVotes(String uuid) {
|
||||
return cachedOnlineVotes.containsKey(uuid);
|
||||
}
|
||||
|
||||
public ArrayList<OfflineBungeeVote> getOnlineVotes(String uuid) {
|
||||
return cachedOnlineVotes.getOrDefault(uuid, new ArrayList<>());
|
||||
}
|
||||
|
||||
public void addOnlineVote(String uuid, OfflineBungeeVote vote) {
|
||||
cachedOnlineVotes.putIfAbsent(uuid, new ArrayList<>());
|
||||
cachedOnlineVotes.get(uuid).add(vote);
|
||||
|
||||
if (useMySQL) {
|
||||
onlineVoteCacheTable.insertVote(vote.getVoteId(), vote.getUuid(), vote.getPlayerName(), vote.getService(),
|
||||
vote.getTime(), vote.isRealVote(), vote.getText());
|
||||
} else {
|
||||
// IMPORTANT: index must come from JSON, not from cachedOnlineVotes (cache can
|
||||
// be out of sync with JSON)
|
||||
int idx = jsonStorage.getOnlineVotes(uuid).size();
|
||||
jsonStorage.addVoteOnline(uuid, idx, vote);
|
||||
jsonStorage.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeOnlineVotes(String uuid) {
|
||||
cachedOnlineVotes.remove(uuid);
|
||||
if (useMySQL) {
|
||||
onlineVoteCacheTable.removeVotesByUuid(uuid);
|
||||
} else {
|
||||
jsonStorage.removeOnlineVotes(uuid);
|
||||
jsonStorage.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void checkVoteCacheTime(int voteCacheTime) {
|
||||
long cTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
|
||||
// Collect expired online votes
|
||||
ArrayList<OfflineBungeeVote> expiredOnlineVotes = new ArrayList<>();
|
||||
for (Entry<String, ArrayList<OfflineBungeeVote>> entry : cachedOnlineVotes.entrySet()) {
|
||||
ArrayList<OfflineBungeeVote> votes = entry.getValue();
|
||||
for (OfflineBungeeVote vote : votes) {
|
||||
if (vote.getTime() + (voteCacheTime * 24 * 60 * 60 * 1000L) < cTime) {
|
||||
debug1("Removing vote from cache: " + vote.toString());
|
||||
expiredOnlineVotes.add(vote);
|
||||
}
|
||||
}
|
||||
}
|
||||
removeOnlineVotes(expiredOnlineVotes);
|
||||
|
||||
// Collect expired server votes
|
||||
ArrayList<OfflineBungeeVote> expiredServerVotes = new ArrayList<>();
|
||||
for (Entry<String, ArrayList<OfflineBungeeVote>> entry : cachedVotes.entrySet()) {
|
||||
ArrayList<OfflineBungeeVote> votes = entry.getValue();
|
||||
for (OfflineBungeeVote vote : votes) {
|
||||
if (vote.getTime() + (voteCacheTime * 24 * 60 * 60 * 1000L) < cTime) {
|
||||
debug1("Removing vote from cache: " + vote.toString());
|
||||
expiredServerVotes.add(vote);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String server : cachedVotes.keySet()) {
|
||||
removeServerVotes(server, expiredServerVotes);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveVoteCache() {
|
||||
if (useMySQL) {
|
||||
|
||||
if (!getTimeChangeQueue().isEmpty()) {
|
||||
for (VoteTimeQueue vote : getTimeChangeQueue()) {
|
||||
timedVoteCacheTable.insertTimedVote(vote.getName(), vote.getService(), vote.getTime());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!getTimeChangeQueue().isEmpty()) {
|
||||
int num = 0;
|
||||
for (VoteTimeQueue vote : getTimeChangeQueue()) {
|
||||
jsonStorage.addTimedVote(num, vote);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
jsonStorage.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void addTimeVoteToCache(VoteTimeQueue vote) {
|
||||
timeChangeQueue.add(vote);
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (useMySQL) {
|
||||
// Load votes from MySQL
|
||||
voteCacheTable.getAllVotes().forEach(voteRow -> {
|
||||
OfflineBungeeVote vote = new OfflineBungeeVote(voteRow.getVoteId(), voteRow.getPlayerName(),
|
||||
voteRow.getUuid(), voteRow.getService(), voteRow.getTime(), voteRow.isRealVote(),
|
||||
voteRow.getText());
|
||||
String server = voteRow.getServer();
|
||||
cachedVotes.putIfAbsent(server, new ArrayList<>());
|
||||
cachedVotes.get(server).add(vote);
|
||||
});
|
||||
|
||||
// Load online votes from MySQL
|
||||
onlineVoteCacheTable.getAllVotes().forEach(voteRow -> {
|
||||
OfflineBungeeVote vote = new OfflineBungeeVote(voteRow.getVoteId(), voteRow.getPlayerName(),
|
||||
voteRow.getUuid(), voteRow.getService(), voteRow.getTime(), voteRow.isRealVote(),
|
||||
voteRow.getText());
|
||||
String player = vote.getUuid();
|
||||
cachedOnlineVotes.putIfAbsent(player, new ArrayList<>());
|
||||
cachedOnlineVotes.get(player).add(vote);
|
||||
});
|
||||
|
||||
// Load timed votes from MySQL
|
||||
ArrayList<VoteTimeQueue> timedVotes = new ArrayList<>();
|
||||
timedVoteCacheTable.getAllVotes().forEach(timedVoteRow -> {
|
||||
VoteTimeQueue voteTimeQueue = new VoteTimeQueue(timedVoteRow.getPlayerName(), timedVoteRow.getService(),
|
||||
timedVoteRow.getTime());
|
||||
timedVotes.add(voteTimeQueue);
|
||||
});
|
||||
timeChangeQueue.addAll(timedVotes);
|
||||
|
||||
timedVoteCacheTable.clearTable();
|
||||
|
||||
} else {
|
||||
try {
|
||||
for (String key : jsonStorage.getTimedVoteCache()) {
|
||||
DataNode data = jsonStorage.getTimedVoteCache(key);
|
||||
|
||||
if (data != null && data.isObject()) {
|
||||
String name = data.has("Name") ? data.get("Name").asString() : "";
|
||||
String service = data.has("Service") ? data.get("Service").asString() : "";
|
||||
long time = data.has("Time") ? data.get("Time").asLong() : 0L;
|
||||
|
||||
getTimeChangeQueue().add(new VoteTimeQueue(name, service, time));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
for (String server : jsonStorage.getServers()) {
|
||||
ArrayList<OfflineBungeeVote> votes = new ArrayList<>();
|
||||
for (String num : jsonStorage.getServerVotes(server)) {
|
||||
DataNode data = jsonStorage.getServerVotes(server, num);
|
||||
|
||||
if (data != null && data.isObject()) {
|
||||
|
||||
String name = data.has("Name") ? data.get("Name").asString() : "";
|
||||
String uuid = data.has("UUID") ? data.get("UUID").asString() : "";
|
||||
String service = data.has("Service") ? data.get("Service").asString() : "";
|
||||
long time = data.has("Time") ? data.get("Time").asLong() : 0L;
|
||||
boolean real = data.has("Real") && data.get("Real").asBoolean();
|
||||
String text = data.has("Text") ? data.get("Text").asString() : "";
|
||||
String voteId = data.has("VoteId") ? data.get("VoteId").asString() : "";
|
||||
|
||||
votes.add(new OfflineBungeeVote(voteId, name, uuid, service, time, real, text));
|
||||
}
|
||||
}
|
||||
cachedVotes.put(server, votes);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
for (String player : jsonStorage.getPlayers()) {
|
||||
ArrayList<OfflineBungeeVote> votes = new ArrayList<>();
|
||||
for (String num : jsonStorage.getOnlineVotes(player)) {
|
||||
DataNode data = jsonStorage.getOnlineVotes(player, num);
|
||||
|
||||
if (data != null && data.isObject()) {
|
||||
|
||||
String name = data.has("Name") ? data.get("Name").asString() : "";
|
||||
String uuid = data.has("UUID") ? data.get("UUID").asString() : "";
|
||||
String service = data.has("Service") ? data.get("Service").asString() : "";
|
||||
long time = data.has("Time") ? data.get("Time").asLong() : 0L;
|
||||
boolean real = data.has("Real") && data.get("Real").asBoolean();
|
||||
String text = data.has("Text") ? data.get("Text").asString() : "";
|
||||
String voteId = data.has("VoteId") ? data.get("VoteId").asString() : "";
|
||||
|
||||
votes.add(new OfflineBungeeVote(voteId, name, uuid, service, time, real, text));
|
||||
}
|
||||
}
|
||||
cachedOnlineVotes.put(player, votes);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// log vote cache load summary
|
||||
|
||||
debug1("Loaded " + cachedVotes.size() + " server vote caches.");
|
||||
int totalServerVotes = cachedVotes.values().stream().mapToInt(ArrayList::size).sum();
|
||||
debug1("Loaded " + totalServerVotes + " total server votes.");
|
||||
|
||||
debug1("Loaded " + cachedOnlineVotes.size() + " online vote caches.");
|
||||
int totalOnlineVotes = cachedOnlineVotes.values().stream().mapToInt(ArrayList::size).sum();
|
||||
debug1("Loaded " + totalOnlineVotes + " total online votes.");
|
||||
|
||||
debug1("Loaded " + timeChangeQueue.size() + " timed votes.");
|
||||
|
||||
}
|
||||
|
||||
private final boolean useMySQL;
|
||||
private ProxyVoteCacheTable voteCacheTable;
|
||||
private ProxyTimedVoteCacheTable timedVoteCacheTable;
|
||||
private ProxyOnlineVoteCacheTable onlineVoteCacheTable;
|
||||
|
||||
private IVoteCache jsonStorage;
|
||||
|
||||
public abstract void logInfo1(String msg);
|
||||
|
||||
public abstract void logSevere1(String msg);
|
||||
|
||||
public abstract void debug1(Exception e);
|
||||
|
||||
public abstract void debug1(Throwable e);
|
||||
|
||||
public abstract void debug1(String msg);
|
||||
|
||||
public VoteCacheHandler(MysqlConfig mysqlConfig, boolean useMySQL, boolean useExistingConnection, MySQL mysql,
|
||||
boolean debug, IVoteCache jsonStorage) {
|
||||
this.useMySQL = useMySQL;
|
||||
|
||||
if (useMySQL) {
|
||||
if (useExistingConnection) {
|
||||
voteCacheTable = new ProxyVoteCacheTable(mysql, mysqlConfig.getTablePrefix(), debug) {
|
||||
@Override
|
||||
public void logSevere(String string) {
|
||||
logSevere1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
logInfo1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Throwable t) {
|
||||
if (debug)
|
||||
debug1(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text) {
|
||||
debug1(text);
|
||||
}
|
||||
};
|
||||
|
||||
timedVoteCacheTable = new ProxyTimedVoteCacheTable(mysql, mysqlConfig.getTablePrefix(), debug) {
|
||||
@Override
|
||||
public void logSevere(String string) {
|
||||
logSevere1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
logInfo1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Throwable t) {
|
||||
if (debug)
|
||||
debug1(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text) {
|
||||
debug1(text);
|
||||
}
|
||||
};
|
||||
|
||||
onlineVoteCacheTable = new ProxyOnlineVoteCacheTable(mysql, mysqlConfig.getTablePrefix(), debug) {
|
||||
@Override
|
||||
public void logSevere(String string) {
|
||||
logSevere1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
logInfo1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Throwable t) {
|
||||
if (debug)
|
||||
debug1(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text) {
|
||||
debug1(text);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
voteCacheTable = new ProxyVoteCacheTable(mysqlConfig, debug) {
|
||||
@Override
|
||||
public void logSevere(String string) {
|
||||
logSevere1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
logInfo1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Throwable t) {
|
||||
if (debug)
|
||||
debug1(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text) {
|
||||
debug1(text);
|
||||
}
|
||||
};
|
||||
|
||||
timedVoteCacheTable = new ProxyTimedVoteCacheTable(voteCacheTable.getMysql(),
|
||||
mysqlConfig.getTablePrefix(), debug) {
|
||||
@Override
|
||||
public void logSevere(String string) {
|
||||
logSevere1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
logInfo1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Throwable t) {
|
||||
if (debug)
|
||||
debug1(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text) {
|
||||
debug1(text);
|
||||
}
|
||||
};
|
||||
|
||||
onlineVoteCacheTable = new ProxyOnlineVoteCacheTable(voteCacheTable.getMysql(),
|
||||
mysqlConfig.getTablePrefix(), debug) {
|
||||
@Override
|
||||
public void logSevere(String string) {
|
||||
logSevere1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
logInfo1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Throwable t) {
|
||||
if (debug)
|
||||
debug1(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text) {
|
||||
debug1(text);
|
||||
}
|
||||
};
|
||||
}
|
||||
} else {
|
||||
this.jsonStorage = jsonStorage;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getCachedVotesServers() {
|
||||
return cachedVotes.keySet().toArray(new String[0]);
|
||||
}
|
||||
|
||||
public void removeServerVotes(String server, ArrayList<OfflineBungeeVote> removed) {
|
||||
for (OfflineBungeeVote vote : removed) {
|
||||
for (Map.Entry<String, ArrayList<OfflineBungeeVote>> entry : cachedVotes.entrySet()) {
|
||||
if (entry.getKey().equals(server)) {
|
||||
entry.getValue().removeIf(v -> v.getUuid().equals(vote.getUuid())
|
||||
&& v.getService().equals(vote.getService()) && v.getTime() == vote.getTime());
|
||||
}
|
||||
}
|
||||
if (useMySQL) {
|
||||
voteCacheTable.removeVote(vote, server);
|
||||
} else {
|
||||
jsonStorage.removeVote(server, vote);
|
||||
jsonStorage.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeOnlineVotes(ArrayList<OfflineBungeeVote> removed) {
|
||||
for (OfflineBungeeVote vote : removed) {
|
||||
for (Map.Entry<String, ArrayList<OfflineBungeeVote>> entry : cachedOnlineVotes.entrySet()) {
|
||||
entry.getValue().removeIf(v -> v.getUuid().equals(vote.getUuid())
|
||||
&& v.getService().equals(vote.getService()) && v.getTime() == vote.getTime());
|
||||
}
|
||||
if (useMySQL) {
|
||||
onlineVoteCacheTable.removeVote(vote);
|
||||
} else {
|
||||
jsonStorage.removeOnlineVote(vote);
|
||||
jsonStorage.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.bencodez.votingplugin.proxy.cache.nonvoted;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface INonVotedPlayersStorage {
|
||||
|
||||
/** Insert or update a player entry. */
|
||||
void upsertPlayer(String uuid, String playerName, long lastTime);
|
||||
|
||||
/** Returns UUID for the player or empty string if not found. */
|
||||
String getUuidByPlayerName(String playerName);
|
||||
|
||||
/** Remove a player from storage. */
|
||||
void removeByPlayerName(String playerName);
|
||||
|
||||
/** Iterate snapshot of all entries. */
|
||||
void forEach(Consumer<NonVotedPlayerEntry> consumer);
|
||||
|
||||
/** Close resources if needed (MySQL); no-op for JSON. */
|
||||
void close();
|
||||
|
||||
final class NonVotedPlayerEntry {
|
||||
private final String playerName;
|
||||
private final String uuid;
|
||||
private final long lastTime;
|
||||
|
||||
public NonVotedPlayerEntry(String playerName, String uuid, long lastTime) {
|
||||
this.playerName = playerName;
|
||||
this.uuid = uuid;
|
||||
this.lastTime = lastTime;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return playerName;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public long getLastTime() {
|
||||
return lastTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.bencodez.votingplugin.proxy.cache.nonvoted;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.bencodez.simpleapi.sql.mysql.MySQL;
|
||||
import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig;
|
||||
|
||||
public abstract class MySQLNonVotedPlayersStorage extends ProxyNonVotedPlayersTable
|
||||
implements INonVotedPlayersStorage {
|
||||
|
||||
private final boolean ownsConnection;
|
||||
|
||||
public MySQLNonVotedPlayersStorage(MySQL existingMysql, String tablePrefix, boolean debug) {
|
||||
super(existingMysql, tablePrefix, debug);
|
||||
this.ownsConnection = false;
|
||||
}
|
||||
|
||||
public MySQLNonVotedPlayersStorage(MysqlConfig config, boolean debug) {
|
||||
super(config, debug);
|
||||
this.ownsConnection = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upsertPlayer(String uuid, String playerName, long lastTime) {
|
||||
super.upsertPlayer(uuid, playerName, lastTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuidByPlayerName(String playerName) {
|
||||
return super.getUuidByPlayerName(playerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByPlayerName(String playerName) {
|
||||
super.removeByPlayerName(playerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<NonVotedPlayerEntry> consumer) {
|
||||
List<NonVotedPlayerRow> rows = getAllRows();
|
||||
for (NonVotedPlayerRow row : rows) {
|
||||
consumer.accept(new NonVotedPlayerEntry(
|
||||
row.getPlayerName(),
|
||||
row.getUuid(),
|
||||
row.getLastTime()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (ownsConnection) {
|
||||
getMysql().disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+132
@@ -0,0 +1,132 @@
|
||||
package com.bencodez.votingplugin.proxy.cache.nonvoted;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.bencodez.simpleapi.sql.mysql.MySQL;
|
||||
import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig;
|
||||
|
||||
public abstract class NonVotedPlayersCache {
|
||||
|
||||
private INonVotedPlayersStorage storage;
|
||||
|
||||
// 5 days in millis (same as your current logic)
|
||||
private static final long MAX_AGE_MILLIS = TimeUnit.DAYS.toMillis(5);
|
||||
|
||||
public NonVotedPlayersCache(MysqlConfig mysqlConfig, boolean useMysql, boolean useExistingConnection, MySQL mysql,
|
||||
INonVotedPlayersStorage storage, boolean debug) {
|
||||
if (useMysql) {
|
||||
if (useExistingConnection) {
|
||||
this.storage = new MySQLNonVotedPlayersStorage(mysql, mysqlConfig.getTablePrefix(), debug) {
|
||||
|
||||
@Override
|
||||
public void logSevere(String string) {
|
||||
logSevere1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
logInfo1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Exception e) {
|
||||
if (debug)
|
||||
debug1(e);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
this.storage = new MySQLNonVotedPlayersStorage(mysqlConfig, debug) {
|
||||
|
||||
@Override
|
||||
public void logSevere(String string) {
|
||||
logSevere1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String string) {
|
||||
logInfo1(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Exception e) {
|
||||
if (debug)
|
||||
debug1(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} else {
|
||||
this.storage = storage;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract boolean userExists(String uuid);
|
||||
|
||||
/**
|
||||
* Add a player directly by uuid + name, only if they don't already have votes.
|
||||
*/
|
||||
public void addPlayer(String uuid, String playerName) {
|
||||
if (uuid == null || uuid.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!userExists(uuid)) {
|
||||
debug1("Adding nonvotedplayer: " + playerName + " / " + uuid);
|
||||
storage.upsertPlayer(uuid, playerName, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Set<String> getAllUUIDs();
|
||||
|
||||
/**
|
||||
* Cleanup: - remove entries older than 5 days - remove entries whose UUID has
|
||||
* now appeared in proxy MySQL - remove entries with empty/invalid UUID
|
||||
*/
|
||||
public void check() {
|
||||
final long now = System.currentTimeMillis();
|
||||
Set<String> uuids = getAllUUIDs();
|
||||
|
||||
storage.forEach(entry -> {
|
||||
boolean remove = false;
|
||||
|
||||
long time = entry.getLastTime();
|
||||
// too old?
|
||||
if ((now - time) > MAX_AGE_MILLIS) {
|
||||
remove = true;
|
||||
} else {
|
||||
String uuid = entry.getUuid();
|
||||
if (uuid == null || uuid.isEmpty()) {
|
||||
remove = true;
|
||||
} else if (uuids.contains(uuid)) {
|
||||
// player has now voted in the main proxy MySQL
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (remove) {
|
||||
debug1("Removing nonvotedplayer: " + entry.getPlayerName());
|
||||
storage.removeByPlayerName(entry.getPlayerName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the UUID for a cached non-voted player, or empty string if not
|
||||
* present.
|
||||
*/
|
||||
public String getUUID(String playerName) {
|
||||
return storage.getUuidByPlayerName(playerName);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
storage.close();
|
||||
}
|
||||
|
||||
public abstract void logInfo1(String msg);
|
||||
|
||||
public abstract void logSevere1(String msg);
|
||||
|
||||
public abstract void debug1(Exception e);
|
||||
|
||||
public abstract void debug1(String msg);
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
package com.bencodez.votingplugin.proxy.cache.nonvoted;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bencodez.simpleapi.sql.mysql.MySQL;
|
||||
import com.bencodez.simpleapi.sql.mysql.config.MysqlConfig;
|
||||
import com.bencodez.simpleapi.sql.mysql.queries.Query;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public abstract class ProxyNonVotedPlayersTable {
|
||||
|
||||
@Getter
|
||||
private final MySQL mysql;
|
||||
private final String tableName;
|
||||
|
||||
public abstract void logSevere(String msg);
|
||||
|
||||
public abstract void logInfo(String msg);
|
||||
|
||||
public abstract void debug(Exception e);
|
||||
|
||||
public ProxyNonVotedPlayersTable(MySQL existingMysql, String tablePrefix, boolean debug) {
|
||||
this.mysql = existingMysql;
|
||||
this.tableName = (tablePrefix != null ? tablePrefix : "") + "votingplugin_nonvotedplayers";
|
||||
createTableIfNeeded();
|
||||
}
|
||||
|
||||
public ProxyNonVotedPlayersTable(MysqlConfig config, boolean debug) {
|
||||
String prefix = config.getTablePrefix() != null ? config.getTablePrefix() : "";
|
||||
this.tableName = prefix + "votingplugin_nonvotedplayers";
|
||||
|
||||
this.mysql = new MySQL(config.getMaxThreads()) {
|
||||
@Override
|
||||
public void debug(SQLException e) {
|
||||
if (debug) {
|
||||
ProxyNonVotedPlayersTable.this.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void severe(String msg) {
|
||||
logSevere(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String msg) {
|
||||
if (debug) {
|
||||
logInfo("MYSQL DEBUG: " + msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!mysql.connect(config)) {
|
||||
logSevere("Failed to connect to MySQL for non-voted players cache!");
|
||||
}
|
||||
try {
|
||||
new Query(mysql, "USE `" + config.getDatabase() + "`;").executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
logSevere("Failed to select database: " + config.getDatabase());
|
||||
debug(e);
|
||||
}
|
||||
|
||||
createTableIfNeeded();
|
||||
}
|
||||
|
||||
private void createTableIfNeeded() {
|
||||
String sql = "CREATE TABLE IF NOT EXISTS `" + tableName + "` (" + "id INT AUTO_INCREMENT PRIMARY KEY,"
|
||||
+ "uuid VARCHAR(36) NOT NULL," + "playerName VARCHAR(100) NOT NULL," + "`lastTime` BIGINT NOT NULL,"
|
||||
+ "UNIQUE KEY uniq_playerName (`playerName`)," + "KEY idx_uuid (`uuid`),"
|
||||
+ "KEY idx_lastTime (`lastTime`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
|
||||
try {
|
||||
new Query(mysql, sql).executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void upsertPlayer(String uuid, String playerName, long lastTime) {
|
||||
String sql = "INSERT INTO `" + tableName + "` (uuid, playerName, lastTime) " + "VALUES (?, ?, ?) "
|
||||
+ "ON DUPLICATE KEY UPDATE uuid = VALUES(uuid), lastTime = VALUES(lastTime);";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, uuid);
|
||||
ps.setString(2, playerName);
|
||||
ps.setLong(3, lastTime);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getUuidByPlayerName(String playerName) {
|
||||
String sql = "SELECT uuid FROM `" + tableName + "` WHERE playerName = ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
String uuid = rs.getString("uuid");
|
||||
return uuid != null ? uuid : "";
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public void removeByPlayerName(String playerName) {
|
||||
String sql = "DELETE FROM `" + tableName + "` WHERE playerName = ?;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, playerName);
|
||||
ps.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<NonVotedPlayerRow> getAllRows() {
|
||||
List<NonVotedPlayerRow> list = new ArrayList<>();
|
||||
String sql = "SELECT id, uuid, playerName, lastTime FROM `" + tableName + "`;";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sql);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
list.add(new NonVotedPlayerRow(rs.getInt("id"), rs.getString("uuid"), rs.getString("playerName"),
|
||||
rs.getLong("lastTime")));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
try {
|
||||
new Query(mysql, "TRUNCATE TABLE `" + tableName + "`;").executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class NonVotedPlayerRow {
|
||||
private final int id;
|
||||
private final String uuid;
|
||||
private final String playerName;
|
||||
private final long lastTime;
|
||||
|
||||
public NonVotedPlayerRow(int id, String uuid, String playerName, long lastTime) {
|
||||
this.id = id;
|
||||
this.uuid = uuid;
|
||||
this.playerName = playerName;
|
||||
this.lastTime = lastTime;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return playerName;
|
||||
}
|
||||
|
||||
public long getLastTime() {
|
||||
return lastTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
+161
-121
@@ -1,35 +1,37 @@
|
||||
// File: com/bencodez/votingplugin/proxy/multiproxy/MultiProxyHandler.java
|
||||
package com.bencodez.votingplugin.proxy.multiproxy;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.bencodez.simpleapi.encryption.EncryptionHandler;
|
||||
import com.bencodez.simpleapi.servercomm.codec.JsonEnvelope;
|
||||
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.votingplugin.proxy.BungeeMessageData;
|
||||
import com.bencodez.votingplugin.proxy.VoteTotalsSnapshot;
|
||||
import com.bencodez.votingplugin.proxy.VotingPluginWire;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public abstract class MultiProxyHandler {
|
||||
private HashMap<String, ClientHandler> multiproxyClientHandles;
|
||||
|
||||
private SocketHandler multiproxySocketHandler;
|
||||
|
||||
@Getter
|
||||
private RedisHandler multiProxyRedis;
|
||||
|
||||
public MultiProxyHandler() {
|
||||
|
||||
}
|
||||
|
||||
public abstract void addNonVotedPlayerCache(String string, String string2);
|
||||
public abstract void addNonVotedPlayerCache(String uuid, String playerName);
|
||||
|
||||
public abstract void clearVote(String string);
|
||||
public abstract void clearVote(String uuid);
|
||||
|
||||
public void close() {
|
||||
if (multiproxySocketHandler != null) {
|
||||
@@ -53,6 +55,8 @@ public abstract class MultiProxyHandler {
|
||||
|
||||
public abstract int getMultiProxyRedisPort();
|
||||
|
||||
public abstract int getMultiProxyRedisDbIndex();
|
||||
|
||||
public abstract boolean getMultiProxyRedisUseExistingConnection();
|
||||
|
||||
public abstract String getMultiProxyServerName();
|
||||
@@ -79,148 +83,184 @@ public abstract class MultiProxyHandler {
|
||||
|
||||
public abstract String getVersion();
|
||||
|
||||
public abstract void logInfo(String msg);
|
||||
|
||||
public abstract void runAsnc(Runnable runnable);
|
||||
|
||||
public abstract void setEncryptionHandler(EncryptionHandler encryptionHandler);
|
||||
|
||||
public abstract void triggerVote(String player, String service, boolean realVote, boolean timeQueue, long queueTime,
|
||||
VoteTotalsSnapshot text, String uuid);
|
||||
|
||||
public void loadMultiProxySupport() {
|
||||
if (getMultiProxySupportEnabled()) {
|
||||
if (getMultiProxyMethod().equals(MultiProxyMethod.SOCKETS)) {
|
||||
if (getEncryptionHandler() == null) {
|
||||
setEncryptionHandler(new EncryptionHandler("VotingPlugin",new File(getPluginDataFolder(), "secretkey.key")));
|
||||
}
|
||||
if (!getMultiProxySupportEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (multiproxySocketHandler != null) {
|
||||
multiproxySocketHandler.closeConnection();
|
||||
multiproxySocketHandler = null;
|
||||
}
|
||||
multiproxySocketHandler = new SocketHandler(getVersion(), getMultiProxySocketHostHost(),
|
||||
getMultiProxySocketHostPort(), getEncryptionHandler(), getDebug()) {
|
||||
if (getMultiProxyMethod().equals(MultiProxyMethod.SOCKETS)) {
|
||||
if (getEncryptionHandler() == null) {
|
||||
setEncryptionHandler(
|
||||
new EncryptionHandler("VotingPlugin", new File(getPluginDataFolder(), "secretkey.key")));
|
||||
}
|
||||
|
||||
if (multiproxySocketHandler != null) {
|
||||
multiproxySocketHandler.closeConnection();
|
||||
multiproxySocketHandler = null;
|
||||
}
|
||||
|
||||
multiproxySocketHandler = new SocketHandler(getVersion(), getMultiProxySocketHostHost(),
|
||||
getMultiProxySocketHostPort(), getEncryptionHandler(), getDebug()) {
|
||||
|
||||
@Override
|
||||
public void log(String str) {
|
||||
logInfo(str);
|
||||
}
|
||||
};
|
||||
|
||||
multiproxySocketHandler.add(new SocketReceiver() {
|
||||
@Override
|
||||
public void onReceiveEnvelope(JsonEnvelope envelope) {
|
||||
handleEnvelope(envelope);
|
||||
}
|
||||
});
|
||||
|
||||
multiproxyClientHandles = new HashMap<>();
|
||||
for (String s : getMultiProxyServers()) {
|
||||
MultiProxyServerSocketConfiguration d = getMultiProxyServersConfiguration(s);
|
||||
multiproxyClientHandles.put(s,
|
||||
new ClientHandler(d.getHost(), d.getPort(), getEncryptionHandler(), getDebug()));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (getMultiProxyRedisUseExistingConnection() && getRedisHandler() != null) {
|
||||
multiProxyRedis = getRedisHandler();
|
||||
} else {
|
||||
multiProxyRedis = new RedisHandler(getMultiProxyRedisHost(), getMultiProxyRedisPort(),
|
||||
getMultiProxyUsername(), getMultiProxyPassword(), getMultiProxyRedisDbIndex()) {
|
||||
@Override
|
||||
public void log(String str) {
|
||||
logInfo(str);
|
||||
public void debug(String message) {
|
||||
if (getDebug()) {
|
||||
logInfo("MultiProxyRedis: " + message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
multiproxySocketHandler.add(new SocketReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(String[] data) {
|
||||
if (data.length > 0) {
|
||||
if (data[0].equalsIgnoreCase("Status")) {
|
||||
logInfo("Multi-proxy status message received");
|
||||
} else if (data[0].equalsIgnoreCase("ClearVote")) {
|
||||
clearVote(data[2]);
|
||||
if (getPrimaryServer()) {
|
||||
sendMultiProxyServerMessage("ClearVotePrimary", data[1], data[2]);
|
||||
}
|
||||
} else if (data[0].equalsIgnoreCase("ClearVotePrimary")) {
|
||||
clearVote(data[2]);
|
||||
} else if (data[0].equalsIgnoreCase("login")) {
|
||||
addNonVotedPlayerCache(data[1], data[2]);
|
||||
// nonVotedPlayersCache.addPlayer(data[1], data[2]);
|
||||
}
|
||||
}
|
||||
if (data.length > 8) {
|
||||
if (data[0].equalsIgnoreCase("Vote")) {
|
||||
triggerVote(data[2], data[3], Boolean.valueOf(data[7]), true, 0,
|
||||
new BungeeMessageData(data[8]), data[1]);
|
||||
} else if (data[0].equalsIgnoreCase("VoteOnline")) {
|
||||
triggerVote(data[2], data[3], Boolean.valueOf(data[7]), true, 0,
|
||||
new BungeeMessageData(data[8]), data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
multiproxyClientHandles = new HashMap<>();
|
||||
for (String s : getMultiProxyServers()) {
|
||||
MultiProxyServerSocketConfiguration d = getMultiProxyServersConfiguration(s);
|
||||
multiproxyClientHandles.put(s,
|
||||
new ClientHandler(d.getHost(), d.getPort(), getEncryptionHandler(), getDebug()));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (getMultiProxyRedisUseExistingConnection() && getRedisHandler() != null) {
|
||||
multiProxyRedis = getRedisHandler();
|
||||
} else {
|
||||
multiProxyRedis = new RedisHandler(getMultiProxyRedisHost(), getMultiProxyRedisPort(),
|
||||
getMultiProxyUsername(), getMultiProxyPassword()) {
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
if (getDebug()) {
|
||||
logInfo("MultiProxyRedis: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String channel, String[] data) {
|
||||
if (data.length > 0) {
|
||||
if (data[0].equalsIgnoreCase("Status")) {
|
||||
logInfo("Multi-proxy status message received");
|
||||
} else if (data[0].equalsIgnoreCase("ClearVote")) {
|
||||
clearVote(data[2]);
|
||||
if (getPrimaryServer()) {
|
||||
sendMultiProxyServerMessage("ClearVotePrimary", data[1], data[2]);
|
||||
}
|
||||
} else if (data[0].equalsIgnoreCase("ClearVotePrimary")) {
|
||||
clearVote(data[2]);
|
||||
} else if (data[0].equalsIgnoreCase("login")) {
|
||||
addNonVotedPlayerCache(data[1], data[2]);
|
||||
// nonVotedPlayersCache.addPlayer(data[1], data[2]);
|
||||
}
|
||||
}
|
||||
if (data.length > 8) {
|
||||
if (data[0].equalsIgnoreCase("Vote")) {
|
||||
triggerVote(data[2], data[3], Boolean.valueOf(data[7]), true, 0,
|
||||
new BungeeMessageData(data[8]), data[1]);
|
||||
} else if (data[0].equalsIgnoreCase("VoteOnline")) {
|
||||
triggerVote(data[2], data[3], Boolean.valueOf(data[7]), true, 0,
|
||||
new BungeeMessageData(data[8]), data[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
runAsnc(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
multiProxyRedis.loadListener(
|
||||
new RedisListener(multiProxyRedis, "VotingPluginProxy_" + getMultiProxyServerName()));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
logInfo("Loaded multi-proxy support: " + getMultiProxyMethod().toString());
|
||||
|
||||
runAsnc(() -> {
|
||||
RedisListener listener = multiProxyRedis.createEnvelopeListener(
|
||||
"VotingPluginProxy_" + getMultiProxyServerName(), (ch, env) -> handleEnvelope(env));
|
||||
multiProxyRedis.loadListener(listener);
|
||||
});
|
||||
}
|
||||
|
||||
logInfo("Loaded multi-proxy support: " + getMultiProxyMethod().toString());
|
||||
}
|
||||
|
||||
public void login(String uuid, String playerName) {
|
||||
if (!getMultiProxySupportEnabled() || getPrimaryServer()) {
|
||||
return;
|
||||
}
|
||||
sendMultiProxyServerMessage("Login", uuid, playerName);
|
||||
sendMultiProxyEnvelope(VotingPluginWire.login(playerName, uuid, getMultiProxyServerName()));
|
||||
}
|
||||
|
||||
public abstract void logInfo(String msg);
|
||||
public void sendClearVote(String uuid, String playerName) {
|
||||
if (!getMultiProxySupportEnabled()) {
|
||||
return;
|
||||
}
|
||||
sendMultiProxyEnvelope(VotingPluginWire.clearVote(uuid, playerName, getMultiProxyServerName()));
|
||||
}
|
||||
|
||||
public abstract void runAsnc(Runnable runnable);
|
||||
public void sendStatus() {
|
||||
if (!getMultiProxySupportEnabled()) {
|
||||
return;
|
||||
}
|
||||
sendMultiProxyEnvelope(VotingPluginWire.status(getMultiProxyServerName()));
|
||||
}
|
||||
|
||||
public void sendMultiProxyServerMessage(String... messageData) {
|
||||
public void sendMultiProxyEnvelope(JsonEnvelope envelope) {
|
||||
if (envelope == null) {
|
||||
return;
|
||||
}
|
||||
if (getMultiProxyMethod().equals(MultiProxyMethod.SOCKETS)) {
|
||||
if (multiproxyClientHandles == null) {
|
||||
return;
|
||||
}
|
||||
for (ClientHandler h : multiproxyClientHandles.values()) {
|
||||
h.sendMessage(messageData);
|
||||
h.sendEnvelope(envelope);
|
||||
}
|
||||
} else if (getMultiProxyMethod().equals(MultiProxyMethod.REDIS)) {
|
||||
if (multiProxyRedis == null) {
|
||||
return;
|
||||
}
|
||||
for (String server : getProxyServers()) {
|
||||
multiProxyRedis.sendMessage("VotingPluginProxy_" + server, messageData);
|
||||
multiProxyRedis.publishEnvelope("VotingPluginProxy_" + server, envelope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void setEncryptionHandler(EncryptionHandler encryptionHandler);
|
||||
private void handleEnvelope(JsonEnvelope envelope) {
|
||||
if (envelope == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
public abstract void triggerVote(String player, String service, boolean realVote, boolean timeQueue, long queueTime,
|
||||
BungeeMessageData text, String uuid);
|
||||
final String sub = envelope.getSubChannel() == null ? "" : envelope.getSubChannel();
|
||||
|
||||
Map<String, String> f = envelope.getFields();
|
||||
if (f == null) {
|
||||
f = new HashMap<>();
|
||||
}
|
||||
|
||||
if (sub.equalsIgnoreCase(VotingPluginWire.SUB_STATUS)) {
|
||||
logInfo("Multi-proxy status message received");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sub.equalsIgnoreCase(VotingPluginWire.SUB_CLEAR_VOTE)) {
|
||||
final String uuid = f.getOrDefault(VotingPluginWire.K_UUID, "");
|
||||
final String player = f.getOrDefault(VotingPluginWire.K_PLAYER, "");
|
||||
final String server = f.getOrDefault(VotingPluginWire.K_SERVER, "");
|
||||
|
||||
if (!uuid.isEmpty()) {
|
||||
clearVote(uuid);
|
||||
if (getPrimaryServer()) {
|
||||
sendMultiProxyEnvelope(VotingPluginWire.clearVotePrimary(uuid, player, server));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (sub.equalsIgnoreCase(VotingPluginWire.SUB_CLEAR_VOTE_PRIMARY)) {
|
||||
final String uuid = f.getOrDefault(VotingPluginWire.K_UUID, "");
|
||||
if (!uuid.isEmpty()) {
|
||||
clearVote(uuid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (sub.equalsIgnoreCase(VotingPluginWire.SUB_LOGIN)) {
|
||||
final String player = f.getOrDefault(VotingPluginWire.K_PLAYER, "");
|
||||
final String uuid = f.getOrDefault(VotingPluginWire.K_UUID, "");
|
||||
if (!player.isEmpty() && !uuid.isEmpty()) {
|
||||
addNonVotedPlayerCache(uuid, player);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (sub.equalsIgnoreCase(VotingPluginWire.SUB_VOTE) || sub.equalsIgnoreCase(VotingPluginWire.SUB_VOTE_ONLINE)) {
|
||||
final String player = f.getOrDefault(VotingPluginWire.K_PLAYER, "");
|
||||
final String uuid = f.getOrDefault(VotingPluginWire.K_UUID, "");
|
||||
final String service = f.getOrDefault(VotingPluginWire.K_SERVICE, "");
|
||||
final String totals = f.getOrDefault(VotingPluginWire.K_TOTALS, "");
|
||||
final boolean realVote = Boolean.parseBoolean(f.getOrDefault(VotingPluginWire.K_REAL_VOTE, "false"));
|
||||
|
||||
if (!player.isEmpty() && !uuid.isEmpty() && !service.isEmpty()) {
|
||||
triggerVote(player, service, realVote, true, 0L, VoteTotalsSnapshot.parseStorage(totals), uuid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (getDebug()) {
|
||||
logInfo("MultiProxy ignored subchannel: " + sub + " fields=" + f);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package com.bencodez.votingplugin.proxy.multiproxy;
|
||||
|
||||
import ninja.leaping.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
|
||||
public class MultiProxyServerSocketConfigurationVelocity implements MultiProxyServerSocketConfiguration {
|
||||
|
||||
@@ -10,8 +10,8 @@ public class MultiProxyServerSocketConfigurationVelocity implements MultiProxySe
|
||||
|
||||
public MultiProxyServerSocketConfigurationVelocity(String s, ConfigurationNode config) {
|
||||
server = s;
|
||||
host = config.getNode("Host").getString("0.0.0.0");
|
||||
port = config.getNode("Port").getInt(1298);
|
||||
host = config.node("Host").getString("0.0.0.0");
|
||||
port = config.node("Port").getInt(1298);
|
||||
|
||||
}
|
||||
|
||||
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
package com.bencodez.votingplugin.proxy.velocity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.bencodez.simpleapi.file.velocity.VelocityJSONFile;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
|
||||
public class NonVotedPlayersCache extends VelocityJSONFile {
|
||||
|
||||
private VotingPluginVelocity plugin;
|
||||
|
||||
public NonVotedPlayersCache(File file, VotingPluginVelocity plugin) {
|
||||
super(file);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void addPlayer(Player player) {
|
||||
if (!plugin.getVotingPluginProxy().getProxyMySQL().containsKeyQuery(player.getUniqueId().toString())) {
|
||||
addPlayer(player.getUniqueId().toString(), player.getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
public void addPlayer(String uuid, String playerName) {
|
||||
getNode("NonVotedPlayers", playerName, "UUID").setValue(uuid);
|
||||
getNode("NonVotedPlayers", playerName, "LastTime").setValue(System.currentTimeMillis());
|
||||
save();
|
||||
}
|
||||
|
||||
public void addPlayerCheck(String uuid, String playerName) {
|
||||
if (!plugin.getVotingPluginProxy().getProxyMySQL().containsKeyQuery(uuid)) {
|
||||
addPlayer(uuid, playerName);
|
||||
}
|
||||
}
|
||||
|
||||
public void check() {
|
||||
for (String player : getKeys(getNode("NonVotedPlayers"))) {
|
||||
long time = getNode("NonVotedPlayers", player, "LastTime").getLong(0);
|
||||
if ((System.currentTimeMillis() - time) > 1000 * 60 * 60 * 24 * 5) {
|
||||
remove(player);
|
||||
} else {
|
||||
String uuid = getNode("NonVotedPlayers", player, "UUID").getString("");
|
||||
if (!uuid.isEmpty()) {
|
||||
if (plugin.getVotingPluginProxy().getProxyMySQL().containsKeyQuery(uuid)) {
|
||||
remove(player);
|
||||
}
|
||||
} else {
|
||||
remove(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
public String playerExists(String playerName) {
|
||||
if (!getNode("NonVotedPlayers", playerName).isEmpty()) {
|
||||
return getNode("NonVotedPlayers", playerName, "UUID").getString("");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private void remove(String player) {
|
||||
plugin.debug("Removing nonvotedplayer: " + player);
|
||||
|
||||
getNode("NonVotedPlayers", player).setValue(null);
|
||||
|
||||
save();
|
||||
}
|
||||
|
||||
}
|
||||
+115
-18
@@ -3,6 +3,7 @@ package com.bencodez.votingplugin.proxy.velocity;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -12,11 +13,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import com.bencodez.simpleapi.file.velocity.VelocityYMLFile;
|
||||
import com.bencodez.votingplugin.proxy.VotingPluginProxyConfig;
|
||||
|
||||
import ninja.leaping.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
|
||||
public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
public class VelocityConfig extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
|
||||
public Config(File file) {
|
||||
public VelocityConfig(File file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
@@ -37,8 +38,30 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBroadcast() {
|
||||
return getBoolean(getNode("Broadcast"), false);
|
||||
public boolean getProxyBroadcastEnabled() {
|
||||
return getBoolean(getNode("ProxyBroadcast", "Enabled"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProxyBroadcastScopeMode() {
|
||||
return getString(getNode("ProxyBroadcast", "Scope", "Mode"), "ALL_SERVERS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getProxyBroadcastScopeServers() {
|
||||
List<String> list = getStringList(getNode("ProxyBroadcast", "Scope", "Servers"), new ArrayList<>());
|
||||
return list != null ? list : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProxyBroadcastOfflineMode() {
|
||||
return getString(getNode("ProxyBroadcast", "OfflineMode"), "QUEUE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getProxyBroadcastOfflineForwardServers() {
|
||||
List<String> list = getStringList(getNode("ProxyBroadcast", "OfflineForward", "Servers"), new ArrayList<>());
|
||||
return list != null ? list : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,6 +139,11 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
return getInt(getNode("MultiProxyRedis", "Port"), 6379);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMultiProxyRedisDbIndex() {
|
||||
return getInt(getNode("MultiProxyRedis", "Db-Index"), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getMultiProxyRedisUseExistingConnection() {
|
||||
return getBoolean(getNode("MultiProxyRedis", "UseExistingConnection"), false);
|
||||
@@ -134,7 +162,7 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
public List<String> getChildrenAsList(ConfigurationNode config) {
|
||||
List<String> children = new ArrayList<>();
|
||||
if (config != null) {
|
||||
for (Map.Entry<Object, ? extends ConfigurationNode> entry : config.getChildrenMap().entrySet()) {
|
||||
for (Map.Entry<Object, ? extends ConfigurationNode> entry : config.childrenMap().entrySet()) {
|
||||
children.add(entry.getKey().toString());
|
||||
}
|
||||
}
|
||||
@@ -205,6 +233,11 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
return getInt(getNode("Redis", "Port"), 6379);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRedisDbIndex() {
|
||||
return getInt(getNode("Redis", "Db-Index"), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedisPrefix() {
|
||||
return getString(getNode("Redis", "Prefix"), "");
|
||||
@@ -253,8 +286,8 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
public Map<String, Object> configToMap(ConfigurationNode config) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
if (config != null) {
|
||||
for (Map.Entry<Object, ? extends ConfigurationNode> entry : config.getChildrenMap().entrySet()) {
|
||||
map.put(entry.getKey().toString(), entry.getValue().getValue());
|
||||
for (Map.Entry<Object, ? extends ConfigurationNode> entry : config.childrenMap().entrySet()) {
|
||||
map.put(entry.getKey().toString(), entry.getValue().raw());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
@@ -292,22 +325,22 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
|
||||
@Override
|
||||
public String getVotePartyBroadcast() {
|
||||
return getString(getVotePartyNode().getNode("Broadcast"), "");
|
||||
return getString(getVotePartyNode().node("Broadcast"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getVotePartyBungeeCommands() {
|
||||
return getStringList(getVotePartyNode().getNode("BungeeCommands"), new ArrayList<>());
|
||||
return getStringList(getVotePartyNode().node("BungeeCommands"), new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVotePartyEnabled() {
|
||||
return getBoolean(getVotePartyNode().getNode("Enabled"), false);
|
||||
return getBoolean(getVotePartyNode().node("Enabled"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVotePartyIncreaseVotesRequired() {
|
||||
return getInt(getVotePartyNode().getNode("IncreaseVotesRequired"), 0);
|
||||
return getInt(getVotePartyNode().node("IncreaseVotesRequired"), 0);
|
||||
}
|
||||
|
||||
public ConfigurationNode getVotePartyNode() {
|
||||
@@ -316,17 +349,17 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
|
||||
@Override
|
||||
public boolean getVotePartySendToAllServers() {
|
||||
return getBoolean(getVotePartyNode().getNode("SendToAllServers"), false);
|
||||
return getBoolean(getVotePartyNode().node("SendToAllServers"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getVotePartyServersToSend() {
|
||||
return getStringList(getVotePartyNode().getNode("ServersToSend"), new ArrayList<>());
|
||||
return getStringList(getVotePartyNode().node("ServersToSend"), new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVotePartyVotesRequired() {
|
||||
return getInt(getVotePartyNode().getNode("VotesRequired"), 100);
|
||||
return getInt(getVotePartyNode().node("VotesRequired"), 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -396,8 +429,72 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getResetMilestonesMonthly() {
|
||||
return getBoolean(getNode("ResetMilestonesMonthly"), false);
|
||||
public boolean getVoteCacheUseMySQL() {
|
||||
return getBoolean(getNode("VoteCache", "UseMySQL"), false);
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public boolean getVoteCacheUseMainMySQL() {
|
||||
return getBoolean(getNode("VoteCache", "UseMainMySQL"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeWeekOffSet() {
|
||||
return getInt(getNode("TimeWeekOffSet"), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getNonVotedCacheUseMySQL() {
|
||||
return getBoolean(getNode("NonVotedCache", "UseMySQL"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getNonVotedCacheUseMainMySQL() {
|
||||
return getBoolean(getNode("NonVotedCache", "UseMainMySQL"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVoteLoggingEnabled() {
|
||||
return getBoolean(getNode("VoteLogging", "Enabled"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVoteLoggingPurgeDays() {
|
||||
return getInt(getNode("VoteLogging", "PurgeDays"), 30);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVoteLoggingUseMainMySQL() {
|
||||
return getBoolean(getNode("VoteLogging", "UseMainMySQL"), true);
|
||||
}
|
||||
|
||||
private boolean isSection(ConfigurationNode node) {
|
||||
return node != null && node.raw() instanceof Map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDatabaseConfigured() {
|
||||
// New-style: Database: { Host: ... }
|
||||
ConfigurationNode db = getNode("Database");
|
||||
if (isSection(db)) {
|
||||
String host = getString(getNode("Database", "Host"), "");
|
||||
return host != null && !host.isEmpty();
|
||||
}
|
||||
|
||||
// Legacy-style: Host at root
|
||||
String host = getString(getNode("Host"), "");
|
||||
if (host != null && !host.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Optional older style some setups used: MySQL.Host
|
||||
ConfigurationNode mysql = getNode("MySQL");
|
||||
if (isSection(mysql)) {
|
||||
String mysqlHost = getString(getNode("MySQL", "Host"), "");
|
||||
return mysqlHost != null && !mysqlHost.isEmpty();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.bencodez.votingplugin.proxy.velocity;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.bencodez.simpleapi.file.velocity.VelocityJSONFile;
|
||||
import com.bencodez.votingplugin.proxy.cache.nonvoted.INonVotedPlayersStorage;
|
||||
|
||||
public class VelocityJsonNonVotedPlayersCache extends VelocityJSONFile implements INonVotedPlayersStorage {
|
||||
|
||||
public VelocityJsonNonVotedPlayersCache(File file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upsertPlayer(String uuid, String playerName, long lastTime) {
|
||||
setPath(uuid, "NonVotedPlayers", playerName, "UUID");
|
||||
setPath(lastTime, "NonVotedPlayers", playerName, "LastTime");
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuidByPlayerName(String playerName) {
|
||||
if (!getNode("NonVotedPlayers", playerName).empty()) {
|
||||
return getNode("NonVotedPlayers", playerName, "UUID").getString("");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByPlayerName(String playerName) {
|
||||
remove("NonVotedPlayers", playerName);
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<NonVotedPlayerEntry> consumer) {
|
||||
// If "NonVotedPlayers" doesn't exist, getNode(...) will just be empty and
|
||||
// getKeys(...) will be an empty set.
|
||||
for (String player : getKeys(getNode("NonVotedPlayers"))) {
|
||||
long time = getNode("NonVotedPlayers", player, "LastTime").getLong(0);
|
||||
String uuid = getNode("NonVotedPlayers", player, "UUID").getString("");
|
||||
consumer.accept(new NonVotedPlayerEntry(player, uuid, time));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
private void setPath(Object value, Object... path) {
|
||||
set(path, value);
|
||||
}
|
||||
|
||||
}
|
||||
+226
@@ -0,0 +1,226 @@
|
||||
package com.bencodez.votingplugin.proxy.velocity;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.bencodez.simpleapi.file.velocity.VelocityJSONFile;
|
||||
import com.bencodez.votingplugin.proxy.OfflineBungeeVote;
|
||||
import com.bencodez.votingplugin.proxy.cache.ConfigDataNode;
|
||||
import com.bencodez.votingplugin.proxy.cache.DataNode;
|
||||
import com.bencodez.votingplugin.proxy.cache.IVoteCache;
|
||||
import com.bencodez.votingplugin.timequeue.VoteTimeQueue;
|
||||
|
||||
public class VelocityJsonVoteCache extends VelocityJSONFile implements IVoteCache {
|
||||
|
||||
public VelocityJsonVoteCache(File file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTimedVote(int num, VoteTimeQueue voteTimedQueue) {
|
||||
setPath(voteTimedQueue.getName(), "TimedVoteCache", String.valueOf(num), "Name");
|
||||
setPath(voteTimedQueue.getService(), "TimedVoteCache", String.valueOf(num), "Service");
|
||||
setPath(voteTimedQueue.getTime(), "TimedVoteCache", String.valueOf(num), "Time");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVote(String server, int num, OfflineBungeeVote voteData) {
|
||||
setPath(voteData.getPlayerName(), "VoteCache", server, String.valueOf(num), "Name");
|
||||
setPath(voteData.getService(), "VoteCache", server, String.valueOf(num), "Service");
|
||||
setPath(voteData.getUuid(), "VoteCache", server, String.valueOf(num), "UUID");
|
||||
setPath(voteData.getTime(), "VoteCache", server, String.valueOf(num), "Time");
|
||||
setPath(voteData.isRealVote(), "VoteCache", server, String.valueOf(num), "Real");
|
||||
setPath(voteData.getText(), "VoteCache", server, String.valueOf(num), "Text");
|
||||
setPath(voteData.getVoteId() != null ? voteData.getVoteId().toString() : null, "VoteCache", server, String.valueOf(num), "VoteID");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVoteOnline(String player, int num, OfflineBungeeVote voteData) {
|
||||
setPath(voteData.getPlayerName(), "OnlineCache", player, String.valueOf(num), "Name");
|
||||
setPath(voteData.getService(), "OnlineCache", player, String.valueOf(num), "Service");
|
||||
setPath(voteData.getUuid(), "OnlineCache", player, String.valueOf(num), "UUID");
|
||||
setPath(voteData.getTime(), "OnlineCache", player, String.valueOf(num), "Time");
|
||||
setPath(voteData.isRealVote(), "OnlineCache", player, String.valueOf(num), "Real");
|
||||
setPath(voteData.getText(), "OnlineCache", player, String.valueOf(num), "Text");
|
||||
setPath(voteData.getVoteId() != null ? voteData.getVoteId().toString() : null, "OnlineCache", player, String.valueOf(num), "VoteID");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearData() {
|
||||
remove("VoteCache");
|
||||
remove("OnlineCache");
|
||||
remove("TimedVoteCache");
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getOnlineVotes(String name) {
|
||||
return getKeys(getNode("OnlineCache", name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigDataNode getOnlineVotes(String name, String num) {
|
||||
return new ConfigDataNode(getNode("OnlineCache", name, num));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getPlayers() {
|
||||
return getKeys(getNode("OnlineCache"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getServers() {
|
||||
return getKeys(getNode("VoteCache"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getServerVotes(String server) {
|
||||
return getKeys(getNode("VoteCache", server));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigDataNode getServerVotes(String server, String num) {
|
||||
return new ConfigDataNode(getNode("VoteCache", server, num));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getTimedVoteCache() {
|
||||
return getKeys(getNode("TimedVoteCache"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigDataNode getTimedVoteCache(String key) {
|
||||
return new ConfigDataNode(getNode("TimedVoteCache", key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVotePartyCache(String server) {
|
||||
return getNode("VoteParty", "Cache", server).getInt(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVotePartyCurrentVotes() {
|
||||
return getInt(getNode("VoteParty", "CurrentVotes"), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVotePartyInreaseVotesRequired() {
|
||||
return getInt(getNode("VoteParty", "IncreaseVotes"), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVotePartyCache(String server, int amount) {
|
||||
setPath(amount, "VoteParty", "Cache", server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVotePartyCurrentVotes(int amount) {
|
||||
setPath(amount, "VoteParty", "CurrentVotes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVotePartyInreaseVotesRequired(int amount) {
|
||||
setPath(amount, "VoteParty", "IncreaseVotes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOnlineVotes(String player) {
|
||||
remove("OnlineCache", player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeServerVotes(String server) {
|
||||
remove("VoteCache", server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeServerVote(String server, String uuid) {
|
||||
Collection<String> votes = getServerVotes(server);
|
||||
if (votes == null) {
|
||||
return;
|
||||
}
|
||||
// search for vote with uuid and remove it
|
||||
for (String num : votes) {
|
||||
ConfigDataNode node = getServerVotes(server, num);
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
DataNode uuidNode = node.get("UUID");
|
||||
if (uuidNode == null) {
|
||||
continue;
|
||||
}
|
||||
String nodeUuid = uuidNode.asString();
|
||||
if (nodeUuid != null && nodeUuid.equals(uuid)) {
|
||||
remove("VoteCache", server, num);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeVote(String server, OfflineBungeeVote vote) {
|
||||
Collection<String> votes = getServerVotes(server);
|
||||
if (votes == null) {
|
||||
return;
|
||||
}
|
||||
for (String num : votes) {
|
||||
ConfigDataNode node = getServerVotes(server, num);
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
DataNode uuidNode = node.get("UUID");
|
||||
DataNode serviceNode = node.get("Service");
|
||||
DataNode timeNode = node.get("Time");
|
||||
if (uuidNode == null || serviceNode == null || timeNode == null) {
|
||||
continue;
|
||||
}
|
||||
String nodeUuid = uuidNode.asString();
|
||||
String nodeService = serviceNode.asString();
|
||||
Long nodeTime = timeNode.asLong();
|
||||
|
||||
if (nodeUuid != null && nodeService != null && nodeTime != null && nodeUuid.equals(vote.getUuid())
|
||||
&& nodeService.equals(vote.getService()) && nodeTime.longValue() == vote.getTime()) {
|
||||
remove("VoteCache", server, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOnlineVote(OfflineBungeeVote vote) {
|
||||
Collection<String> players = getPlayers();
|
||||
if (players == null) {
|
||||
return;
|
||||
}
|
||||
for (String player : players) {
|
||||
Collection<String> onlineVotes = getOnlineVotes(player);
|
||||
if (onlineVotes == null) {
|
||||
continue;
|
||||
}
|
||||
for (String num : onlineVotes) {
|
||||
ConfigDataNode node = getOnlineVotes(player, num);
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
DataNode uuidNode = node.get("UUID");
|
||||
DataNode serviceNode = node.get("Service");
|
||||
DataNode timeNode = node.get("Time");
|
||||
if (uuidNode == null || serviceNode == null || timeNode == null) {
|
||||
continue;
|
||||
}
|
||||
String nodeUuid = uuidNode.asString();
|
||||
String nodeService = serviceNode.asString();
|
||||
Long nodeTime = timeNode.asLong();
|
||||
|
||||
if (nodeUuid != null && nodeService != null && nodeTime != null && nodeUuid.equals(vote.getUuid())
|
||||
&& nodeService.equals(vote.getService()) && nodeTime.longValue() == vote.getTime()) {
|
||||
remove("OnlineCache", player, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setPath(Object value, Object... path) {
|
||||
set(path, value);
|
||||
}
|
||||
|
||||
}
|
||||
Loaded 100 of 188 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user