mirror of
https://github.com/CodedRed-Spigot/PlayTimes.git
synced 2026-11-06 09:42:33 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf43f85993 | ||
|
|
f8006c5337 | ||
|
|
52e989b6b0 | ||
|
|
393000c8db | ||
|
|
0bfb51e9a1 | ||
|
|
d8ae3aca1e | ||
|
|
d8245aa23f | ||
|
|
cdead9f0f8 | ||
|
|
ff0670c65c | ||
|
|
deb86b6772 | ||
|
|
7ab32d73ab | ||
|
|
b3dfd53a37 | ||
|
|
ccc7e17383 | ||
|
|
53dbd2d991 | ||
|
|
1407e43c6f | ||
|
|
c45096360e | ||
|
|
9bae99ce8d | ||
|
|
e02e765154 | ||
|
|
a554819066 | ||
|
|
cc3e835b49 | ||
|
|
79a351fbfe | ||
|
|
5133c031d1 | ||
|
|
526feb0aa5 | ||
|
|
82493b27f6 | ||
|
|
c38bafb608 | ||
|
|
bab7c374f1 | ||
|
|
2ef20ea5d1 | ||
|
|
76c15ac56d | ||
|
|
19871bc0db | ||
|
|
e0747b37f7 | ||
|
|
7ac62d1681 | ||
|
|
e257740aaa | ||
|
|
7d0f7c76cd | ||
|
|
0e1f2146d6 | ||
|
|
02d75354df | ||
|
|
36b53c17cd | ||
|
|
534bbba9fc | ||
|
|
52800c3de0 | ||
|
|
4c1219de2b | ||
|
|
88a40062c9 | ||
|
|
931f192f95 | ||
|
|
6bc6e8395a | ||
|
|
4897fe11a8 | ||
|
|
c28ce839ea | ||
|
|
b38b080d4b | ||
|
|
c279d60d88 | ||
|
|
5dc8a9c1a9 | ||
|
|
79c36751ca | ||
|
|
7644a91756 | ||
|
|
7abae06f54 | ||
|
|
f58f182bc4 | ||
|
|
7e7a16bcdf | ||
|
|
963ef56818 | ||
|
|
9075dcd4ad | ||
|
|
8300a4d2e3 | ||
|
|
ab7178c3bb | ||
|
|
52d11b9958 | ||
|
|
dad538a890 | ||
|
|
30b43df049 | ||
|
|
6e0043e197 | ||
|
|
97cba3598a | ||
|
|
32110fc2f2 | ||
|
|
8e5db3928f | ||
|
|
1e7a5ffadb | ||
|
|
62a5966270 | ||
|
|
47666f3a74 | ||
|
|
4ae41d91cb | ||
|
|
ea39b43725 | ||
|
|
7ab49c419d | ||
|
|
ecea1640ab | ||
|
|
cbc8253b4b | ||
|
|
e292e6e1b3 | ||
|
|
afe66090f9 | ||
|
|
fc8e2dc3c6 | ||
|
|
1cbfe86785 | ||
|
|
cbc8b632e0 | ||
|
|
b4b899b031 | ||
|
|
3f2fe03fff | ||
|
|
8630c14648 | ||
|
|
71917d811d | ||
|
|
185510320b | ||
|
|
bf320aca14 | ||
|
|
4497848cc5 | ||
|
|
8ff6cd3a33 | ||
|
|
ab497b8157 | ||
|
|
a13fdba083 | ||
|
|
044c4c8f13 | ||
|
|
2d6501dbfc | ||
|
|
3435ac4fdd | ||
|
|
8d5a815f22 | ||
|
|
93a8dd97cc | ||
|
|
2a497041f8 | ||
|
|
0d5167bf53 | ||
|
|
9dec539ab9 | ||
|
|
106ce705a3 | ||
|
|
961cd9c5a5 | ||
|
|
d739c329ff | ||
|
|
5fcc916cce | ||
|
|
1f21dd5046 | ||
|
|
c2ec5303f2 | ||
|
|
d06ef50677 | ||
|
|
9cef097cf7 | ||
|
|
d79acc4641 | ||
|
|
3ea405947e | ||
|
|
24c4438dcf | ||
|
|
b787f8db6f | ||
|
|
4d92c2c9ad | ||
|
|
155a08207e | ||
|
|
0b9301a400 | ||
|
|
6aa59e4cb7 | ||
|
|
9a8cdda6b8 | ||
|
|
899f04967f | ||
|
|
ad05be5f5c | ||
|
|
252e454224 | ||
|
|
a01b4db91d | ||
|
|
aaca127457 | ||
|
|
cdc53fbe6c | ||
|
|
c628acd809 | ||
|
|
725389ff02 | ||
|
|
c20806f0bc | ||
|
|
60b079e6d0 | ||
|
|
19587e44ff | ||
|
|
02297b8cfa | ||
|
|
834455344b | ||
|
|
22d0c25161 | ||
|
|
9f367a5194 | ||
|
|
5f0bcb5cd1 | ||
|
|
c575ed7f74 | ||
|
|
94afb36d5a | ||
|
|
38001557be | ||
|
|
b2a1cfa247 | ||
|
|
a98e1e2bb0 | ||
|
|
94267e64e1 | ||
|
|
febfc7d378 | ||
|
|
b185d1364a | ||
|
|
4a1d5c7deb | ||
|
|
6a5238d8dd | ||
|
|
ac40ac17dd | ||
|
|
51bfaf656d | ||
|
|
6db539fb88 | ||
|
|
7a8fdbedc4 | ||
|
|
24e35e01e2 | ||
|
|
ee28c37637 | ||
|
|
5bbe1a1018 | ||
|
|
6d5cad3607 | ||
|
|
deb512dfd0 | ||
|
|
550338b799 | ||
|
|
46f5435684 |
No files matched your search
@@ -0,0 +1,52 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Bug Report Template
|
||||
|
||||
Thank you for helping us improve PlayTimes by reporting a bug! Please fill out the form below to help us diagnose and fix the issue.
|
||||
|
||||
---
|
||||
|
||||
## Basic Information
|
||||
|
||||
**Minecraft Version:**
|
||||
- Please run `/version` and provide the output here.
|
||||
|
||||
**PlayTimes Version:**
|
||||
- Please run `/pt version` .
|
||||
- **Screenshot**: Upload a screenshot of the `/pt version` output here.
|
||||
|
||||
---
|
||||
|
||||
## Describe the Bug
|
||||
|
||||
**Description:**
|
||||
- A clear and concise description of what the bug is.
|
||||
|
||||
---
|
||||
|
||||
## Screenshots
|
||||
|
||||
**Screenshots:**
|
||||
- If applicable, add screenshots to help explain your problem.
|
||||
|
||||
---
|
||||
|
||||
## Additional Context
|
||||
|
||||
**Additional Context:**
|
||||
- Add any other context about the problem here.
|
||||
|
||||
---
|
||||
|
||||
For more information and updates, visit [PlayTimes on Spigot](https://www.spigotmc.org/resources/playtimes-track-player-playtime.58858/).
|
||||
|
||||
## Disclaimer
|
||||
|
||||
Please note that responses to bug reports may take up to 72 hours or longer. PlayTimes is a FREE and OPEN-SOURCE plugin, and we greatly appreciate community involvement in its development. As PlayTimes is a side project and hobby for CodedRed, updates may occasionally take longer than anticipated. We sincerely thank you for using PlayTimes and for your understanding and patience.
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[SUGGESTION]"
|
||||
labels: enhancement
|
||||
assignees: CodedRedGIT
|
||||
|
||||
---
|
||||
|
||||
# Suggestion Template
|
||||
|
||||
Thank you for helping us improve PlayTimes by sharing your suggestions! Please fill out the form below to provide us with detailed information about your suggestion.
|
||||
|
||||
---
|
||||
|
||||
## Suggestion
|
||||
|
||||
**Description:**
|
||||
- A clear and concise description of your suggestion.
|
||||
|
||||
**Benefits:**
|
||||
- Describe how this suggestion would improve PlayTimes or enhance the user experience.
|
||||
|
||||
**Implementation:**
|
||||
- If possible, provide any ideas on how this suggestion could be implemented.
|
||||
|
||||
---
|
||||
|
||||
## Additional Context
|
||||
|
||||
**Additional Context:**
|
||||
- Add any other context or information about your suggestion here.
|
||||
|
||||
---
|
||||
|
||||
For more information and updates, visit [PlayTimes on Spigot](https://www.spigotmc.org/resources/playtimes-track-player-playtime.58858/).
|
||||
|
||||
## Disclaimer
|
||||
|
||||
Please note that responses to suggestions may take up to 72 hours or longer. PlayTimes is a FREE and OPEN-SOURCE plugin, and we greatly appreciate community involvement in its development. As PlayTimes is a side project and hobby for CodedRed, implementation of new features may occasionally take longer than anticipated. We sincerely thank you for using PlayTimes and for your understanding and patience.
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Build Minecraft Plugin
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x ./gradlew
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
# User-specific stuff
|
||||
.idea/
|
||||
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# Hide my todo txt file
|
||||
/src/main/resources/todo.txt
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
bin
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
.gradle
|
||||
build/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
**/build/
|
||||
|
||||
# Common working directory
|
||||
run/
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# VS Code directories
|
||||
.vscode/
|
||||
|
||||
# User workspace settings
|
||||
.vscode/settings.json
|
||||
|
||||
# User workspace launch configurations
|
||||
.vscode/launch.json
|
||||
|
||||
# User workspace tasks
|
||||
.vscode/tasks.json
|
||||
|
||||
# Recommended extensions for this workspace
|
||||
.vscode/extensions.json
|
||||
|
||||
# VS Code directories for Java development
|
||||
.vscode-test/
|
||||
|
||||
# VS Code for Java standalone server
|
||||
.vscode-server/
|
||||
|
||||
# Windows image file caches
|
||||
iconcache_*.db
|
||||
|
||||
# Windows Installer directory
|
||||
Installer/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
Generated
-5
@@ -1,5 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# CodeStream ignored files
|
||||
/../../PlayTimes\.idea/codestream.xml
|
||||
Generated
-6
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CodeStream">
|
||||
<option name="webViewContext" value="{"chatProviderAccess":"strict","currentTeamId":"","currentStreamId":"","pullRequestCheckoutBranch":false,"isRepositioning":false,"onboardStep":0,"panelStack":["landing-redirect"],"hasFocus":false,"channelFilter":"all","channelsMuteAll":false,"codemarkFileFilter":"all","codemarkTypeFilter":"all","codemarkTagFilter":"all","codemarkBranchFilter":"all","codemarkAuthorFilter":"all","codemarksFileViewStyle":"inline","codemarksShowArchived":false,"codemarksShowResolved":false,"codemarksWrapComments":false,"showFeedbackSmiley":true,"route":{"name":"newUserEntry","params":{}},"spatialViewShowPRComments":false}" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
-16
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="PlayTimes" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
<bytecodeTargetLevel>
|
||||
<module name="PlayTimes" target="1.8" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
</project>
|
||||
Generated
-6
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
-7
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AccessToNonThreadSafeStaticFieldFromInstance" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="nonThreadSafeClasses">
|
||||
<value />
|
||||
</option>
|
||||
<option name="nonThreadSafeTypes" value="" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ArrayEquality" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="BooleanExpressionMayBeConditional" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="CallToSimpleGetterInClass" enabled="false" level="WEAK WARNING" enabled_by_default="false">
|
||||
<option name="ignoreGetterCallsOnOtherObjects" value="false" />
|
||||
<option name="onlyReportPrivateGetter" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="CallToSimpleSetterInClass" enabled="false" level="WEAK WARNING" enabled_by_default="false">
|
||||
<option name="ignoreSetterCallsOnOtherObjects" value="false" />
|
||||
<option name="onlyReportPrivateSetter" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="CallToStringConcatCanBeReplacedByOperator" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="ClassName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="CodotaLocalLearning" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="ConditionalExpressionWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="ConnectionResource" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="ConstPropertyName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="ConstantConditions" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
|
||||
<option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="DeprecatedIsStillUsed" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="Deprecation" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="EnumEntryName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="FunctionName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="IOResource" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredTypesString" value="java.io.ByteArrayOutputStream,java.io.ByteArrayInputStream,java.io.StringBufferInputStream,java.io.CharArrayWriter,java.io.CharArrayReader,java.io.StringWriter,java.io.StringReader" />
|
||||
<option name="insideTryAllowed" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="IgnoreResultOfCall" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="m_reportAllNonLibraryCalls" value="false" />
|
||||
<option name="callCheckString" value="java.io.File,.*,java.io.InputStream,read|skip|available|markSupported,java.io.Reader,read|skip|ready|markSupported,java.lang.Boolean,.*,java.lang.Byte,.*,java.lang.Character,.*,java.lang.Double,.*,java.lang.Float,.*,java.lang.Integer,.*,java.lang.Long,.*,java.lang.Math,.*,java.lang.Object,equals|hashCode|toString,java.lang.Short,.*,java.lang.StrictMath,.*,java.lang.String,.*,java.lang.Thread,interrupted,java.math.BigInteger,.*,java.math.BigDecimal,.*,java.net.InetAddress,.*,java.net.URI,.*,java.util.Arrays,.*,java.util.List,of,java.util.Set,of,java.util.Map,of|ofEntries|entry,java.util.Collections,(?!addAll).*,java.util.UUID,.*,java.util.regex.Matcher,pattern|toMatchResult|start|end|group|groupCount|matches|find|lookingAt|quoteReplacement|replaceAll|replaceFirst|regionStart|regionEnd|hasTransparentBounds|hasAnchoringBounds|hitEnd|requireEnd,java.util.regex.Pattern,.*,java.util.stream.BaseStream,.*" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="KeySetIterationMayUseEntrySet" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="LengthOneStringInIndexOf" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="LocalVariableName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="MapReplaceableByEnumMap" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="MultiplyOrDivideByPowerOfTwo" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="checkDivision" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="NegatedConditionalExpression" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="NotNullFieldNotInitialized" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="NullableProblems" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="REPORT_NULLABLE_METHOD_OVERRIDES_NOTNULL" value="true" />
|
||||
<option name="REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL" value="true" />
|
||||
<option name="REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE" value="true" />
|
||||
<option name="REPORT_NOT_ANNOTATED_PARAMETER_OVERRIDES_NOTNULL" value="true" />
|
||||
<option name="REPORT_NOT_ANNOTATED_GETTER" value="true" />
|
||||
<option name="REPORT_NOT_ANNOTATED_SETTER_PARAMETER" value="true" />
|
||||
<option name="REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS" value="true" />
|
||||
<option name="REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ObjectAllocationInLoop" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="ObjectPropertyName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PackageName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PointlessIndexOfComparison" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PrivatePropertyName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PropertyName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RandomDoubleForRandomInteger" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RecordStoreResource" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="RedundantInnerClassModifier" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SetReplaceableByEnumSet" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SimplifiableAnnotation" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SimplifiableEqualsExpression" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SizeReplaceableByIsEmpty" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SleepWhileHoldingLock" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SocketResource" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="insideTryAllowed" value="false" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="StringBufferToStringInConcatenation" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="StringEqualsEmptyString" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="StringReplaceableByStringBuffer" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="onlyWarnOnLoop" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="TestFunctionName" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="ThreadStopSuspendResume" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="TodoComment" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnnecessaryConstantArrayCreationExpression" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnnecessaryConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnnecessaryFinalOnLocalVariableOrParameter" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnnecessarySuperConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnnecessarySuperQualifier" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnnecessaryThis" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="UnqualifiedInnerClassAccess" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoreReferencesToLocalInnerClasses" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="UnsecureRandomNumberGeneration" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="ZeroLengthArrayInitialization" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
Generated
-30
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="spigot-repo" />
|
||||
<option name="name" value="spigot-repo" />
|
||||
<option name="url" value="https://hub.spigotmc.org/nexus/content/repositories/snapshots/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="placeholderapi" />
|
||||
<option name="name" value="placeholderapi" />
|
||||
<option name="url" value="https://repo.extendedclip.com/content/repositories/placeholderapi/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: com.google.code.gson:gson:2.8.7">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.8.7/gson-2.8.7.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.8.7/gson-2.8.7-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.8.7/gson-2.8.7-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: com.google.guava:guava:21.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/21.0/guava-21.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/21.0/guava-21.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/21.0/guava-21.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: commons-lang:commons-lang:2.6">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-lang/commons-lang/2.6/commons-lang-2.6.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-lang/commons-lang/2.6/commons-lang-2.6-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/commons-lang/commons-lang/2.6/commons-lang-2.6-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: me.clip:placeholderapi:2.10.9">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/me/clip/placeholderapi/2.10.9/placeholderapi-2.10.9.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/me/clip/placeholderapi/2.10.9/placeholderapi-2.10.9-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/me/clip/placeholderapi/2.10.9/placeholderapi-2.10.9-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: net.md-5:bungeecord-chat:1.16-R0.4">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/md-5/bungeecord-chat/1.16-R0.4/bungeecord-chat-1.16-R0.4.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/md-5/bungeecord-chat/1.16-R0.4/bungeecord-chat-1.16-R0.4-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/md-5/bungeecord-chat/1.16-R0.4/bungeecord-chat-1.16-R0.4-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: org.jetbrains:annotations:19.0.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/19.0.0/annotations-19.0.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/19.0.0/annotations-19.0.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/19.0.0/annotations-19.0.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.17-R0.1-SNAPSHOT/spigot-api-1.17-R0.1-20210616.003322-46.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.17-R0.1-SNAPSHOT/spigot-api-1.17-R0.1-20210616.003322-46-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/spigotmc/spigot-api/1.17-R0.1-SNAPSHOT/spigot-api-1.17-R0.1-20210616.003322-46-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Maven: org.yaml:snakeyaml:1.28">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/yaml/snakeyaml/1.28/snakeyaml-1.28.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/yaml/snakeyaml/1.28/snakeyaml-1.28-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/yaml/snakeyaml/1.28/snakeyaml-1.28-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
Generated
-18
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
-8
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/PlayTimes.iml" filepath="$PROJECT_DIR$/PlayTimes.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
-124
@@ -1,124 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
Generated
-6
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
PlayTimes Copyright (C) 2021 CodedRed
|
||||
PlayTimes Copyright (C) 2023 CodedRed
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="minecraft" name="Minecraft">
|
||||
<configuration>
|
||||
<autoDetectTypes>
|
||||
<platformType>SPIGOT</platformType>
|
||||
</autoDetectTypes>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: com.google.guava:guava:21.0" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: net.md-5:bungeecord-chat:1.16-R0.4" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.yaml:snakeyaml:1.28" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: me.clip:placeholderapi:2.10.9" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.jetbrains:annotations:19.0.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.8" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,97 +1,46 @@
|
||||
# PlayTimes
|
||||
> The best /playtime plugin! PAPI support, offline checks, API & more!
|
||||
|
||||
[![Downloads][downloads-shield]][downloads-url]
|
||||
[![Bstatsp][bstatsp-shield]][bstatsp-url]
|
||||
[![Bstatss][bstatss-shield]][bstatss-url]
|
||||
[![Bstats Players][bstatsp-shield]][bstatsp-url]
|
||||
[![Bstats Servers][bstatss-shield]][bstatss-url]
|
||||
[![Issues][issues-shield]][issues-url]
|
||||
[![GNU License][license-shield]][license-url]
|
||||
|
||||
|
||||
|
||||
<!-- PROJECT LOGO -->
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://github.com/CodedRed-Spigot/PlayTimes">
|
||||
<img src="logo.png" alt="Logo" width="750" height="500">
|
||||
<img src="logo.png" alt="PlayTimes logo" width="750" height="500">
|
||||
</a>
|
||||
|
||||
<h3 align="center">PlayTimes</h3>
|
||||
|
||||
<p align="center">
|
||||
The best /playtime plugin! PAPI support, offline checks, API & more!
|
||||
<br />
|
||||
<a href="https://github.com/CodedRed-Spigot/PlayTimes/wiki"><strong>Explore the docs »</strong></a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://www.spigotmc.org/resources/playtimes-check-players-playtime-server-uptime.58858/">View Demo</a>
|
||||
·
|
||||
<a href="https://github.com/CodedRed-Spigot/PlayTimes/issues">Report Bug</a>
|
||||
·
|
||||
<a href="https://github.com/CodedRed-Spigot/PlayTimes/issues">Request Feature</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
## Table of Contents
|
||||
- [About The Project](#about-the-project)
|
||||
- [Usage](#usage)
|
||||
- [Roadmap](#roadmap)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
- [Contact](#contact)
|
||||
|
||||
|
||||
<!-- TABLE OF CONTENTS -->
|
||||
<details open="open">
|
||||
<summary><h2 style="display: inline-block">Table of Contents</h2></summary>
|
||||
<ol>
|
||||
<li>
|
||||
<a href="#about-the-project">About The Project</a>
|
||||
</li>
|
||||
<!-- <li>
|
||||
<a href="#getting-started">Getting Started</a>
|
||||
<ul>
|
||||
<li><a href="#prerequisites">Prerequisites</a></li>
|
||||
<li><a href="#installation">Installation</a></li>
|
||||
</ul>
|
||||
</li> -->
|
||||
<li><a href="#usage">Usage</a></li>
|
||||
<li><a href="#roadmap">Roadmap</a></li>
|
||||
<li><a href="#contributing">Contributing</a></li>
|
||||
<li><a href="#license">License</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
</ol>
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
<!-- ABOUT THE PROJECT -->
|
||||
## About The Project
|
||||
|
||||
PlayTimes is the perfect plugin for your server! Have players show off and compete for more time played with playtime's leaderboards! Not only can you check online/offline players playtime you can also check the uptime of the server! There is a lot coming to playtime such as PlayTime Rewards, PlayTime Ranks & PlayTime Shop!
|
||||
Introducing PlayTimes, the ultimate plugin for your server! Elevate the gaming experience by allowing players to showcase their skills and compete for top positions on the prestigious playtime leaderboards. Not only can you effortlessly monitor the playtime of online and offline players, but you can also keep track of the server's uptime for maximum efficiency. But that's not all! Brace yourself for an array of exciting features that are on the horizon, including PlayTime Rewards, PlayTime Ranks, and the immersive PlayTime Shop. Get ready to take your server to the next level with PlayTimes!
|
||||
|
||||
<!-- GETTING STARTED
|
||||
## Getting Started -->
|
||||
<img src="https://imgur.com/KebViUJ.gif"> <img src="https://imgur.com/v6ErIo9.gif">
|
||||
|
||||
<!-- To get a local copy up and running follow these simple steps. -->
|
||||
<img src="https://imgur.com/VGZ0iuV.gif"> <img src="https://imgur.com/f4A5LRY.gif">
|
||||
|
||||
<img src="https://imgur.com/kOy8YSx.gif"> <img src="https://imgur.com/gNYsU00.gif">
|
||||
|
||||
|
||||
|
||||
<!-- USAGE EXAMPLES -->
|
||||
## Usage
|
||||
|
||||
Check out the Wiki!
|
||||
[Documentation](https://github.com/CodedRed-Spigot/PlayTimes/wiki)
|
||||
For detailed instructions and examples on how to use the plugin, refer to our comprehensive [Documentation](https://github.com/CodedRed-Spigot/PlayTimes/wiki).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ROADMAP -->
|
||||
## Roadmap
|
||||
|
||||
See the [open issues](https://github.com/CodedRed-Spigot/PlayTimes/issues) for a list of proposed features (and known issues).
|
||||
Check out the [open issues](https://github.com/CodedRed-Spigot/PlayTimes/issues) for a list of proposed features and known bugs.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- CONTRIBUTING -->
|
||||
## Contributing
|
||||
|
||||
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
|
||||
Contributions are the lifeblood of the open source community. We appreciate and welcome any contributions you can make. Here's how you can contribute:
|
||||
|
||||
1. Fork the Project
|
||||
2. Create your Feature Branch (`git checkout -b feature/AwesomeFeature`)
|
||||
@@ -99,47 +48,28 @@ Contributions are what make the open source community such an amazing place to b
|
||||
4. Push to the Branch (`git push origin feature/AwesomeFeature`)
|
||||
5. Open a Pull Request
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- LICENSE -->
|
||||
## License
|
||||
|
||||
Distributed under the GNU General Public License v3.0. See `LICENSE` for more information.
|
||||
PlayTimes is distributed under the GNU General Public License v3.0. See `LICENSE` for more information.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- CONTACT -->
|
||||
## Contact
|
||||
|
||||
CodedRed - [@twitter](https://twitter.com/devcodedred) - devcodedred@gmail.com
|
||||
|
||||
[@spigotmc](https://www.spigotmc.org/resources/authors/codedred.421005/)
|
||||
Discord: CodedRed#0900
|
||||
|
||||
Project Link: [https://github.com/CodedRed-Spigot/PlayTimes](https://github.com/CodedRed-Spigot/PlayTimes)
|
||||
|
||||
|
||||
You can reach out to us using the following platforms:
|
||||
|
||||
- Twitter: [@twitter](https://twitter.com/devcodedred)
|
||||
- Email: devcodedred@gmail.com
|
||||
- SpigotMC: [@spigotmc](https://www.spigotmc.org/resources/authors/codedred.421005/)
|
||||
- Discord: .CodedRed
|
||||
|
||||
Find the project on GitHub: [https://github.com/CodedRed-Spigot/PlayTimes](https://github.com/CodedRed-Spigot/PlayTimes)
|
||||
|
||||
<!-- MARKDOWN LINKS & IMAGES -->
|
||||
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
|
||||
[contributors-shield]: https://img.shields.io/github/contributors/CodedRed-Spigot/PlayTimes.svg?style=for-the-badge
|
||||
[contributors-url]: https://github.com/CodedRed-Spigot/PlayTimes/graphs/contributors
|
||||
[downloads-shield]: https://img.shields.io/spiget/downloads/58858?style=for-the-badge
|
||||
[downloads-url]: https://www.spigotmc.org/resources/playtimes-check-players-playtime-server-uptime.58858/
|
||||
[bstatsp-shield]: https://img.shields.io/bstats/players/5289?style=for-the-badge
|
||||
[bstatsp-url]: https://bstats.org/plugin/bukkit/PlayTimes/5289
|
||||
[bstatss-shield]: https://img.shields.io/bstats/servers/5289?color=orange&style=for-the-badge
|
||||
[bstatss-url]: https://bstats.org/plugin/bukkit/PlayTimes/5289
|
||||
[stars-shield]: https://img.shields.io/github/stars/CodedRed-Spigot/PlayTimes.svg?style=for-the-badge
|
||||
[stars-url]: https://github.com/CodedRed-Spigot/PlayTimes/stargazers
|
||||
[downloads-shield]: https://img.shields.io/spiget/downloads/58858?style=for-the-badge
|
||||
[downloads-url]: https://www.spigotmc.org/resources/playtimes-check-players-playtime-server-uptime.58858/
|
||||
[issues-shield]: https://img.shields.io/github/issues/CodedRed-Spigot/PlayTimes.svg?style=for-the-badge
|
||||
[issues-url]: https://github.com/CodedRed-Spigot/PlayTimes/issues
|
||||
[license-shield]: https://img.shields.io/github/license/CodedRed-Spigot/PlayTimes.svg?style=for-the-badge
|
||||
[license-url]: https://github.com/CodedRed-Spigot/PlayTimes/blob/main/LICENSE
|
||||
[site-url]: https://www.spigotmc.org/resources/playtimes-check-players-playtime-server-uptime.58858/
|
||||
[license-shield]: https://img.shields.io/github/license/CodedRed-Spigot/PlayTimes.svg?
|
||||
@@ -0,0 +1,46 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
group = 'dev.codedred'
|
||||
version = '1.6.2b'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
maven { name = 'spigotmc-repo'; url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
|
||||
maven { name = 'sonatype'; url = 'https://oss.sonatype.org/content/groups/public/' }
|
||||
maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.jetbrains:annotations:23.0.0'
|
||||
compileOnly 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
|
||||
compileOnly 'me.clip:placeholderapi:2.10.9'
|
||||
compileOnly 'org.projectlombok:lombok:1.18.28'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.28'
|
||||
}
|
||||
|
||||
def targetJavaVersion = 8
|
||||
java {
|
||||
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
|
||||
sourceCompatibility = javaVersion
|
||||
targetCompatibility = javaVersion
|
||||
if (JavaVersion.current() < javaVersion) {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8'
|
||||
options.release = targetJavaVersion
|
||||
}
|
||||
|
||||
processResources {
|
||||
def props = [version: version]
|
||||
inputs.properties props
|
||||
filteringCharset 'UTF-8'
|
||||
filesMatching('plugin.yml') {
|
||||
expand props
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
Vendored
BIN
Binary file not shown.
+5
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,234 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
+89
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,88 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>groupId</groupId>
|
||||
<artifactId>PlayTimes</artifactId>
|
||||
<version>1.4.5</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<outputFile>C:\Users\chris\OneDrive\Desktop\Spigot\Servers\Spigot 1.17\plugins\PlayTimes.jar</outputFile>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<!-- This adds the Spigot Maven repository to the build -->
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>placeholderapi</id>
|
||||
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!--This adds the Spigot API artifact to the build -->
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.17-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
<version>2.10.9</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
NEW_VERSION="1.6.2b"
|
||||
|
||||
git checkout main
|
||||
git pull origin main
|
||||
|
||||
git tag -a $NEW_VERSION -m "Release version $NEW_VERSION"
|
||||
|
||||
git push origin $NEW_VERSION
|
||||
|
||||
git checkout production
|
||||
git pull origin production
|
||||
|
||||
git merge main -m "Release $NEW_VERSION"
|
||||
|
||||
git push origin production
|
||||
|
||||
echo "Release $NEW_VERSION completed and merged into production."
|
||||
read -p "Press any key to continue... "
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
rootProject.name = 'PlayTimes'
|
||||
@@ -1,6 +1,10 @@
|
||||
package me.codedred.playtimes;
|
||||
|
||||
import java.util.*;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
@@ -10,176 +14,257 @@ import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This class will automatically register as a placeholder expansion
|
||||
* when a jar including this class is added to the directory
|
||||
* {@code /plugins/PlaceholderAPI/expansions} on your server.
|
||||
* <br>
|
||||
* <br>If you create such a class inside your own plugin, you have to
|
||||
* register it manually in your plugins {@code onEnable()} by using
|
||||
* {@code new YourExpansionClass().register();}
|
||||
*/
|
||||
public class Expansions extends PlaceholderExpansion {
|
||||
|
||||
/**
|
||||
* This method should always return true unless we
|
||||
* have a dependency we need to make sure is on the server
|
||||
* for our placeholders to work!
|
||||
*
|
||||
* @return always true since we do not have any dependencies.
|
||||
*/
|
||||
@Override
|
||||
public boolean canRegister(){
|
||||
return true;
|
||||
@Override
|
||||
public boolean canRegister() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return "CodedRed";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return "PlayTimes";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return "1.6.1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
|
||||
identifier = identifier.toLowerCase();
|
||||
switch (identifier) {
|
||||
case "playtime":
|
||||
return getPlayerPlayTime(player);
|
||||
case "uptime":
|
||||
return StatManager.getInstance().getUptime();
|
||||
case "joindate":
|
||||
return StatManager.getInstance().getJoinDate(player.getUniqueId());
|
||||
case "timesjoined":
|
||||
return Long.toString(
|
||||
StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(player.getUniqueId(), StatisticType.TIMES_JOINED)
|
||||
);
|
||||
case "rawtime":
|
||||
return getRawtime(player);
|
||||
case "afktime":
|
||||
return getAfktime(player);
|
||||
case "global_playtime":
|
||||
return getGlobalPlaytime(player);
|
||||
case "global_rawtime":
|
||||
return getGlobalRawtime(player);
|
||||
case "global_afktime":
|
||||
return getGlobalAfktime(player);
|
||||
default:
|
||||
if (identifier.startsWith("rawtime_")) {
|
||||
return getServerSpecificRawtime(player, identifier.substring(8));
|
||||
}
|
||||
if (identifier.startsWith("playtime_")) {
|
||||
return getServerSpecificPlaytime(player, identifier.substring(9));
|
||||
}
|
||||
if (identifier.startsWith("afktime_")) {
|
||||
return getServerSpecificAfktime(player, identifier.substring(8));
|
||||
}
|
||||
return handleLeaderboardIdentifier(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
private String getServerSpecificRawtime(
|
||||
OfflinePlayer player,
|
||||
String serverId
|
||||
) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
if (dbManager.hasTimeForServer(player.getUniqueId(), serverId)) {
|
||||
Long rawtime = dbManager
|
||||
.getTimeForServer(player.getUniqueId(), serverId)
|
||||
.get("playtime");
|
||||
return timeManager.buildFormat(rawtime != null ? rawtime : 0);
|
||||
}
|
||||
return timeManager.buildFormat(0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getServerSpecificPlaytime(
|
||||
OfflinePlayer player,
|
||||
String serverId
|
||||
) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
if (dbManager.hasTimeForServer(player.getUniqueId(), serverId)) {
|
||||
Map<String, Long> timeForServer = dbManager.getTimeForServer(
|
||||
player.getUniqueId(),
|
||||
serverId
|
||||
);
|
||||
Long playtime =
|
||||
timeForServer.get("playtime") -
|
||||
timeForServer.getOrDefault("afktime", 0L);
|
||||
return timeManager.buildFormat(playtime != null ? playtime : 0);
|
||||
}
|
||||
return timeManager.buildFormat(0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getServerSpecificAfktime(
|
||||
OfflinePlayer player,
|
||||
String serverId
|
||||
) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
if (dbManager.hasTimeForServer(player.getUniqueId(), serverId)) {
|
||||
Long afktime = dbManager
|
||||
.getTimeForServer(player.getUniqueId(), serverId)
|
||||
.get("afktime");
|
||||
return timeManager.buildFormat(afktime != null ? afktime : 0);
|
||||
}
|
||||
return timeManager.buildFormat(0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getGlobalPlaytime(OfflinePlayer player) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long globalPlaytime = DatabaseManager
|
||||
.getInstance()
|
||||
.getTotalPlaytime(player.getUniqueId());
|
||||
return timeManager.buildFormat(
|
||||
globalPlaytime != null ? globalPlaytime : 0
|
||||
);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getGlobalRawtime(OfflinePlayer player) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long globalRawtime = DatabaseManager
|
||||
.getInstance()
|
||||
.getTotalRawtime(player.getUniqueId());
|
||||
return timeManager.buildFormat(globalRawtime != null ? globalRawtime : 0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getGlobalAfktime(OfflinePlayer player) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long globalAfktime = DatabaseManager
|
||||
.getInstance()
|
||||
.getTotalAfktime(player.getUniqueId());
|
||||
return timeManager.buildFormat(globalAfktime != null ? globalAfktime : 0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getPlayerPlayTime(OfflinePlayer player) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
long afkTime = AFKManager.getInstance().getAFKTime(player.getUniqueId());
|
||||
return timeManager.buildFormat(
|
||||
stats.getPlayerStat(player.getUniqueId(), StatisticType.PLAYTIME) /
|
||||
20 -
|
||||
afkTime
|
||||
);
|
||||
}
|
||||
|
||||
private String getRawtime(OfflinePlayer player) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
return timeManager.buildFormat(
|
||||
stats.getPlayerStat(player.getUniqueId(), StatisticType.PLAYTIME) / 20
|
||||
);
|
||||
}
|
||||
|
||||
private String getAfktime(OfflinePlayer player) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
long afkTime = AFKManager.getInstance().getAFKTime(player.getUniqueId());
|
||||
return timeManager.buildFormat(afkTime);
|
||||
}
|
||||
|
||||
private String handleLeaderboardIdentifier(String identifier) {
|
||||
if (identifier.contains("topname")) {
|
||||
return getLeaderboardPlayerName(identifier);
|
||||
} else if (identifier.contains("toptime")) {
|
||||
return getLeaderboardPlayTime(identifier);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getLeaderboardPlayerName(String identifier) {
|
||||
Leaderboard board = new Leaderboard();
|
||||
int val = parseLeaderboardPosition(identifier);
|
||||
if (val == -1) {
|
||||
return ChatColor.RED + "Invalid leaderboard position!";
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the person who created this expansion should go here.
|
||||
*
|
||||
* @return The name of the author as a String.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull String getAuthor(){
|
||||
return "Cmaaxx"; // CodedRed
|
||||
List<UUID> players = getTopPlayersUUID(board);
|
||||
if (players.size() < val + 1) return "N/A";
|
||||
|
||||
OfflinePlayer targetPlayer = Bukkit.getOfflinePlayer(players.get(val));
|
||||
return targetPlayer.getName();
|
||||
}
|
||||
|
||||
private String getLeaderboardPlayTime(String identifier) {
|
||||
Leaderboard board = new Leaderboard();
|
||||
int val = parseLeaderboardPosition(identifier);
|
||||
if (val == -1) {
|
||||
return ChatColor.RED + "Invalid leaderboard position!";
|
||||
}
|
||||
|
||||
/**
|
||||
* The placeholder identifier should go here.
|
||||
* <br>This is what tells PlaceholderAPI to call our onRequest
|
||||
* method to obtain a value if a placeholder starts with our
|
||||
* identifier.
|
||||
* <br>This must be unique and can not contain % or _
|
||||
*
|
||||
* @return The identifier in {@code %<identifier>_<value>%} as String.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull String getIdentifier(){
|
||||
return "PlayTimes";
|
||||
List<Integer> players = getTopPlayersPlayTime(board);
|
||||
if (players.size() < val + 1) return "N/A";
|
||||
|
||||
return TimeManager.getInstance().buildFormat(players.get(val) / 20);
|
||||
}
|
||||
|
||||
private List<UUID> getTopPlayersUUID(Leaderboard board) {
|
||||
List<UUID> players = new ArrayList<>();
|
||||
for (Map.Entry<String, Integer> entry : board
|
||||
.getTopTen()
|
||||
.entrySet()) players.add(UUID.fromString(entry.getKey()));
|
||||
return players;
|
||||
}
|
||||
|
||||
private List<Integer> getTopPlayersPlayTime(Leaderboard board) {
|
||||
List<Integer> players = new ArrayList<>();
|
||||
for (Map.Entry<String, Integer> entry : board
|
||||
.getTopTen()
|
||||
.entrySet()) players.add(entry.getValue());
|
||||
return players;
|
||||
}
|
||||
|
||||
private int parseLeaderboardPosition(String identifier) {
|
||||
String num = identifier.substring(7);
|
||||
if (isInteger(num)) {
|
||||
return (Integer.parseInt(num) < 1) ? 0 : Integer.parseInt(num) - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the version of this expansion.
|
||||
* <br>You don't have to use numbers, since it is set as a String.
|
||||
*
|
||||
* @return The version as a String.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull String getVersion(){
|
||||
return "1.4.6";
|
||||
private boolean isInteger(String str) {
|
||||
try {
|
||||
Integer.parseInt(str);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist(){
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* This is the method called when a placeholder with our identifier
|
||||
* is found and needs a value.
|
||||
* <br>We specify the value identifier in this method.
|
||||
* <br>Since version 2.9.1 can you use OfflinePlayers in your requests.
|
||||
*
|
||||
* @param player
|
||||
* A {@link OfflinePlayer OfflinePlayer}.
|
||||
* @param identifier
|
||||
* A String containing the identifier/value.
|
||||
*
|
||||
* @return Possibly-null String of the requested identifier.
|
||||
*/
|
||||
@Override
|
||||
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
|
||||
identifier = identifier.toLowerCase();
|
||||
StatManager stats = StatManager.getInstance();
|
||||
TimeManager timings = TimeManager.getInstance();
|
||||
switch (identifier) {
|
||||
case "playtime":
|
||||
return timings.buildFormat(stats.getPlayerStat(player.getUniqueId(), StatisticType.PLAYTIME)/20);
|
||||
case "uptime":
|
||||
return stats.getUptime();
|
||||
case "joindate":
|
||||
return stats.getJoinDate(player.getUniqueId());
|
||||
}
|
||||
|
||||
// %PlayTimes_topname#%
|
||||
if (identifier.contains("topname")) {
|
||||
Leaderboard board = new Leaderboard();
|
||||
List<UUID> players = new ArrayList<>();
|
||||
for (Map.Entry<String, Integer> entry : board.getTopTen().entrySet())
|
||||
players.add(UUID.fromString(entry.getKey()));
|
||||
String num = identifier.substring(7);
|
||||
int val;
|
||||
|
||||
if (isInteger(num))
|
||||
val = (Integer.parseInt(num) < 1) ? 0 : Integer.parseInt(num) - 1;
|
||||
else
|
||||
return ChatColor.RED + "Invalid leaderboard position!";
|
||||
|
||||
if (players.size() < val + 1)
|
||||
return "N/A";
|
||||
|
||||
OfflinePlayer targetPlayer = Bukkit.getOfflinePlayer(players.get(val));
|
||||
String name = targetPlayer.getName();
|
||||
|
||||
|
||||
return (players.isEmpty() ? "N/A" : name);
|
||||
}
|
||||
|
||||
// %PlayTimes_toptime#%
|
||||
else if (identifier.contains("toptime")) {
|
||||
Leaderboard board = new Leaderboard();
|
||||
List<Integer> players = new ArrayList<>();
|
||||
for (Map.Entry<String, Integer> entry : board.getTopTen().entrySet())
|
||||
players.add(entry.getValue());
|
||||
|
||||
String num = identifier.substring(7);
|
||||
int val;
|
||||
if (isInteger(num))
|
||||
val = (Integer.parseInt(num) < 1) ? 0 : Integer.parseInt(num) - 1;
|
||||
else
|
||||
return ChatColor.RED + "Invalid leaderboard position!";
|
||||
if (players.size() < val + 1)
|
||||
return "N/A";
|
||||
|
||||
return (players.isEmpty() ? "N/A" : timings.buildFormat(players.get(val)/20));
|
||||
}
|
||||
|
||||
|
||||
// We return null if an invalid placeholder (f.e. %example_placeholder3%)
|
||||
// was provided
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isInteger(String str) {
|
||||
try {
|
||||
Integer.parseInt(str);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,83 +1,170 @@
|
||||
package me.codedred.playtimes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.afk.listeners.onChat;
|
||||
import me.codedred.playtimes.afk.listeners.onInteract;
|
||||
import me.codedred.playtimes.afk.listeners.onJoinQuit;
|
||||
import me.codedred.playtimes.afk.listeners.onMove;
|
||||
import me.codedred.playtimes.commands.Time;
|
||||
import me.codedred.playtimes.commands.TopTime;
|
||||
import me.codedred.playtimes.commands.Uptime;
|
||||
import me.codedred.playtimes.data.Debugger;
|
||||
import me.codedred.playtimes.commands.completer.TimeTabCompleter;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.listeners.Join;
|
||||
import me.codedred.playtimes.listeners.Quit;
|
||||
import me.codedred.playtimes.server.ServerManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class PlayTimes extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Debugger debug = new Debugger();
|
||||
debug.execute();
|
||||
|
||||
checkForUpdate();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
checkForUpdate();
|
||||
|
||||
ServerManager.getInstance().register();
|
||||
StatManager.getInstance().registerStatistics();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
Expansions exp = new Expansions();
|
||||
exp.register();
|
||||
getServer().getConsoleSender().sendMessage(ChatColor.DARK_PURPLE + "[PlayTimes] " + ChatColor.WHITE + "PlaceholdersAPI Hooked!");
|
||||
}
|
||||
ServerManager.getInstance().register();
|
||||
StatManager.getInstance().registerStatistics();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
|
||||
registerEvents();
|
||||
registerCommands();
|
||||
loadDatabase();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Metrics metrics = new Metrics(this);
|
||||
getServer().getConsoleSender().sendMessage(ChatColor.DARK_PURPLE + "[PlayTimes] " + ChatColor.WHITE + "Successfully loaded.");
|
||||
}
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
Expansions exp = new Expansions();
|
||||
exp.register();
|
||||
getLogger().info("PlaceholdersAPI Hooked!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
registerEvents();
|
||||
registerCommands();
|
||||
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
Metrics metrics = new Metrics(this, 5289);
|
||||
|
||||
private void registerEvents() {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new Join(), this);
|
||||
pm.registerEvents(new Quit(), this);
|
||||
}
|
||||
AFKManager.getInstance().startAFKChecker();
|
||||
getLogger().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
getCommand("playtime").setExecutor(
|
||||
new Time());
|
||||
getCommand("uptime").setExecutor(
|
||||
new Uptime());
|
||||
getCommand("topplaytime").setExecutor(
|
||||
new TopTime());
|
||||
}
|
||||
@Override
|
||||
public void onDisable() {
|
||||
AFKManager.getInstance().endAFKChecker();
|
||||
getLogger().info("PlayTimes shutting down");
|
||||
}
|
||||
|
||||
private void checkForUpdate() {
|
||||
UpdateChecker updater = new UpdateChecker(this, 58858);
|
||||
try {
|
||||
if (updater.checkForUpdates()) {
|
||||
getServer().getConsoleSender().sendMessage(ChatUtil.format("&eYou are using an older version of PlayTimes!"));
|
||||
getServer().getConsoleSender().sendMessage(ChatUtil.format("&eDownload the newest version here:"));
|
||||
getServer().getConsoleSender().sendMessage(ChatUtil.format("&bhttps://www.spigotmc.org/resources/58858/"));
|
||||
} else {
|
||||
getServer().getConsoleSender().sendMessage("[PlayTimes] Plugin is up to date! - "
|
||||
+ getDescription().getVersion());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getServer().getConsoleSender().sendMessage("[PlayTimes] Could not check for updates!");
|
||||
private void registerEvents() {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
pm.registerEvents(new Join(), this);
|
||||
pm.registerEvents(new Quit(), this);
|
||||
|
||||
if (data.hasAfkEnabled()) {
|
||||
pm.registerEvents(new onJoinQuit(), this);
|
||||
|
||||
FileConfiguration config = data.getConfig();
|
||||
boolean cancelAfkOnMove = config.getBoolean(
|
||||
"afk-settings.cancel-afk.on-player-move"
|
||||
);
|
||||
boolean cancelAfkOnChat = config.getBoolean(
|
||||
"afk-settings.cancel-afk.on-player-chat"
|
||||
);
|
||||
boolean cancelAfkOnInteract = config.getBoolean(
|
||||
"afk-settings.cancel-afk.on-player-interact"
|
||||
);
|
||||
|
||||
if (cancelAfkOnMove || cancelAfkOnChat || cancelAfkOnInteract) {
|
||||
if (cancelAfkOnMove) pm.registerEvents(new onMove(), this);
|
||||
if (cancelAfkOnChat) pm.registerEvents(new onChat(), this);
|
||||
if (cancelAfkOnInteract) pm.registerEvents(new onInteract(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
Objects.requireNonNull(getCommand("playtime")).setExecutor(new Time());
|
||||
Objects.requireNonNull(getCommand("uptime")).setExecutor(new Uptime());
|
||||
Objects
|
||||
.requireNonNull(getCommand("topplaytime"))
|
||||
.setExecutor(new TopTime());
|
||||
Objects
|
||||
.requireNonNull(this.getCommand("pt"))
|
||||
.setTabCompleter(new TimeTabCompleter());
|
||||
}
|
||||
|
||||
public void loadDatabase() {
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
getLogger().info("Connecting to Database...");
|
||||
DatabaseManager databaseManager = DatabaseManager.getInstance();
|
||||
|
||||
try {
|
||||
if (databaseManager.getDataSource().getConnection() != null) {
|
||||
try {
|
||||
databaseManager.getDataSource().closeConnection();
|
||||
} catch (Exception e) {
|
||||
getLogger()
|
||||
.warning("Error while trying to close Database connection..");
|
||||
}
|
||||
databaseManager.load();
|
||||
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("purge-database.enabled")
|
||||
) databaseManager.purgeOldPlaytimeData();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
getLogger().severe("Error loading the database: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForUpdate() {
|
||||
Bukkit
|
||||
.getScheduler()
|
||||
.runTaskAsynchronously(
|
||||
this,
|
||||
() -> {
|
||||
UpdateChecker updater = new UpdateChecker(this, 58858);
|
||||
try {
|
||||
if (updater.hasUpdatesAvailable()) {
|
||||
getLogger()
|
||||
.warning(
|
||||
ChatUtil.format(
|
||||
"You are using an older version of PlayTimes!"
|
||||
)
|
||||
);
|
||||
getLogger()
|
||||
.info(ChatUtil.format("Download the newest version here:"));
|
||||
getLogger()
|
||||
.info(
|
||||
ChatUtil.format("https://www.spigotmc.org/resources/58858/")
|
||||
);
|
||||
} else {
|
||||
getLogger()
|
||||
.info(
|
||||
"[PlayTimes] Plugin is up to date! - " +
|
||||
getDescription().getVersion()
|
||||
);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
getLogger().warning("[PlayTimes] Could not check for updates!");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,48 @@
|
||||
package me.codedred.playtimes;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
import java.util.Objects;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class UpdateChecker {
|
||||
|
||||
private URL checkURL;
|
||||
private String newVersion;
|
||||
private final JavaPlugin plugin;
|
||||
private static final String UPDATE_URL =
|
||||
"https://api.spigotmc.org/legacy/update.php?resource=%d";
|
||||
|
||||
public UpdateChecker(JavaPlugin plugin, int projectID) {
|
||||
this.plugin = plugin;
|
||||
newVersion = plugin.getDescription().getVersion();
|
||||
try {
|
||||
checkURL = new URL(
|
||||
"https://api.spigotmc.org/legacy/update.php?resource=" + projectID);
|
||||
} catch (MalformedURLException e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
private final JavaPlugin plugin;
|
||||
private final int projectId;
|
||||
|
||||
public UpdateChecker(JavaPlugin plugin, int projectId) {
|
||||
this.plugin = Objects.requireNonNull(plugin, "Plugin cannot be null.");
|
||||
this.projectId = projectId;
|
||||
}
|
||||
|
||||
public boolean hasUpdatesAvailable() throws IOException {
|
||||
String latestVersion;
|
||||
|
||||
URL url = new URL(String.format(UPDATE_URL, projectId));
|
||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setUseCaches(true);
|
||||
|
||||
try (
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(connection.getInputStream())
|
||||
)
|
||||
) {
|
||||
latestVersion = reader.readLine();
|
||||
}
|
||||
|
||||
/*public int getProjectID() {
|
||||
return project;
|
||||
if (latestVersion == null || latestVersion.isEmpty()) {
|
||||
throw new IOException("Failed to retrieve latest version.");
|
||||
}
|
||||
|
||||
public JavaPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public String getLatestVersion() {
|
||||
return newVersion;
|
||||
}
|
||||
|
||||
public String getResourceURL() {
|
||||
return "https://www.spigotmc.org/resources/" + project;
|
||||
}*/
|
||||
|
||||
public boolean checkForUpdates() throws Exception {
|
||||
URLConnection con = checkURL.openConnection();
|
||||
newVersion = new BufferedReader(new InputStreamReader(con.getInputStream()))
|
||||
.readLine();
|
||||
return !plugin.getDescription().getVersion().equals(newVersion);
|
||||
}
|
||||
return !plugin.getDescription().getVersion().equals(latestVersion);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package me.codedred.playtimes.afk;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
public class AFKManager {
|
||||
|
||||
private static AFKManager instance = null;
|
||||
|
||||
private final HashMap<UUID, Long> lastActive = new HashMap<>();
|
||||
private final HashMap<UUID, Long> afkTime = new HashMap<>();
|
||||
private final FileConfiguration config;
|
||||
private long afkThresholdMillis;
|
||||
|
||||
private boolean notifyOnAfk;
|
||||
private boolean notifyOnBack;
|
||||
|
||||
private String onAfkMessage;
|
||||
private String onBackMessage;
|
||||
|
||||
private BukkitTask afkCheckerTask = null;
|
||||
|
||||
private AFKManager() {
|
||||
config = DataManager.getInstance().getConfig();
|
||||
afkThresholdMillis = config.getLong("afk-settings.threshold") * 60L * 1000L;
|
||||
notifyOnAfk = config.getBoolean("afk-settings.broadcast-afk.on-enter-afk");
|
||||
notifyOnBack = config.getBoolean("afk-settings.broadcast-afk.on-exit-afk");
|
||||
onAfkMessage = config.getString("afk-settings.on-enter-afk-message");
|
||||
onBackMessage = config.getString("afk-settings.on-exit-afk-message");
|
||||
}
|
||||
|
||||
public static AFKManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new AFKManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void updateActivity(Player player) {
|
||||
boolean wasAFK = isAFK(player);
|
||||
lastActive.put(player.getUniqueId(), System.currentTimeMillis());
|
||||
|
||||
if (wasAFK && notifyOnBack) {
|
||||
player.sendMessage(ChatUtil.format(onBackMessage));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAFK(Player player) {
|
||||
return (
|
||||
lastActive.containsKey(player.getUniqueId()) &&
|
||||
System.currentTimeMillis() -
|
||||
lastActive.get(player.getUniqueId()) >
|
||||
afkThresholdMillis
|
||||
);
|
||||
}
|
||||
|
||||
public void startAFKChecker() {
|
||||
if (afkCheckerTask == null || afkCheckerTask.isCancelled()) {
|
||||
afkCheckerTask =
|
||||
Bukkit
|
||||
.getScheduler()
|
||||
.runTaskTimerAsynchronously(
|
||||
PlayTimes.getPlugin(PlayTimes.class),
|
||||
() -> {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (isAFK(player)) {
|
||||
if (
|
||||
!afkTime.containsKey(player.getUniqueId()) && notifyOnAfk
|
||||
) {
|
||||
player.sendMessage(ChatUtil.format(onAfkMessage));
|
||||
}
|
||||
afkTime.put(
|
||||
player.getUniqueId(),
|
||||
afkTime.getOrDefault(
|
||||
player.getUniqueId(),
|
||||
getDefaultAfkTime(player.getUniqueId())
|
||||
) +
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
20L,
|
||||
20L
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void endAFKChecker() {
|
||||
if (afkCheckerTask != null) {
|
||||
afkCheckerTask.cancel();
|
||||
afkCheckerTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Long getDefaultAfkTime(UUID uuid) {
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
|
||||
if (
|
||||
dataManager.hasDatabase() &&
|
||||
DatabaseManager.getInstance().hasTimeForServer(uuid)
|
||||
) {
|
||||
Map<String, Long> timeMap = DatabaseManager
|
||||
.getInstance()
|
||||
.getTimeForServer(uuid);
|
||||
return timeMap != null ? timeMap.getOrDefault("afktime", 0L) : 0L;
|
||||
} else {
|
||||
return dataManager.getData().getLong("afktime." + uuid, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlayer(UUID uuid) {
|
||||
lastActive.remove(uuid);
|
||||
afkTime.remove(uuid);
|
||||
}
|
||||
|
||||
public long getAFKTime(UUID uuid) {
|
||||
return afkTime.getOrDefault(uuid, getDefaultAfkTime(uuid));
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
endAFKChecker();
|
||||
FileConfiguration config = DataManager.getInstance().getConfig();
|
||||
afkThresholdMillis = config.getLong("afk-settings.threshold") * 60L * 1000L;
|
||||
notifyOnAfk = config.getBoolean("afk-settings.broadcast-afk.on-enter-afk");
|
||||
notifyOnBack = config.getBoolean("afk-settings.broadcast-afk.on-exit-afk");
|
||||
onAfkMessage = config.getString("afk-settings.on-enter-afk-message");
|
||||
onBackMessage = config.getString("afk-settings.on-exit-afk-message");
|
||||
startAFKChecker();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package me.codedred.playtimes.afk.listeners;
|
||||
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
|
||||
public class onChat implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
||||
AFKManager.getInstance().updateActivity(event.getPlayer());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package me.codedred.playtimes.afk.listeners;
|
||||
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
public class onInteract implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
AFKManager.getInstance().updateActivity(event.getPlayer());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package me.codedred.playtimes.afk.listeners;
|
||||
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class onJoinQuit implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
AFKManager.getInstance().updateActivity(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
AFKManager.getInstance().removePlayer(event.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package me.codedred.playtimes.afk.listeners;
|
||||
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
public class onMove implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
if (event.getFrom().getBlock().equals(event.getTo().getBlock())) {
|
||||
return;
|
||||
}
|
||||
AFKManager.getInstance().updateActivity(event.getPlayer());
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,36 @@
|
||||
package me.codedred.playtimes.api;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TimelessPlayer {
|
||||
|
||||
private final Player player;
|
||||
private final UUID uuid;
|
||||
|
||||
private final StatManager stats;
|
||||
private final TimeManager timings;
|
||||
private final UUID uuid;
|
||||
private final StatManager stats;
|
||||
private final TimeManager timings;
|
||||
|
||||
public TimelessPlayer(Player player) {
|
||||
this.player = player;
|
||||
this.uuid = player.getUniqueId();
|
||||
public TimelessPlayer(final Player player) {
|
||||
this.uuid = player.getUniqueId();
|
||||
this.stats = StatManager.getInstance();
|
||||
this.timings = TimeManager.getInstance();
|
||||
}
|
||||
|
||||
stats = StatManager.getInstance();
|
||||
timings = TimeManager.getInstance();
|
||||
}
|
||||
|
||||
public TimelessPlayer(UUID player) {
|
||||
this.uuid = player;
|
||||
this.player = null;
|
||||
public TimelessPlayer(final UUID player) {
|
||||
this.uuid = player;
|
||||
this.stats = StatManager.getInstance();
|
||||
this.timings = TimeManager.getInstance();
|
||||
}
|
||||
|
||||
stats = StatManager.getInstance();
|
||||
timings = TimeManager.getInstance();
|
||||
}
|
||||
|
||||
public String getPlayTime() {
|
||||
return timings.buildFormat(stats.getPlayerStat(uuid, StatisticType.PLAYTIME)/20);
|
||||
}
|
||||
public String getPlayTime() {
|
||||
return this.timings.buildFormat(
|
||||
this.stats.getPlayerStat(this.uuid, StatisticType.PLAYTIME) / 20L
|
||||
);
|
||||
}
|
||||
|
||||
public long getRawPlayTimeInSeconds() {
|
||||
return stats.getPlayerStat(uuid, StatisticType.PLAYTIME)/20;
|
||||
}
|
||||
|
||||
public long getRawPlayTimeInSeconds() {
|
||||
return this.stats.getPlayerStat(this.uuid, StatisticType.PLAYTIME) / 20L;
|
||||
}
|
||||
}
|
||||
@@ -1,87 +1,90 @@
|
||||
package me.codedred.playtimes.api;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TimelessServer {
|
||||
|
||||
public List<UUID> getTop10Players() {
|
||||
List<UUID> players = new ArrayList<>();
|
||||
Leaderboard board = new Leaderboard();
|
||||
Map<String, Integer> map = board.getTopTen();
|
||||
Object[] array = map.keySet().toArray();
|
||||
for (int i = 0; i < map.size(); i++)
|
||||
players.add(UUID.fromString(array[i].toString()));
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
public List<Integer> getTop10Times() {
|
||||
List<Integer> players = new ArrayList<>();
|
||||
Leaderboard board = new Leaderboard();
|
||||
Map<String, Integer> map = board.getTopTen();
|
||||
Object[] array = map.values().toArray();
|
||||
for (int i = 0; i < map.size(); i++)
|
||||
players.add(Integer.parseInt(array[i].toString())/20);
|
||||
return players;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getTopMap() {
|
||||
Leaderboard board = new Leaderboard();
|
||||
return board.getTopTen();
|
||||
public List<UUID> getTop10Players() {
|
||||
final List<UUID> players = new ArrayList<>();
|
||||
final Leaderboard board = new Leaderboard();
|
||||
final Map<String, Integer> map = board.getTopTen();
|
||||
final Object[] array = map.keySet().toArray();
|
||||
for (int i = 0; i < map.size(); ++i) {
|
||||
players.add(UUID.fromString(array[i].toString()));
|
||||
}
|
||||
|
||||
public UUID getNumberOne() {
|
||||
return getTop10Players().get(0);
|
||||
}
|
||||
|
||||
public UUID getNumberTwo() {
|
||||
return getTop10Players().get(1);
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
public UUID getNumberThree() {
|
||||
return getTop10Players().get(2);
|
||||
}
|
||||
|
||||
public UUID getNumberFour() {
|
||||
return getTop10Players().get(3);
|
||||
}
|
||||
|
||||
public UUID getNumberFive() {
|
||||
return getTop10Players().get(4);
|
||||
}
|
||||
|
||||
public UUID getNumberSix() {
|
||||
return getTop10Players().get(5);
|
||||
}
|
||||
|
||||
public UUID getNumberSeven() {
|
||||
return getTop10Players().get(6);
|
||||
}
|
||||
|
||||
public UUID getNumberEight() {
|
||||
return getTop10Players().get(7);
|
||||
}
|
||||
|
||||
public UUID getNumberNine() {
|
||||
return getTop10Players().get(8);
|
||||
}
|
||||
|
||||
public UUID getNumberTen() {
|
||||
return getTop10Players().get(9);
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return StatManager.getInstance().getUptime();
|
||||
}
|
||||
|
||||
public long getUptimeInSeconds() {
|
||||
return TimeUnit.MILLISECONDS.toSeconds(ManagementFactory.getRuntimeMXBean().getUptime());
|
||||
}
|
||||
public List<Integer> getTop10Times() {
|
||||
final List<Integer> players = new ArrayList<>();
|
||||
final Leaderboard board = new Leaderboard();
|
||||
final Map<String, Integer> map = board.getTopTen();
|
||||
final Object[] array = map.values().toArray();
|
||||
for (int i = 0; i < map.size(); ++i) {
|
||||
players.add(Integer.parseInt(array[i].toString()) / 20);
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getTopMap() {
|
||||
final Leaderboard board = new Leaderboard();
|
||||
return board.getTopTen();
|
||||
}
|
||||
|
||||
public UUID getNumberOne() {
|
||||
return this.getTop10Players().get(0);
|
||||
}
|
||||
|
||||
public UUID getNumberTwo() {
|
||||
return this.getTop10Players().get(1);
|
||||
}
|
||||
|
||||
public UUID getNumberThree() {
|
||||
return this.getTop10Players().get(2);
|
||||
}
|
||||
|
||||
public UUID getNumberFour() {
|
||||
return this.getTop10Players().get(3);
|
||||
}
|
||||
|
||||
public UUID getNumberFive() {
|
||||
return this.getTop10Players().get(4);
|
||||
}
|
||||
|
||||
public UUID getNumberSix() {
|
||||
return this.getTop10Players().get(5);
|
||||
}
|
||||
|
||||
public UUID getNumberSeven() {
|
||||
return this.getTop10Players().get(6);
|
||||
}
|
||||
|
||||
public UUID getNumberEight() {
|
||||
return this.getTop10Players().get(7);
|
||||
}
|
||||
|
||||
public UUID getNumberNine() {
|
||||
return this.getTop10Players().get(8);
|
||||
}
|
||||
|
||||
public UUID getNumberTen() {
|
||||
return this.getTop10Players().get(9);
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return StatManager.getInstance().getUptime();
|
||||
}
|
||||
|
||||
public long getUptimeInSeconds() {
|
||||
return TimeUnit.MILLISECONDS.toSeconds(
|
||||
ManagementFactory.getRuntimeMXBean().getUptime()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,198 +1,311 @@
|
||||
package me.codedred.playtimes.commands;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.Debugger;
|
||||
import me.codedred.playtimes.models.Message;
|
||||
import me.codedred.playtimes.server.ServerManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.time.TimeConstants;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import me.codedred.playtimes.player.OnlinePlayer;
|
||||
import me.codedred.playtimes.player.OfflinePlayer;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Time implements CommandExecutor {
|
||||
|
||||
public boolean onCommand(CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!sender.hasPermission("pt.use")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
// command -> /playtimes [0 arguments]
|
||||
if (args.length == 0) {
|
||||
if (!(sender instanceof Player)) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
sender.sendMessage(ChatUtil.format("&cThe console has been up for " + stats.getUptime()));
|
||||
return true;
|
||||
}
|
||||
OnlinePlayer player = new OnlinePlayer((Player) sender);
|
||||
player.sendMessageToTarget();
|
||||
return true;
|
||||
}
|
||||
|
||||
private final DataManager data = DataManager.getInstance();
|
||||
|
||||
public boolean onCommand(
|
||||
CommandSender sender,
|
||||
@NotNull Command cmd,
|
||||
@NotNull String label,
|
||||
String[] args
|
||||
) {
|
||||
if (!sender.hasPermission("pt.use")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
// command -> /playtimes reload
|
||||
if (args[0].equalsIgnoreCase("reload")) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
Debugger debug = new Debugger();
|
||||
debug.execute();
|
||||
data.reloadAll();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
sender.sendMessage(ChatUtil.format("&9&lPlayTime Configurations Reloaded!"));
|
||||
return true;
|
||||
}
|
||||
String arg = args.length > 0 ? args[0].toLowerCase() : "";
|
||||
|
||||
switch (arg) {
|
||||
case "":
|
||||
handlePlayerCommand(sender);
|
||||
break;
|
||||
case "reload":
|
||||
handleReloadCommand(sender);
|
||||
break;
|
||||
case "reloaddatabase":
|
||||
handleReloadDatabaseCommand(sender);
|
||||
break;
|
||||
case "top":
|
||||
handleTopCommand(sender);
|
||||
break;
|
||||
case "block":
|
||||
handleBlockCommand(sender, args, true);
|
||||
break;
|
||||
case "unblock":
|
||||
handleBlockCommand(sender, args, false);
|
||||
break;
|
||||
case "version":
|
||||
handleVersionCommand(sender);
|
||||
break;
|
||||
case "help":
|
||||
handleHelpCommand(sender);
|
||||
break;
|
||||
default:
|
||||
handleOtherPlayerCommand(sender, args);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleHelpCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Help ***"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt: &7Displays your play time"));
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt <player>: &7Displays the play time of <player>")
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&e/pt reload: &7Reloads the PlayTimes plugin configurations"
|
||||
)
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt top: &7Shows the top players by play time")
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&e/pt block <player>: &7Blocks a player from leaderboards"
|
||||
)
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&e/pt unblock <player>: &7Unblocks a player from leaderboards"
|
||||
)
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt version: &7Displays the version info")
|
||||
);
|
||||
}
|
||||
|
||||
// command -> /playtimes top
|
||||
else if (args[0].equalsIgnoreCase("top")) {
|
||||
Bukkit.dispatchCommand(sender, "toppt");
|
||||
return true;
|
||||
}
|
||||
private void handleVersionCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
boolean isOnline = ServerManager.getInstance().isOnline();
|
||||
String serverStatus = isOnline ? "Online" : "Offline";
|
||||
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Version Info ***"));
|
||||
sender.sendMessage(
|
||||
ChatColor.GOLD +
|
||||
"Server version: " +
|
||||
ChatColor.WHITE +
|
||||
Bukkit.getServer().getVersion() +
|
||||
ChatColor.GOLD +
|
||||
"\nPlayTimes version: " +
|
||||
ChatColor.WHITE +
|
||||
JavaPlugin.getPlugin(PlayTimes.class).getDescription().getVersion() +
|
||||
ChatColor.GOLD +
|
||||
"\nStat Manager: " +
|
||||
ChatColor.WHITE +
|
||||
StatManager.getInstance().name +
|
||||
ChatColor.GOLD +
|
||||
"\nServer Status: " +
|
||||
ChatColor.WHITE +
|
||||
serverStatus +
|
||||
ChatColor.GOLD +
|
||||
"\nDatabase connected: " +
|
||||
ChatColor.WHITE +
|
||||
DataManager.getInstance().hasDatabase() +
|
||||
ChatColor.GOLD +
|
||||
"\nAFK Status: " +
|
||||
ChatColor.WHITE +
|
||||
DataManager.getInstance().hasAfkEnabled() +
|
||||
ChatColor.GOLD +
|
||||
"\nUUID Lookup Type: " +
|
||||
ChatColor.WHITE +
|
||||
ServerManager.getInstance().lookupType()
|
||||
);
|
||||
}
|
||||
|
||||
private void handlePlayerCommand(CommandSender sender) {
|
||||
if (!(sender instanceof Player)) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&cThe console has been up for " + stats.getUptime())
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// command -> /playtimes block <player>
|
||||
else if (args[0].equalsIgnoreCase("block")) {
|
||||
if (!sender.hasPermission("pt.block")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&c&lIncorrect Usage&c, try &7/pt block <player>"));
|
||||
return true;
|
||||
}
|
||||
if (data.getData().contains("blocked." + args[1].toLowerCase())) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&cUser is already blocked!"));
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&c&oMaybe try, &7/pt unblock <player>"));
|
||||
return true;
|
||||
}
|
||||
UUID uuid;
|
||||
if (Bukkit.getPlayer(args[1]) == null) {
|
||||
try {
|
||||
uuid = ServerManager.getInstance().getUUID(args[1].toLowerCase());
|
||||
} catch (NullPointerException e) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
uuid = Bukkit.getPlayer(args[1]).getUniqueId();
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Player player = (Player) sender;
|
||||
Message message = new Message(
|
||||
sender,
|
||||
player.getUniqueId(),
|
||||
player.getName()
|
||||
);
|
||||
message.sendMessageToTarget();
|
||||
}
|
||||
}
|
||||
.runTaskAsynchronously(JavaPlugin.getPlugin(PlayTimes.class));
|
||||
}
|
||||
|
||||
|
||||
data.getData().set("blocked." + args[1].toLowerCase(), uuid.toString());
|
||||
private void handleReloadCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
data.reloadAll();
|
||||
TimeConstants.reload();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
sender.sendMessage(ChatUtil.format("&aPlayTimes Configurations Reloaded!"));
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&aTrying to reload the Database settings?")
|
||||
);
|
||||
sender.sendMessage(ChatUtil.format(" &e&oTry, /pt reloadDatabase"));
|
||||
}
|
||||
}
|
||||
|
||||
if (data.getData().contains("leaderboard." + uuid))
|
||||
data.getData().set("leaderboard." + uuid, null);
|
||||
private void handleReloadDatabaseCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
data.reloadDatabase();
|
||||
PlayTimes.getPlugin(PlayTimes.class).loadDatabase();
|
||||
sender.sendMessage(ChatUtil.format("&aDatabase Reloaded."));
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&oIf you are still encountering issues try restarting your server."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
data.saveData();
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&aUser &c&lBLOCKED &afrom leaderboards!"));
|
||||
return true;
|
||||
}
|
||||
private void handleTopCommand(CommandSender sender) {
|
||||
Bukkit.dispatchCommand(sender, "toppt");
|
||||
}
|
||||
|
||||
private void handleBlockCommand(
|
||||
CommandSender sender,
|
||||
String[] args,
|
||||
boolean block
|
||||
) {
|
||||
String blockAction = block ? "block" : "unblock";
|
||||
if (!sender.hasPermission("pt.block")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix(
|
||||
"&c&lIncorrect Usage&c, try &7/pt " + blockAction + " <player>"
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
String playerName = args[1];
|
||||
String blockedKey = "blocked." + playerName.toLowerCase();
|
||||
if (block == data.getData().contains(blockedKey)) {
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix("&cUser is already " + blockAction + "ed!")
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix(
|
||||
"&c&oMaybe try, &7/pt " + (block ? "unblock" : "block") + " <player>"
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
UUID uuid;
|
||||
if (Bukkit.getPlayer(playerName) == null) {
|
||||
try {
|
||||
uuid = ServerManager.getInstance().getUUID(playerName.toLowerCase());
|
||||
} catch (NullPointerException e) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
uuid = Objects.requireNonNull(Bukkit.getPlayer(playerName)).getUniqueId();
|
||||
}
|
||||
if (uuid == null) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&c&lUser not found."));
|
||||
return;
|
||||
}
|
||||
if (block) {
|
||||
data.getData().set(blockedKey, uuid.toString());
|
||||
if (data.getData().contains("leaderboard." + uuid)) {
|
||||
data.getData().set("leaderboard." + uuid, null);
|
||||
}
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix("&aUser &c&lBLOCKED &afrom leaderboards!")
|
||||
);
|
||||
} else {
|
||||
data.getData().set(blockedKey, null);
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix("&aUser &b&lUNBLOCKED &afrom leaderboards!")
|
||||
);
|
||||
}
|
||||
data.saveData();
|
||||
}
|
||||
|
||||
private void handleOtherPlayerCommand(CommandSender sender, String[] args) {
|
||||
if (!sender.hasPermission("pt.others")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pattern p = Pattern.compile("[^a-z0-9_]", Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(args[0]);
|
||||
boolean b = m.find();
|
||||
|
||||
if (b) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// command -> /playtimes block <player>
|
||||
else if (args[0].equalsIgnoreCase("unblock")) {
|
||||
if (!sender.hasPermission("pt.block")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&c&lIncorrect Usage&c, try &7/pt unblock <player>"));
|
||||
return true;
|
||||
}
|
||||
if (!data.getData().contains("blocked." + args[1].toLowerCase())) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&cUser is not blocked!"));
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&c&oMaybe try, &7/pt block <player>"));
|
||||
return true;
|
||||
}
|
||||
data.getData().set("blocked." + args[1].toLowerCase(), null);
|
||||
data.saveData();
|
||||
UUID target;
|
||||
if (Bukkit.getPlayer(args[0]) == null) {
|
||||
target = ServerManager.getInstance().getUUID(args[0]);
|
||||
if (target == null) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
target =
|
||||
Objects.requireNonNull(Bukkit.getPlayer(args[0])).getUniqueId();
|
||||
}
|
||||
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&aUser &b&lUNBLOCKED &afrom leaderboards!"));
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// command -/playtimes holo
|
||||
/*else if (args[0].equalsIgnoreCase("holo")) {
|
||||
if (args.length != 3) {
|
||||
switch(args[2].toUpperCase()) {
|
||||
case "CUSTOM":
|
||||
|
||||
return true;
|
||||
case "TOP10":
|
||||
return true;
|
||||
case "TOP5":
|
||||
return true;
|
||||
case "TOP3":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
// command -> /playtimes <player>
|
||||
if (!sender.hasPermission("pt.others")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pattern p = Pattern.compile("[^a-z0-9_]", Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(args[0]);
|
||||
boolean b = m.find();
|
||||
|
||||
if (b) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
UUID target;
|
||||
if (Bukkit.getPlayer(args[0]) == null) {
|
||||
target = ServerManager.getInstance().getUUID(args[0]);
|
||||
if (target == null) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
target = Bukkit.getPlayer(args[0]).getUniqueId();
|
||||
|
||||
org.bukkit.OfflinePlayer offlinePlayer = Bukkit.getServer().getOfflinePlayer(target);
|
||||
OfflinePlayer player = new OfflinePlayer(sender, target, offlinePlayer.getName());
|
||||
player.sendMessageToTarget();
|
||||
|
||||
|
||||
}
|
||||
}.runTaskAsynchronously(PlayTimes.getPlugin(PlayTimes.class));
|
||||
return true;
|
||||
}
|
||||
OfflinePlayer offlinePlayer = Bukkit
|
||||
.getServer()
|
||||
.getOfflinePlayer(target);
|
||||
Message message = new Message(sender, target, offlinePlayer.getName());
|
||||
message.sendMessageToTarget();
|
||||
}
|
||||
}
|
||||
.runTaskAsynchronously(JavaPlugin.getPlugin(PlayTimes.class));
|
||||
}
|
||||
}
|
||||
@@ -1,92 +1,161 @@
|
||||
package me.codedred.playtimes.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import me.codedred.playtimes.utils.CoolDownUtil;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import me.codedred.playtimes.utils.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
import me.codedred.playtimes.utils.PAPIHolders;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TopTime implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) {
|
||||
if (!sender.hasPermission("pt.top")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (data.getConfig().getBoolean("top-playtime.enable-cooldown") && !sender.hasPermission("pt.block-cooldown")) {
|
||||
if (sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
if (CoolDownUtil.contains(player.getUniqueId())) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix(data.getConfig().getString("messages.cooldown")
|
||||
.replace("%timeleft%", Integer.toString(CoolDownUtil.left(player.getUniqueId())))));
|
||||
return true;
|
||||
}
|
||||
CoolDownUtil.add(player.getUniqueId(), System.currentTimeMillis() +
|
||||
(data.getConfig().getInt("top-playtime.cooldown-seconds") * 1000L));
|
||||
}
|
||||
}
|
||||
Leaderboard board = new Leaderboard();
|
||||
Map<String, Integer> map = board.getTopTen();
|
||||
|
||||
if (map.isEmpty()) {
|
||||
sender.sendMessage(ChatUtil.format("&cRejoin the server to fill the leaderboard!"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String header = ChatUtil.format(data.getConfig().getString("top-playtime.header"));
|
||||
String footer = ChatUtil.format(data.getConfig().getString("top-playtime.footer"));
|
||||
String content = data.getConfig().getString("top-playtime.content");
|
||||
@Override
|
||||
public boolean onCommand(
|
||||
CommandSender sender,
|
||||
@NotNull Command cmd,
|
||||
@NotNull String label,
|
||||
String[] args
|
||||
) {
|
||||
if (!sender.hasPermission("pt.top")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
if (ServerUtils.hasPAPI() && sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
header = PAPIHolders.getHolders(player, header);
|
||||
footer = PAPIHolders.getHolders(player, footer);
|
||||
}
|
||||
if (
|
||||
data.getConfig().getBoolean("top-playtime.enable-cooldown") &&
|
||||
!sender.hasPermission("pt.block-cooldown") &&
|
||||
sender instanceof Player
|
||||
) {
|
||||
Player player = (Player) sender;
|
||||
if (CoolDownUtil.contains(player.getUniqueId())) {
|
||||
String cooldownMessage = Objects
|
||||
.requireNonNull(data.getConfig().getString("messages.cooldown"))
|
||||
.replace(
|
||||
"%timeleft%",
|
||||
Integer.toString(CoolDownUtil.left(player.getUniqueId()))
|
||||
);
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix(cooldownMessage));
|
||||
return true;
|
||||
}
|
||||
CoolDownUtil.add(
|
||||
player.getUniqueId(),
|
||||
System.currentTimeMillis() +
|
||||
(data.getConfig().getInt("top-playtime.cooldown-seconds") * 1000L)
|
||||
);
|
||||
}
|
||||
|
||||
String original = content;
|
||||
sender.sendMessage(header);
|
||||
for (int i = 0; i < map.size(); i++) {
|
||||
UUID uuid = UUID.fromString(map.keySet().toArray()[i].toString());
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
org.bukkit.OfflinePlayer player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
content = PAPIHolders.getHolders(player, content);
|
||||
else {
|
||||
org.bukkit.OfflinePlayer oplayer = Bukkit.getOfflinePlayer(uuid);
|
||||
content = PAPIHolders.getHolders(oplayer, content);
|
||||
}
|
||||
generateAndSendLeaderboard(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
private void generateAndSendLeaderboard(CommandSender sender) {
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
Leaderboard board = new Leaderboard();
|
||||
Map<String, Integer> map = board.getTopTen();
|
||||
|
||||
if (map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[][] replacements = {{"%player%", Bukkit.getServer().getOfflinePlayer(uuid).getName()},
|
||||
{"%place%",String.valueOf(i + 1)},
|
||||
{"%time%", timeManager.buildFormat(Integer.parseInt(map.values().toArray()[i].toString())/20) }};
|
||||
for (String[] r : replacements)
|
||||
content = StringUtils.replace(content, r[0], r[1]);
|
||||
content = StringUtils.replace(content,"%joindate%", statManager.getJoinDate(uuid));
|
||||
sender.sendMessage(ChatUtil.format(content));
|
||||
content = original;
|
||||
}
|
||||
sender.sendMessage(footer);
|
||||
return generateLeaderboardMessages(map, sender);
|
||||
}).thenAccept(messages -> {
|
||||
Bukkit.getScheduler().runTask(getPlugin(), () -> {
|
||||
if (messages == null) {
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&cRejoin the server to fill the leaderboard!")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
for (String message : messages) {
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
});
|
||||
}).exceptionally(throwable -> {
|
||||
throwable.printStackTrace();
|
||||
Bukkit.getScheduler().runTask(getPlugin(), () -> {
|
||||
sender.sendMessage(ChatUtil.format("&cError generating leaderboard!"));
|
||||
});
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private List<String> generateLeaderboardMessages(Map<String, Integer> map, CommandSender sender) {
|
||||
List<String> messages = new ArrayList<>();
|
||||
DataManager data = DataManager.getInstance();
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
|
||||
String header = ChatUtil.format(
|
||||
data.getConfig().getString("top-playtime.header")
|
||||
);
|
||||
String footer = ChatUtil.format(
|
||||
data.getConfig().getString("top-playtime.footer")
|
||||
);
|
||||
String contentTemplate = data.getConfig().getString("top-playtime.content");
|
||||
|
||||
if (ServerUtils.hasPAPI() && sender instanceof Player) {
|
||||
header = PAPIHolders.getHolders((Player) sender, header);
|
||||
footer = PAPIHolders.getHolders((Player) sender, footer);
|
||||
}
|
||||
|
||||
messages.add(header);
|
||||
|
||||
int place = 1;
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
UUID uuid = UUID.fromString(entry.getKey());
|
||||
org.bukkit.OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
|
||||
|
||||
String content = contentTemplate;
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
content = PAPIHolders.getHolders(offlinePlayer, content);
|
||||
}
|
||||
|
||||
String defaultPlayerName = "Unknown";
|
||||
String defaultJoinDate = "N/A";
|
||||
String defaultTime = "0h 0m 0s";
|
||||
|
||||
String offlinePlayerName = offlinePlayer.getName() != null
|
||||
? offlinePlayer.getName()
|
||||
: defaultPlayerName;
|
||||
String time = timeManager.buildFormat(entry.getValue() / 20);
|
||||
String joinDate = statManager.getJoinDate(uuid) != null
|
||||
? statManager.getJoinDate(uuid)
|
||||
: defaultJoinDate;
|
||||
|
||||
if (time == null) {
|
||||
time = defaultTime;
|
||||
}
|
||||
|
||||
String formattedContent = content
|
||||
.replace("%player%", offlinePlayerName)
|
||||
.replace("%place%", String.valueOf(place))
|
||||
.replace("%time%", time)
|
||||
.replace("%joindate%", joinDate);
|
||||
|
||||
messages.add(ChatUtil.format(formattedContent));
|
||||
place++;
|
||||
}
|
||||
|
||||
messages.add(footer);
|
||||
return messages;
|
||||
}
|
||||
|
||||
private Plugin getPlugin() {
|
||||
return Bukkit.getPluginManager().getPlugin("PlayTimes");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.codedred.playtimes.commands;
|
||||
|
||||
import java.util.List;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
@@ -13,34 +14,53 @@ import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Uptime implements CommandExecutor {
|
||||
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, String cmdL, String[] args) {
|
||||
if (cmdL.equalsIgnoreCase("uptime") || cmdL.equalsIgnoreCase("serveruptime") || cmdL.equalsIgnoreCase("serverupt")) {
|
||||
if (sender.hasPermission("pt.uptime")) {
|
||||
if (args.length >= 0) {
|
||||
if (sender instanceof Player ) {
|
||||
Player player = (Player) sender;
|
||||
for (String msg : DataManager.getInstance().getConfig().getStringList("uptime.message")) {
|
||||
if (ServerUtils.hasPAPI())
|
||||
msg = PlaceholderAPI.setPlaceholders(player, msg);
|
||||
if (msg.contains("{\"text\":")) {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), ("tellraw " + player + " " + msg.replace("%serveruptime%",
|
||||
StatManager.getInstance().getUptime())));
|
||||
} else
|
||||
player.sendMessage(ChatUtil.format(msg.replace("%serveruptime%", StatManager.getInstance().getUptime())));
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
for (String msg : DataManager.getInstance().getConfig().getStringList("uptime.message")) {
|
||||
sender.sendMessage(ChatUtil.format(msg.replace("%serveruptime%", StatManager.getInstance().getUptime())));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(
|
||||
@NotNull CommandSender sender,
|
||||
@NotNull Command cmd,
|
||||
String cmdL,
|
||||
String[] args
|
||||
) {
|
||||
if (
|
||||
!cmdL.equalsIgnoreCase("uptime") &&
|
||||
!cmdL.equalsIgnoreCase("serveruptime") &&
|
||||
!cmdL.equalsIgnoreCase("serverupt")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sender.hasPermission("pt.uptime")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
String uptime = StatManager.getInstance().getUptime();
|
||||
List<String> messages = DataManager
|
||||
.getInstance()
|
||||
.getConfig()
|
||||
.getStringList("uptime.message");
|
||||
|
||||
for (String message : messages) {
|
||||
if (ServerUtils.hasPAPI() && sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
message = PlaceholderAPI.setPlaceholders(player, message);
|
||||
}
|
||||
|
||||
if (message.contains("{\"text\":")) {
|
||||
String consoleCommand =
|
||||
"tellraw " +
|
||||
sender.getName() +
|
||||
" " +
|
||||
message.replace("%serveruptime%", uptime);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), consoleCommand);
|
||||
} else {
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(message.replace("%serveruptime%", uptime))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package me.codedred.playtimes.commands.completer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TimeTabCompleter implements TabCompleter {
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(
|
||||
@NotNull CommandSender sender,
|
||||
@NotNull Command command,
|
||||
@NotNull String alias,
|
||||
String[] args
|
||||
) {
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
if (args.length == 1) {
|
||||
if (sender.hasPermission("pt.use")) {
|
||||
completions.add("top");
|
||||
completions.addAll(getOnlinePlayerNames(sender));
|
||||
}
|
||||
if (sender.hasPermission("pt.block")) {
|
||||
completions.add("block");
|
||||
completions.add("unblock");
|
||||
}
|
||||
if (sender.hasPermission("pt.reload")) {
|
||||
completions.add("reload");
|
||||
completions.add("version");
|
||||
completions.add("help");
|
||||
}
|
||||
}
|
||||
|
||||
return completions;
|
||||
}
|
||||
|
||||
private List<String> getOnlinePlayerNames(CommandSender sender) {
|
||||
List<String> playerNames = new ArrayList<>();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (
|
||||
!isVanished(player) ||
|
||||
sender.equals(player) ||
|
||||
sender.hasPermission("pt.seevanished")
|
||||
) {
|
||||
playerNames.add(player.getName());
|
||||
}
|
||||
}
|
||||
return playerNames;
|
||||
}
|
||||
|
||||
private boolean isVanished(Player player) {
|
||||
for (MetadataValue meta : player.getMetadata("vanished")) {
|
||||
if (meta.asBoolean()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +1,183 @@
|
||||
package me.codedred.playtimes.data;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class CustomConfig {
|
||||
private final PlayTimes plugin;
|
||||
private FileConfiguration dataConfig = null;
|
||||
private File dataConfigFile = null;
|
||||
private final String name;
|
||||
|
||||
public CustomConfig(PlayTimes plugin, String name) {
|
||||
this.plugin = plugin;
|
||||
this.name = name;
|
||||
saveDefaultConfig();
|
||||
}
|
||||
private final String name;
|
||||
private final PlayTimes plugin;
|
||||
private FileConfiguration dataConfig = null;
|
||||
private File dataConfigFile = null;
|
||||
|
||||
public void reloadConfig() {
|
||||
if (dataConfigFile == null) {
|
||||
dataConfigFile = new File(plugin.getDataFolder(),
|
||||
name);
|
||||
}
|
||||
|
||||
dataConfig = YamlConfiguration
|
||||
.loadConfiguration(dataConfigFile);
|
||||
public CustomConfig(PlayTimes plugin, String fileName) {
|
||||
this.plugin = plugin;
|
||||
this.name = fileName;
|
||||
saveDefaultConfig();
|
||||
}
|
||||
|
||||
InputStream defConfigStream = plugin.getResource(name);
|
||||
if (defConfigStream != null) {
|
||||
YamlConfiguration defConfig = YamlConfiguration
|
||||
.loadConfiguration(new InputStreamReader(defConfigStream));
|
||||
dataConfig.setDefaults(defConfig);
|
||||
}
|
||||
}
|
||||
public void reloadConfig() {
|
||||
if (this.dataConfigFile == null) {
|
||||
this.dataConfigFile = new File(this.plugin.getDataFolder(), name);
|
||||
}
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
if (dataConfig == null) {
|
||||
reloadConfig();
|
||||
}
|
||||
return dataConfig;
|
||||
}
|
||||
this.dataConfig = YamlConfiguration.loadConfiguration(this.dataConfigFile);
|
||||
|
||||
public void saveConfig() {
|
||||
if ((dataConfig == null) || (dataConfigFile == null)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
getConfig().save(dataConfigFile);
|
||||
} catch (IOException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Could not save config to "
|
||||
+ dataConfigFile, ex);
|
||||
}
|
||||
}
|
||||
if ("config.yml".equals(name)) checkAndAddDefaults();
|
||||
|
||||
public void saveDefaultConfig() {
|
||||
if (dataConfigFile == null) {
|
||||
dataConfigFile = new File(plugin.getDataFolder(),
|
||||
name);
|
||||
}
|
||||
if (!dataConfigFile.exists()) {
|
||||
plugin.saveResource(name, false);
|
||||
}
|
||||
}
|
||||
try (InputStream defConfigStream = this.plugin.getResource(name)) {
|
||||
if (defConfigStream != null) {
|
||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
|
||||
new InputStreamReader(defConfigStream)
|
||||
);
|
||||
this.dataConfig.setDefaults(defConfig);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.plugin.getLogger()
|
||||
.log(Level.SEVERE, "Error reading default config", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private void checkAndAddDefaults() {
|
||||
Map<String, Object> requiredKeys = new LinkedHashMap<>();
|
||||
requiredKeys.put("prefix", "&7[&b&lPlayTimes&7]");
|
||||
requiredKeys.put("use-papi-placeholders", false);
|
||||
|
||||
requiredKeys.put(
|
||||
"playtime.message",
|
||||
new String[] {
|
||||
"&b&m=======&b&l[%player%]&b&m=======",
|
||||
"&aPlaytime:&f %playtime%",
|
||||
"&aTimes Joined:&f %timesjoined%",
|
||||
"&aJoin Date:&f %joindate%",
|
||||
"&b&m============================",
|
||||
}
|
||||
);
|
||||
|
||||
requiredKeys.put("playtime.name.second", "s");
|
||||
requiredKeys.put("playtime.name.minute", "min ");
|
||||
requiredKeys.put("playtime.name.hour", "hr ");
|
||||
requiredKeys.put("playtime.name.day", "day ");
|
||||
requiredKeys.put("playtime.name.seconds", "s");
|
||||
requiredKeys.put("playtime.name.minutes", "mins ");
|
||||
requiredKeys.put("playtime.name.hours", "hrs ");
|
||||
requiredKeys.put("playtime.name.days", "days ");
|
||||
requiredKeys.put("playtime.only-hours", false);
|
||||
requiredKeys.put("playtime.show-seconds", true);
|
||||
requiredKeys.put("playtime.show-days", true);
|
||||
requiredKeys.put("playtime.round-numbers", true);
|
||||
|
||||
requiredKeys.put("afk-settings.enabled", false);
|
||||
requiredKeys.put("afk-settings.threshold", 5);
|
||||
requiredKeys.put("afk-settings.broadcast-afk.on-enter-afk", true);
|
||||
requiredKeys.put("afk-settings.broadcast-afk.on-exit-afk", true);
|
||||
requiredKeys.put(
|
||||
"afk-settings.on-enter-afk-message",
|
||||
"&eYou are now marked as AFK."
|
||||
);
|
||||
requiredKeys.put(
|
||||
"afk-settings.on-exit-afk-message",
|
||||
"&eYou are no longer AFK."
|
||||
);
|
||||
requiredKeys.put("afk-settings.cancel-afk.on-player-move", true);
|
||||
requiredKeys.put("afk-settings.cancel-afk.on-player-chat", true);
|
||||
requiredKeys.put("afk-settings.cancel-afk.on-player-interact", true);
|
||||
|
||||
requiredKeys.put(
|
||||
"uptime.message",
|
||||
new String[] {
|
||||
"&b&m============================",
|
||||
"&aServer Uptime:&f %serveruptime%",
|
||||
"&b&m============================",
|
||||
}
|
||||
);
|
||||
|
||||
requiredKeys.put(
|
||||
"top-playtime.header",
|
||||
"&b******&9[&3&lPlayTime Leaderboards&9]&b*****"
|
||||
);
|
||||
requiredKeys.put(
|
||||
"top-playtime.content",
|
||||
"&5%place%) &9&l%player% &9&o- %time%"
|
||||
);
|
||||
requiredKeys.put(
|
||||
"top-playtime.footer",
|
||||
"&b****************************************"
|
||||
);
|
||||
requiredKeys.put("top-playtime.enable-cooldown", true);
|
||||
requiredKeys.put("top-playtime.cooldown-seconds", 60);
|
||||
requiredKeys.put("top-playtime.track-rawtime", false);
|
||||
|
||||
requiredKeys.put("date-format", "MM/dd/yyyy");
|
||||
|
||||
requiredKeys.put("messages.noPermission", "&cYou cannot run this command.");
|
||||
requiredKeys.put("messages.player-not-found", "&cUnable to locate player.");
|
||||
requiredKeys.put(
|
||||
"messages.player-never-joined",
|
||||
"&cThis player has not joined the server."
|
||||
);
|
||||
requiredKeys.put(
|
||||
"messages.cooldown",
|
||||
"&cCommand unavailable for %timeleft% seconds!"
|
||||
);
|
||||
|
||||
requiredKeys.put(
|
||||
"uuid-lookups.what-does-this-do",
|
||||
"https://github.com/CodedRed-Spigot/PlayTimes/wiki/UUID-LOOKUPS"
|
||||
);
|
||||
requiredKeys.put("uuid-lookups.type", "default");
|
||||
|
||||
boolean changesMade = false;
|
||||
for (Map.Entry<String, Object> entry : requiredKeys.entrySet()) {
|
||||
if (!this.dataConfig.contains(entry.getKey())) {
|
||||
this.dataConfig.set(entry.getKey(), entry.getValue());
|
||||
changesMade = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changesMade) {
|
||||
plugin
|
||||
.getLogger()
|
||||
.info(
|
||||
"Missing configuration keys detected in 'Config.yml'. Adding them now."
|
||||
);
|
||||
saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
if (this.dataConfig == null) reloadConfig();
|
||||
return this.dataConfig;
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
if (this.dataConfig == null || this.dataConfigFile == null) return;
|
||||
try {
|
||||
getConfig().save(this.dataConfigFile);
|
||||
} catch (IOException ex) {
|
||||
this.plugin.getLogger()
|
||||
.log(
|
||||
Level.SEVERE,
|
||||
ex,
|
||||
() -> "Could not save config to " + this.dataConfigFile
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveDefaultConfig() {
|
||||
if (this.dataConfigFile == null) {
|
||||
this.dataConfigFile = new File(this.plugin.getDataFolder(), name);
|
||||
}
|
||||
if (!this.dataConfigFile.exists()) {
|
||||
this.plugin.saveResource(name, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +1,68 @@
|
||||
package me.codedred.playtimes.data;
|
||||
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.server.ServerManager;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class DataManager {
|
||||
|
||||
private final static DataManager instance = new DataManager();
|
||||
|
||||
public static DataManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final CustomConfig data = new CustomConfig(PlayTimes.getPlugin(PlayTimes.class), "data.yml");
|
||||
private final CustomConfig cfg = new CustomConfig(PlayTimes.getPlugin(PlayTimes.class), "config.yml");
|
||||
//private final CustomConfig holo = new CustomConfig(PlayTimes.getPlugin(PlayTimes.class), "hologram.yml");
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
return cfg.getConfig();
|
||||
}
|
||||
private static final DataManager instance = new DataManager();
|
||||
private final CustomConfig data = new CustomConfig(
|
||||
JavaPlugin.getPlugin(PlayTimes.class),
|
||||
"data.yml"
|
||||
);
|
||||
private final CustomConfig db = new CustomConfig(
|
||||
JavaPlugin.getPlugin(PlayTimes.class),
|
||||
"database.yml"
|
||||
);
|
||||
private final CustomConfig cfg = new CustomConfig(
|
||||
JavaPlugin.getPlugin(PlayTimes.class),
|
||||
"config.yml"
|
||||
);
|
||||
|
||||
public FileConfiguration getData() {
|
||||
return data.getConfig();
|
||||
}
|
||||
public static DataManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
//public FileConfiguration getHolo() {
|
||||
// return holo.getConfig();
|
||||
//}
|
||||
public FileConfiguration getConfig() {
|
||||
return cfg.getConfig();
|
||||
}
|
||||
|
||||
public void reloadAll() {
|
||||
data.reloadConfig();
|
||||
cfg.reloadConfig();
|
||||
//holo.reloadConfig();
|
||||
}
|
||||
public FileConfiguration getData() {
|
||||
return data.getConfig();
|
||||
}
|
||||
|
||||
public void saveData() {
|
||||
data.saveConfig();
|
||||
}
|
||||
|
||||
//public void saveHolo() {
|
||||
// holo.saveConfig();
|
||||
//}
|
||||
public FileConfiguration getDBConfig() {
|
||||
return db.getConfig();
|
||||
}
|
||||
|
||||
public void saveData() {
|
||||
data.saveConfig();
|
||||
}
|
||||
|
||||
public void reloadAll() {
|
||||
data.reloadConfig();
|
||||
cfg.reloadConfig();
|
||||
db.reloadConfig();
|
||||
ServerManager.getInstance().updateLookupType();
|
||||
if (hasAfkEnabled()) AFKManager.getInstance().reload();
|
||||
}
|
||||
|
||||
public void reloadDatabase() {
|
||||
db.reloadConfig();
|
||||
}
|
||||
|
||||
public boolean hasDatabase() {
|
||||
return (
|
||||
getDBConfig().getBoolean("database-settings.enabled") &&
|
||||
DatabaseManager.getInstance().isConnected()
|
||||
);
|
||||
}
|
||||
|
||||
public boolean hasAfkEnabled() {
|
||||
return getConfig().getBoolean("afk-settings.enabled", false);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package me.codedred.playtimes.data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Debugger {
|
||||
|
||||
public void execute() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
//Data file update
|
||||
if (!data.getData().contains("leaderboard")) {
|
||||
//Bukkit.getServer().getConsoleSender().sendMessage(ChatColor.DARK_PURPLE + "[PlayTime] " + ChatColor.WHITE + "Updating data file...");
|
||||
Map<String, Long> boardData = new HashMap<>();
|
||||
for (String uuid : data.getData().getKeys(false))
|
||||
boardData.put(uuid, data.getData().getLong(uuid));
|
||||
for (String uuid : data.getData().getKeys(false))
|
||||
data.getData().set(uuid, null);
|
||||
for (Map.Entry<String, Long> d : boardData.entrySet())
|
||||
data.getData().set("leaderboard." + d.getKey(), d.getValue());
|
||||
|
||||
// Bukkit.getServer().getConsoleSender().sendMessage(ChatColor.DARK_PURPLE + "[PlayTime] " + ChatColor.WHITE + "Data file updated!");
|
||||
data.saveData();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package me.codedred.playtimes.data.database.datasource;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public interface DataSource {
|
||||
Connection getConnection() throws SQLException;
|
||||
|
||||
void closeConnection() throws SQLException;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package me.codedred.playtimes.data.database.datasource.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import lombok.val;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.datasource.DataSource;
|
||||
|
||||
public class MySQL implements DataSource {
|
||||
|
||||
private final String connectionUrl;
|
||||
private final String user;
|
||||
private final String password;
|
||||
|
||||
public MySQL(PlayTimes plugin) {
|
||||
val config = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getConfigurationSection("database-settings");
|
||||
val host = config.getString("host");
|
||||
val port = config.getString("port");
|
||||
this.user = config.getString("user");
|
||||
this.password = config.getString("password");
|
||||
val database = config.getString("database");
|
||||
val SSL = config.getBoolean("useSSL");
|
||||
|
||||
this.connectionUrl =
|
||||
String.format(
|
||||
"jdbc:mysql://%s:%s/%s?autoReconnect=true&useSSL=" + SSL,
|
||||
host,
|
||||
port,
|
||||
database
|
||||
);
|
||||
|
||||
try {
|
||||
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||
plugin.getLogger().info("Successfully connected to database.");
|
||||
} catch (ClassNotFoundException e) {
|
||||
plugin
|
||||
.getLogger()
|
||||
.severe("MySQL JDBC Driver not found: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
return DriverManager.getConnection(connectionUrl, user, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() throws SQLException {
|
||||
// connection.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package me.codedred.playtimes.data.database.datasource.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import lombok.val;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.datasource.DataSource;
|
||||
|
||||
public class SQLite implements DataSource {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
public SQLite(PlayTimes plugin) {
|
||||
val config = DataManager.getInstance().getDBConfig();
|
||||
val database = config.getString("database");
|
||||
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
String url =
|
||||
"jdbc:sqlite:" + plugin.getDataFolder() + "/" + database + ".db";
|
||||
this.connection = DriverManager.getConnection(url);
|
||||
plugin.getLogger().info("Successfully connected to database.");
|
||||
} catch (SQLException | ClassNotFoundException exception) {
|
||||
plugin
|
||||
.getLogger()
|
||||
.severe(
|
||||
"ERROR! Database failed to connect. Please check your config.yml and try again."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() throws SQLException {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package me.codedred.playtimes.data.database.manager;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.Getter;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.datasource.DataSource;
|
||||
import me.codedred.playtimes.data.database.datasource.impl.MySQL;
|
||||
import me.codedred.playtimes.data.database.datasource.impl.SQLite;
|
||||
import me.codedred.playtimes.data.database.table.UsersTable;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@Getter
|
||||
public class DatabaseManager {
|
||||
|
||||
private static DatabaseManager instance;
|
||||
|
||||
private DataSource dataSource;
|
||||
private UsersTable usersTable;
|
||||
private boolean connected = false;
|
||||
private final String serverId;
|
||||
|
||||
private Map<UUID, Map<String, Map<String, Long>>> userPlaytimes = new HashMap<>();
|
||||
|
||||
private DatabaseManager() {
|
||||
serverId =
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getString("database-settings.serverId");
|
||||
setupDataSource();
|
||||
}
|
||||
|
||||
public static DatabaseManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DatabaseManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void setupDataSource() {
|
||||
String type = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getString("database-settings.type");
|
||||
|
||||
switch (type.toLowerCase()) {
|
||||
case "mysql":
|
||||
this.dataSource = new MySQL(PlayTimes.getPlugin(PlayTimes.class));
|
||||
break;
|
||||
case "sqlite":
|
||||
this.dataSource = new SQLite(PlayTimes.getPlugin(PlayTimes.class));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"Unexpected database type: " +
|
||||
type +
|
||||
". Accepted Values: 'mysql', 'sqlite'"
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
connected = dataSource != null && dataSource.getConnection() != null;
|
||||
} catch (SQLException e) {
|
||||
Bukkit
|
||||
.getServer()
|
||||
.getLogger()
|
||||
.warning("[PlayTimes] Error thrown from DatabaseManager!");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (isConnected()) {
|
||||
this.usersTable = new UsersTable(dataSource);
|
||||
this.usersTable.createTable();
|
||||
} else {
|
||||
Bukkit
|
||||
.getServer()
|
||||
.getLogger()
|
||||
.warning("[PlayTimes] Couldn't connect to Database!");
|
||||
}
|
||||
}
|
||||
|
||||
private UsersTable getUsersTable() {
|
||||
if (this.usersTable == null) {
|
||||
this.usersTable = new UsersTable(dataSource);
|
||||
}
|
||||
return this.usersTable;
|
||||
}
|
||||
|
||||
public boolean retrievePlaytime(UUID uuid) {
|
||||
Map<String, Map<String, Long>> timeMap = getUsersTable()
|
||||
.getPlaytimesByUuid(uuid);
|
||||
if (timeMap != null && !timeMap.isEmpty()) {
|
||||
userPlaytimes.put(uuid, timeMap);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updatePlaytime(UUID uuid, Long playtime, Long afktime) {
|
||||
getUsersTable()
|
||||
.insertOrUpdate(uuid.toString(), serverId, playtime, afktime);
|
||||
|
||||
userPlaytimes
|
||||
.computeIfAbsent(uuid, k -> new HashMap<>())
|
||||
.computeIfAbsent(serverId, k -> new HashMap<>())
|
||||
.put("playtime", playtime);
|
||||
userPlaytimes.get(uuid).get(serverId).put("afktime", afktime);
|
||||
}
|
||||
|
||||
public boolean hasTimeForServer(UUID uuid, String server) {
|
||||
if (!userPlaytimes.containsKey(uuid)) {
|
||||
return retrievePlaytime(uuid);
|
||||
}
|
||||
return (
|
||||
userPlaytimes.containsKey(uuid) &&
|
||||
userPlaytimes.get(uuid).containsKey(server)
|
||||
);
|
||||
}
|
||||
|
||||
public boolean hasTimeForServer(UUID uuid) {
|
||||
return (hasTimeForServer(uuid, serverId));
|
||||
}
|
||||
|
||||
public Map<String, Long> getTimeForServer(UUID uuid, String server) {
|
||||
return userPlaytimes.get(uuid).get(server);
|
||||
}
|
||||
|
||||
public Map<String, Long> getTimeForServer(UUID uuid) {
|
||||
return getTimeForServer(uuid, serverId);
|
||||
}
|
||||
|
||||
public Long getTotalRawtime(UUID uuid) {
|
||||
Long rawtime = 0L;
|
||||
Map<String, Map<String, Long>> userTimeData = userPlaytimes.get(uuid);
|
||||
if (userTimeData != null) {
|
||||
for (Map.Entry<String, Map<String, Long>> entry : userTimeData.entrySet()) {
|
||||
String server = entry.getKey();
|
||||
Map<String, Long> serverData = entry.getValue();
|
||||
if (!server.equals(serverId)) {
|
||||
Long individualRawtime = serverData.getOrDefault("playtime", 0L);
|
||||
rawtime += individualRawtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
StatManager stats = StatManager.getInstance();
|
||||
Long currentServerRawtime =
|
||||
stats.getPlayerStat(uuid, StatisticType.PLAYTIME) / 20;
|
||||
rawtime += currentServerRawtime;
|
||||
return rawtime;
|
||||
}
|
||||
|
||||
public Long getTotalAfktime(UUID uuid) {
|
||||
Long afktime = 0L;
|
||||
Map<String, Map<String, Long>> userTimeData = userPlaytimes.get(uuid);
|
||||
if (userTimeData != null) {
|
||||
for (Map.Entry<String, Map<String, Long>> entry : userTimeData.entrySet()) {
|
||||
String server = entry.getKey();
|
||||
Map<String, Long> serverData = entry.getValue();
|
||||
if (!server.equals(serverId)) {
|
||||
Long individualAfktime = serverData.getOrDefault("afktime", 0L);
|
||||
afktime += individualAfktime;
|
||||
}
|
||||
}
|
||||
}
|
||||
long currentServerAfkTime = AFKManager.getInstance().getAFKTime(uuid);
|
||||
afktime += currentServerAfkTime;
|
||||
return afktime;
|
||||
}
|
||||
|
||||
// Calculate the total playtime after subtracting total afktime
|
||||
public Long getTotalPlaytime(UUID uuid) {
|
||||
Long totalPlaytime = 0L;
|
||||
Long totalAfktime = 0L;
|
||||
|
||||
Map<String, Map<String, Long>> userTimeData = userPlaytimes.get(uuid);
|
||||
|
||||
if (userTimeData != null) {
|
||||
for (Map.Entry<String, Map<String, Long>> entry : userTimeData.entrySet()) {
|
||||
String server = entry.getKey();
|
||||
Map<String, Long> serverData = entry.getValue();
|
||||
|
||||
if (!server.equals(serverId)) {
|
||||
totalPlaytime += serverData.getOrDefault("playtime", 0L);
|
||||
totalAfktime += serverData.getOrDefault("afktime", 0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatManager stats = StatManager.getInstance();
|
||||
Long currentServerPlaytime =
|
||||
stats.getPlayerStat(uuid, StatisticType.PLAYTIME) / 20;
|
||||
long afkTime = AFKManager.getInstance().getAFKTime(uuid);
|
||||
|
||||
totalPlaytime += currentServerPlaytime;
|
||||
totalAfktime += afkTime;
|
||||
|
||||
return totalPlaytime - totalAfktime;
|
||||
}
|
||||
|
||||
public void purgeOldPlaytimeData() {
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.info("[PlayTimes] Initiating purge of outdated playtime data...");
|
||||
|
||||
int months = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getInt("purge-database.months", 12);
|
||||
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.info(
|
||||
String.format(
|
||||
"[PlayTimes] Purging playtime data for server ID '%s' that is older than %d months.",
|
||||
serverId,
|
||||
months
|
||||
)
|
||||
);
|
||||
this.usersTable.purgeOldPlaytimes(serverId, months);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package me.codedred.playtimes.data.database.table;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.database.datasource.DataSource;
|
||||
import me.codedred.playtimes.utils.Async;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class UsersTable {
|
||||
|
||||
private static final String TABLE_NAME = "playtimes";
|
||||
private final DataSource dataSource;
|
||||
|
||||
public UsersTable(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
public void createTable() {
|
||||
String createTableSql = String.format(
|
||||
"CREATE TABLE IF NOT EXISTS `%s` (" +
|
||||
"`uniqueId` VARCHAR(36) NOT NULL," +
|
||||
"`serverId` VARCHAR(255) NOT NULL," +
|
||||
"`playtime` BIGINT NOT NULL DEFAULT 0," +
|
||||
"`afktime` BIGINT NOT NULL DEFAULT 0," +
|
||||
"`lastUpdated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
|
||||
"PRIMARY KEY (`uniqueId`, `serverId`))",
|
||||
TABLE_NAME
|
||||
);
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(
|
||||
createTableSql
|
||||
)
|
||||
) {
|
||||
preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void insertOrUpdate(
|
||||
String uuid,
|
||||
String serverId,
|
||||
long playtime,
|
||||
long afktime
|
||||
) {
|
||||
Async.run(() -> {
|
||||
String query = String.format(
|
||||
"INSERT INTO `%s` (`uniqueId`, `serverId`, `playtime`, `afktime`) VALUES (?, ?, ?, ?) " +
|
||||
"ON DUPLICATE KEY UPDATE `playtime` = ?, `afktime` = ?",
|
||||
TABLE_NAME
|
||||
);
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(query)
|
||||
) {
|
||||
preparedStatement.setString(1, uuid);
|
||||
preparedStatement.setString(2, serverId);
|
||||
preparedStatement.setLong(3, playtime);
|
||||
preparedStatement.setLong(4, afktime);
|
||||
preparedStatement.setLong(5, playtime);
|
||||
preparedStatement.setLong(6, afktime);
|
||||
|
||||
preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Map<String, Map<String, Long>> getPlaytimesByUuid(UUID uuid) {
|
||||
Map<String, Map<String, Long>> timesMap = new HashMap<>();
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(
|
||||
String.format("SELECT * FROM `%s` WHERE `uniqueId` = ?", TABLE_NAME)
|
||||
)
|
||||
) {
|
||||
preparedStatement.setString(1, uuid.toString());
|
||||
|
||||
try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
String serverId = resultSet.getString("serverId");
|
||||
long playtime = resultSet.getLong("playtime");
|
||||
long afktime = resultSet.getLong("afktime");
|
||||
|
||||
Map<String, Long> timeData = new HashMap<>();
|
||||
timeData.put("playtime", playtime);
|
||||
timeData.put("afktime", afktime);
|
||||
|
||||
timesMap.put(serverId, timeData);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return timesMap;
|
||||
}
|
||||
|
||||
public Map<String, Timestamp> getLastUpdatedTimesByUuid(UUID uuid) {
|
||||
Map<String, Timestamp> lastUpdatedTimes = new HashMap<>();
|
||||
|
||||
String query = String.format(
|
||||
"SELECT `serverId`, `lastUpdated` FROM `%s` WHERE `uniqueId` = ?",
|
||||
TABLE_NAME
|
||||
);
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(query)
|
||||
) {
|
||||
preparedStatement.setString(1, uuid.toString());
|
||||
|
||||
try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
String serverId = resultSet.getString("serverId");
|
||||
Timestamp lastUpdated = resultSet.getTimestamp("lastUpdated");
|
||||
lastUpdatedTimes.put(serverId, lastUpdated);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return lastUpdatedTimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes rows from the database where the last update was more than the specified number of months ago.
|
||||
*
|
||||
* @param serverId The server ID to match rows.
|
||||
* @param months The number of months to check for old data.
|
||||
*/
|
||||
public void purgeOldPlaytimes(String serverId, int months) {
|
||||
Async.run(() -> {
|
||||
String query = String.format(
|
||||
"DELETE FROM `%s` WHERE `serverId` = ? AND `lastUpdated` < (NOW() - INTERVAL ? MONTH)",
|
||||
TABLE_NAME
|
||||
);
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(query)
|
||||
) {
|
||||
preparedStatement.setString(1, serverId);
|
||||
preparedStatement.setInt(2, months);
|
||||
|
||||
int deletedRows = preparedStatement.executeUpdate();
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.info(
|
||||
"[PlayTimes] Deleted " +
|
||||
deletedRows +
|
||||
" rows for serverId " +
|
||||
serverId +
|
||||
" older than " +
|
||||
months +
|
||||
" months."
|
||||
);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package me.codedred.playtimes.holograms;
|
||||
|
||||
public enum HoloType {
|
||||
|
||||
CUSTOM,
|
||||
TOP10,
|
||||
TOP5,
|
||||
TOP3
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package me.codedred.playtimes.holograms;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Hologram {
|
||||
|
||||
private List<String> lines;
|
||||
|
||||
private HoloType type;
|
||||
|
||||
private Location location;
|
||||
|
||||
public Hologram() {
|
||||
lines = new ArrayList<>();
|
||||
type = HoloType.CUSTOM;
|
||||
location = null;
|
||||
}
|
||||
|
||||
private void setLocation(Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public Location getLocation(Location location) {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void addLine(String line) {
|
||||
lines.add(line);
|
||||
}
|
||||
|
||||
public void setLines(List<String> lines) {
|
||||
this.lines = lines;
|
||||
}
|
||||
|
||||
public List<String> getLines() {
|
||||
return lines;
|
||||
}
|
||||
|
||||
public void setType(HoloType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public HoloType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,31 +1,79 @@
|
||||
package me.codedred.playtimes.listeners;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class Join implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (data.getData().contains("blocked." + event.getPlayer().getName().toLowerCase()))
|
||||
return;
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
if (!data.getData().contains("leaderboard." + uuid)) {
|
||||
long time = StatManager.getInstance().getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
data.getData().set("leaderboard." + uuid, time);
|
||||
data.saveData();
|
||||
}
|
||||
// Database
|
||||
if (data.hasDatabase()) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.retrievePlaytime(uuid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// hacky bug fix that will update data again if database query was too slow.
|
||||
// this bug only arises when switching servers super fast!
|
||||
Bukkit
|
||||
.getScheduler()
|
||||
.runTaskLaterAsynchronously(
|
||||
PlayTimes.getPlugin(PlayTimes.class),
|
||||
() -> {
|
||||
dbManager.retrievePlaytime(uuid);
|
||||
},
|
||||
20L * 30
|
||||
);
|
||||
}
|
||||
|
||||
// Leaderboard
|
||||
if (
|
||||
data
|
||||
.getData()
|
||||
.contains("blocked." + event.getPlayer().getName().toLowerCase())
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationSection leaderboardSection = data
|
||||
.getData()
|
||||
.getConfigurationSection("leaderboard");
|
||||
|
||||
if (leaderboardSection == null) {
|
||||
leaderboardSection = data.getData().createSection("leaderboard");
|
||||
}
|
||||
|
||||
if (leaderboardSection.contains(uuid.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
long time = StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
|
||||
if (
|
||||
!data.getConfig().getBoolean("top-playtime.track-rawtime", false) &&
|
||||
data.hasAfkEnabled()
|
||||
) {
|
||||
time -=
|
||||
AFKManager.getInstance().getAFKTime(event.getPlayer().getUniqueId()) *
|
||||
20;
|
||||
}
|
||||
|
||||
leaderboardSection.set(uuid.toString(), time);
|
||||
|
||||
data.saveData();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,65 @@
|
||||
package me.codedred.playtimes.listeners;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class Quit implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (data.getData().contains("blocked." + event.getPlayer().getName().toLowerCase()))
|
||||
return;
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
long time = StatManager.getInstance().getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
data.getData().set("leaderboard." + uuid, time);
|
||||
data.saveData();
|
||||
}
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
// Database
|
||||
if (data.hasDatabase()) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.updatePlaytime(
|
||||
uuid,
|
||||
StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(uuid, StatisticType.PLAYTIME) /
|
||||
20,
|
||||
AFKManager.getInstance().getAFKTime(uuid)
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Save AFK time in data.yml
|
||||
CompletableFuture.runAsync(() -> {
|
||||
data
|
||||
.getData()
|
||||
.set("afktime." + uuid, AFKManager.getInstance().getAFKTime(uuid));
|
||||
data.saveData();
|
||||
});
|
||||
}
|
||||
|
||||
// Leaderboard
|
||||
String playerName = event.getPlayer().getName().toLowerCase();
|
||||
if (data.getData().contains("blocked." + playerName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Run leaderboard update
|
||||
CompletableFuture.runAsync(() -> {
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
long playtime = statManager.getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
if (
|
||||
!data.getConfig().getBoolean("top-playtime.track-rawtime", false) &&
|
||||
data.hasAfkEnabled()
|
||||
) {
|
||||
playtime -= AFKManager.getInstance().getAFKTime(uuid) * 20;
|
||||
}
|
||||
|
||||
data.getData().set("leaderboard." + uuid, playtime);
|
||||
data.saveData();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,123 @@
|
||||
package me.codedred.playtimes.models;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Leaderboard {
|
||||
|
||||
/***
|
||||
* Grabs the uuids from the data file, sorts them, then removes redundant uuids and updates the top 10
|
||||
* @return listing of top 10 players
|
||||
*/
|
||||
public Map<String, Integer> getTopTen() {
|
||||
Map<String, Integer> topTen = new LinkedHashMap<>();
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard"))
|
||||
return topTen;
|
||||
for (String key : data.getData().getConfigurationSection("leaderboard").getKeys(false))
|
||||
topTen.put(key, Integer.valueOf(data.getData().getString("leaderboard." + key)));
|
||||
final String LEADERBOARD = "leaderboard";
|
||||
|
||||
private static final Map<String, Integer> cachedLeaderboard = java.util.Collections.synchronizedMap(new LinkedHashMap<>());
|
||||
private static long lastCacheUpdate = 0;
|
||||
private static final long CACHE_DURATION = 30000; // 30 seconds
|
||||
|
||||
List<Map.Entry<String, Integer>> list = new LinkedList<>(topTen.entrySet());
|
||||
list.sort((o1, o2) -> o2.getValue() - o1.getValue());
|
||||
|
||||
if (list.size() > 20) {
|
||||
List<Map.Entry<String, Integer>> delList = list.subList(20, list.size());
|
||||
|
||||
for (Map.Entry<String, Integer> key : delList)
|
||||
data.getData().set("leaderboard." + key.getKey(), null);
|
||||
data.saveData();
|
||||
}
|
||||
|
||||
if (list.size() > 9)
|
||||
list = list.subList(0, 10);
|
||||
|
||||
topTen.clear();
|
||||
|
||||
for (Map.Entry<String, Integer> aList : list)
|
||||
topTen.put(aList.getKey(), aList.getValue());
|
||||
|
||||
topTen = updateTimes(topTen);
|
||||
return topTen;
|
||||
/**
|
||||
* Grabs the uuids from the data file, sorts them, then removes redundant uuids and updates the top 10
|
||||
*
|
||||
* @return listing of top 10 players
|
||||
*/
|
||||
public Map<String, Integer> getTopTen() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
if (currentTime - lastCacheUpdate < CACHE_DURATION && !cachedLeaderboard.isEmpty()) {
|
||||
return new LinkedHashMap<>(cachedLeaderboard);
|
||||
}
|
||||
|
||||
Map<String, Integer> topTen = generateTopTen();
|
||||
|
||||
cachedLeaderboard.clear();
|
||||
cachedLeaderboard.putAll(topTen);
|
||||
lastCacheUpdate = currentTime;
|
||||
|
||||
return topTen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces cache invalidation and regenerates the leaderboard
|
||||
*/
|
||||
public static void invalidateCache() {
|
||||
lastCacheUpdate = 0;
|
||||
cachedLeaderboard.clear();
|
||||
}
|
||||
|
||||
private Map<String, Integer> generateTopTen() {
|
||||
Map<String, Integer> allUsers = new LinkedHashMap<>();
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard")) {
|
||||
return allUsers;
|
||||
}
|
||||
|
||||
for (String key : data
|
||||
.getData()
|
||||
.getConfigurationSection(LEADERBOARD)
|
||||
.getKeys(false)) {
|
||||
allUsers.put(
|
||||
key,
|
||||
Integer.valueOf(data.getData().getString(LEADERBOARD + "." + key))
|
||||
);
|
||||
}
|
||||
|
||||
/***
|
||||
* Updates the top ten times.
|
||||
* Need to find better solution eventually.
|
||||
* @param topTen - Map of top ten uuids and times
|
||||
* @return updated map
|
||||
*/
|
||||
private Map<String, Integer> updateTimes(Map<String, Integer> topTen) {
|
||||
Map<String, Integer> updatedUsers = updateAllUserTimes(allUsers);
|
||||
|
||||
List<Map.Entry<String, Integer>> list = new ArrayList<>(updatedUsers.entrySet());
|
||||
list.sort(Map.Entry.<String, Integer>comparingByValue().reversed());
|
||||
|
||||
StatManager stats = StatManager.getInstance();
|
||||
topTen.replaceAll((u, v) -> (int) stats.getPlayerStat(UUID.fromString(u), StatisticType.PLAYTIME));
|
||||
if (list.size() > 20) {
|
||||
List<Map.Entry<String, Integer>> delList = list.subList(20, list.size());
|
||||
|
||||
List<Map.Entry<String, Integer>> list = new LinkedList<>(topTen.entrySet());
|
||||
list.sort((o1, o2) -> o2.getValue() - o1.getValue());
|
||||
for (Map.Entry<String, Integer> key : delList) {
|
||||
data.getData().set(LEADERBOARD + "." + key.getKey(), null);
|
||||
}
|
||||
data.saveData();
|
||||
|
||||
list = list.subList(0, 20);
|
||||
}
|
||||
|
||||
topTen.clear();
|
||||
Map<String, Integer> topTen = new LinkedHashMap<>();
|
||||
int count = Math.min(list.size(), 10);
|
||||
for (int i = 0; i < count; i++) {
|
||||
Map.Entry<String, Integer> entry = list.get(i);
|
||||
topTen.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Integer> aList : list)
|
||||
topTen.put(aList.getKey(), aList.getValue());
|
||||
|
||||
return topTen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return topTen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all users' times by querying the latest times from the StatManager.
|
||||
*
|
||||
* @param allUsers all users with their cached playtime data
|
||||
* @return updated map with current playtime data
|
||||
*/
|
||||
private Map<String, Integer> updateAllUserTimes(Map<String, Integer> allUsers) {
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
Map<String, Integer> updatedUsers = new LinkedHashMap<>();
|
||||
|
||||
for (Map.Entry<String, Integer> entry : allUsers.entrySet()) {
|
||||
String uuid = entry.getKey();
|
||||
int latestTime = (int) statManager.getPlayerStat(
|
||||
UUID.fromString(uuid),
|
||||
StatisticType.PLAYTIME
|
||||
);
|
||||
|
||||
if (
|
||||
!dataManager
|
||||
.getConfig()
|
||||
.getBoolean("top-playtime.track-rawtime", false) &&
|
||||
dataManager.hasAfkEnabled()
|
||||
) {
|
||||
latestTime -=
|
||||
AFKManager.getInstance().getAFKTime(UUID.fromString(uuid)) * 20;
|
||||
}
|
||||
|
||||
updatedUsers.put(uuid, latestTime);
|
||||
}
|
||||
|
||||
return updatedUsers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package me.codedred.playtimes.models;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import me.codedred.playtimes.utils.PAPIHolders;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class Message {
|
||||
|
||||
private final CommandSender sender;
|
||||
private final UUID targetUUID;
|
||||
private final String targetName;
|
||||
private List<String> message;
|
||||
|
||||
private final DataManager dataManager;
|
||||
private final StatManager statManager;
|
||||
private final TimeManager timeManager;
|
||||
|
||||
/**
|
||||
* Constructor for Message.
|
||||
* Initializes the message for the target player.
|
||||
*
|
||||
* @param sender The command sender.
|
||||
* @param targetUUID The UUID of the offline player.
|
||||
* @param targetName The name of the offline player.
|
||||
*/
|
||||
public Message(CommandSender sender, UUID targetUUID, String targetName) {
|
||||
this.sender = sender;
|
||||
this.targetUUID = targetUUID;
|
||||
this.targetName = targetName;
|
||||
|
||||
this.dataManager = DataManager.getInstance();
|
||||
this.statManager = StatManager.getInstance();
|
||||
this.timeManager = TimeManager.getInstance();
|
||||
|
||||
this.message = buildMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the message to be sent to the sender about the target player.
|
||||
* This involves fetching playtime statistics, formatting them,
|
||||
* and applying any necessary replacements and PlaceholderAPI placeholders.
|
||||
*
|
||||
* @return A list of formatted strings representing the message.
|
||||
*/
|
||||
private List<String> buildMessage() {
|
||||
List<String> builtMessage = dataManager
|
||||
.getConfig()
|
||||
.getStringList("playtime.message");
|
||||
long rawTime = statManager.getPlayerStat(
|
||||
targetUUID,
|
||||
StatisticType.PLAYTIME
|
||||
);
|
||||
long afkTime = AFKManager.getInstance().getAFKTime(targetUUID);
|
||||
|
||||
if (dataManager.hasDatabase()) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.updatePlaytime(targetUUID, rawTime / 20, afkTime);
|
||||
}
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
builtMessage = applyPAPIPlaceholders(builtMessage);
|
||||
}
|
||||
|
||||
return processMessageWithReplacements(
|
||||
builtMessage,
|
||||
prepareReplacements(rawTime, afkTime)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies PlaceholderAPI placeholders to the message if available.
|
||||
*
|
||||
* @param message The message list to process.
|
||||
* @return A list of messages with placeholders applied.
|
||||
*/
|
||||
private List<String> applyPAPIPlaceholders(List<String> message) {
|
||||
List<String> papiMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
papiMessage.add(
|
||||
PAPIHolders.getHolders(Bukkit.getOfflinePlayer(targetUUID), msg)
|
||||
);
|
||||
}
|
||||
return papiMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a map of replacements to be used in the message.
|
||||
*
|
||||
* @param rawTime The playtime statistic to format and include in the replacements.
|
||||
* @param afkTime The afktime statistic to format and include in the replacements.
|
||||
* @return A map of placeholder keys and their replacement values.
|
||||
*/
|
||||
private Map<String, String> prepareReplacements(long rawTime, long afkTime) {
|
||||
Map<String, String> replacements = new HashMap<>();
|
||||
replacements.put("%time%", timeManager.buildFormat(rawTime / 20 - afkTime));
|
||||
replacements.put(
|
||||
"%playtime%",
|
||||
timeManager.buildFormat(rawTime / 20 - afkTime)
|
||||
);
|
||||
replacements.put("%rawtime%", timeManager.buildFormat(rawTime / 20));
|
||||
replacements.put("%afktime%", timeManager.buildFormat(afkTime));
|
||||
replacements.put("%player%", targetName);
|
||||
replacements.put(
|
||||
"%timesjoined%",
|
||||
Long.toString(
|
||||
statManager.getPlayerStat(targetUUID, StatisticType.TIMES_JOINED)
|
||||
)
|
||||
);
|
||||
replacements.put("%joindate%", statManager.getJoinDate(targetUUID));
|
||||
|
||||
if (dataManager.hasDatabase()) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
|
||||
long globalPlaytime = dbManager.getTotalPlaytime(targetUUID);
|
||||
long globalRawtime = dbManager.getTotalRawtime(targetUUID);
|
||||
long globalAfktime = dbManager.getTotalAfktime(targetUUID);
|
||||
|
||||
replacements.put(
|
||||
"%global_playtime%",
|
||||
timeManager.buildFormat(globalPlaytime)
|
||||
);
|
||||
replacements.put(
|
||||
"%global_rawtime%",
|
||||
timeManager.buildFormat(globalRawtime)
|
||||
);
|
||||
replacements.put(
|
||||
"%global_afktime%",
|
||||
timeManager.buildFormat(globalAfktime)
|
||||
);
|
||||
}
|
||||
|
||||
return replacements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the message by applying the necessary replacements.
|
||||
*
|
||||
* @param message The original message.
|
||||
* @param replacements The map of placeholders and their replacements.
|
||||
* @return A list of processed messages.
|
||||
*/
|
||||
private List<String> processMessageWithReplacements(
|
||||
List<String> message,
|
||||
Map<String, String> replacements
|
||||
) {
|
||||
List<String> newMessage = new ArrayList<>();
|
||||
boolean hasDatabase = dataManager.hasDatabase();
|
||||
DatabaseManager dbManager = hasDatabase
|
||||
? DatabaseManager.getInstance()
|
||||
: null;
|
||||
Pattern pattern = Pattern.compile("%(rawtime|afktime|playtime)_(\\w+)%");
|
||||
|
||||
for (String msg : message) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
if (hasDatabase && dbManager != null) {
|
||||
Matcher matcher = pattern.matcher(msg);
|
||||
while (matcher.find()) {
|
||||
String placeholderType = matcher.group(1);
|
||||
String serverId = matcher.group(2);
|
||||
Long timeValue = 0L;
|
||||
|
||||
if (dbManager.hasTimeForServer(targetUUID, serverId)) {
|
||||
Map<String, Long> timeForServer = dbManager.getTimeForServer(
|
||||
targetUUID,
|
||||
serverId
|
||||
);
|
||||
timeValue =
|
||||
timeForServer.getOrDefault(
|
||||
placeholderType.equals("rawtime")
|
||||
? "playtime"
|
||||
: placeholderType,
|
||||
0L
|
||||
);
|
||||
if (placeholderType.equals("playtime")) {
|
||||
timeValue -= timeForServer.getOrDefault("afktime", 0L);
|
||||
}
|
||||
}
|
||||
|
||||
matcher.appendReplacement(sb, timeManager.buildFormat(timeValue));
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
msg = sb.toString();
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : replacements.entrySet()) {
|
||||
msg =
|
||||
msg.replace(
|
||||
entry.getKey(),
|
||||
entry.getValue() != null ? entry.getValue() : entry.getKey()
|
||||
);
|
||||
}
|
||||
|
||||
newMessage.add(msg);
|
||||
}
|
||||
|
||||
return newMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the formatted message to the sender.
|
||||
* This method determines the appropriate method to send the message
|
||||
* (e.g., standard chat message or JSON formatted tellraw command).
|
||||
*/
|
||||
public void sendMessageToTarget() {
|
||||
for (String msg : message) {
|
||||
String formattedMsg = ChatUtil.format(msg);
|
||||
if (formattedMsg.contains("{\"text\":")) {
|
||||
Bukkit.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
"tellraw " + sender.getName() + " " + formattedMsg
|
||||
);
|
||||
} else {
|
||||
sender.sendMessage(formattedMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package me.codedred.playtimes.player;
|
||||
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import me.codedred.playtimes.utils.PAPIHolders;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class OfflinePlayer {
|
||||
|
||||
private final CommandSender sender;
|
||||
private final UUID target;
|
||||
private final String name;
|
||||
|
||||
private List<String> message = new ArrayList<>();
|
||||
|
||||
public OfflinePlayer(CommandSender sender, UUID target, String name) {
|
||||
this.target = target;
|
||||
this.sender = sender;
|
||||
this.name = name;
|
||||
buildMessage();
|
||||
}
|
||||
|
||||
private void buildMessage() {
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
|
||||
message = dataManager.getConfig().getStringList("playtime.message");
|
||||
|
||||
long rawTime = statManager.getPlayerStat(target, StatisticType.PLAYTIME);
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
org.bukkit.OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(target);
|
||||
List<String> papiMessage = new ArrayList<>();
|
||||
if (offlinePlayer != null) {
|
||||
for (String msg : message)
|
||||
papiMessage.add(PAPIHolders.getHolders(offlinePlayer, msg));
|
||||
message = papiMessage;
|
||||
}
|
||||
}
|
||||
String timeFormat = timeManager.buildFormat(rawTime/20);
|
||||
List<String> newMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
msg = StringUtils.replace(msg,"%time%", timeFormat);
|
||||
msg = StringUtils.replace(msg, "%player%", name);
|
||||
msg = StringUtils.replace(msg, "%timesjoined%", Long.toString(statManager.getPlayerStat(target, StatisticType.LEAVE)));
|
||||
msg = StringUtils.replace(msg, "%joindate%", statManager.getJoinDate(target));
|
||||
newMessage.add(msg);
|
||||
}
|
||||
message = newMessage;
|
||||
}
|
||||
|
||||
public void sendMessageToTarget() {
|
||||
for (String msg : message) {
|
||||
if (msg.contains("{\"text\":"))
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender + " " + ChatUtil.format(msg));
|
||||
else
|
||||
sender.sendMessage(ChatUtil.format(msg));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package me.codedred.playtimes.player;
|
||||
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import me.codedred.playtimes.utils.PAPIHolders;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class OnlinePlayer {
|
||||
|
||||
private final Player target;
|
||||
private List<String> message = new ArrayList<>();
|
||||
|
||||
public OnlinePlayer(Player target) {
|
||||
this.target = target;
|
||||
buildMessage();
|
||||
}
|
||||
|
||||
private void buildMessage() {
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
|
||||
message = dataManager.getConfig().getStringList("playtime.message");
|
||||
|
||||
long rawTime;
|
||||
if (statManager.isLegacy())
|
||||
rawTime = statManager.getPlayerStat(target.getUniqueId(), StatisticType.PLAYTIME);
|
||||
else
|
||||
rawTime = statManager.getStats().getOnlineStatistic(target, StatisticType.PLAYTIME);
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
List<String> papiMessage = new ArrayList<>();
|
||||
for (String msg : message)
|
||||
papiMessage.add(PAPIHolders.getHolders(target, msg));
|
||||
message = papiMessage;
|
||||
}
|
||||
String timeFormat = timeManager.buildFormat(rawTime/20);
|
||||
List<String> newMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
msg = StringUtils.replace(msg,"%time%", timeFormat);
|
||||
msg = StringUtils.replace(msg, "%player%", target.getName());
|
||||
msg = StringUtils.replace(msg, "%timesjoined%", Long.toString(statManager.getPlayerStat(target.getUniqueId(), StatisticType.LEAVE)));
|
||||
msg = StringUtils.replace(msg, "%joindate%", statManager.getJoinDate(target.getUniqueId()));
|
||||
newMessage.add(msg);
|
||||
}
|
||||
message = newMessage;
|
||||
}
|
||||
|
||||
public void sendMessageToTarget() {
|
||||
for (String msg : message) {
|
||||
if (msg.contains("{\"text\":"))
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + target + " " + ChatUtil.format(msg));
|
||||
else
|
||||
target.sendMessage(ChatUtil.format(msg));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,52 +1,95 @@
|
||||
package me.codedred.playtimes.server;
|
||||
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class ServerManager {
|
||||
private final static ServerManager instance = new ServerManager();
|
||||
|
||||
public static ServerManager getInstance() {
|
||||
return instance;
|
||||
private static final ServerManager instance = new ServerManager();
|
||||
|
||||
public enum LookUpTypes {
|
||||
OFFLINE,
|
||||
ONLINE,
|
||||
}
|
||||
|
||||
public static ServerManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ServerStatus status;
|
||||
private LookUpTypes lookupType = LookUpTypes.ONLINE;
|
||||
|
||||
public void register() {
|
||||
if (Bukkit.getOnlineMode()) {
|
||||
status = new ServerOnline();
|
||||
} else {
|
||||
status = new ServerOffline();
|
||||
}
|
||||
cleanLeaderboard();
|
||||
updateLookupType();
|
||||
}
|
||||
|
||||
private ServerStatus status;
|
||||
public ServerStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void register() {
|
||||
if (Bukkit.getOnlineMode())
|
||||
status = new ServerOnline();
|
||||
else
|
||||
status = new ServerOffline();
|
||||
cleanLeaderboard();
|
||||
public UUID getUUID(String name) {
|
||||
return getStatus().getUUID(name);
|
||||
}
|
||||
|
||||
public String getName(UUID uuid) throws IOException {
|
||||
return getStatus().getName(uuid);
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return getStatus().isOnline();
|
||||
}
|
||||
|
||||
public LookUpTypes lookupType() {
|
||||
return lookupType;
|
||||
}
|
||||
|
||||
public void updateLookupType() {
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
boolean databaseEnabled = dataManager
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled");
|
||||
|
||||
boolean isSetToOffline = dataManager
|
||||
.getConfig()
|
||||
.getString("uuid-lookups.type")
|
||||
.equalsIgnoreCase("offline");
|
||||
|
||||
boolean isSetToOnline = dataManager
|
||||
.getConfig()
|
||||
.getString("uuid-lookups.type")
|
||||
.equalsIgnoreCase("online");
|
||||
|
||||
boolean serverOnline = isOnline();
|
||||
|
||||
if (isSetToOnline) lookupType = LookUpTypes.ONLINE; else if (
|
||||
(!serverOnline && !databaseEnabled) || isSetToOffline
|
||||
) {
|
||||
lookupType = LookUpTypes.OFFLINE;
|
||||
} else {
|
||||
lookupType = LookUpTypes.ONLINE;
|
||||
}
|
||||
}
|
||||
|
||||
public ServerStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public UUID getUUID(String name) {
|
||||
return getStatus().getUUID(name);
|
||||
}
|
||||
|
||||
public String getName(UUID uuid) throws IOException {
|
||||
return getStatus().getName(uuid);
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return getStatus().isOnline();
|
||||
}
|
||||
|
||||
private void cleanLeaderboard() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard"))
|
||||
return;
|
||||
for (String key : data.getData().getConfigurationSection("leaderboard").getKeys(false)) {
|
||||
if (Bukkit.getServer().getOfflinePlayer(UUID.fromString(key)).getName() == null)
|
||||
data.getData().set("leaderboard." + key, null);
|
||||
}
|
||||
data.saveData();
|
||||
private void cleanLeaderboard() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard")) return;
|
||||
for (String key : data
|
||||
.getData()
|
||||
.getConfigurationSection("leaderboard")
|
||||
.getKeys(false)) {
|
||||
if (
|
||||
Bukkit.getServer().getOfflinePlayer(UUID.fromString(key)).getName() ==
|
||||
null
|
||||
) data.getData().set("leaderboard." + key, null);
|
||||
}
|
||||
data.saveData();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
package me.codedred.playtimes.server;
|
||||
|
||||
import com.google.gson.*;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -10,41 +9,92 @@ import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.server.ServerManager.LookUpTypes;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ServerOffline implements ServerStatus {
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try {
|
||||
InputStream is = new URL("https://api.mojang.com/users/profiles/minecraft/" + name).openStream();
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
String fixedName = rootobj.get("name").getAsString();
|
||||
is.close();
|
||||
UUID uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + fixedName).getBytes(StandardCharsets.UTF_8));
|
||||
if (!StatManager.getInstance().hasJoinedBefore(uuid))
|
||||
return null;
|
||||
return uuid;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
UUID offlineUUID = null;
|
||||
Player onlinePlayer = Bukkit.getServer().getPlayer(name);
|
||||
if (onlinePlayer != null) {
|
||||
offlineUUID = onlinePlayer.getUniqueId();
|
||||
}
|
||||
|
||||
if (offlineUUID == null) {
|
||||
OfflinePlayer offlinePlayers[] = Bukkit.getServer().getOfflinePlayers();
|
||||
int playerIndex = 0;
|
||||
while ((playerIndex < offlinePlayers.length) && (offlineUUID == null)) {
|
||||
if (offlinePlayers[playerIndex].getName().equalsIgnoreCase(name)) {
|
||||
offlineUUID = offlinePlayers[playerIndex].getUniqueId();
|
||||
}
|
||||
playerIndex = playerIndex + 1;
|
||||
}
|
||||
}
|
||||
if (offlineUUID != null) {
|
||||
return offlineUUID;
|
||||
} else {
|
||||
try (
|
||||
InputStream is = new URL(
|
||||
"https://api.mojang.com/users/profiles/minecraft/" + name
|
||||
)
|
||||
.openStream()
|
||||
) {
|
||||
BufferedReader rd = new BufferedReader(
|
||||
new InputStreamReader(is, StandardCharsets.UTF_8)
|
||||
);
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
UUID uuid;
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return false;
|
||||
}
|
||||
if (ServerManager.getInstance().lookupType() == LookUpTypes.OFFLINE) {
|
||||
String fixedName = rootobj.get("name").getAsString();
|
||||
uuid =
|
||||
UUID.nameUUIDFromBytes(
|
||||
("OfflinePlayer:" + fixedName).getBytes(StandardCharsets.UTF_8)
|
||||
);
|
||||
} else {
|
||||
String id = rootobj.get("id").getAsString();
|
||||
String uuidWithDashes = id.replaceAll(
|
||||
"(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})",
|
||||
"$1-$2-$3-$4-$5"
|
||||
);
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) throws JsonSyntaxException, IOException {
|
||||
try (InputStream is = new URL("https://mcapi.ca/player/profile/" + uuid).openStream()) {
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
|
||||
return rootobj.get("name").getAsString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "User Not Found";
|
||||
uuid = UUID.fromString(uuidWithDashes);
|
||||
}
|
||||
|
||||
if (!StatManager.getInstance().hasJoinedBefore(uuid)) {
|
||||
return null;
|
||||
}
|
||||
return uuid;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) throws IOException {
|
||||
try (
|
||||
InputStream is = new URL("https://mcapi.ca/player/profile/" + uuid)
|
||||
.openStream();
|
||||
BufferedReader rd = new BufferedReader(
|
||||
new InputStreamReader(is, StandardCharsets.UTF_8)
|
||||
)
|
||||
) {
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
return rootobj.get("name").getAsString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "User Not Found";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
package me.codedred.playtimes.server;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import com.google.gson.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -13,52 +8,43 @@ import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ServerOnline implements ServerStatus {
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
UUID uuid = Bukkit.getOfflinePlayer(name).getUniqueId();
|
||||
if (!StatManager.getInstance().hasJoinedBefore(uuid))
|
||||
return null;
|
||||
return uuid;
|
||||
@Override
|
||||
public UUID getUUID(@NotNull String name) {
|
||||
UUID uuid = Bukkit.getServer().getOfflinePlayer(name).getUniqueId();
|
||||
if (!StatManager.getInstance().hasJoinedBefore(uuid)) {
|
||||
return null;
|
||||
}
|
||||
return uuid;
|
||||
}
|
||||
|
||||
private UUID getMainThreadMojangUUID(String name) {
|
||||
try {
|
||||
InputStream is = new URL("https://api.mojang.com/users/profiles/minecraft/" + name).openStream();
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
String u = rootobj.get("id").getAsString();
|
||||
StringBuilder uuid = new StringBuilder();
|
||||
for (int i = 0; i <= 31; i++) {
|
||||
uuid.append(u.charAt(i));
|
||||
if (i == 7 || i == 11 || i == 15 || i == 19) {
|
||||
uuid.append("-");
|
||||
}
|
||||
}
|
||||
is.close();
|
||||
return UUID.fromString(uuid.toString());
|
||||
} catch (JsonSyntaxException | IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) throws JsonSyntaxException, IOException {
|
||||
try (InputStream is = new URL("https://mcapi.ca/player/profile/" + uuid).openStream()) {
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
|
||||
return rootobj.get("name").getAsString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "User Not Found";
|
||||
}
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) throws IOException {
|
||||
try (
|
||||
InputStream is = new URL("https://mcapi.ca/player/profile/" + uuid)
|
||||
.openStream()
|
||||
) {
|
||||
BufferedReader rd = new BufferedReader(
|
||||
new InputStreamReader(is, StandardCharsets.UTF_8)
|
||||
);
|
||||
JsonElement root = JsonParser.parseReader(rd);
|
||||
|
||||
JsonObject rootObj = root.getAsJsonObject();
|
||||
|
||||
return rootObj.get("name").getAsString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "User Not Found";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,9 @@ import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ServerStatus {
|
||||
public UUID getUUID(String name);
|
||||
|
||||
public UUID getUUID(String name);
|
||||
public boolean isOnline();
|
||||
public String getName(UUID uuid) throws IOException;
|
||||
public boolean isOnline();
|
||||
|
||||
public String getName(UUID uuid) throws IOException;
|
||||
}
|
||||
@@ -2,65 +2,66 @@ package me.codedred.playtimes.statistics;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LegacyStats implements Stats {
|
||||
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson().fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson()
|
||||
.fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
|
||||
switch(type) {
|
||||
case PLAYTIME:
|
||||
return jsonObject.get("stat.playOneMinute").getAsLong();
|
||||
case LEAVE:
|
||||
return jsonObject.get("stat.leaveGame").getAsLong();
|
||||
case REST:
|
||||
return jsonObject.get("stat.timeSinceDeath").getAsLong();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
return jsonObject.get("stat.playOneMinute").getAsLong();
|
||||
case TIMES_JOINED:
|
||||
return jsonObject.get("stat.leaveGame").getAsLong();
|
||||
}
|
||||
return 0;
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
return getPlayerStatistic(player.getUniqueId(), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
} else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
return getPlayerStatistic(player.getUniqueId(), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DataManager.getInstance().getConfig().getString("date-format"));
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -2,82 +2,83 @@ package me.codedred.playtimes.statistics;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class RisenStats implements Stats {
|
||||
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
if (Bukkit.getPlayer(uuid) != null)
|
||||
return getOnlineStatistic(Bukkit.getPlayer(uuid), type);
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
if (Bukkit.getPlayer(uuid) != null) return getOnlineStatistic(
|
||||
Bukkit.getPlayer(uuid),
|
||||
type
|
||||
);
|
||||
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson()
|
||||
.fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
JsonObject pilot = (JsonObject) jsonObject.get("stats");
|
||||
JsonObject passenger = (JsonObject) pilot.get("minecraft:custom");
|
||||
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson().fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
|
||||
JsonObject pilot = (JsonObject) jsonObject.get("stats");
|
||||
JsonObject passenger = (JsonObject) pilot.get("minecraft:custom");
|
||||
|
||||
switch(type) {
|
||||
case PLAYTIME:
|
||||
if (passenger.get("minecraft:play_time") == null)
|
||||
return passenger.get("minecraft:play_one_minute").getAsLong();
|
||||
return passenger.get("minecraft:play_time").getAsLong();
|
||||
case LEAVE:
|
||||
return passenger.get("minecraft:leave_game").getAsLong();
|
||||
case REST:
|
||||
return passenger.get("minecraft:time_since_rest").getAsLong();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
if (passenger.get("minecraft:play_time") == null) return passenger
|
||||
.get("minecraft:play_one_minute")
|
||||
.getAsLong();
|
||||
return passenger.get("minecraft:play_time").getAsLong();
|
||||
case TIMES_JOINED:
|
||||
return passenger.get("minecraft:leave_game").getAsLong();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
return player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case TIMES_JOINED:
|
||||
return player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
switch(type) {
|
||||
case PLAYTIME:
|
||||
return player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case REST:
|
||||
return player.getStatistic(Statistic.TIME_SINCE_REST);
|
||||
case LEAVE:
|
||||
return player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
}
|
||||
return 0;
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
} else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DataManager.getInstance().getConfig().getString("date-format"));
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -2,79 +2,80 @@ package me.codedred.playtimes.statistics;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class RisingStats implements Stats {
|
||||
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
if (Bukkit.getPlayer(uuid) != null)
|
||||
return getOnlineStatistic(Bukkit.getPlayer(uuid), type);
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
if (Bukkit.getPlayer(uuid) != null) return getOnlineStatistic(
|
||||
Bukkit.getPlayer(uuid),
|
||||
type
|
||||
);
|
||||
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson().fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson()
|
||||
.fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
JsonObject pilot = (JsonObject) jsonObject.get("stats");
|
||||
JsonObject passenger = (JsonObject) pilot.get("minecraft:custom");
|
||||
|
||||
JsonObject pilot = (JsonObject) jsonObject.get("stats");
|
||||
JsonObject passenger = (JsonObject) pilot.get("minecraft:custom");
|
||||
|
||||
switch(type) {
|
||||
case PLAYTIME:
|
||||
return passenger.get("minecraft:play_one_minute").getAsLong();
|
||||
case LEAVE:
|
||||
return passenger.get("minecraft:leave_game").getAsLong();
|
||||
case REST:
|
||||
return passenger.get("minecraft:time_since_rest").getAsLong();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
return passenger.get("minecraft:play_one_minute").getAsLong();
|
||||
case TIMES_JOINED:
|
||||
return passenger.get("minecraft:leave_game").getAsLong();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
return player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case TIMES_JOINED:
|
||||
return player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
switch(type) {
|
||||
case PLAYTIME:
|
||||
return player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case REST:
|
||||
return player.getStatistic(Statistic.TIME_SINCE_REST);
|
||||
case LEAVE:
|
||||
return player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
}
|
||||
return 0;
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
} else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DataManager.getInstance().getConfig().getString("date-format"));
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -1,60 +1,69 @@
|
||||
package me.codedred.playtimes.statistics;
|
||||
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
|
||||
public class StatManager {
|
||||
|
||||
private final static StatManager instance = new StatManager();
|
||||
private static final StatManager instance = new StatManager();
|
||||
|
||||
public static StatManager getInstance() {
|
||||
return instance;
|
||||
public static StatManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Stats stats;
|
||||
private boolean legacy = false;
|
||||
|
||||
public String name;
|
||||
|
||||
public void registerStatistics() {
|
||||
if (ServerUtils.isRisenVersion()) {
|
||||
stats = new RisenStats();
|
||||
name = "Risen";
|
||||
} else if (ServerUtils.isNewerVersion()) {
|
||||
stats = new RisingStats();
|
||||
name = "Rising";
|
||||
} else {
|
||||
stats = new LegacyStats();
|
||||
setLegacy();
|
||||
name = "Legacy";
|
||||
}
|
||||
}
|
||||
|
||||
private Stats stats;
|
||||
private boolean legacy = false;
|
||||
public Stats getStats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
public void registerStatistics() {
|
||||
if (ServerUtils.isRisenVersion())
|
||||
stats = new RisenStats();
|
||||
else if (ServerUtils.isNewerVersion())
|
||||
stats = new RisingStats();
|
||||
else {
|
||||
stats = new LegacyStats();
|
||||
setLegacy();
|
||||
}
|
||||
}
|
||||
public long getPlayerStat(UUID uuid, StatisticType type) {
|
||||
return getStats().getPlayerStatistic(uuid, type);
|
||||
}
|
||||
|
||||
public Stats getStats() {
|
||||
return stats;
|
||||
}
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
return getStats().hasJoinedBefore(uuid);
|
||||
}
|
||||
|
||||
public long getPlayerStat(UUID uuid, StatisticType type) {
|
||||
return getStats().getPlayerStatistic(uuid, type);
|
||||
}
|
||||
public String getJoinDate(UUID uuid) {
|
||||
return getStats().getJoinDate(uuid);
|
||||
}
|
||||
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
return getStats().hasJoinedBefore(uuid);
|
||||
}
|
||||
private void setLegacy() {
|
||||
legacy = true;
|
||||
}
|
||||
|
||||
public String getJoinDate(UUID uuid) {
|
||||
return getStats().getJoinDate(uuid);
|
||||
}
|
||||
|
||||
private void setLegacy() {
|
||||
legacy = true;
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return legacy;
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return TimeManager.getInstance().buildFormat((int) TimeUnit.MILLISECONDS.toSeconds(ManagementFactory.getRuntimeMXBean().getUptime()));
|
||||
}
|
||||
public boolean isLegacy() {
|
||||
return legacy;
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return TimeManager
|
||||
.getInstance()
|
||||
.buildFormat(
|
||||
(int) TimeUnit.MILLISECONDS.toSeconds(
|
||||
ManagementFactory.getRuntimeMXBean().getUptime()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
package me.codedred.playtimes.statistics;
|
||||
|
||||
public enum StatisticType {
|
||||
|
||||
// todo add monthly/weekly/daily times
|
||||
|
||||
PLAYTIME,
|
||||
LEAVE,
|
||||
REST
|
||||
|
||||
PLAYTIME,
|
||||
TIMES_JOINED,
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
package me.codedred.playtimes.statistics;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface Stats {
|
||||
long getPlayerStatistic(UUID uuid, StatisticType type);
|
||||
boolean hasJoinedBefore(UUID uuid);
|
||||
String getJoinDate(UUID uuid);
|
||||
long getOnlineStatistic(Player player, StatisticType type);
|
||||
|
||||
long getPlayerStatistic(UUID uuid, StatisticType type);
|
||||
boolean hasJoinedBefore(UUID uuid);
|
||||
String getJoinDate(UUID uuid);
|
||||
long getOnlineStatistic(Player player, StatisticType type);
|
||||
|
||||
File worldFolder = new File(Bukkit.getServer().getWorlds().get(0).getWorldFolder(), "stats");
|
||||
File worldFolder = new File(
|
||||
Bukkit.getServer().getWorlds().get(0).getWorldFolder(),
|
||||
"stats"
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package me.codedred.playtimes.time;
|
||||
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class TimeConstants {
|
||||
|
||||
private static String second, seconds, minute, minutes, hour, hours, day, days;
|
||||
private static boolean rounded;
|
||||
|
||||
static {
|
||||
reload();
|
||||
}
|
||||
|
||||
public static void reload() {
|
||||
FileConfiguration data = DataManager.getInstance().getConfig();
|
||||
second = data.getString("playtime.name.second");
|
||||
seconds = data.getString("playtime.name.seconds");
|
||||
minute = data.getString("playtime.name.minute");
|
||||
minutes = data.getString("playtime.name.minutes");
|
||||
hour = data.getString("playtime.name.hour");
|
||||
hours = data.getString("playtime.name.hours");
|
||||
day = data.getString("playtime.name.day");
|
||||
days = data.getString("playtime.name.days");
|
||||
rounded = data.getBoolean("playtime.round-numbers");
|
||||
}
|
||||
|
||||
public static String getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public static String getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
public static String getMinute() {
|
||||
return minute;
|
||||
}
|
||||
|
||||
public static String getMinutes() {
|
||||
return minutes;
|
||||
}
|
||||
|
||||
public static String getHour() {
|
||||
return hour;
|
||||
}
|
||||
|
||||
public static String getHours() {
|
||||
return hours;
|
||||
}
|
||||
|
||||
public static String getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
public static String getDays() {
|
||||
return days;
|
||||
}
|
||||
|
||||
public static boolean getRounded() {
|
||||
return rounded;
|
||||
}
|
||||
}
|
||||
@@ -5,43 +5,43 @@ import me.codedred.playtimes.time.formats.*;
|
||||
|
||||
public class TimeManager {
|
||||
|
||||
private static final TimeManager instance = new TimeManager();
|
||||
private static final TimeManager instance = new TimeManager();
|
||||
|
||||
public static TimeManager getInstance() {
|
||||
return instance;
|
||||
public static TimeManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Timings timings;
|
||||
|
||||
public void registerTimings() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
if (data.getConfig().getBoolean("playtime.only-hours")) {
|
||||
timings = new OnlyHours();
|
||||
return;
|
||||
}
|
||||
|
||||
private Timings timings;
|
||||
|
||||
public void registerTimings() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
if (data.getConfig().getBoolean("playtime.only-hours")) {
|
||||
timings = new OnlyHours();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.getConfig().getBoolean("playtime.show-seconds")) {
|
||||
if (!data.getConfig().getBoolean("playtime.show-days")) {
|
||||
timings = new NoDaysNoSeconds();
|
||||
return;
|
||||
}
|
||||
timings = new NoSeconds();
|
||||
return;
|
||||
}
|
||||
if (!data.getConfig().getBoolean("playtime.show-days")) {
|
||||
timings = new NoDays();
|
||||
return;
|
||||
}
|
||||
|
||||
timings = new NativeFormat();
|
||||
if (!data.getConfig().getBoolean("playtime.show-seconds")) {
|
||||
if (!data.getConfig().getBoolean("playtime.show-days")) {
|
||||
timings = new NoDaysNoSeconds();
|
||||
return;
|
||||
}
|
||||
timings = new NoSeconds();
|
||||
return;
|
||||
}
|
||||
if (!data.getConfig().getBoolean("playtime.show-days")) {
|
||||
timings = new NoDays();
|
||||
return;
|
||||
}
|
||||
|
||||
private Timings getTimings() {
|
||||
return timings;
|
||||
}
|
||||
timings = new NativeFormat();
|
||||
}
|
||||
|
||||
public String buildFormat(long time) {
|
||||
return getTimings().buildFormat(time);
|
||||
}
|
||||
private Timings getTimings() {
|
||||
return timings;
|
||||
}
|
||||
|
||||
public String buildFormat(long time) {
|
||||
return getTimings().buildFormat(time);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package me.codedred.playtimes.time;
|
||||
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
|
||||
public interface TimeRegistry {
|
||||
|
||||
String SECOND = DataManager.getInstance().getConfig().getString("playtime.name.second");
|
||||
String SECONDS = DataManager.getInstance().getConfig().getString("playtime.name.seconds");
|
||||
String MINUTE = DataManager.getInstance().getConfig().getString("playtime.name.minute");
|
||||
String MINUTES = DataManager.getInstance().getConfig().getString("playtime.name.minutes");
|
||||
String HOUR = DataManager.getInstance().getConfig().getString("playtime.name.hour");
|
||||
String HOURS = DataManager.getInstance().getConfig().getString("playtime.name.hours");
|
||||
String DAY = DataManager.getInstance().getConfig().getString("playtime.name.day");
|
||||
String DAYS = DataManager.getInstance().getConfig().getString("playtime.name.days");
|
||||
|
||||
}
|
||||
@@ -1,40 +1,5 @@
|
||||
package me.codedred.playtimes.time;
|
||||
|
||||
public interface Timings extends TimeRegistry {
|
||||
|
||||
String buildFormat(long time);
|
||||
/*public static int getDays(long l) {
|
||||
if (l < 60) {
|
||||
return 0;
|
||||
}
|
||||
int minutes = (int) (l / 60);
|
||||
if (minutes < 1440)
|
||||
return 0;
|
||||
return minutes / 1440;
|
||||
}
|
||||
|
||||
public static int getHours(long l) {
|
||||
if (l < 60) {
|
||||
return 0;
|
||||
}
|
||||
int minutes = (int) (l / 60);
|
||||
if (minutes < 60)
|
||||
return 0;
|
||||
return minutes / 60;
|
||||
}
|
||||
|
||||
public static int getMins(long l) {
|
||||
if (l < 60) {
|
||||
return 0;
|
||||
}
|
||||
return (int) (l / 60);
|
||||
}
|
||||
|
||||
public static int getSecs(long l) {
|
||||
if (l <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return (int) (l);
|
||||
}*/
|
||||
|
||||
public interface Timings {
|
||||
String buildFormat(long time);
|
||||
}
|
||||
@@ -1,65 +1,70 @@
|
||||
package me.codedred.playtimes.time.formats;
|
||||
|
||||
import me.codedred.playtimes.time.TimeConstants;
|
||||
import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class NativeFormat implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60)
|
||||
return time + ( time == 1 ? SECONDS : SECOND);
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60) return formatSeconds(time);
|
||||
|
||||
int minutes = (int) (time / 60);
|
||||
int seconds = 60 * minutes;
|
||||
int secondsLeft = (int) (time - seconds);
|
||||
int minutes = (int) (time / 60);
|
||||
int secondsLeft = (int) (time % 60);
|
||||
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) {
|
||||
if (secondsLeft > 0)
|
||||
return minutes + (minutes == 1 ? MINUTE : MINUTES) + " " + secondsLeft + (secondsLeft == 1 ? SECOND : SECONDS);
|
||||
return minutes + (minutes == 1 ? MINUTE : MINUTES);
|
||||
}
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) return formatMinutes(minutes, secondsLeft);
|
||||
|
||||
String format;
|
||||
|
||||
// Time less than 1 Day
|
||||
if (minutes < 1440) {
|
||||
int hours = minutes / 60;
|
||||
format = hours + (hours == 1 ? HOUR : HOURS);
|
||||
int inMins = 60 * hours;
|
||||
int left = minutes - inMins;
|
||||
|
||||
if (left >= 1)
|
||||
format = format + " " + left + (left == 1 ? MINUTE : MINUTES);
|
||||
|
||||
if (secondsLeft > 0)
|
||||
format = format + " " + secondsLeft + (secondsLeft == 1 ? SECOND : SECONDS);
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
// Time greater than 1 day
|
||||
int days = minutes / 1440;
|
||||
format = days + (days == 1 ? DAY : DAYS);
|
||||
int inMins = 1440 * days;
|
||||
int leftOver = minutes - inMins;
|
||||
if (leftOver >= 1) {
|
||||
if (leftOver < 60) {
|
||||
format = format + " " + leftOver + (leftOver == 1 ? MINUTE : MINUTES);
|
||||
}
|
||||
else {
|
||||
int hours = leftOver / 60;
|
||||
format = format + " " + hours + (hours == 1 ? HOUR : HOURS);
|
||||
int hoursInMins = 60 * hours;
|
||||
int minsLeft = leftOver - hoursInMins;
|
||||
if (leftOver >= 1) {
|
||||
format = format + " " + minsLeft + (minsLeft == 1 ? MINUTE : MINUTES);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (secondsLeft > 0)
|
||||
format = format + " " + secondsLeft + (secondsLeft == 1 ? SECOND : SECONDS);
|
||||
return format;
|
||||
// Time less than 1 Day
|
||||
if (minutes < 1440) {
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
return formatHours(hours, minutesLeft, secondsLeft);
|
||||
}
|
||||
|
||||
// Time greater than 1 day
|
||||
int days = minutes / 1440;
|
||||
int minutesLeft = minutes % 1440;
|
||||
return formatDays(days, minutesLeft, secondsLeft);
|
||||
}
|
||||
|
||||
private String formatSeconds(long seconds) {
|
||||
return (
|
||||
seconds +
|
||||
(seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond())
|
||||
);
|
||||
}
|
||||
|
||||
private String formatMinutes(int minutes, int secondsLeft) {
|
||||
String format =
|
||||
minutes +
|
||||
(minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
if (secondsLeft > 0) format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
|
||||
private String formatHours(int hours, int minutesLeft, int secondsLeft) {
|
||||
String format =
|
||||
hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1) format +=
|
||||
formatMinutes(minutesLeft, secondsLeft); else if (
|
||||
secondsLeft > 0
|
||||
) format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
|
||||
private String formatDays(int days, int minutesLeft, int secondsLeft) {
|
||||
String format =
|
||||
days + (days == 1 ? TimeConstants.getDay() : TimeConstants.getDays());
|
||||
if (minutesLeft >= 60) {
|
||||
int hours = minutesLeft / 60;
|
||||
int minutesAfterHours = minutesLeft % 60;
|
||||
format += formatHours(hours, minutesAfterHours, secondsLeft);
|
||||
} else if (minutesLeft >= 1) {
|
||||
format += formatMinutes(minutesLeft, secondsLeft);
|
||||
} else if (secondsLeft > 0) {
|
||||
format += formatSeconds(secondsLeft);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,49 @@
|
||||
package me.codedred.playtimes.time.formats;
|
||||
|
||||
import me.codedred.playtimes.time.TimeConstants;
|
||||
import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class NoDays implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60)
|
||||
return time + ( time == 1 ? SECONDS : SECOND);
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60) return formatSeconds(time);
|
||||
|
||||
int minutes = (int) (time / 60);
|
||||
int seconds = 60 * minutes;
|
||||
int secondsLeft = (int) (time - seconds);
|
||||
int minutes = (int) (time / 60);
|
||||
int secondsLeft = (int) (time % 60);
|
||||
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) {
|
||||
if (secondsLeft > 0)
|
||||
return minutes + (minutes == 1 ? MINUTE : MINUTES) + " " + secondsLeft + (secondsLeft == 1 ? SECOND : SECONDS);
|
||||
return minutes + (minutes == 1 ? MINUTE : MINUTES);
|
||||
}
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) return formatMinutes(minutes, secondsLeft);
|
||||
|
||||
String format;
|
||||
// Greater than 1 hour, only in hours
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
|
||||
// Greater than 1 hour, only in hours
|
||||
int hours = minutes / 60;
|
||||
format = hours + (hours == 1 ? HOUR : HOURS);
|
||||
int inMins = 60 * hours;
|
||||
int left = minutes - inMins;
|
||||
return formatHours(hours, minutesLeft, secondsLeft);
|
||||
}
|
||||
|
||||
if (left >= 1)
|
||||
format = format + " " + left + (left == 1 ? MINUTE : MINUTES);
|
||||
private String formatSeconds(long seconds) {
|
||||
return (
|
||||
seconds +
|
||||
(seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond())
|
||||
);
|
||||
}
|
||||
|
||||
if (secondsLeft > 0)
|
||||
format = format + " " + secondsLeft + (secondsLeft == 1 ? SECOND : SECONDS);
|
||||
private String formatMinutes(int minutes, int secondsLeft) {
|
||||
String format =
|
||||
minutes +
|
||||
(minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
if (secondsLeft > 0) format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
private String formatHours(int hours, int minutesLeft, int secondsLeft) {
|
||||
String format =
|
||||
hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1) format +=
|
||||
formatMinutes(minutesLeft, secondsLeft); else if (
|
||||
secondsLeft > 0
|
||||
) format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,38 @@
|
||||
package me.codedred.playtimes.time.formats;
|
||||
|
||||
import me.codedred.playtimes.time.TimeConstants;
|
||||
import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class NoDaysNoSeconds implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60)
|
||||
return time + ( time == 1 ? SECONDS : SECOND);
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60) return (
|
||||
time +
|
||||
(time == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond())
|
||||
);
|
||||
|
||||
int minutes = (int) (time / 60);
|
||||
int minutes = (int) (time / 60);
|
||||
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60)
|
||||
return minutes + (minutes == 1 ? MINUTE : MINUTES);
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) return (
|
||||
minutes +
|
||||
(minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes())
|
||||
);
|
||||
|
||||
String format;
|
||||
String format;
|
||||
|
||||
int hours = minutes / 60;
|
||||
format = hours + (hours == 1 ? HOUR : HOURS);
|
||||
int inMins = 60 * hours;
|
||||
int left = minutes - inMins;
|
||||
int hours = minutes / 60;
|
||||
format =
|
||||
hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
int inMins = 60 * hours;
|
||||
int left = minutes - inMins;
|
||||
|
||||
if (left >= 1)
|
||||
format = format + " " + left + (left == 1 ? MINUTE : MINUTES);
|
||||
|
||||
return format;
|
||||
|
||||
}
|
||||
if (left >= 1) format =
|
||||
format +
|
||||
left +
|
||||
(left == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +1,63 @@
|
||||
package me.codedred.playtimes.time.formats;
|
||||
|
||||
import me.codedred.playtimes.time.TimeConstants;
|
||||
import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class NoSeconds implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60)
|
||||
return time + ( time == 1 ? SECONDS : SECOND);
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60) return formatSeconds(time);
|
||||
|
||||
int minutes = (int) (time / 60);
|
||||
int minutes = (int) (time / 60);
|
||||
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60)
|
||||
return minutes + (minutes == 1 ? MINUTE : MINUTES);
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) return formatMinutes(minutes);
|
||||
|
||||
String format;
|
||||
|
||||
// Time less than 1 Day
|
||||
if (minutes < 1440) {
|
||||
int hours = minutes / 60;
|
||||
format = hours + (hours == 1 ? HOUR : HOURS);
|
||||
int inMins = 60 * hours;
|
||||
int left = minutes - inMins;
|
||||
|
||||
if (left >= 1)
|
||||
format = format + " " + left + (left == 1 ? MINUTE : MINUTES);
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
// Time greater than 1 day
|
||||
int days = minutes / 1440;
|
||||
format = days + (days == 1 ? DAY : DAYS);
|
||||
int inMins = 1440 * days;
|
||||
int leftOver = minutes - inMins;
|
||||
if (leftOver >= 1) {
|
||||
if (leftOver < 60) {
|
||||
format = format + " " + leftOver + (leftOver == 1 ? MINUTE : MINUTES);
|
||||
}
|
||||
else {
|
||||
int hours = leftOver / 60;
|
||||
format = format + " " + hours + (hours == 1 ? HOUR : HOURS);
|
||||
int hoursInMins = 60 * hours;
|
||||
int minsLeft = leftOver - hoursInMins;
|
||||
if (leftOver >= 1) {
|
||||
format = format + " " + minsLeft + (minsLeft == 1 ? MINUTE : MINUTES);
|
||||
}
|
||||
}
|
||||
}
|
||||
return format;
|
||||
// Time less than 1 Day
|
||||
if (minutes < 1440) {
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
return formatHours(hours, minutesLeft);
|
||||
}
|
||||
|
||||
// Time greater than 1 day
|
||||
int days = minutes / 1440;
|
||||
int minutesLeft = minutes % 1440;
|
||||
return formatDays(days, minutesLeft);
|
||||
}
|
||||
|
||||
private String formatSeconds(long seconds) {
|
||||
return (
|
||||
seconds +
|
||||
(seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond())
|
||||
);
|
||||
}
|
||||
|
||||
private String formatMinutes(int minutes) {
|
||||
return (
|
||||
minutes +
|
||||
(minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes())
|
||||
);
|
||||
}
|
||||
|
||||
private String formatHours(int hours, int minutesLeft) {
|
||||
String format =
|
||||
hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1) format += formatMinutes(minutesLeft);
|
||||
return format;
|
||||
}
|
||||
|
||||
private String formatDays(int days, int minutesLeft) {
|
||||
String format =
|
||||
days + (days == 1 ? TimeConstants.getDay() : TimeConstants.getDays());
|
||||
if (minutesLeft >= 60) {
|
||||
int hours = minutesLeft / 60;
|
||||
int minutesAfterHours = minutesLeft % 60;
|
||||
format += formatHours(hours, minutesAfterHours);
|
||||
} else if (minutesLeft >= 1) {
|
||||
format += formatMinutes(minutesLeft);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,21 @@
|
||||
package me.codedred.playtimes.time.formats;
|
||||
|
||||
import me.codedred.playtimes.time.TimeConstants;
|
||||
import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class OnlyHours implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
return ((double)Math.round((time/3600.0)*100d))/100d + HOURS;
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
boolean round = TimeConstants.getRounded();
|
||||
double hours = time / 3600.0;
|
||||
|
||||
if (round) {
|
||||
int roundedHours = (int) Math.round(hours);
|
||||
return roundedHours + TimeConstants.getHours();
|
||||
}
|
||||
|
||||
hours = (Math.round(hours * 100d)) / 100d;
|
||||
return hours + TimeConstants.getHours();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package me.codedred.playtimes.utils;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import lombok.Getter;
|
||||
|
||||
public class Async {
|
||||
|
||||
@Getter
|
||||
private static final ForkJoinPool worker = new ForkJoinPool(
|
||||
8,
|
||||
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
|
||||
(t, e) -> e.printStackTrace(),
|
||||
false
|
||||
);
|
||||
|
||||
public static CompletableFuture<Void> run(Runnable runnable) {
|
||||
return CompletableFuture.runAsync(
|
||||
() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception exception) {
|
||||
throw new CompletionException(exception);
|
||||
}
|
||||
},
|
||||
worker
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,40 +6,52 @@ import org.bukkit.command.CommandSender;
|
||||
|
||||
public class ChatUtil {
|
||||
|
||||
public enum ChatTypes {
|
||||
private static final DataManager DATA_MANAGER = DataManager.getInstance();
|
||||
private static final boolean IS_NEWER_VERSION = ServerUtils.isNewerVersion();
|
||||
|
||||
NO_PERMISSION,
|
||||
PLAYER_NOT_FOUND,
|
||||
PLAYER_NEVER_PLAYED
|
||||
public enum ChatTypes {
|
||||
NO_PERMISSION,
|
||||
PLAYER_NOT_FOUND,
|
||||
PLAYER_NEVER_PLAYED,
|
||||
}
|
||||
|
||||
public static void errno(CommandSender sender, ChatTypes type) {
|
||||
switch (type) {
|
||||
case NO_PERMISSION:
|
||||
sender.sendMessage(
|
||||
format(DATA_MANAGER.getConfig().getString("messages.noPermission"))
|
||||
);
|
||||
break;
|
||||
case PLAYER_NOT_FOUND:
|
||||
sender.sendMessage(
|
||||
formatWithPrefix(
|
||||
DATA_MANAGER.getConfig().getString("messages.player-not-found")
|
||||
)
|
||||
);
|
||||
break;
|
||||
case PLAYER_NEVER_PLAYED:
|
||||
sender.sendMessage(
|
||||
formatWithPrefix(
|
||||
DATA_MANAGER.getConfig().getString("messages.player-never-joined")
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void errno(CommandSender sender, ChatTypes type) {
|
||||
DataManager data = DataManager.getInstance();
|
||||
switch (type) {
|
||||
case NO_PERMISSION:
|
||||
sender.sendMessage(format(data.getConfig().getString("messages.noPermission")));
|
||||
break;
|
||||
case PLAYER_NOT_FOUND:
|
||||
sender.sendMessage(formatWithPrefix(data.getConfig().getString("messages.player-not-found")));
|
||||
break;
|
||||
case PLAYER_NEVER_PLAYED:
|
||||
sender.sendMessage(formatWithPrefix(data.getConfig().getString("messages.player-never-joined")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
public static String format(String msg) {
|
||||
msg = ChatColor.translateAlternateColorCodes('&', msg);
|
||||
if (IS_NEWER_VERSION) msg = HexUtil.hex(msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static String format(String msg) {
|
||||
msg = ChatColor.translateAlternateColorCodes('&', msg);
|
||||
if (ServerUtils.isNewerVersion())
|
||||
msg = HexUtil.hex(msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static String formatWithPrefix(String msg) {
|
||||
msg = ChatColor.translateAlternateColorCodes('&', DataManager.getInstance().getConfig().getString("prefix") + " " + msg);
|
||||
if (ServerUtils.isNewerVersion())
|
||||
msg = HexUtil.hex(msg);
|
||||
return msg;
|
||||
}
|
||||
public static String formatWithPrefix(String msg) {
|
||||
msg =
|
||||
ChatColor.translateAlternateColorCodes(
|
||||
'&',
|
||||
DATA_MANAGER.getConfig().getString("prefix") + " " + msg
|
||||
);
|
||||
if (IS_NEWER_VERSION) msg = HexUtil.hex(msg);
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,35 @@
|
||||
package me.codedred.playtimes.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CoolDownUtil {
|
||||
|
||||
private static Hashtable<UUID, Long> cooldowns = new Hashtable<>();
|
||||
|
||||
public static void remove(UUID uuid) {
|
||||
cooldowns.remove(uuid);
|
||||
}
|
||||
|
||||
|
||||
public static void add(UUID uuid, long time) {
|
||||
cooldowns.put(uuid, time);
|
||||
}
|
||||
|
||||
|
||||
public static int left(UUID uuid) {
|
||||
return (int) (cooldowns.get(uuid)/1000 - (System.currentTimeMillis()/1000));
|
||||
}
|
||||
|
||||
|
||||
public static boolean contains(UUID uuid) {
|
||||
if (cooldowns.containsKey(uuid)) {
|
||||
if (cooldowns.get(uuid) > System.currentTimeMillis())
|
||||
return true;
|
||||
remove(uuid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private CoolDownUtil() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
}
|
||||
|
||||
private static final HashMap<UUID, Long> cooldowns = new HashMap<>();
|
||||
|
||||
public static void remove(UUID uuid) {
|
||||
cooldowns.remove(uuid);
|
||||
}
|
||||
|
||||
public static void add(UUID uuid, long time) {
|
||||
cooldowns.put(uuid, time);
|
||||
}
|
||||
|
||||
public static int left(UUID uuid) {
|
||||
return (int) (
|
||||
cooldowns.get(uuid) / 1000 - (System.currentTimeMillis() / 1000)
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean contains(UUID uuid) {
|
||||
if (cooldowns.containsKey(uuid)) {
|
||||
if (cooldowns.get(uuid) > System.currentTimeMillis()) return true;
|
||||
remove(uuid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2,21 +2,36 @@ package me.codedred.playtimes.utils;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class HexUtil {
|
||||
|
||||
private static final Pattern hexPattern = Pattern.compile("<#([A-Fa-f0-9]){6}>");
|
||||
public static String hex(String message){
|
||||
Matcher matcher = hexPattern.matcher(message);
|
||||
while (matcher.find()) {
|
||||
ChatColor hexColor = ChatColor.of(matcher.group().substring(1, matcher.group().length() - 1));
|
||||
String before = message.substring(0, matcher.start());
|
||||
String after = message.substring(matcher.end());
|
||||
message = before + hexColor + after;
|
||||
matcher = hexPattern.matcher(message);
|
||||
}
|
||||
return ChatColor.translateAlternateColorCodes('&', message);
|
||||
}
|
||||
private HexUtil() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
}
|
||||
|
||||
public static String hex(String message) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int length = message.length();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (
|
||||
message.charAt(i) == '<' &&
|
||||
i + 8 < length &&
|
||||
message.charAt(i + 1) == '#'
|
||||
) {
|
||||
String hexCode = message.substring(i + 2, i + 8);
|
||||
if (message.charAt(i + 8) == '>' && isValidHexCode(hexCode)) {
|
||||
builder.append(ChatColor.of('#' + hexCode));
|
||||
i += 8; // Skip the processed hex code and the '>'
|
||||
continue;
|
||||
}
|
||||
}
|
||||
builder.append(message.charAt(i));
|
||||
}
|
||||
|
||||
return ChatColor.translateAlternateColorCodes('&', builder.toString());
|
||||
}
|
||||
|
||||
private static boolean isValidHexCode(String hexCode) {
|
||||
return hexCode.matches("^[a-fA-F0-9]{6}$");
|
||||
}
|
||||
}
|
||||
@@ -6,33 +6,29 @@ import org.bukkit.entity.Player;
|
||||
|
||||
public class PAPIHolders {
|
||||
|
||||
/***
|
||||
* Translates PAPI holders
|
||||
*
|
||||
* @param player - receiver
|
||||
* @param msg - message that is being checked/translated
|
||||
* @return fixed message with updated PAPI holders
|
||||
*/
|
||||
public static String getHolders(Player player, String msg) {
|
||||
try {
|
||||
return PlaceholderAPI.setPlaceholders(player, msg);
|
||||
} catch (Exception e) {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Translates PAPI holders for offline player
|
||||
*
|
||||
* @param player - receiver
|
||||
* @param msg - message that is being checked/translated
|
||||
* @return fixed message with updated PAPI holders
|
||||
*/
|
||||
public static String getHolders(OfflinePlayer player, String msg) {
|
||||
try {
|
||||
return PlaceholderAPI.setPlaceholders(player, msg);
|
||||
} catch (Exception e) {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
private PAPIHolders() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates PAPI holders
|
||||
*
|
||||
* @param player the receiver of the message
|
||||
* @param msg the message that is being checked/translated
|
||||
* @return the fixed message with updated PAPI holders
|
||||
*/
|
||||
public static String getHolders(Player player, String msg) {
|
||||
return PlaceholderAPI.setPlaceholders(player, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates PAPI holders for offline players
|
||||
*
|
||||
* @param player the receiver of the message
|
||||
* @param msg the message that is being checked/translated
|
||||
* @return the fixed message with updated PAPI holders
|
||||
*/
|
||||
public static String getHolders(OfflinePlayer player, String msg) {
|
||||
return PlaceholderAPI.setPlaceholders(player, msg);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,80 @@
|
||||
package me.codedred.playtimes.utils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ServerUtils {
|
||||
|
||||
public static boolean isNewerVersion() {
|
||||
try {
|
||||
Class<?> class_Material = Material.class;
|
||||
Method method = class_Material.getDeclaredMethod("matchMaterial", String.class, Boolean.TYPE);
|
||||
return (method != null);
|
||||
} catch(ReflectiveOperationException ex) {
|
||||
return false;
|
||||
}
|
||||
private static Boolean isNewerVersion = null;
|
||||
|
||||
private ServerUtils() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
}
|
||||
|
||||
public static boolean isNewerVersion() {
|
||||
if (isNewerVersion == null) {
|
||||
try {
|
||||
Class<?> classMaterial = Material.class;
|
||||
Method method = classMaterial.getDeclaredMethod(
|
||||
"matchMaterial",
|
||||
String.class,
|
||||
boolean.class
|
||||
);
|
||||
isNewerVersion = (method != null);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
isNewerVersion = false;
|
||||
}
|
||||
}
|
||||
return isNewerVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the server version is 1.17+
|
||||
*
|
||||
* @return true if so
|
||||
*/
|
||||
public static boolean isRisenVersion() {
|
||||
String version = Bukkit.getServer().getVersion();
|
||||
String mcVersion = null;
|
||||
|
||||
if (version.contains("(MC:")) {
|
||||
int startIndex = version.indexOf("(MC:") + 5;
|
||||
int endIndex = version.indexOf(")", startIndex);
|
||||
mcVersion = version.substring(startIndex, endIndex).trim();
|
||||
}
|
||||
|
||||
public static boolean isRisenVersion() {
|
||||
return Bukkit.getServer().getVersion().contains("1.17");
|
||||
if (mcVersion == null) {
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.warning("PlayTimes failed to extract Minecraft version: " + version);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasPAPI() {
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null)
|
||||
return DataManager.getInstance().getConfig().getBoolean("use-papi-placeholders");
|
||||
return false;
|
||||
String[] versionParts = mcVersion.split("\\.");
|
||||
|
||||
try {
|
||||
int minorVersion = versionParts.length >= 2
|
||||
? Integer.parseInt(versionParts[1])
|
||||
: 0;
|
||||
|
||||
return minorVersion >= 17;
|
||||
} catch (NumberFormatException e) {
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.warning("PlayTimes failed to parse Minecraft version: " + mcVersion);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasPAPI() {
|
||||
if (
|
||||
Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null
|
||||
) return DataManager
|
||||
.getInstance()
|
||||
.getConfig()
|
||||
.getBoolean("use-papi-placeholders");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +1,102 @@
|
||||
# PlayTimes by CodedRed
|
||||
# For support please ask here: https://discord.gg/7A9UA2n
|
||||
# For assistance, please submit inquiries here: https://github.com/CodedRed-Spigot/PlayTimes/issues
|
||||
|
||||
# Prefix will show before 'player-not-found' & 'player-never-joined' messages
|
||||
# The 'prefix' configures the introductory text for 'player-not-found' and 'player-never-joined' notifications.
|
||||
prefix: "&7[&b&lPlayTimes&7]"
|
||||
|
||||
# date-format can be changed to your liking.
|
||||
# For more placeholders look here: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
|
||||
# This is the join date format.
|
||||
date-format: MM/dd/yyyy
|
||||
|
||||
# Placeholders API info
|
||||
# Only enable this if you are using PAPI holders in PlayTimes
|
||||
# If you want to use PlayTimes placeholders in other plugins...
|
||||
# Just download PAPI and it will *automatically* register
|
||||
# Placeholder API Configuration
|
||||
# Activate this only if using PlaceholderAPI with PlayTimes.
|
||||
# To integrate PlayTimes placeholders into other plugins, simply install PlaceholderAPI; integration occurs seamlessly.
|
||||
use-papi-placeholders: false
|
||||
|
||||
# Main Playtimes info.
|
||||
# The name refers to the format. Example if you have minute = " min" then it will display "x min"
|
||||
# PlayTimes Formatting and Message Customization
|
||||
# 'playtime.name' defines time unit labels. For formatting guidance, refer to our Spigot plugin page.
|
||||
playtime:
|
||||
## Default Placeholders:
|
||||
## %player%, %playtime%, %timesjoined%, %joindate%, %rawTime%, %afkTime%
|
||||
## For database placeholders, visit: https://github.com/CodedRed-Spigot/PlayTimes/wiki/Bungee-Support
|
||||
## PlaceholderAPI placeholders are also compatible.
|
||||
message:
|
||||
- "&b&m=======&b&l[%player%]&b&m======="
|
||||
- "&aPlaytime:&f %playtime%"
|
||||
- "&aTimes Joined:&f %timesjoined%"
|
||||
- "&aJoin Date:&f %joindate%"
|
||||
- "&b&m============================"
|
||||
name:
|
||||
second: "s"
|
||||
minute: "min"
|
||||
hour: "hr"
|
||||
day: "day"
|
||||
minute: "min "
|
||||
hour: "hr "
|
||||
day: "day "
|
||||
seconds: "s"
|
||||
minutes: "mins"
|
||||
hours: "hrs"
|
||||
days: "days"
|
||||
minutes: "mins "
|
||||
hours: "hrs "
|
||||
days: "days "
|
||||
|
||||
## only-hours - when true it will display playtime in hours (When true this will also disable show-seconds/days setting)
|
||||
## show-seconds - when true it will display seconds
|
||||
## show-days - when true it will display days
|
||||
## 'only-hours' - Displays playtime solely in hours. Activating this overrides 'show-seconds' and 'show-days'.
|
||||
## 'show-seconds' - Includes seconds in the display.
|
||||
## 'show-days' - Includes days in the display.
|
||||
only-hours: false
|
||||
show-seconds: true
|
||||
show-days: true
|
||||
## 'round-numbers' - Rounds off the playtime to whole numbers when 'only-hours' is true.
|
||||
round-numbers: true
|
||||
|
||||
# AFK Tracker Configuration
|
||||
# NOTE: When enabled, this will remove afk time from %playtime% placeholder
|
||||
afk-settings:
|
||||
enabled: true
|
||||
|
||||
## Built-in Placeholders:
|
||||
## %player% %time% %timesjoined% %joindate%
|
||||
## You may also use PAPI Placeholders
|
||||
message:
|
||||
- "&b&m=======&b&l[%player%]&b&m======="
|
||||
- "&aPlaytime:&f %time%"
|
||||
- "&aTimes joined:&f %timesjoined%"
|
||||
- "&aJoined Date:&f %joindate%"
|
||||
- "&b&m============================"
|
||||
## Time in minutes after which a player is considered AFK.
|
||||
threshold: 5
|
||||
|
||||
# /Uptime command info - only placeholder is %serveruptime%
|
||||
## Notifications settings for AFK status changes.
|
||||
broadcast-afk:
|
||||
on-enter-afk: true
|
||||
on-exit-afk: true
|
||||
|
||||
# Message to send to the player when they are marked as AFK.
|
||||
on-enter-afk-message: "&eYou are now marked as AFK."
|
||||
# Message to send to the player when they are no longer marked as AFK.
|
||||
on-exit-afk-message: "&eYou are no longer AFK."
|
||||
# Leave true unless you are experiencing lag/issues with one of the afk listeners.
|
||||
cancel-afk:
|
||||
on-player-move: true
|
||||
on-player-chat: true
|
||||
on-player-interact: true
|
||||
|
||||
# /Uptime Command Configuration - Use '%serveruptime%' to display server uptime.
|
||||
uptime:
|
||||
message:
|
||||
- "&b&m============================"
|
||||
- "&aServer Uptime:&f %serveruptime%"
|
||||
- "&b&m============================"
|
||||
|
||||
# /toppt command info
|
||||
## Built-in Placeholders:
|
||||
## %player% %place% %time% %joindate%
|
||||
## You may also use PAPI placeholders
|
||||
# /toppt Command Settings
|
||||
## Standard Placeholders:
|
||||
## %player%, %place%, %time%, %joindate%
|
||||
## PlaceholderAPI placeholders are also supported.
|
||||
top-playtime:
|
||||
header: "&b******&9[&3&lPlayTime Leaderboards&9]&b*****"
|
||||
content: "&5%place%) &9&l%player% &9&o- %time%"
|
||||
footer: "&b****************************************"
|
||||
enable-cooldown: true
|
||||
cooldown-seconds: 60
|
||||
track-rawtime: false
|
||||
|
||||
# Built in messages, may change to your liking :D
|
||||
# 'date-format' - Customize this to change the format of join dates.
|
||||
# Explore more formatting options at: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
|
||||
date-format: "MM/dd/yyyy"
|
||||
|
||||
# Customizable Built-In Messages
|
||||
messages:
|
||||
noPermission: "&cYou cannot run this command."
|
||||
player-not-found: "&cPlayer not found."
|
||||
player-never-joined: "&cPlayer has never joined the server!"
|
||||
cooldown: "&cYou cannot use this command for %timeleft% seconds!"
|
||||
player-not-found: "&cUnable to locate player."
|
||||
player-never-joined: "&cThis player has not joined the server."
|
||||
cooldown: "&cCommand unavailable for %timeleft% seconds!"
|
||||
|
||||
# Do not change this unless you know what you're doing!
|
||||
# This setting is for servers experiencing issues when looking up offline players.
|
||||
# For more information, see the link below.
|
||||
uuid-lookups:
|
||||
what-does-this-do: https://github.com/CodedRed-Spigot/PlayTimes/wiki/UUID-LOOKUPS
|
||||
type: "default"
|
||||
@@ -0,0 +1 @@
|
||||
# DO NOT ALTER THIS FILE.
|
||||
@@ -0,0 +1,30 @@
|
||||
database-settings:
|
||||
enabled: false
|
||||
type: "mysql" # change to 'sqlite' for SQLite
|
||||
database: "playtimes"
|
||||
host: "localhost"
|
||||
port: 3306
|
||||
user: "root"
|
||||
password: "password"
|
||||
useSSL: false
|
||||
# IMPORTANT:
|
||||
# 'serverId' must be UNIQUE to each server!
|
||||
# If you have multiple servers running PlayTimes, ensure each config has a unique 'serverId'.
|
||||
# The 'serverId' will also be used for placeholders, like %playtime_serverId% (e.g., %playtime_survival%).
|
||||
# The placeholder will return the playtime on that specific server.
|
||||
serverId: "survival"
|
||||
|
||||
# If enabled, upon starting your server it will purge all user info that is older than x months.
|
||||
# NOTE: This will only purge data for the specific 'serverId', not for all servers!
|
||||
purge-database:
|
||||
enabled: false
|
||||
months: 12
|
||||
# Placeholders:
|
||||
## For use in Plugin:
|
||||
# %rawtime_serverId%
|
||||
# %afktime_serverId%
|
||||
# %playtime_serverId%
|
||||
## For PAPI:
|
||||
# %PlayTimes_rawtime_serverId%
|
||||
# %PlayTimes_afktime_serverId%
|
||||
# %PlayTimes_playtime_serverId%
|
||||
@@ -0,0 +1,89 @@
|
||||
# PlayTimes by CodedRed
|
||||
# For assistance, please submit inquiries here: https://github.com/CodedRed-Spigot/PlayTimes/issues
|
||||
|
||||
# The 'prefix' configures the introductory text for 'player-not-found' and 'player-never-joined' notifications.
|
||||
prefix: "&7[&b&lPlayTimes&7]"
|
||||
|
||||
# Placeholder API Configuration
|
||||
# Activate this only if using PlaceholderAPI with PlayTimes.
|
||||
# To integrate PlayTimes placeholders into other plugins, simply install PlaceholderAPI; integration occurs seamlessly.
|
||||
use-papi-placeholders: false
|
||||
|
||||
# PlayTimes Formatting and Message Customization
|
||||
# 'playtime.name' defines time unit labels. For formatting guidance, refer to our Spigot plugin page.
|
||||
playtime:
|
||||
## Default Placeholders:
|
||||
## %player%, %playtime%, %timesjoined%, %joindate%, %rawTime%, %afkTime%
|
||||
## For database placeholders, visit: https://github.com/CodedRed-Spigot/PlayTimes/wiki/Bungee-Support
|
||||
## PlaceholderAPI placeholders are also compatible.
|
||||
message:
|
||||
- "&b&m=======&b&l[%player%]&b&m======="
|
||||
- "&aPlaytime:&f %playtime%"
|
||||
- "&aTimes Joined:&f %timesjoined%"
|
||||
- "&aJoin Date:&f %joindate%"
|
||||
- "&b&m============================"
|
||||
name:
|
||||
second: "s"
|
||||
minute: "min "
|
||||
hour: "hr "
|
||||
day: "day "
|
||||
seconds: "s"
|
||||
minutes: "mins "
|
||||
hours: "hrs "
|
||||
days: "days "
|
||||
|
||||
## 'only-hours' - Displays playtime solely in hours. Activating this overrides 'show-seconds' and 'show-days'.
|
||||
## 'show-seconds' - Includes seconds in the display.
|
||||
## 'show-days' - Includes days in the display.
|
||||
only-hours: false
|
||||
show-seconds: true
|
||||
show-days: true
|
||||
## 'round-numbers' - Rounds off the playtime to whole numbers when 'only-hours' is true.
|
||||
round-numbers: true
|
||||
|
||||
# AFK Tracker Configuration
|
||||
# NOTE: When enabled, this will remove afk time from %time% placeholder
|
||||
afk-settings:
|
||||
enabled: true
|
||||
|
||||
## Time in minutes after which a player is considered AFK.
|
||||
threshold: 2
|
||||
|
||||
## Notifications settings for AFK status changes.
|
||||
notify-on-afk:
|
||||
onAFK: true
|
||||
onBackFromAFK: true
|
||||
|
||||
# Message to send to the player when they are marked as AFK.
|
||||
afk-message: "&eYou are now marked as AFK."
|
||||
# Message to send to the player when they are no longer marked as AFK.
|
||||
back-from-afk-message: "&eYou are no longer AFK."
|
||||
|
||||
# /Uptime Command Configuration - Use '%serveruptime%' to display server uptime.
|
||||
uptime:
|
||||
message:
|
||||
- "&b&m============================"
|
||||
- "&aServer Uptime:&f %serveruptime%"
|
||||
- "&b&m============================"
|
||||
|
||||
# /toppt Command Settings
|
||||
## Standard Placeholders:
|
||||
## %player%, %place%, %time%, %joindate%
|
||||
## PlaceholderAPI placeholders are also supported.
|
||||
top-playtime:
|
||||
header: "&b******&9[&3&lPlayTime Leaderboards&9]&b*****"
|
||||
content: "&5%place%) &9&l%player% &9&o- %time%"
|
||||
footer: "&b****************************************"
|
||||
enable-cooldown: true
|
||||
cooldown-seconds: 60
|
||||
|
||||
# 'date-format' - Customize this to change the format of join dates.
|
||||
# Explore more formatting options at: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
|
||||
date-format: "MM/dd/yyyy"
|
||||
|
||||
# Customizable Built-In Messages
|
||||
messages:
|
||||
noPermission: "&cYou cannot run this command."
|
||||
player-not-found: "&cUnable to locate player."
|
||||
player-never-joined: "&cThis player has not joined the server."
|
||||
cooldown: "&cCommand unavailable for %timeleft% seconds!"
|
||||
@@ -1,24 +1,21 @@
|
||||
name: Playtimes
|
||||
version: "${version}"
|
||||
main: me.codedred.playtimes.PlayTimes
|
||||
# Keeping 'Cmaaxx' as author for Metric purposes.
|
||||
author: Cmaaxx
|
||||
authors: [CodedRed]
|
||||
version: 1.4.5
|
||||
softdepend: [PlaceholdersAPI, PlaceholderAPI]
|
||||
softdepend: [PlaceholderAPI]
|
||||
description: Check Players PlayTime And More!
|
||||
|
||||
commands:
|
||||
playtime:
|
||||
description: Check your playtime!
|
||||
usage: /playtime
|
||||
permission: pt.use
|
||||
aliases: [playt, playerinfo, pt]
|
||||
description: "Check your playtime!"
|
||||
usage: "/playtime"
|
||||
uptime:
|
||||
description: Check your servers uptime!
|
||||
usage: /uptime
|
||||
permission: pt.uptime
|
||||
aliases: [serveruptime, serverupt]
|
||||
description: "Check your servers uptime!"
|
||||
usage: "/uptime"
|
||||
topplaytime:
|
||||
description: Check your servers uptime!
|
||||
usage: /topplaytime
|
||||
permission: pt.top
|
||||
aliases: [toppt, topplayt]
|
||||
aliases: [topplayt, toppt]
|
||||
description: "Check your servers uptime!"
|
||||
usage: "/topplaytime"
|
||||
Reference in new issue
Block a user