mirror of
https://github.com/BenCodez/VotingPlugin.git
synced 2026-11-04 09:02:00 -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 | ||
|
|
b8acfe20ec | ||
|
|
110aaf096e | ||
|
|
171975c3d3 | ||
|
|
ac96d277c5 | ||
|
|
b1ad952950 | ||
|
|
ca30bcb183 | ||
|
|
eecd975731 | ||
|
|
aa55b10e50 | ||
|
|
64f59f8195 | ||
|
|
a51e041430 | ||
|
|
b39f768a46 | ||
|
|
e98bc49add | ||
|
|
8b2209aa59 | ||
|
|
58a0e85d00 | ||
|
|
3febfa4056 | ||
|
|
e5668c862a | ||
|
|
fd4c6a3954 | ||
|
|
9e9472680a | ||
|
|
cbecd7be30 | ||
|
|
fcb1af77cf | ||
|
|
5d9b5b7b6c | ||
|
|
d26d61a6f0 | ||
|
|
3f885aa358 | ||
|
|
d088f2e91a | ||
|
|
a536c53dd9 | ||
|
|
5d2d6f0763 | ||
|
|
0848ed83c2 | ||
|
|
1771fe0889 | ||
|
|
ce5b197e8b | ||
|
|
15489d9c64 | ||
|
|
758632b5a5 | ||
|
|
3dc45b6a63 | ||
|
|
26c9ad98bc | ||
|
|
ee2531af1e | ||
|
|
461e5f8413 | ||
|
|
1c5acbd1a1 | ||
|
|
e855c01854 | ||
|
|
aeec7d9d17 | ||
|
|
4861c041e4 | ||
|
|
d1c6752240 | ||
|
|
caa7058363 | ||
|
|
b67f6a509c | ||
|
|
0edc09dc80 | ||
|
|
19e597e094 | ||
|
|
bfc838bfaa | ||
|
|
9cda17e89e | ||
|
|
54a573a445 | ||
|
|
5432b2a0d3 | ||
|
|
13d3a614ed | ||
|
|
f9641e158d | ||
|
|
a0c1f64aac | ||
|
|
1f88cb0261 | ||
|
|
71ccf6a7b0 | ||
|
|
47a42d2bc8 | ||
|
|
ac41787c1e | ||
|
|
ed4e3968da | ||
|
|
09da81cc4e | ||
|
|
fd35c43c16 |
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.
|
||||
+664
-613
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+909
-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("_")) {
|
||||
|
||||
+3
-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;
|
||||
@@ -28,6 +29,7 @@ import com.bencodez.votingplugin.user.VotingPluginUser;
|
||||
|
||||
public class AdminVoteTopPoints extends GUIHandler {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private int page;
|
||||
private VotingPluginMain plugin;
|
||||
private VotingPluginUser user;
|
||||
@@ -62,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 {
|
||||
|
||||
|
||||
+34
-25
@@ -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())
|
||||
@@ -186,8 +181,26 @@ public class VoteURL extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onChest(Player player) {
|
||||
// normal GUI
|
||||
|
||||
BInventory inv = new BInventory(plugin.getGui().getChestVoteURLName());
|
||||
|
||||
if (!plugin.getConfigFile().isAlwaysCloseInventory()) {
|
||||
inv.dontClose();
|
||||
}
|
||||
|
||||
for (final String str : plugin.getGui().getChestVoteURLExtraItems()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(plugin.getGui().getChestVoteURLExtraItemsItem(str))) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new RewardBuilder(plugin.getGui().getData(),
|
||||
"CHEST.VoteURL.ExtraItems." + str + "." + clickEvent.getButton().getLastRewardsPath(player))
|
||||
.setGiveOffline(false).send(clickEvent.getPlayer());
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (plugin.getGui().isChestVoteURLViewAllUrlsButtonEnabled()) {
|
||||
ItemBuilder builderAll = getItemAll();
|
||||
|
||||
@@ -195,6 +208,7 @@ public class VoteURL extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
event.closeInventory();
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(event.getPlayer());
|
||||
json = true;
|
||||
if (event.getClick().equals(ClickType.SHIFT_LEFT)
|
||||
@@ -213,11 +227,20 @@ 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);
|
||||
if (startSlot >= 0) {
|
||||
if (inv.isSlotTaken(startSlot)) {
|
||||
boolean found = false;
|
||||
while (!found) {
|
||||
startSlot++;
|
||||
if (!inv.isSlotTaken(startSlot)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.setSlot(startSlot);
|
||||
startSlot++;
|
||||
}
|
||||
@@ -226,6 +249,7 @@ public class VoteURL extends GUIHandler {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
event.closeInventory();
|
||||
Player player = event.getPlayer();
|
||||
if (player != null) {
|
||||
VotingPluginUser user = plugin.getVotingPluginUserManager().getVotingPluginUser(player);
|
||||
@@ -252,21 +276,6 @@ public class VoteURL extends GUIHandler {
|
||||
}
|
||||
}
|
||||
|
||||
for (
|
||||
|
||||
final String str : plugin.getGui().getChestVoteURLExtraItems()) {
|
||||
inv.addButton(new BInventoryButton(new ItemBuilder(plugin.getGui().getChestVoteURLExtraItemsItem(str))) {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
new RewardBuilder(plugin.getGui().getData(),
|
||||
"CHEST.VoteURL.ExtraItems." + str + "." + clickEvent.getButton().getLastRewardsPath(player))
|
||||
.setGiveOffline(false).send(clickEvent.getPlayer());
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (plugin.getGui().isChestVoteURLBackButton()) {
|
||||
inv.addButton(plugin.getCommandLoader().getBackButton(user));
|
||||
}
|
||||
|
||||
+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,31 +25,55 @@ 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 = "";
|
||||
|
||||
@ConfigDataString(path = "MQTT.BrokerURL")
|
||||
@Getter
|
||||
private String mqttBrokerURL = "tcp://localhost:1883";
|
||||
|
||||
@ConfigDataString(path = "MQTT.Username")
|
||||
@Getter
|
||||
private String mqttUsername = "";
|
||||
|
||||
@ConfigDataString(path = "MQTT.Password")
|
||||
@Getter
|
||||
private String mqttPassword = "";
|
||||
|
||||
@ConfigDataString(path = "MQTT.Prefix")
|
||||
@Getter
|
||||
private String mqttPrefix = "";
|
||||
|
||||
@ConfigDataString(path = "BungeeServer.Host")
|
||||
@Getter
|
||||
@@ -71,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;
|
||||
@@ -111,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;
|
||||
@@ -129,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() {
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.bencodez.simpleapi.file.annotation.ConfigDataBoolean;
|
||||
import com.bencodez.simpleapi.file.annotation.ConfigDataInt;
|
||||
import com.bencodez.simpleapi.file.annotation.ConfigDataKeys;
|
||||
import com.bencodez.simpleapi.file.annotation.ConfigDataListString;
|
||||
import com.bencodez.simpleapi.file.annotation.ConfigDataLong;
|
||||
import com.bencodez.simpleapi.file.annotation.ConfigDataString;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.placeholders.PlaceholderCacheLevel;
|
||||
@@ -51,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;
|
||||
@@ -67,6 +72,185 @@ public class Config extends YMLFile {
|
||||
@Getter
|
||||
private boolean preloadSkulls = false;
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.Enabled")
|
||||
@Getter
|
||||
private boolean discordSRVEnabled = false;
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.Enabled")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterAllTimeEnabled = false;
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.AllTime.NewMessageOnUpdate")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterAllTimeNewMessageOnUpdate = false;
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.NewMessageOnUpdate")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterMonthlyNewMessageOnUpdate = false;
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.NewMessageOnUpdate")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterWeeklyNewMessageOnUpdate = false;
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.NewMessageOnUpdate")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterDailyNewMessageOnUpdate = false;
|
||||
|
||||
@ConfigDataLong(path = "DiscordSRV.TopVoter.AllTime.Channel")
|
||||
@Getter
|
||||
private long discordSRVTopVoterAllTimeChannel = 0;
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.Title")
|
||||
@Getter
|
||||
private String discordSRVTopVoterAllTimeTitle = "All Time Top Voters";
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.AllTime.RankDisplay")
|
||||
@Getter
|
||||
private String discordSRVTopVoterAllTimeRankDisplay = "%rank%: %player% - %votes% Votes";
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Monthly.Enabled")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterMonthlyEnabled = false;
|
||||
|
||||
@ConfigDataLong(path = "DiscordSRV.TopVoter.Monthly.Channel")
|
||||
@Getter
|
||||
private long discordSRVTopVoterMonthlyChannel = 0;
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.Title")
|
||||
@Getter
|
||||
private String discordSRVTopVoterMonthlyTitle = "Top Voters of the Month";
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Monthly.RankDisplay")
|
||||
@Getter
|
||||
private String discordSRVTopVoterMonthlyRankDisplay = "%rank%: %player% - %votes% Votes";
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Weekly.Enabled")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterWeeklyEnabled = false;
|
||||
|
||||
@ConfigDataLong(path = "DiscordSRV.TopVoter.Weekly.Channel")
|
||||
@Getter
|
||||
private long discordSRVTopVoterWeeklyChannel = 0;
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.Title")
|
||||
@Getter
|
||||
private String discordSRVTopVoterWeeklyTitle = "Top Voters of the Week";
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Weekly.RankDisplay")
|
||||
@Getter
|
||||
private String discordSRVTopVoterWeeklyRankDisplay = "%rank%: %player% - %votes% Votes";
|
||||
|
||||
@ConfigDataBoolean(path = "DiscordSRV.TopVoter.Daily.Enabled")
|
||||
@Getter
|
||||
private boolean discordSRVTopVoterDailyEnabled = false;
|
||||
|
||||
@ConfigDataLong(path = "DiscordSRV.TopVoter.Daily.Channel")
|
||||
@Getter
|
||||
private long discordSRVTopVoterDailyChannel = 0;
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Daily.Title")
|
||||
@Getter
|
||||
private String discordSRVTopVoterDailyTitle = "Top Voters of the Day";
|
||||
|
||||
@ConfigDataString(path = "DiscordSRV.TopVoter.Daily.RankDisplay")
|
||||
@Getter
|
||||
private String discordSRVTopVoterDailyRankDisplay = "%rank%: %player% - %votes% Votes";
|
||||
|
||||
// VoteLogging configuration section - minimal options mirror Config.yml
|
||||
@ConfigDataBoolean(path = "VoteLogging.Enabled")
|
||||
@Getter
|
||||
private boolean voteLoggingEnabled = false;
|
||||
|
||||
@ConfigDataInt(path = "VoteLogging.PurgeDays")
|
||||
@Getter
|
||||
private int voteLoggingPurgeDays = 30;
|
||||
|
||||
@ConfigDataBoolean(path = "VoteLogging.UseMainMySQL")
|
||||
@Getter
|
||||
private boolean voteLoggingUseMainMySQL = true;
|
||||
|
||||
public ConfigurationSection getVoteLoggingSection() {
|
||||
if (!getData().isConfigurationSection("VoteLogging")) {
|
||||
getData().createSection("VoteLogging");
|
||||
}
|
||||
return getData().getConfigurationSection("VoteLogging");
|
||||
}
|
||||
|
||||
public boolean isDiscordSRVTopVoterEnabled(TopVoter topVoter) {
|
||||
switch (topVoter) {
|
||||
case AllTime:
|
||||
return isDiscordSRVTopVoterAllTimeEnabled();
|
||||
case Monthly:
|
||||
return isDiscordSRVTopVoterMonthlyEnabled();
|
||||
case Weekly:
|
||||
return isDiscordSRVTopVoterWeeklyEnabled();
|
||||
case Daily:
|
||||
return isDiscordSRVTopVoterDailyEnabled();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
return getDiscordSRVTopVoterAllTimeChannel();
|
||||
case Monthly:
|
||||
return getDiscordSRVTopVoterMonthlyChannel();
|
||||
case Weekly:
|
||||
return getDiscordSRVTopVoterWeeklyChannel();
|
||||
case Daily:
|
||||
return getDiscordSRVTopVoterDailyChannel();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDiscordSRVTopVoterTitle(TopVoter topVoter) {
|
||||
switch (topVoter) {
|
||||
case AllTime:
|
||||
return getDiscordSRVTopVoterAllTimeTitle();
|
||||
case Monthly:
|
||||
return getDiscordSRVTopVoterMonthlyTitle();
|
||||
case Weekly:
|
||||
return getDiscordSRVTopVoterWeeklyTitle();
|
||||
case Daily:
|
||||
return getDiscordSRVTopVoterDailyTitle();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getDiscordSRVTopVoterRankDisplay(TopVoter topVoter) {
|
||||
switch (topVoter) {
|
||||
case AllTime:
|
||||
return getDiscordSRVTopVoterAllTimeRankDisplay();
|
||||
case Monthly:
|
||||
return getDiscordSRVTopVoterMonthlyRankDisplay();
|
||||
case Weekly:
|
||||
return getDiscordSRVTopVoterWeeklyRankDisplay();
|
||||
case Daily:
|
||||
return getDiscordSRVTopVoterDailyRankDisplay();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigDataBoolean(path = "AllowUnJoinedCheckServer")
|
||||
@Getter
|
||||
private boolean allowUnJoinedCheckServer = true;
|
||||
@@ -87,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;
|
||||
@@ -99,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
|
||||
@@ -139,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;
|
||||
@@ -155,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;
|
||||
@@ -287,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;
|
||||
@@ -323,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;
|
||||
@@ -347,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;
|
||||
@@ -581,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -718,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;
|
||||
}
|
||||
|
||||
@@ -41,13 +44,13 @@ public class ConfigVoteSites extends YMLFile {
|
||||
public void generateVoteSite(String siteName) {
|
||||
if (plugin.getConfigFile().isAutoCreateVoteSites()) {
|
||||
String org = siteName;
|
||||
siteName = siteName.replace(".", "_");
|
||||
siteName = siteName.replace(".", "_").replace(" ", "_");
|
||||
plugin.getLogger().warning("VoteSite " + siteName + " does not exist with the servicesite '" + org
|
||||
+ "', creating one, set AutoCreateVoteSites to false to prevent this");
|
||||
setEnabled(siteName, true);
|
||||
setServiceSite(siteName, org);
|
||||
setVoteURL(siteName, "VoteURL");
|
||||
setVoteDelay(siteName, 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)"));
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import com.bencodez.simpleapi.array.ArrayUtils;
|
||||
import com.bencodez.votingplugin.VotingPluginMain;
|
||||
import com.bencodez.votingplugin.signs.SignHandler;
|
||||
import com.bencodez.votingplugin.timequeue.VoteTimeQueue;
|
||||
import com.bencodez.votingplugin.topvoter.TopVoter;
|
||||
|
||||
// TODO: Auto-generated Javadoc
|
||||
/**
|
||||
@@ -244,6 +245,15 @@ public class ServerData {
|
||||
plugin.getServerDataFile().reloadData();
|
||||
}
|
||||
|
||||
public long getTopVoterMessageId(TopVoter top) {
|
||||
return getData().getLong("DiscordSRV.TopVoterMessageId." + top.toString(), 0);
|
||||
}
|
||||
|
||||
public void setTopVoterMessageId(TopVoter top, long messageId) {
|
||||
getData().set("DiscordSRV.TopVoterMessageId." + top.toString(), messageId);
|
||||
saveData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the sign.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
package com.bencodez.votingplugin.discord;
|
||||
|
||||
import java.awt.Color;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
import github.scarsz.discordsrv.DiscordSRV;
|
||||
import github.scarsz.discordsrv.api.Subscribe;
|
||||
import github.scarsz.discordsrv.api.events.DiscordReadyEvent;
|
||||
import github.scarsz.discordsrv.dependencies.jda.api.EmbedBuilder;
|
||||
import github.scarsz.discordsrv.dependencies.jda.api.JDA;
|
||||
import github.scarsz.discordsrv.dependencies.jda.api.entities.TextChannel;
|
||||
import github.scarsz.discordsrv.util.DiscordUtil;
|
||||
import lombok.Getter;
|
||||
|
||||
public class DiscordHandler {
|
||||
|
||||
private final VotingPluginMain plugin;
|
||||
@Getter
|
||||
private final HashMap<TopVoter, Long> topVoterMessageIds = new HashMap<TopVoter, Long>();
|
||||
private final AtomicBoolean discordReady = new AtomicBoolean(false);
|
||||
|
||||
public DiscordHandler(VotingPluginMain plugin) {
|
||||
this.plugin = plugin;
|
||||
for (TopVoter top : TopVoter.values()) {
|
||||
long savedId = plugin.getServerData().getTopVoterMessageId(top);
|
||||
topVoterMessageIds.put(top, savedId);
|
||||
}
|
||||
}
|
||||
|
||||
/** Call this early, e.g. from onEnable() in main plugin class */
|
||||
public void load() {
|
||||
DiscordSRV.api.subscribe(this);
|
||||
plugin.getLogger().info("DiscordHandler loaded; awaiting Discord readiness.");
|
||||
|
||||
// if DiscordSRV is already up and running, mark it ready now
|
||||
if (DiscordUtil.getJda().getStatus() == JDA.Status.CONNECTED) {
|
||||
discordReady.set(true);
|
||||
plugin.getLogger().info("DiscordSRV was already ready; manual update now available.");
|
||||
}
|
||||
|
||||
plugin.getRewardHandler().addInjectedReward(new RewardInjectConfigurationSection("DiscordSRV") {
|
||||
|
||||
@Override
|
||||
public String onRewardRequested(Reward arg0, com.bencodez.advancedcore.api.user.AdvancedCoreUser user,
|
||||
ConfigurationSection section, HashMap<String, String> placeholders) {
|
||||
if (section.getBoolean("Enabled")) {
|
||||
String msg = PlaceholderUtils
|
||||
.replacePlaceHolder(section.getString("Message", "Please set a message"), placeholders);
|
||||
msg = PlaceholderUtils.replacePlaceHolders(user.getOfflinePlayer(), msg);
|
||||
sendRewardMessage(msg, section.getString("ChannelID", "0"));
|
||||
}
|
||||
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 */
|
||||
@Subscribe
|
||||
public void onDiscordReady(DiscordReadyEvent event) {
|
||||
discordReady.set(true);
|
||||
plugin.getLogger().info("DiscordSRV is ready; manual update now available.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method to update the Top Voter message on demand. Checks Discord
|
||||
* readiness internally.
|
||||
*/
|
||||
public void updateDiscordLeaderboard() {
|
||||
if (!discordReady.get()) {
|
||||
plugin.getLogger().warning("DiscordSRV not ready yet; cannot update Top Voters.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (TopVoter top : TopVoter.values()) {
|
||||
if (plugin.getConfigFile().isDiscordSRVTopVoterEnabled(top)) {
|
||||
plugin.debug("Updating Discord Top Voter: " + top.toString());
|
||||
updateTopVoterMessageId(top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
boolean newMessage = plugin.getConfigFile().isDiscordSRVTopVoterNewMessageOnUpdate(top);
|
||||
|
||||
EmbedBuilder eb = new EmbedBuilder().setTitle(title).setColor(Color.CYAN).setTimestamp(Instant.now());
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
long existingId = topVoterMessageIds.getOrDefault(top, 0L);
|
||||
|
||||
if (existingId <= 0 || newMessage) {
|
||||
channel.sendMessageEmbeds(eb.build()).queue(msg -> {
|
||||
long newId = msg.getIdLong();
|
||||
topVoterMessageIds.put(top, newId);
|
||||
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(existingId, eb.build()).queue(
|
||||
m -> plugin.debug("Edited Top Voters " + top + " (ID: " + existingId + ")"),
|
||||
err -> plugin.getLogger().warning("Error editing Top Voters " + top + ": " + err.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void sendRewardMessage(String message, String channelId) {
|
||||
TextChannel channel = DiscordUtil.getJda().getTextChannelById(channelId);
|
||||
if (channel != null) {
|
||||
channel.sendMessage(message).queue();
|
||||
} else {
|
||||
plugin.getLogger().warning("Discord channel ID " + channelId + " not found for reward message.");
|
||||
}
|
||||
}
|
||||
}
|
||||
+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;
|
||||
}
|
||||
}
|
||||
+75
-47
@@ -6,19 +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.BungeeMethod;
|
||||
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.
|
||||
@@ -29,66 +30,93 @@ 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();
|
||||
|
||||
plugin.getPlaceholders().onUpdate(user, true);
|
||||
|
||||
if (plugin.getBungeeSettings().isUseBungeecoord()
|
||||
&& (plugin.getBungeeHandler().getMethod().equals(BungeeMethod.PLUGINMESSAGING)
|
||||
|| plugin.getBungeeHandler().getMethod().equals(BungeeMethod.REDIS))) {
|
||||
plugin.getBungeeHandler().getGlobalMessageHandler().sendMessage("Login", user.getPlayerName(),
|
||||
user.getUUID(), plugin.getBungeeSettings().getServer());
|
||||
if (plugin.getBungeeSettings().isUseBungeecoord()) {
|
||||
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
-76
@@ -3,6 +3,8 @@ package com.bencodez.votingplugin.listeners;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -10,15 +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.proxy.BungeeMethod;
|
||||
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));
|
||||
@@ -127,6 +130,7 @@ public class PlayerVoteListener implements Listener {
|
||||
// player online
|
||||
user = plugin.getVotingPluginUserManager().getVotingPluginUser(p);
|
||||
} else {
|
||||
// attempt to get exact name from cache matching casing
|
||||
user = plugin.getVotingPluginUserManager().getVotingPluginUser(playerName);
|
||||
}
|
||||
}
|
||||
@@ -144,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
|
||||
@@ -154,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) {
|
||||
@@ -178,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()) {
|
||||
@@ -203,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);
|
||||
}
|
||||
@@ -214,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 {
|
||||
@@ -244,40 +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);
|
||||
|
||||
if (plugin.getBungeeSettings().isUseBungeecoord()) {
|
||||
if (plugin.getBungeeHandler().getMethod().equals(BungeeMethod.MYSQL)) {
|
||||
|
||||
plugin.getBukkitScheduler().runTaskLaterAsynchronously(plugin, new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (Bukkit.getOnlinePlayers().size() > 0) {
|
||||
plugin.getBungeeHandler().getGlobalMessageHandler().sendMessage("VoteUpdate", uuid);
|
||||
}
|
||||
}
|
||||
}, 2);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,9 +72,11 @@ public class VotiferEvent implements Listener {
|
||||
plugin.getServerData().addServiceSite(voteSite);
|
||||
if (plugin.getBungeeSettings().isUseBungeecoord() && !plugin.getBungeeSettings().isVotifierBypass()
|
||||
&& (plugin.getBungeeHandler().getMethod().equals(BungeeMethod.PLUGINMESSAGING)
|
||||
|| plugin.getBungeeHandler().getMethod().equals(BungeeMethod.SOCKETS))) {
|
||||
|| plugin.getBungeeHandler().getMethod().equals(BungeeMethod.SOCKETS)
|
||||
|| plugin.getBungeeHandler().getMethod().equals(BungeeMethod.MQTT)
|
||||
|| plugin.getBungeeHandler().getMethod().equals(BungeeMethod.REDIS))) {
|
||||
plugin.getLogger().severe(
|
||||
"Ignoring vote from votifier since pluginmessaging or socket bungee method is enabled, this means you aren't setup correctly for those methods, please check: https://github.com/BenCodez/VotingPlugin/wiki/Bungeecord-Setups");
|
||||
"Ignoring vote from votifier since pluginmessaging, socket, redis, or mqtt bungee method is enabled, this means you aren't setup correctly for those methods, please check: https://github.com/BenCodez/VotingPlugin/wiki/Bungeecord-Setups");
|
||||
return;
|
||||
}
|
||||
String matchSite = "";
|
||||
@@ -84,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;
|
||||
@@ -116,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 +1,11 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
public enum BungeeMethod {
|
||||
MYSQL, PLUGINMESSAGING, SOCKETS, REDIS;
|
||||
MYSQL, PLUGINMESSAGING, SOCKETS, REDIS, MQTT;
|
||||
|
||||
public boolean requiresPlayerOnline() {
|
||||
return this == PLUGINMESSAGING;
|
||||
}
|
||||
|
||||
public static BungeeMethod getByName(String str) {
|
||||
for (BungeeMethod method : values()) {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
public class BungeeVersion {
|
||||
public static int getPluginMessageVersion() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class OfflineBungeeVote {
|
||||
|
||||
@@ -11,24 +14,45 @@ public class OfflineBungeeVote {
|
||||
@Getter
|
||||
private String service;
|
||||
@Getter
|
||||
@Setter
|
||||
private String text;
|
||||
@Getter
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,484 @@
|
||||
package com.bencodez.votingplugin.proxy;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.bencodez.simpleapi.sql.Column;
|
||||
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;
|
||||
|
||||
public abstract class ProxyMysqlUserTable extends AbstractSqlTable {
|
||||
|
||||
// Keep this so existing callers relying on getName() still work
|
||||
private final String name;
|
||||
|
||||
// For int-vs-string decode in getExactQuery (same pattern as before)
|
||||
private final List<String> intColumns = new ArrayList<>();
|
||||
|
||||
// Backwards-compat wrapper (your old code expects getUuids())
|
||||
private final Set<String> uuidsView;
|
||||
|
||||
// ---- Required subclass hooks ----
|
||||
|
||||
@Override
|
||||
public String getPrimaryKeyColumn() {
|
||||
return "uuid";
|
||||
}
|
||||
|
||||
@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(" (");
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// ---- Logging hooks required by AbstractSqlTable ----
|
||||
|
||||
@Override
|
||||
public abstract void logSevere(String msg);
|
||||
|
||||
@Override
|
||||
public abstract void logInfo(String msg);
|
||||
|
||||
@Override
|
||||
public abstract void debug(Throwable t);
|
||||
|
||||
// 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);
|
||||
|
||||
this.name = super.getTableName();
|
||||
|
||||
// keep uuids view
|
||||
this.uuidsView = super.getPrimaryKeys();
|
||||
|
||||
// keep old "uuid column type tweak" behavior (but now uses base helper)
|
||||
alterColumnType("uuid", bestUuidType());
|
||||
|
||||
// load intColumns behavior if you rely on it elsewhere
|
||||
// (no-op: it's only used if you add to it)
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an already-connected pool (shared).
|
||||
*/
|
||||
public ProxyMysqlUserTable(String tableName, MySQL existingMysql, boolean debug) {
|
||||
super(tableName, existingMysql, debug);
|
||||
|
||||
this.name = super.getTableName();
|
||||
this.uuidsView = super.getPrimaryKeys();
|
||||
|
||||
alterColumnType("uuid", bestUuidType());
|
||||
}
|
||||
|
||||
// ---- Backwards-compatible API ----
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
clearCacheBasic();
|
||||
}
|
||||
|
||||
public void clearCacheBasic() {
|
||||
clearCaches();
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
close();
|
||||
}
|
||||
|
||||
// Keep old containsKeyQuery signature
|
||||
public boolean containsKeyQuery(String index) {
|
||||
return super.containsKeyQuery(index);
|
||||
}
|
||||
|
||||
// ---- Required old utility methods (kept) ----
|
||||
|
||||
public ArrayList<String> getColumnsQueury() {
|
||||
return new ArrayList<>(getColumnsQuery());
|
||||
}
|
||||
|
||||
public ArrayList<Column> getRowsNameQuery() {
|
||||
ArrayList<Column> result = new ArrayList<>();
|
||||
checkColumn("PlayerName", DataType.STRING);
|
||||
|
||||
String sqlStr = "SELECT " + qi("PlayerName") + " FROM " + qi(getTableName()) + ";";
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sqlStr);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
|
||||
while (rs.next()) {
|
||||
result.add(new Column("PlayerName", new DataValueString(rs.getString(1))));
|
||||
}
|
||||
} 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 " + qi("uuid") + " FROM " + qi(getTableName()) + ";";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sqlStr);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
|
||||
while (rs.next()) {
|
||||
result.add(new Column("uuid", new DataValueString(rs.getString(1))));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<UUID, String> getRowsUUIDNameQuery() {
|
||||
ConcurrentHashMap<UUID, String> uuidNames = new ConcurrentHashMap<>();
|
||||
|
||||
checkColumn("PlayerName", DataType.STRING);
|
||||
|
||||
String sqlStr = "SELECT " + qi("uuid") + ", " + qi("PlayerName") + " FROM " + qi(getTableName()) + ";";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(sqlStr);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
|
||||
while (rs.next()) {
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException ignored) {
|
||||
}
|
||||
|
||||
return uuidNames;
|
||||
}
|
||||
|
||||
public String getUUID(String playerName) {
|
||||
checkColumn("PlayerName", DataType.STRING);
|
||||
|
||||
String query = "SELECT " + qi("uuid") + " FROM " + qi(getTableName()) + " WHERE " + qi("PlayerName") + " = ?;";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
debug(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ArrayList<Column> getExactQuery(Column column) {
|
||||
ArrayList<Column> result = new ArrayList<>();
|
||||
|
||||
String query = "SELECT * FROM " + qi(getTableName()) + " WHERE " + qi(column.getName()) + " = ?;";
|
||||
|
||||
try (Connection conn = mysql.getConnectionManager().getConnection();
|
||||
PreparedStatement ps = conn.prepareStatement(query)) {
|
||||
|
||||
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 {
|
||||
ps.setString(1, v);
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
// ---- 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 void insertQuery(String index, List<Column> cols) {
|
||||
for (Column c : cols) {
|
||||
checkColumn(c.getName(), c.getDataType());
|
||||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
// keep old behavior: if missing, insert
|
||||
if (!getUuids().contains(index) && !containsKeyQuery(index)) {
|
||||
insertQuery(index, cols);
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (updateLock) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("UPDATE ").append(qi(getTableName())).append(" SET ");
|
||||
|
||||
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(", ");
|
||||
}
|
||||
}
|
||||
|
||||
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) && !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 " + 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1004
-391
File diff suppressed because it is too large.
Load diff
+7
-18
@@ -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,20 +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 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) {
|
||||
|
||||
+84
-2
@@ -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,24 @@ public interface VotingPluginProxyConfig {
|
||||
|
||||
public boolean getDebug();
|
||||
|
||||
public boolean getVoteCacheUseMySQL();
|
||||
|
||||
public boolean getVoteCacheUseMainMySQL();
|
||||
|
||||
public boolean getNonVotedCacheUseMySQL();
|
||||
|
||||
public boolean getNonVotedCacheUseMainMySQL();
|
||||
|
||||
public String getMqttClientID();
|
||||
|
||||
public String getMqttBrokerURL();
|
||||
|
||||
public String getMqttUsername();
|
||||
|
||||
public String getMqttPassword();
|
||||
|
||||
public String getMqttPrefix();
|
||||
|
||||
public String getFallBack();
|
||||
|
||||
public boolean getGlobalDataEnabled();
|
||||
@@ -78,6 +134,8 @@ public interface VotingPluginProxyConfig {
|
||||
|
||||
public int getRedisPort();
|
||||
|
||||
public int getRedisDbIndex();
|
||||
|
||||
public String getRedisPrefix();
|
||||
|
||||
public String getRedisUsername();
|
||||
@@ -94,6 +152,8 @@ public interface VotingPluginProxyConfig {
|
||||
|
||||
public int getTimeHourOffSet();
|
||||
|
||||
public int getTimeWeekOffSet();
|
||||
|
||||
public String getTimeZone();
|
||||
|
||||
public boolean getUseMonthDateTotalsAsPrimaryTotal();
|
||||
@@ -120,8 +180,30 @@ public interface VotingPluginProxyConfig {
|
||||
|
||||
public List<String> getWhiteListedServers();
|
||||
|
||||
public Collection<String> getWaitUntilVoteDelaySites();
|
||||
|
||||
public String getWaitUntilVoteDelayService(String site);
|
||||
|
||||
public int getWaitUntilVoteDelayVoteDelay(String site);
|
||||
|
||||
public int getWaitUntilVoteDelayVoteDelayMin(String site);
|
||||
|
||||
public int getWaitUntilVoteDelayVoteDelayHour(String site);
|
||||
|
||||
public boolean getWaitUntilVoteDelayVoteDelayDaily(String site);
|
||||
|
||||
public void load();
|
||||
|
||||
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);
|
||||
|
||||
+209
-7
@@ -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,226 +34,339 @@ 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBedrockPlayerPrefix() {
|
||||
return getData().getString("BedrockPlayerPrefix", ".");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getBlockedServers() {
|
||||
return getData().getStringList("BlockedServers");
|
||||
}
|
||||
|
||||
public boolean getBroadcast() {
|
||||
return getData().getBoolean("Broadcast", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBungeeHost() {
|
||||
return getData().getString("BungeeServer.Host", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBungeeManageTotals() {
|
||||
return getData().getBoolean("BungeeManageTotals", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBungeeMethod() {
|
||||
return getData().getString("BungeeMethod", "SOCKETS");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBungeePort() {
|
||||
return getData().getInt("BungeeServer.Port", 1297);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDebug() {
|
||||
return getData().getBoolean("Debug", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFallBack() {
|
||||
return getData().getString("FallBackServer", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getGlobalDataEnabled() {
|
||||
return getData().getBoolean("GlobalData.Enabled", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getGlobalDataUseMainMySQL() {
|
||||
return getData().getBoolean("GlobalData.UseMainMySQL", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLimitVotePoints() {
|
||||
return getData().getInt("LimitVotePoints", -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAmountOfVotesPerDay() {
|
||||
return getData().getInt("MaxAmountOfVotesPerDay", -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxyMethod() {
|
||||
return getData().getString("MultiProxyMethod", "SOCKET");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getMultiProxyOneGlobalReward() {
|
||||
return getData().getBoolean("MultiProxyOneGlobalReward", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxyRedisHost() {
|
||||
return getData().getString("MultiProxyRedis.Host", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxyRedisPassword() {
|
||||
return getData().getString("MultiProxyRedis.Password", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMultiProxyRedisPort() {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxyRedisUsername() {
|
||||
return getData().getString("MultiProxyRedis.Username", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getMultiProxyServers() {
|
||||
return getData().getSection("MultiProxyServers").getKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getMultiProxyServersConfiguration(String s) {
|
||||
return configToMap(getData().getSection("MultiProxyServers." + s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxySocketHostHost() {
|
||||
return getData().getString("MultiProxySocketHost.Host", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMultiProxySocketHostPort() {
|
||||
return getData().getInt("MultiProxySocketHost.Port", 1297);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getMultiProxySupport() {
|
||||
return getData().getBoolean("MultiProxySupport", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOnlineMode() {
|
||||
return getData().getBoolean("OnlineMode", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointsOnVote() {
|
||||
return getData().getInt("PointsOnVote", 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPrimaryServer() {
|
||||
return getData().getBoolean("PrimaryServer", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProxyServerName() {
|
||||
return getData().getString("ProxyServerName", "SOCKET");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getProxyServers() {
|
||||
return getData().getStringList("ProxyServers");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedisHost() {
|
||||
return getData().getString("Redis.Host", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedisPassword() {
|
||||
return getData().getString("Redis.Password", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRedisPort() {
|
||||
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", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedisUsername() {
|
||||
return getData().getString("Redis.Username", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSendVotesToAllServers() {
|
||||
return getData().getBoolean("SendVotesToAllServers");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getSpigotServerConfiguration(String s) {
|
||||
return configToMap(getData().getSection("SpigotServers." + s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getSpigotServers() {
|
||||
return getData().getSection("SpigotServers").getKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getStoreMonthTotalsWithDate() {
|
||||
return getData().getBoolean("StoreMonthTotalsWithDate", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTimeChangeFailSafeBypass() {
|
||||
return getData().getBoolean("TimeChangeFailSafeBypass", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeHourOffSet() {
|
||||
return getData().getInt("TimeHourOffSet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTimeZone() {
|
||||
return getData().getString("TimeZone", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getUseMonthDateTotalsAsPrimaryTotal() {
|
||||
return getData().getBoolean("UseMonthDateTotalsAsPrimaryTotal", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getUUIDLookup() {
|
||||
return getData().getBoolean("UUIDLookup", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVoteCacheTime() {
|
||||
return getData().getInt("VoteCacheTime", -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVotePartyBroadcast() {
|
||||
return getData().getString("VoteParty.Broadcast", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getVotePartyBungeeCommands() {
|
||||
return getData().getStringList("VoteParty.BungeeCommands");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVotePartyEnabled() {
|
||||
return getData().getBoolean("VoteParty.Enabled", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVotePartyIncreaseVotesRequired() {
|
||||
return getData().getInt("VoteParty.IncreaseVotesRequired", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getVotePartySendToAllServers() {
|
||||
return getData().getBoolean("VoteParty.SendToAllServers", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getVotePartyServersToSend() {
|
||||
return getData().getStringList("VoteParty.ServersToSend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVotePartyVotesRequired() {
|
||||
return getData().getInt("VoteParty.VotesRequired", 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getWaitForUserOnline() {
|
||||
return getData().getBoolean("WaitForUserOnline", false);
|
||||
return getData().getBoolean("WaitForUserOnline", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getWhiteListedServers() {
|
||||
return getData().getStringList("WhiteListedServers");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttClientID() {
|
||||
return getData().getString("MQTT.ClientID", "proxy");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttBrokerURL() {
|
||||
return getData().getString("MQTT.BrokerURL", "tcp://localhost:1883");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttUsername() {
|
||||
return getData().getString("MQTT.Username", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttPassword() {
|
||||
return getData().getString("MQTT.Password", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttPrefix() {
|
||||
return getData().getString("MQTT.Prefix", "");
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (!bungee.getDataFolder().exists()) {
|
||||
bungee.getDataFolder().mkdir();
|
||||
@@ -294,4 +408,92 @@ public class Config implements VotingPluginProxyConfig {
|
||||
return getData().getBoolean("PluginMessageEncryption", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getWaitUntilVoteDelaySites() {
|
||||
return getData().getSection("WaitUntilVoteDelay").getKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWaitUntilVoteDelayService(String site) {
|
||||
return getData().getString("WaitUntilVoteDelay." + site + ".ServiceSite", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaitUntilVoteDelayVoteDelay(String site) {
|
||||
return getData().getInt("WaitUntilVoteDelay." + site + ".VoteDelay", 24);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getWaitUntilVoteDelayVoteDelayDaily(String site) {
|
||||
return getData().getBoolean("WaitUntilVoteDelay." + site + ".VoteDelayDaily", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaitUntilVoteDelayVoteDelayHour(String site) {
|
||||
return getData().getInt("WaitUntilVoteDelay." + site + ".VoteDelayDailyHour", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaitUntilVoteDelayVoteDelayMin(String site) {
|
||||
return getData().getInt("WaitUntilVoteDelay." + site + ".VoteDelayMin", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
}
|
||||
+548
-524
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();
|
||||
}
|
||||
|
||||
}
|
||||
+229
-17
@@ -2,6 +2,8 @@ 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;
|
||||
@@ -11,98 +13,148 @@ 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllowUnJoined() {
|
||||
return getBoolean(getNode("AllowUnJoined"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBedrockPlayerPrefix() {
|
||||
return getString(getNode("BedrockPlayerPrefix"), ".");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public List<String> getBlockedServers() {
|
||||
return getStringList(getNode("BlockedServers"), new ArrayList<>());
|
||||
}
|
||||
|
||||
public boolean getBroadcast() {
|
||||
return getBoolean(getNode("Broadcast"), false);
|
||||
@Override
|
||||
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
|
||||
public String getBungeeHost() {
|
||||
return getString(getNode("BungeeServer", "Host"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBungeeManageTotals() {
|
||||
return getBoolean(getNode("BungeeManageTotals"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBungeeMethod() {
|
||||
return getString(getNode("BungeeMethod"), "PLUGINMESSAGING");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBungeePort() {
|
||||
return getInt(getNode("BungeeServer", "Port"), 1297);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDebug() {
|
||||
return getBoolean(getNode("Debug"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFallBack() {
|
||||
return getString(getNode("FallBackServer"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getGlobalDataEnabled() {
|
||||
return getBoolean(getNode("GlobalData", "Enabled"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getGlobalDataUseMainMySQL() {
|
||||
return getBoolean(getNode("GlobalData", "UseMainMySQL"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLimitVotePoints() {
|
||||
return getInt(getNode("LimitVotePoints"), -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAmountOfVotesPerDay() {
|
||||
return getInt(getNode("MaxAmountOfVotesPerDay"), -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxyMethod() {
|
||||
return getString(getNode("MultiProxyMethod"), "SOCKET");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getMultiProxyOneGlobalReward() {
|
||||
return getBoolean(getNode("MultiProxyOneGlobalReward"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxyRedisHost() {
|
||||
return getString(getNode("MultiProxyRedis", "Host"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxyRedisPassword() {
|
||||
return getString(getNode("MultiProxyRedis", "Password"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMultiProxyRedisPort() {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxyRedisUsername() {
|
||||
return getString(getNode("MultiProxyRedis", "Username"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull List<String> getMultiProxyServers() {
|
||||
return getChildrenAsList(getNode("MultiProxyServers"));
|
||||
}
|
||||
@@ -110,25 +162,29 @@ 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());
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getMultiProxyServersConfiguration(String s) {
|
||||
return configToMap(getNode("MultiProxyServers", s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultiProxySocketHostHost() {
|
||||
return getString(getNode("MultiProxySocketHost", "Host"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMultiProxySocketHostPort() {
|
||||
return getInt(getNode("MultiProxySocketHost", "Port"), 1297);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getMultiProxySupport() {
|
||||
return getBoolean(getNode("MultiProxySupport"), false);
|
||||
}
|
||||
@@ -137,124 +193,181 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
return getNode("MySQL");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOnlineMode() {
|
||||
return getBoolean(getNode("OnlineMode"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointsOnVote() {
|
||||
return getInt(getNode("PointsOnVote"), 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPrimaryServer() {
|
||||
return getBoolean(getNode("PrimaryServer"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProxyServerName() {
|
||||
return getString(getNode("ProxyServerName"), "SOCKET");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getProxyServers() {
|
||||
return getStringList(getNode("ProxyServers"), new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedisHost() {
|
||||
return getString(getNode("Redis", "Host"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedisPassword() {
|
||||
return getString(getNode("Redis", "Password"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRedisPort() {
|
||||
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"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRedisUsername() {
|
||||
return getString(getNode("Redis", "Username"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSendVotesToAllServers() {
|
||||
return getBoolean(getNode("SendVotesToAllServers"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getSpigotServerConfiguration(String s) {
|
||||
return configToMap(getNode("SpigotServers", s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttClientID() {
|
||||
return getString(getNode("MQTT", "ClientID"), "proxy");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttBrokerURL() {
|
||||
return getString(getNode("MQTT", "BrokerURL"), "tcp://localhost:1883");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttUsername() {
|
||||
return getString(getNode("MQTT", "Username"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttPassword() {
|
||||
return getString(getNode("MQTT", "Password"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMqttPrefix() {
|
||||
return getString(getNode("MQTT", "Prefix"), "");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull List<String> getSpigotServers() {
|
||||
return getChildrenAsList(getNode("SpigotServers"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getStoreMonthTotalsWithDate() {
|
||||
return getBoolean(getNode("StoreMonthTotalsWithDate"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTimeChangeFailSafeBypass() {
|
||||
return getBoolean(getNode("TimeChangeFailSafeBypass"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getUseMonthDateTotalsAsPrimaryTotal() {
|
||||
return getBoolean(getNode("UseMonthDateTotalsAsPrimaryTotal"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getUUIDLookup() {
|
||||
return getBoolean(getNode("UUIDLookup"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVoteCacheTime() {
|
||||
return getInt(getNode("VoteCacheTime"), -1);
|
||||
}
|
||||
|
||||
@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() {
|
||||
return getNode("VoteParty");
|
||||
}
|
||||
|
||||
@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
|
||||
public boolean getWaitForUserOnline() {
|
||||
return getBoolean(getNode("WaitForUserOnline"), false);
|
||||
return getBoolean(getNode("WaitForUserOnline"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getWhiteListedServers() {
|
||||
return getStringList(getNode("WhiteListedServers"), new ArrayList<>());
|
||||
}
|
||||
@@ -285,4 +398,103 @@ public class Config extends VelocityYMLFile implements VotingPluginProxyConfig {
|
||||
return getBoolean(getNode("PluginMessageEncryption"), false);
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public Collection<String> getWaitUntilVoteDelaySites() {
|
||||
return getChildrenAsList(getNode("WaitUntilVoteDelay"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWaitUntilVoteDelayService(String site) {
|
||||
return getString(getNode("WaitUntilVoteDelay", site, "ServiceSite"), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaitUntilVoteDelayVoteDelay(String site) {
|
||||
return getInt(getNode("WaitUntilVoteDelay", site, "VoteDelay"), 24);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getWaitUntilVoteDelayVoteDelayDaily(String site) {
|
||||
return getBoolean(getNode("WaitUntilVoteDelay", site, "VoteDelayDaily"), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaitUntilVoteDelayVoteDelayHour(String site) {
|
||||
return getInt(getNode("WaitUntilVoteDelay", site, "VoteDelayDailyHour"), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaitUntilVoteDelayVoteDelayMin(String site) {
|
||||
return getInt(getNode("WaitUntilVoteDelay", site, "VoteDelayMin"), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
Loaded 100 of 191 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user