├── .github
└── workflows
│ └── gradle.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── build.gradle
├── crowdin.yml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── libs
└── nuvotifier-2.7.3.jar
├── renovate.json
├── settings.gradle
├── src
└── main
│ ├── java
│ └── me
│ │ └── clip
│ │ └── voteparty
│ │ └── plugin
│ │ └── VotePartyPlugin.java
│ ├── kotlin
│ └── me
│ │ └── clip
│ │ └── voteparty
│ │ ├── VoteParty.kt
│ │ ├── base
│ │ ├── Addon.kt
│ │ └── State.kt
│ │ ├── bungee
│ │ └── NuVotifierBungeeHandler.kt
│ │ ├── cmds
│ │ └── CommandVoteParty.kt
│ │ ├── conf
│ │ ├── VoteDataConfiguration.kt
│ │ ├── VotePartyConfiguration.kt
│ │ ├── mapper
│ │ │ └── SingleValueToCollectionMapper.kt
│ │ ├── migrations
│ │ │ └── VoteMigrationService.kt
│ │ ├── objects
│ │ │ ├── Command.kt
│ │ │ ├── Commands.kt
│ │ │ ├── Counter.kt
│ │ │ ├── CumulativeVoteCommands.kt
│ │ │ ├── CumulativeVoteRewards.kt
│ │ │ ├── CumulativeVoting.kt
│ │ │ ├── Effects.kt
│ │ │ ├── NuVotifier.kt
│ │ │ ├── PermCommands.kt
│ │ │ ├── PermRewards.kt
│ │ │ ├── RewardsPerEvent.kt
│ │ │ ├── VotesiteCommands.kt
│ │ │ └── VotesiteRewards.kt
│ │ └── sections
│ │ │ ├── CrateSettings.kt
│ │ │ ├── EffectsSettings.kt
│ │ │ ├── HookSettings.kt
│ │ │ ├── PartySettings.kt
│ │ │ ├── PluginSettings.kt
│ │ │ ├── VoteData.kt
│ │ │ └── VoteSettings.kt
│ │ ├── data
│ │ ├── base
│ │ │ ├── DatabaseVotePlayer.kt
│ │ │ ├── PartiesCache.kt
│ │ │ └── VotedForPartyCache.kt
│ │ └── impl
│ │ │ ├── DatabaseVotePlayerGson.kt
│ │ │ ├── PartiesCacheGson.kt
│ │ │ └── VotedForPartyCacheGson.kt
│ │ ├── events
│ │ ├── PartyEndEvent.kt
│ │ ├── PartyStartEvent.kt
│ │ ├── PrePartyEvent.kt
│ │ └── VoteReceivedEvent.kt
│ │ ├── exte
│ │ ├── const.kt
│ │ ├── funcs.kt
│ │ └── texts.kt
│ │ ├── handler
│ │ ├── LeaderboardHandler.kt
│ │ ├── PartyHandler.kt
│ │ └── VotesHandler.kt
│ │ ├── leaderboard
│ │ ├── Leaderboard.kt
│ │ ├── LeaderboardType.kt
│ │ └── LeaderboardUser.kt
│ │ ├── listener
│ │ ├── CrateListener.kt
│ │ ├── HooksListenerNuVotifier.kt
│ │ ├── VotesListener.kt
│ │ └── base
│ │ │ └── VotePartyListener.kt
│ │ ├── messages
│ │ └── Messages.kt
│ │ ├── placeholders
│ │ └── VotePartyPlaceholders.kt
│ │ ├── user
│ │ ├── User.kt
│ │ └── UsersHandler.kt
│ │ └── util
│ │ ├── JarFileWalker.kt
│ │ └── UpdateChecker.kt
│ └── resources
│ ├── config.yml
│ ├── languages
│ ├── de-DE.yml
│ ├── en-US.yml
│ ├── fr-FR.yml
│ ├── nl-NL.yml
│ └── sv-SE.yml
│ ├── parties.json
│ ├── plugin.yml
│ ├── voted-for-party-cache.json
│ └── votes.yml
├── version
├── build.gradle
└── src
│ └── main
│ └── kotlin
│ └── me
│ └── clip
│ └── voteparty
│ └── version
│ ├── EffectType.kt
│ └── VersionHook.kt
├── version_new
├── build.gradle
└── src
│ └── main
│ └── kotlin
│ └── me
│ └── clip
│ └── voteparty
│ └── version
│ └── VersionHookNew.kt
└── version_old
├── build.gradle
└── src
└── main
└── kotlin
└── me
└── clip
└── voteparty
└── version
└── VersionHookOld.kt
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: CI
4 |
5 | # Controls when the action will run. Triggers the workflow on push or pull request
6 | # events but only for the master branch
7 | on:
8 | push:
9 | branches: [ master ]
10 | pull_request:
11 | branches: [ master ]
12 |
13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
14 | jobs:
15 | # This workflow contains a single job called "build"
16 | build:
17 | # The type of runner that the job will run on
18 | runs-on: ubuntu-latest
19 |
20 | # Steps represent a sequence of tasks that will be executed as part of the job
21 | steps:
22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
23 | - uses: actions/checkout@v4
24 | - uses: actions/setup-java@v4
25 | with:
26 | distribution: 'zulu'
27 | java-version: '11'
28 | - name: Gradle Test Build
29 | run: ./gradlew clean shadowJar
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore Gradle project-specific cache directory
2 | .gradle
3 |
4 | # Ignore Gradle build output directory
5 | build
6 |
7 | # IntelliJ
8 | .idea
9 |
10 | out
11 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Glare
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
Welcome to VoteParty 👋
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | > Give rewards to all online players when the server gets a certain amount of votes! 1.8+
14 |
15 | ## Author
16 |
17 | 👤 **Glare**
18 |
19 | * Website: https://glaremasters.me/
20 | * Github: [@darbyjack](https://github.com/darbyjack)
21 |
22 | ## Get Help
23 | [](https://discord.gg/helpchat)
24 |
25 | ## 🤝 Contributing
26 |
27 | Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/darbyjack/VoteParty/issues).
28 |
29 | ## Show your support
30 |
31 | Give a ⭐️ if this project helped you!
32 |
33 | ## 📝 License
34 |
35 | Copyright © 2021 [darbyjack](https://github.com/darbyjack).
36 | This project is [MIT](https://github.com/darbyjack/VoteParty/blob/master/LICENSE.md) licensed.
37 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | import org.apache.tools.ant.filters.ReplaceTokens
2 |
3 | plugins {
4 | id 'org.jetbrains.kotlin.jvm' version '2.0.0'
5 | id 'io.github.goooler.shadow' version '8.1.7' apply false
6 | id "com.github.ben-manes.versions" version "0.51.0"
7 | id "net.kyori.indra" version "3.1.3"
8 | id "net.kyori.indra.publishing" version "3.1.3"
9 | }
10 |
11 | allprojects {
12 | apply plugin: 'org.jetbrains.kotlin.jvm'
13 | apply plugin: 'net.kyori.indra'
14 | apply plugin: 'net.kyori.indra.publishing'
15 |
16 | archivesBaseName = 'VoteParty'
17 | group 'me.clip'
18 | version '2.40-SNAPSHOT'
19 |
20 | repositories {
21 | mavenCentral()
22 |
23 | maven { url = "https://oss.sonatype.org/content/repositories/snapshots/" }
24 | maven { url = "https://repo.aikar.co/content/groups/aikar/" }
25 | maven { url = "https://papermc.io/repo/repository/maven-public/" }
26 | maven { url = "https://repo.extendedclip.com/content/repositories/placeholderapi/" }
27 | maven { url = "https://repo.glaremasters.me/repository/public/" }
28 | }
29 |
30 | dependencies {
31 | // kotlin
32 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
33 |
34 | // Support for materials across all versions
35 | implementation 'com.github.cryptomorin:XSeries:11.1.0'
36 | }
37 |
38 | indra {
39 | mitLicense()
40 |
41 | javaVersions {
42 | target(8)
43 | }
44 |
45 | github("darbyjack", "voteparty") {
46 | publishing(true)
47 | }
48 |
49 | publishAllTo("nexus", "https://repo.glaremasters.me/repository/random-stuff/")
50 | }
51 |
52 | compileJava {
53 | options.compilerArgs += ["-parameters"]
54 | }
55 |
56 | compileKotlin {
57 | kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8
58 | kotlinOptions.javaParameters = true
59 | }
60 | }
61 |
62 | apply plugin: 'io.github.goooler.shadow'
63 |
64 | shadowJar {
65 | minimize()
66 | relocate("co.aikar.commands", "me.clip.voteparty.libs.acf")
67 | relocate("co.aikar.locales", "me.clip.voteparty.libs.locales")
68 | relocate("ch.jalu.configme", "me.clip.voteparty.libs.configme")
69 | relocate("org.inventivetalent", "me.clip.voteparty.libs.inventivetalent")
70 | relocate("net.kyori", "me.clip.voteparty.libs.kyori")
71 | relocate("com.cryptomorin.xseries", "me.clip.voteparty.libs.xseries")
72 | relocate("kotlin", "me.clip.voteparty.libs.kotlin")
73 | relocate("org.bstats", "me.clip.voteparty.libs.bstats")
74 | archiveFileName = "VoteParty-${project.version}.jar"
75 | }
76 |
77 |
78 | dependencies {
79 |
80 | // spigot
81 | compileOnly "org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT"
82 |
83 | // config
84 | implementation "ch.jalu:configme:1.3.0"
85 |
86 | // placeholderapi
87 | compileOnly "me.clip:placeholderapi:2.11.6"
88 |
89 | // NuVotifier hook
90 | compileOnly files("libs/nuvotifier-2.7.3.jar")
91 |
92 | // command handler
93 | implementation "co.aikar:acf-paper:0.5.1-SNAPSHOT"
94 |
95 | // bstats
96 | implementation 'org.bstats:bstats-bukkit:3.0.2'
97 |
98 | // json stuff
99 | implementation 'net.kyori:adventure-platform-bukkit:4.3.3'
100 | implementation 'net.kyori:adventure-api:4.17.0'
101 | implementation 'net.kyori:adventure-text-minimessage:4.17.0'
102 |
103 | implementation project(":version")
104 | implementation project(":version_old")
105 | implementation project(":version_new")
106 | }
107 |
108 | processResources {
109 | filter ReplaceTokens, tokens: [version: version]
110 | }
111 |
--------------------------------------------------------------------------------
/crowdin.yml:
--------------------------------------------------------------------------------
1 | files:
2 | - source: /src/main/resources/languages/en-US.yml
3 | translation: /src/main/resources/languages/%locale%.yml
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darbyjack/VoteParty/456c4c7565bfdaa1f917c7259486126e1f0abd2c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
147 | # shellcheck disable=SC3045
148 | MAX_FD=$( ulimit -H -n ) ||
149 | warn "Could not query maximum file descriptor limit"
150 | esac
151 | case $MAX_FD in #(
152 | '' | soft) :;; #(
153 | *)
154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
155 | # shellcheck disable=SC3045
156 | ulimit -n "$MAX_FD" ||
157 | warn "Could not set maximum file descriptor limit to $MAX_FD"
158 | esac
159 | fi
160 |
161 | # Collect all arguments for the java command, stacking in reverse order:
162 | # * args from the command line
163 | # * the main class name
164 | # * -classpath
165 | # * -D...appname settings
166 | # * --module-path (only if needed)
167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
168 |
169 | # For Cygwin or MSYS, switch paths to Windows format before running java
170 | if "$cygwin" || "$msys" ; then
171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
173 |
174 | JAVACMD=$( cygpath --unix "$JAVACMD" )
175 |
176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
177 | for arg do
178 | if
179 | case $arg in #(
180 | -*) false ;; # don't mess with options #(
181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
182 | [ -e "$t" ] ;; #(
183 | *) false ;;
184 | esac
185 | then
186 | arg=$( cygpath --path --ignore --mixed "$arg" )
187 | fi
188 | # Roll the args list around exactly as many times as the number of
189 | # args, so each arg winds up back in the position where it started, but
190 | # possibly modified.
191 | #
192 | # NB: a `for` loop captures its iteration list before it begins, so
193 | # changing the positional parameters here affects neither the number of
194 | # iterations, nor the values presented in `arg`.
195 | shift # remove old arg
196 | set -- "$@" "$arg" # push replacement arg
197 | done
198 | fi
199 |
200 | # Collect all arguments for the java command;
201 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
202 | # shell script including quotes and variable substitutions, so put them in
203 | # double quotes to make sure that they get re-expanded; and
204 | # * put everything else in single quotes, so that it's not re-expanded.
205 |
206 | set -- \
207 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
208 | -classpath "$CLASSPATH" \
209 | org.gradle.wrapper.GradleWrapperMain \
210 | "$@"
211 |
212 | # Stop when "xargs" is not available.
213 | if ! command -v xargs >/dev/null 2>&1
214 | then
215 | die "xargs is not available"
216 | fi
217 |
218 | # Use "xargs" to parse quoted args.
219 | #
220 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
221 | #
222 | # In Bash we could simply go:
223 | #
224 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
225 | # set -- "${ARGS[@]}" "$@"
226 | #
227 | # but POSIX shell has neither arrays nor command substitution, so instead we
228 | # post-process each arg (as a line of input to sed) to backslash-escape any
229 | # character that might be a shell metacharacter, then use eval to reverse
230 | # that process (while maintaining the separation between arguments), and wrap
231 | # the whole thing up as a single "set" statement.
232 | #
233 | # This will of course break if any of these variables contains a newline or
234 | # an unmatched quote.
235 | #
236 |
237 | eval "set -- $(
238 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
239 | xargs -n1 |
240 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
241 | tr '\n' ' '
242 | )" '"$@"'
243 |
244 | exec "$JAVACMD" "$@"
245 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/libs/nuvotifier-2.7.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darbyjack/VoteParty/456c4c7565bfdaa1f917c7259486126e1f0abd2c/libs/nuvotifier-2.7.3.jar
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:base"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = "VP"
2 | include 'version'
3 | include 'version_old'
4 | include 'version_new'
5 |
6 |
--------------------------------------------------------------------------------
/src/main/java/me/clip/voteparty/plugin/VotePartyPlugin.java:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.plugin;
2 |
3 | import me.clip.voteparty.VoteParty;
4 | import org.bstats.bukkit.Metrics;
5 | import org.bukkit.plugin.ServicePriority;
6 | import org.bukkit.plugin.java.JavaPlugin;
7 | import org.jetbrains.annotations.Nullable;
8 |
9 | public final class VotePartyPlugin extends JavaPlugin
10 | {
11 | private VoteParty voteParty;
12 |
13 | @Override
14 | public void onEnable()
15 | {
16 | this.voteParty = new VoteParty(this);
17 | this.voteParty.load();
18 |
19 | new Metrics(this, 17932);
20 |
21 | getServer().getServicesManager().register(VoteParty.class, this.voteParty, this, ServicePriority.Normal);
22 | }
23 |
24 | @Override
25 | public void onDisable()
26 | {
27 | if (this.voteParty != null)
28 | {
29 | this.voteParty.kill();
30 | }
31 |
32 | this.voteParty = null;
33 |
34 | getServer().getServicesManager().unregisterAll(this);
35 | }
36 |
37 |
38 | @Nullable
39 | public VoteParty getVoteParty()
40 | {
41 | return this.voteParty;
42 | }
43 |
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/VoteParty.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty
2 |
3 | import ch.jalu.configme.SettingsManager
4 | import co.aikar.commands.PaperCommandManager
5 | import com.google.gson.Gson
6 | import me.clip.voteparty.base.State
7 | import me.clip.voteparty.bungee.NuVotifierBungeeHandler
8 | import me.clip.voteparty.cmds.CommandVoteParty
9 | import me.clip.voteparty.conf.VoteDataConfiguration
10 | import me.clip.voteparty.conf.VotePartyConfiguration
11 | import me.clip.voteparty.conf.sections.VoteSettings
12 | import me.clip.voteparty.conf.sections.HookSettings
13 | import me.clip.voteparty.conf.sections.PartySettings
14 | import me.clip.voteparty.conf.sections.PluginSettings
15 | import me.clip.voteparty.conf.sections.VoteData
16 | import me.clip.voteparty.data.impl.PartiesCacheGson
17 | import me.clip.voteparty.data.impl.VotedForPartyCacheGson
18 | import me.clip.voteparty.exte.color
19 | import me.clip.voteparty.exte.runTaskTimer
20 | import me.clip.voteparty.exte.runTaskTimerAsync
21 | import me.clip.voteparty.handler.LeaderboardHandler
22 | import me.clip.voteparty.handler.PartyHandler
23 | import me.clip.voteparty.handler.VotesHandler
24 | import me.clip.voteparty.listener.CrateListener
25 | import me.clip.voteparty.listener.HooksListenerNuVotifier
26 | import me.clip.voteparty.listener.VotesListener
27 | import me.clip.voteparty.placeholders.VotePartyPlaceholders
28 | import me.clip.voteparty.plugin.VotePartyPlugin
29 | import me.clip.voteparty.user.UsersHandler
30 | import me.clip.voteparty.util.JarFileWalker
31 | import me.clip.voteparty.util.UpdateChecker
32 | import me.clip.voteparty.version.VersionHook
33 | import me.clip.voteparty.version.VersionHookNew
34 | import me.clip.voteparty.version.VersionHookOld
35 | import net.kyori.adventure.platform.bukkit.BukkitAudiences
36 | import org.bukkit.Bukkit
37 | import org.bukkit.OfflinePlayer
38 | import org.bukkit.command.ConsoleCommandSender
39 | import org.bukkit.configuration.file.YamlConfiguration
40 | import org.bukkit.entity.Player
41 | import java.io.File
42 | import java.io.InputStream
43 | import java.util.Locale
44 | import java.util.logging.Level
45 |
46 | class VoteParty internal constructor(internal val plugin: VotePartyPlugin) : State
47 | {
48 |
49 | val votesHandler = VotesHandler(plugin)
50 | val partyHandler = PartyHandler(plugin)
51 | val usersHandler = UsersHandler(plugin)
52 | val leaderboardHandler = LeaderboardHandler(plugin)
53 |
54 |
55 | private var conf = null as? SettingsManager?
56 | private var voteData = null as? SettingsManager?
57 | private var audiences = null as? BukkitAudiences?
58 | private val cmds = PaperCommandManager(plugin)
59 |
60 | private val crateListener = CrateListener(plugin)
61 | private val votesListener = VotesListener(plugin)
62 | private val hooksListener = HooksListenerNuVotifier(plugin)
63 | private val votedForPartyCache = VotedForPartyCacheGson(plugin)
64 | private val partiesCache = PartiesCacheGson(plugin)
65 |
66 | private var hook = null as? VersionHook?
67 | private var papi = null as? VotePartyPlaceholders?
68 |
69 |
70 | override fun load()
71 | {
72 | logo(plugin.server.consoleSender)
73 |
74 | this.audiences = BukkitAudiences.create(plugin)
75 |
76 | loadConf()
77 | loadVoteData()
78 | loadCmds()
79 | loadHook()
80 | loadPapi()
81 |
82 | saveLang()
83 | loadLang()
84 |
85 | checkForUpdates()
86 |
87 | // handlers
88 | votesHandler.load()
89 | usersHandler.load()
90 | leaderboardHandler.load()
91 |
92 | // listeners
93 | crateListener.load()
94 | votesListener.load()
95 |
96 | // voted for party cache
97 | votedForPartyCache.load()
98 |
99 | // parties cache
100 | partiesCache.load()
101 |
102 | if (conf().getProperty(HookSettings.NUVOTIFIER).backend)
103 | {
104 | hooksListener.load()
105 | }
106 |
107 | if (conf().getProperty(HookSettings.NUVOTIFIER).pluginMessaging) {
108 | NuVotifierBungeeHandler(plugin).load()
109 | }
110 |
111 | // votes
112 | loadVotes()
113 |
114 | plugin.runTaskTimerAsync(conf().getProperty(PluginSettings.SAVE_INTERVAL).toLong() * 20L)
115 | {
116 | saveVotes()
117 | }
118 |
119 | plugin.runTaskTimerAsync(conf().getProperty(PluginSettings.PLAYER_SAVE_INTERVAL).toLong() * 20L)
120 | {
121 | usersHandler.saveAll()
122 | votedForPartyCache.save()
123 | partiesCache.save()
124 | }
125 |
126 | if (conf().getProperty(VoteSettings.REMINDER_ENABLED)) {
127 | plugin.runTaskTimer(conf().getProperty(VoteSettings.REMINDER_INTERVAL_SECONDS).toLong() * 20L)
128 | {
129 | votesHandler.sendVoteReminders()
130 | }
131 | }
132 | }
133 |
134 | override fun kill()
135 | {
136 | saveVotes()
137 | if (conf().getProperty(HookSettings.NUVOTIFIER).backend)
138 | {
139 | hooksListener.kill()
140 | }
141 | crateListener.kill()
142 | votesListener.kill()
143 |
144 | usersHandler.kill()
145 | leaderboardHandler.kill()
146 | votedForPartyCache.kill()
147 | partiesCache.kill()
148 | }
149 |
150 |
151 | private fun loadConf()
152 | {
153 | val file = plugin.dataFolder.resolve("config.yml")
154 |
155 | if (!file.exists())
156 | {
157 | file.parentFile.mkdirs()
158 | file.createNewFile()
159 | }
160 |
161 | this.conf = VotePartyConfiguration(file)
162 | }
163 |
164 | private fun loadVoteData()
165 | {
166 | val file = plugin.dataFolder.resolve("votes.yml")
167 |
168 | if (!file.exists()) {
169 | file.parentFile.mkdirs()
170 | file.createNewFile()
171 | }
172 |
173 | this.voteData = VoteDataConfiguration(file)
174 | }
175 |
176 | private fun saveLang()
177 | {
178 | JarFileWalker.walk("/languages")
179 | { path, stream ->
180 |
181 | if (stream == null)
182 | {
183 | return@walk // do nothing if the stream couldn't be opened
184 | }
185 |
186 | val file = plugin.dataFolder.resolve(path.toString().drop(1)).absoluteFile
187 | if (file.exists())
188 | {
189 | mergeLanguage(stream, file)
190 | return@walk // language file was already created
191 | }
192 |
193 | file.parentFile.mkdirs()
194 | file.createNewFile()
195 |
196 | file.outputStream().use()
197 | {
198 | stream.copyTo(it)
199 | stream.close()
200 | }
201 | }
202 | }
203 |
204 | private fun mergeLanguage(stream: InputStream, outside: File)
205 | {
206 | val new = YamlConfiguration.loadConfiguration(stream.reader())
207 | val old = YamlConfiguration.loadConfiguration(outside)
208 |
209 | for (path in new.getKeys(true))
210 | {
211 | if (!old.contains(path)) {
212 | old.set(path, old.get(path, new.get(path)))
213 | }
214 | }
215 | old.save(outside)
216 | }
217 |
218 | private fun loadCmds()
219 | {
220 | if (conf().getProperty(PluginSettings.BRIGADIER))
221 | {
222 | cmds.enableUnstableAPI("brigadier")
223 | }
224 |
225 | cmds.locales.defaultLocale = Locale.forLanguageTag(conf().getProperty(PluginSettings.LANGUAGE) ?: "en-US")
226 | cmds.usePerIssuerLocale(false, false)
227 |
228 | cmds.commandCompletions.registerCompletion("online")
229 | {
230 | plugin.server.onlinePlayers.map(Player::getName)
231 | }
232 |
233 | cmds.commandReplacements.addReplacement("vp", "vp|voteparty")
234 |
235 | cmds.registerCommand(CommandVoteParty(plugin))
236 | }
237 |
238 | private fun loadHook()
239 | {
240 | this.hook = if (Bukkit.getBukkitVersion().substringBefore('-').substringAfter('.').substringBefore('.').toInt() >= 13)
241 | {
242 | VersionHookNew()
243 | }
244 | else
245 | {
246 | VersionHookOld()
247 | }
248 | }
249 |
250 | private fun loadPapi()
251 | {
252 | val papi = VotePartyPlaceholders(this)
253 | papi.register()
254 |
255 | this.papi = papi
256 | }
257 |
258 |
259 | private fun loadVotes()
260 | {
261 | votesHandler.setVotes(voteData().getProperty(VoteData.COUNTER))
262 | }
263 |
264 | private fun saveVotes()
265 | {
266 | voteData().setProperty(VoteData.COUNTER, votesHandler.getVotes())
267 | voteData().save()
268 | }
269 |
270 |
271 | private fun logo(sender: ConsoleCommandSender)
272 | {
273 | val logo = LOGO.replace("{plugin_version}", plugin.description.version).replace("{server_version}", plugin.server.version)
274 | sender.sendMessage(color(logo))
275 | }
276 |
277 | private fun checkForUpdates()
278 | {
279 | UpdateChecker.check(plugin, 987)
280 | {
281 | when (it)
282 | {
283 | is UpdateChecker.UpdateResult.UP_TO_DATE ->
284 | {
285 | plugin.logger.info(it.message)
286 | }
287 | is UpdateChecker.UpdateResult.UNRELEASED ->
288 | {
289 | plugin.logger.warning(it.message)
290 | }
291 | is UpdateChecker.UpdateResult.NEW_UPDATE ->
292 | {
293 | plugin.logger.info("${it.message}: ${it.version}")
294 | }
295 | is UpdateChecker.UpdateResult.EXCEPTIONS ->
296 | {
297 | plugin.logger.log(Level.WARNING, it.message, it.throwable)
298 | }
299 | }
300 | }
301 | }
302 |
303 |
304 | fun loadLang()
305 | {
306 | plugin.dataFolder.resolve("languages").listFiles()?.filter()
307 | {
308 | it.extension.equals("yml", true)
309 | }?.forEach()
310 | {
311 | val locale = Locale.forLanguageTag(it.nameWithoutExtension)
312 |
313 | cmds.addSupportedLanguage(locale)
314 | cmds.locales.loadYamlLanguageFile(it, locale)
315 | }
316 | }
317 |
318 |
319 | fun conf(): SettingsManager
320 | {
321 | return checkNotNull(conf)
322 | }
323 |
324 | fun voteData(): SettingsManager
325 | {
326 | return checkNotNull(voteData)
327 | }
328 |
329 | fun hook(): VersionHook
330 | {
331 | return checkNotNull(hook)
332 | }
333 |
334 | fun manager(): PaperCommandManager
335 | {
336 | return cmds
337 | }
338 |
339 | fun audiences(): BukkitAudiences
340 | {
341 | return checkNotNull(audiences)
342 | }
343 |
344 | fun getVotes(): Int
345 | {
346 | return votesHandler.getVotes()
347 | }
348 |
349 | fun getVotesNeeded(): Int
350 | {
351 | return conf().getProperty(PartySettings.VOTES_NEEDED)
352 | }
353 |
354 | @Deprecated("This was only used in the PlaceholderAPI Placeholders. A new and improved method has been implemented", ReplaceWith("UserHandler#getVotesWithinRange"))
355 | fun getPlayerVotes(player: OfflinePlayer): Int
356 | {
357 | return usersHandler[player].votes().size
358 | }
359 |
360 |
361 | internal companion object
362 | {
363 | internal val GSON = Gson()
364 | internal val LOGO =
365 | """
366 |
367 | &6 _ _ &d ____
368 | &6/ )( \&d( _ \
369 | &6\ \/ /&d ) __/ &3VoteParty &8v{plugin_version}
370 | &6 \__/ &d(__) &3Server Version: &8{server_version}
371 |
372 | """.trimIndent()
373 | }
374 |
375 | }
376 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/base/Addon.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.base
2 |
3 | import me.clip.voteparty.VoteParty
4 | import me.clip.voteparty.plugin.VotePartyPlugin
5 | import org.bukkit.Server
6 | import java.util.logging.Logger
7 |
8 | /**
9 | * Defines an aspect of the plugin that requires access to spigot api
10 | */
11 | internal interface Addon
12 | {
13 |
14 | val plugin: VotePartyPlugin
15 |
16 | val server: Server
17 | get() = plugin.server
18 |
19 | val logger: Logger
20 | get() = plugin.logger
21 |
22 | val party: VoteParty
23 | get() = checkNotNull(plugin.voteParty)
24 | {
25 | "vote party is unavailable"
26 | }
27 |
28 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/base/State.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.base
2 |
3 | /**
4 | * Defines an object that holds state and requires enable and disable logic
5 | */
6 | internal interface State
7 | {
8 |
9 | /**
10 | * Holds logic for when this enables
11 | */
12 | fun load()
13 |
14 | /**
15 | * Holds logic for when this is disabled
16 | */
17 | fun kill()
18 |
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/bungee/NuVotifierBungeeHandler.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.bungee
2 |
3 | import com.google.gson.Gson
4 | import com.vexsoftware.votifier.model.Vote
5 | import me.clip.voteparty.base.Addon
6 | import me.clip.voteparty.base.State
7 | import me.clip.voteparty.conf.sections.HookSettings
8 | import me.clip.voteparty.conf.sections.VoteSettings
9 | import me.clip.voteparty.events.VoteReceivedEvent
10 | import me.clip.voteparty.plugin.VotePartyPlugin
11 | import org.bukkit.Bukkit
12 | import org.bukkit.entity.Player
13 | import org.bukkit.plugin.messaging.PluginMessageListener
14 | import java.nio.charset.StandardCharsets
15 | import java.util.regex.Pattern
16 |
17 | internal data class BungeeVote(
18 | val username: String,
19 | val address: String,
20 | val timestamp: String,
21 | val serviceName: String
22 | )
23 |
24 | internal class NuVotifierBungeeHandler(override val plugin: VotePartyPlugin) : Addon, State, PluginMessageListener {
25 | private lateinit var channel: String
26 | private lateinit var usernameRegex: Pattern
27 | private val gson = Gson()
28 |
29 | override fun load() {
30 | this.channel = party.conf().getProperty(HookSettings.NUVOTIFIER).pluginMessageChannel
31 | usernameRegex = Pattern.compile(party.conf().getProperty(VoteSettings.NAME_REGEX))
32 |
33 | Bukkit.getMessenger().registerIncomingPluginChannel(plugin, channel, this)
34 | Bukkit.getMessenger().registerOutgoingPluginChannel(plugin, channel)
35 | }
36 |
37 | override fun kill() {
38 | Bukkit.getMessenger().unregisterIncomingPluginChannel(plugin, channel, this)
39 | Bukkit.getMessenger().unregisterOutgoingPluginChannel(plugin, channel)
40 | }
41 |
42 | override fun onPluginMessageReceived(channel: String, player: Player, message: ByteArray?) {
43 | if (!channel.equals(this.channel, ignoreCase = true)) {
44 | return
45 | }
46 |
47 | if (message == null) {
48 | return
49 | }
50 |
51 | val content = String(message, StandardCharsets.UTF_8)
52 | val vote = gson.fromJson(content, BungeeVote::class.java)
53 |
54 | if (party.conf().getProperty(VoteSettings.VALIDATE_NAMES) && !usernameRegex.matcher(vote.username).matches()) {
55 | plugin.logger.warning("A vote came through NuVotifier (username: ${vote.username}) which did not match the username regex. Throwing away.")
56 | return
57 | }
58 |
59 | val player = party.usersHandler[vote.username]?.player() ?: server.getOfflinePlayer(vote.username)
60 | val event = VoteReceivedEvent(player, vote.serviceName)
61 | server.pluginManager.callEvent(event)
62 | }
63 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/cmds/CommandVoteParty.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.cmds
2 |
3 | import co.aikar.commands.BaseCommand
4 | import co.aikar.commands.CommandIssuer
5 | import co.aikar.commands.annotation.CommandAlias
6 | import co.aikar.commands.annotation.CommandCompletion
7 | import co.aikar.commands.annotation.CommandPermission
8 | import co.aikar.commands.annotation.Default
9 | import co.aikar.commands.annotation.Description
10 | import co.aikar.commands.annotation.Name
11 | import co.aikar.commands.annotation.Optional
12 | import co.aikar.commands.annotation.Subcommand
13 | import co.aikar.commands.annotation.Syntax
14 | import co.aikar.commands.annotation.Values
15 | import co.aikar.commands.bukkit.contexts.OnlinePlayer
16 | import me.clip.voteparty.base.Addon
17 | import me.clip.voteparty.conf.sections.PartySettings
18 | import me.clip.voteparty.conf.sections.VoteSettings
19 | import me.clip.voteparty.events.VoteReceivedEvent
20 | import me.clip.voteparty.exte.ADMIN_PERM
21 | import me.clip.voteparty.exte.CLAIM_PERM
22 | import me.clip.voteparty.exte.deserialize
23 | import me.clip.voteparty.exte.helpMenu
24 | import me.clip.voteparty.exte.msgAsString
25 | import me.clip.voteparty.exte.sendMessage
26 | import me.clip.voteparty.leaderboard.LeaderboardType
27 | import me.clip.voteparty.messages.Messages
28 | import me.clip.voteparty.plugin.VotePartyPlugin
29 | import net.kyori.adventure.identity.Identity
30 | import org.bukkit.OfflinePlayer
31 | import org.bukkit.entity.Player
32 | import java.util.*
33 | import java.util.concurrent.TimeUnit
34 | import kotlin.text.StringBuilder
35 |
36 | @CommandAlias("%vp")
37 | internal class CommandVoteParty(override val plugin: VotePartyPlugin) : BaseCommand(), Addon
38 | {
39 |
40 | @Subcommand("addvote")
41 | @Syntax(" [amount]")
42 | @Description("Add a vote to a player with the ability to trigger or not the rewards.")
43 | @CommandPermission(ADMIN_PERM)
44 | fun addVote(
45 | issuer: CommandIssuer,
46 | @Name("target") target: String,
47 | @Name("silent") @Default("false") silent: Boolean,
48 | @Name("amount") @Optional @Default("1") amount: Int
49 | ) {
50 |
51 | if (amount <= 0)
52 | {
53 | return sendMessage(issuer, Messages.ERROR__INVALID_NUMBER)
54 | }
55 |
56 | val user = party.usersHandler[target] ?: return sendMessage(issuer, Messages.ERROR__USER_NOT_FOUND)
57 |
58 | if (silent)
59 | {
60 | repeat(amount) {
61 | user.voted()
62 | }
63 |
64 | return sendMessage(issuer, Messages.VOTES__ADDED_TO_PLAYER, user.player(), "{count}", amount)
65 | }
66 |
67 | repeat(amount) {
68 | plugin.server.pluginManager.callEvent(VoteReceivedEvent(user.player(), ""))
69 | }
70 |
71 | return sendMessage(issuer, Messages.VOTES__ADDED_TO_PLAYER, user.player(), "{count}", amount)
72 | }
73 |
74 | @Subcommand("addpartyvote")
75 | @Syntax("")
76 | @Description("Add a Vote to the party")
77 | @CommandPermission(ADMIN_PERM)
78 | fun addPartyVote(issuer: CommandIssuer, @Default("1") amount: Int)
79 | {
80 |
81 | if (amount <= 0)
82 | {
83 | return sendMessage(issuer, Messages.ERROR__INVALID_NUMBER)
84 | }
85 |
86 | party.votesHandler.addVotes(amount)
87 | sendMessage(issuer, Messages.VOTES__VOTE_COUNTER_UPDATED)
88 | }
89 |
90 | @Subcommand("givecrate")
91 | @CommandCompletion("@online")
92 | @Syntax(" ")
93 | @Description("Give Crate")
94 | @CommandPermission(ADMIN_PERM)
95 | fun giveCrate(issuer: CommandIssuer, @Values("@online") target: OnlinePlayer, @Default("1") amount: Int)
96 | {
97 | if (amount <= 0)
98 | {
99 | return sendMessage(issuer, Messages.ERROR__INVALID_NUMBER)
100 | }
101 |
102 | sendMessage(issuer, Messages.CRATE__CRATE_GIVEN, target.player)
103 | sendMessage(currentCommandManager.getCommandIssuer(target.player), Messages.CRATE__CRATE_RECEIVED)
104 |
105 | target.player.inventory.addItem(party.partyHandler.buildCrate(amount))
106 | }
107 |
108 | @Subcommand("setcounter")
109 | @Syntax("")
110 | @Description("Set Counter")
111 | @CommandPermission(ADMIN_PERM)
112 | fun setCounter(issuer: CommandIssuer, amount: Int)
113 | {
114 | if (amount < 0)
115 | {
116 | return sendMessage(issuer, Messages.ERROR__INVALID_NUMBER)
117 | }
118 |
119 | party.conf().setProperty(PartySettings.VOTES_NEEDED, amount)
120 | party.conf().save()
121 |
122 | sendMessage(issuer, Messages.VOTES__VOTES_NEEDED_UPDATED)
123 | }
124 |
125 | @Subcommand("top")
126 | @Syntax(" [page]")
127 | @Description("List top voters")
128 | @CommandPermission("voteparty.top")
129 | fun top(issuer: CommandIssuer, type: LeaderboardType, @Default("1") page: Int)
130 | {
131 | if (page <= 0)
132 | {
133 | return sendMessage(issuer, Messages.ERROR__INVALID_NUMBER)
134 | }
135 |
136 |
137 | val leaderboard = party.leaderboardHandler.getLeaderboard(type)
138 | ?: return sendMessage(issuer, Messages.ERROR__LEADERBOARD_NOT_FOUND, null, "{type}", type.displayName)
139 |
140 | val pages = leaderboard.data.chunked(10)
141 | if (page > pages.size)
142 | {
143 | return sendMessage(issuer, Messages.ERROR__INVALID_PAGE_NUMBER, null, "{max}", pages.size.toString())
144 | }
145 |
146 | val actualPage = pages[page - 1]
147 | if (actualPage.isEmpty())
148 | {
149 | return sendMessage(issuer, Messages.ERROR__INVALID_PAGE_NUMBER, null, "{max}", pages.size.toString())
150 | }
151 |
152 |
153 |
154 | val message = StringBuilder()
155 | message.appendLine(
156 | msgAsString(issuer, Messages.TOP__HEADER)
157 | .replace("{type}", type.displayName)
158 | .replace("{page}", page.toString())
159 | .replace("{total}", pages.size.toString())
160 | )
161 |
162 | message.appendLine()
163 |
164 | for ((index, leaderboardUser) in actualPage.withIndex()) {
165 | message.appendLine(
166 | msgAsString(issuer, Messages.TOP__LINE)
167 | .replace("{position}", (index + 1).toString())
168 | .replace("{player}", leaderboardUser.user.name)
169 | .replace("{uuid}", leaderboardUser.user.uuid.toString())
170 | .replace("{votes}", leaderboardUser.votes.toString())
171 | )
172 | }
173 |
174 | message.appendLine()
175 |
176 | message.append(
177 | msgAsString(issuer, Messages.TOP__FOOTER)
178 | .replace("{type}", type.displayName)
179 | .replace("{page}", page.toString())
180 | .replace("{total}", pages.size.toString())
181 | )
182 |
183 | party.audiences().sender(issuer.getIssuer()).sendMessage(Identity.nil(), deserialize(message.toString()))
184 | }
185 |
186 | @Subcommand("checkvotes")
187 | @Syntax(" ")
188 | @CommandCompletion("@online")
189 | @Description("Check Votes")
190 | @CommandPermission(ADMIN_PERM)
191 | fun checkVotes(issuer: CommandIssuer, offlinePlayer: OfflinePlayer, amount: Long, unit: TimeUnit)
192 | {
193 | val count = party.usersHandler.getVoteCountSince(offlinePlayer, amount, unit)
194 | sendMessage(
195 | issuer,
196 | Messages.INFO__PLAYER_CHECK_VOTES,
197 | offlinePlayer,
198 | "{count}",
199 | count,
200 | "{amount}",
201 | amount,
202 | "{unit}",
203 | unit.toString().lowercase(Locale.getDefault())
204 | )
205 | }
206 |
207 | @Subcommand("totalvotes")
208 | @Syntax("")
209 | @CommandCompletion("@online")
210 | @Description("Total Votes")
211 | @CommandPermission(ADMIN_PERM)
212 | fun totalVotes(issuer: CommandIssuer, offlinePlayer: OfflinePlayer)
213 | {
214 | sendMessage(issuer, Messages.INFO__PLAYER_TOTAL_VOTES, offlinePlayer)
215 | }
216 |
217 | @Subcommand("resetvotes")
218 | @Syntax("")
219 | @CommandCompletion("@online")
220 | @Description("Reset Votes")
221 | @CommandPermission(ADMIN_PERM)
222 | fun resetVotes(issuer: CommandIssuer, offlinePlayer: OfflinePlayer)
223 | {
224 | party.usersHandler.reset(offlinePlayer)
225 | sendMessage(issuer, Messages.INFO__VOTE_COUNT_RESET, offlinePlayer)
226 | }
227 |
228 | @Subcommand("startparty")
229 | @Description("Start Party")
230 | @CommandPermission(ADMIN_PERM)
231 | fun startParty(issuer: CommandIssuer)
232 | {
233 | party.partyHandler.startParty()
234 | sendMessage(issuer, Messages.PARTY__FORCE_START_SUCCESSFUL)
235 | }
236 |
237 | @Subcommand("giveparty")
238 | @CommandCompletion("@players")
239 | @Description("Give Party")
240 | @Syntax("")
241 | @CommandPermission(ADMIN_PERM)
242 | fun giveParty(issuer: CommandIssuer, @Values("@players") target: OnlinePlayer)
243 | {
244 | if (target.player.world.name in party.conf().getProperty(PartySettings.DISABLED_WORLDS))
245 | {
246 | return sendMessage(issuer, Messages.ERROR__DISABLED_WORLD)
247 | }
248 |
249 | if (party.conf().getProperty(PartySettings.USE_CRATE))
250 | {
251 | target.player.inventory.addItem(party.partyHandler.buildCrate(1))
252 | }
253 | else
254 | {
255 | party.partyHandler.runAll(target.player)
256 | }
257 |
258 | sendMessage(issuer, Messages.VOTES__PRIVATE_PARTY_GIVEN, target.player)
259 | sendMessage(currentCommandManager.getCommandIssuer(target.player), Messages.VOTES__PRIVATE_PARTY_RECEIVED)
260 | }
261 |
262 | @Subcommand("reload")
263 | @Description("Reload")
264 | @CommandPermission(ADMIN_PERM)
265 | fun reload(issuer: CommandIssuer)
266 | {
267 | party.conf().reload()
268 | party.loadLang()
269 |
270 | sendMessage(issuer, Messages.INFO__RELOADED)
271 | }
272 |
273 | @Subcommand("claim")
274 | @Description("Claim")
275 | @CommandPermission(CLAIM_PERM)
276 | fun claim(player: Player)
277 | {
278 | val user = party.usersHandler[player]
279 |
280 | if (user.claimable <= 0)
281 | {
282 | return sendMessage(currentCommandIssuer, Messages.CLAIM__NONE)
283 | }
284 |
285 | if (player.inventory.firstEmpty() == -1 && party.conf().getProperty(VoteSettings.CLAIMABLE_IF_FULL))
286 | {
287 | return sendMessage(currentCommandIssuer, Messages.CLAIM__FULL)
288 | }
289 |
290 | party.votesHandler.runAll(player)
291 | user.claimable--
292 |
293 | sendMessage(currentCommandIssuer, Messages.CLAIM__SUCCESS, null, "{claim}", user.claimable)
294 | }
295 |
296 | @Subcommand("claimall")
297 | @Description("Claim All")
298 | @CommandPermission(CLAIM_PERM)
299 | fun claimAll(player: Player)
300 | {
301 | val user = party.usersHandler[player]
302 |
303 | if (user.claimable <= 0)
304 | {
305 | return sendMessage(currentCommandIssuer, Messages.CLAIM__NONE)
306 | }
307 |
308 | for (i in 1..user.claimable)
309 | {
310 | if (player.inventory.firstEmpty() == -1 && party.conf().getProperty(VoteSettings.CLAIMABLE_IF_FULL))
311 | {
312 | return sendMessage(currentCommandIssuer, Messages.CLAIM__FULL_ALL, null, "{claimed}", i, "{claim}", user.claimable)
313 | }
314 |
315 | party.votesHandler.runAll(player)
316 | user.claimable--
317 | }
318 | sendMessage(currentCommandIssuer, Messages.CLAIM__SUCCESS_ALL)
319 | }
320 |
321 | @Subcommand("help")
322 | @Description("Help")
323 | @CommandPermission("voteparty.help")
324 | fun help(issuer: CommandIssuer)
325 | {
326 | party.audiences().sender(issuer.getIssuer()).sendMessage(Identity.nil(), helpMenu(issuer))
327 | }
328 |
329 | @Default
330 | fun default(issuer: CommandIssuer)
331 | {
332 | sendMessage(issuer, Messages.INFO__VOTES_NEEDED)
333 | }
334 |
335 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/VoteDataConfiguration.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf
2 |
3 | import ch.jalu.configme.SettingsManagerImpl
4 | import ch.jalu.configme.configurationdata.ConfigurationDataBuilder
5 | import ch.jalu.configme.migration.PlainMigrationService
6 | import ch.jalu.configme.resource.YamlFileResource
7 | import me.clip.voteparty.conf.sections.VoteData
8 | import java.io.File
9 |
10 | internal class VoteDataConfiguration(file: File) : SettingsManagerImpl(YamlFileResource(file.toPath()), ConfigurationDataBuilder.createConfiguration(SECTIONS), PlainMigrationService())
11 | {
12 | private companion object
13 | {
14 | private val SECTIONS = listOf(
15 | VoteData::class.java
16 | )
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/VotePartyConfiguration.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf
2 |
3 | import ch.jalu.configme.SettingsManagerImpl
4 | import ch.jalu.configme.configurationdata.ConfigurationDataBuilder
5 | import ch.jalu.configme.resource.YamlFileResource
6 | import me.clip.voteparty.conf.migrations.VoteMigrationService
7 | import me.clip.voteparty.conf.sections.CrateSettings
8 | import me.clip.voteparty.conf.sections.EffectsSettings
9 | import me.clip.voteparty.conf.sections.HookSettings
10 | import me.clip.voteparty.conf.sections.PartySettings
11 | import me.clip.voteparty.conf.sections.PluginSettings
12 | import me.clip.voteparty.conf.sections.VoteSettings
13 | import java.io.File
14 |
15 | internal class VotePartyConfiguration(file: File) : SettingsManagerImpl(YamlFileResource(file.toPath()), ConfigurationDataBuilder.createConfiguration(SECTIONS), VoteMigrationService())
16 | {
17 |
18 | private companion object
19 | {
20 |
21 | private val SECTIONS = listOf(
22 | PluginSettings::class.java,
23 | HookSettings::class.java,
24 | CrateSettings::class.java,
25 | EffectsSettings::class.java,
26 | PartySettings::class.java,
27 | VoteSettings::class.java
28 | )
29 |
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/mapper/SingleValueToCollectionMapper.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.mapper
2 |
3 | import ch.jalu.configme.beanmapper.MapperImpl
4 | import ch.jalu.configme.beanmapper.MappingContext
5 | import java.util.Collections
6 |
7 |
8 | /**
9 | * Extension of the bean mapper representing a simple migration where a property is changed from
10 | * a single value to a collection. This mapper wraps a single value into a collection whenever a
11 | * collection should be constructed. Example for issue #117.
12 | */
13 | class SingleValueToCollectionMapper : MapperImpl()
14 | {
15 | override fun createCollection(context: MappingContext, value: Any): Collection<*>?
16 | {
17 | if (value !is Iterable<*>)
18 | {
19 | val coll = super.createCollection(context, Collections.singleton(value))
20 | // Register error to trigger a rewrite with the proper structure
21 | context.registerError("Found single value where a collection is expected")
22 | return if (isCollectionWithOneElement(coll)) coll else null
23 | }
24 | return super.createCollection(context, value)
25 | }
26 |
27 | companion object
28 | {
29 | private fun isCollectionWithOneElement(coll: Collection<*>?): Boolean
30 | {
31 | return coll != null && coll.size == 1
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/migrations/VoteMigrationService.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.migrations
2 |
3 | import ch.jalu.configme.configurationdata.ConfigurationData
4 | import ch.jalu.configme.migration.PlainMigrationService
5 | import ch.jalu.configme.resource.PropertyReader
6 |
7 |
8 | internal class VoteMigrationService : PlainMigrationService()
9 | {
10 | override fun performMigrations(reader: PropertyReader, configurationData: ConfigurationData): Boolean
11 | {
12 | return hasDeprecatedProperties(reader)
13 | }
14 |
15 | private fun hasDeprecatedProperties(reader: PropertyReader): Boolean
16 | {
17 | val deprecatedProperties = arrayOf("settings.counter.votes", "hooks.nuvotifier")
18 | for (deprecatedPath in deprecatedProperties)
19 | {
20 | if (reader.contains(deprecatedPath))
21 | {
22 | return true
23 | }
24 | }
25 | return false
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/Command.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | import java.util.concurrent.ThreadLocalRandom
4 |
5 | internal data class Command(var chance: Double = 50.0,
6 | var command: List = listOf(""))
7 | {
8 |
9 | fun shouldExecute(): Boolean
10 | {
11 | return chance >= ThreadLocalRandom.current().nextDouble(100.0)
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/Commands.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class Commands(var enabled: Boolean = true,
4 | var commands: List = listOf(""))
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/Counter.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class Counter(var votes: Int = 0,
4 | var save_interval: Int = 60)
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/CumulativeVoteCommands.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class CumulativeVoteCommands(var votes: Int = 5,
4 | var commands: List = listOf(""))
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/CumulativeVoteRewards.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class CumulativeVoteRewards(
4 | var enabled: Boolean = false,
5 | var entries: List = listOf(CumulativeVoteCommands(5, listOf("eco give %player_name% 500")))
6 | )
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/CumulativeVoting.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class CumulativeVoting(
4 | var daily: CumulativeVoteRewards = CumulativeVoteRewards(false, listOf(CumulativeVoteCommands(5, listOf("give %player_name% STEAK 10")))),
5 | var weekly: CumulativeVoteRewards = CumulativeVoteRewards(false, listOf(CumulativeVoteCommands(5, listOf("give %player_name% STEAK 10")))),
6 | var monthly: CumulativeVoteRewards = CumulativeVoteRewards(false, listOf(CumulativeVoteCommands(5, listOf("give %player_name% STEAK 10")))),
7 | var yearly: CumulativeVoteRewards = CumulativeVoteRewards(false, listOf(CumulativeVoteCommands(5, listOf("give %player_name% STEAK 10")))),
8 | var total: CumulativeVoteRewards = CumulativeVoteRewards(false, listOf(CumulativeVoteCommands(5, listOf("give %player_name% STEAK 10"))))
9 | )
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/Effects.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class Effects(var enable: Boolean = true,
4 | var effects: List = listOf("SMOKE_NORMAL", "HEART"),
5 | var offsetX: Double = 0.0,
6 | var offsetY: Double = 0.0,
7 | var offsetZ: Double = 0.0,
8 | var speed: Double = 0.0,
9 | var count: Int = 3)
10 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/NuVotifier.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class NuVotifier(
4 | var backend: Boolean = true,
5 | var pluginMessaging: Boolean = false,
6 | var pluginMessageChannel: String = "nuvotifier:votes"
7 | )
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/PermCommands.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class PermCommands(var permission: String = "",
4 | var commands: List = listOf(""))
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/PermRewards.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class PermRewards(var enabled: Boolean = true,
4 | var permCommands: List = listOf(PermCommands("my.special.permission", listOf("eco give %player_name% 500"))))
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/RewardsPerEvent.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class RewardsPerEvent(var enabled: Boolean = true,
4 | var max_possible: Int = 1,
5 | var commands: List = listOf(Command(50.0, listOf("eco give %player_name% 100")), Command(70.0, listOf("give %player_name% STEAK 10"))))
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/VotesiteCommands.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class VotesiteCommands(var serviceName: String = "",
4 | var commands: List = listOf(""))
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/objects/VotesiteRewards.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.objects
2 |
3 | internal data class VotesiteRewards(var enabled: Boolean = true,
4 | var votesiteCommands: List = listOf(VotesiteCommands("TestVote", listOf("eco give %player_name% 500"))))
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/sections/CrateSettings.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.sections
2 |
3 | import ch.jalu.configme.SettingsHolder
4 | import ch.jalu.configme.properties.Property
5 | import ch.jalu.configme.properties.PropertyInitializer.*
6 | import com.cryptomorin.xseries.XMaterial
7 |
8 | internal object CrateSettings : SettingsHolder
9 | {
10 |
11 | @JvmField
12 | val ENABLED: Property = newProperty("crate.enabled", true)
13 |
14 | @JvmField
15 | val LORE: Property> = newListProperty("crate.lore", "", "&7Place the chest in order to", "&7to receive rewards!", "")
16 |
17 | @JvmField
18 | val MATERIAL: Property = newBeanProperty(XMaterial::class.java, "crate.material", XMaterial.CHEST)
19 |
20 | @JvmField
21 | val NAME: Property = newProperty("crate.name", "&d&lVote&5&lParty &f&lCrate")
22 |
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/sections/EffectsSettings.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.sections
2 |
3 | import ch.jalu.configme.Comment
4 | import ch.jalu.configme.SettingsHolder
5 | import ch.jalu.configme.configurationdata.CommentsConfiguration
6 | import ch.jalu.configme.properties.Property
7 | import ch.jalu.configme.properties.PropertyInitializer.newBeanProperty
8 | import me.clip.voteparty.conf.objects.Effects
9 |
10 |
11 | internal object EffectsSettings : SettingsHolder
12 | {
13 |
14 | @JvmField
15 | @Comment("Configuration for particles when party commands are being executed")
16 | val PARTY_COMMAND_EXECUTE: Property = newBeanProperty(Effects::class.java, "effects.party_commands_execute", Effects(true, listOf("SMOKE", "HEART"), 0.0, 0.0, 0.0, 0.1, 2))
17 |
18 | @JvmField
19 | @Comment("Configuration for particles when a party starts")
20 | val PARTY_START: Property = newBeanProperty(Effects::class.java, "effects.party_start", Effects(true, listOf("SMOKE", "HEART"), 0.0, 0.0, 0.0, 0.1, 2))
21 |
22 | @JvmField
23 | @Comment("Configuration for particles when a player votes")
24 | val VOTE: Property = newBeanProperty(Effects::class.java, "effects.vote", Effects(true, listOf("SMOKE", "HEART"), 0.0, 0.0, 0.0, 0.1, 2))
25 |
26 |
27 | override fun registerComments(conf: CommentsConfiguration)
28 | {
29 | conf.setComment("effects", "Configuration for particle effects you can play", "throughout different parts of the plugin")
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/sections/HookSettings.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.sections
2 |
3 | import ch.jalu.configme.Comment
4 | import ch.jalu.configme.SettingsHolder
5 | import ch.jalu.configme.configurationdata.CommentsConfiguration
6 | import ch.jalu.configme.properties.Property
7 | import ch.jalu.configme.properties.PropertyInitializer.newBeanProperty
8 | import ch.jalu.configme.properties.PropertyInitializer.newProperty
9 | import me.clip.voteparty.conf.objects.NuVotifier
10 |
11 | internal object HookSettings : SettingsHolder {
12 |
13 | @JvmField
14 | @Comment(
15 | "This property represents whether or not to listen to NuVotifier for incoming votes.",
16 | "If the backend is set to true, it assumes that the NuVotifier plugin is already enabled on the backend Spigot server,",
17 | "and pluginMessaging does not need to be enabled. If the backend is disabled, pluginMessaging should be enabled to allow",
18 | "NuVotifier to work on the proxy server. Additionally, make sure that the channel specified here matches the one set in",
19 | "your NuVotifier configuration, and that the \"method\" in your NuVotifier config is set to \"pluginMessaging\"."
20 | )
21 | val NUVOTIFIER: Property = newBeanProperty(
22 | NuVotifier::class.java, "hooks.votifier", NuVotifier(
23 | backend = true,
24 | pluginMessaging = false,
25 | pluginMessageChannel = "nuvotifier:votes"
26 | )
27 | )
28 |
29 | override fun registerComments(conf: CommentsConfiguration) {
30 | conf.setComment(
31 | "hooks",
32 | "The hook part of the config allows you to configure which plugins you would like to hook into for votes.",
33 | "By default, the plugin will utilize NuVotifier and listen for it's vote events.",
34 | "If you would like to use the plugin without NuVotifier, just disable the hook!",
35 | "NOTE: Keep in mind that without being hooked into a vote plugin, the plugin will not automatically handle votes.",
36 | "You will be required to do everything manually.",
37 | "Over time, more plugins may become supported!"
38 | )
39 | }
40 |
41 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/sections/PartySettings.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.sections
2 |
3 | import ch.jalu.configme.Comment
4 | import ch.jalu.configme.SettingsHolder
5 | import ch.jalu.configme.properties.BeanProperty
6 | import ch.jalu.configme.properties.Property
7 | import ch.jalu.configme.properties.PropertyInitializer.*
8 | import me.clip.voteparty.conf.mapper.SingleValueToCollectionMapper
9 | import me.clip.voteparty.conf.objects.Command
10 | import me.clip.voteparty.conf.objects.Commands
11 | import me.clip.voteparty.conf.objects.PermCommands
12 | import me.clip.voteparty.conf.objects.PermRewards
13 | import me.clip.voteparty.conf.objects.RewardsPerEvent
14 |
15 | internal object PartySettings : SettingsHolder
16 | {
17 |
18 | @JvmField
19 | @Comment("The amount of votes needed for a party to occur")
20 | val VOTES_NEEDED: Property = newProperty("party.votes_needed", 50)
21 |
22 | @JvmField
23 | @Comment("Would you like to use a crate for the rewards?")
24 | val USE_CRATE: Property = newProperty("party.use_crate", false)
25 |
26 | @JvmField
27 | @Comment("The list of worlds where party rewards won't be given")
28 | val DISABLED_WORLDS: Property> = newListProperty("party.disabled_worlds", "")
29 |
30 | @JvmField
31 | @Comment("Choose to allow offline votes count towards the party")
32 | val OFFLINE_VOTES: Property = newProperty("party.offline_votes", true)
33 |
34 | @JvmField
35 | @Comment(
36 | "There are 3 different ways that a party can work.",
37 | "1) \"everyone\" - everyone can join the party whether they voted or not",
38 | "2) \"daily\" - everyone who voted in the past 24 hours can join the party",
39 | "3) \"party\" - everyone who voted in this specific party can join the party",
40 | "Set the mode below to one of the options above to specify how the party should function"
41 | )
42 | val PARTY_MODE: Property = newProperty("party.party_mode", "everyone")
43 |
44 | @JvmField
45 | @Comment("The amount of time (in seconds) the server will wait to start the party after the amount needed has been achieved")
46 | val START_DELAY: Property = newProperty("party.start_delay", 15)
47 |
48 | @JvmField
49 | @Comment("The amount of time (in seconds) the server will wait between executing reward commands")
50 | val COMMAND_DELAY: Property = newProperty("party.command_delay", 1)
51 |
52 | @JvmField
53 | @Comment("Configuration for chance rewards to be given during a party.", "Add as many commands as you want, set their chance, and choose the max amount a player can earn!")
54 | val REWARD_COMMANDS: Property = BeanProperty(RewardsPerEvent::class.java, "party.reward_commands", RewardsPerEvent(true, 1, listOf(Command(50.0, listOf("eco give %player_name% 100")), Command(50.0, listOf("give %player_name% DIAMOND 6")), Command(50.0, listOf("give %player_name% IRON_INGOT 12")))), SingleValueToCollectionMapper())
55 |
56 | @JvmField
57 | @Comment("Configuration for extra commands to be executed on players who have specific permission nodes when a party happens")
58 | val PERMISSION_PARTY_REWARDS: Property = newBeanProperty(PermRewards::class.java, "party.permission-rewards", PermRewards(true, listOf(PermCommands("my.special.permission", listOf("eco give %player_name% 500")))))
59 |
60 | @JvmField
61 | @Comment("A list of rewards that will ALWAYS be given to a player during a party")
62 | val GUARANTEED_REWARDS: Property = newBeanProperty(Commands::class.java, "party.guaranteed_rewards", Commands(true, listOf("eco give %player_name% 10", "give %player_name% STEAK 8")))
63 |
64 | @JvmField
65 | @Comment("Commands to be executed before a party is started")
66 | val PRE_PARTY_COMMANDS: Property = newBeanProperty(Commands::class.java, "party.pre_party_commands", Commands(true, listOf("broadcast Party will start soon!")))
67 |
68 | @JvmField
69 | @Comment("Commands to be executed when a party has started")
70 | val PARTY_COMMANDS: Property = newBeanProperty(Commands::class.java, "party.party_commands", Commands(true, listOf("broadcast A Vote Party has started!")))
71 |
72 | @JvmField
73 | @Comment("Commands to be executed when a party has ended")
74 | val POST_PARTY_COMMANDS: Property = newBeanProperty(Commands::class.java, "party.post_party_commands", Commands(false, listOf("broadcast The Vote Party has ended!")))
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/sections/PluginSettings.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.sections
2 |
3 | import ch.jalu.configme.Comment
4 | import ch.jalu.configme.SettingsHolder
5 | import ch.jalu.configme.configurationdata.CommentsConfiguration
6 | import ch.jalu.configme.properties.Property
7 | import ch.jalu.configme.properties.PropertyInitializer.newProperty
8 |
9 | internal object PluginSettings : SettingsHolder
10 | {
11 |
12 | @JvmField
13 | @Comment("The default language of the plugin")
14 | val LANGUAGE: Property = newProperty("settings.language", "en-US")
15 |
16 | @JvmField
17 | @Comment("The prefix of all the messages in the plugin")
18 | val PREFIX: Property = newProperty("settings.prefix", "&d&lVote&5&lParty &7&l» ")
19 |
20 | @JvmField
21 | @Comment("How often to save the current amount of votes (in seconds)")
22 | val SAVE_INTERVAL: Property = newProperty("settings.counter.save-interval", 300)
23 |
24 | @JvmField
25 | @Comment("How often do we want to save the player data (in seconds)")
26 | val PLAYER_SAVE_INTERVAL: Property = newProperty("settings.data.save-interval", 300)
27 |
28 | @JvmField
29 | @Comment("Do you want to save a player's data instantly on vote? This will happen along with the interval saving above.",
30 | "Some servers just prefer to save instantly to ensure all the data is there.")
31 | val SAVE_ON_VOTE: Property = newProperty("settings.data.save-on-vote", false)
32 |
33 | @JvmField
34 | @Comment("Would you like to enable Brigadier command support? (I think it does more than just pretty colors) 1.13+")
35 | val BRIGADIER: Property = newProperty("settings.brigadier", false);
36 |
37 |
38 | override fun registerComments(conf: CommentsConfiguration)
39 | {
40 | conf.setComment("settings",
41 | "VoteParty",
42 | "Creator: Clip & Glare",
43 | "Contributors: https://github.com/VoteParty/VoteParty/graphs/contributors",
44 | "Issues: https://github.com/VoteParty/VoteParty/issues",
45 | "Spigot: https://www.spigotmc.org/resources/987/",
46 | "Wiki: https://wiki.helpch.at/glares-plugins/voteparty",
47 | "Discord: https://helpch.at/discord")
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/sections/VoteData.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.sections
2 |
3 | import ch.jalu.configme.SettingsHolder
4 | import ch.jalu.configme.properties.Property
5 | import ch.jalu.configme.properties.PropertyInitializer
6 |
7 | internal object VoteData : SettingsHolder
8 | {
9 | @JvmField
10 | val COUNTER: Property = PropertyInitializer.newProperty("votes", 0)
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/conf/sections/VoteSettings.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.conf.sections
2 |
3 | import ch.jalu.configme.Comment
4 | import ch.jalu.configme.SettingsHolder
5 | import ch.jalu.configme.properties.BeanProperty
6 | import ch.jalu.configme.properties.Property
7 | import ch.jalu.configme.properties.PropertyInitializer.newBeanProperty
8 | import ch.jalu.configme.properties.PropertyInitializer.newProperty
9 | import me.clip.voteparty.conf.mapper.SingleValueToCollectionMapper
10 | import me.clip.voteparty.conf.objects.Command
11 | import me.clip.voteparty.conf.objects.Commands
12 | import me.clip.voteparty.conf.objects.CumulativeVoting
13 | import me.clip.voteparty.conf.objects.PermCommands
14 | import me.clip.voteparty.conf.objects.PermRewards
15 | import me.clip.voteparty.conf.objects.RewardsPerEvent
16 | import me.clip.voteparty.conf.objects.VotesiteCommands
17 | import me.clip.voteparty.conf.objects.VotesiteRewards
18 |
19 | internal object VoteSettings : SettingsHolder
20 | {
21 |
22 | @JvmField
23 | @Comment("Would you like to validate the usernames being sent from voting sites?")
24 | val VALIDATE_NAMES: Property = newProperty("voting.validate_names", false)
25 |
26 | @JvmField
27 | @Comment("This is the regex for username checking. The default should apply to most accounts, but you are given access to modify in case you need to.")
28 | val NAME_REGEX: Property = newProperty("voting.name_regex", "^[a-zA-Z0-9_]{2,16}$")
29 |
30 | @JvmField
31 | @Comment("Enable or disable the voting reminder.")
32 | val REMINDER_ENABLED: Property = newProperty("voting.reminder_enabled", true)
33 |
34 | @JvmField
35 | @Comment("This is how long (in hours) the plugin should check that it has been since a user has voted before reminding them to vote.")
36 | val REMINDER_INTERVAL: Property = newProperty("voting.reminder_interval", 24)
37 |
38 | @JvmField
39 | @Comment("This is how many votes the plugin should check that a user has in the last X amount of time (defined above) before reminding them to vote.",
40 | "For example, if you set the reminder interval to 24 hours, and the reminder threshold to 3, the plugin will check if the user has voted 3 times in the last 24 hours.",
41 | "If they have, they will not be reminded to vote until they have voted 3 times in the last 24 hours.")
42 | val REMINDER_THRESHOLD: Property = newProperty("voting.reminder_threshold", 3)
43 |
44 | @JvmField
45 | @Comment("How often in seconds should players be reminded to vote? (Default is 10 minutes)",
46 | "Note: A FULL reboot is required for this to take effect if changed after the plugin has been loaded.")
47 | val REMINDER_INTERVAL_SECONDS: Property = newProperty("voting.reminder_interval_seconds", 600)
48 |
49 | @JvmField
50 | @Comment("If a player's inventory is full when voting, do you want to send the vote to a /vote claim?")
51 | val CLAIMABLE_IF_FULL: Property = newProperty("voting.claim_if_full", true)
52 |
53 | @JvmField
54 | @Comment("Configuration for chance rewards to be given for voting.", "Add as many commands as you want, set their chance, and choose the max amount a player can earn!")
55 | val PER_VOTE_REWARDS: Property = BeanProperty(RewardsPerEvent::class.java, "voting.per_vote_rewards", RewardsPerEvent(true, 1, listOf(Command(50.0, listOf("eco give %player_name% 100")), Command(70.0, listOf("give %player_name% STEAK 10")))), SingleValueToCollectionMapper())
56 |
57 | @JvmField
58 | @Comment("Configuration for extra commands to be executed on players who have specific permission nodes")
59 | val PERMISSION_VOTE_REWARDS: Property = newBeanProperty(PermRewards::class.java, "voting.permission-rewards", PermRewards(true, listOf(PermCommands("my.special.permission", listOf("eco give %player_name% 500")))))
60 |
61 | @JvmField
62 | @Comment("A list of rewards that will ALWAYS be given to a player for voting")
63 | val GUARANTEED_REWARDS: Property = newBeanProperty(Commands::class.java, "voting.guaranteed_rewards", Commands(true, listOf("eco give %player_name% 10", "give %player_name% STEAK 8")))
64 |
65 | @JvmField
66 | @Comment("A list of commands to run when it's the first time a player has voted (only works for online players)")
67 | val FIRST_TIME_REWARDS: Property = newBeanProperty(Commands::class.java, "voting.first_time_rewards", Commands(false, listOf("eco give %player_name% 100", "give %player_name% STEAK 10")))
68 |
69 | @JvmField
70 | @Comment("Configuration for extra commands to be executed on players who voted on a specific website (only works for online players)",
71 | "Known Service Names:",
72 | "TopG.com",
73 | "PlanetMinecraft.com",
74 | "Minecraft-MP.com",
75 | "MinecraftServers.org",
76 | "Minecraft-Server.net")
77 | val VOTESITE_VOTE_REWARDS: Property = newBeanProperty(VotesiteRewards::class.java, "voting.votesite-rewards", VotesiteRewards(false, listOf(VotesiteCommands("TestVote", listOf("eco give %player_name% 500")))))
78 |
79 | @JvmField
80 | @Comment("Global commands (such as a broadcast message) to be executed when a player votes")
81 | val GLOBAL_COMMANDS: Property = newBeanProperty(Commands::class.java, "voting.global_commands", Commands(true, listOf("broadcast %player_name% just voted! Only %voteparty_votes_required_party% more votes until a VoteParty!")))
82 |
83 | @JvmField
84 | @Comment("Would you like players to be able to claim rewards for offline votes?",
85 | "Note: They will only be able to get credit for rewards if you have `offline_votes` enabled")
86 | val OFFLINE_VOTE_CLAIMING: Property = newProperty("voting.offline_vote_claiming.enabled", false)
87 |
88 | @JvmField
89 | @Comment("Would you like to notify the player when they login that they have votes to claim?")
90 | val OFFLINE_VOTE_CLAIMING_NOTIFY: Property = newProperty("voting.offline_vote_claiming.notify", false)
91 |
92 | @JvmField
93 | @Comment("Configuration for extra commands to be executed on players who have voted a specific amount of times in the past day, week, month, year, and all time.")
94 | val CUMULATIVE_VOTE_REWARDS: Property = newBeanProperty(CumulativeVoting::class.java, "voting.cumulative-rewards", CumulativeVoting())
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/data/base/DatabaseVotePlayer.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.data.base
2 |
3 | import me.clip.voteparty.base.Addon
4 | import me.clip.voteparty.base.State
5 | import me.clip.voteparty.user.User
6 | import java.util.UUID
7 |
8 | internal interface DatabaseVotePlayer : Addon, State
9 | {
10 |
11 | override fun load()
12 |
13 | override fun kill()
14 |
15 |
16 | fun load(uuid: UUID): User?
17 |
18 | fun save(data: User)
19 |
20 |
21 | fun load(uuid: Collection): Map
22 | {
23 | return uuid.associateWith(::load)
24 | }
25 |
26 | fun save(data: Collection)
27 | {
28 | data.forEach(::save)
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/data/base/PartiesCache.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.data.base
2 |
3 | import me.clip.voteparty.base.Addon
4 | import me.clip.voteparty.base.State
5 |
6 | internal interface PartiesCache : Addon, State {
7 |
8 | override fun load()
9 |
10 | override fun kill()
11 |
12 | fun save()
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/data/base/VotedForPartyCache.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.data.base
2 |
3 | import me.clip.voteparty.base.Addon
4 | import me.clip.voteparty.base.State
5 |
6 | internal interface VotedForPartyCache : Addon, State {
7 |
8 | override fun load()
9 |
10 | override fun kill()
11 |
12 | fun save()
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/data/impl/DatabaseVotePlayerGson.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.data.impl
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.GsonBuilder
5 | import me.clip.voteparty.data.base.DatabaseVotePlayer
6 | import me.clip.voteparty.plugin.VotePartyPlugin
7 | import me.clip.voteparty.user.User
8 | import java.util.UUID
9 | import java.util.logging.Level
10 |
11 | internal class DatabaseVotePlayerGson(override val plugin: VotePartyPlugin) : DatabaseVotePlayer
12 | {
13 |
14 | private lateinit var gson: Gson
15 |
16 |
17 | override fun load()
18 | {
19 | val builder = GsonBuilder().disableHtmlEscaping().enableComplexMapKeySerialization().setPrettyPrinting().serializeNulls()
20 | gson = builder.create()
21 |
22 | plugin.dataFolder.resolve("players").mkdirs()
23 | }
24 |
25 | override fun kill()
26 | {
27 |
28 | }
29 |
30 |
31 | override fun load(uuid: UUID): User?
32 | {
33 | return try
34 | {
35 | gson.fromJson(plugin.dataFolder.resolve("players").resolve("$uuid.json").readText(), User::class.java)
36 | }
37 | catch (ex: Exception)
38 | {
39 | logger.log(Level.SEVERE, "failed to load player:$uuid", ex)
40 | null
41 | }
42 | }
43 |
44 | override fun save(data: User)
45 | {
46 | try
47 | {
48 | plugin.dataFolder.resolve("players").resolve("${data.uuid}.json").writeText(gson.toJson(data, User::class.java))
49 | }
50 | catch (ex: Exception)
51 | {
52 | logger.log(Level.SEVERE, "failed to save player:${data.uuid}", ex)
53 | }
54 | }
55 |
56 | override fun load(uuid: Collection): Map
57 | {
58 | if (uuid.isNotEmpty())
59 | {
60 | return super.load(uuid)
61 | }
62 |
63 | val files = plugin.dataFolder.resolve("players").listFiles() ?: return emptyMap()
64 |
65 | return files.mapNotNull()
66 | {
67 | try
68 | {
69 | UUID.fromString(it.nameWithoutExtension)
70 | }
71 | catch (ex: Exception)
72 | {
73 | null
74 | }
75 | }.associateWith(::load)
76 | }
77 |
78 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/data/impl/PartiesCacheGson.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.data.impl
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.GsonBuilder
5 | import com.google.gson.reflect.TypeToken
6 | import java.io.File
7 | import java.util.logging.Level
8 | import me.clip.voteparty.data.base.PartiesCache
9 | import me.clip.voteparty.plugin.VotePartyPlugin
10 |
11 | class PartiesCacheGson(override val plugin: VotePartyPlugin) : PartiesCache {
12 |
13 | private lateinit var gson: Gson
14 | private lateinit var file: File
15 | private lateinit var backupFile: File
16 | private val type = object : TypeToken>() {}.type
17 |
18 | override fun load()
19 | {
20 | val builder = GsonBuilder().setPrettyPrinting()
21 | gson = builder.create()
22 |
23 | file = plugin.dataFolder.resolve("parties.json")
24 | backupFile = plugin.dataFolder.resolve("parties.json.bak")
25 |
26 | if (!file.exists())
27 | {
28 | file.parentFile.mkdirs()
29 | file.createNewFile()
30 | }
31 |
32 | try
33 | {
34 | if (file.length() == 0L)
35 | {
36 | party.partyHandler.setParties(mutableListOf())
37 | }
38 | else
39 | {
40 | party.partyHandler.setParties(gson.fromJson(file.readText(), type))
41 | }
42 | }
43 | catch (exception: Exception)
44 | {
45 | logger.log(
46 | Level.SEVERE,
47 | "failed to load voted for party cache. This can end up in data loss!" + System.lineSeparator() +
48 | "A backup of the ${file.name} file was saved to: ${backupFile.name}",
49 | exception
50 | )
51 |
52 | if (!backupFile.exists())
53 | {
54 | backupFile.createNewFile()
55 | }
56 |
57 | backupFile.writeText(file.readText())
58 | }
59 | }
60 |
61 | override fun kill()
62 | {
63 | save()
64 | }
65 |
66 | override fun save()
67 | {
68 | try
69 | {
70 | file.writeText(gson.toJson(party.partyHandler.getParties(), type))
71 | }
72 | catch (exception: Exception)
73 | {
74 | logger.log(
75 | Level.SEVERE,
76 | "failed to save parties cache. This can end up in data loss!" + System.lineSeparator() +
77 | "For backup purposes, the cached data is: " + party.partyHandler.getParties().joinToString(", "),
78 | exception
79 | )
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/data/impl/VotedForPartyCacheGson.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.data.impl
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.GsonBuilder
5 | import com.google.gson.reflect.TypeToken
6 | import me.clip.voteparty.data.base.VotedForPartyCache
7 | import me.clip.voteparty.plugin.VotePartyPlugin
8 | import java.io.File
9 | import java.util.UUID
10 | import java.util.logging.Level
11 |
12 | internal class VotedForPartyCacheGson(override val plugin: VotePartyPlugin) : VotedForPartyCache
13 | {
14 |
15 | private lateinit var gson: Gson
16 | private lateinit var file: File
17 | private val type = object : TypeToken>() {}.type
18 |
19 | override fun load() {
20 | val builder = GsonBuilder().setPrettyPrinting()
21 | gson = builder.create()
22 |
23 | file = plugin.dataFolder.resolve("voted-for-party-cache.json")
24 |
25 | if (!file.exists()) {
26 | file.parentFile.mkdirs()
27 | file.createNewFile()
28 | }
29 |
30 | try
31 | {
32 | party.partyHandler.voted = gson.fromJson(file.readText(), type)
33 | }
34 | catch (ex: Exception)
35 | {
36 | party.partyHandler.voted = mutableListOf()
37 | }
38 | }
39 |
40 | override fun kill() {
41 | save()
42 | }
43 |
44 | override fun save() {
45 | try
46 | {
47 | file.writeText(gson.toJson(party.partyHandler.voted, type))
48 | }
49 | catch (ex: Exception)
50 | {
51 | logger.log(Level.SEVERE, "failed to save voted for party cache.", ex)
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/events/PartyEndEvent.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.events
2 |
3 | import org.bukkit.event.Event
4 | import org.bukkit.event.HandlerList
5 |
6 | class PartyEndEvent : Event()
7 | {
8 |
9 | override fun getHandlers(): HandlerList
10 | {
11 | return handlerList
12 | }
13 |
14 | companion object
15 | {
16 | @JvmStatic
17 | val handlerList = HandlerList()
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/events/PartyStartEvent.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.events
2 |
3 | import org.bukkit.event.Cancellable
4 | import org.bukkit.event.Event
5 | import org.bukkit.event.HandlerList
6 |
7 | class PartyStartEvent : Event(), Cancellable
8 | {
9 | private var isCancelled = false
10 |
11 |
12 | override fun isCancelled(): Boolean
13 | {
14 | return isCancelled
15 | }
16 |
17 | override fun setCancelled(cancelled: Boolean)
18 | {
19 | isCancelled = cancelled
20 | }
21 |
22 |
23 | override fun getHandlers(): HandlerList
24 | {
25 | return handlerList
26 | }
27 |
28 |
29 | companion object
30 | {
31 | @JvmStatic
32 | val handlerList = HandlerList()
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/events/PrePartyEvent.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.events
2 |
3 | import org.bukkit.event.Cancellable
4 | import org.bukkit.event.Event
5 | import org.bukkit.event.HandlerList
6 |
7 | class PrePartyEvent : Event(), Cancellable
8 | {
9 | private var isCancelled = false
10 |
11 |
12 | override fun isCancelled(): Boolean
13 | {
14 | return isCancelled
15 | }
16 |
17 | override fun setCancelled(cancelled: Boolean)
18 | {
19 | isCancelled = cancelled
20 | }
21 |
22 |
23 | override fun getHandlers(): HandlerList
24 | {
25 | return handlerList
26 | }
27 |
28 |
29 | companion object
30 | {
31 | @JvmStatic
32 | val handlerList = HandlerList()
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/events/VoteReceivedEvent.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.events
2 |
3 | import org.bukkit.OfflinePlayer
4 | import org.bukkit.event.Cancellable
5 | import org.bukkit.event.Event
6 | import org.bukkit.event.HandlerList
7 |
8 | class VoteReceivedEvent(val player: OfflinePlayer, val vote: String) : Event(), Cancellable
9 | {
10 |
11 | private var isCancelled = false
12 |
13 |
14 | override fun isCancelled(): Boolean
15 | {
16 | return isCancelled
17 | }
18 |
19 | override fun setCancelled(cancelled: Boolean)
20 | {
21 | isCancelled = cancelled
22 | }
23 |
24 |
25 | override fun getHandlers(): HandlerList
26 | {
27 | return handlerList
28 | }
29 |
30 |
31 | companion object
32 | {
33 | @JvmStatic
34 | val handlerList = HandlerList()
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/exte/const.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.exte
2 |
3 | internal const val PREFIX = "&d&lV&dote&5&lP&5arty &7&l» "
4 |
5 | internal const val BASE_PERM = "voteparty.command"
6 |
7 | internal const val ADMIN_PERM = "$BASE_PERM.admin"
8 | internal const val CLAIM_PERM = "$BASE_PERM.claim"
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/exte/funcs.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.exte
2 |
3 | import co.aikar.commands.ACFUtil
4 | import co.aikar.commands.CommandIssuer
5 | import co.aikar.locales.MessageKeyProvider
6 | import me.clip.placeholderapi.PlaceholderAPI
7 | import me.clip.voteparty.base.Addon
8 | import me.clip.voteparty.conf.objects.Command
9 | import me.clip.voteparty.conf.sections.PluginSettings
10 | import net.kyori.adventure.identity.Identity
11 | import net.kyori.adventure.text.Component
12 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
13 | import org.bukkit.Bukkit
14 | import org.bukkit.ChatColor
15 | import org.bukkit.Material
16 | import org.bukkit.OfflinePlayer
17 | import org.bukkit.inventory.ItemStack
18 | import org.bukkit.inventory.meta.ItemMeta
19 | import org.bukkit.plugin.Plugin
20 | import org.bukkit.scheduler.BukkitRunnable
21 |
22 | private val serializer = LegacyComponentSerializer.legacyAmpersand()
23 |
24 | internal fun color(message: String): String
25 | {
26 | return ChatColor.translateAlternateColorCodes('&', message)
27 | }
28 |
29 | internal fun deserialize(message: String): Component
30 | {
31 | return serializer.deserialize(color(message))
32 | }
33 |
34 | internal fun formMessage(player: OfflinePlayer, message: String): String
35 | {
36 | return color(PlaceholderAPI.setPlaceholders(player, message))
37 | }
38 |
39 | internal fun Addon.sendMessage(receiver: CommandIssuer, message: MessageKeyProvider, placeholderTarget: OfflinePlayer? = null, vararg replacements: Any = emptyArray())
40 | {
41 | var msg = receiver.manager.locales.getMessage(receiver, message)
42 |
43 | if (replacements.isNotEmpty() && replacements.size % 2 == 0)
44 | {
45 | msg = ACFUtil.replaceStrings(msg, *replacements.map(Any::toString).toTypedArray())
46 | }
47 |
48 | val result = formMessage(Bukkit.getOfflinePlayer(placeholderTarget?.uniqueId ?: receiver.uniqueId), (party.conf().getProperty(PluginSettings.PREFIX) ?: PREFIX) + msg)
49 |
50 | party.audiences().sender(receiver.getIssuer()).sendMessage(Identity.nil(), serializer.deserialize(result))
51 | }
52 |
53 | internal fun msgAsString(issuer: CommandIssuer, key: MessageKeyProvider): String
54 | {
55 | return issuer.manager.locales.getMessage(issuer, key)
56 | }
57 |
58 |
59 | internal fun Plugin.runTaskTimer(period: Long, task: BukkitRunnable.() -> Unit)
60 | {
61 | object : BukkitRunnable()
62 | {
63 | override fun run()
64 | {
65 | task.invoke(this)
66 | }
67 | }.runTaskTimer(this, 0L, period)
68 | }
69 |
70 | internal fun Plugin.runTaskTimerAsync(period: Long, task: BukkitRunnable.() -> Unit)
71 | {
72 | object : BukkitRunnable()
73 | {
74 | override fun run()
75 | {
76 | task.invoke(this)
77 | }
78 | }.runTaskTimerAsynchronously(this, 0L, period)
79 | }
80 |
81 | internal fun Plugin.runTaskLater(delay: Long, task: () -> Unit)
82 | {
83 | server.scheduler.runTaskLater(this, task, delay)
84 | }
85 |
86 |
87 | internal fun Collection.takeRandomly(amount: Int): Collection
88 | {
89 | return filter(Command::shouldExecute).shuffled().take(amount)
90 | }
91 |
92 |
93 | internal fun item(type: Material, amount: Int, function: ItemMeta.() -> Unit = {}): ItemStack
94 | {
95 | return ItemStack(type, amount).meta(function)
96 | }
97 |
98 | internal fun ItemStack.meta(function: ItemMeta.() -> Unit): ItemStack
99 | {
100 | itemMeta = itemMeta?.apply(function)
101 |
102 | return this
103 | }
104 |
105 | internal var ItemMeta.name: String
106 | get() = displayName
107 | set(value)
108 | {
109 | setDisplayName(color(value))
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/exte/texts.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.exte
2 |
3 | import co.aikar.commands.CommandIssuer
4 | import me.clip.voteparty.messages.Messages
5 | import net.kyori.adventure.text.Component
6 | import net.kyori.adventure.text.minimessage.MiniMessage
7 | import java.util.*
8 |
9 | fun helpMenu(issuer: CommandIssuer): Component
10 | {
11 | val mini = MiniMessage.miniMessage()
12 | val builder = Component.text()
13 | val lineText = msgAsString(issuer, Messages.HELP__LINE_TEXT)
14 | val lineHoverTemplate = msgAsString(issuer, Messages.HELP__LINE_HOVER)
15 |
16 | // Header
17 | builder.append(mini.deserialize(msgAsString(issuer, Messages.HELP__HEADER))).append(Component.newline())
18 |
19 | // Commands
20 | issuer.manager.getRootCommand("vp").subCommands.entries().forEach {
21 | val key = it.key
22 | val cmd = it.value
23 | if (key != "__default")
24 | {
25 | val updatedHover = lineHoverTemplate
26 | .replace("{text}", cmd.helpText)
27 | .replace("{desc}", msgAsString(issuer, Messages.valueOf("DESCRIPTIONS__" + key.uppercase(Locale.getDefault()))))
28 | .replace("{cmd}", it.key)
29 | .replace("{args}", cmd.syntaxText)
30 | .replace("{perm}", if (key == "help") "" else ADMIN_PERM)
31 |
32 | builder.append(mini.deserialize(lineText.replace("{cmd}", it.key).replace("{line-hover}", updatedHover)))
33 | }
34 | }
35 |
36 | // Footer
37 | builder.append((mini.deserialize(msgAsString(issuer, Messages.HELP__FOOTER))))
38 |
39 | return builder.build()
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/handler/LeaderboardHandler.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.handler
2 |
3 | import com.google.common.cache.CacheBuilder
4 | import com.google.common.cache.CacheLoader
5 | import com.google.common.cache.LoadingCache
6 | import me.clip.voteparty.base.Addon
7 | import me.clip.voteparty.base.State
8 | import me.clip.voteparty.leaderboard.Leaderboard
9 | import me.clip.voteparty.leaderboard.LeaderboardType
10 | import me.clip.voteparty.plugin.VotePartyPlugin
11 | import java.util.concurrent.TimeUnit
12 |
13 | class LeaderboardHandler(override val plugin: VotePartyPlugin) : Addon, State
14 | {
15 | private val cache: LoadingCache = CacheBuilder.newBuilder().refreshAfterWrite(2, TimeUnit.MINUTES)
16 | .build(object : CacheLoader()
17 | {
18 | override fun load(key: LeaderboardType): Leaderboard
19 | {
20 | return Leaderboard(key, plugin.voteParty?.usersHandler?.getUsersWithVotesWithinRange(key.start.invoke(), key.end.invoke()) ?: emptyList())
21 | }
22 | })
23 |
24 | override fun load()
25 | {
26 | LeaderboardType.values.forEach()
27 | { type ->
28 | cache.put(type, Leaderboard(type, plugin.voteParty?.usersHandler?.getUsersWithVotesWithinRange(type.start.invoke(), type.end.invoke()) ?: emptyList()))
29 | }
30 | }
31 |
32 | override fun kill()
33 | {
34 | cache.invalidateAll()
35 | }
36 |
37 | fun getLeaderboard(type: LeaderboardType): Leaderboard?
38 | {
39 | return cache.get(type)
40 | }
41 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/handler/PartyHandler.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.handler
2 |
3 | import java.time.LocalDateTime
4 | import java.time.ZoneId
5 | import me.clip.voteparty.base.Addon
6 | import me.clip.voteparty.conf.sections.CrateSettings
7 | import me.clip.voteparty.conf.sections.EffectsSettings
8 | import me.clip.voteparty.conf.sections.PartySettings
9 | import me.clip.voteparty.events.PartyEndEvent
10 | import me.clip.voteparty.events.PartyStartEvent
11 | import me.clip.voteparty.events.PrePartyEvent
12 | import me.clip.voteparty.exte.color
13 | import me.clip.voteparty.exte.formMessage
14 | import me.clip.voteparty.exte.meta
15 | import me.clip.voteparty.exte.name
16 | import me.clip.voteparty.exte.runTaskLater
17 | import me.clip.voteparty.exte.runTaskTimer
18 | import me.clip.voteparty.exte.sendMessage
19 | import me.clip.voteparty.exte.takeRandomly
20 | import me.clip.voteparty.messages.Messages
21 | import me.clip.voteparty.plugin.VotePartyPlugin
22 | import me.clip.voteparty.version.EffectType
23 | import org.bukkit.Bukkit
24 | import org.bukkit.Material
25 | import org.bukkit.entity.Player
26 | import org.bukkit.inventory.ItemStack
27 | import java.util.UUID
28 | import java.util.concurrent.TimeUnit
29 |
30 | class PartyHandler(override val plugin: VotePartyPlugin) : Addon
31 | {
32 |
33 | var voted = mutableListOf()
34 | private var parties = mutableListOf()
35 |
36 | fun getParties(): MutableList {
37 | return parties
38 | }
39 |
40 | fun setParties(new: MutableList)
41 | {
42 | parties = new
43 | }
44 |
45 | fun addParties(vararg new: Long)
46 | {
47 | new.forEach { parties.add(it) }
48 | }
49 |
50 | fun getPartiesSince(time: LocalDateTime): Int
51 | {
52 | val timeEpoch = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
53 |
54 | return parties.count { partyEpoch -> partyEpoch > timeEpoch }
55 | }
56 |
57 | fun giveRandomPartyRewards(player: Player)
58 | {
59 | if (player.world.name in party.conf().getProperty(PartySettings.DISABLED_WORLDS)) {
60 | return
61 | }
62 |
63 | val settings = party.conf().getProperty(PartySettings.REWARD_COMMANDS)
64 |
65 | if (!settings.enabled || settings.max_possible <= 0 || settings.commands.isEmpty())
66 | {
67 | return
68 | }
69 |
70 | if (player.world.name in party.conf().getProperty(PartySettings.DISABLED_WORLDS)) {
71 | return
72 | }
73 |
74 | val iter = settings.commands.takeRandomly(settings.max_possible).iterator()
75 |
76 | plugin.runTaskTimer(party.conf().getProperty(PartySettings.COMMAND_DELAY).toLong() * 20L)
77 | {
78 | if (!iter.hasNext())
79 | {
80 | return@runTaskTimer cancel()
81 | }
82 |
83 | runPartyCommandEffects(player)
84 | iter.next().command.forEach()
85 | { command ->
86 | server.dispatchCommand(server.consoleSender, formMessage (player, command))
87 | }
88 | }
89 | }
90 |
91 | fun giveGuaranteedPartyRewards(player: Player)
92 | {
93 | val settings = party.conf().getProperty(PartySettings.GUARANTEED_REWARDS)
94 |
95 | executeCommands(settings.enabled, settings.commands, player)
96 | }
97 |
98 | fun givePermissionPartyRewards(player: Player)
99 | {
100 | if (player.world.name in party.conf().getProperty(PartySettings.DISABLED_WORLDS)) {
101 | return
102 | }
103 |
104 | val settings = party.conf().getProperty(PartySettings.PERMISSION_PARTY_REWARDS)
105 |
106 | if (!settings.enabled || settings.permCommands.isEmpty())
107 | {
108 | return
109 | }
110 |
111 | if (player.world.name in party.conf().getProperty(PartySettings.DISABLED_WORLDS)) {
112 | return
113 | }
114 |
115 | settings.permCommands.filter { player.hasPermission(it.permission) }.forEach()
116 | { perm ->
117 | perm.commands.forEach()
118 | { command ->
119 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
120 | }
121 |
122 | }
123 | }
124 |
125 | fun runAll(player: Player)
126 | {
127 | giveRandomPartyRewards(player)
128 | giveGuaranteedPartyRewards(player)
129 | givePermissionPartyRewards(player)
130 | }
131 |
132 | fun runPrePartyCommands()
133 | {
134 | val settings = party.conf().getProperty(PartySettings.PRE_PARTY_COMMANDS)
135 |
136 | executeCommands(settings.enabled, settings.commands)
137 | }
138 |
139 | fun runPartyCommands()
140 | {
141 | val settings = party.conf().getProperty(PartySettings.PARTY_COMMANDS)
142 |
143 | executeCommands(settings.enabled, settings.commands)
144 | }
145 |
146 | fun runPostPartyCommands()
147 | {
148 | val settings = party.conf().getProperty(PartySettings.POST_PARTY_COMMANDS)
149 |
150 | executeCommands(settings.enabled, settings.commands)
151 | }
152 |
153 | fun runPartyStartEffects()
154 | {
155 | val settings = party.conf().getProperty(EffectsSettings.PARTY_START)
156 |
157 | executeEffects(settings.enable, settings.effects, server.onlinePlayers,
158 | settings.offsetX, settings.offsetY, settings.offsetZ,
159 | settings.speed, settings.count)
160 | }
161 |
162 | fun runPartyCommandEffects(player: Player)
163 | {
164 | val settings = party.conf().getProperty(EffectsSettings.PARTY_COMMAND_EXECUTE)
165 |
166 | executeEffects(settings.enable, settings.effects, listOf(player),
167 | settings.offsetX, settings.offsetY, settings.offsetZ,
168 | settings.speed, settings.count)
169 | }
170 |
171 |
172 | fun buildCrate(amount: Int): ItemStack
173 | {
174 | val item = party.conf().getProperty(CrateSettings.MATERIAL).parseItem() ?: ItemStack(Material.CHEST, 1)
175 | item.amount = amount
176 |
177 | return item.meta()
178 | {
179 | name = party.conf().getProperty(CrateSettings.NAME) ?: "Vote Party Crate"
180 | lore = party.conf().getProperty(CrateSettings.LORE).map(::color)
181 | }
182 | }
183 |
184 | fun startParty()
185 | {
186 |
187 | val prePartyEvent = PrePartyEvent()
188 | Bukkit.getPluginManager().callEvent(prePartyEvent)
189 |
190 | if (prePartyEvent.isCancelled) {
191 | return
192 | }
193 |
194 | runPrePartyCommands()
195 |
196 | plugin.runTaskLater(party.conf().getProperty(PartySettings.START_DELAY) * 20L)
197 | {
198 |
199 | val partyStartEvent = PartyStartEvent()
200 | Bukkit.getPluginManager().callEvent(partyStartEvent)
201 |
202 | if (partyStartEvent.isCancelled) {
203 | return@runTaskLater
204 | }
205 |
206 | addParties(System.currentTimeMillis())
207 | runPartyCommands()
208 | runPartyStartEffects()
209 |
210 | val targets: Collection = when(party.conf().getProperty(PartySettings.PARTY_MODE)) {
211 | "everyone" -> server.onlinePlayers
212 | "daily" -> server.onlinePlayers.filter { party.usersHandler.getPlayersWhoVotedSince(1, TimeUnit.DAYS).contains(it.uniqueId) }
213 | "party" -> server.onlinePlayers.filter { voted.contains(it.uniqueId) }
214 | else -> server.onlinePlayers
215 | }
216 |
217 | server.onlinePlayers.filterNot { it in targets }.forEach {
218 | sendMessage(party.manager().getCommandIssuer(it), Messages.PARTY__REQUIREMENTS_NOT_MET)
219 | }
220 |
221 | if (party.conf().getProperty(PartySettings.USE_CRATE)) {
222 | val disabledWorlds = party.conf().getProperty(PartySettings.DISABLED_WORLDS)
223 | targets.filterNot { it.world.name in disabledWorlds }.forEach {
224 | it.inventory.addItem(buildCrate(1))
225 | }
226 | }
227 | else {
228 | targets.forEach()
229 | {
230 | giveGuaranteedPartyRewards(it)
231 | giveRandomPartyRewards(it)
232 | givePermissionPartyRewards(it)
233 | }
234 | }
235 |
236 | voted.clear()
237 | val partyEndEvent = PartyEndEvent()
238 | Bukkit.getPluginManager().callEvent(partyEndEvent)
239 |
240 | runPostPartyCommands()
241 | }
242 | }
243 |
244 |
245 | private fun executeCommands(enabled: Boolean, cmds: Collection?, player: Player? = null)
246 | {
247 | if (!enabled || (player != null && (player.world.name in party.conf().getProperty(PartySettings.DISABLED_WORLDS))))
248 | {
249 | return
250 | }
251 |
252 | cmds?.forEach()
253 | {
254 | server.dispatchCommand(server.consoleSender, if (player == null) it else formMessage(player, it))
255 | }
256 | }
257 |
258 |
259 | private fun executeEffects(enabled: Boolean, effects: Collection, players: Collection, offsetX: Double, offsetY: Double, offsetZ: Double, speed: Double, count: Int)
260 | {
261 | if (!enabled)
262 | {
263 | return
264 | }
265 |
266 | val targets = players.filter()
267 | {
268 | it.world.name !in party.conf().getProperty(PartySettings.DISABLED_WORLDS)
269 | }
270 |
271 | effects.forEach()
272 | { effect ->
273 | targets.forEach()
274 | { player ->
275 | party.hook().display(EffectType.valueOf(effect), player.location, offsetX, offsetY, offsetZ, speed, count)
276 | }
277 | }
278 | }
279 |
280 | }
281 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/handler/VotesHandler.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.handler
2 |
3 | import me.clip.voteparty.base.Addon
4 | import me.clip.voteparty.base.State
5 | import me.clip.voteparty.conf.sections.EffectsSettings
6 | import me.clip.voteparty.conf.sections.PartySettings
7 | import me.clip.voteparty.conf.sections.VoteData
8 | import me.clip.voteparty.conf.sections.VoteSettings
9 | import me.clip.voteparty.exte.formMessage
10 | import me.clip.voteparty.exte.sendMessage
11 | import me.clip.voteparty.exte.takeRandomly
12 | import me.clip.voteparty.leaderboard.LeaderboardType
13 | import me.clip.voteparty.messages.Messages
14 | import me.clip.voteparty.plugin.VotePartyPlugin
15 | import me.clip.voteparty.version.EffectType
16 | import org.bukkit.Bukkit
17 | import org.bukkit.entity.Player
18 | import java.util.concurrent.TimeUnit
19 | import java.util.concurrent.atomic.AtomicInteger
20 |
21 | class VotesHandler(override val plugin: VotePartyPlugin) : Addon, State
22 | {
23 |
24 | private val votes = AtomicInteger()
25 |
26 |
27 | override fun load()
28 | {
29 | votes.set(party.voteData().getProperty(VoteData.COUNTER))
30 | }
31 |
32 | override fun kill()
33 | {
34 | votes.set(0)
35 | }
36 |
37 |
38 | fun getVotes(): Int
39 | {
40 | return votes.get()
41 | }
42 |
43 | fun setVotes(amount: Int)
44 | {
45 | votes.set(amount)
46 | }
47 |
48 | fun addVotes(amount: Int)
49 | {
50 | if (votes.addAndGet(amount) < party.conf().getProperty(PartySettings.VOTES_NEEDED))
51 | {
52 | return
53 | }
54 |
55 | votes.set(0)
56 | party.partyHandler.startParty()
57 | }
58 |
59 | fun runAll(player: Player)
60 | {
61 | giveRandomVoteRewards(player)
62 | giveGuaranteedVoteRewards(player)
63 | givePermissionVoteRewards(player)
64 | }
65 |
66 |
67 | fun giveGuaranteedVoteRewards(player: Player)
68 | {
69 | val settings = party.conf().getProperty(VoteSettings.GUARANTEED_REWARDS)
70 |
71 | if (!settings.enabled || settings.commands.isEmpty())
72 | {
73 | return
74 | }
75 |
76 | settings.commands.forEach()
77 | { command ->
78 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
79 | }
80 | }
81 |
82 | fun givePermissionVoteRewards(player: Player)
83 | {
84 | val settings = party.conf().getProperty(VoteSettings.PERMISSION_VOTE_REWARDS)
85 |
86 | if (!settings.enabled || settings.permCommands.isEmpty())
87 | {
88 | return
89 | }
90 |
91 | settings.permCommands.filter { player.hasPermission(it.permission) }.forEach()
92 | { perm ->
93 | perm.commands.forEach()
94 | { command ->
95 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
96 | }
97 | }
98 | }
99 |
100 | fun checkDailyCumulative(player: Player)
101 | {
102 | val settings = party.conf().getProperty(VoteSettings.CUMULATIVE_VOTE_REWARDS)
103 |
104 | if (!settings.daily.enabled || settings.daily.entries.isEmpty())
105 | {
106 | return
107 | }
108 |
109 | settings.daily.entries.filter { entry -> entry.votes == party.usersHandler.getVoteCountSince(player, LeaderboardType.DAILY.start.invoke()) }.forEach { entry ->
110 | entry.commands.forEach()
111 | { command ->
112 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
113 | }
114 | }
115 | }
116 |
117 | fun checkWeeklyCumulative(player: Player)
118 | {
119 | val settings = party.conf().getProperty(VoteSettings.CUMULATIVE_VOTE_REWARDS)
120 |
121 | if (!settings.weekly.enabled || settings.weekly.entries.isEmpty())
122 | {
123 | return
124 | }
125 |
126 | settings.weekly.entries.filter { entry -> entry.votes == party.usersHandler.getVoteCountSince(player, LeaderboardType.WEEKLY.start.invoke()) }.forEach { entry ->
127 | entry.commands.forEach()
128 | { command ->
129 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
130 | }
131 | }
132 | }
133 |
134 | fun checkMonthlyCumulative(player: Player)
135 | {
136 | val settings = party.conf().getProperty(VoteSettings.CUMULATIVE_VOTE_REWARDS)
137 |
138 | if (!settings.monthly.enabled || settings.monthly.entries.isEmpty())
139 | {
140 | return
141 | }
142 |
143 | settings.monthly.entries.filter { entry -> entry.votes == party.usersHandler.getVoteCountSince(player, LeaderboardType.MONTHLY.start.invoke()) }.forEach { entry ->
144 | entry.commands.forEach()
145 | { command ->
146 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
147 | }
148 | }
149 | }
150 |
151 | fun checkYearlyCumulative(player: Player)
152 | {
153 | val settings = party.conf().getProperty(VoteSettings.CUMULATIVE_VOTE_REWARDS)
154 |
155 | if (!settings.yearly.enabled || settings.yearly.entries.isEmpty())
156 | {
157 | return
158 | }
159 |
160 | settings.yearly.entries.filter { entry -> entry.votes == party.usersHandler.getVoteCountSince(player, LeaderboardType.ANNUALLY.start.invoke()) }.forEach { entry ->
161 | entry.commands.forEach()
162 | { command ->
163 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
164 | }
165 | }
166 | }
167 |
168 | fun checkTotalCumulative(player: Player)
169 | {
170 | val settings = party.conf().getProperty(VoteSettings.CUMULATIVE_VOTE_REWARDS)
171 |
172 | if (!settings.total.enabled || settings.total.entries.isEmpty())
173 | {
174 | return
175 | }
176 |
177 | settings.total.entries.filter { entry -> entry.votes == party.usersHandler.getVoteCountSince(player, LeaderboardType.ALLTIME.start.invoke()) }.forEach { entry ->
178 | entry.commands.forEach()
179 | { command ->
180 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
181 | }
182 | }
183 | }
184 |
185 | fun giveVotesiteVoteRewards(player: Player, serviceName: String)
186 | {
187 | val settings = party.conf().getProperty(VoteSettings.VOTESITE_VOTE_REWARDS)
188 |
189 | if (!settings.enabled || settings.votesiteCommands.isEmpty())
190 | {
191 | return
192 | }
193 |
194 | val first = settings.votesiteCommands.firstOrNull { serviceName == it.serviceName }
195 |
196 | first?.commands?.forEach()
197 | {
198 | server.dispatchCommand(server.consoleSender, formMessage(player, it))
199 | }
200 | }
201 |
202 | fun giveFirstTimeVoteRewards(player: Player)
203 | {
204 | val settings = party.conf().getProperty(VoteSettings.FIRST_TIME_REWARDS)
205 |
206 | if (!settings.enabled || settings.commands.isEmpty())
207 | {
208 | return
209 | }
210 |
211 | settings.commands.forEach()
212 | { command ->
213 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
214 | }
215 | }
216 |
217 | fun giveRandomVoteRewards(player: Player)
218 | {
219 | val settings = party.conf().getProperty(VoteSettings.PER_VOTE_REWARDS)
220 |
221 | if (!settings.enabled || settings.max_possible <= 0 || settings.commands.isEmpty())
222 | {
223 | return
224 | }
225 |
226 | settings.commands.takeRandomly(settings.max_possible).forEach()
227 | { section ->
228 | section.command.forEach()
229 | { command ->
230 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
231 | }
232 | }
233 | }
234 |
235 | fun playerVoteEffects(player: Player)
236 | {
237 | val settings = party.conf().getProperty(EffectsSettings.VOTE)
238 |
239 | if (!settings.enable || settings.effects.isEmpty())
240 | {
241 | return
242 | }
243 |
244 | val location = player.location
245 |
246 | settings.effects.forEach {
247 | party.hook().display(EffectType.valueOf(it), location, settings.offsetX, settings.offsetY, settings.offsetZ, settings.speed, settings.count)
248 | }
249 | }
250 |
251 | fun runGlobalCommands(player: Player)
252 | {
253 | val settings = party.conf().getProperty(VoteSettings.GLOBAL_COMMANDS)
254 |
255 | if (!settings.enabled || settings.commands.isEmpty())
256 | {
257 | return
258 | }
259 |
260 | settings.commands.forEach()
261 | { command ->
262 | server.dispatchCommand(server.consoleSender, formMessage(player, command))
263 | }
264 | }
265 |
266 | fun sendVoteReminders()
267 | {
268 | val players = Bukkit.getOnlinePlayers().filter {
269 | party.usersHandler.getVoteCountSince(
270 | it,
271 | party.conf().getProperty(VoteSettings.REMINDER_INTERVAL).toLong(),
272 | TimeUnit.HOURS
273 | ) < party.conf().getProperty(VoteSettings.REMINDER_THRESHOLD)
274 | }
275 |
276 | players.forEach {
277 | sendMessage(party.manager().getCommandIssuer(it), Messages.VOTES__REMINDER)
278 | }
279 | }
280 |
281 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/leaderboard/Leaderboard.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.leaderboard
2 |
3 | import me.clip.voteparty.user.User
4 |
5 | data class Leaderboard(val type: LeaderboardType, val data: List)
6 | {
7 | fun getEntry(entry: Int) : LeaderboardUser?
8 | {
9 | return data.getOrNull((entry - 1).coerceAtLeast(0))
10 | }
11 |
12 | private fun getUser(user: User) : LeaderboardUser?
13 | {
14 | return data.firstOrNull{ user.name == it.name() }
15 | }
16 |
17 | fun getPlacement(user: User) : Int?
18 | {
19 | return data.indexOfFirst { getUser(user) == it }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/leaderboard/LeaderboardType.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.leaderboard
2 |
3 | import java.time.LocalDate
4 | import java.time.LocalDateTime
5 | import java.time.temporal.ChronoField
6 |
7 | enum class LeaderboardType(val start: () -> LocalDateTime, val end: () -> LocalDateTime, val displayName: String) {
8 | DAILY(
9 | { LocalDate.now().atStartOfDay() },
10 | { LocalDateTime.MIN },
11 | "Daily"
12 | ),
13 | WEEKLY(
14 | { LocalDate.now().with(ChronoField.DAY_OF_WEEK, 1).atStartOfDay() },
15 | { LocalDateTime.MIN },
16 | "Weekly"
17 | ),
18 | LASTMONTH(
19 | { LocalDate.now().minusMonths(1).with(ChronoField.DAY_OF_MONTH, 1).atStartOfDay() },
20 | { LocalDate.now().with(ChronoField.DAY_OF_MONTH, 1).atStartOfDay() },
21 | "Last Month"
22 | ),
23 | MONTHLY(
24 | { LocalDate.now().with(ChronoField.DAY_OF_MONTH, 1).atStartOfDay() },
25 | { LocalDateTime.MIN },
26 | "Monthly"
27 | ),
28 | ANNUALLY(
29 | { LocalDate.now().with(ChronoField.DAY_OF_YEAR, 1).atStartOfDay() },
30 | { LocalDateTime.MIN },
31 | "Annually"
32 | ),
33 | ALLTIME(
34 | { LocalDate.now().with(ChronoField.EPOCH_DAY, 1).atStartOfDay() },
35 | { LocalDateTime.MIN },
36 | "All Time"
37 | );
38 |
39 | companion object
40 | {
41 | internal val values = values()
42 |
43 | internal fun find(name: String): LeaderboardType?
44 | {
45 | return values.find { it.name.equals(name, true) }
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/leaderboard/LeaderboardUser.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.leaderboard
2 |
3 | import me.clip.voteparty.user.User
4 |
5 | data class LeaderboardUser(val user: User, var votes: Int)
6 | {
7 | fun name() : String
8 | {
9 | return user.name
10 | }
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/listener/CrateListener.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.listener
2 |
3 | import me.clip.voteparty.conf.sections.CrateSettings
4 | import me.clip.voteparty.conf.sections.PartySettings
5 | import me.clip.voteparty.listener.base.VotePartyListener
6 | import me.clip.voteparty.plugin.VotePartyPlugin
7 | import org.bukkit.event.EventHandler
8 | import org.bukkit.event.block.Action
9 | import org.bukkit.event.player.PlayerInteractEvent
10 |
11 | internal class CrateListener(override val plugin: VotePartyPlugin) : VotePartyListener
12 | {
13 |
14 | @EventHandler
15 | fun PlayerInteractEvent.onInteract()
16 | {
17 | if (party.conf().getProperty(CrateSettings.ENABLED) == false)
18 | {
19 | return
20 | }
21 |
22 | if (action != Action.RIGHT_CLICK_AIR && action != Action.RIGHT_CLICK_BLOCK)
23 | {
24 | return
25 | }
26 |
27 | val held = player.inventory.itemInHand
28 | val item = party.partyHandler.buildCrate(1)
29 |
30 | if (!held.isSimilar(item))
31 | {
32 | return
33 | }
34 |
35 | if (player.world.name in party.conf().getProperty(PartySettings.DISABLED_WORLDS))
36 | {
37 | return
38 | }
39 |
40 | isCancelled = true
41 |
42 | if (held.amount == 1)
43 | {
44 | player.inventory.removeItem(held)
45 | }
46 | else
47 | {
48 | player.inventory.itemInHand.amount = held.amount - 1
49 | }
50 |
51 | party.partyHandler.runAll(player)
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/listener/HooksListenerNuVotifier.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.listener
2 |
3 | import com.vexsoftware.votifier.model.VotifierEvent
4 | import me.clip.voteparty.conf.sections.VoteSettings
5 | import me.clip.voteparty.events.VoteReceivedEvent
6 | import me.clip.voteparty.listener.base.VotePartyListener
7 | import me.clip.voteparty.plugin.VotePartyPlugin
8 | import org.bukkit.event.EventHandler
9 | import java.util.regex.Pattern
10 |
11 | internal class HooksListenerNuVotifier(override val plugin: VotePartyPlugin) : VotePartyListener
12 | {
13 | private lateinit var usernameRegex: Pattern
14 | override fun load() {
15 | super.load()
16 | usernameRegex = Pattern.compile(party.conf().getProperty(VoteSettings.NAME_REGEX))
17 | }
18 |
19 | @EventHandler
20 | fun VotifierEvent.onVote()
21 | {
22 | if (vote == null || vote.username.isNullOrEmpty()) {
23 | plugin.logger.warning("A vote come through NuVotifier which was null or did not provide a username. Throwing away.")
24 | return
25 | }
26 |
27 | if (party.conf().getProperty(VoteSettings.VALIDATE_NAMES) && !usernameRegex.matcher(vote.username).matches()) {
28 | plugin.logger.warning("A vote came through NuVotifier (username: ${vote.username}) which did not match the username regex. Throwing away.")
29 | return
30 | }
31 |
32 | // Try pulling the username from the user cache first before querying Bukkit / Mojang
33 | val player = party.usersHandler[vote.username]?.player() ?: server.getOfflinePlayer(vote.username)
34 | val event = VoteReceivedEvent(player, vote.serviceName)
35 | server.pluginManager.callEvent(event)
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/listener/VotesListener.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.listener
2 |
3 | import me.clip.voteparty.conf.sections.PartySettings
4 | import me.clip.voteparty.conf.sections.PluginSettings
5 | import me.clip.voteparty.conf.sections.VoteSettings
6 | import me.clip.voteparty.events.VoteReceivedEvent
7 | import me.clip.voteparty.exte.runTaskLater
8 | import me.clip.voteparty.exte.sendMessage
9 | import me.clip.voteparty.listener.base.VotePartyListener
10 | import me.clip.voteparty.messages.Messages
11 | import me.clip.voteparty.plugin.VotePartyPlugin
12 | import org.bukkit.event.EventHandler
13 | import org.bukkit.event.EventPriority
14 | import org.bukkit.event.player.PlayerJoinEvent
15 |
16 | internal class VotesListener(override val plugin: VotePartyPlugin) : VotePartyListener
17 | {
18 |
19 | @EventHandler
20 | fun VoteReceivedEvent.onReceive()
21 | {
22 |
23 | var first = false
24 |
25 | val user = party.usersHandler[player]
26 | if (!user.hasVotedBefore())
27 | {
28 | first = true
29 | }
30 | user.voted()
31 |
32 | if (!player.isOnline && party.conf().getProperty(VoteSettings.OFFLINE_VOTE_CLAIMING))
33 | {
34 | user.claimable++
35 | }
36 |
37 | if (party.conf().getProperty(PluginSettings.SAVE_ON_VOTE))
38 | {
39 | party.usersHandler.save(user)
40 | }
41 |
42 | if (!player.isOnline && !party.conf().getProperty(PartySettings.OFFLINE_VOTES))
43 | {
44 | return
45 | }
46 |
47 | if ((party.conf().getProperty(PartySettings.PARTY_MODE) == "party") && !party.partyHandler.voted.contains(user.uuid)) {
48 | party.partyHandler.voted.add(user.uuid)
49 | }
50 |
51 | party.votesHandler.addVotes(1)
52 |
53 | val online = player.player ?: return
54 |
55 |
56 | if (online.inventory.firstEmpty() == -1 && party.conf().getProperty(VoteSettings.CLAIMABLE_IF_FULL))
57 | {
58 | user.claimable++
59 | return sendMessage(party.manager().getCommandIssuer(online), Messages.VOTES__INVENTORY_FULL)
60 | }
61 |
62 | party.votesHandler.runGlobalCommands(online)
63 | party.votesHandler.runAll(online)
64 |
65 | if (vote != "")
66 | {
67 | party.votesHandler.giveVotesiteVoteRewards(online, vote)
68 | }
69 |
70 | if (first)
71 | {
72 | party.votesHandler.giveFirstTimeVoteRewards(online)
73 | }
74 |
75 | party.votesHandler.checkDailyCumulative(online)
76 | party.votesHandler.checkWeeklyCumulative(online)
77 | party.votesHandler.checkMonthlyCumulative(online)
78 | party.votesHandler.checkYearlyCumulative(online)
79 | party.votesHandler.checkTotalCumulative(online)
80 |
81 | party.votesHandler.playerVoteEffects(online)
82 | }
83 |
84 | @EventHandler(priority = EventPriority.HIGH)
85 | fun PlayerJoinEvent.onJoin()
86 | {
87 | if (!player.hasPlayedBefore())
88 | {
89 | return
90 | }
91 |
92 | if (party.usersHandler[player].claimable > 0 && party.conf().getProperty(VoteSettings.OFFLINE_VOTE_CLAIMING_NOTIFY))
93 | {
94 | plugin.runTaskLater(40L)
95 | {
96 | sendMessage(party.manager().getCommandIssuer(player), Messages.CLAIM__NOTIFY)
97 | }
98 | }
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/listener/base/VotePartyListener.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.listener.base
2 |
3 | import me.clip.voteparty.base.Addon
4 | import me.clip.voteparty.base.State
5 | import org.bukkit.event.HandlerList
6 | import org.bukkit.event.Listener
7 |
8 | internal interface VotePartyListener : Addon, State, Listener
9 | {
10 |
11 | override fun load()
12 | {
13 | server.pluginManager.registerEvents(this, plugin)
14 | }
15 |
16 | override fun kill()
17 | {
18 | HandlerList.unregisterAll(this)
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/messages/Messages.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.messages
2 |
3 | import co.aikar.locales.MessageKey
4 | import co.aikar.locales.MessageKeyProvider
5 | import java.util.*
6 |
7 | enum class Messages : MessageKeyProvider
8 | {
9 |
10 | ERROR__LEADERBOARD_NOT_FOUND,
11 | ERROR__INVALID_PAGE_NUMBER,
12 | ERROR__INVALID_NUMBER,
13 | ERROR__DISABLED_WORLD,
14 | ERROR__USER_NOT_FOUND,
15 |
16 | INFO__VOTES_NEEDED,
17 | INFO__RELOADED,
18 | INFO__VOTE_COUNT_RESET,
19 | INFO__PLAYER_TOTAL_VOTES,
20 | INFO__PLAYER_CHECK_VOTES,
21 |
22 | PARTY__FORCE_START_SUCCESSFUL,
23 | PARTY__REQUIREMENTS_NOT_MET,
24 |
25 | VOTES__VOTES_NEEDED_UPDATED,
26 | VOTES__VOTE_COUNTER_UPDATED,
27 | VOTES__PRIVATE_PARTY_GIVEN,
28 | VOTES__PRIVATE_PARTY_RECEIVED,
29 | VOTES__ADDED_TO_PLAYER,
30 | VOTES__INVENTORY_FULL,
31 | VOTES__REMINDER,
32 |
33 | CRATE__CRATE_GIVEN,
34 | CRATE__CRATE_RECEIVED,
35 |
36 | CLAIM__SUCCESS,
37 | CLAIM__SUCCESS_ALL,
38 | CLAIM__NONE,
39 | CLAIM__NOTIFY,
40 | CLAIM__FULL,
41 | CLAIM__FULL_ALL,
42 |
43 | DESCRIPTIONS__HELP,
44 | DESCRIPTIONS__SETCOUNTER,
45 | DESCRIPTIONS__ADDVOTE,
46 | DESCRIPTIONS__STARTPARTY,
47 | DESCRIPTIONS__TOP,
48 | DESCRIPTIONS__ADDPARTYVOTE,
49 | DESCRIPTIONS__GIVECRATE,
50 | DESCRIPTIONS__GIVEPARTY,
51 | DESCRIPTIONS__RELOAD,
52 | DESCRIPTIONS__CHECKVOTES,
53 | DESCRIPTIONS__TOTALVOTES,
54 | DESCRIPTIONS__RESETVOTES,
55 | DESCRIPTIONS__CLAIM,
56 | DESCRIPTIONS__CLAIMALL,
57 |
58 | TOP__HEADER,
59 | TOP__LINE,
60 | TOP__FOOTER,
61 |
62 | HELP__HEADER,
63 | HELP__LINE_TEXT,
64 | HELP__LINE_HOVER,
65 | HELP__FOOTER;
66 |
67 |
68 | private val key = MessageKey.of(name.lowercase(Locale.getDefault()).replace("__", ".").replace('_', '-'))
69 |
70 | override fun getMessageKey(): MessageKey
71 | {
72 | return key
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/placeholders/VotePartyPlaceholders.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.placeholders
2 |
3 | import me.clip.placeholderapi.expansion.PlaceholderExpansion
4 | import me.clip.voteparty.VoteParty
5 | import me.clip.voteparty.leaderboard.LeaderboardType
6 | import org.bukkit.OfflinePlayer
7 | import java.util.*
8 |
9 | class VotePartyPlaceholders(private val voteParty: VoteParty) : PlaceholderExpansion()
10 | {
11 |
12 | override fun getAuthor(): String
13 | {
14 | return "Glare"
15 | }
16 |
17 | override fun getVersion(): String
18 | {
19 | return "2.0"
20 | }
21 |
22 | override fun getIdentifier(): String
23 | {
24 | return "voteparty"
25 | }
26 |
27 | override fun persist(): Boolean
28 | {
29 | return true
30 | }
31 |
32 |
33 | override fun onRequest(player: OfflinePlayer?, arg: String): String {
34 | if (arg.startsWith("top_")) {
35 | return getTop(arg.replace("top_", "").lowercase(Locale.getDefault()))
36 | }
37 |
38 | if (arg.startsWith("placement_")) {
39 | return getPlacement(arg.replace("placement_", "").lowercase(Locale.getDefault()), player ?: return "")
40 | }
41 |
42 | if (arg.startsWith("totalvotes_")) {
43 | return getVotes(arg.replace("totalvotes_", "").lowercase(Locale.getDefault()), player ?: return "")
44 | }
45 |
46 | if (arg.startsWith("totalparties_")) {
47 | return getParties(arg.replace("totalparties_", "").lowercase(Locale.getDefault()))
48 | }
49 |
50 | return when (arg.lowercase(Locale.getDefault())) {
51 | "votes_recorded" -> voteParty.getVotes().toString()
52 | "votes_required_party" -> voteParty.getVotesNeeded().minus(voteParty.getVotes()).toString()
53 | "votes_required_total" -> voteParty.getVotesNeeded().toString()
54 | "votes_total" -> voteParty.usersHandler.getTotalVotes().toString()
55 | "player_votes" -> voteParty.usersHandler[player ?: return ""].votes().size.toString()
56 | else -> ""
57 | }
58 | }
59 |
60 | /**
61 | * Get the "top" data for a leaderboard
62 | */
63 | private fun getTop(input: String): String
64 | {
65 | val (type, info, placement) = input.split('_').takeIf { it.size >= 3 } ?: return ""
66 |
67 | // Get the leaderboard type but return empty if invalid type
68 | val leaderboard = LeaderboardType.find(type)?.let(voteParty.leaderboardHandler::getLeaderboard) ?: return ""
69 |
70 | // Get the user if the placeholder isn't null
71 | val user = placement.toIntOrNull()?.let(leaderboard::getEntry) ?: return ""
72 |
73 | // Return the correct data
74 | return when (info)
75 | {
76 | "name" -> user.name()
77 | "votes" -> user.votes.toString()
78 | else -> ""
79 | }
80 | }
81 |
82 | /**
83 | * Get the placement of a player based on the given leaderboard type
84 | */
85 | private fun getPlacement(input: String, player: OfflinePlayer): String
86 | {
87 | val leaderboard = LeaderboardType.find(input)?.let(voteParty.leaderboardHandler::getLeaderboard) ?: return ""
88 |
89 | return leaderboard.getPlacement(voteParty.usersHandler[player])?.plus(1)?.toString() ?: ""
90 | }
91 |
92 | /**
93 | * Get the amount of votes a player has based on the given leaderboard type
94 | */
95 | private fun getVotes(input: String, player: OfflinePlayer): String
96 | {
97 | return LeaderboardType.find(input)?.let {
98 | voteParty.usersHandler.getVoteCountWithinRange(player, it.start.invoke(), it.end.invoke())
99 | }?.toString() ?: ""
100 | }
101 |
102 | /**
103 | * Get the amount of parties that have been triggered based on the given leaderboard type
104 | */
105 | private fun getParties(input: String): String
106 | {
107 | return LeaderboardType.find(input)?.let { voteParty.partyHandler.getPartiesSince(it.start.invoke()) }?.toString() ?: ""
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/user/User.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.user
2 |
3 | import org.bukkit.Bukkit
4 | import org.bukkit.OfflinePlayer
5 | import java.util.UUID
6 |
7 | data class User(val uuid: UUID, var name: String, private val data: MutableList, var claimable: Int)
8 | {
9 |
10 | fun voted()
11 | {
12 | data += System.currentTimeMillis()
13 | }
14 |
15 | fun votes(): List
16 | {
17 | return data
18 | }
19 |
20 | fun hasVotedBefore(): Boolean
21 | {
22 | return data.isNotEmpty()
23 | }
24 |
25 | fun reset()
26 | {
27 | data.clear()
28 | }
29 |
30 | fun player() : OfflinePlayer
31 | {
32 | return Bukkit.getOfflinePlayer(uuid)
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/user/UsersHandler.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.user
2 |
3 | import me.clip.voteparty.base.Addon
4 | import me.clip.voteparty.base.State
5 | import me.clip.voteparty.data.impl.DatabaseVotePlayerGson
6 | import me.clip.voteparty.leaderboard.LeaderboardUser
7 | import me.clip.voteparty.plugin.VotePartyPlugin
8 | import org.bukkit.OfflinePlayer
9 | import org.bukkit.event.EventHandler
10 | import org.bukkit.event.HandlerList
11 | import org.bukkit.event.Listener
12 | import org.bukkit.event.player.PlayerJoinEvent
13 | import java.time.Instant
14 | import java.time.LocalDateTime
15 | import java.time.ZoneId
16 | import java.util.*
17 | import java.util.concurrent.TimeUnit
18 |
19 | /**
20 | *
21 | * And I quote. "Wait till someone complains" - Glare 2020
22 | *
23 | */
24 | class UsersHandler(override val plugin: VotePartyPlugin) : Addon, State, Listener
25 | {
26 |
27 | private val database = DatabaseVotePlayerGson(plugin)
28 | private val cached = mutableMapOf()
29 |
30 |
31 | override fun load()
32 | {
33 | database.load()
34 |
35 | database.load(emptyList()).forEach()
36 | { (_, data) ->
37 | data ?: return@forEach
38 |
39 | cached[data.uuid] = data
40 | cached[data.name.lowercase(Locale.getDefault())] = data
41 | }
42 | server.pluginManager.registerEvents(this, plugin)
43 | }
44 |
45 | override fun kill()
46 | {
47 | saveAll()
48 | database.kill()
49 |
50 | cached.clear()
51 |
52 | HandlerList.unregisterAll(this)
53 | }
54 |
55 |
56 | operator fun get(uuid: UUID): User
57 | {
58 | return cached.getOrPut(uuid)
59 | {
60 | User(uuid, "", mutableListOf(), 0)
61 | }
62 | }
63 |
64 | operator fun get(name: String): User?
65 | {
66 | return cached[name.lowercase(Locale.getDefault())]
67 | }
68 |
69 | operator fun get(player: OfflinePlayer): User
70 | {
71 | return get(player.uniqueId)
72 | }
73 |
74 |
75 | fun reset(player: OfflinePlayer)
76 | {
77 | get(player).reset()
78 | }
79 |
80 | fun saveAll()
81 | {
82 | database.save(cached.values.distinct())
83 | }
84 |
85 | fun save(user: User)
86 | {
87 | database.save(user)
88 | }
89 |
90 | /**
91 | * Get the amount of votes a player has made since the given time.
92 | * @param offlinePlayer The player to check.
93 | * @param amount The amount of time to check since.
94 | * @param unit The unit of time to check since.
95 | * @return The amount of votes the player has made since the given time.
96 | */
97 | fun getVoteCountSince(offlinePlayer: OfflinePlayer, amount: Long, unit: TimeUnit): Int
98 | {
99 | val timeEpoch = Instant.now().minusMillis(TimeUnit.MILLISECONDS.convert(amount, unit)).toEpochMilli()
100 |
101 | return getVoteCountSince(offlinePlayer, timeEpoch)
102 | }
103 |
104 | /**
105 | * Get the amount of votes a player has made since the given time.
106 | * @param offlinePlayer The player to check.
107 | * @param time The time to check since.
108 | * @return The amount of votes the player has made since the given time.
109 | */
110 | fun getVoteCountSince(offlinePlayer: OfflinePlayer, time: LocalDateTime): Int
111 | {
112 | val timeEpoch = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
113 |
114 | return getVoteCountSince(offlinePlayer, timeEpoch)
115 | }
116 |
117 | /**
118 | * Get the amount of votes a player has made since the given time.
119 | * @param offlinePlayer The player to check.
120 | * @param epoch The epoch time to check since.
121 | * @return The amount of votes the player has made since the given time.
122 | */
123 | fun getVoteCountSince(offlinePlayer: OfflinePlayer, epoch: Long) : Int
124 | {
125 | return get(offlinePlayer).votes().count { it >= epoch }
126 | }
127 |
128 | /**
129 | * Get the amount of votes a player has made in a range of time.
130 | * @param offlinePlayer The player to check.
131 | * @param start The start of the range.
132 | * @param end The end of the range.
133 | * @return The amount of votes the player has made in the given range.
134 | */
135 | fun getVoteCountWithinRange(offlinePlayer: OfflinePlayer, start: LocalDateTime, end: LocalDateTime): Int
136 | {
137 | if (end < start) {
138 | return getVoteCountSince(offlinePlayer, start)
139 | }
140 |
141 | val startEpoch = start.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
142 | val endEpoch = end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
143 |
144 | return getVoteCountWithinRange(offlinePlayer, startEpoch, endEpoch)
145 | }
146 |
147 | /**
148 | * Get the amount of votes a player has made in a range of time.
149 | * @param offlinePlayer The player to check.
150 | * @param startEpoch The start of the range.
151 | * @param endEpoch The end of the range.
152 | * @return The amount of votes the player has made in the given range.
153 | */
154 | fun getVoteCountWithinRange(offlinePlayer: OfflinePlayer, startEpoch: Long, endEpoch: Long): Int
155 | {
156 | if (endEpoch < startEpoch) {
157 | return getVoteCountSince(offlinePlayer, startEpoch)
158 | }
159 |
160 | return get(offlinePlayer).votes().count { voteEpoch -> voteEpoch in startEpoch until endEpoch }
161 | }
162 |
163 | /**
164 | * Get a list of all players who have voted since the given time.
165 | * @param amount The amount of time to check since.
166 | * @param unit The unit of time to check since.
167 | */
168 | fun getPlayersWhoVotedSince(amount: Long, unit: TimeUnit) : List
169 | {
170 | val timeEpoch = Instant.now().minusMillis(TimeUnit.MILLISECONDS.convert(amount, unit)).toEpochMilli()
171 |
172 | return getPlayersWhoVotedSince(timeEpoch)
173 | }
174 |
175 | /**
176 | * Get a list of all players who have voted since the given time.
177 | * @param epoch The epoch time to check since.
178 | * @return A list of players who have voted since the given time.
179 | */
180 | fun getPlayersWhoVotedSince(epoch: Long): List
181 | {
182 | return cached.values.distinct().filter { getVoteCountSince(it.player(), epoch) > 0 }.map { it.uuid }
183 | }
184 |
185 | /**
186 | * Get a list of all users who have voted within the given range with the amount of votes they have made in that range.
187 | * @param start The start of the range.
188 | * @param end The end of the range.
189 | * @return A list of users who have voted within the given range.
190 | */
191 | fun getUsersWithVotesWithinRange(start: LocalDateTime, end: LocalDateTime): List
192 | {
193 | if (end < start) {
194 | return getUsersWithVotesSince(start)
195 | }
196 |
197 | val startEpoch = start.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
198 | val endEpoch = end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
199 |
200 | return cached.values.asSequence()
201 | .distinct()
202 | .filter()
203 | { user ->
204 | user.votes().isNotEmpty()
205 | }
206 | .map()
207 | { user ->
208 |
209 | val votes = user.votes().count()
210 | { voteEpoch ->
211 | voteEpoch in startEpoch until endEpoch
212 | }
213 |
214 | LeaderboardUser(user, votes)
215 | }
216 | .sortedByDescending()
217 | { user ->
218 | user.votes
219 | }
220 | .toList()
221 | }
222 |
223 | /**
224 | * Get a list of all users who have voted since the given time with the amount of votes they have made since then.
225 | * @param time The time to check since.
226 | * @return A list of users who have voted since the given time.
227 | */
228 | fun getUsersWithVotesSince(time: LocalDateTime): List
229 | {
230 | val timeEpoch = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
231 |
232 | return getUsersWithVotesSince(timeEpoch)
233 | }
234 |
235 | /**
236 | * Get a list of all users who have voted since the given time with the amount of votes they have made since then.
237 | * @param epoch The epoch time to check since.
238 | * @return A list of users who have voted since the given time.
239 | */
240 | fun getUsersWithVotesSince(epoch: Long) : List
241 | {
242 | return cached.values.asSequence().distinct()
243 | .filter { it.votes().isNotEmpty() }
244 | .map { user -> LeaderboardUser(user, user.votes().count { voteTime -> voteTime >= epoch }) }
245 | .sortedByDescending { it.votes }
246 | .toList()
247 | }
248 |
249 | /**
250 | * Get the total amount of votes made by all users ever.
251 | * @return The total amount of votes made by all users ever.
252 | */
253 | fun getTotalVotes(): Int {
254 | return cached.values.distinct().sumOf { it.votes().size }
255 | }
256 |
257 | @EventHandler
258 | fun PlayerJoinEvent.onJoin()
259 | {
260 | val old = cached[player.uniqueId]
261 |
262 | if (old != null && old.name != player.name) {
263 | cached -= old.name.lowercase(Locale.getDefault())
264 | cached[player.name.lowercase(Locale.getDefault())] = old
265 | old.name = player.name
266 | }
267 |
268 | if (old == null)
269 | {
270 | val new = User(player.uniqueId, player.name, mutableListOf(), 0)
271 |
272 | cached[new.uuid] = new
273 | cached[new.name.lowercase(Locale.getDefault())] = new
274 | }
275 | }
276 |
277 | }
278 |
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/util/JarFileWalker.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.util
2 |
3 | import java.io.InputStream
4 | import java.nio.file.FileSystems
5 | import java.nio.file.Files
6 | import java.nio.file.Path
7 |
8 | /**
9 | * Walks the "directory" inside the actual jar
10 | */
11 | object JarFileWalker
12 | {
13 |
14 | fun walk(path: String, function: (Path, InputStream?) -> Unit)
15 | {
16 | FileSystems.newFileSystem(javaClass.getResource(path).toURI(), emptyMap()).use()
17 | { files ->
18 | Files.walk(files.getPath(path)).forEach()
19 | { path ->
20 | if (Files.isDirectory(path))
21 | {
22 | return@forEach // do nothing if this is a directory
23 | }
24 |
25 | try
26 | {
27 | // attempt to pass the stream for this resource
28 | function.invoke(path, javaClass.classLoader.getResourceAsStream(path.toString().drop(1)))
29 | }
30 | catch (ex: Exception)
31 | {
32 | // fallback to just the path
33 | function.invoke(path, null)
34 | }
35 | }
36 | }
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/src/main/kotlin/me/clip/voteparty/util/UpdateChecker.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.util
2 |
3 | import org.bukkit.plugin.Plugin
4 | import java.net.URL
5 |
6 | object UpdateChecker
7 | {
8 |
9 | private const val API = "https://api.spigotmc.org/legacy/update.php?resource=%d"
10 |
11 |
12 | fun check(plugin: Plugin, id: Int, complete: (result: UpdateResult) -> Unit)
13 | {
14 | plugin.server.scheduler.runTaskAsynchronously(plugin, Runnable
15 | {
16 | complete.invoke(check(plugin.description.version, id))
17 | })
18 | }
19 |
20 | /**
21 | * runs the update check on the current thread, and returns an appropriate result
22 | */
23 | fun check(version: String, id: Int): UpdateResult
24 | {
25 | val old = version
26 | val new = try
27 | {
28 | URL(API.format(id)).readText()
29 | }
30 | catch (ex: Exception)
31 | {
32 | return UpdateResult.EXCEPTIONS(throwable = ex)
33 | }
34 |
35 | if (old == new)
36 | {
37 | return UpdateResult.UP_TO_DATE
38 | }
39 |
40 | val oldVersion = old.split('.').mapNotNull(String::toIntOrNull)
41 | val newVersion = new.split('.').mapNotNull(String::toIntOrNull)
42 |
43 | if (newVersion.size > oldVersion.size)
44 | {
45 | return UpdateResult.NEW_UPDATE(version = new)
46 | }
47 |
48 | oldVersion.forEachIndexed()
49 | { index, value ->
50 | if (value >= newVersion[index])
51 | {
52 | return@forEachIndexed
53 | }
54 |
55 | return UpdateResult.NEW_UPDATE(version = new)
56 | }
57 |
58 | return UpdateResult.UNRELEASED
59 | }
60 |
61 |
62 | private data class Version(val name: String?)
63 |
64 | sealed class UpdateResult
65 | {
66 |
67 | abstract val message: String
68 |
69 |
70 | object UP_TO_DATE : UpdateResult()
71 | {
72 | override val message = "Version is up to date"
73 |
74 |
75 | override fun toString(): String
76 | {
77 | return "UP_TO_DATE(${UNRELEASED.message})"
78 | }
79 |
80 | }
81 |
82 | object UNRELEASED : UpdateResult()
83 | {
84 | override val message = "You're on a newer version than latest"
85 |
86 | override fun toString(): String
87 | {
88 | return "UNRELEASED($message)"
89 | }
90 |
91 | }
92 |
93 | data class NEW_UPDATE(override val message: String = "There is an update available", val version: String)
94 | : UpdateResult()
95 |
96 | data class EXCEPTIONS(override val message: String = "Failed to check for an update", val throwable: Throwable)
97 | : UpdateResult()
98 |
99 | }
100 |
101 | }
--------------------------------------------------------------------------------
/src/main/resources/config.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darbyjack/VoteParty/456c4c7565bfdaa1f917c7259486126e1f0abd2c/src/main/resources/config.yml
--------------------------------------------------------------------------------
/src/main/resources/languages/de-DE.yml:
--------------------------------------------------------------------------------
1 | ---
2 | descriptions:
3 | help: "Hilfreiche Befehle für VoteParty."
4 | setcounter: "Setzt den aktuellen Stimmenzähler."
5 | addvote: "Add a vote to a player with the ability to trigger or not the rewards."
6 | addpartyvote: "Add a vote to the party"
7 | startparty: "Erzwingt eine VoteParty."
8 | givecrate: "Versorge ein Player mit einem Vote."
9 | giveparty: "Führt eine Private Vote Party für einen Spieler durch."
10 | reload: "Lädt die Konfiguration und die Sprach Daten erneut."
11 | checkvotes: "Checkt die Anzahl der Votes die ein Spieler hat."
12 | totalvotes: "Erhalte die Gesamtanzahl an Stimmen, die ein Spieler hat."
13 | resetvotes: "Setze die Anzahl der Stimmen zurück, die ein Spieler hat."
14 | claim: "Beanspruchen der Belohnung für Offline Votes."
15 | claimall: "Claim all rewards from offline votes at once."
16 | top: "List top voters."
17 | error:
18 | leaderboard-not-found: "&fSorry, but could not find a leaderboard of type: {type}!"
19 | invalid-page-number: "&fSorry, but this page number is invalid! Please use a number between &d1 &fand &d{max}&f!"
20 | invalid-number: "&fEntschuldige, aber diese Zahl muss positiv sein, um korrekt zu funktionieren!"
21 | disabled-world: "&fEntschuldige, aber dieser Spieler ist derzeit in einer deaktivierten Welt!"
22 | user-not-found: "&fEntschuldige, dieser Spieler konnte nicht gefunden werden!"
23 | info:
24 | votes-needed: "&d%voteparty_votes_required_party% Votes &fbenötigt für die nächste Party."
25 | reloaded: "&fDie Konfiguration wurde neu geladen!"
26 | player-total-votes: "&d%player_name% &fhat &d%voteparty_player_votes% &fvote(s)!"
27 | player-check-votes: "&d%player_name% &f hat in &d{count} &fZeit der letzten &d{amount} {unit}&d &fgevotet!"
28 | vote-count-reset: "&d%player_name%&f's Stimmenanzahl wurde zurückgesetzt auf &d0&f!"
29 | party:
30 | force-start-successful: "&fDu hast eine &dVote Party gestartet &ffür alle Spieler online!"
31 | requirements-not-met: "&fSorry, but you did not meet the requirements to join this party!"
32 | votes:
33 | votes-needed-updated: "&fNeue erforderlichen Stimmen wurden gesetzt! &d%voteparty_votes_required_party% Votes &fwerden benötigt für die nächste Party."
34 | vote-counter-updated: "&fAktuell Votes wurden geupdated zu &d%voteparty_votes_recorded%&f!"
35 | private-party-given: "&fDu gibst eine Private &dVote Party &ffür &d%player_name%&f!"
36 | private-party-received: "&fDu hast eine private &dVote Party&f erhalten!"
37 | added-to-player: "&fDu hast {count} Stimmen für %player_name% gegeben!"
38 | inventory-full: "&fDein Inventar scheint voll zu sein! Wir haben deine Vote Belohnung in dein Rucksack gepackt! Mache /vp claim, sobald dein Inventar nicht voll ist!"
39 | reminder: "&fDon't forget to vote for our server!"
40 | crate:
41 | crate-given: "&fDu hast &d%player_name% &fvote bekommen oder erstellt!"
42 | crate-received: "Du hast ein Vote erstellt!"
43 | claim:
44 | success: "&fDu hast erfolgreich die Belohnungen von deiner Offline-Abstimmung abgeholt! Du hast &d{claim} &fnoch zur abzuholen."
45 | success-all: "&fYou successfully claimed the rewards for all offline votes!"
46 | none: "&fDu hast keine Belohnungen von Offline-Votes!"
47 | notify: "&fHey! Du scheinst offline abgestimmt zu haben! Du hast eine oder einige Belohnungen! Sammle sie durch die Verwendung von &d/vp claim&f &fein!"
48 | full: "&aDein Inventar ist voll! Mache platz und versuche es erneut!"
49 | full-all: "&aYour inventory is full! Make some space and try again! You have claimed &d{claimed} &aoffline rewards. You have &d{claim} &aleft to claim."
50 | top:
51 | header: "&fTop Voters - {type}"
52 | line: "&e{position}. &fUser: &d{player} &f- Votes: &d{votes}"
53 | footer: "&fPage: &d{page} &f/ &d{total}"
54 | help:
55 | header: " VoteParty Hilfe "
56 | line-text: "• /vp {cmd}\n"
57 | line-hover: "{text}\n{desc}\n\n/vp {cmd} {args}\n{perm}"
58 | footer: " \nHover for more info"
59 |
60 |
--------------------------------------------------------------------------------
/src/main/resources/languages/en-US.yml:
--------------------------------------------------------------------------------
1 | descriptions:
2 | help: "Helpful commands for VoteParty."
3 | setcounter: "Set the current vote counter."
4 | addvote: "Add a vote to a player with the ability to trigger or not the rewards."
5 | addpartyvote: "Add a vote to the party"
6 | startparty: "Force launch a VoteParty."
7 | givecrate: "Supply a player with a Vote crate."
8 | giveparty: "Host a private Vote Party for a player."
9 | reload: "Reload the config and language file."
10 | checkvotes: "Check the amount of votes a player has."
11 | totalvotes: "Get the total amount of votes a player has."
12 | resetvotes: "Reset the amount of votes a player has."
13 | claim: "Claim rewards from offline votes."
14 | claimall: "Claim all rewards from offline votes at once."
15 | top: "List top voters."
16 | error:
17 | leaderboard-not-found: "&fSorry, but could not find a leaderboard of type: {type}!"
18 | invalid-page-number: "&fSorry, but this page number is invalid! Please use a number between &d1 &fand &d{max}&f!"
19 | invalid-number: "&fSorry, but this number must be positive in order to work correctly!"
20 | disabled-world: "&fSorry, but this player is currently in a disabled world!"
21 | user-not-found: "&fSorry, but this player could not be found!"
22 | info:
23 | votes-needed: "&d%voteparty_votes_required_party% Votes &fneeded for the next party."
24 | reloaded: "&fThe config has been reloaded!"
25 | player-total-votes: "&d%player_name% &fhas a total of &d%voteparty_player_votes% &fvote(s)!"
26 | player-check-votes: "&d%player_name% &f has voted &d{count} &ftimes in the last &d{amount} {unit}&d!"
27 | vote-count-reset: "&d%player_name%&f's vote count has been reset to &d0&f!"
28 | party:
29 | force-start-successful: "&fYou've force started a &dVote Party &ffor all online players!"
30 | requirements-not-met: "&fSorry, but you did not meet the requirements to join this party!"
31 | votes:
32 | votes-needed-updated: "&fNew required votes has been set! &d%voteparty_votes_required_party% Votes &fneeded for the next party."
33 | vote-counter-updated: "&fCurrent votes updated to &d%voteparty_votes_recorded%&f!"
34 | private-party-given: "&fYou've given a private &dVote Party &fto &d%player_name%&f!"
35 | private-party-received: "&fYou've received a private &dVote Party&f!"
36 | added-to-player: "&fYou've given {count} votes to %player_name%!"
37 | inventory-full: "&fYour inventory seems to be full! We've put this vote in your claimables! Do /vp claim once your inventory isn't full!"
38 | reminder: "&fDon't forget to vote for our server!"
39 | crate:
40 | crate-given: "&fYou've given &d%player_name% &fvote crate(s)!"
41 | crate-received: "&fYou've received a vote crate!"
42 | claim:
43 | success: "&fYou successfully claimed the rewards from an offline vote! You have &d{claim} &fleft to claim."
44 | success-all: "&fYou successfully claimed the rewards for all offline votes!"
45 | none: "&fYou don't have any rewards to claim from offline votes!"
46 | notify: "&fHey there! You seemed to have voted while offline! You have some claiming rewards! Collect them by using &d/vp claim&f!"
47 | full: "&aYour inventory is full! Make some space and try again!"
48 | full-all: "&aYour inventory is full! Make some space and try again! You have claimed &d{claimed} &aoffline rewards. You have &d{claim} &aleft to claim."
49 | top:
50 | header: "&fTop Voters - {type}"
51 | line: "&e{position}. &fUser: &d{player} &f- Votes: &d{votes}"
52 | footer: "&fPage: &d{page} &f/ &d{total}"
53 | help:
54 | header: " VoteParty Help "
55 | line-text: "• /vp {cmd}\n"
56 | line-hover: "{text}\n{desc}\n\n/vp {cmd} {args}\n{perm}"
57 | footer: " \nHover for more info"
58 |
59 |
--------------------------------------------------------------------------------
/src/main/resources/languages/fr-FR.yml:
--------------------------------------------------------------------------------
1 | ---
2 | descriptions:
3 | help: "Commandes utiles pour VoteParty."
4 | setcounter: "Régler le compteur de vote actuel."
5 | addvote: "Add a vote to a player with the ability to trigger or not the rewards."
6 | addpartyvote: "Add a vote to the party"
7 | startparty: "Forcer le lancement d'un VoteParty."
8 | givecrate: "Fournir une caisse de vote à un joueur."
9 | giveparty: "Organiser un VoteParty privée pour un joueur."
10 | reload: "Rechargez le fichier de configuration."
11 | checkvotes: "Vérifiez le nombre de votes d'un joueur."
12 | totalvotes: "Obtenez le nombre total de votes d'un joueur."
13 | resetvotes: "Réinitialisez le nombre de votes d'un joueur."
14 | claim: "Réclamez les récompenses pour vos votes hors ligne."
15 | claimall: "Claim all rewards from offline votes at once."
16 | top: "List top voters."
17 | error:
18 | leaderboard-not-found: "&fSorry, but could not find a leaderboard of type: {type}!"
19 | invalid-page-number: "&fSorry, but this page number is invalid! Please use a number between &d1 &fand &d{max}&f!"
20 | invalid-number: "&fDésolé, mais ce numéro doit être positif pour fonctionner correctement !"
21 | disabled-world: "&fDésolé, mais ce joueur est actuellement dans un monde désactivé !"
22 | user-not-found: "&fDésolé, mais ce joueur est introuvable!"
23 | info:
24 | votes-needed: "&d%voteparty_votes_required_party% Votes &frequis pour la prochaine party."
25 | reloaded: "&fLa configuration a été rechargée !"
26 | player-total-votes: "&d%player_name% &fa un total de &d%voteparty_player_votes% &fvote(s)!"
27 | player-check-votes: "&d%player_name% &f a voté &d{count} &ffois dans le dernier &d{amount} {unit}&d!"
28 | vote-count-reset: "&d%player_name%&f le décompte des votes a été réinitialisé à &d0&f!"
29 | party:
30 | force-start-successful: "&fVous avez lancé de force un &dVote Party &fpour tous les joueurs en ligne !"
31 | requirements-not-met: "&fSorry, but you did not meet the requirements to join this party!"
32 | votes:
33 | votes-needed-updated: "&fDe nouveaux votes obligatoires ont été fixés ! &d%voteparty_votes_required_party% Vote Party &fpour tous les joueurs en ligne."
34 | vote-counter-updated: "&fVotes actuels mis à jour à &d%voteparty_votes_recorded%&f!"
35 | private-party-given: "&f Vous avex donne des &dcaisse de votes &fa %player_name%&f!"
36 | private-party-received: "&fVous avez reçu un &dVote Party&f!"
37 | added-to-player: "&fVous avez donné {count} votes à %player_name%!"
38 | inventory-full: "&fYour inventory seems to be full! We've put this vote in your claimables! Do /vp claim once your inventory isn't full!"
39 | reminder: "&fDon't forget to vote for our server!"
40 | crate:
41 | crate-given: "&fVous avez donné à &d%player_name% &f une vote crate(s)!"
42 | crate-received: "&fVous avez reçu une caisse de vote !"
43 | claim:
44 | success: "&fVous avez réclamé les récompenses pour un vote hors ligne ! Il vous reste &d{claim} &fà récupérer."
45 | success-all: "&fYou successfully claimed the rewards for all offline votes!"
46 | none: "&fVous n'avez aucune récompense à réclamer pour des votes hors ligne !"
47 | notify: "&fHé là! Vous semblez avoir voté pendant que vous étiez hors ligne! Vous pouvez réclamer des récompenses! Collectez-les avec &d/vp claim&f!"
48 | full: "&aYour inventory is full! Make some space and try again!"
49 | full-all: "&aYour inventory is full! Make some space and try again! You have claimed &d{claimed} &aoffline rewards. You have &d{claim} &aleft to claim."
50 | top:
51 | header: "&fTop Voters - {type}"
52 | line: "&e{position}. &fUser: &d{player} &f- Votes: &d{votes}"
53 | footer: "&fPage: &d{page} &f/ &d{total}"
54 | help:
55 | header: " VoteParty Help "
56 | line-text: "• /vp {cmd}\n"
57 | line-hover: "{text}\n{desc}\n\n/vp {cmd} {args}\n{perm}"
58 | footer: " \nHover for more info"
59 |
60 |
--------------------------------------------------------------------------------
/src/main/resources/languages/nl-NL.yml:
--------------------------------------------------------------------------------
1 | ---
2 | descriptions:
3 | help: "Behulpzame commands voor VoteParty."
4 | setcounter: "Stel de huidige stem teller in."
5 | addvote: "Add a vote to a player with the ability to trigger or not the rewards."
6 | addpartyvote: "Add a vote to the party"
7 | startparty: "Forceer het starten van een VoteParty."
8 | givecrate: "Voorzie een speler van een Vote crate."
9 | giveparty: "Organiseer een privé Vote Party voor een speler."
10 | reload: "Herlaad het configuratie- en taalbestand."
11 | checkvotes: "Controleer de hoeveelheid stemmen die een speler heeft."
12 | totalvotes: "Haal het totale aantal stemmen op die een speler heeft."
13 | resetvotes: "Reset het aantal stemmen dat een speler heeft."
14 | claim: "Claim beloningen bij offline stemmen."
15 | claimall: "Claim all rewards from offline votes at once."
16 | top: "List top voters."
17 | error:
18 | leaderboard-not-found: "&fSorry, but could not find a leaderboard of type: {type}!"
19 | invalid-page-number: "&fSorry, but this page number is invalid! Please use a number between &d1 &fand &d{max}&f!"
20 | invalid-number: "&fSorry, maar dit nummer moet positief zijn om goed te werken!"
21 | disabled-world: "&fSorry, maar deze speler bevindt zich momenteel in een uitgeschakelde wereld!"
22 | user-not-found: "&fSorry, deze speler kon niet gevonded worden!"
23 | info:
24 | votes-needed: "&d%voteparty_votes_required_party% stemmen zijn nodig voor de volgende party."
25 | reloaded: "&fDe configuratie is herladen!"
26 | player-total-votes: "&d%player_name% &fheeft een totaal van &d%voteparty_player_votes% &fstem(men)!"
27 | player-check-votes: "&d%player_name% &f heeft &d{count} &fkeer gestemd in de laatste &d{amount} {unit}&d!"
28 | vote-count-reset: "&d%player_name%&f's aantal stemmen is gereset naar &d0&f!"
29 | party:
30 | force-start-successful: "&fJe hebt een &dVote Party &fvoor alle online spelers gestart!"
31 | requirements-not-met: "&fSorry, je voldeed niet aan de vereisten om deel te nemen aan deze VoteParty!"
32 | votes:
33 | votes-needed-updated: "&fNieuwe vereiste stemmen zijn ingesteld! &d%voteparty_votes_required_party% Stemmen &zijn nodig voor de volgende party."
34 | vote-counter-updated: "&fHuidige stemmen bijgewerkt naar &d%voteparty_votes_recorded%&f!"
35 | private-party-given: "&fJe hebt een privé &dVote Party &fgegeven aan &d%player_name%&f!"
36 | private-party-received: "&fJe hebt een privé &dVote Party&f ontvangen!"
37 | added-to-player: "&fJe hebt {count} stemmen aan %player_name% gegeven!"
38 | inventory-full: "&fJou inventaris is vol! We hebben deze stem in je claimables geplaats! Doe /vp claim wanneer je inventaris niet vol is!"
39 | reminder: "&fDon't forget to vote for our server!"
40 | crate:
41 | crate-given: "&fJe hebt &d%player_name% &fvote crate(s) gegeven!"
42 | crate-received: "&fJe hebt een vote crate ontvangen!"
43 | claim:
44 | success: "&fJe hebt succesvol de beloningen geclaimd van een offline stem! Je hebt &d{claim} &fover om te claimen."
45 | success-all: "&fYou successfully claimed the rewards for all offline votes!"
46 | none: "&fJe hebt geen beloningen die je kunt claimen van offline stemmen!"
47 | notify: "&fHey daar! Je leek te hebben gestemd terwijl je offline was! Je hebt enkele claim beloningen beschikbaar! Verzamel ze met behulp van &d/vp claim&f!"
48 | full: "&aJou inventaris is vol! Maak wat plaats en probeer opnieuw!"
49 | full-all: "&aYour inventory is full! Make some space and try again! You have claimed &d{claimed} &aoffline rewards. You have &d{claim} &aleft to claim."
50 | top:
51 | header: "&fTop Voters - {type}"
52 | line: "&e{position}. &fUser: &d{player} &f- Votes: &d{votes}"
53 | footer: "&fPage: &d{page} &f/ &d{total}"
54 | help:
55 | header: " VoteParty Hulp "
56 | line-text: "• /vp {cmd}\n"
57 | line-hover: "{text}\n{desc}\n\n/vp {cmd} {args}\n{perm}"
58 | footer: " \nHover for more info"
59 |
60 |
--------------------------------------------------------------------------------
/src/main/resources/languages/sv-SE.yml:
--------------------------------------------------------------------------------
1 | ---
2 | descriptions:
3 | help: "Hjälpsamma kommandon till VoteParty."
4 | setcounter: "Ange nuvarande röstantal."
5 | addvote: "Add a vote to a player with the ability to trigger or not the rewards."
6 | addpartyvote: "Add a vote to the party"
7 | startparty: "Tvångs kör ett VoteParty."
8 | givecrate: "Förse en spelare med en röstlåda."
9 | giveparty: "Aktivera ett privat Vote Party för en spelare."
10 | reload: "Ladda om konfigurations filerna."
11 | checkvotes: "Kontrollera antalet röster en spelare har."
12 | totalvotes: "Få totala antalet röster en spelare har."
13 | resetvotes: "Nollställ antalet röster en spelare har."
14 | claim: "Hämta belöningar från offline röster."
15 | claimall: "Claim all rewards from offline votes at once."
16 | top: "List top voters."
17 | error:
18 | leaderboard-not-found: "&fSorry, but could not find a leaderboard of type: {type}!"
19 | invalid-page-number: "&fSorry, but this page number is invalid! Please use a number between &d1 &fand &d{max}&f!"
20 | invalid-number: "&fTyvärr, men det måste vara ett positivt heltal för att det ska fungera korrekt!"
21 | disabled-world: "&fTyvärr, men den spelaren är i en avstängd värld!"
22 | user-not-found: "&fTyvärr, men spelaren hittades ej!"
23 | info:
24 | votes-needed: "&d%voteparty_votes_required_party% Röster &fbehövs för nästa party."
25 | reloaded: "&fKonfigurationen config har laddats om!"
26 | player-total-votes: "&d%player_name% &fhar ett totalt antal av &d%voteparty_player_votes% &fröst(er)!"
27 | player-check-votes: "&d%player_name% &fhar röstat &d{count} gånger under de senaste &d{amount} {unit}&d!"
28 | vote-count-reset: "&d%player_name%&f's röster har återställts till &d0&f!"
29 | party:
30 | force-start-successful: "&fDu tvingade igång ett &dVote Party &fför alla onlinespelare!"
31 | requirements-not-met: "&fSorry, but you did not meet the requirements to join this party!"
32 | votes:
33 | votes-needed-updated: "&fNya nödvändiga röster har ändrats! &d%voteparty_votes_required_party% Röster &fbehövda för nästa party."
34 | vote-counter-updated: "&fNuvarande röster uppdaterades till &d%voteparty_votes_recorded%&f!"
35 | private-party-given: "&fDu har skänkt ett privat &dVote Party &ftill &d%player_name%&f!"
36 | private-party-received: "&fDu har fått ett privat &dVote Party&f!"
37 | added-to-player: "&fDu har gett {count} röster till %player_name%!"
38 | inventory-full: "&fYour inventory seems to be full! We've put this vote in your claimables! Do /vp claim once your inventory isn't full!"
39 | reminder: "&fDon't forget to vote for our server!"
40 | crate:
41 | crate-given: "&fDu har gett &d%player_name% röstlådor!"
42 | crate-received: "&fDu har fått en röstlåda!"
43 | claim:
44 | success: "&fDu har lyckats hämtat belöningarna från en offlineröst! Du har &d{claim} &fkvar att hämta."
45 | success-all: "&fYou successfully claimed the rewards for all offline votes!"
46 | none: "&fDu har inga belöningar från offlineröster att hämta!"
47 | notify: "&fHej där! Du har röstat när du varit offline! Du har belöningar att hämta! Samla in dem genom kommandot &d/vp claim&f!"
48 | full: "&aYour inventory is full! Make some space and try again!"
49 | full-all: "&aYour inventory is full! Make some space and try again! You have claimed &d{claimed} &aoffline rewards. You have &d{claim} &aleft to claim."
50 | top:
51 | header: "&fTop Voters - {type}"
52 | line: "&e{position}. &fUser: &d{player} &f- Votes: &d{votes}"
53 | footer: "&fPage: &d{page} &f/ &d{total}"
54 | help:
55 | header: " VoteParty Help "
56 | line-text: "• /vp {cmd}\n"
57 | line-hover: "{text}\n{desc}\n\n/vp {cmd} {args}\n{perm}"
58 | footer: " \nHover for more info"
59 |
60 |
--------------------------------------------------------------------------------
/src/main/resources/parties.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darbyjack/VoteParty/456c4c7565bfdaa1f917c7259486126e1f0abd2c/src/main/resources/parties.json
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: VoteParty
2 | main: me.clip.voteparty.plugin.VotePartyPlugin
3 |
4 | version: '@version@'
5 | website: 'https://helpch.at/discord'
6 | authors: ['Glare', 'Clip', 'Sxtanna']
7 |
8 | depend:
9 | - 'PlaceholderAPI'
10 | softdepend:
11 | - 'Votifier'
12 |
13 | api-version: '1.13'
14 | description: 'Reward players with random commands being executed for them when the server gets x amount of votes'
15 |
16 |
17 | permissions:
18 | voteparty.command.admin:
19 | description: 'Ability to use all admin commands'
20 | default: op
21 | voteparty.command.claim:
22 | description: 'Ability to claim offline vote rewards'
23 | default: true
--------------------------------------------------------------------------------
/src/main/resources/voted-for-party-cache.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darbyjack/VoteParty/456c4c7565bfdaa1f917c7259486126e1f0abd2c/src/main/resources/voted-for-party-cache.json
--------------------------------------------------------------------------------
/src/main/resources/votes.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darbyjack/VoteParty/456c4c7565bfdaa1f917c7259486126e1f0abd2c/src/main/resources/votes.yml
--------------------------------------------------------------------------------
/version/build.gradle:
--------------------------------------------------------------------------------
1 | group 'me.clip'
2 | version '2.0'
3 |
4 | dependencies {
5 | compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT")
6 | }
--------------------------------------------------------------------------------
/version/src/main/kotlin/me/clip/voteparty/version/EffectType.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.version
2 |
3 | enum class EffectType
4 | {
5 |
6 | EXPLOSION_NORMAL,
7 | EXPLOSION_LARGE,
8 | EXPLOSION_HUGE,
9 | FIREWORKS_SPARK,
10 | WATER_BUBBLE,
11 | WATER_SPLASH,
12 | WATER_WAKE,
13 | SUSPENDED,
14 | SUSPENDED_DEPTH,
15 | CRIT,
16 | CRIT_MAGIC,
17 | SMOKE_NORMAL,
18 | SMOKE_LARGE,
19 | SPELL,
20 | SPELL_INSTANT,
21 | SPELL_MOB,
22 | SPELL_MOB_AMBIENT,
23 | SPELL_WITCH,
24 | DRIP_WATER,
25 | DRIP_LAVA,
26 | VILLAGER_ANGRY,
27 | VILLAGER_HAPPY,
28 | TOWN_AURA,
29 | NOTE,
30 | PORTAL,
31 | ENCHANTMENT_TABLE,
32 | FLAME,
33 | LAVA,
34 | CLOUD,
35 | REDSTONE,
36 | SNOWBALL,
37 | SNOW_SHOVEL,
38 | SLIME,
39 | HEART,
40 | BARRIER,
41 | ITEM_CRACK,
42 | BLOCK_CRACK,
43 | BLOCK_DUST,
44 | WATER_DROP,
45 | MOB_APPEARANCE,
46 | DRAGON_BREATH,
47 | END_ROD,
48 | DAMAGE_INDICATOR,
49 | SWEEP_ATTACK,
50 | FALLING_DUST,
51 | TOTEM,
52 | SPIT,
53 | SQUID_INK,
54 | BUBBLE_POP,
55 | CURRENT_DOWN,
56 | BUBBLE_COLUMN_UP,
57 | NAUTILUS,
58 | DOLPHIN,
59 | SNEEZE,
60 | CAMPFIRE_COSY_SMOKE,
61 | CAMPFIRE_SIGNAL_SMOKE,
62 | COMPOSTER,
63 | FLASH,
64 | FALLING_LAVA,
65 | LANDING_LAVA,
66 | FALLING_WATER;
67 |
68 |
69 | companion object
70 | {
71 |
72 | private val values = values()
73 |
74 | fun find(text: String): EffectType?
75 | {
76 | return values.find { it.name.equals(text, true) }
77 | }
78 |
79 | }
80 |
81 | }
--------------------------------------------------------------------------------
/version/src/main/kotlin/me/clip/voteparty/version/VersionHook.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.version
2 |
3 | import org.bukkit.Color
4 | import org.bukkit.Location
5 |
6 | interface VersionHook
7 | {
8 |
9 | fun display(type: EffectType, location: Location, offsetX: Double, offsetY: Double, offsetZ: Double, speed: Double, count: Int, color: Color? = null)
10 |
11 | }
--------------------------------------------------------------------------------
/version_new/build.gradle:
--------------------------------------------------------------------------------
1 | group 'me.clip'
2 | version '2.0'
3 |
4 | dependencies {
5 | implementation project(":version")
6 | compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT")
7 | }
--------------------------------------------------------------------------------
/version_new/src/main/kotlin/me/clip/voteparty/version/VersionHookNew.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.version
2 |
3 | import com.cryptomorin.xseries.particles.XParticle
4 | import org.bukkit.Color
5 | import org.bukkit.Location
6 | import org.bukkit.Particle
7 | import org.bukkit.Particle.DustOptions
8 |
9 | class VersionHookNew : VersionHook
10 | {
11 |
12 | override fun display(type: EffectType, location: Location, offsetX: Double, offsetY: Double, offsetZ: Double, speed: Double, count: Int, color: Color?)
13 | {
14 |
15 | val world = location.world ?: return
16 | val optionalParticle = XParticle.of(type.name)
17 |
18 | if (!optionalParticle.isPresent)
19 | {
20 | return
21 | }
22 |
23 | val particle = optionalParticle.get()
24 |
25 | if (particle.get().dataType == DustOptions::class.java)
26 | {
27 | return world.spawnParticle(particle.get(), location, 1, if (color == null) OPTION else DustOptions(color, 0.8F))
28 | }
29 |
30 | when (particle)
31 | {
32 | in SINGLE ->
33 | {
34 | world.spawnParticle(particle.get(), location, count)
35 | }
36 | in SPELLS ->
37 | {
38 | val r: Double
39 | val g: Double
40 | val b: Double
41 |
42 | if (color == null)
43 | {
44 | r = 0.0
45 | g = 0.0
46 | b = 0.0
47 | }
48 | else
49 | {
50 | r = color.red / 255.0
51 | g = color.green / 255.0
52 | b = color.blue / 255.0
53 | }
54 |
55 | world.spawnParticle(particle.get(), location, count, r, g, b, 1)
56 | }
57 | XParticle.NOTE ->
58 | {
59 | val note = if (color == null)
60 | {
61 | 0.0
62 | }
63 | else
64 | {
65 | color.red / 24.0
66 | }
67 |
68 | world.spawnParticle(particle.get(), location, count, note, offsetY, offsetZ, 1)
69 | }
70 | else ->
71 | {
72 | world.spawnParticle(particle.get(), location, count, offsetX, offsetY, offsetZ, 0.001)
73 | }
74 | }
75 | }
76 |
77 | private companion object
78 | {
79 |
80 | private val OPTION = DustOptions(Color.RED, 0.8F)
81 |
82 | private val SPELLS = setOf(
83 | XParticle.ENTITY_EFFECT,
84 | )
85 |
86 | private val SINGLE = setOf(
87 | XParticle.BUBBLE,
88 | XParticle.FISHING,
89 | XParticle.CRIT,
90 | XParticle.ENCHANTED_HIT,
91 | XParticle.SMOKE,
92 | XParticle.LARGE_SMOKE,
93 | XParticle.PORTAL,
94 | XParticle.ENCHANT,
95 | XParticle.FLAME,
96 | XParticle.CLOUD,
97 | XParticle.DRAGON_BREATH,
98 | XParticle.END_ROD,
99 | XParticle.DAMAGE_INDICATOR,
100 | XParticle.TOTEM_OF_UNDYING,
101 | XParticle.SPIT,
102 | XParticle.SQUID_INK,
103 | XParticle.BUBBLE_POP,
104 | XParticle.BUBBLE_COLUMN_UP,
105 | XParticle.NAUTILUS
106 | )
107 |
108 | }
109 |
110 | }
--------------------------------------------------------------------------------
/version_old/build.gradle:
--------------------------------------------------------------------------------
1 | group 'me.clip'
2 | version '2.0'
3 |
4 |
5 | repositories {
6 | maven {
7 | url = "https://repo.glaremasters.me/repository/public/"
8 | }
9 | maven {
10 | url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/"
11 | }
12 | }
13 |
14 | dependencies {
15 | implementation project(":version")
16 | implementation "org.inventivetalent:particleapi:+"
17 |
18 | compileOnly("org.spigotmc:spigot-api") {
19 | version {
20 | require("1.8.8-R0.1-SNAPSHOT")
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/version_old/src/main/kotlin/me/clip/voteparty/version/VersionHookOld.kt:
--------------------------------------------------------------------------------
1 | package me.clip.voteparty.version
2 |
3 | import org.bukkit.Color
4 | import org.bukkit.Location
5 | import org.inventivetalent.particle.ParticleEffect
6 |
7 | class VersionHookOld : VersionHook
8 | {
9 |
10 | override fun display(type: EffectType, location: Location, offsetX: Double, offsetY: Double, offsetZ: Double, speed: Double, count: Int, color: Color?)
11 | {
12 | val effect = resolve(type) ?: return
13 |
14 | if (color != null && effect.hasFeature(ParticleEffect.Feature.COLOR))
15 | {
16 | effect.sendColor(location.world.players, location, color)
17 | }
18 | else
19 | {
20 | effect.send(location.world.players, location, offsetX, offsetY, offsetZ, speed, count)
21 | }
22 | }
23 |
24 |
25 | private companion object
26 | {
27 | private val VALUES = ParticleEffect.entries.toTypedArray()
28 |
29 |
30 | private fun resolve(type: EffectType): ParticleEffect?
31 | {
32 | return VALUES.find { it.name.equals(type.name, true) }
33 | }
34 |
35 | }
36 |
37 | }
--------------------------------------------------------------------------------