mirror of
https://github.com/HibiscusMC/HMCCosmetics.git
synced 2025-12-19 15:09:19 +00:00
Compare commits
297 Commits
v1.0.2
...
1_11_2_pli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e94d74990 | ||
|
|
5e3edd472c | ||
|
|
791fe53c48 | ||
|
|
c9f7762a26 | ||
|
|
1be95c78c2 | ||
|
|
2be06e3ad9 | ||
|
|
d4bf6f256b | ||
|
|
5ffe39cdba | ||
|
|
e6c81f8d1e | ||
|
|
0378b98967 | ||
|
|
a26edbfc9c | ||
|
|
19e8a3bf10 | ||
|
|
b8aefbacdb | ||
|
|
7a29aa8927 | ||
|
|
482aec27f1 | ||
|
|
007e5487e6 | ||
|
|
e7f077af7a | ||
|
|
99b1afd15c | ||
|
|
3f5acde838 | ||
|
|
2676505c9a | ||
|
|
f5d1a09d28 | ||
|
|
1b9e2ac531 | ||
|
|
b005614881 | ||
|
|
a41fb7df2b | ||
|
|
e0fbbc7f76 | ||
|
|
cb09da91fe | ||
|
|
cd7ed29522 | ||
|
|
f5a7c2f9f0 | ||
|
|
6af8e13dab | ||
|
|
e3f081f1c9 | ||
|
|
c7ba2f179a | ||
|
|
8f012f6c97 | ||
|
|
e95b30131c | ||
|
|
2dc068a938 | ||
|
|
7bdc122cb1 | ||
|
|
a3d57af18d | ||
|
|
235c0a9307 | ||
|
|
4d7e565c23 | ||
|
|
57d3110740 | ||
|
|
61e226b826 | ||
|
|
bd7b045c0f | ||
|
|
1ce28a9f66 | ||
|
|
70c2b79b6c | ||
|
|
39d485ddfe | ||
|
|
548a6bf4ec | ||
|
|
fb15919f52 | ||
|
|
9a5923bb7d | ||
|
|
02239396f0 | ||
|
|
942d48adf8 | ||
|
|
99ae2b765a | ||
|
|
6b59ba88a5 | ||
|
|
4d7dff885a | ||
|
|
f4bc6f1bc3 | ||
|
|
938dfe677d | ||
|
|
1c30924410 | ||
|
|
bd731c8b6b | ||
|
|
41f4f830d1 | ||
|
|
86346583cc | ||
|
|
b13d44536f | ||
|
|
822422d4a5 | ||
|
|
449fc8a84b | ||
|
|
9be234cf11 | ||
|
|
08be1d56ac | ||
|
|
c6aecaae80 | ||
|
|
d25336f966 | ||
|
|
49dfb46cc5 | ||
|
|
4774e2d1d6 | ||
|
|
31775c5e85 | ||
|
|
59bba0e854 | ||
|
|
74a0d279b0 | ||
|
|
3d51b77123 | ||
|
|
fc7b886727 | ||
|
|
4be32d3849 | ||
|
|
e39b56a63e | ||
|
|
bc994bfa2f | ||
|
|
0ea5c92d86 | ||
|
|
3ed245c95b | ||
|
|
7bb4312fee | ||
|
|
24c06fd12c | ||
|
|
3a0ff5504e | ||
|
|
7caeec3fd1 | ||
|
|
4e3c0b1c6b | ||
|
|
383ee49d67 | ||
|
|
67e3dbfcf5 | ||
|
|
355920ae8c | ||
|
|
cd2a8e54e1 | ||
|
|
a05fde5038 | ||
|
|
14b0cc6275 | ||
|
|
f9ffd91116 | ||
|
|
7b063815fc | ||
|
|
6653ac6edc | ||
|
|
2beadca574 | ||
|
|
844e7c852f | ||
|
|
6c2363a9fb | ||
|
|
13212fe26e | ||
|
|
766eed0387 | ||
|
|
a06a5004e1 | ||
|
|
8eec822a8c | ||
|
|
56ca9b2a39 | ||
|
|
88b24aefbc | ||
|
|
e0044c6d15 | ||
|
|
6c2049a8d8 | ||
|
|
2ffb791ce1 | ||
|
|
6ced156e23 | ||
|
|
8045a63964 | ||
|
|
49681c7c1d | ||
|
|
1e69dcea89 | ||
|
|
2b832c33a4 | ||
|
|
8cda481a55 | ||
|
|
6294a26b1d | ||
|
|
29b26c29ca | ||
|
|
01230dda3f | ||
|
|
181bd722ac | ||
|
|
4deb586813 | ||
|
|
d478736b5b | ||
|
|
d961bd2966 | ||
|
|
58ddceb5f1 | ||
|
|
4be4c5fe2a | ||
|
|
23c1774f37 | ||
|
|
7c911d1247 | ||
|
|
89a32dcd30 | ||
|
|
badc2f7b87 | ||
|
|
16d516ef18 | ||
|
|
1fcbe27d6a | ||
|
|
8da9100dd3 | ||
|
|
1888145ee0 | ||
|
|
84864303fc | ||
|
|
960bb97a04 | ||
|
|
a55ad14934 | ||
|
|
8b345bc56c | ||
|
|
4e21945bbb | ||
|
|
b3aa0b942f | ||
|
|
607d2ea7bd | ||
|
|
23bcd56eac | ||
|
|
ba7327dd54 | ||
|
|
35c6b01f34 | ||
|
|
ee86569f22 | ||
|
|
59dbee34ae | ||
|
|
d12a5d090f | ||
|
|
5ba03402a0 | ||
|
|
b7c80437e2 | ||
|
|
e4cba947d3 | ||
|
|
e026739b34 | ||
|
|
440a106534 | ||
|
|
068a147e1e | ||
|
|
f3b780e730 | ||
|
|
8fa606954e | ||
|
|
9d3ca106c9 | ||
|
|
98a6528e50 | ||
|
|
a3bce9b766 | ||
|
|
d10afc3df3 | ||
|
|
be7092b422 | ||
|
|
6ccc40798a | ||
|
|
8503f3cb39 | ||
|
|
ffd15345d2 | ||
|
|
a42730dc19 | ||
|
|
363c57141c | ||
|
|
cc67eff1f7 | ||
|
|
9b7b5ce1ad | ||
|
|
ed41b71ff3 | ||
|
|
54fe2719d1 | ||
|
|
a7892ce434 | ||
|
|
39583b3685 | ||
|
|
eec995a7f3 | ||
|
|
c75182d118 | ||
|
|
268ccff0db | ||
|
|
deb7806e78 | ||
|
|
832980f593 | ||
|
|
c8ee8c0c7c | ||
|
|
ce3989edca | ||
|
|
09e252bd48 | ||
|
|
f58d328bae | ||
|
|
2347c5175d | ||
|
|
977b5e388a | ||
|
|
46c47b0a1f | ||
|
|
4b8d2c1517 | ||
|
|
4d632c612a | ||
|
|
0b4e2a6966 | ||
|
|
23a5ffa068 | ||
|
|
56fa927ca6 | ||
|
|
9c16008f29 | ||
|
|
0dc69241f1 | ||
|
|
cf1e94e116 | ||
|
|
72f92be6f6 | ||
|
|
39ac2713b7 | ||
|
|
a07eec4ddc | ||
|
|
231dcc163e | ||
|
|
d22b13fe05 | ||
|
|
0c54f52785 | ||
|
|
16ede1baab | ||
|
|
1ba07b87cf | ||
|
|
11baacaa5f | ||
|
|
8b231535c9 | ||
|
|
b81241a019 | ||
|
|
4b64ee1b3e | ||
|
|
d2592809c7 | ||
|
|
ffae42c5a7 | ||
|
|
7e4d9459ba | ||
|
|
30f5278ca9 | ||
|
|
6e3de56071 | ||
|
|
3d9c006310 | ||
|
|
3d8b582a8f | ||
|
|
311253aed3 | ||
|
|
8912ab5b94 | ||
|
|
136a5679a6 | ||
|
|
e024d6420b | ||
|
|
7a7ddf09fb | ||
|
|
412688eebc | ||
|
|
4aa3ecc147 | ||
|
|
700ff1aa3f | ||
|
|
929fd84a74 | ||
|
|
cc768d8186 | ||
|
|
85fc9d9056 | ||
|
|
538690612a | ||
|
|
998cc02edd | ||
|
|
cfadc69a0d | ||
|
|
a29d7f20d0 | ||
|
|
4460938dc3 | ||
|
|
8a0ce58297 | ||
|
|
20efcb0b36 | ||
|
|
af05a83451 | ||
|
|
aed81b4a13 | ||
|
|
eec23ab54b | ||
|
|
45c51492a3 | ||
|
|
80f6e02598 | ||
|
|
edc8724e90 | ||
|
|
f7d8a7205f | ||
|
|
3551de2cd3 | ||
|
|
3da27b0bf4 | ||
|
|
b63c130730 | ||
|
|
81db0cab06 | ||
|
|
f02871871c | ||
|
|
7207974ada | ||
|
|
7ea5cdcf46 | ||
|
|
512627d1c7 | ||
|
|
246fd3f9a6 | ||
|
|
70ee381f48 | ||
|
|
d78bf20ca9 | ||
|
|
1c7aa2c672 | ||
|
|
f0a046f434 | ||
|
|
22c4323a16 | ||
|
|
77e913257e | ||
|
|
2cc4fcc878 | ||
|
|
e35eee9937 | ||
|
|
941b82de08 | ||
|
|
81bea485a5 | ||
|
|
cfa36dab4b | ||
|
|
14d1cf5d19 | ||
|
|
8455492322 | ||
|
|
c4dba6f9a8 | ||
|
|
280018fb9f | ||
|
|
14617fdaff | ||
|
|
61f13eb3c1 | ||
|
|
39b6a8de67 | ||
|
|
f19b4d359e | ||
|
|
0ca9350ce6 | ||
|
|
d9f12db6dc | ||
|
|
3c302e6c4b | ||
|
|
e22b776d13 | ||
|
|
915285c485 | ||
|
|
02a3c96137 | ||
|
|
7bb8fd79c2 | ||
|
|
27cab1fb4b | ||
|
|
3c8c585634 | ||
|
|
b2465c8b13 | ||
|
|
3cc489cac9 | ||
|
|
328aacb73d | ||
|
|
3e609dac93 | ||
|
|
14eb7b8edc | ||
|
|
5c9041acfc | ||
|
|
f40c6fc292 | ||
|
|
f800ceaed6 | ||
|
|
a6c5761636 | ||
|
|
bb812a180f | ||
|
|
d69dd1afef | ||
|
|
4a1eb8a85f | ||
|
|
d6c052294a | ||
|
|
32afd0d144 | ||
|
|
66ff99e657 | ||
|
|
67cf6d3267 | ||
|
|
1d988ed809 | ||
|
|
22f095f236 | ||
|
|
cc0b2d75b7 | ||
|
|
520b9854f5 | ||
|
|
f8bc649799 | ||
|
|
44c99ae6d2 | ||
|
|
63681ab9cf | ||
|
|
705664441a | ||
|
|
d7a8cac2e2 | ||
|
|
3cef8dc0e3 | ||
|
|
b054207012 | ||
|
|
1bb80e0fcd | ||
|
|
e9694e77d7 | ||
|
|
a8ba081975 | ||
|
|
6843373298 | ||
|
|
c97c3650ea | ||
|
|
dbdc6a5c90 |
20
.github/ISSUE_TEMPLATE/bug-report.md
vendored
20
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Create a bug report to help us keep track of all bugs that have to be fixed
|
||||
title: "[BUG] Bug name"
|
||||
labels: bug
|
||||
|
||||
---
|
||||
|
||||
**I have checked...**
|
||||
- [ ] ...if there are any similar bug reports
|
||||
- [ ] ...if a bug fix is already planned
|
||||
|
||||
**Complete description**
|
||||
Write your bug description as good as you can.
|
||||
|
||||
**Possible solution**
|
||||
If you have any possible solutions, write them here, if not, leave it blank or put "N/A".
|
||||
|
||||
**Error/Server log**
|
||||
If you have any errors put them in here (from paste.gg or sentry)
|
||||
62
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
62
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Bug Report
|
||||
description: Create a bug report to help us keep track of all bugs that have to be fixed
|
||||
title: "[BUG] <name for bug>"
|
||||
labels: [bug]
|
||||
|
||||
body:
|
||||
- type: checkboxes
|
||||
id: i-have-checked
|
||||
attributes:
|
||||
label: I have checked...
|
||||
options:
|
||||
- label: "I am using the latest version of HMCCosmetics"
|
||||
required: true
|
||||
- label: "I am using the latest version of any dependencies"
|
||||
required: true
|
||||
- label: "I have checked if any similar bug reports exist"
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: A full description of the bug
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Explain how to reproduce this issue step-by-step, in as much detail as possible.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: hmcc-version
|
||||
attributes:
|
||||
label: Plugin Version
|
||||
description: Run `version HMCCosmetics` in your console and paste the output
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: meg-version
|
||||
attributes:
|
||||
label: ModelEngine Version
|
||||
description: "Run `version ModelEngine` in your console and paste the output. Optional if not using balloons."
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: server-version
|
||||
attributes:
|
||||
label: Server Version
|
||||
description: "Run `version` in your console and paste the output."
|
||||
validations:
|
||||
required: true
|
||||
- type: "dropdown"
|
||||
id: "type"
|
||||
attributes:
|
||||
label: "How breaking is the bug?"
|
||||
options:
|
||||
- "Breaking Bug - Plugin unusable"
|
||||
- "Non-breaking Bug - Plugin still usable, but certain features unavailable"
|
||||
- "Minor Bug - Plugin completely functional, but features have non-working aspects"
|
||||
validations:
|
||||
required: true
|
||||
29
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
29
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Feature Request
|
||||
description: Create a feature request to help us keep track of all features you want to be added
|
||||
title: "[FEATURE] <title>"
|
||||
labels: [feature]
|
||||
|
||||
body:
|
||||
- type: "checkboxes"
|
||||
id: "i-have-checked"
|
||||
attributes:
|
||||
label: "I have checked that..."
|
||||
options:
|
||||
- label: "...such a feature does not exist already"
|
||||
required: true
|
||||
- label: "...such a feature request has not been submitted already"
|
||||
required: true
|
||||
- type: "textarea"
|
||||
id: "description"
|
||||
attributes:
|
||||
label: "Description"
|
||||
description: "A full description of the feature"
|
||||
validations:
|
||||
required: true
|
||||
- type: "textarea"
|
||||
id: "config-changes"
|
||||
attributes:
|
||||
label: "Config Changes"
|
||||
description: "The configuration changes your feature should have"
|
||||
validations:
|
||||
required: false
|
||||
19
.github/ISSUE_TEMPLATE/feature-to-do.md
vendored
19
.github/ISSUE_TEMPLATE/feature-to-do.md
vendored
@@ -1,19 +0,0 @@
|
||||
---
|
||||
name: Feature To-Do
|
||||
about: Create an issue with this template to keep track of the current development projects.
|
||||
title: "[FEATURE] Feature name"
|
||||
labels: enhancement
|
||||
|
||||
---
|
||||
|
||||
**I have checked...**
|
||||
|
||||
- [ ] ...if there are any similar features in other branches
|
||||
- [ ] ...if there are any similar issues
|
||||
- [ ] ...if such a feature is already planned
|
||||
|
||||
**Complete description**
|
||||
Write your feature description as good as you can.
|
||||
|
||||
**Reason for feature request**
|
||||
Write your reason for the feature request as good as you can.
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,4 +1,11 @@
|
||||
# Project exclude paths
|
||||
/.gradle/
|
||||
/gradle/
|
||||
/.idea/
|
||||
/build/
|
||||
/build/classes/java/main/
|
||||
/build/classes/java/main/
|
||||
/common/build/
|
||||
/1.16/build/
|
||||
/1.17/build/
|
||||
/1.18/build/
|
||||
/nms/build/
|
||||
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="16" />
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/discord.xml
generated
7
.idea/discord.xml
generated
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="ASK" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
||||
17
.idea/gradle.xml
generated
17
.idea/gradle.xml
generated
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/hotswap_agent.xml
generated
6
.idea/hotswap_agent.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="HotSwapAgentPluginSettingsProvider">
|
||||
<option name="agentPath" value="C:\Users\barry\AppData\Roaming\JetBrains\IdeaIC2021.2\plugins\hotswap-agent-intellij-plugin\lib\agent\hotswap-agent-1.4.1.jar" />
|
||||
</component>
|
||||
</project>
|
||||
55
.idea/jarRepositories.xml
generated
55
.idea/jarRepositories.xml
generated
@@ -1,55 +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="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</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>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven4" />
|
||||
<option name="name" value="maven4" />
|
||||
<option name="url" value="https://repo.extendedclip.com/content/repositories/placeholderapi/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="MavenRepo" />
|
||||
<option name="name" value="MavenRepo" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven" />
|
||||
<option name="name" value="maven" />
|
||||
<option name="url" value="https://papermc.io/repo/repository/maven-public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven6" />
|
||||
<option name="name" value="maven6" />
|
||||
<option name="url" value="https://jitpack.io" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven2" />
|
||||
<option name="name" value="maven2" />
|
||||
<option name="url" value="https://repo.mattstudios.me/artifactory/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven5" />
|
||||
<option name="name" value="maven5" />
|
||||
<option name="url" value="https://repo.leonardobishop.com/releases/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="MavenLocal" />
|
||||
<option name="name" value="MavenLocal" />
|
||||
<option name="url" value="file:/$MAVEN_REPOSITORY$/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven7" />
|
||||
<option name="name" value="maven7" />
|
||||
<option name="url" value="https://repo.dmulloy2.net/repository/public/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
15
.idea/misc.xml
generated
15
.idea/misc.xml
generated
@@ -1,15 +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="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" default="true" project-jdk-name="16" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
17
.idea/modules/HMCCosmetics.main.iml
generated
17
.idea/modules/HMCCosmetics.main.iml
generated
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="minecraft" name="Minecraft">
|
||||
<configuration>
|
||||
<autoDetectTypes>
|
||||
<platformType>PAPER</platformType>
|
||||
<platformType>MCP</platformType>
|
||||
<platformType>ADVENTURE</platformType>
|
||||
</autoDetectTypes>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="McpModuleSettings">
|
||||
<option name="srgType" value="SRG" />
|
||||
</component>
|
||||
</module>
|
||||
12
.idea/modules/HMCCosmetics.test.iml
generated
12
.idea/modules/HMCCosmetics.test.iml
generated
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="minecraft" name="Minecraft">
|
||||
<configuration>
|
||||
<autoDetectTypes>
|
||||
<platformType>ADVENTURE</platformType>
|
||||
</autoDetectTypes>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
</module>
|
||||
124
.idea/uiDesigner.xml
generated
124
.idea/uiDesigner.xml
generated
@@ -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>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -10,17 +10,15 @@
|
||||
|
||||
### Description
|
||||
|
||||
HMCCosmetics is a free, open source cosmetics plugin which allows you to easily give players backpack and hat type cosmetics.
|
||||
|
||||
HMCCosmetics is an intuitive, easy-to-use cosmetics plugin, designed for servers using resource packs.
|
||||
|
||||
### Requirements
|
||||
|
||||
- Server running PaperMC (or a fork of PaperMC)
|
||||
- ProtocolLib
|
||||
- [packetevents 2.0](https://github.com/retrooper/packetevents)
|
||||
|
||||
### Download
|
||||
|
||||
Download on the [Releases Page](https://github.com/HibiscusMC/HMCCosmetics/releases)
|
||||
If you would like to support the development of our plugin, please purchase it on [Polymart](https://polymart.org/resource/hmccosmetics.1879)
|
||||
|
||||
|
||||
|
||||
|
||||
51
build.gradle
51
build.gradle
@@ -1,51 +0,0 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'com.github.johnrengelman.shadow' version '6.1.0'
|
||||
}
|
||||
|
||||
group 'io.github.fisher2911'
|
||||
version '1.0.2'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven { url = 'https://papermc.io/repo/repository/maven-public/' }
|
||||
maven { url = 'https://repo.mattstudios.me/artifactory/public/' }
|
||||
maven { url = 'https://jitpack.io' }
|
||||
maven { url = 'https://repo.leonardobishop.com/releases/' }
|
||||
maven { url = 'https://repo.dmulloy2.net/repository/public/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
|
||||
compileOnly 'io.papermc.paper:paper:1.17.1-R0.1-SNAPSHOT'
|
||||
compileOnly 'org.jetbrains:annotations:22.0.0'
|
||||
compileOnly 'com.comphenix.protocol:ProtocolLib:4.7.0'
|
||||
compileOnly 'net.kyori:adventure-api:4.9.3'
|
||||
implementation 'net.kyori:adventure-text-minimessage:4.2.0-SNAPSHOT'
|
||||
implementation 'net.kyori:adventure-platform-bukkit:4.0.0'
|
||||
implementation 'dev.triumphteam:triumph-gui:3.0.3'
|
||||
implementation 'me.mattstudios.utils:matt-framework:1.4.6'
|
||||
implementation 'org.spongepowered:configurate-yaml:4.1.2'
|
||||
implementation 'org.bstats:bstats-bukkit:2.2.1'
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'dev.triumphteam.gui', 'io.github.fisher2911.hmccosmetics.gui'
|
||||
relocate 'me.mattstudios.mf', 'io.github.fisher2911.hmccosmetics.mf'
|
||||
relocate 'net.kyori.adventure.text.minimessage', 'io.github.fisher2911.hmccosmetics.adventure.minimessage'
|
||||
relocate 'net.kyori.adventure.platform', 'io.github.fisher2911.hmccosmetics.adventure.platform'
|
||||
relocate 'org.spongepowered.configurate', 'io.github.fisher2911.hmccosmetics.configurate'
|
||||
relocate 'org.bstats', 'io.github.fisher2911.hmccosmetics.bstats'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveBaseName.set('HMCCosmetics')
|
||||
archiveClassifier.set('')
|
||||
archiveVersion.set('')
|
||||
}
|
||||
3
build.gradle.kts
Normal file
3
build.gradle.kts
Normal file
@@ -0,0 +1,3 @@
|
||||
plugins {
|
||||
id("java")
|
||||
}
|
||||
Binary file not shown.
BIN
common/.gradle/7.1.1/executionHistory/executionHistory.bin
Normal file
BIN
common/.gradle/7.1.1/executionHistory/executionHistory.bin
Normal file
Binary file not shown.
BIN
common/.gradle/7.1.1/executionHistory/executionHistory.lock
Normal file
BIN
common/.gradle/7.1.1/executionHistory/executionHistory.lock
Normal file
Binary file not shown.
BIN
common/.gradle/7.1.1/fileChanges/last-build.bin
Normal file
BIN
common/.gradle/7.1.1/fileChanges/last-build.bin
Normal file
Binary file not shown.
BIN
common/.gradle/7.1.1/fileHashes/fileHashes.bin
Normal file
BIN
common/.gradle/7.1.1/fileHashes/fileHashes.bin
Normal file
Binary file not shown.
BIN
common/.gradle/7.1.1/fileHashes/fileHashes.lock
Normal file
BIN
common/.gradle/7.1.1/fileHashes/fileHashes.lock
Normal file
Binary file not shown.
0
common/.gradle/7.1.1/gc.properties
Normal file
0
common/.gradle/7.1.1/gc.properties
Normal file
BIN
common/.gradle/7.3.3/checksums/checksums.lock
Normal file
BIN
common/.gradle/7.3.3/checksums/checksums.lock
Normal file
Binary file not shown.
Binary file not shown.
BIN
common/.gradle/7.3.3/executionHistory/executionHistory.lock
Normal file
BIN
common/.gradle/7.3.3/executionHistory/executionHistory.lock
Normal file
Binary file not shown.
BIN
common/.gradle/7.3.3/fileChanges/last-build.bin
Normal file
BIN
common/.gradle/7.3.3/fileChanges/last-build.bin
Normal file
Binary file not shown.
BIN
common/.gradle/7.3.3/fileHashes/fileHashes.lock
Normal file
BIN
common/.gradle/7.3.3/fileHashes/fileHashes.lock
Normal file
Binary file not shown.
0
common/.gradle/7.3.3/gc.properties
Normal file
0
common/.gradle/7.3.3/gc.properties
Normal file
BIN
common/.gradle/buildOutputCleanup/buildOutputCleanup.lock
Normal file
BIN
common/.gradle/buildOutputCleanup/buildOutputCleanup.lock
Normal file
Binary file not shown.
2
common/.gradle/buildOutputCleanup/cache.properties
Normal file
2
common/.gradle/buildOutputCleanup/cache.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
#Wed Feb 02 16:44:24 EST 2022
|
||||
gradle.version=7.3.3
|
||||
BIN
common/.gradle/buildOutputCleanup/outputFiles.bin
Normal file
BIN
common/.gradle/buildOutputCleanup/outputFiles.bin
Normal file
Binary file not shown.
BIN
common/.gradle/checksums/checksums.lock
Normal file
BIN
common/.gradle/checksums/checksums.lock
Normal file
Binary file not shown.
0
common/.gradle/vcs-1/gc.properties
Normal file
0
common/.gradle/vcs-1/gc.properties
Normal file
168
common/build.gradle.kts
Normal file
168
common/build.gradle.kts
Normal file
@@ -0,0 +1,168 @@
|
||||
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
|
||||
|
||||
plugins {
|
||||
id("java")
|
||||
id("com.github.johnrengelman.shadow") version "7.1.1"
|
||||
id("net.minecrell.plugin-yml.bukkit") version "0.5.1"
|
||||
}
|
||||
|
||||
group = "io.github.fisher2911"
|
||||
version = "1.12.0-BETA-5"
|
||||
description = "Intuitive, easy-to-use cosmetics plugin, designed for servers using resource packs.\n"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://papermc.io/repo/repository/maven-public/")
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
maven("https://repo.mattstudios.me/artifactory/public/")
|
||||
maven("https://jitpack.io")
|
||||
maven("https://repo.dmulloy2.net/repository/public/")
|
||||
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
|
||||
maven("https://mvnrepository.com/artifact/com.zaxxer/HikariCP")
|
||||
maven("https://repo.jeff-media.de/maven2/")
|
||||
maven("https://repo.citizensnpcs.co")
|
||||
//maven("https://mvn.lumine.io/repository/maven-public")
|
||||
maven {
|
||||
url = uri("https://mvn.lumine.io/repository/maven-public")
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
maven("https://jitpack.io/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// implementation(project(":1.16"))
|
||||
// implementation(project(":1.17"))
|
||||
// implementation(project(":1.18"))
|
||||
// implementation(project(":nms"))
|
||||
compileOnly("com.mojang:authlib:1.5.25")
|
||||
compileOnly("org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT")
|
||||
compileOnly("org.jetbrains:annotations:23.0.0")
|
||||
compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0-SNAPSHOT")
|
||||
compileOnly("me.clip:placeholderapi:2.11.1")
|
||||
compileOnly("com.github.oraxen:oraxen:-SNAPSHOT")
|
||||
compileOnly("com.github.LoneDev6:API-ItemsAdder:2.5.4")
|
||||
compileOnly("net.citizensnpcs:citizens-main:2.0.30-SNAPSHOT")
|
||||
compileOnly("com.ticxo.modelengine:api:R3.0.0")
|
||||
//compileOnly("com.github.retrooper.packetevents:spigot:2.0-SNAPSHOT")
|
||||
implementation("net.kyori:adventure-api:4.11.0")
|
||||
implementation ("net.kyori:adventure-text-minimessage:4.11.0")
|
||||
implementation("net.kyori:adventure-platform-bukkit:4.1.2")
|
||||
implementation("dev.triumphteam:triumph-gui:3.1.3")
|
||||
implementation("me.mattstudios.utils:matt-framework:1.4.6")
|
||||
implementation("org.spongepowered:configurate-yaml:4.1.2")
|
||||
implementation("org.bstats:bstats-bukkit:3.0.0")
|
||||
implementation("com.zaxxer:HikariCP:5.0.1")
|
||||
implementation("com.j256.ormlite:ormlite-jdbc:6.1")
|
||||
implementation("com.j256.ormlite:ormlite-core:6.1")
|
||||
}
|
||||
|
||||
tasks {
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(16)
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate("dev.triumphteam.gui", "io.github.fisher2911.hmccosmetics.gui")
|
||||
relocate("me.mattstudios.mf", "io.github.fisher2911.hmccosmetics.mf")
|
||||
relocate("net.kyori.adventure", "io.github.fisher2911.hmccosmetics.adventure")
|
||||
relocate("org.spongepowered.configurate", "io.github.fisher2911.hmccosmetics.configurate")
|
||||
relocate("org.bstats", "io.github.fisher2911.hmccosmetics.bstats")
|
||||
relocate("com.zaxxer.hikaricp", "io.github.fisher2911.hmccosmetics.hikaricp")
|
||||
relocate("com.j256.ormlite", "io.github.fisher2911.hmccosmetics.ormlite")
|
||||
//relocate("com.github.retrooper.packetevents", "io.github.fisher2911.hmccosmetics.packetevents")
|
||||
//relocate("io.github.retrooper.packetevents", "io.github.fisher2911.hmccosmetics.packetevents")
|
||||
archiveFileName.set("HMCCosmetics.jar")
|
||||
|
||||
dependencies {
|
||||
exclude(dependency("org.yaml:snakeyaml"))
|
||||
}
|
||||
|
||||
// todo - remove (Testing only)
|
||||
//destinationDirectory.set(file("D:\\paper-1.18.1\\plugins"))
|
||||
}
|
||||
|
||||
javadoc {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
|
||||
processResources {
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
filteringCharset = Charsets.UTF_8.name()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(16
|
||||
))
|
||||
}
|
||||
|
||||
bukkit {
|
||||
load = BukkitPluginDescription.PluginLoadOrder.STARTUP
|
||||
main = "io.github.fisher2911.hmccosmetics.HMCCosmetics"
|
||||
apiVersion = "1.16"
|
||||
name = "HMCCosmetics"
|
||||
authors = listOf("MasterOfTheFish")
|
||||
softDepend = listOf("Multiverse", "PlaceholderAPI", "Oraxen", "ItemsAdder", "Citizens", "ModelEngine")
|
||||
depend = listOf("ProtocolLib")
|
||||
permissions {
|
||||
register("hmccosmetics.cmd.default") {
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
description = "Permission to execute the default command."
|
||||
}
|
||||
register("hmccosmetics.cmd.dye") {
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
description = "Permission to dye armor."
|
||||
}
|
||||
register("hmccosmetics.cmd.reload") {
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
description = "Permission to use the reload command."
|
||||
}
|
||||
register("hmccosmetics.cmd.set") {
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
description = "Permission to set other users' cosmetics."
|
||||
}
|
||||
register("hmccosmetics.cmd.wardrobe.portable") {
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
description = "Permission to use a portable wardrobe"
|
||||
}
|
||||
register("hmccosmetics.cmd.wardrobe") {
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
description = "Permission to view the wardrobe"
|
||||
}
|
||||
register("hmccosmetics.cmd.wardrobe.other") {
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
description = "Permission to open another player's wardrobe"
|
||||
}
|
||||
register("hmccosmetics.cmd.token.give") {
|
||||
default = BukkitPluginDescription.Permission.Default.OP
|
||||
description = "Permission to give other players tokens"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val copyJar: String? by project
|
||||
val pluginPath = project.findProperty("hibiscusmc_plugin_path")
|
||||
|
||||
if(copyJar != "false" && pluginPath != null) {
|
||||
tasks {
|
||||
register<Copy>("copyJar") {
|
||||
from(findByName("reobfJar") ?: findByName("shadowJar") ?: findByName("jar"))
|
||||
into(pluginPath)
|
||||
doLast {
|
||||
println("Copied to plugin directory $pluginPath")
|
||||
}
|
||||
}
|
||||
|
||||
named<DefaultTask>("build") {
|
||||
dependsOn("copyJar")
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
common/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
common/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
common/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
common/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -0,0 +1,254 @@
|
||||
package io.github.fisher2911.hmccosmetics;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import io.github.fisher2911.hmccosmetics.command.CosmeticsCommand;
|
||||
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
|
||||
import io.github.fisher2911.hmccosmetics.config.Settings;
|
||||
import io.github.fisher2911.hmccosmetics.config.TokenLoader;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.database.Database;
|
||||
import io.github.fisher2911.hmccosmetics.database.DatabaseFactory;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
|
||||
import io.github.fisher2911.hmccosmetics.gui.Token;
|
||||
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
|
||||
import io.github.fisher2911.hmccosmetics.hook.HookManager;
|
||||
import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook;
|
||||
import io.github.fisher2911.hmccosmetics.listener.ClickListener;
|
||||
import io.github.fisher2911.hmccosmetics.listener.CosmeticFixListener;
|
||||
import io.github.fisher2911.hmccosmetics.listener.JoinListener;
|
||||
import io.github.fisher2911.hmccosmetics.listener.PlayerShiftListener;
|
||||
import io.github.fisher2911.hmccosmetics.listener.RespawnListener;
|
||||
import io.github.fisher2911.hmccosmetics.listener.TeleportListener;
|
||||
import io.github.fisher2911.hmccosmetics.listener.WardrobeListener;
|
||||
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
|
||||
import io.github.fisher2911.hmccosmetics.message.Messages;
|
||||
import io.github.fisher2911.hmccosmetics.message.Translation;
|
||||
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
|
||||
import io.github.fisher2911.hmccosmetics.task.TaskManager;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import me.mattstudios.mf.base.CommandManager;
|
||||
import me.mattstudios.mf.base.CompletionHandler;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class HMCCosmetics extends JavaPlugin {
|
||||
|
||||
public static final Path PLUGIN_FOLDER = Paths.get("plugins", "HMCCosmetics");
|
||||
|
||||
private TaskManager taskManager;
|
||||
private Settings settings;
|
||||
private UserManager userManager;
|
||||
private CosmeticManager cosmeticManager;
|
||||
private MessageHandler messageHandler;
|
||||
private CosmeticsMenu cosmeticsMenu;
|
||||
private TokenLoader tokenLoader;
|
||||
private CommandManager commandManager;
|
||||
private Database database;
|
||||
|
||||
private BukkitTask saveTask;
|
||||
private ProtocolManager manager;
|
||||
|
||||
/* // commented because PacketEvents is no longer shaded
|
||||
@Override
|
||||
public void onLoad() {
|
||||
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
||||
PacketEvents.getAPI().load();
|
||||
}
|
||||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
final int pluginId = 13873;
|
||||
final Metrics metrics = new Metrics(this, pluginId);
|
||||
this.taskManager = new TaskManager(this);
|
||||
this.taskManager.start();
|
||||
this.settings = new Settings(this);
|
||||
this.messageHandler = new MessageHandler(this);
|
||||
this.userManager = new UserManager(this);
|
||||
this.cosmeticManager = new CosmeticManager(new HashMap<>(), new HashMap<>(), new HashMap<>());
|
||||
this.cosmeticsMenu = new CosmeticsMenu(this);
|
||||
this.tokenLoader = new TokenLoader(this);
|
||||
this.manager = ProtocolLibrary.getProtocolManager();
|
||||
|
||||
this.userManager.startTeleportTask();
|
||||
|
||||
try {
|
||||
this.database = DatabaseFactory.create(this);
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
PacketManager.setupPackets();
|
||||
this.registerCommands();
|
||||
this.registerListeners();
|
||||
|
||||
if (!HookManager.getInstance().isEnabled(ItemsAdderHook.class)) {
|
||||
this.load();
|
||||
}
|
||||
|
||||
HookManager.getInstance().init();
|
||||
|
||||
this.saveTask = Bukkit.getScheduler().runTaskTimerAsynchronously(
|
||||
this,
|
||||
() -> Threads.getInstance().execute(
|
||||
() -> this.database.saveAll()
|
||||
),
|
||||
20 * 60,
|
||||
20 * 60
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
//PacketEvents.getAPI().terminate();
|
||||
this.saveTask.cancel();
|
||||
this.database.saveAll();
|
||||
this.messageHandler.close();
|
||||
this.userManager.removeAll();
|
||||
Threads.getInstance().onDisable();
|
||||
this.database.close();
|
||||
this.taskManager.end();
|
||||
}
|
||||
|
||||
private void registerListeners() {
|
||||
List.of(
|
||||
new JoinListener(this),
|
||||
new ClickListener(this),
|
||||
new TeleportListener(this),
|
||||
new RespawnListener(this),
|
||||
new CosmeticFixListener(this),
|
||||
new PlayerShiftListener(this),
|
||||
new WardrobeListener(this)
|
||||
).
|
||||
forEach(
|
||||
listener -> this.getServer().getPluginManager()
|
||||
.registerEvents(listener, this)
|
||||
);
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
this.commandManager = new CommandManager(this, true);
|
||||
final HookManager hookManager = HookManager.getInstance();
|
||||
final me.mattstudios.mf.base.MessageHandler messageHandler = this.commandManager.getMessageHandler();
|
||||
messageHandler.register("cmd.no.console", player ->
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.MUST_BE_PLAYER
|
||||
)
|
||||
);
|
||||
messageHandler.register("cmd.no.permission", player ->
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.NO_PERMISSION
|
||||
)
|
||||
);
|
||||
messageHandler.register("cmd.no.exists", player ->
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.HELP_COMMAND
|
||||
));
|
||||
messageHandler.register("cmd.wrong.usage", player ->
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.HELP_COMMAND
|
||||
));
|
||||
final CompletionHandler completionHandler = this.commandManager.getCompletionHandler();
|
||||
completionHandler.register("#types",
|
||||
resolver ->
|
||||
Arrays.stream(ArmorItem.Type.
|
||||
values()).
|
||||
map(ArmorItem.Type::toString).
|
||||
collect(Collectors.toList())
|
||||
);
|
||||
completionHandler.register("#ids",
|
||||
resolver ->
|
||||
this.cosmeticManager.getAllArmorItems().stream().map(ArmorItem::getId)
|
||||
.collect(Collectors.toList()));
|
||||
completionHandler.register("#tokens",
|
||||
resolver ->
|
||||
this.cosmeticManager.getAllTokens().stream().map(Token::getId)
|
||||
.collect(Collectors.toList()));
|
||||
completionHandler.register("#menus",
|
||||
resolver -> new ArrayList<>(this.cosmeticsMenu.getMenus())
|
||||
);
|
||||
completionHandler.register("#npc-args",
|
||||
resolver -> List.of(CosmeticsCommand.NPC_REMOVE, CosmeticsCommand.NPC_APPLY));
|
||||
completionHandler.register("#npcs", resolver -> {
|
||||
final List<String> ids = new ArrayList<>();
|
||||
if (!hookManager.isEnabled(CitizensHook.class)) return ids;
|
||||
for (final int id : hookManager.getCitizensHook().getAllNPCS()) {
|
||||
ids.add(String.valueOf(id));
|
||||
}
|
||||
return ids;
|
||||
});
|
||||
this.commandManager.register(new CosmeticsCommand(this));
|
||||
}
|
||||
|
||||
public void load() {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(this,
|
||||
() -> {
|
||||
this.settings.load();
|
||||
this.messageHandler.load();
|
||||
this.cosmeticsMenu.load();
|
||||
this.tokenLoader.load();
|
||||
Translation.getInstance().load();
|
||||
this.database.load();
|
||||
}, 1);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(this,
|
||||
() -> {
|
||||
this.settings.load();
|
||||
this.messageHandler.load();
|
||||
this.cosmeticsMenu.reload();
|
||||
this.tokenLoader.load();
|
||||
Translation.getInstance().load();
|
||||
});
|
||||
}
|
||||
|
||||
public TaskManager getTaskManager() {
|
||||
return taskManager;
|
||||
}
|
||||
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public MessageHandler getMessageHandler() {
|
||||
return messageHandler;
|
||||
}
|
||||
|
||||
public UserManager getUserManager() {
|
||||
return userManager;
|
||||
}
|
||||
|
||||
public CosmeticManager getCosmeticManager() {
|
||||
return cosmeticManager;
|
||||
}
|
||||
|
||||
public CosmeticsMenu getCosmeticsMenu() {
|
||||
return cosmeticsMenu;
|
||||
}
|
||||
|
||||
public Database getDatabase() {
|
||||
return database;
|
||||
}
|
||||
public ProtocolManager getProtocolManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package io.github.fisher2911.hmccosmetics.api;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* Wrapper for ArmorItem used internally for convenience and safety
|
||||
*/
|
||||
public class CosmeticItem {
|
||||
|
||||
private final ArmorItem armorItem;
|
||||
|
||||
public CosmeticItem(final ArmorItem armorItem) {
|
||||
this.armorItem = armorItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemStack the {@link org.bukkit.inventory.ItemStack} display item
|
||||
* @param id the id of the item
|
||||
* @param type the cosmetic item type
|
||||
* @param dyeable whether the item can be dyed
|
||||
* @param rgb from Bukkit's {@link Color#asRGB()}
|
||||
*/
|
||||
|
||||
public CosmeticItem(
|
||||
final ItemStack itemStack,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack locked,
|
||||
final ItemStack applied,
|
||||
final String permission,
|
||||
final ArmorItem.Type type,
|
||||
final boolean dyeable,
|
||||
final int rgb) {
|
||||
this.armorItem = new ArmorItem(itemStack, name, id, locked, applied, permission, type, dyeable, rgb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param material the {@link org.bukkit.Material} display item
|
||||
* @param id the id of the item
|
||||
* @param type the cosmetic item type
|
||||
* @param dyeable whether the item can be dyed
|
||||
* @param rgb from Bukkit's {@link Color#asRGB()}
|
||||
*/
|
||||
|
||||
public CosmeticItem(
|
||||
final Material material,
|
||||
final String name,
|
||||
final String id,
|
||||
final Material locked,
|
||||
final Material applied,
|
||||
final String permission,
|
||||
final ArmorItem.Type type,
|
||||
final boolean dyeable,
|
||||
final int rgb
|
||||
) {
|
||||
this.armorItem = new ArmorItem(material, name, id, new ItemStack(locked), new ItemStack(applied), permission, type, dyeable, rgb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemStack the {@link org.bukkit.inventory.ItemStack} display item
|
||||
* @param id the id of the item
|
||||
* @param type the cosmetic item type
|
||||
*/
|
||||
|
||||
public CosmeticItem(final ItemStack itemStack, final String name, final String id, final ItemStack locked, final ItemStack applied, final ArmorItem.Type type) {
|
||||
this(itemStack, name, id, locked, applied, "", type, false, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param material the {@link org.bukkit.Material} display item
|
||||
* @param id the id of the item
|
||||
* @param type the cosmetic item type
|
||||
*/
|
||||
|
||||
public CosmeticItem(final Material material, final Material locked, final Material applied, final String name, final String id, final ArmorItem.Type type) {
|
||||
this(material, name, id, locked, applied, "", type, false, -1);
|
||||
}
|
||||
|
||||
public ItemStack getItemStack(final ArmorItem.Status status) {
|
||||
return this.armorItem.getItemStack(status);
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return this.armorItem.getItemStack();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.armorItem.getId();
|
||||
}
|
||||
|
||||
public ArmorItem.Type getType() {
|
||||
return this.armorItem.getType();
|
||||
}
|
||||
|
||||
public boolean isDyeable() {
|
||||
return this.armorItem.isDyeable();
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return this.armorItem.getDye();
|
||||
}
|
||||
|
||||
public ArmorItem getArmorItem() {
|
||||
return this.armorItem;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package io.github.fisher2911.hmccosmetics.api;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class HMCCosmeticsAPI {
|
||||
|
||||
private static final HMCCosmetics plugin;
|
||||
|
||||
static {
|
||||
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will attempt to get the {@link CosmeticItem} that
|
||||
* the user is wearing. It returns an empty {@link CosmeticItem}
|
||||
* if the user is not found, or if the user is not wearing a cosmetic
|
||||
*
|
||||
* @param uuid the uuid of the user
|
||||
* @param type the type of cosmetic being retrieved
|
||||
* @return the current cosmetic of the player
|
||||
*/
|
||||
public static CosmeticItem getUserCurrentItem(final UUID uuid, final ArmorItem.Type type) {
|
||||
final Optional<User> userOptional = plugin.getUserManager().get(uuid);
|
||||
if (userOptional.isEmpty()) {
|
||||
return new CosmeticItem(ArmorItem.empty(type));
|
||||
}
|
||||
return new CosmeticItem(userOptional.get().getPlayerArmor().getItem(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uuid the uuid of the user whose cosmetic is being set
|
||||
* @param cosmeticItem the cosmetic being set
|
||||
* @return true if the cosmetic was set, or else false
|
||||
*/
|
||||
public static boolean setCosmeticItem(final UUID uuid, final CosmeticItem cosmeticItem) {
|
||||
final UserManager userManager = plugin.getUserManager();
|
||||
final Optional<User> userOptional = userManager.get(uuid);
|
||||
if (userOptional.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
userManager.setItem(userOptional.get(), cosmeticItem.getArmorItem(), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id the id of the cosmetic item being retrieved
|
||||
* @return null if the cosmetic was not found, or a copy of the cosmetic item
|
||||
*/
|
||||
|
||||
@Nullable
|
||||
public static CosmeticItem getCosmeticFromId(final String id) {
|
||||
final ArmorItem armorItem = plugin.getCosmeticManager().getArmorItem(id);
|
||||
if (armorItem == null) {
|
||||
return null;
|
||||
}
|
||||
return new CosmeticItem(armorItem.copy());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uuid the uuid of the user whose armor stand id is being retrieved
|
||||
* @return the armor stand id, or -1 if the user is not found
|
||||
*/
|
||||
|
||||
public static int getUserArmorStandId(final UUID uuid) {
|
||||
final Optional<User> userOptional = plugin.getUserManager().get(uuid);
|
||||
if (userOptional.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
return userOptional.get().getArmorStandId();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package io.github.fisher2911.hmccosmetics.api.event;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;
|
||||
import io.github.fisher2911.hmccosmetics.user.BaseUser;
|
||||
|
||||
|
||||
/**
|
||||
* Called when a user changes their equipped cosmetic
|
||||
*/
|
||||
public class CosmeticChangeEvent extends CosmeticItemEvent {
|
||||
|
||||
private final BaseUser<?> user;
|
||||
private CosmeticItem removed;
|
||||
|
||||
public CosmeticChangeEvent(
|
||||
final CosmeticItem cosmeticItem,
|
||||
final CosmeticItem removed,
|
||||
final BaseUser<?> user) {
|
||||
super(cosmeticItem);
|
||||
this.removed = removed;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public CosmeticChangeEvent(final boolean isAsync, final CosmeticItem cosmeticItem, final CosmeticItem removed, final BaseUser<?> user) {
|
||||
super(isAsync, cosmeticItem);
|
||||
this.removed = removed;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public BaseUser<?> getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public CosmeticItem getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void setRemoved(final CosmeticItem removed) {
|
||||
this.removed = removed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package io.github.fisher2911.hmccosmetics.api.event;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public abstract class CosmeticItemEvent extends Event implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private CosmeticItem cosmeticItem;
|
||||
private boolean cancelled;
|
||||
|
||||
public CosmeticItemEvent(final CosmeticItem cosmeticItem) {
|
||||
this.cosmeticItem = cosmeticItem;
|
||||
this.cancelled = false;
|
||||
}
|
||||
|
||||
public CosmeticItemEvent(final boolean isAsync, final CosmeticItem cosmeticItem) {
|
||||
super(isAsync);
|
||||
this.cosmeticItem = cosmeticItem;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
public CosmeticItem getCosmeticItem() {
|
||||
return this.cosmeticItem;
|
||||
}
|
||||
|
||||
public void setCosmeticItem(final CosmeticItem cosmeticItem) {
|
||||
this.cosmeticItem = cosmeticItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(final boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
package io.github.fisher2911.hmccosmetics.command;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
|
||||
import io.github.fisher2911.hmccosmetics.config.Settings;
|
||||
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
|
||||
import io.github.fisher2911.hmccosmetics.gui.Token;
|
||||
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
|
||||
import io.github.fisher2911.hmccosmetics.hook.HookManager;
|
||||
import io.github.fisher2911.hmccosmetics.message.Message;
|
||||
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
|
||||
import io.github.fisher2911.hmccosmetics.message.Messages;
|
||||
import io.github.fisher2911.hmccosmetics.message.Placeholder;
|
||||
import io.github.fisher2911.hmccosmetics.task.TaskChain;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
|
||||
import io.github.fisher2911.hmccosmetics.util.StringUtils;
|
||||
import me.mattstudios.mf.annotations.Command;
|
||||
import me.mattstudios.mf.annotations.Completion;
|
||||
import me.mattstudios.mf.annotations.Default;
|
||||
import me.mattstudios.mf.annotations.Permission;
|
||||
import me.mattstudios.mf.annotations.SubCommand;
|
||||
import me.mattstudios.mf.base.CommandBase;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Command("cosmetics")
|
||||
public class CosmeticsCommand extends CommandBase {
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final UserManager userManager;
|
||||
private final MessageHandler messageHandler;
|
||||
private final CosmeticsMenu cosmeticsMenu;
|
||||
private final CosmeticManager cosmeticManager;
|
||||
private final Settings settings;
|
||||
private final CosmeticSettings cosmeticSettings;
|
||||
|
||||
public CosmeticsCommand(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.userManager = this.plugin.getUserManager();
|
||||
this.messageHandler = this.plugin.getMessageHandler();
|
||||
this.cosmeticsMenu = this.plugin.getCosmeticsMenu();
|
||||
this.cosmeticManager = this.plugin.getCosmeticManager();
|
||||
this.settings = this.plugin.getSettings();
|
||||
this.cosmeticSettings = this.settings.getCosmeticSettings();
|
||||
}
|
||||
|
||||
@Default
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
|
||||
public void defaultCommand(final Player player) {
|
||||
this.defaultCommand(player, this.cosmeticSettings.getDefaultMenu());
|
||||
}
|
||||
|
||||
@SubCommand("menu")
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DEFAULT_COMMAND)
|
||||
public void defaultCommand(
|
||||
final Player player,
|
||||
@Completion("#menus") @me.mattstudios.mf.annotations.Optional String menu) {
|
||||
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
if (menu == null) menu = this.cosmeticSettings.getDefaultMenu();
|
||||
if (optionalUser.isEmpty()) {
|
||||
this.cosmeticsMenu.openMenu(menu, player);
|
||||
return;
|
||||
}
|
||||
final User user = optionalUser.get();
|
||||
final Wardrobe wardrobe = user.getWardrobe();
|
||||
if (wardrobe.isActive() &&
|
||||
!this.settings.getWardrobeSettings().inDistanceOfWardrobe(wardrobe.getCurrentLocation(), player.getLocation())) {
|
||||
wardrobe.setActive(false);
|
||||
wardrobe.despawnFakePlayer(player, userManager);
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.CLOSED_WARDROBE
|
||||
);
|
||||
}
|
||||
this.cosmeticsMenu.openMenu(menu, player);
|
||||
}
|
||||
|
||||
@SubCommand("reload")
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.RELOAD_COMMAND)
|
||||
public void reloadCommand(final CommandSender sender) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(
|
||||
this.plugin,
|
||||
() -> {
|
||||
this.plugin.reload();
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.RELOADED
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@SubCommand("dye")
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.DYE_COMMAND)
|
||||
public void dyeArmor(
|
||||
final Player player,
|
||||
@Completion("#types") String typeString,
|
||||
final @me.mattstudios.mf.annotations.Optional String dyeColor
|
||||
) {
|
||||
|
||||
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
|
||||
if (optionalUser.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeString.toUpperCase());
|
||||
|
||||
final User user = optionalUser.get();
|
||||
|
||||
if (dyeColor == null) {
|
||||
this.cosmeticsMenu.openDyeSelectorGui(user, type);
|
||||
return;
|
||||
}
|
||||
|
||||
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
|
||||
|
||||
this.setDyeColor(dyeColor, armorItem, player);
|
||||
|
||||
this.userManager.setItem(user, armorItem, true);
|
||||
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.SET_DYE_COLOR,
|
||||
Map.of(Placeholder.ITEM, StringUtils.formatArmorItemType(typeString))
|
||||
);
|
||||
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.INVALID_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@SubCommand("help") // WORK IN PROGRESS (WIP)
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.HELP_COMMAND)
|
||||
public void helpCommand(final CommandSender sender) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.HELP_COMMAND
|
||||
);
|
||||
}
|
||||
|
||||
@SubCommand("add")
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.SET_COSMETIC_COMMAND)
|
||||
public void setCommand(
|
||||
final CommandSender sender,
|
||||
@Completion("#players") final Player player,
|
||||
@Completion("#ids") final String id,
|
||||
final @me.mattstudios.mf.annotations.Optional String dyeColor
|
||||
) {
|
||||
final Optional<User> userOptional = this.userManager.get(player.getUniqueId());
|
||||
|
||||
if (userOptional.isEmpty()) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.INVALID_USER
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = userOptional.get();
|
||||
final ArmorItem armorItem = this.plugin.getCosmeticManager().getArmorItem(id);
|
||||
|
||||
if (armorItem == null) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.ITEM_NOT_FOUND
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dyeColor != null) {
|
||||
this.setDyeColor(dyeColor, armorItem, player);
|
||||
}
|
||||
|
||||
final Message setMessage = Messages.getSetMessage(armorItem.getType());
|
||||
final Message setOtherMessage = Messages.getSetOtherMessage(armorItem.getType());
|
||||
this.userManager.setItem(user, armorItem, true);
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
setMessage
|
||||
);
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
setOtherMessage,
|
||||
Map.of(Placeholder.PLAYER, player.getName(),
|
||||
Placeholder.TYPE, id)
|
||||
);
|
||||
}
|
||||
|
||||
@SubCommand("remove")
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.SET_COSMETIC_COMMAND)
|
||||
public void removeCommand(
|
||||
final CommandSender sender,
|
||||
@Completion("#players") final Player player,
|
||||
@Completion("#types") String typeString
|
||||
) {
|
||||
final Optional<User> userOptional = this.userManager.get(player.getUniqueId());
|
||||
|
||||
if (userOptional.isEmpty()) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.INVALID_USER
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = userOptional.get();
|
||||
|
||||
try {
|
||||
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeString.toUpperCase());
|
||||
|
||||
final Message setOtherMessage = Messages.getSetOtherMessage(type);
|
||||
this.userManager.removeItem(user, type, true);
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
setOtherMessage,
|
||||
Map.of(Placeholder.PLAYER, player.getName(),
|
||||
Placeholder.TYPE, "none")
|
||||
);
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
this.messageHandler.sendMessage(player, Messages.INVALID_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@SubCommand("wardrobe")
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.WARDROBE)
|
||||
public void openWardrobe(
|
||||
CommandSender sender,
|
||||
@me.mattstudios.mf.annotations.Optional final Player other
|
||||
) {
|
||||
Player player = null;
|
||||
if (other != null) {
|
||||
if (!sender.hasPermission(io.github.fisher2911.hmccosmetics.message.Permission.OPEN_OTHER_WARDROBE)) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.NO_PERMISSION
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.OPENED_OTHER_WARDROBE,
|
||||
Map.of(Placeholder.PLAYER, other.getName())
|
||||
);
|
||||
player = other;
|
||||
} else if (!(sender instanceof final Player p)) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.MUST_BE_PLAYER
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
player = p;
|
||||
}
|
||||
|
||||
final Optional<User> optionalUser = this.plugin.getUserManager().get(player.getUniqueId());
|
||||
if (optionalUser.isEmpty()) return;
|
||||
|
||||
final User user = optionalUser.get();
|
||||
|
||||
final Wardrobe wardrobe = user.getWardrobe();
|
||||
if (wardrobe.isActive()) {
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.WARDROBE_ALREADY_OPEN
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final WardrobeSettings settings = this.settings.getWardrobeSettings();
|
||||
|
||||
final boolean inDistanceOfStatic = settings.inDistanceOfStatic(player.getLocation());
|
||||
|
||||
if (!settings.isPortable() && !inDistanceOfStatic) {
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.NOT_NEAR_WARDROBE
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.isPortable() && !inDistanceOfStatic) {
|
||||
if (!player.hasPermission(io.github.fisher2911.hmccosmetics.message.Permission.PORTABLE_WARDROBE)) {
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.CANNOT_USE_PORTABLE_WARDROBE
|
||||
);
|
||||
return;
|
||||
}
|
||||
wardrobe.setCurrentLocation(null);
|
||||
}
|
||||
|
||||
settings.playOpenSound(player);
|
||||
|
||||
final Player finalPlayer = player;
|
||||
new TaskChain(this.plugin).
|
||||
chain(() -> wardrobe.spawnFakePlayer(finalPlayer), true).
|
||||
chain(() -> {
|
||||
// this.cosmeticsMenu.openDefault(finalPlayer);
|
||||
this.messageHandler.sendMessage(
|
||||
finalPlayer,
|
||||
Messages.OPENED_WARDROBE
|
||||
);
|
||||
}).execute();
|
||||
}
|
||||
|
||||
public static final String NPC_APPLY = "apply";
|
||||
public static final String NPC_REMOVE = "remove";
|
||||
|
||||
@SubCommand("npc")
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.SET_COSMETIC_COMMAND)
|
||||
public void applyNpc(
|
||||
final CommandSender sender,
|
||||
@Completion("#npc-args") final String arg,
|
||||
@Completion("#npcs") final Integer npcId,
|
||||
@Completion("#types") final String typeStr,
|
||||
@me.mattstudios.mf.annotations.Optional @Completion("#ids") final String itemId
|
||||
) {
|
||||
final CitizensHook citizensHook = HookManager.getInstance().getCitizensHook();
|
||||
if (citizensHook == null) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.HOOK_NOT_ENABLED,
|
||||
Map.of(Placeholder.TYPE, "Citizens")
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (npcId == null) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
new Message("illegal-npc-id", "<red>" + "Invalid NPC id specified: " + npcId)
|
||||
);
|
||||
return;
|
||||
}
|
||||
final ArmorItem armorItem = this.plugin.getCosmeticManager().getArmorItem(itemId);
|
||||
if (armorItem == null) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.ITEM_NOT_FOUND
|
||||
);
|
||||
return;
|
||||
}
|
||||
switch (arg.toLowerCase(Locale.ROOT)) {
|
||||
case NPC_APPLY -> {
|
||||
this.setNpcCosmetic(citizensHook, sender, npcId, armorItem);
|
||||
}
|
||||
|
||||
case NPC_REMOVE -> {
|
||||
try {
|
||||
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeStr);
|
||||
this.setNpcCosmetic(citizensHook, sender, npcId, ArmorItem.empty(type, "none"));
|
||||
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.INVALID_TYPE,
|
||||
Map.of(Placeholder.TYPE, typeStr)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubCommand("hide")
|
||||
public void hide(final Player player) {
|
||||
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
if (optionalUser.isEmpty()) return;
|
||||
final User user = optionalUser.get();
|
||||
if (user.isHidden()) {
|
||||
user.setHidden(false);
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.SHOWN_COSMETICS
|
||||
);
|
||||
return;
|
||||
}
|
||||
user.setHidden(true);
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.HID_COSMETICS
|
||||
);
|
||||
}
|
||||
|
||||
@SubCommand("token")
|
||||
@Permission(io.github.fisher2911.hmccosmetics.message.Permission.GIVE_TOKEN)
|
||||
public void token(
|
||||
final CommandSender sender,
|
||||
@Completion("#tokens") final String tokenId,
|
||||
@Completion("#players") @me.mattstudios.mf.annotations.Optional Player giveTo) {
|
||||
if (!(sender instanceof Player) && giveTo == null) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.MUST_BE_PLAYER
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (giveTo == null) {
|
||||
giveTo = ((Player) sender);
|
||||
}
|
||||
final Token token = this.cosmeticManager.getToken(tokenId);
|
||||
if (token == null) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.ITEM_NOT_FOUND
|
||||
);
|
||||
return;
|
||||
}
|
||||
giveTo.getInventory().addItem(token.getItemStack().clone());
|
||||
final String tokenName = token.getArmorItem().getName();
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.GAVE_TOKEN,
|
||||
Map.of(Placeholder.ID, tokenName,
|
||||
Placeholder.PLAYER, giveTo.getDisplayName())
|
||||
);
|
||||
this.messageHandler.sendMessage(
|
||||
giveTo,
|
||||
Messages.RECEIVED_TOKEN,
|
||||
Map.of(Placeholder.ID, tokenName)
|
||||
);
|
||||
}
|
||||
|
||||
private void setNpcCosmetic(final CitizensHook hook, final CommandSender sender, final int npcId, final ArmorItem item) {
|
||||
final boolean isSet = hook.setNpcCosmetic(npcId, item);
|
||||
if (!isSet) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.NPC_NOT_FOUND,
|
||||
Map.of(Placeholder.ID, String.valueOf(npcId))
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.SET_NPC_COSMETIC,
|
||||
Map.of(Placeholder.TYPE, item.getType().toString(),
|
||||
Placeholder.ITEM, item.getId(),
|
||||
Placeholder.ID, String.valueOf(npcId))
|
||||
);
|
||||
}
|
||||
|
||||
private void setDyeColor(final String dyeColor, final ArmorItem armorItem, final CommandSender sender) {
|
||||
try {
|
||||
final java.awt.Color awtColor = java.awt.Color.decode(dyeColor);
|
||||
Color color = Color.fromRGB(awtColor.getRed(), awtColor.getGreen(), awtColor.getBlue());
|
||||
armorItem.setDye(color.asRGB());
|
||||
} catch (final NumberFormatException exception) {
|
||||
this.messageHandler.sendMessage(
|
||||
sender,
|
||||
Messages.INVALID_COLOR,
|
||||
Map.of(Placeholder.ITEM, dyeColor)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package io.github.fisher2911.hmccosmetics.concurrent;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class Threads {
|
||||
|
||||
private static final Threads INSTANCE;
|
||||
|
||||
static {
|
||||
INSTANCE = new Threads();
|
||||
}
|
||||
|
||||
private final ExecutorService service;
|
||||
|
||||
private Threads() {
|
||||
this.service = Executors.newFixedThreadPool(1);
|
||||
}
|
||||
|
||||
public static Threads getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public void execute(final Runnable runnable) {
|
||||
this.service.execute(runnable);
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
this.service.shutdownNow().forEach(Runnable::run);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
|
||||
import io.github.fisher2911.hmccosmetics.message.Message;
|
||||
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
|
||||
import io.github.fisher2911.hmccosmetics.message.Placeholder;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import io.github.fisher2911.hmccosmetics.util.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ActionSerializer implements TypeSerializer<List<CosmeticGuiAction>> {
|
||||
|
||||
public static final ActionSerializer INSTANCE = new ActionSerializer();
|
||||
private static final HMCCosmetics plugin;
|
||||
|
||||
private static final String OPEN_MENU = "open-menu";
|
||||
private static final String CLOSE_MENU = "close-menu";
|
||||
private static final String SET_ITEMS = "set-items";
|
||||
private static final String REMOVE_COSMETICS = "remove-cosmetics";
|
||||
private static final String SET_COSMETICS = "set-cosmetics";
|
||||
private static final String SEND_MESSAGE = "send-message";
|
||||
private static final String SEND_MESSAGES = "send-messages";
|
||||
private static final String SEND_COMMAND = "send-command";
|
||||
private static final String SEND_COMMANDS = "send-commands";
|
||||
private static final String SOUND = "sound";
|
||||
|
||||
static {
|
||||
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
|
||||
}
|
||||
|
||||
private ActionSerializer() {
|
||||
}
|
||||
|
||||
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
|
||||
throws SerializationException {
|
||||
if (!source.hasChild(path)) {
|
||||
throw new SerializationException(
|
||||
"Required field " + Arrays.toString(path) + " was not present in node");
|
||||
}
|
||||
|
||||
return source.node(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CosmeticGuiAction> deserialize(final Type type, final ConfigurationNode source) {
|
||||
return this.deserialize(type, new ArrayList<>(), source, CosmeticGuiAction.When.ALL);
|
||||
}
|
||||
|
||||
private List<CosmeticGuiAction> deserialize(
|
||||
final Type type,
|
||||
final List<CosmeticGuiAction> consumers,
|
||||
final ConfigurationNode source,
|
||||
final CosmeticGuiAction.When when) {
|
||||
final var children = source.childrenMap();
|
||||
for (final var entry : children.entrySet()) {
|
||||
final String clickType = entry.getKey().toString();
|
||||
try {
|
||||
final CosmeticGuiAction.When nextWhen = CosmeticGuiAction.When.valueOf(clickType.toUpperCase());
|
||||
this.deserialize(type, consumers, entry.getValue(), nextWhen);
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
consumers.add(this.parseAction(entry.getValue(), clickType.toUpperCase(Locale.ROOT), when));
|
||||
}
|
||||
}
|
||||
|
||||
return consumers;
|
||||
}
|
||||
|
||||
private CosmeticGuiAction parseAction(
|
||||
final ConfigurationNode node,
|
||||
final String clickType,
|
||||
final CosmeticGuiAction.When when
|
||||
) {
|
||||
final ConfigurationNode openMenuNode = node.node(OPEN_MENU);
|
||||
final ConfigurationNode setItemsNode = node.node(SET_ITEMS);
|
||||
final ConfigurationNode removeItemsNode = node.node(REMOVE_COSMETICS);
|
||||
final ConfigurationNode setCosmeticsNode = node.node(SET_COSMETICS);
|
||||
final ConfigurationNode soundNode = node.node(SOUND);
|
||||
final boolean closeMenu = node.node(CLOSE_MENU).getBoolean(false);
|
||||
|
||||
final String openMenu = openMenuNode.getString();
|
||||
|
||||
final List<ArmorItem.Type> removeCosmeticTypes = this.loadRemoveTypes(removeItemsNode);
|
||||
final int totalRemoveCosmetics = removeCosmeticTypes.size();
|
||||
final List<String> setCosmetics = this.loadSetCosmetics(setCosmeticsNode);
|
||||
final int totalSetCosmetics = setCosmetics.size();
|
||||
|
||||
final ClickType click = Utils.stringToEnum(clickType, ClickType.class, ClickType.UNKNOWN);
|
||||
final Map<Integer, GuiItem> setItems = this.loadSetItems(setItemsNode);
|
||||
|
||||
final Consumer<Player> messageConsumer = this.loadMessages(node, plugin);
|
||||
final SoundData soundData = this.loadSoundData(soundNode);
|
||||
|
||||
return new CosmeticGuiAction(
|
||||
when,
|
||||
event -> {
|
||||
if (click != ClickType.UNKNOWN && event.getClick() != click) return;
|
||||
if (!(event.getWhoClicked() instanceof final Player player)) return;
|
||||
|
||||
if (soundData != null) {
|
||||
soundData.play(player);
|
||||
}
|
||||
|
||||
if (openMenu != null) plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
|
||||
messageConsumer.accept(player);
|
||||
final UserManager userManager = plugin.getUserManager();
|
||||
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
|
||||
if (optionalUser.isEmpty()) return;
|
||||
final User user = optionalUser.get();
|
||||
final CosmeticManager cosmeticManager = plugin.getCosmeticManager();
|
||||
int index = 0;
|
||||
for (final String id : setCosmetics) {
|
||||
index++;
|
||||
final boolean sendPacket = index == totalSetCosmetics ;
|
||||
final ArmorItem armorItem = cosmeticManager.getArmorItem(id);
|
||||
if (armorItem == null) continue;
|
||||
userManager.setItem(user, armorItem, sendPacket);
|
||||
}
|
||||
index = 0;
|
||||
for (final ArmorItem.Type type : removeCosmeticTypes) {
|
||||
index++;
|
||||
final boolean sendPacket = index == totalSetCosmetics ;
|
||||
userManager.removeItem(user, type, sendPacket);
|
||||
}
|
||||
final CosmeticGui gui = user.getOpenGui();
|
||||
if (gui != null) {
|
||||
for (final var entry : setItems.entrySet()) {
|
||||
final GuiItem item = entry.getValue();
|
||||
gui.updateItem(entry.getKey(), item, user, player);
|
||||
}
|
||||
}
|
||||
if (closeMenu) player.closeInventory();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private Map<Integer, GuiItem> loadSetItems(final ConfigurationNode node) {
|
||||
if (node.virtual()) return Collections.emptyMap();
|
||||
final Map<Integer, GuiItem> setItems = new HashMap<>();
|
||||
try {
|
||||
for (final var entry : node.childrenMap().entrySet()) {
|
||||
if (!(entry.getKey() instanceof final Integer slot)) continue;
|
||||
final var key = entry.getValue();
|
||||
final GuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(GuiItem.class, key);
|
||||
if (guiItem == null) continue;
|
||||
setItems.put(slot, guiItem);
|
||||
}
|
||||
} catch (final SerializationException exception) {
|
||||
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().severe(
|
||||
"Error loading set-items"
|
||||
);
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
return setItems;
|
||||
}
|
||||
|
||||
private static final String CONSOLE = "console";
|
||||
private static final String PLAYER = "player";
|
||||
|
||||
private Consumer<Player> loadMessages(final ConfigurationNode source, final HMCCosmetics plugin) {
|
||||
final ConfigurationNode messageNode = source.node(SEND_MESSAGE);
|
||||
final ConfigurationNode messagesNode = source.node(SEND_MESSAGES);
|
||||
final ConfigurationNode commandNode = source.node(SEND_COMMAND);
|
||||
final ConfigurationNode commandsNode = source.node(SEND_COMMANDS);
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
final List<String> commands = new ArrayList<>();
|
||||
|
||||
final String message = messageNode.getString();
|
||||
if (message != null) messages.add(message);
|
||||
final String command = commandNode.getString();
|
||||
if (command != null) commands.add(command);
|
||||
|
||||
for (final var node : messagesNode.childrenList()) {
|
||||
final String listMessage = node.getString();
|
||||
if (listMessage == null) continue;
|
||||
messages.add(listMessage);
|
||||
}
|
||||
|
||||
for (final var node : commandsNode.childrenList()) {
|
||||
final String commandMessage = node.getString();
|
||||
if (commandMessage == null) continue;
|
||||
commands.add(commandMessage);
|
||||
}
|
||||
|
||||
return player -> {
|
||||
final String playerName = player.getName();
|
||||
final Map<String, String> placeholders = Map.of(Placeholder.PLAYER, playerName);
|
||||
final MessageHandler messageHandler = plugin.getMessageHandler();
|
||||
for (final String sendMessage : messages) {
|
||||
messageHandler.sendMessage(
|
||||
player,
|
||||
new Message("", sendMessage),
|
||||
placeholders
|
||||
);
|
||||
}
|
||||
|
||||
for (final String sendCommand : commands) {
|
||||
final String[] parts = sendCommand.split(":");
|
||||
if (parts.length < 2) {
|
||||
Bukkit.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
sendCommand.replace(Placeholder.PLAYER, playerName)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final String sender = parts[0];
|
||||
final String commandToSend = parts[1];
|
||||
|
||||
if (sender.equalsIgnoreCase(CONSOLE)) {
|
||||
Bukkit.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
commandToSend.replace(Placeholder.PLAYER, playerName)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
player.chat("/" + commandToSend.replace(Placeholder.PLAYER, playerName));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private List<ArmorItem.Type> loadRemoveTypes(final ConfigurationNode node) {
|
||||
try {
|
||||
final List<String> typeStrings = node.getList(String.class);
|
||||
if (typeStrings == null) return new ArrayList<>();
|
||||
return typeStrings.stream().map(
|
||||
string -> {
|
||||
try {
|
||||
return ArmorItem.Type.valueOf(string.toUpperCase(Locale.ROOT));
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
plugin.getLogger().severe(string + " is not a valid cosmetic type.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
).
|
||||
filter(type -> type != null).
|
||||
collect(Collectors.toList());
|
||||
} catch (final SerializationException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private SoundData loadSoundData(final ConfigurationNode node) {
|
||||
try {
|
||||
return SoundSerializer.INSTANCE.deserialize(SoundData.class, node);
|
||||
} catch (final ConfigurateException exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> loadSetCosmetics(final ConfigurationNode node) {
|
||||
try {
|
||||
return node.getList(String.class);
|
||||
} catch (final ConfigurateException exception) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, @Nullable final List<CosmeticGuiAction> obj, final ConfigurationNode node) throws SerializationException {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import dev.triumphteam.gui.components.GuiAction;
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.BalloonItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.util.StringUtils;
|
||||
import io.github.fisher2911.hmccosmetics.util.Utils;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ArmorItemSerializer implements TypeSerializer<WrappedGuiItem> {
|
||||
|
||||
public static final ArmorItemSerializer INSTANCE = new ArmorItemSerializer();
|
||||
|
||||
private ArmorItemSerializer() {
|
||||
}
|
||||
|
||||
private static final String NAME = "name";
|
||||
private static final String LOCKED_LORE = "locked-lore";
|
||||
private static final String APPLIED_LORE = "applied-lore";
|
||||
private static final String LOCKED_ITEM = "locked-item";
|
||||
private static final String APPLIED_ITEM = "applied-item";
|
||||
private static final String PERMISSION = "permission";
|
||||
private static final String TYPE = "type";
|
||||
private static final String ACTION = "action";
|
||||
private static final String ID = "id";
|
||||
private static final String DYEABLE = "dyeable";
|
||||
private static final String BALLOON_MODEL_ID = "balloon";
|
||||
|
||||
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
|
||||
throws SerializationException {
|
||||
if (!source.hasChild(path)) {
|
||||
throw new SerializationException(
|
||||
"Required field " + Arrays.toString(path) + " was not present in node");
|
||||
}
|
||||
|
||||
return source.node(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedGuiItem deserialize(final Type type, final ConfigurationNode source)
|
||||
throws SerializationException {
|
||||
final ConfigurationNode nameNode = source.node(NAME);
|
||||
final ConfigurationNode lockedLoreNode = source.node(LOCKED_LORE);
|
||||
final ConfigurationNode appliedLoreNode = source.node(APPLIED_LORE);
|
||||
final ConfigurationNode lockedItemNode = source.node(LOCKED_ITEM);
|
||||
final ConfigurationNode appliedItemNode = source.node(APPLIED_ITEM);
|
||||
final ConfigurationNode permissionNode = source.node(PERMISSION);
|
||||
final ConfigurationNode typeNode = source.node(TYPE);
|
||||
final ConfigurationNode actionNode = source.node(ACTION);
|
||||
final ConfigurationNode idNode = source.node(ID);
|
||||
final ConfigurationNode dyeableNode = source.node(DYEABLE);
|
||||
final ConfigurationNode balloonModelIdNode = source.node(BALLOON_MODEL_ID);
|
||||
|
||||
final ItemStack itemStack = Utils.replaceIfNull(
|
||||
ItemSerializer.INSTANCE.deserialize(ItemStack.class, source),
|
||||
new ItemStack(Material.AIR)
|
||||
);
|
||||
ItemStack lockedItem = ItemSerializer.INSTANCE.deserialize(ItemStack.class, lockedItemNode);
|
||||
if (lockedItem == null) {
|
||||
final List<String> lockedLore = Utils.replaceIfNull(lockedLoreNode.getList(String.class),
|
||||
new ArrayList<String>()).
|
||||
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
|
||||
lockedItem = ItemBuilder.from(itemStack.clone()).lore(lockedLore).build();
|
||||
}
|
||||
ItemStack appliedItem = ItemSerializer.INSTANCE.deserialize(ItemStack.class, appliedItemNode);
|
||||
if (appliedItem == null) {
|
||||
final List<String> appliedLore = Utils.replaceIfNull(appliedLoreNode.getList(String.class),
|
||||
new ArrayList<String>()).
|
||||
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
|
||||
appliedItem = ItemBuilder.from(itemStack.clone()).lore(appliedLore).build();
|
||||
}
|
||||
|
||||
final boolean dyeable = dyeableNode.getBoolean();
|
||||
|
||||
final List<CosmeticGuiAction> actions = ActionSerializer.INSTANCE.deserialize(GuiAction.class, actionNode);
|
||||
|
||||
try {
|
||||
final ArmorItem.Type cosmeticType = ArmorItem.Type.valueOf(
|
||||
Utils.replaceIfNull(
|
||||
typeNode.getString(), ""
|
||||
).toUpperCase(Locale.ROOT)
|
||||
);
|
||||
|
||||
final String permission = permissionNode.getString();
|
||||
|
||||
if (cosmeticType == ArmorItem.Type.BALLOON) {
|
||||
return new BalloonItem(
|
||||
itemStack,
|
||||
actions,
|
||||
Utils.replaceIfNull(nameNode.getString(), ""),
|
||||
Utils.replaceIfNull(idNode.getString(), ""),
|
||||
lockedItem,
|
||||
appliedItem,
|
||||
permission,
|
||||
cosmeticType,
|
||||
dyeable,
|
||||
-1,
|
||||
balloonModelIdNode.getString()
|
||||
);
|
||||
}
|
||||
|
||||
return new ArmorItem(
|
||||
itemStack,
|
||||
actions,
|
||||
Utils.replaceIfNull(nameNode.getString(), ""),
|
||||
Utils.replaceIfNull(idNode.getString(), ""),
|
||||
lockedItem,
|
||||
appliedItem,
|
||||
permission,
|
||||
cosmeticType,
|
||||
dyeable,
|
||||
-1
|
||||
);
|
||||
|
||||
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
final GuiItem guiItem = dev.triumphteam.gui.builder.item.ItemBuilder.from(itemStack).asGuiItem();
|
||||
final GuiAction<InventoryClickEvent> guiAction = event -> {
|
||||
for (final CosmeticGuiAction action : actions) {
|
||||
action.execute(event, CosmeticGuiAction.When.ALL);
|
||||
}
|
||||
};
|
||||
guiItem.setAction(guiAction);
|
||||
return new WrappedGuiItem(guiItem, guiAction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, @Nullable final WrappedGuiItem obj, final ConfigurationNode node) throws SerializationException {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CosmeticGuiAction {
|
||||
|
||||
private final When when;
|
||||
private final Consumer<InventoryClickEvent> consumer;
|
||||
|
||||
public CosmeticGuiAction(final When when, final Consumer<InventoryClickEvent> consumer) {
|
||||
this.when = when;
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
public void execute(final InventoryClickEvent event, final When when) {
|
||||
if (this.when != When.ALL && this.when != when) return;
|
||||
consumer.accept(event);
|
||||
}
|
||||
|
||||
public enum When {
|
||||
|
||||
EQUIP,
|
||||
REMOVE,
|
||||
ALL
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
|
||||
import io.github.fisher2911.hmccosmetics.util.Utils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ConfigSerializable
|
||||
public class CosmeticSettings {
|
||||
|
||||
private static final String DEFAULT_MENU = "default-menu";
|
||||
private static final String COSMETIC_SETTINGS_PATH = "cosmetic-settings";
|
||||
private static final String REQUIRE_EMPTY_HELMET_PATH = "require-empty-helmet";
|
||||
private static final String REQUIRE_EMPTY_OFF_HAND_PATH = "require-empty-off-hand";
|
||||
private static final String REQUIRE_EMPTY_CHEST_PLATE_PATH = "require-empty-chest-plate";
|
||||
private static final String REQUIRE_EMPTY_PANTS_PATH = "require-empty-pants";
|
||||
private static final String REQUIRE_EMPTY_BOOTS_PATH = "require-empty-boots";
|
||||
private static final String BALLOON_OFFSET = "balloon-offset";
|
||||
private static final String FIRST_PERSON_BACKPACK_MODE = "first-person-backpack-mode";
|
||||
|
||||
private static final transient String LOOK_DOWN_PITCH_PATH = "look-down-backpack-remove";
|
||||
private static final String VIEW_DISTANCE_PATH = "view-distance";
|
||||
private static final String PARTICLE_COUNT = "particle-count";
|
||||
|
||||
private String defaultMenu;
|
||||
private boolean requireEmptyHelmet;
|
||||
private boolean requireEmptyOffHand;
|
||||
private boolean requireEmptyChestPlate;
|
||||
private boolean requireEmptyPants;
|
||||
private boolean requireEmptyBoots;
|
||||
private int lookDownPitch;
|
||||
private int viewDistance;
|
||||
private Vector balloonOffset;
|
||||
private boolean firstPersonBackpackMode;
|
||||
private int particleCount;
|
||||
|
||||
public void load(final FileConfiguration config) {
|
||||
this.particleCount = config.getInt(PARTICLE_COUNT, 1);
|
||||
this.defaultMenu = Utils.replaceIf(config.getString(DEFAULT_MENU), CosmeticsMenu.DEFAULT_MAIN_MENU, null, "");
|
||||
this.requireEmptyHelmet = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_HELMET_PATH);
|
||||
this.requireEmptyOffHand = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_OFF_HAND_PATH);
|
||||
this.requireEmptyChestPlate = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_CHEST_PLATE_PATH);
|
||||
this.requireEmptyPants = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_PANTS_PATH);
|
||||
this.requireEmptyBoots = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_BOOTS_PATH);
|
||||
|
||||
this.lookDownPitch = config.getInt(COSMETIC_SETTINGS_PATH + "." + LOOK_DOWN_PITCH_PATH);
|
||||
this.viewDistance = config.getInt(COSMETIC_SETTINGS_PATH + "." + VIEW_DISTANCE_PATH);
|
||||
|
||||
this.firstPersonBackpackMode = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + FIRST_PERSON_BACKPACK_MODE, false);
|
||||
|
||||
final var balloonSection = config.getConfigurationSection(COSMETIC_SETTINGS_PATH + "." + BALLOON_OFFSET);
|
||||
|
||||
if (balloonSection != null) {
|
||||
this.balloonOffset = loadVector(balloonSection);
|
||||
}
|
||||
}
|
||||
|
||||
public int getParticleCount() {
|
||||
return particleCount;
|
||||
}
|
||||
|
||||
private Vector loadVector(final ConfigurationSection section) {
|
||||
return new Vector(section.getDouble("x"), section.getDouble("y"), section.getDouble("z"));
|
||||
}
|
||||
|
||||
public boolean isRequireEmptyHelmet() {
|
||||
return requireEmptyHelmet;
|
||||
}
|
||||
|
||||
public void setRequireEmptyHelmet(final boolean requireEmptyHelmet) {
|
||||
this.requireEmptyHelmet = requireEmptyHelmet;
|
||||
}
|
||||
|
||||
public boolean isRequireEmptyOffHand() {
|
||||
return requireEmptyOffHand;
|
||||
}
|
||||
|
||||
public void setRequireEmptyOffHand(final boolean requireEmptyOffHand) {
|
||||
this.requireEmptyOffHand = requireEmptyOffHand;
|
||||
}
|
||||
|
||||
public boolean isRequireEmptyChestPlate() {
|
||||
return requireEmptyChestPlate;
|
||||
}
|
||||
|
||||
public void setRequireEmptyChestPlate(final boolean requireEmptyChestPlate) {
|
||||
this.requireEmptyChestPlate = requireEmptyChestPlate;
|
||||
}
|
||||
|
||||
public boolean isRequireEmptyPants() {
|
||||
return requireEmptyPants;
|
||||
}
|
||||
|
||||
public void setRequireEmptyPants(final boolean requireEmptyPants) {
|
||||
this.requireEmptyPants = requireEmptyPants;
|
||||
}
|
||||
|
||||
public boolean isRequireEmptyBoots() {
|
||||
return requireEmptyBoots;
|
||||
}
|
||||
|
||||
public void setRequireEmptyBoots(final boolean requireEmptyBoots) {
|
||||
this.requireEmptyBoots = requireEmptyBoots;
|
||||
}
|
||||
|
||||
public Vector getBalloonOffset() {
|
||||
return balloonOffset;
|
||||
}
|
||||
|
||||
public int getLookDownPitch() {
|
||||
return lookDownPitch;
|
||||
}
|
||||
|
||||
public int getViewDistance() {
|
||||
return viewDistance;
|
||||
}
|
||||
|
||||
public String getDefaultMenu() {
|
||||
return defaultMenu;
|
||||
}
|
||||
|
||||
public boolean isFirstPersonBackpackMode() {
|
||||
return firstPersonBackpackMode;
|
||||
}
|
||||
|
||||
public boolean requireEmpty(final EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
case OFF_HAND -> this.isRequireEmptyOffHand();
|
||||
case HEAD -> this.isRequireEmptyHelmet();
|
||||
case CHEST -> this.isRequireEmptyChestPlate();
|
||||
case LEGS -> this.isRequireEmptyPants();
|
||||
case FEET -> this.isRequireEmptyBoots();
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isInViewDistance(final Location location, final Location other) {
|
||||
if (!Objects.equals(other.getWorld(), location.getWorld())) return false;
|
||||
return !(other.distanceSquared(location) > this.getViewDistance() * this.getViewDistance());
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ColorItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.DyeSelectorGui;
|
||||
import io.github.fisher2911.hmccosmetics.message.Adventure;
|
||||
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
|
||||
import org.bukkit.Color;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
@@ -13,56 +16,59 @@ import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DyeGuiSerializer implements TypeSerializer<DyeSelectorGui> {
|
||||
|
||||
private static final HMCCosmetics plugin;
|
||||
|
||||
static {
|
||||
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
|
||||
}
|
||||
|
||||
public static final DyeGuiSerializer INSTANCE = new DyeGuiSerializer();
|
||||
|
||||
private DyeGuiSerializer() {}
|
||||
|
||||
private static final HMCCosmetics plugin;
|
||||
private static final String TITLE = "title";
|
||||
private static final String ROWS = "rows";
|
||||
private static final String ITEMS = "items";
|
||||
private static final String COSMETICS_SLOTS = "cosmetics-slots";
|
||||
private static final String SET_COLOR = "set-color";
|
||||
private static final String RED = "red";
|
||||
private static final String GREEN = "green";
|
||||
private static final String BLUE = "blue";
|
||||
|
||||
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path) throws SerializationException {
|
||||
static {
|
||||
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
|
||||
}
|
||||
|
||||
private DyeGuiSerializer() {
|
||||
}
|
||||
|
||||
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
|
||||
throws SerializationException {
|
||||
if (!source.hasChild(path)) {
|
||||
throw new SerializationException("Required field " + Arrays.toString(path) + " was not present in node");
|
||||
throw new SerializationException(
|
||||
"Required field " + Arrays.toString(path) + " was not present in node");
|
||||
}
|
||||
return source.node(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DyeSelectorGui deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
|
||||
public DyeSelectorGui deserialize(final Type type, final ConfigurationNode source)
|
||||
throws SerializationException {
|
||||
final ConfigurationNode titleNode = this.nonVirtualNode(source, TITLE);
|
||||
final ConfigurationNode rowsNode = this.nonVirtualNode(source, ROWS);
|
||||
final ConfigurationNode itemsNode = source.node(ITEMS);
|
||||
|
||||
final ConfigurationNode cosmeticSlotsNode = source.node(COSMETICS_SLOTS);
|
||||
|
||||
final Map<Integer, GuiItem> guiItemMap = new HashMap<>();
|
||||
|
||||
final var map = itemsNode.childrenMap();
|
||||
final var itemMap = itemsNode.childrenMap();
|
||||
final var cosmeticSlotsMap = cosmeticSlotsNode.childrenMap();
|
||||
|
||||
for (final var entry : map.entrySet()) {
|
||||
for (final var entry : itemMap.entrySet()) {
|
||||
if (!(entry.getKey() instanceof final Integer slot)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final var node = entry.getValue();
|
||||
|
||||
final GuiItem guiItem = ItemSerializer.INSTANCE.deserialize(
|
||||
final WrappedGuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(
|
||||
GuiItem.class,
|
||||
node
|
||||
);
|
||||
@@ -78,19 +84,50 @@ public class DyeGuiSerializer implements TypeSerializer<DyeSelectorGui> {
|
||||
final int green = colorNode.node(GREEN).getInt();
|
||||
final int blue = colorNode.node(BLUE).getInt();
|
||||
|
||||
guiItemMap.put(slot, new ColorItem(guiItem.getItemStack(), Color.fromRGB(red, green, blue)));
|
||||
guiItemMap.put(slot,
|
||||
new ColorItem(guiItem.getItemStack(), guiItem.getAction(), Color.fromRGB(red, green, blue))
|
||||
);
|
||||
}
|
||||
|
||||
final BiMap<Integer, ArmorItem.Type> cosmeticSlots = HashBiMap.create();
|
||||
int selectedCosmetic = -1;
|
||||
for (final var entry : cosmeticSlotsMap.entrySet()) {
|
||||
if (!(entry.getKey() instanceof final Integer slot)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
selectedCosmetic = selectedCosmetic == -1 ? slot : selectedCosmetic;
|
||||
|
||||
final var node = entry.getValue();
|
||||
|
||||
final String typeStr = node.getString();
|
||||
|
||||
try {
|
||||
final ArmorItem.Type itemType = ArmorItem.Type.valueOf(typeStr);
|
||||
cosmeticSlots.put(slot, itemType);
|
||||
} catch (final IllegalArgumentException | NullPointerException exception) {
|
||||
plugin.getLogger().severe(typeStr + " is not a valid ArmorItem type in DyeGui!");
|
||||
}
|
||||
}
|
||||
|
||||
String title = titleNode.getString();
|
||||
|
||||
if (title == null) {
|
||||
title = "";
|
||||
}
|
||||
|
||||
return new DyeSelectorGui(
|
||||
plugin,
|
||||
Adventure.SERIALIZER.serialize(
|
||||
Adventure.MINI_MESSAGE.parse(titleNode.getString())),
|
||||
title,
|
||||
rowsNode.getInt(),
|
||||
guiItemMap);
|
||||
guiItemMap,
|
||||
cosmeticSlots,
|
||||
selectedCosmetic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, @Nullable final DyeSelectorGui obj, final ConfigurationNode node) throws SerializationException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package io.github.fisher2911.hmccosmetics.config;
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
|
||||
import io.github.fisher2911.hmccosmetics.message.Adventure;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
@@ -16,43 +15,42 @@ import java.util.Map;
|
||||
|
||||
public class GuiSerializer implements TypeSerializer<CosmeticGui> {
|
||||
|
||||
public static final GuiSerializer INSTANCE = new GuiSerializer();
|
||||
private static final HMCCosmetics plugin;
|
||||
private static final String TITLE = "title";
|
||||
private static final String ROWS = "rows";
|
||||
private static final String ITEMS = "items";
|
||||
|
||||
static {
|
||||
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
|
||||
}
|
||||
|
||||
public static final GuiSerializer INSTANCE = new GuiSerializer();
|
||||
private GuiSerializer() {
|
||||
}
|
||||
|
||||
private GuiSerializer() {}
|
||||
|
||||
private static final String TITLE = "title";
|
||||
private static final String ROWS = "rows";
|
||||
private static final String ITEMS = "items";
|
||||
|
||||
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path) throws SerializationException {
|
||||
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path)
|
||||
throws SerializationException {
|
||||
if (!source.hasChild(path)) {
|
||||
throw new SerializationException("Required field " + Arrays.toString(path) + " was not present in node");
|
||||
throw new SerializationException(
|
||||
"Required field " + Arrays.toString(path) + " was not present in node");
|
||||
}
|
||||
return source.node(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CosmeticGui deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
|
||||
public CosmeticGui deserialize(final Type type, final ConfigurationNode source)
|
||||
throws SerializationException {
|
||||
final ConfigurationNode titleNode = this.nonVirtualNode(source, TITLE);
|
||||
final ConfigurationNode rowsNode = this.nonVirtualNode(source, ROWS);
|
||||
final ConfigurationNode itemsNode = source.node(ITEMS);
|
||||
|
||||
final var childrenMap = source.node(ITEMS).childrenMap();
|
||||
final var childrenMap = itemsNode.childrenMap();
|
||||
|
||||
final Map<Integer, GuiItem> guiItemMap = new HashMap<>();
|
||||
|
||||
for (final var entry : childrenMap.entrySet()) {
|
||||
if (!(entry.getKey() instanceof final Integer slot)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final GuiItem guiItem = ItemSerializer.INSTANCE.deserialize(
|
||||
if (!(entry.getKey() instanceof final Integer slot)) continue;
|
||||
final GuiItem guiItem = ArmorItemSerializer.INSTANCE.deserialize(
|
||||
GuiItem.class,
|
||||
entry.getValue()
|
||||
);
|
||||
@@ -60,9 +58,14 @@ public class GuiSerializer implements TypeSerializer<CosmeticGui> {
|
||||
guiItemMap.put(slot, guiItem);
|
||||
}
|
||||
|
||||
String title = titleNode.getString();
|
||||
|
||||
if (title == null) {
|
||||
title = "";
|
||||
}
|
||||
|
||||
return new CosmeticGui(plugin,
|
||||
Adventure.SERIALIZER.serialize(
|
||||
Adventure.MINI_MESSAGE.parse(titleNode.getString())),
|
||||
title,
|
||||
rowsNode.getInt(),
|
||||
guiItemMap);
|
||||
}
|
||||
@@ -71,4 +74,5 @@ public class GuiSerializer implements TypeSerializer<CosmeticGui> {
|
||||
public void serialize(final Type type, @Nullable final CosmeticGui obj, final ConfigurationNode node) throws SerializationException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,12 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.message.Adventure;
|
||||
import io.github.fisher2911.hmccosmetics.hook.HookManager;
|
||||
import io.github.fisher2911.hmccosmetics.util.Keys;
|
||||
import io.github.fisher2911.hmccosmetics.util.StringUtils;
|
||||
import io.github.fisher2911.hmccosmetics.util.Utils;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.SkullBuilder;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
@@ -27,24 +23,20 @@ import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ItemSerializer implements TypeSerializer<GuiItem> {
|
||||
public class ItemSerializer implements TypeSerializer<ItemStack> {
|
||||
|
||||
public static final ItemSerializer INSTANCE = new ItemSerializer();
|
||||
|
||||
private static final String MATERIAL = "material";
|
||||
private static final String AMOUNT = "amount";
|
||||
private static final String NAME = "name";
|
||||
private static final String UNBREAKABLE = "unbreakable";
|
||||
private static final String GLOWING = "glowing";
|
||||
private static final String LORE = "lore";
|
||||
private static final String LOCKED_LORE = "locked-lore";
|
||||
private static final String MODEL_DATA = "model-data";
|
||||
private static final String ENCHANTS = "enchants";
|
||||
private static final String ITEM_FLAGS = "item-flags";
|
||||
@@ -54,32 +46,19 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
|
||||
private static final String RED = "red";
|
||||
private static final String GREEN = "green";
|
||||
private static final String BLUE = "blue";
|
||||
private static final String PERMISSION = "permission";
|
||||
private static final String TYPE = "type";
|
||||
private static final String OPEN_MENU = "open-menu";
|
||||
private static final String ID = "id";
|
||||
private static final String DYEABLE = "dyeable";
|
||||
|
||||
private ItemSerializer() {
|
||||
}
|
||||
|
||||
private ConfigurationNode nonVirtualNode(final ConfigurationNode source, final Object... path) throws SerializationException {
|
||||
if (!source.hasChild(path)) {
|
||||
throw new SerializationException("Required field " + Arrays.toString(path) + " was not present in node");
|
||||
}
|
||||
|
||||
return source.node(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiItem deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
|
||||
final ConfigurationNode materialNode = this.nonVirtualNode(source, MATERIAL);
|
||||
public ItemStack deserialize(final Type type, final ConfigurationNode source)
|
||||
throws SerializationException {
|
||||
final ConfigurationNode materialNode = source.node(MATERIAL);
|
||||
final ConfigurationNode amountNode = source.node(AMOUNT);
|
||||
final ConfigurationNode nameNode = source.node(NAME);
|
||||
final ConfigurationNode unbreakableNode = source.node(UNBREAKABLE);
|
||||
final ConfigurationNode glowingNode = source.node(GLOWING);
|
||||
final ConfigurationNode loreNode = source.node(LORE);
|
||||
final ConfigurationNode lockedLoreNode = source.node(LOCKED_LORE);
|
||||
final ConfigurationNode modelDataNode = source.node(MODEL_DATA);
|
||||
final ConfigurationNode enchantsNode = source.node(ENCHANTS);
|
||||
final ConfigurationNode itemFlagsNode = source.node(ITEM_FLAGS);
|
||||
@@ -89,33 +68,34 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
|
||||
final ConfigurationNode redNode = colorNode.node(RED);
|
||||
final ConfigurationNode greenNode = colorNode.node(GREEN);
|
||||
final ConfigurationNode blueNode = colorNode.node(BLUE);
|
||||
final ConfigurationNode permissionNode = source.node(PERMISSION);
|
||||
final ConfigurationNode typeNode = source.node(TYPE);
|
||||
final ConfigurationNode openMenuNode = source.node(OPEN_MENU);
|
||||
final ConfigurationNode idNode = source.node(ID);
|
||||
final ConfigurationNode dyeableNode = source.node(DYEABLE);
|
||||
|
||||
|
||||
final Material material = Utils.stringToEnum(Utils.replaceIfNull(materialNode.getString(), ""),
|
||||
Material.class, Material.AIR);
|
||||
final String materialString = Utils.replaceIfNull(materialNode.getString(), "");
|
||||
final int amount = amountNode.getInt();
|
||||
final Component name = StringUtils.parse(nameNode.getString());
|
||||
// Adventure.MINI_MESSAGE.parse(
|
||||
// Utils.replaceIfNull(nameNode.getString(), "")
|
||||
// );
|
||||
|
||||
ItemStack itemStack;
|
||||
|
||||
try {
|
||||
itemStack = new ItemStack(Material.valueOf(materialString.toUpperCase()), amount);
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
itemStack = HookManager.getInstance().getItemHooks().getItemStack(materialString);
|
||||
if (itemStack == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final String name = StringUtils.parseStringToString(Utils.replaceIfNull(nameNode.getString(), ""));
|
||||
|
||||
final boolean unbreakable = unbreakableNode.getBoolean();
|
||||
final boolean glowing = glowingNode.getBoolean();
|
||||
|
||||
final List<String> lore = Utils.replaceIfNull(loreNode.getList(String.class), new ArrayList<String>()).
|
||||
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
|
||||
|
||||
final List<String> lockedLore = Utils.replaceIfNull(lockedLoreNode.getList(String.class), new ArrayList<String>()).
|
||||
final List<String> lore = Utils.replaceIfNull(loreNode.getList(String.class),
|
||||
new ArrayList<String>()).
|
||||
stream().map(StringUtils::parseStringToString).collect(Collectors.toList());
|
||||
|
||||
final int modelData = modelDataNode.getInt();
|
||||
|
||||
final Set<ItemFlag> itemFlags = Utils.replaceIfNull(itemFlagsNode.getList(String.class), new ArrayList<String>()).
|
||||
final Set<ItemFlag> itemFlags = Utils.replaceIfNull(itemFlagsNode.getList(String.class),
|
||||
new ArrayList<String>()).
|
||||
stream().map(flag -> {
|
||||
try {
|
||||
return ItemFlag.valueOf(flag.toUpperCase());
|
||||
@@ -126,14 +106,12 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
|
||||
final String texture = textureNode.getString();
|
||||
final String owner = ownerNode.getString();
|
||||
|
||||
final boolean dyeable = dyeableNode.getBoolean();
|
||||
|
||||
final Color color;
|
||||
|
||||
if (colorNode.virtual()) {
|
||||
color = null;
|
||||
} else {
|
||||
color = Color.fromBGR(redNode.getInt(), greenNode.getInt(), blueNode.getInt());
|
||||
color = Color.fromRGB(redNode.getInt(), greenNode.getInt(), blueNode.getInt());
|
||||
}
|
||||
|
||||
final Map<Enchantment, Integer> enchantments =
|
||||
@@ -146,9 +124,10 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
|
||||
return null;
|
||||
}
|
||||
|
||||
final NamespacedKey namespacedKey = NamespacedKey.minecraft(enchantmentString.
|
||||
split(":")[0].
|
||||
toLowerCase());
|
||||
final NamespacedKey namespacedKey = NamespacedKey.minecraft(
|
||||
enchantmentString.
|
||||
split(":")[0].
|
||||
toLowerCase());
|
||||
return Registry.ENCHANTMENT.get(namespacedKey);
|
||||
|
||||
}, enchantmentString -> {
|
||||
@@ -162,12 +141,10 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
final ItemBuilder itemBuilder;
|
||||
|
||||
if (material == Material.PLAYER_HEAD) {
|
||||
itemBuilder = SkullBuilder.
|
||||
create();
|
||||
if (itemStack.getType() == Material.PLAYER_HEAD) {
|
||||
itemBuilder = SkullBuilder.create();
|
||||
|
||||
if (texture != null) {
|
||||
((SkullBuilder) itemBuilder).texture(texture);
|
||||
@@ -175,64 +152,38 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
|
||||
final OfflinePlayer player = Bukkit.getOfflinePlayer(owner);
|
||||
((SkullBuilder) itemBuilder).owner(player);
|
||||
}
|
||||
} else if (ColorBuilder.canBeColored(material)) {
|
||||
itemBuilder = ColorBuilder.from(material);
|
||||
} else if (ColorBuilder.canBeColored(itemStack)) {
|
||||
itemBuilder = ColorBuilder.from(itemStack);
|
||||
if (color != null) {
|
||||
((ColorBuilder) itemBuilder).color(color);
|
||||
}
|
||||
} else {
|
||||
itemBuilder = ItemBuilder.from(material);
|
||||
itemBuilder = ItemBuilder.from(itemStack);
|
||||
}
|
||||
|
||||
final ItemStack itemStack = itemBuilder.
|
||||
if (itemStack.getItemMeta() != null && !itemStack.getItemMeta().hasCustomModelData()) {
|
||||
itemBuilder.modelData(modelData);
|
||||
}
|
||||
|
||||
if (!lore.isEmpty()) itemBuilder.lore(lore);
|
||||
if (!name.isBlank()) itemBuilder.name(name);
|
||||
|
||||
itemStack = itemBuilder.
|
||||
amount(amount).
|
||||
name(name).
|
||||
unbreakable(unbreakable).
|
||||
glow(glowing).
|
||||
lore(lore).
|
||||
modelData(modelData).
|
||||
enchants(enchantments, true).
|
||||
itemFlags(itemFlags).
|
||||
build();
|
||||
|
||||
final String openMenu = openMenuNode.getString(
|
||||
Utils.replaceIfNull(OPEN_MENU, ""));
|
||||
|
||||
Keys.setKey(itemStack);
|
||||
|
||||
try {
|
||||
final ArmorItem.Type cosmeticType = ArmorItem.Type.valueOf(
|
||||
Utils.replaceIfNull(
|
||||
typeNode.getString(), ""
|
||||
).toUpperCase(Locale.ROOT)
|
||||
);
|
||||
|
||||
final String permission = permissionNode.getString();
|
||||
|
||||
return new ArmorItem(
|
||||
itemStack,
|
||||
event -> {
|
||||
final HMCCosmetics plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
|
||||
plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
|
||||
},
|
||||
Utils.replaceIfNull(idNode.getString(), ""),
|
||||
lockedLore,
|
||||
permission,
|
||||
cosmeticType,
|
||||
dyeable);
|
||||
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
return dev.triumphteam.gui.builder.item.ItemBuilder.from(
|
||||
itemStack).
|
||||
asGuiItem(event -> {
|
||||
final HMCCosmetics plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
|
||||
plugin.getCosmeticsMenu().openMenu(openMenu, event.getWhoClicked());
|
||||
});
|
||||
}
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, @Nullable final GuiItem obj, final ConfigurationNode node) throws SerializationException {
|
||||
public void serialize(final Type type, @Nullable final ItemStack obj, final ConfigurationNode node) throws SerializationException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class LocationSerializer implements TypeSerializer<Location> {
|
||||
|
||||
public static final LocationSerializer INSTANCE = new LocationSerializer();
|
||||
|
||||
private static final String WORLD = "world";
|
||||
private static final String X = "x";
|
||||
private static final String Y = "y";
|
||||
private static final String Z = "z";
|
||||
private static final String PITCH = "pitch";
|
||||
private static final String YAW = "yaw";
|
||||
|
||||
|
||||
private LocationSerializer() {}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Location deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
|
||||
final World world = Bukkit.getWorld(source.node(WORLD).getString());
|
||||
if (world == null) return null;
|
||||
return new Location(
|
||||
world,
|
||||
source.node(X).getDouble(),
|
||||
source.node(Y).getDouble(),
|
||||
source.node(Z).getDouble(),
|
||||
source.node(YAW).getFloat(),
|
||||
source.node(PITCH).getFloat()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, @Nullable final Location obj, final ConfigurationNode node) throws SerializationException {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
|
||||
public class Settings {
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final CosmeticSettings cosmeticSettings;
|
||||
private final WardrobeSettings wardrobeSettings;
|
||||
|
||||
public Settings(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.cosmeticSettings = new CosmeticSettings();
|
||||
this.wardrobeSettings = new WardrobeSettings(this.plugin);
|
||||
}
|
||||
|
||||
public void load() {
|
||||
this.plugin.saveDefaultConfig();
|
||||
this.plugin.reloadConfig();
|
||||
this.cosmeticSettings.load(this.plugin.getConfig());
|
||||
this.wardrobeSettings.load();
|
||||
}
|
||||
|
||||
public CosmeticSettings getCosmeticSettings() {
|
||||
return cosmeticSettings;
|
||||
}
|
||||
|
||||
public WardrobeSettings getWardrobeSettings() {
|
||||
return wardrobeSettings;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||
import net.minecraft.server.v1_16_R3.MinecraftKey;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SoundData {
|
||||
|
||||
private final String name;
|
||||
private final EnumWrappers.SoundCategory soundCategory;
|
||||
private final float volume;
|
||||
private final float pitch;
|
||||
|
||||
public SoundData(final String name, final EnumWrappers.SoundCategory soundCategory, final float volume, final float pitch) {
|
||||
this.name = name;
|
||||
this.soundCategory = soundCategory;
|
||||
this.volume = volume;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public float getVolume() {
|
||||
return volume;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public EnumWrappers.SoundCategory getSoundCategory() {
|
||||
return soundCategory;
|
||||
}
|
||||
|
||||
public void play(final Player player) {
|
||||
// todo - once packetevents updates
|
||||
// final PacketContainer soundPacket = PacketManager.getSoundPacket(
|
||||
// player,
|
||||
// player.getLocation(),
|
||||
// this.getKey(this.name),
|
||||
// this.volume,
|
||||
// this.pitch,
|
||||
// this.soundCategory
|
||||
// );
|
||||
//
|
||||
// PacketManager.sendPacket(player, soundPacket);
|
||||
}
|
||||
|
||||
private MinecraftKey getKey(final String string) {
|
||||
if (!string.contains(":")) {
|
||||
return new MinecraftKey(string);
|
||||
}
|
||||
|
||||
final String[] parts = string.split(":");
|
||||
|
||||
return new MinecraftKey(parts[0], parts[1]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class SoundSerializer implements TypeSerializer<SoundData> {
|
||||
|
||||
public static final SoundSerializer INSTANCE = new SoundSerializer();
|
||||
|
||||
private SoundSerializer() {}
|
||||
|
||||
private static final String SOUND_NAME = "name";
|
||||
private static final String SOUND_VOLUME = "volume";
|
||||
private static final String SOUND_PITCH = "pitch";
|
||||
private static final String SOUND_CATEGORY = "category";
|
||||
|
||||
@Override
|
||||
public SoundData deserialize(final Type type, final ConfigurationNode node) throws SerializationException {
|
||||
final ConfigurationNode soundNameNode = node.node(SOUND_NAME);
|
||||
final ConfigurationNode volumeNode = node.node(SOUND_VOLUME);
|
||||
final ConfigurationNode pitchNode = node.node(SOUND_PITCH);
|
||||
final ConfigurationNode categoryNode = node.node(SOUND_CATEGORY);
|
||||
|
||||
final SoundData soundData;
|
||||
|
||||
final String soundName = soundNameNode.getString();
|
||||
final String category = categoryNode.getString();
|
||||
final int volume = volumeNode.getInt();
|
||||
final int pitch = pitchNode.getInt();
|
||||
if (soundName == null || category == null) {
|
||||
soundData = null;
|
||||
} else {
|
||||
soundData = new SoundData(
|
||||
soundName,
|
||||
EnumWrappers.SoundCategory.valueOf(category),
|
||||
volume,
|
||||
pitch
|
||||
);
|
||||
}
|
||||
|
||||
return soundData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, @Nullable final SoundData obj, final ConfigurationNode node) throws SerializationException {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
|
||||
import io.github.fisher2911.hmccosmetics.gui.TokenGui;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class TokenGuiSerializer implements TypeSerializer<TokenGui> {
|
||||
|
||||
public static final TokenGuiSerializer INSTANCE = new TokenGuiSerializer();
|
||||
private static final String TOKEN_SLOT = "token-slot";
|
||||
private static final String COSMETIC_SLOT = "cosmetic-slot";
|
||||
|
||||
private TokenGuiSerializer() {}
|
||||
|
||||
@Override
|
||||
public TokenGui deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
|
||||
final CosmeticGui cosmeticGui = GuiSerializer.INSTANCE.deserialize(CosmeticGui.class, source);
|
||||
final ConfigurationNode tokenSlotNode = source.node(TOKEN_SLOT);
|
||||
final ConfigurationNode cosmeticSlotNode = source.node(COSMETIC_SLOT);
|
||||
|
||||
return new TokenGui(
|
||||
cosmeticGui,
|
||||
tokenSlotNode.getInt(),
|
||||
cosmeticSlotNode.getInt()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, @Nullable final TokenGui obj, final ConfigurationNode node) throws SerializationException {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.Token;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public class TokenLoader {
|
||||
|
||||
private static final String FILE_NAME = "tokens.yml";
|
||||
private static final String TOKEN_PATH = "tokens";
|
||||
private static final String ID_PATH = "id";
|
||||
private static final String COMMANDS_PATH = "commands";
|
||||
private final HMCCosmetics plugin;
|
||||
private final CosmeticManager cosmeticManager;
|
||||
|
||||
public TokenLoader(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.cosmeticManager = this.plugin.getCosmeticManager();
|
||||
}
|
||||
|
||||
public void load() {
|
||||
final Path path = Path.of(this.plugin.getDataFolder().getPath(), FILE_NAME);
|
||||
final File file = path.toFile();
|
||||
if (!file.exists()) {
|
||||
this.plugin.saveResource(FILE_NAME, false);
|
||||
}
|
||||
final YamlConfigurationLoader loader = YamlConfigurationLoader.
|
||||
builder().
|
||||
defaultOptions(opts -> opts.serializers(build -> build.register(ItemStack.class, ItemSerializer.INSTANCE))).
|
||||
path(path).
|
||||
build();
|
||||
try {
|
||||
final ConfigurationNode source = loader.load().node(TOKEN_PATH);
|
||||
for (final var entry : source.childrenMap().entrySet()) {
|
||||
final var node = entry.getValue();
|
||||
final String id = node.node(ID_PATH).getString();
|
||||
final ItemStack itemStack = node.get(ItemStack.class);
|
||||
final ArmorItem armorItem = this.cosmeticManager.getArmorItem(id);
|
||||
if (armorItem == null) {
|
||||
this.plugin.getLogger().severe("Could not find armor item for token: " + id + " with id: " + id);
|
||||
continue;
|
||||
}
|
||||
final List<String> commands = node.node(COMMANDS_PATH).getList(String.class);
|
||||
this.cosmeticManager.addToken(new Token(itemStack, armorItem, commands));
|
||||
}
|
||||
} catch (final ConfigurateException exception) {
|
||||
this.plugin.getLogger().severe("Error loading tokens!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package io.github.fisher2911.hmccosmetics.config;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.util.Utils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class WardrobeSettings {
|
||||
|
||||
private static final String WARDROBE_PATH = "wardrobe";
|
||||
private static final String DISABLE_ON_DAMAGE_PATH = "disable-on-damage";
|
||||
private static final String DISPLAY_RADIUS_PATH = "display-radius";
|
||||
private static final String PORTABLE_PATH = "portable";
|
||||
private static final String ALWAYS_DISPLAY_PATH = "always-display";
|
||||
private static final String STATIC_RADIUS_PATH = "static-radius";
|
||||
private static final String ROTATION_SPEED_PATH = "rotation-speed";
|
||||
private static final String SPAWN_DELAY_PATH = "spawn-delay";
|
||||
private static final String DESPAWN_DELAY_PATH = "despawn-delay";
|
||||
private static final String APPLY_COSMETICS_ON_CLOSE = "apply-cosmetics-on-close";
|
||||
private static final String OPEN_SOUND = "open-sound";
|
||||
private static final String CLOSE_SOUND = "close-sound";
|
||||
private static final String STATIC_LOCATION_PATH = "wardrobe-location";
|
||||
private static final String VIEWER_LOCATION_PATH = "viewer-location";
|
||||
private static final String LEAVE_LOCATION_PATH = "leave-location";
|
||||
private static final String EQUIP_PUMPKIN_WARDROBE = "equip-pumpkin";
|
||||
private static final String RETURN_LAST_LOCATION = "return-last-location";
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
|
||||
private boolean disableOnDamage;
|
||||
private int displayRadius;
|
||||
private boolean portable;
|
||||
private boolean alwaysDisplay;
|
||||
private int staticRadius;
|
||||
private int rotationSpeed;
|
||||
private int spawnDelay;
|
||||
private int despawnDelay;
|
||||
private boolean applyCosmeticsOnClose;
|
||||
private boolean equipPumpkin;
|
||||
private boolean returnLastLocation;
|
||||
private SoundData openSound;
|
||||
private SoundData closeSound;
|
||||
private Location wardrobeLocation;
|
||||
private Location viewerLocation;
|
||||
private Location leaveLocation;
|
||||
|
||||
public WardrobeSettings(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
final File file = Path.of(this.plugin.getDataFolder().getPath(), "config.yml").toFile();
|
||||
final YamlConfigurationLoader loader = YamlConfigurationLoader.
|
||||
builder().
|
||||
path(file.toPath()).
|
||||
defaultOptions(opts ->
|
||||
opts.serializers(build -> {
|
||||
build.register(SoundData.class, SoundSerializer.INSTANCE);
|
||||
build.register(Location.class, LocationSerializer.INSTANCE);
|
||||
}))
|
||||
.build();
|
||||
try {
|
||||
final var source = loader.load().node(WARDROBE_PATH);
|
||||
this.disableOnDamage = source.node(DISABLE_ON_DAMAGE_PATH).getBoolean();
|
||||
this.displayRadius = source.node(DISPLAY_RADIUS_PATH).getInt();
|
||||
this.portable = source.node(PORTABLE_PATH).getBoolean();
|
||||
this.staticRadius = source.node(STATIC_RADIUS_PATH).getInt();
|
||||
this.alwaysDisplay = source.node(ALWAYS_DISPLAY_PATH).getBoolean();
|
||||
this.rotationSpeed = source.node(ROTATION_SPEED_PATH).getInt();
|
||||
this.spawnDelay = source.node(SPAWN_DELAY_PATH).getInt();
|
||||
this.despawnDelay = source.node(DESPAWN_DELAY_PATH).getInt();
|
||||
this.applyCosmeticsOnClose = source.node(APPLY_COSMETICS_ON_CLOSE).getBoolean();
|
||||
this.equipPumpkin = source.node(EQUIP_PUMPKIN_WARDROBE).getBoolean();
|
||||
this.returnLastLocation = source.node(RETURN_LAST_LOCATION).getBoolean();
|
||||
this.openSound = source.node(OPEN_SOUND).get(SoundData.class);
|
||||
this.closeSound = source.node(CLOSE_SOUND).get(SoundData.class);
|
||||
this.wardrobeLocation = source.node(STATIC_LOCATION_PATH).get(Location.class);
|
||||
this.viewerLocation = source.node(VIEWER_LOCATION_PATH).get(Location.class);
|
||||
this.leaveLocation = Utils.replaceIfNull(source.node(LEAVE_LOCATION_PATH).get(Location.class), this.viewerLocation);
|
||||
} catch (final ConfigurateException exception) {
|
||||
this.plugin.getLogger().severe("Error loading wardrobe settings");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getDisableOnDamage() {
|
||||
return disableOnDamage;
|
||||
}
|
||||
|
||||
public int getDisplayRadius() {
|
||||
return displayRadius;
|
||||
}
|
||||
|
||||
public boolean isPortable() {
|
||||
return portable;
|
||||
}
|
||||
|
||||
public boolean isAlwaysDisplay() {
|
||||
return alwaysDisplay;
|
||||
}
|
||||
|
||||
public int getStaticRadius() {
|
||||
return staticRadius;
|
||||
}
|
||||
|
||||
public int getRotationSpeed() {
|
||||
return rotationSpeed;
|
||||
}
|
||||
|
||||
public int getSpawnDelay() {
|
||||
return spawnDelay;
|
||||
}
|
||||
|
||||
public int getDespawnDelay() {
|
||||
return despawnDelay;
|
||||
}
|
||||
|
||||
public boolean isApplyCosmeticsOnClose() {
|
||||
return applyCosmeticsOnClose;
|
||||
}
|
||||
public boolean isEquipPumpkin() {
|
||||
return equipPumpkin;
|
||||
}
|
||||
public boolean isReturnLastLocation() {
|
||||
return returnLastLocation;
|
||||
}
|
||||
|
||||
public Location getWardrobeLocation() {
|
||||
return this.wardrobeLocation.clone();
|
||||
}
|
||||
|
||||
public Location getViewerLocation() {
|
||||
return viewerLocation;
|
||||
}
|
||||
|
||||
public Location getLeaveLocation() {
|
||||
return leaveLocation;
|
||||
}
|
||||
|
||||
public void playOpenSound(final Player player) {
|
||||
if (this.openSound == null) return;
|
||||
this.openSound.play(player);
|
||||
}
|
||||
|
||||
public void playCloseSound(final Player player) {
|
||||
if (this.closeSound == null) return;
|
||||
this.closeSound.play(player);
|
||||
}
|
||||
|
||||
public boolean inDistanceOfWardrobe(final Location wardrobeLocation, final Location playerLocation) {
|
||||
if (this.displayRadius == -1) return true;
|
||||
if (!wardrobeLocation.getWorld().equals(playerLocation.getWorld())) return false;
|
||||
return playerLocation.distanceSquared(wardrobeLocation) <= this.displayRadius * this.displayRadius;
|
||||
}
|
||||
|
||||
public boolean inDistanceOfStatic(final Location location) {
|
||||
if (this.wardrobeLocation == null) return false;
|
||||
if (this.staticRadius == -1) return false;
|
||||
if (!this.wardrobeLocation.getWorld().equals(location.getWorld())) return false;
|
||||
return this.wardrobeLocation.distanceSquared(location) <= this.staticRadius * this.staticRadius;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package io.github.fisher2911.hmccosmetics.cosmetic;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.config.ArmorItemSerializer;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.gui.Token;
|
||||
import io.github.fisher2911.hmccosmetics.gui.WrappedGuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.util.Keys;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
public class CosmeticManager {
|
||||
|
||||
private final Path ITEMS_PATH = Path.of(HMCCosmetics.getPlugin(HMCCosmetics.class).getDataFolder().getPath(), "items.yml");
|
||||
|
||||
private final Map<String, Token> tokenMap;
|
||||
private final Map<String, ArmorItem> armorItemMap;
|
||||
private final Map<String, Integer> backpackParticleCounts;
|
||||
|
||||
public CosmeticManager(final Map<String, Token> tokenMap, final Map<String, ArmorItem> armorItemMap, final Map<String, Integer> backpackParticleCounts) {
|
||||
this.tokenMap = tokenMap;
|
||||
this.armorItemMap = armorItemMap;
|
||||
this.backpackParticleCounts = backpackParticleCounts;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ArmorItem getArmorItem(final String id) {
|
||||
return this.armorItemMap.get(id);
|
||||
}
|
||||
|
||||
public void addArmorItem(final ArmorItem armorItem) {
|
||||
this.armorItemMap.put(armorItem.getId(), armorItem);
|
||||
}
|
||||
|
||||
public Collection<ArmorItem> getAllArmorItems() {
|
||||
return this.armorItemMap.values();
|
||||
}
|
||||
|
||||
public Map<String, ArmorItem> getArmorItemMap() {
|
||||
return armorItemMap;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Token getToken(final String id) {
|
||||
return this.tokenMap.get(id);
|
||||
}
|
||||
|
||||
public void addToken(final Token token) {
|
||||
this.tokenMap.put(token.getId(), token);
|
||||
}
|
||||
|
||||
public Collection<Token> getAllTokens() {
|
||||
return this.tokenMap.values();
|
||||
}
|
||||
|
||||
public Map<String, Token> getTokenMap() {
|
||||
return this.tokenMap;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Token getToken(final ItemStack itemStack) {
|
||||
final String id = Keys.getValue(itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING);
|
||||
if (id == null) return null;
|
||||
return this.tokenMap.get(id);
|
||||
}
|
||||
|
||||
public boolean isToken(final ItemStack itemStack) {
|
||||
return Keys.hasKey(itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING);
|
||||
}
|
||||
|
||||
public void clearTokens() {
|
||||
this.tokenMap.clear();
|
||||
}
|
||||
|
||||
public void clearItems() {
|
||||
this.armorItemMap.clear();
|
||||
}
|
||||
|
||||
public int getBackpackParticleCount(final String id) {
|
||||
return this.backpackParticleCounts.getOrDefault(id, 0);
|
||||
}
|
||||
|
||||
public int getBackpackParticleCount(final ArmorItem armorItem) {
|
||||
return this.getBackpackParticleCount(armorItem.getId());
|
||||
}
|
||||
|
||||
private static final String PARTICLE_COUNT = "particle-count";
|
||||
|
||||
public void load() {
|
||||
this.clearItems();
|
||||
this.backpackParticleCounts.clear();
|
||||
try {
|
||||
final File file = ITEMS_PATH.toFile();
|
||||
if (!file.exists()) {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
}
|
||||
final YamlConfigurationLoader loader = YamlConfigurationLoader.
|
||||
builder().
|
||||
path(ITEMS_PATH).
|
||||
defaultOptions(opts ->
|
||||
opts.serializers(build ->
|
||||
build.register(WrappedGuiItem.class, ArmorItemSerializer.INSTANCE))
|
||||
)
|
||||
.build();
|
||||
for (var node : loader.load().childrenMap().values()) {
|
||||
final WrappedGuiItem item = ArmorItemSerializer.INSTANCE.deserialize(WrappedGuiItem.class, node);
|
||||
if (item instanceof ArmorItem armorItem) {
|
||||
armorItem.setAction(null);
|
||||
if (armorItem.getType() == ArmorItem.Type.SELF_BACKPACK) {
|
||||
final int particleCount = node.node(PARTICLE_COUNT).getInt(5);
|
||||
this.backpackParticleCounts.put(armorItem.getId(), particleCount);
|
||||
}
|
||||
this.armorItemMap.put(armorItem.getId(), armorItem);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package io.github.fisher2911.hmccosmetics.dao;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import java.util.Objects;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@DatabaseTable(tableName = "armor_items")
|
||||
public class ArmorItemDAO {
|
||||
|
||||
@DatabaseField(columnName = "uuid", useGetSet = true, uniqueCombo = true)
|
||||
private String uuid;
|
||||
|
||||
@DatabaseField
|
||||
private String id;
|
||||
|
||||
@DatabaseField(id = true, useGetSet = true, columnName = "artificial_id")
|
||||
private String artificialId;
|
||||
|
||||
@DatabaseField(uniqueCombo = true)
|
||||
private String type;
|
||||
|
||||
@DatabaseField(columnName = "color")
|
||||
private int rgbDye;
|
||||
|
||||
public ArmorItemDAO(final String id, final String type, final int rgbDye) {
|
||||
this.id = id;
|
||||
this.artificialId = this.getArtificialId();
|
||||
this.type = type;
|
||||
this.rgbDye = rgbDye;
|
||||
}
|
||||
|
||||
public ArmorItemDAO() {
|
||||
}
|
||||
|
||||
public static ArmorItemDAO fromArmorItem(final ArmorItem armorItem) {
|
||||
return new ArmorItemDAO(armorItem.getId(), armorItem.getType().toString(), armorItem.getDye());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ArmorItem toArmorItem(final CosmeticManager cosmeticManager) {
|
||||
final ArmorItem armorItem = cosmeticManager.getArmorItem(this.id);
|
||||
if (armorItem == null) {
|
||||
return null;
|
||||
}
|
||||
final ArmorItem copy = armorItem.copy();
|
||||
copy.setDye(this.rgbDye);
|
||||
return copy;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(final String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* ORMLite does not allow more than one primary key (WHYYYY???????????)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getArtificialId() {
|
||||
return this.uuid + "-" + this.type;
|
||||
}
|
||||
|
||||
public void setArtificialId(final String artificialId) {
|
||||
this.artificialId = artificialId;
|
||||
}
|
||||
|
||||
public void setId(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getRgbDye() {
|
||||
return rgbDye;
|
||||
}
|
||||
|
||||
public void setRgbDye(final int rgbDye) {
|
||||
this.rgbDye = rgbDye;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final ArmorItemDAO that = (ArmorItemDAO) o;
|
||||
return Objects.equals(getUuid(), that.getUuid()) && Objects.equals(getType(),
|
||||
that.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getUuid(), getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArmorItemDAO{" +
|
||||
"uuid='" + uuid + '\'' +
|
||||
", id='" + id + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
", rgbDye=" + rgbDye +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package io.github.fisher2911.hmccosmetics.dao;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
|
||||
import io.github.fisher2911.hmccosmetics.user.Backpack;
|
||||
import io.github.fisher2911.hmccosmetics.user.EntityIds;
|
||||
import io.github.fisher2911.hmccosmetics.user.NPCUser;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@DatabaseTable(tableName = "citizen")
|
||||
public class CitizenDAO {
|
||||
|
||||
@DatabaseField(id = true)
|
||||
private int citizensId;
|
||||
|
||||
public CitizenDAO() {
|
||||
}
|
||||
|
||||
public CitizenDAO(final int citizensId) {
|
||||
this.citizensId = citizensId;
|
||||
}
|
||||
|
||||
public void setCitizensId(final int citizensId) {
|
||||
this.citizensId = citizensId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public NPCUser toUser(
|
||||
final CosmeticManager cosmeticManager,
|
||||
final EntityIds entityIds,
|
||||
final List<ArmorItemDAO> armorItems,
|
||||
Backpack backpack
|
||||
) {
|
||||
final PlayerArmor playerArmor = PlayerArmor.empty();
|
||||
|
||||
for (final ArmorItemDAO armorItemDao : armorItems) {
|
||||
final ArmorItem armorItem = armorItemDao.toArmorItem(cosmeticManager);
|
||||
if (armorItem == null) {
|
||||
continue;
|
||||
}
|
||||
playerArmor.setItem(armorItem);
|
||||
}
|
||||
|
||||
return new NPCUser(this.citizensId, playerArmor, backpack, entityIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
final CitizenDAO that = (CitizenDAO) o;
|
||||
return citizensId == that.citizensId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(citizensId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package io.github.fisher2911.hmccosmetics.dao;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
|
||||
import io.github.fisher2911.hmccosmetics.user.Backpack;
|
||||
import io.github.fisher2911.hmccosmetics.user.EntityIds;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@DatabaseTable(tableName = "user")
|
||||
public class UserDAO {
|
||||
|
||||
@DatabaseField(id = true)
|
||||
private UUID uuid;
|
||||
|
||||
public UserDAO() {
|
||||
}
|
||||
|
||||
public UserDAO(final UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public void setUuid(final UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public User toUser(
|
||||
final CosmeticManager cosmeticManager,
|
||||
final EntityIds entityIds,
|
||||
final List<ArmorItemDAO> armorItems,
|
||||
final Backpack backpack,
|
||||
final Wardrobe wardrobe
|
||||
) {
|
||||
final PlayerArmor playerArmor = PlayerArmor.empty();
|
||||
|
||||
for (final ArmorItemDAO armorItemDao : armorItems) {
|
||||
final ArmorItem armorItem = armorItemDao.toArmorItem(cosmeticManager);
|
||||
if (armorItem == null) {
|
||||
continue;
|
||||
}
|
||||
playerArmor.setItem(armorItem);
|
||||
}
|
||||
|
||||
return new User(this.uuid, playerArmor, backpack, wardrobe, entityIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserDAO{" +
|
||||
"uuid=" + uuid +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final UserDAO userDAO = (UserDAO) o;
|
||||
return Objects.equals(uuid, userDAO.uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(uuid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package io.github.fisher2911.hmccosmetics.database;
|
||||
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.dao.DaoManager;
|
||||
import com.j256.ormlite.support.ConnectionSource;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
|
||||
import io.github.fisher2911.hmccosmetics.dao.ArmorItemDAO;
|
||||
import io.github.fisher2911.hmccosmetics.dao.CitizenDAO;
|
||||
import io.github.fisher2911.hmccosmetics.dao.UserDAO;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
|
||||
import io.github.fisher2911.hmccosmetics.user.Backpack;
|
||||
import io.github.fisher2911.hmccosmetics.user.EntityIds;
|
||||
import io.github.fisher2911.hmccosmetics.user.NPCUser;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Database {
|
||||
|
||||
protected final HMCCosmetics plugin;
|
||||
private final Dao<UserDAO, UUID> userDao;
|
||||
private final Dao<CitizenDAO, Integer> citizenDao;
|
||||
private final Dao<ArmorItemDAO, String> armorItemDao;
|
||||
private final ConnectionSource dataSource;
|
||||
private final DatabaseType databaseType;
|
||||
|
||||
public Database(
|
||||
final HMCCosmetics plugin,
|
||||
final ConnectionSource dataSource,
|
||||
final DatabaseType databaseType) throws SQLException {
|
||||
this.plugin = plugin;
|
||||
this.dataSource = dataSource;
|
||||
this.userDao = DaoManager.createDao(this.dataSource, UserDAO.class);
|
||||
this.citizenDao = DaoManager.createDao(this.dataSource, CitizenDAO.class);
|
||||
this.armorItemDao = DaoManager.createDao(this.dataSource, ArmorItemDAO.class);
|
||||
this.databaseType = databaseType;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
Threads.getInstance().execute(() -> new DatabaseConverter(this.plugin, this).convert());
|
||||
}
|
||||
|
||||
protected void createTables() {
|
||||
try {
|
||||
TableUtils.createTableIfNotExists(this.dataSource, ArmorItemDAO.class);
|
||||
TableUtils.createTableIfNotExists(this.dataSource, UserDAO.class);
|
||||
TableUtils.createTableIfNotExists(this.dataSource, CitizenDAO.class);
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadUser(final Entity entity, final Consumer<User> onComplete) {
|
||||
final UUID uuid = entity.getUniqueId();
|
||||
final int armorStandId = getNextEntityId();
|
||||
final int balloonId = getNextEntityId();
|
||||
final int wardrobeViewerId = getNextEntityId();
|
||||
final Wardrobe wardrobe = this.createNewWardrobe(uuid);
|
||||
Threads.getInstance().execute(
|
||||
() -> {
|
||||
try {
|
||||
UserDAO user = this.userDao.queryForId(uuid);
|
||||
|
||||
if (user == null) {
|
||||
user = this.userDao.createIfNotExists(new UserDAO(uuid));
|
||||
}
|
||||
|
||||
final List<ArmorItemDAO> armorItems = this.armorItemDao.queryForEq("uuid", uuid.toString());
|
||||
|
||||
final User actualUser = user.toUser(
|
||||
this.plugin.getCosmeticManager(),
|
||||
new EntityIds(
|
||||
entity.getEntityId(),
|
||||
armorStandId,
|
||||
balloonId,
|
||||
wardrobeViewerId
|
||||
),
|
||||
armorItems,
|
||||
new Backpack(this.plugin, armorStandId),
|
||||
wardrobe
|
||||
);
|
||||
Bukkit.getScheduler().runTask(this.plugin,
|
||||
() -> onComplete.accept(actualUser)
|
||||
);
|
||||
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
onComplete.accept(new User(
|
||||
uuid,
|
||||
PlayerArmor.empty(),
|
||||
new Backpack(this.plugin, armorStandId),
|
||||
wardrobe,
|
||||
new EntityIds(entity.getEntityId(), armorStandId, balloonId, wardrobeViewerId)
|
||||
));
|
||||
}
|
||||
|
||||
public void loadNPCUser(final int id, final Entity entity, final Consumer<NPCUser> onComplete) {
|
||||
final int armorStandId = getNextEntityId();
|
||||
final int balloonId = getNextEntityId();
|
||||
final int wardrobeViewerId = getNextEntityId();
|
||||
Threads.getInstance().execute(
|
||||
() -> {
|
||||
try {
|
||||
CitizenDAO citizen = this.citizenDao.queryForId(id);
|
||||
|
||||
if (citizen == null) {
|
||||
citizen = this.citizenDao.createIfNotExists(new CitizenDAO(id));
|
||||
}
|
||||
|
||||
final List<ArmorItemDAO> armorItems = this.armorItemDao.queryForEq("uuid", String.valueOf(id));
|
||||
|
||||
final NPCUser actualUser = citizen.toUser(
|
||||
this.plugin.getCosmeticManager(),
|
||||
new EntityIds(
|
||||
entity.getEntityId(),
|
||||
armorStandId,
|
||||
balloonId,
|
||||
wardrobeViewerId
|
||||
),
|
||||
armorItems,
|
||||
new Backpack(this.plugin, armorStandId)
|
||||
);
|
||||
|
||||
Bukkit.getScheduler().runTask(this.plugin,
|
||||
() -> onComplete.accept(actualUser)
|
||||
);
|
||||
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
onComplete.accept(new NPCUser(
|
||||
id,
|
||||
PlayerArmor.empty(),
|
||||
new Backpack(this.plugin, armorStandId),
|
||||
new EntityIds(entity.getEntityId(), armorStandId, balloonId, wardrobeViewerId)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void saveUser(final User user) {
|
||||
try {
|
||||
final UserDAO userDAO = new UserDAO(user.getId());
|
||||
this.userDao.createOrUpdate(userDAO);
|
||||
|
||||
final String uuid = user.getId().toString();
|
||||
for (final ArmorItem armorItem : user.getPlayerArmor().getArmorItems()) {
|
||||
final ArmorItemDAO dao = ArmorItemDAO.fromArmorItem(armorItem);
|
||||
dao.setUuid(uuid);
|
||||
this.armorItemDao.createOrUpdate(dao);
|
||||
}
|
||||
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void saveNPCUser(final NPCUser user) {
|
||||
try {
|
||||
final CitizenDAO citizenDAO = new CitizenDAO(user.getId());
|
||||
this.citizenDao.createOrUpdate(citizenDAO);
|
||||
|
||||
final String id = user.getId().toString();
|
||||
for (final ArmorItem armorItem : user.getPlayerArmor().getArmorItems()) {
|
||||
final ArmorItemDAO dao = ArmorItemDAO.fromArmorItem(armorItem);
|
||||
dao.setUuid(id);
|
||||
this.armorItemDao.createOrUpdate(dao);
|
||||
}
|
||||
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void saveAll() {
|
||||
for (final User user : this.plugin.getUserManager().getAll()) {
|
||||
this.saveUser(user);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
this.dataSource.close();
|
||||
} catch (final Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected ConnectionSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
public DatabaseType getDatabaseType() {
|
||||
return databaseType;
|
||||
}
|
||||
|
||||
public Dao<UserDAO, UUID> getUserDao() {
|
||||
return userDao;
|
||||
}
|
||||
|
||||
public Dao<ArmorItemDAO, String> getArmorItemDao() {
|
||||
return armorItemDao;
|
||||
}
|
||||
|
||||
public Wardrobe createNewWardrobe(final UUID ownerUUID) {
|
||||
final int armorStandId = getNextEntityId();
|
||||
return new Wardrobe(
|
||||
this.plugin,
|
||||
UUID.randomUUID(),
|
||||
ownerUUID,
|
||||
PlayerArmor.empty(),
|
||||
new Backpack(this.plugin, armorStandId),
|
||||
new EntityIds(
|
||||
getNextEntityId(),
|
||||
armorStandId,
|
||||
getNextEntityId(),
|
||||
getNextEntityId()
|
||||
),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
public static int getNextEntityId() {
|
||||
Random random = new Random();
|
||||
return random.nextInt(999999);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package io.github.fisher2911.hmccosmetics.database;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
|
||||
import io.github.fisher2911.hmccosmetics.user.Backpack;
|
||||
import io.github.fisher2911.hmccosmetics.user.EntityIds;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class DatabaseConverter {
|
||||
|
||||
private static final int CURRENT_VERSION = 2;
|
||||
private static final String FILE_NAME = "info.yml";
|
||||
private final HMCCosmetics plugin;
|
||||
private final Database database;
|
||||
|
||||
public DatabaseConverter(final HMCCosmetics plugin, final Database database) {
|
||||
this.database = database;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void convert() {
|
||||
final File folder = new File(this.plugin.getDataFolder(), "database");
|
||||
|
||||
final File file = Path.of(
|
||||
folder.getPath(),
|
||||
FILE_NAME
|
||||
).toFile();
|
||||
|
||||
if (!file.exists()) {
|
||||
this.plugin.saveResource("database" + File.separator + FILE_NAME, true);
|
||||
}
|
||||
|
||||
final YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
|
||||
final int version = config.getInt("version") == 0 ? 1 : config.getInt("version");
|
||||
|
||||
final Set<User> users = new HashSet<>();
|
||||
|
||||
this.convert(version, users::add);
|
||||
|
||||
try {
|
||||
config.set("version", CURRENT_VERSION);
|
||||
config.save(file);
|
||||
} catch (final IOException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
this.database.createTables();
|
||||
|
||||
for (final User user : users) {
|
||||
database.saveUser(user);
|
||||
}
|
||||
}
|
||||
|
||||
private void convert(final int version, final Consumer<User> consumer) {
|
||||
switch (version) {
|
||||
case 1 -> this.convertVersionOne(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertVersionOne(final Consumer<User> consumer) {
|
||||
final String query = "SELECT * from user";
|
||||
|
||||
try (final PreparedStatement statement = this.database.getDataSource()
|
||||
.getReadOnlyConnection("user").
|
||||
getUnderlyingConnection().prepareStatement(query)) {
|
||||
final ResultSet results = statement.executeQuery();
|
||||
try {
|
||||
|
||||
final Map<String, ArmorItem> armorItems = new ConcurrentHashMap<>(
|
||||
this.plugin.getCosmeticManager().getArmorItemMap());
|
||||
|
||||
while (results.next()) {
|
||||
final PlayerArmor playerArmor = PlayerArmor.empty();
|
||||
final UUID uuid = UUID.fromString(results.getString(1));
|
||||
final int armorStandId = Database.getNextEntityId();
|
||||
final User user = new User(
|
||||
uuid,
|
||||
playerArmor,
|
||||
new Backpack(this.plugin, armorStandId),
|
||||
this.database.createNewWardrobe(uuid),
|
||||
new EntityIds(
|
||||
-1,
|
||||
armorStandId,
|
||||
Database.getNextEntityId(),
|
||||
Database.getNextEntityId()
|
||||
)
|
||||
);
|
||||
final String backpackId = results.getString(2);
|
||||
final String hatId = results.getString(3);
|
||||
final int hatDye = results.getInt(4);
|
||||
|
||||
final ArmorItem backpack = armorItems.get(backpackId);
|
||||
final ArmorItem hat = armorItems.get(hatId);
|
||||
if (backpack != null) {
|
||||
playerArmor.setItem(backpack);
|
||||
}
|
||||
if (hat != null) {
|
||||
hat.setDye(hatDye);
|
||||
playerArmor.setItem(hat);
|
||||
}
|
||||
|
||||
consumer.accept(user);
|
||||
}
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
try (final PreparedStatement dropStatement = this.database.getDataSource()
|
||||
.getReadWriteConnection("user").
|
||||
getUnderlyingConnection().prepareStatement("DROP TABLE user")) {
|
||||
dropStatement.executeUpdate();
|
||||
} catch (final SQLException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package io.github.fisher2911.hmccosmetics.database;
|
||||
|
||||
import com.j256.ormlite.jdbc.DataSourceConnectionSource;
|
||||
import com.j256.ormlite.jdbc.JdbcPooledConnectionSource;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class DatabaseFactory {
|
||||
|
||||
private static final Path FILE_PATH = HMCCosmetics.PLUGIN_FOLDER.resolve("database.yml");
|
||||
private static final String TYPE_PATH = "type";
|
||||
private static final String NAME_PATH = "name";
|
||||
private static final String USERNAME_PATH = "username";
|
||||
private static final String PASSWORD_PATH = "password";
|
||||
private static final String IP_PATH = "ip";
|
||||
private static final String PORT_PATH = "port";
|
||||
|
||||
public static Database create(final HMCCosmetics plugin) throws SQLException {
|
||||
if (!Files.exists(FILE_PATH)) {
|
||||
plugin.saveResource(FILE_PATH.getFileName().toString(), false);
|
||||
}
|
||||
|
||||
final FileConfiguration config = YamlConfiguration.loadConfiguration(FILE_PATH.toFile());
|
||||
|
||||
final String type = config.getString(TYPE_PATH);
|
||||
|
||||
final Logger logger = plugin.getLogger();
|
||||
|
||||
if (type == null) {
|
||||
logger.severe("Database type was null, disabling plugin.");
|
||||
Bukkit.getPluginManager().disablePlugin(plugin);
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
final Database database = switch (type.toLowerCase()) {
|
||||
case "mysql" -> {
|
||||
final String name = config.getString(NAME_PATH);
|
||||
final String username = config.getString(USERNAME_PATH);
|
||||
final String password = config.getString(PASSWORD_PATH);
|
||||
final String ip = config.getString(IP_PATH);
|
||||
final String port = config.getString(PORT_PATH);
|
||||
|
||||
final HikariConfig hikari = new HikariConfig();
|
||||
|
||||
final String jdbcUrl = "jdbc:mysql://" + ip + ":" + port + "/" + name;
|
||||
|
||||
hikari.setJdbcUrl(jdbcUrl);
|
||||
hikari.setUsername(username);
|
||||
hikari.setPassword(password);
|
||||
hikari.setConnectionTimeout(1000000000);
|
||||
|
||||
final HikariDataSource source = new HikariDataSource(hikari);
|
||||
|
||||
yield new Database(
|
||||
plugin,
|
||||
new DataSourceConnectionSource(source, jdbcUrl),
|
||||
DatabaseType.MYSQL
|
||||
);
|
||||
}
|
||||
case "sqlite" -> {
|
||||
final File folder = new File(plugin.getDataFolder().getPath(), "database");
|
||||
folder.mkdirs();
|
||||
yield new Database(plugin, new JdbcPooledConnectionSource("jdbc:sqlite:" + new File(
|
||||
folder.getPath(),
|
||||
"users.db"
|
||||
).getPath()),
|
||||
DatabaseType.SQLITE
|
||||
);
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
|
||||
if (database == null) {
|
||||
logger.severe(
|
||||
"Error loading database, type " + type + " is invalid! Disabling plugin.");
|
||||
Bukkit.getPluginManager().disablePlugin(plugin);
|
||||
}
|
||||
|
||||
return database;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package io.github.fisher2911.hmccosmetics.database;
|
||||
|
||||
public enum DatabaseType {
|
||||
|
||||
MYSQL,
|
||||
SQLITE
|
||||
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
package io.github.fisher2911.hmccosmetics.gui;
|
||||
|
||||
import dev.triumphteam.gui.components.GuiAction;
|
||||
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.ColorBuilder;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArmorItem extends WrappedGuiItem {
|
||||
|
||||
private final String name;
|
||||
private final String id;
|
||||
private final ItemStack lockedItem;
|
||||
private final ItemStack appliedItem;
|
||||
private final String permission;
|
||||
private final Type type;
|
||||
private List<CosmeticGuiAction> actions;
|
||||
private boolean dyeable;
|
||||
private int dye;
|
||||
|
||||
public ArmorItem(
|
||||
@NotNull final ItemStack itemStack,
|
||||
final List<CosmeticGuiAction> actions,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack lockedItem,
|
||||
final ItemStack appliedItem,
|
||||
final String permission,
|
||||
final Type type,
|
||||
final int dye) {
|
||||
super(itemStack, null);
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.lockedItem = lockedItem;
|
||||
this.appliedItem = appliedItem;
|
||||
this.actions = actions;
|
||||
this.permission = permission;
|
||||
this.type = type;
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
public ArmorItem(
|
||||
@NotNull final ItemStack itemStack,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack lockedItem,
|
||||
final ItemStack appliedItem,
|
||||
final String permission,
|
||||
final Type type,
|
||||
final int dye) {
|
||||
super(itemStack);
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.lockedItem = lockedItem;
|
||||
this.appliedItem = appliedItem;
|
||||
this.actions = new ArrayList<>();
|
||||
this.permission = permission;
|
||||
this.type = type;
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
public ArmorItem(
|
||||
@NotNull final Material material,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack lockedItem,
|
||||
final ItemStack appliedItem,
|
||||
final String permission,
|
||||
final Type type,
|
||||
final int dye) {
|
||||
super(material);
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.lockedItem = lockedItem;
|
||||
this.appliedItem = appliedItem;
|
||||
this.actions = new ArrayList<>();
|
||||
this.permission = permission;
|
||||
this.type = type;
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
public ArmorItem(
|
||||
@NotNull final Material material,
|
||||
final List<CosmeticGuiAction> actions,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack lockedItem,
|
||||
final ItemStack appliedItem,
|
||||
final String permission,
|
||||
final Type type,
|
||||
final int dye) {
|
||||
super(material, null);
|
||||
this.actions = actions;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.lockedItem = lockedItem;
|
||||
this.appliedItem = appliedItem;
|
||||
this.permission = permission;
|
||||
this.type = type;
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
public ArmorItem(
|
||||
@NotNull final ItemStack itemStack,
|
||||
final List<CosmeticGuiAction> actions,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack lockedItem,
|
||||
final ItemStack appliedItem,
|
||||
final String permission,
|
||||
final Type type,
|
||||
final boolean dyeable,
|
||||
final int dye) {
|
||||
super(itemStack, null);
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.lockedItem = lockedItem;
|
||||
this.appliedItem = appliedItem;
|
||||
this.actions = actions;
|
||||
this.permission = permission;
|
||||
this.type = type;
|
||||
this.dyeable = dyeable;
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
public ArmorItem(
|
||||
@NotNull final ItemStack itemStack,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack lockedItem,
|
||||
final ItemStack appliedItem,
|
||||
final String permission,
|
||||
final Type type,
|
||||
final boolean dyeable,
|
||||
final int dye) {
|
||||
super(itemStack);
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.lockedItem = lockedItem;
|
||||
this.appliedItem = appliedItem;
|
||||
this.actions = new ArrayList<>();
|
||||
this.permission = permission;
|
||||
this.type = type;
|
||||
this.dyeable = dyeable;
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
public ArmorItem(
|
||||
@NotNull final Material material,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack lockedItem,
|
||||
final ItemStack appliedItem,
|
||||
final String permission,
|
||||
final Type type,
|
||||
final boolean dyeable,
|
||||
final int dye) {
|
||||
super(material);
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.lockedItem = lockedItem;
|
||||
this.appliedItem = appliedItem;
|
||||
this.actions = new ArrayList<>();
|
||||
this.permission = permission;
|
||||
this.type = type;
|
||||
this.dyeable = dyeable;
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
public ArmorItem(
|
||||
@NotNull final Material material,
|
||||
@Nullable final GuiAction<InventoryClickEvent> action,
|
||||
final String name,
|
||||
final String id,
|
||||
final ItemStack lockedItem,
|
||||
final ItemStack appliedItem,
|
||||
final String permission,
|
||||
final Type type,
|
||||
final boolean dyeable,
|
||||
final int dye) {
|
||||
super(material, action);
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.lockedItem = lockedItem;
|
||||
this.appliedItem = appliedItem;
|
||||
this.actions = new ArrayList<>();
|
||||
this.permission = permission;
|
||||
this.type = type;
|
||||
this.dyeable = dyeable;
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
protected ArmorItem(final ArmorItem armorItem) {
|
||||
super(armorItem.getItemStack().clone(), null);
|
||||
this.name = armorItem.getName();
|
||||
this.id = armorItem.getId();
|
||||
this.lockedItem = armorItem.getLockedItem().clone();
|
||||
this.appliedItem = armorItem.getAppliedItem().clone();
|
||||
this.actions = armorItem.getActions();
|
||||
this.permission = armorItem.getPermission();
|
||||
this.type = armorItem.getType();
|
||||
this.dyeable = armorItem.isDyeable();
|
||||
this.dye = armorItem.getDye();
|
||||
}
|
||||
|
||||
public static ArmorItem empty(final Type type) {
|
||||
return empty(type, "");
|
||||
}
|
||||
|
||||
public static ArmorItem empty(final Type type, final String id) {
|
||||
if (type == Type.BALLOON) {
|
||||
return new BalloonItem(
|
||||
new ItemStack(Material.AIR),
|
||||
id,
|
||||
id,
|
||||
new ItemStack(Material.AIR),
|
||||
new ItemStack(Material.AIR),
|
||||
"",
|
||||
type,
|
||||
-1,
|
||||
""
|
||||
);
|
||||
}
|
||||
return new ArmorItem(
|
||||
new ItemStack(Material.AIR),
|
||||
id,
|
||||
id,
|
||||
new ItemStack(Material.AIR),
|
||||
new ItemStack(Material.AIR),
|
||||
"",
|
||||
type,
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public ItemStack getLockedItem() {
|
||||
return lockedItem;
|
||||
}
|
||||
|
||||
public ItemStack getAppliedItem() {
|
||||
return appliedItem;
|
||||
}
|
||||
|
||||
public List<CosmeticGuiAction> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public void setActions(final List<CosmeticGuiAction> actions) {
|
||||
this.actions.clear();
|
||||
this.actions.addAll(actions);
|
||||
}
|
||||
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isDyeable() {
|
||||
return dyeable;
|
||||
}
|
||||
|
||||
public int getDye() {
|
||||
return dye;
|
||||
}
|
||||
|
||||
public void setDye(final int dye) {
|
||||
this.dye = dye;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack(final Status status) {
|
||||
return this.color(switch (status) {
|
||||
case ALLOWED -> super.getItemStack();
|
||||
case LOCKED -> this.getLockedItem();
|
||||
case APPLIED -> this.getAppliedItem();
|
||||
});
|
||||
}
|
||||
|
||||
private ItemStack color(final ItemStack itemStack) {
|
||||
if (this.dye == -1 || !ColorBuilder.canBeColored(itemStack)) {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
return ColorBuilder.from(itemStack).
|
||||
color(Color.fromRGB(this.dye)).
|
||||
build();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.getItemStack().getType() == Material.AIR;
|
||||
}
|
||||
|
||||
public ArmorItem copy() {
|
||||
if (this instanceof final BalloonItem item) {
|
||||
return new BalloonItem(item);
|
||||
}
|
||||
return new ArmorItem(this);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
|
||||
HAT(EquipmentSlot.HEAD),
|
||||
BACKPACK(null),
|
||||
SELF_BACKPACK(null),
|
||||
BALLOON(null),
|
||||
OFF_HAND(EquipmentSlot.OFF_HAND),
|
||||
CHEST_PLATE(EquipmentSlot.CHEST),
|
||||
PANTS(EquipmentSlot.LEGS),
|
||||
BOOTS(EquipmentSlot.FEET);
|
||||
|
||||
private final EquipmentSlot slot;
|
||||
|
||||
Type(final EquipmentSlot slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public EquipmentSlot getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Type fromWrapper(EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
case HEAD -> Type.HAT;
|
||||
case CHEST -> Type.CHEST_PLATE;
|
||||
case LEGS -> Type.PANTS;
|
||||
case FEET -> Type.BOOTS;
|
||||
case OFF_HAND -> Type.OFF_HAND;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Type fromEquipmentSlot(final EquipmentSlot slot) {
|
||||
for (final Type type : values()) {
|
||||
if (type.getSlot() == slot) return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Status {
|
||||
ALLOWED,
|
||||
LOCKED,
|
||||
APPLIED
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package io.github.fisher2911.hmccosmetics.gui;
|
||||
|
||||
import dev.triumphteam.gui.components.GuiAction;
|
||||
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BalloonItem extends ArmorItem {
|
||||
|
||||
private final String modelId;
|
||||
|
||||
public BalloonItem(final BalloonItem item) {
|
||||
this(
|
||||
item.getItemStack(),
|
||||
item.getActions(),
|
||||
item.getName(),
|
||||
item.getId(),
|
||||
item.getLockedItem(),
|
||||
item.getAppliedItem(),
|
||||
item.getPermission(),
|
||||
item.getType(),
|
||||
item.getDye(),
|
||||
item.getModelId()
|
||||
);
|
||||
}
|
||||
|
||||
public BalloonItem(final @NotNull ItemStack itemStack, final List<CosmeticGuiAction> actions, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final int dye, final String modelId) {
|
||||
super(itemStack, actions, name, id, lockedItem, appliedItem, permission, type, dye);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public BalloonItem(final @NotNull ItemStack itemStack, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final int dye, final String modelId) {
|
||||
super(itemStack, name, id, lockedItem, appliedItem, permission, type, dye);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public BalloonItem(final @NotNull Material material, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final int dye, final String modelId) {
|
||||
super(material, name, id, lockedItem, appliedItem, permission, type, dye);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public BalloonItem(final @NotNull Material material, final List<CosmeticGuiAction> actions, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final int dye, final String modelId) {
|
||||
super(material, actions, name, id, lockedItem, appliedItem, permission, type, dye);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public BalloonItem(final @NotNull ItemStack itemStack, final List<CosmeticGuiAction> actions, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
|
||||
super(itemStack, actions, name, id, lockedItem, appliedItem, permission, type, dyeable, dye);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public BalloonItem(final @NotNull ItemStack itemStack, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
|
||||
super(itemStack, name, id, lockedItem, appliedItem, permission, type, dyeable, dye);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public BalloonItem(final @NotNull Material material, final String name, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
|
||||
super(material, name, id, lockedItem, appliedItem, permission, type, dyeable, dye);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public BalloonItem(final @NotNull Material material, final String name, final @Nullable GuiAction<InventoryClickEvent> action, final String id, final ItemStack lockedItem, final ItemStack appliedItem, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
|
||||
super(material, action, name, id, lockedItem, appliedItem, permission, type, dyeable, dye);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public BalloonItem(final ArmorItem armorItem, final String modelId) {
|
||||
super(armorItem);
|
||||
this.modelId = modelId;
|
||||
}
|
||||
|
||||
public String getModelId() {
|
||||
if (this.modelId == null) {
|
||||
return Strings.EMPTY;
|
||||
}
|
||||
return this.modelId;
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,16 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ColorItem extends GuiItem {
|
||||
public class ColorItem extends WrappedGuiItem {
|
||||
|
||||
private final Color color;
|
||||
|
||||
public ColorItem(final @NotNull ItemStack itemStack, final GuiAction<InventoryClickEvent> action, final Color color) {
|
||||
public ColorItem(final GuiItem item, final GuiAction<InventoryClickEvent> action, final Color color) {
|
||||
super(item, action);
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public ColorItem(final @NotNull ItemStack itemStack, final @Nullable GuiAction<@NotNull InventoryClickEvent> action, final Color color) {
|
||||
super(itemStack, action);
|
||||
this.color = color;
|
||||
}
|
||||
@@ -28,7 +33,7 @@ public class ColorItem extends GuiItem {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public ColorItem(final @NotNull Material material, final @Nullable GuiAction<InventoryClickEvent> action, final Color color) {
|
||||
public ColorItem(final @NotNull Material material, final @Nullable GuiAction<@NotNull InventoryClickEvent> action, final Color color) {
|
||||
super(material, action);
|
||||
this.color = color;
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
package io.github.fisher2911.hmccosmetics.gui;
|
||||
|
||||
import dev.triumphteam.gui.guis.Gui;
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
|
||||
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
|
||||
import io.github.fisher2911.hmccosmetics.message.Adventure;
|
||||
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
|
||||
import io.github.fisher2911.hmccosmetics.message.Messages;
|
||||
import io.github.fisher2911.hmccosmetics.message.Placeholder;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class CosmeticGui {
|
||||
|
||||
private static final float COOL_DOWN = 0.5f;
|
||||
protected final HMCCosmetics plugin;
|
||||
protected final MessageHandler messageHandler;
|
||||
protected final String title;
|
||||
protected final int rows;
|
||||
protected final Map<Integer, ItemStack> itemStackMap;
|
||||
protected final Map<Integer, GuiItem> guiItemMap;
|
||||
protected Gui gui;
|
||||
private long lastClicked;
|
||||
|
||||
public CosmeticGui(
|
||||
final HMCCosmetics plugin,
|
||||
final String title,
|
||||
final int rows,
|
||||
final Map<Integer, GuiItem> guiItemMap) {
|
||||
this.plugin = plugin;
|
||||
this.messageHandler = this.plugin.getMessageHandler();
|
||||
this.title = title;
|
||||
this.rows = rows;
|
||||
this.guiItemMap = guiItemMap;
|
||||
this.itemStackMap = new HashMap<>();
|
||||
this.guiItemMap.forEach((key, value) -> itemStackMap.put(key, value.getItemStack()));
|
||||
|
||||
}
|
||||
|
||||
private void setItems(final User user) {
|
||||
final Player player = user.getPlayer();
|
||||
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final var entry : guiItemMap.entrySet()) {
|
||||
final int slot = entry.getKey();
|
||||
|
||||
final GuiItem guiItem = this.getGuiItem(user, player, slot);
|
||||
if (guiItem == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.gui.setItem(slot, guiItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUserArmor(
|
||||
final HumanEntity human,
|
||||
final User user,
|
||||
final ArmorItem armorItem,
|
||||
final InventoryClickEvent event,
|
||||
final List<CosmeticGuiAction> actions) {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
if ((current - this.lastClicked) / 1000. < COOL_DOWN) {
|
||||
return;
|
||||
}
|
||||
this.lastClicked = current;
|
||||
|
||||
if (!(human instanceof final Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ArmorItem.Type type = armorItem.getType();
|
||||
|
||||
final User setUser;
|
||||
if (user.isWardrobeActive()) {
|
||||
setUser = user.getWardrobe();
|
||||
} else {
|
||||
setUser = user;
|
||||
}
|
||||
final ArmorItem setTo = this.plugin.getUserManager().setOrUnset(
|
||||
setUser,
|
||||
armorItem,
|
||||
Messages.getRemovedMessage(type),
|
||||
Messages.getSetMessage(type),
|
||||
true
|
||||
);
|
||||
|
||||
if (!setTo.isEmpty()) {
|
||||
executeActions(event, actions, CosmeticGuiAction.When.EQUIP);
|
||||
} else {
|
||||
executeActions(event, actions, CosmeticGuiAction.When.REMOVE);
|
||||
}
|
||||
|
||||
final int slot = event.getSlot();
|
||||
|
||||
final GuiItem guiItem = this.getGuiItem(user, player, slot);
|
||||
|
||||
if (guiItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.gui.updateItem(slot, guiItem);
|
||||
}
|
||||
|
||||
private void executeActions(
|
||||
final InventoryClickEvent event,
|
||||
final List<CosmeticGuiAction> actions,
|
||||
final CosmeticGuiAction.When when
|
||||
) {
|
||||
for (final CosmeticGuiAction action : actions) {
|
||||
action.execute(event, when);
|
||||
}
|
||||
}
|
||||
|
||||
public void open(final User user, final Player player) {
|
||||
final Component component = Adventure.MINI_MESSAGE.deserialize(Placeholder.applyPapiPlaceholders(user.getPlayer(), this.title));
|
||||
this.gui = Gui.gui().
|
||||
title(component).
|
||||
rows(this.rows).
|
||||
create();
|
||||
|
||||
this.gui.setDefaultClickAction(event -> event.setCancelled(true));
|
||||
this.gui.setCloseGuiAction(event -> user.setOpenGui(null));
|
||||
|
||||
this.setItems(user);
|
||||
|
||||
this.gui.open(player);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GuiItem getGuiItem(final User user, final Player player, final int slot) {
|
||||
final GuiItem guiItem = this.guiItemMap.get(slot);
|
||||
if (guiItem == null) {
|
||||
return null;
|
||||
}
|
||||
final ItemStack itemStack = this.itemStackMap.get(slot);
|
||||
if (itemStack == null) return null;
|
||||
return this.getGuiItem(user, player, guiItem, itemStack);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected GuiItem getGuiItem(final User user, final Player player, final GuiItem guiItem, final ItemStack itemStack) {
|
||||
if (guiItem instanceof final ArmorItem armorItem) {
|
||||
final String permission =
|
||||
armorItem.getPermission() == null ? "" : armorItem.getPermission();
|
||||
|
||||
final boolean hasPermission = permission.isBlank() || user.hasPermissionToUse(armorItem);
|
||||
|
||||
return new GuiItem(
|
||||
this.applyPlaceholders(user, player, armorItem, hasPermission),
|
||||
event -> {
|
||||
if (!hasPermission) {
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.NO_COSMETIC_PERMISSION
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final ArmorItem cosmeticItem = this.plugin.getCosmeticManager()
|
||||
.getArmorItem(armorItem.getId());
|
||||
|
||||
if (cosmeticItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setUserArmor(player, user, cosmeticItem, event, armorItem.getActions());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
guiItem.setItemStack(
|
||||
ItemBuilder.from(itemStack.clone()).papiPlaceholders(player).build()
|
||||
);
|
||||
|
||||
return guiItem;
|
||||
}
|
||||
|
||||
protected ItemStack applyPlaceholders(
|
||||
final User user,
|
||||
final Player player,
|
||||
final ArmorItem armorItem,
|
||||
final boolean hasPermission
|
||||
) {
|
||||
final Map<String, String> placeholders = new HashMap<>();
|
||||
|
||||
final PlayerArmor playerArmor = user.getPlayerArmor();
|
||||
|
||||
final ArmorItem.Type type = armorItem.getType();
|
||||
|
||||
final String id = playerArmor.getItem(type).getId();
|
||||
|
||||
placeholders.put(
|
||||
Placeholder.ENABLED,
|
||||
String.valueOf(id.equals(armorItem.getId())).
|
||||
toLowerCase(Locale.ROOT));
|
||||
|
||||
placeholders.put(
|
||||
Placeholder.ALLOWED,
|
||||
String.valueOf(hasPermission).
|
||||
toLowerCase(Locale.ROOT));
|
||||
|
||||
final ItemStack itemStack;
|
||||
|
||||
if (!hasPermission) {
|
||||
itemStack = armorItem.getItemStack(ArmorItem.Status.LOCKED);
|
||||
} else {
|
||||
itemStack = armorItem.getItemStack(ArmorItem.Status.ALLOWED);
|
||||
}
|
||||
|
||||
return ItemBuilder.from(
|
||||
itemStack
|
||||
).namePlaceholders(placeholders).
|
||||
lorePlaceholders(placeholders).
|
||||
papiPlaceholders(player).
|
||||
build();
|
||||
}
|
||||
|
||||
public void updateItem(final int slot, final GuiItem guiItem, final User user, final Player player) {
|
||||
final ItemStack itemStack = guiItem.getItemStack().clone();
|
||||
this.guiItemMap.put(slot, guiItem);
|
||||
this.itemStackMap.put(slot, itemStack);
|
||||
final GuiItem setItem = this.getGuiItem(user, player, guiItem, itemStack);
|
||||
if (setItem == null) return;
|
||||
this.gui.updateItem(slot, setItem);
|
||||
}
|
||||
|
||||
public CosmeticGui copy() {
|
||||
return new CosmeticGui(
|
||||
this.plugin,
|
||||
this.title,
|
||||
this.rows,
|
||||
new HashMap<>(this.guiItemMap)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package io.github.fisher2911.hmccosmetics.gui;
|
||||
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.config.ArmorItemSerializer;
|
||||
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
|
||||
import io.github.fisher2911.hmccosmetics.config.DyeGuiSerializer;
|
||||
import io.github.fisher2911.hmccosmetics.config.GuiSerializer;
|
||||
import io.github.fisher2911.hmccosmetics.config.TokenGuiSerializer;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public class CosmeticsMenu {
|
||||
|
||||
public static final String DEFAULT_MAIN_MENU = "main";
|
||||
public static final String DEFAULT_DYE_MENU = "dye-menu";
|
||||
public static final String DEFAULT_TOKEN_MENU = "token-menu";
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final CosmeticSettings settings;
|
||||
private final CosmeticManager cosmeticManager;
|
||||
|
||||
private final Map<String, CosmeticGui> guiMap = new HashMap<>();
|
||||
|
||||
private final Set<String> registeredPermissions = new HashSet<>();
|
||||
|
||||
public CosmeticsMenu(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.settings = this.plugin.getSettings().getCosmeticSettings();
|
||||
this.cosmeticManager = this.plugin.getCosmeticManager();
|
||||
}
|
||||
|
||||
public void openMenu(final String id, final HumanEntity humanEntity) {
|
||||
if (!(humanEntity instanceof final Player player)) return;
|
||||
final CosmeticGui cosmeticGui = this.getGui(id);
|
||||
|
||||
final Optional<User> optionalUser = this.plugin.getUserManager().get(humanEntity.getUniqueId());
|
||||
|
||||
if (optionalUser.isEmpty()) return;
|
||||
|
||||
User user = optionalUser.get();
|
||||
|
||||
final Wardrobe wardrobe = user.getWardrobe();
|
||||
if (wardrobe.isActive()) user = wardrobe;
|
||||
|
||||
if (cosmeticGui instanceof final DyeSelectorGui dyeSelectorGui) {
|
||||
dyeSelectorGui.getGui(user, user.getLastSetItem().getType()).open(humanEntity);
|
||||
user.setOpenGui(dyeSelectorGui);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cosmeticGui != null) {
|
||||
user.setOpenGui(cosmeticGui);
|
||||
cosmeticGui.open(user, player);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getMenus() {
|
||||
return this.guiMap.keySet();
|
||||
}
|
||||
|
||||
public void openDefault(final HumanEntity humanEntity) {
|
||||
this.openMenu(this.settings.getDefaultMenu(), humanEntity);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
for (final ArmorItem armorItem : this.cosmeticManager.getAllArmorItems()) {
|
||||
Bukkit.getPluginManager().removePermission(new Permission(armorItem.getPermission()));
|
||||
}
|
||||
this.load();
|
||||
}
|
||||
|
||||
public void openDyeSelectorGui(
|
||||
User user,
|
||||
final ArmorItem.Type type) {
|
||||
|
||||
final Player player = user.getPlayer();
|
||||
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Wardrobe wardrobe = user.getWardrobe();
|
||||
if (wardrobe.isActive()) user = wardrobe;
|
||||
|
||||
final CosmeticGui gui = this.getGui(this.settings.getDefaultMenu());
|
||||
|
||||
if (gui instanceof final DyeSelectorGui dyeSelectorGui) {
|
||||
dyeSelectorGui.getGui(user, type).open(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CosmeticGui getGui(final String id) {
|
||||
final CosmeticGui gui = this.guiMap.get(id);
|
||||
if (gui == null) return null;
|
||||
return gui.copy();
|
||||
}
|
||||
|
||||
private static final String GUI_TYPE = "gui-type";
|
||||
private static final String DYE_TYPE = "dye";
|
||||
private static final String TOKEN_TYPE = "token";
|
||||
|
||||
public void load() {
|
||||
this.guiMap.clear();
|
||||
this.cosmeticManager.clearTokens();
|
||||
this.cosmeticManager.load();
|
||||
final File file = Path.of(this.plugin.getDataFolder().getPath(),
|
||||
"menus").toFile();
|
||||
|
||||
if (!Path.of(this.plugin.getDataFolder().getPath(),
|
||||
"menus",
|
||||
this.settings.getDefaultMenu() + ".yml").toFile().exists()) {
|
||||
this.plugin.saveResource(
|
||||
new File("menus", this.settings.getDefaultMenu() + ".yml").getPath(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (!Path.of(this.plugin.getDataFolder().getPath(),
|
||||
"menus",
|
||||
DEFAULT_DYE_MENU + ".yml").toFile().exists()) {
|
||||
this.plugin.saveResource(
|
||||
new File("menus", DEFAULT_DYE_MENU + ".yml").getPath(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (!Path.of(this.plugin.getDataFolder().getPath(),
|
||||
"menus",
|
||||
DEFAULT_TOKEN_MENU + ".yml").toFile().exists()) {
|
||||
this.plugin.saveResource(
|
||||
new File("menus", DEFAULT_TOKEN_MENU + ".yml").getPath(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (!file.exists() ||
|
||||
!file.isDirectory()) {
|
||||
this.plugin.getLogger().severe("No directory found");
|
||||
return;
|
||||
}
|
||||
|
||||
final List<File> files = this.getSubFiles(file);
|
||||
|
||||
if (files.isEmpty()) {
|
||||
this.plugin.getLogger().severe("No GUI files found.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (final File guiFile : files) {
|
||||
final String id = guiFile.getName().replace(".yml", "");
|
||||
|
||||
final YamlConfigurationLoader loader = YamlConfigurationLoader.
|
||||
builder().
|
||||
path(Path.of(guiFile.getPath())).
|
||||
defaultOptions(opts ->
|
||||
opts.serializers(build -> {
|
||||
build.register(WrappedGuiItem.class, ArmorItemSerializer.INSTANCE);
|
||||
build.register(CosmeticGui.class, GuiSerializer.INSTANCE);
|
||||
build.register(DyeSelectorGui.class, DyeGuiSerializer.INSTANCE);
|
||||
build.register(TokenGui.class, TokenGuiSerializer.INSTANCE);
|
||||
}))
|
||||
.build();
|
||||
|
||||
try {
|
||||
final ConfigurationNode source = loader.load();
|
||||
final ConfigurationNode typeNode = source.node(GUI_TYPE);
|
||||
|
||||
final String type;
|
||||
|
||||
if (typeNode != null) {
|
||||
type = typeNode.getString();
|
||||
} else {
|
||||
type = "";
|
||||
}
|
||||
|
||||
if (id.equals(DEFAULT_DYE_MENU) || DYE_TYPE.equals(type)) {
|
||||
this.guiMap.put(id, DyeGuiSerializer.INSTANCE.deserialize(DyeSelectorGui.class, source));
|
||||
this.plugin.getLogger().info("Loaded dye gui: " + id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TOKEN_TYPE.equals(type)) {
|
||||
this.guiMap.put(id, TokenGuiSerializer.INSTANCE.deserialize(TokenGui.class, source));
|
||||
this.plugin.getLogger().info("Loaded token gui: " + id);
|
||||
continue;
|
||||
}
|
||||
|
||||
final CosmeticGui gui = source.get(CosmeticGui.class);
|
||||
|
||||
if (gui == null) continue;
|
||||
|
||||
for (final GuiItem guiItem : gui.guiItemMap.values()) {
|
||||
if (guiItem instanceof final ArmorItem item) {
|
||||
final ArmorItem copy = item.copy();
|
||||
copy.setAction(null);
|
||||
this.cosmeticManager.addArmorItem(copy);
|
||||
final String perm = copy.getPermission();
|
||||
if (perm.isBlank() || this.registeredPermissions.contains(perm)) continue;
|
||||
this.registeredPermissions.add(perm);
|
||||
Bukkit.getPluginManager().addPermission(new Permission(perm));
|
||||
}
|
||||
}
|
||||
|
||||
this.guiMap.put(id, source.get(CosmeticGui.class));
|
||||
this.plugin.getLogger().info("Loaded gui: " + id);
|
||||
} catch (final ConfigurateException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private List<File> getSubFiles(final File dir) {
|
||||
final List<File> files = new ArrayList<>();
|
||||
if (!dir.isDirectory()) return files;
|
||||
final File[] arr = dir.listFiles();
|
||||
if (arr == null) return files;
|
||||
for (final File file : arr) {
|
||||
if (file.isDirectory()) {
|
||||
files.addAll(this.getSubFiles(file));
|
||||
continue;
|
||||
}
|
||||
files.add(file);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package io.github.fisher2911.hmccosmetics.gui;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import dev.triumphteam.gui.guis.Gui;
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
|
||||
import io.github.fisher2911.hmccosmetics.message.Adventure;
|
||||
import io.github.fisher2911.hmccosmetics.message.Placeholder;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DyeSelectorGui extends CosmeticGui {
|
||||
|
||||
private final BiMap<Integer, ArmorItem.Type> cosmeticsSlots;
|
||||
private int selectedCosmetic;
|
||||
|
||||
public DyeSelectorGui(
|
||||
final HMCCosmetics plugin,
|
||||
final String title,
|
||||
final int rows,
|
||||
final Map<Integer, GuiItem> guiItemMap,
|
||||
final BiMap<Integer, ArmorItem.Type> cosmeticsSlots,
|
||||
final int selectedCosmetic
|
||||
) {
|
||||
super(plugin, title, rows, guiItemMap);
|
||||
this.cosmeticsSlots = cosmeticsSlots;
|
||||
this.selectedCosmetic = selectedCosmetic;
|
||||
}
|
||||
|
||||
public Gui getGui(final User user) {
|
||||
return this.getGui(user, null);
|
||||
}
|
||||
|
||||
public Gui getGui(final User user, @Nullable final ArmorItem.Type type) {
|
||||
final Component component = Adventure.MINI_MESSAGE.deserialize(Placeholder.applyPapiPlaceholders(user.getPlayer(), this.title));
|
||||
this.gui = Gui.gui().
|
||||
title(component).
|
||||
rows(rows).
|
||||
create();
|
||||
|
||||
final Player player = user.getPlayer();
|
||||
|
||||
if (type != null) {
|
||||
final Integer selected = this.cosmeticsSlots.inverse().get(type);
|
||||
this.selectedCosmetic = selected == null ? this.selectedCosmetic : selected;
|
||||
}
|
||||
|
||||
for (final var entry : this.guiItemMap.entrySet()) {
|
||||
|
||||
final GuiItem guiItem = entry.getValue();
|
||||
|
||||
final ItemStack itemStack = this.itemStackMap.get(entry.getKey());
|
||||
|
||||
if (itemStack == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
guiItem.setItemStack(
|
||||
ItemBuilder.from(itemStack.clone()).papiPlaceholders(player).build()
|
||||
);
|
||||
|
||||
gui.setItem(entry.getKey(), guiItem);
|
||||
}
|
||||
|
||||
for (final var entry : this.cosmeticsSlots.entrySet()) {
|
||||
|
||||
final ArmorItem guiItem = user.getPlayerArmor().getItem(entry.getValue()).copy();
|
||||
|
||||
final ItemStack itemStack = guiItem.getItemStack();
|
||||
|
||||
if (itemStack == null || guiItem.isEmpty()) continue;
|
||||
|
||||
guiItem.setItemStack(
|
||||
ItemBuilder.from(
|
||||
this.applyPlaceholders(
|
||||
user, player, guiItem, true
|
||||
)
|
||||
).build()
|
||||
);
|
||||
|
||||
gui.setItem(entry.getKey(), guiItem);
|
||||
}
|
||||
|
||||
final PlayerArmor playerArmor = user.getPlayerArmor();
|
||||
|
||||
this.select(this.selectedCosmetic, user, player);
|
||||
|
||||
gui.setDefaultClickAction(event -> {
|
||||
event.setCancelled(true);
|
||||
|
||||
final ArmorItem armorItem = playerArmor.getItem(
|
||||
this.cosmeticsSlots.get(this.selectedCosmetic)
|
||||
);
|
||||
|
||||
if (armorItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ItemStack itemStack = playerArmor.getItem(type).getItemStack();
|
||||
|
||||
if (itemStack == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int slot = event.getSlot();
|
||||
|
||||
final ArmorItem.Type clickedType = this.cosmeticsSlots.get(slot);
|
||||
|
||||
if (clickedType != null) {
|
||||
this.select(slot, user, player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!armorItem.isDyeable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final GuiItem guiItem = this.guiItemMap.get(slot);
|
||||
|
||||
if (!(guiItem instanceof ColorItem colorItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
armorItem.setDye(colorItem.getColor().asRGB());
|
||||
|
||||
if (user.isWardrobeActive()) {
|
||||
this.plugin.getUserManager().setItem(user.getWardrobe(), armorItem, true);
|
||||
} else {
|
||||
this.plugin.getUserManager().setItem(user, armorItem, true);
|
||||
}
|
||||
if (colorItem.getAction() != null) {
|
||||
colorItem.getAction().execute(event);
|
||||
}
|
||||
this.updateSelected(user, player);
|
||||
});
|
||||
|
||||
return gui;
|
||||
}
|
||||
|
||||
private void select(final int slot, final User user, final Player player) {
|
||||
|
||||
final PlayerArmor playerArmor = user.getPlayerArmor();
|
||||
|
||||
final ArmorItem previousArmorItem = playerArmor.getItem(this.cosmeticsSlots.get(this.selectedCosmetic));
|
||||
|
||||
final ItemStack previous = this.applyPlaceholders(
|
||||
user,
|
||||
player,
|
||||
previousArmorItem,
|
||||
true
|
||||
);
|
||||
|
||||
if (previous != null && !previousArmorItem.isEmpty()) {
|
||||
final ItemStack previousItem = dev.triumphteam.gui.builder.item.ItemBuilder.from(
|
||||
previous
|
||||
).build();
|
||||
|
||||
this.gui.updateItem(this.selectedCosmetic, previousItem);
|
||||
} else {
|
||||
final GuiItem guiItem = this.guiItemMap.get(this.selectedCosmetic);
|
||||
final ItemStack itemStack = this.itemStackMap.get(this.selectedCosmetic);
|
||||
if (itemStack != null && guiItem != null) {
|
||||
final GuiItem setItem = this.getGuiItem(
|
||||
user,
|
||||
player,
|
||||
guiItem,
|
||||
itemStack
|
||||
);
|
||||
if (setItem != null) this.gui.updateItem(this.selectedCosmetic, setItem);
|
||||
}
|
||||
}
|
||||
|
||||
this.selectedCosmetic = slot;
|
||||
|
||||
this.updateSelected(user, player);
|
||||
}
|
||||
|
||||
private void updateSelected(final User user, final Player player) {
|
||||
final ArmorItem.Type type = this.cosmeticsSlots.get(this.selectedCosmetic);
|
||||
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
|
||||
if (armorItem.isEmpty()) return;
|
||||
|
||||
this.gui.updateItem(
|
||||
this.selectedCosmetic,
|
||||
ItemBuilder.from(
|
||||
this.applyPlaceholders(
|
||||
user, player, armorItem, true
|
||||
)
|
||||
).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(final User user, final Player player) {
|
||||
this.getGui(user, user.getLastSetItem().getType()).open(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
public DyeSelectorGui copy() {
|
||||
return new DyeSelectorGui(
|
||||
this.plugin,
|
||||
super.title,
|
||||
super.rows,
|
||||
new HashMap<>(super.guiItemMap),
|
||||
HashBiMap.create(this.cosmeticsSlots),
|
||||
this.selectedCosmetic
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package io.github.fisher2911.hmccosmetics.gui;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.util.Keys;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Token {
|
||||
|
||||
private final ItemStack itemStack;
|
||||
private final ArmorItem armorItem;
|
||||
private final List<String> commands;
|
||||
|
||||
public Token(final ItemStack itemStack, final ArmorItem armorItem, final List<String> commands) {
|
||||
this.itemStack = itemStack;
|
||||
this.armorItem = armorItem;
|
||||
this.commands = commands;
|
||||
Keys.setKey(this.itemStack, Keys.TOKEN_KEY, PersistentDataType.STRING, this.armorItem.getId());
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.armorItem.getId();
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public ArmorItem getArmorItem() {
|
||||
return armorItem;
|
||||
}
|
||||
|
||||
public List<String> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package io.github.fisher2911.hmccosmetics.gui;
|
||||
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
|
||||
import io.github.fisher2911.hmccosmetics.message.Messages;
|
||||
import io.github.fisher2911.hmccosmetics.message.Placeholder;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TokenGui extends CosmeticGui {
|
||||
|
||||
private final int tokenSlot;
|
||||
private final int cosmeticSlot;
|
||||
private final CosmeticManager cosmeticManager;
|
||||
|
||||
public TokenGui(final CosmeticGui gui, final int tokenSlot, final int cosmeticSlot) {
|
||||
this(gui.plugin, gui.title, gui.rows, gui.guiItemMap, tokenSlot, cosmeticSlot);
|
||||
}
|
||||
|
||||
public TokenGui(final HMCCosmetics plugin, final String title, final int rows, final Map<Integer, GuiItem> guiItemMap, final int tokenSlot, final int cosmeticSlot) {
|
||||
super(plugin, title, rows, guiItemMap);
|
||||
this.tokenSlot = tokenSlot;
|
||||
this.cosmeticSlot = cosmeticSlot;
|
||||
this.cosmeticManager = this.plugin.getCosmeticManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(final User user, final Player player) {
|
||||
super.open(user, player);
|
||||
this.gui.setDragAction(event -> event.setCancelled(true));
|
||||
this.gui.setDefaultClickAction(event -> {
|
||||
final int slot = event.getSlot();
|
||||
final Inventory inventory = event.getClickedInventory();
|
||||
if (inventory == null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
final ClickType clickType = event.getClick();
|
||||
if (clickType == ClickType.SHIFT_RIGHT || clickType == ClickType.SHIFT_LEFT) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (event.getClickedInventory().equals(event.getView().getBottomInventory())) return;
|
||||
ItemStack tokenItem = event.getInventory().getItem(this.tokenSlot);
|
||||
if (slot != tokenSlot && slot != this.cosmeticSlot) {
|
||||
event.setCancelled(true);
|
||||
if (tokenItem == null) {
|
||||
inventory.setItem(this.cosmeticSlot, new ItemStack(Material.AIR));
|
||||
}
|
||||
return;
|
||||
}
|
||||
final ItemStack inHand = event.getCursor();
|
||||
Token token;
|
||||
if (slot == this.tokenSlot) {
|
||||
if (inHand == null || inHand.getType() == Material.AIR) {
|
||||
if (tokenItem != null && tokenItem.getAmount() > 1 && clickType == ClickType.RIGHT) return;
|
||||
inventory.setItem(this.cosmeticSlot, new ItemStack(Material.AIR));
|
||||
return;
|
||||
}
|
||||
token = this.cosmeticManager.getToken(inHand);
|
||||
if (token == null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
final ArmorItem item = token.getArmorItem();
|
||||
inventory.setItem(this.cosmeticSlot,
|
||||
this.applyPlaceholders(
|
||||
user,
|
||||
player,
|
||||
item,
|
||||
true
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (inHand != null && inHand.getType() != Material.AIR) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
tokenItem = inventory.getItem(this.tokenSlot);
|
||||
token = this.cosmeticManager.getToken(tokenItem);
|
||||
if (tokenItem == null || token == null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
final ItemStack clicked = event.getCurrentItem();
|
||||
final ArmorItem armorItem = token.getArmorItem();
|
||||
if (clicked == null) return;
|
||||
if (user.hasPermissionToUse(armorItem)) {
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.ALREADY_UNLOCKED,
|
||||
Map.of(Placeholder.ID, armorItem.getName())
|
||||
);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
tokenItem.setAmount(tokenItem.getAmount() - 1);
|
||||
inventory.setItem(this.tokenSlot, tokenItem);
|
||||
clicked.setAmount(0);
|
||||
for (final String command : token.getCommands()) {
|
||||
Bukkit.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
command.replace(Placeholder.PLAYER, player.getName())
|
||||
);
|
||||
}
|
||||
this.messageHandler.sendMessage(
|
||||
player,
|
||||
Messages.TRADED_TOKEN,
|
||||
Map.of(Placeholder.ID, armorItem.getName())
|
||||
);
|
||||
});
|
||||
|
||||
this.gui.setCloseGuiAction(event -> {
|
||||
final Inventory inventory = event.getInventory();
|
||||
final ItemStack tokens = inventory.getItem(this.tokenSlot);
|
||||
if (tokens == null) return;
|
||||
event.getPlayer().getInventory().addItem(tokens);
|
||||
user.setOpenGui(null);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TokenGui copy() {
|
||||
return new TokenGui(
|
||||
this.plugin,
|
||||
super.title,
|
||||
super.rows,
|
||||
new HashMap<>(super.guiItemMap),
|
||||
this.tokenSlot,
|
||||
this.cosmeticSlot
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package io.github.fisher2911.hmccosmetics.gui;
|
||||
|
||||
import dev.triumphteam.gui.components.GuiAction;
|
||||
import dev.triumphteam.gui.guis.GuiItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class WrappedGuiItem extends GuiItem {
|
||||
|
||||
private GuiAction<InventoryClickEvent> action;
|
||||
|
||||
public WrappedGuiItem(final GuiItem item, final GuiAction<InventoryClickEvent> action) {
|
||||
super(item.getItemStack(), action);
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public WrappedGuiItem(final @NotNull ItemStack itemStack, @Nullable final GuiAction<@NotNull InventoryClickEvent> action) {
|
||||
super(itemStack, action);
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public WrappedGuiItem(final @NotNull ItemStack itemStack) {
|
||||
super(itemStack);
|
||||
this.action = null;
|
||||
}
|
||||
|
||||
public WrappedGuiItem(final @NotNull Material material) {
|
||||
super(material);
|
||||
this.action = null;
|
||||
}
|
||||
|
||||
public WrappedGuiItem(final @NotNull Material material, @Nullable final GuiAction<@NotNull InventoryClickEvent> action) {
|
||||
super(material, action);
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GuiAction<InventoryClickEvent> getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAction(final GuiAction<InventoryClickEvent> action) {
|
||||
super.setAction(action);
|
||||
this.action = action;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
|
||||
import io.github.fisher2911.hmccosmetics.config.Settings;
|
||||
import io.github.fisher2911.hmccosmetics.database.Database;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.task.InfiniteTask;
|
||||
import io.github.fisher2911.hmccosmetics.user.NPCUser;
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.event.*;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class CitizensHook implements Hook, Listener {
|
||||
|
||||
private static final String IDENTIFIER = "citizens";
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final Database database;
|
||||
|
||||
private final Map<Integer, NPCUser> npcs = new ConcurrentHashMap<>();
|
||||
|
||||
public CitizensHook(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.database = this.plugin.getDatabase();
|
||||
final Settings settings = this.plugin.getSettings();
|
||||
this.plugin.getTaskManager().submit(
|
||||
new InfiniteTask(() -> {
|
||||
for (final NPCUser user : this.npcs.values()) {
|
||||
if (!user.isValid()) {
|
||||
continue;
|
||||
}
|
||||
user.updateOutsideCosmetics(settings);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public List<Integer> getAllNPCS() {
|
||||
final Iterator<NPC> iterator = CitizensAPI.getNPCRegistry().sorted().iterator();
|
||||
final List<Integer> ids = new ArrayList<>();
|
||||
while (iterator.hasNext()) {
|
||||
ids.add(iterator.next().getId());
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
public int getCitizensId(final Entity entity) {
|
||||
final NPC npc = CitizensAPI.getNPCRegistry().getNPC(entity);
|
||||
if (npc == null) return -1;
|
||||
return npc.getId();
|
||||
}
|
||||
|
||||
public boolean setNpcCosmetic(final int id, final ArmorItem armorItem) {
|
||||
final NPC npc = CitizensAPI.getNPCRegistry().getById(id);
|
||||
if (npc == null) return false;
|
||||
final NPCUser user = this.npcs.get(npc.getId());
|
||||
final Entity entity = npc.getEntity();
|
||||
if (entity == null) return false;
|
||||
if (user == null) {
|
||||
Threads.getInstance().execute(() -> {
|
||||
this.database.loadNPCUser(
|
||||
npc.getId(),
|
||||
entity,
|
||||
npcUser ->
|
||||
Bukkit.getScheduler().runTask(
|
||||
this.plugin,
|
||||
() -> {
|
||||
this.npcs.put(npc.getId(), npcUser);
|
||||
this.setNpcCosmetic(npcUser, armorItem);
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return this.setNpcCosmetic(user, armorItem);
|
||||
}
|
||||
|
||||
public boolean setNpcCosmetic(final NPCUser user, final ArmorItem armorItem) {
|
||||
if (user == null) return false;
|
||||
final NPC npc = this.getNPC(user.getId());
|
||||
if (npc == null) return false;
|
||||
if (!(npc.getEntity() instanceof final LivingEntity entity)) return false;
|
||||
user.getPlayerArmor().setItem(armorItem);
|
||||
final ArmorItem.Type type = armorItem.getType();
|
||||
if (type != ArmorItem.Type.BACKPACK) {
|
||||
entity.getEquipment().setItem(
|
||||
type.getSlot(),
|
||||
armorItem.getItemStack(ArmorItem.Status.APPLIED)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public NPC getNPC(final UUID uuid) {
|
||||
return CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(uuid);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public NPC getNPC(final int id) {
|
||||
return CitizensAPI.getNPCRegistry().getById(id);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onNpcLoad(final PlayerCreateNPCEvent event) {
|
||||
this.loadNpc(event.getNPC());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onNpcLoad(final NPCSpawnEvent event) {
|
||||
this.loadNpc(event.getNPC());
|
||||
}
|
||||
|
||||
private void loadNpc(final NPC npc) {
|
||||
if (Bukkit.getPlayer(npc.getUniqueId()) != null) return;
|
||||
final Entity entity = npc.getEntity();
|
||||
if (entity == null) return;
|
||||
Bukkit.getScheduler().runTaskLater(this.plugin,
|
||||
() -> Threads.getInstance().execute(() -> this.database.loadNPCUser(
|
||||
npc.getId(),
|
||||
entity,
|
||||
user -> Bukkit.getScheduler().runTask(
|
||||
this.plugin,
|
||||
() -> {
|
||||
this.npcs.put(npc.getId(), user);
|
||||
for (final ArmorItem.Type type : ArmorItem.Type.values()) {
|
||||
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
|
||||
if (armorItem.isEmpty()) continue;
|
||||
this.setNpcCosmetic(npc.getId(), armorItem);
|
||||
}
|
||||
}
|
||||
)
|
||||
)),
|
||||
1);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onNpcUnload(final NPCDespawnEvent event) {
|
||||
this.unloadNpc(event.getNPC());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onNpcUnload(final NPCRemoveEvent event) {
|
||||
this.unloadNpc(event.getNPC());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onNpcUnload(final NPCDeathEvent event) {
|
||||
this.unloadNpc(event.getNPC());
|
||||
}
|
||||
|
||||
private void unloadNpc(final NPC npc) {
|
||||
final NPCUser user = this.npcs.remove(npc.getId());
|
||||
if (user == null) return;
|
||||
user.despawnAttached();
|
||||
Threads.getInstance().execute(() -> this.database.saveNPCUser(user));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook;
|
||||
|
||||
public interface Hook {
|
||||
|
||||
String getId();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.hook.item.ItemHook;
|
||||
import io.github.fisher2911.hmccosmetics.hook.item.ItemHooks;
|
||||
import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook;
|
||||
import io.github.fisher2911.hmccosmetics.hook.item.OraxenHook;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class HookManager {
|
||||
|
||||
private static final HookManager INSTANCE;
|
||||
|
||||
static {
|
||||
INSTANCE = new HookManager(HMCCosmetics.getPlugin(HMCCosmetics.class));
|
||||
}
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final ItemHooks itemHooks;
|
||||
private final PAPIHook papiHook;
|
||||
private final CitizensHook citizensHook;
|
||||
private final ModelEngineHook modelEngineHook;
|
||||
private final Set<Class<? extends Hook>> registeredHooks;
|
||||
private final Set<Listener> listeners;
|
||||
|
||||
private HookManager(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.registeredHooks = new HashSet<>();
|
||||
this.listeners = new HashSet<>();
|
||||
final PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
if (pluginManager.getPlugin("PlaceholderApi") != null) {
|
||||
this.registeredHooks.add(PAPIHook.class);
|
||||
this.papiHook = new PAPIHook();
|
||||
} else {
|
||||
this.papiHook = null;
|
||||
}
|
||||
|
||||
final Map<String, ItemHook> itemHookMap = new HashMap<>();
|
||||
final OraxenHook oraxenHook = new OraxenHook();
|
||||
final ItemsAdderHook itemsAdderHook = new ItemsAdderHook();
|
||||
final CitizensHook citizensHook = new CitizensHook(this.plugin);
|
||||
if (pluginManager.getPlugin("Oraxen") != null) {
|
||||
itemHookMap.put(oraxenHook.getIdentifier(), oraxenHook);
|
||||
}
|
||||
if (pluginManager.getPlugin("ItemsAdder") != null) {
|
||||
itemHookMap.put(itemsAdderHook.getIdentifier(), itemsAdderHook);
|
||||
this.listeners.add(itemsAdderHook);
|
||||
}
|
||||
if (pluginManager.getPlugin("Citizens") != null) {
|
||||
this.citizensHook = null;
|
||||
/*
|
||||
this.registerHook(citizensHook.getClass());
|
||||
this.listeners.add(citizensHook);
|
||||
this.citizensHook = citizensHook;
|
||||
this.plugin.getLogger().info("Successfully Hooked into Citizens!");
|
||||
*/
|
||||
} else {
|
||||
this.citizensHook = null;
|
||||
}
|
||||
if (pluginManager.getPlugin("ModelEngine") != null) {
|
||||
this.plugin.getLogger().info("ModelEngine has been detected and has been enabled.");
|
||||
// 3.0 Model Engine Beta
|
||||
final ModelEngineHook modelEngineHook = new ModelEngineHook();
|
||||
this.registerHook(modelEngineHook.getClass());
|
||||
this.modelEngineHook = modelEngineHook;
|
||||
} else {
|
||||
this.modelEngineHook = null;
|
||||
}
|
||||
|
||||
this.itemHooks = new ItemHooks(itemHookMap);
|
||||
itemHookMap.values().forEach(hook -> this.registerHook(hook.getClass()));
|
||||
}
|
||||
|
||||
public static HookManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
protected void registerHook(final Class<? extends Hook> hook) {
|
||||
this.registeredHooks.add(hook);
|
||||
}
|
||||
|
||||
public boolean isEnabled(final Class<? extends Hook> hook) {
|
||||
return this.registeredHooks.contains(hook);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (this.isEnabled(PAPIHook.class)) {
|
||||
new PAPIExpansion(this.plugin).register();
|
||||
}
|
||||
this.registerListeners(this.plugin);
|
||||
}
|
||||
|
||||
public void registerListeners(final HMCCosmetics plugin) {
|
||||
for (final Listener listener : this.listeners) {
|
||||
plugin.getServer().getPluginManager().registerEvents(listener, plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PAPIHook getPapiHook() {
|
||||
return papiHook;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CitizensHook getCitizensHook() {
|
||||
return this.citizensHook;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ModelEngineHook getModelEngineHook() {
|
||||
return modelEngineHook;
|
||||
}
|
||||
|
||||
public ItemHooks getItemHooks() {
|
||||
return itemHooks;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook;
|
||||
|
||||
public class ModelEngineHook implements Hook {
|
||||
|
||||
public ModelEngineHook() {
|
||||
}
|
||||
|
||||
private static final String ID = "model-engine";
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.message.Translation;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PAPIExpansion extends PlaceholderExpansion {
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final UserManager userManager;
|
||||
private static final String IDENTIFIER = "hmccosmetics";
|
||||
private static final String AUTHOR = "MasterOfTheFish";
|
||||
|
||||
public PAPIExpansion(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.userManager = this.plugin.getUserManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return AUTHOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return this.plugin.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String onPlaceholderRequest(final Player player, @NotNull final String params) {
|
||||
final String[] parts = params.split("_");
|
||||
if (parts.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
|
||||
if (optionalUser.isEmpty()) return null;
|
||||
final User user = optionalUser.get();
|
||||
|
||||
// %hmccosmetics_using_id%
|
||||
if (parts[0].equalsIgnoreCase("using")) {
|
||||
if (parts.length < 2) return null;
|
||||
final String id = this.getId(parts, 1);
|
||||
for (final ArmorItem item : user.getPlayerArmor().getArmorItems()) {
|
||||
if (item.getId().equals(id)) return Translation.translate(Translation.TRUE);
|
||||
}
|
||||
return Translation.translate(Translation.FALSE);
|
||||
}
|
||||
|
||||
// %hmccosmetics_current_type%
|
||||
if (parts[0].startsWith("current")) {
|
||||
final boolean formatted = parts[0].contains("formatted");
|
||||
if (parts.length >= 2) {
|
||||
final String typeStr = getId(parts, 1);
|
||||
try {
|
||||
final ArmorItem.Type type = ArmorItem.Type.valueOf(typeStr.toUpperCase());
|
||||
for (final ArmorItem item : user.getPlayerArmor().getArmorItems()) {
|
||||
if (item.getType().equals(type)) {
|
||||
if (formatted) {
|
||||
final String name = item.getName();
|
||||
if (name.isBlank()) return item.getId().replace("_", "");
|
||||
return name;
|
||||
}
|
||||
return item.getId();
|
||||
}
|
||||
}
|
||||
return Translation.translate(Translation.NONE);
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parts[0].equals("wardrobe-enabled")) {
|
||||
return Translation.translate(String.valueOf(user.getWardrobe().isActive()));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getId(final String[] parts, final int fromIndex) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (int i = fromIndex; i < parts.length; i++) {
|
||||
builder.append(parts[i]);
|
||||
if (i < parts.length - 1) builder.append("_");
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook;
|
||||
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PAPIHook implements Hook {
|
||||
|
||||
private static final String ID = "PAPI";
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public String parse(final Player player, final String string) {
|
||||
return PlaceholderAPI.setPlaceholders(player, string);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook.entity;
|
||||
|
||||
import com.ticxo.modelengine.api.ModelEngineAPI;
|
||||
import com.ticxo.modelengine.api.model.ActiveModel;
|
||||
import com.ticxo.modelengine.api.model.ModeledEntity;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BalloonEntity {
|
||||
|
||||
private final int balloonID;
|
||||
private final MEGEntity megEntity;
|
||||
|
||||
public BalloonEntity(int balloonID, Location location) {
|
||||
this.balloonID = balloonID;
|
||||
this.megEntity = new MEGEntity(UUID.randomUUID(), balloonID, new Vector(0, 0, 0), location, false);
|
||||
}
|
||||
|
||||
public void updateModel() {
|
||||
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
|
||||
|
||||
if (model == null) return;
|
||||
|
||||
if (model.getBase() instanceof final MEGEntity e) e.update(this);
|
||||
}
|
||||
|
||||
public void spawnModel(final String id) {
|
||||
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Attempting Spawning");
|
||||
if (ModelEngineAPI.api.getModelRegistry().getBlueprint(id) == null) {
|
||||
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().warning("Invalid Model Engine Blueprint " + id);
|
||||
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().warning("Possible Blueprints" + ModelEngineAPI.api.getModelRegistry().getAllBlueprintId());
|
||||
return;
|
||||
}
|
||||
final ActiveModel model = ModelEngineAPI.api.createActiveModelImpl(ModelEngineAPI.getBlueprint(id));
|
||||
ModeledEntity modeledEntity = ModelEngineAPI.api.createModeledEntityImpl(megEntity);
|
||||
modeledEntity.addModel(model, false);
|
||||
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Spawned Model");
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
final ModeledEntity entity = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
|
||||
|
||||
if (entity == null) return;
|
||||
|
||||
for (final Player player : entity.getRangeManager().getPlayerInRange()) {
|
||||
entity.hideFromPlayer(player);
|
||||
}
|
||||
|
||||
//ModelEngineAPI.removeModeledEntity(megEntity.getUniqueId());
|
||||
entity.destroy();
|
||||
}
|
||||
|
||||
public void addPlayerToModel(final Player player, final String id) {
|
||||
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
|
||||
if (model == null) {
|
||||
this.spawnModel(id);
|
||||
return;
|
||||
}
|
||||
if (megEntity.getRangeManager().getPlayerInRange().contains(player)) return;
|
||||
model.showToPlayer(player);
|
||||
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Added " + player.getName() + " to " + id);
|
||||
}
|
||||
|
||||
public void removePlayerFromModel(final Player player) {
|
||||
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
|
||||
|
||||
if (model == null) return;
|
||||
|
||||
model.hideFromPlayer(player);
|
||||
}
|
||||
|
||||
|
||||
public int getBalloonID() {
|
||||
return balloonID;
|
||||
}
|
||||
|
||||
public UUID getUniqueID() {
|
||||
return megEntity.getUniqueId();
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return this.megEntity.getLocation();
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return this.megEntity.isAlive();
|
||||
}
|
||||
|
||||
public void setLocation(Location location) {
|
||||
this.megEntity.setLocation(location);
|
||||
}
|
||||
|
||||
public void setVelocity(Vector vector) {
|
||||
this.megEntity.setVelocity(vector);
|
||||
}
|
||||
|
||||
public void setAlive(boolean alive) {
|
||||
this.megEntity.setAlive(alive);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook.entity;
|
||||
|
||||
import com.ticxo.modelengine.api.entity.BaseEntity;
|
||||
import com.ticxo.modelengine.api.generator.Hitbox;
|
||||
import com.ticxo.modelengine.api.model.IModel;
|
||||
import com.ticxo.modelengine.api.nms.entity.impl.DefaultBodyRotationController;
|
||||
import com.ticxo.modelengine.api.nms.entity.impl.EmptyRangeManager;
|
||||
import com.ticxo.modelengine.api.nms.entity.impl.ManualRangeManager;
|
||||
import com.ticxo.modelengine.api.nms.entity.wrapper.BodyRotationController;
|
||||
import com.ticxo.modelengine.api.nms.entity.wrapper.LookController;
|
||||
import com.ticxo.modelengine.api.nms.entity.wrapper.MoveController;
|
||||
import com.ticxo.modelengine.api.nms.entity.wrapper.RangeManager;
|
||||
import com.ticxo.modelengine.api.nms.world.IDamageSource;
|
||||
import com.ticxo.modelengine.api.utils.data.EntityData;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MEGEntity implements BaseEntity {
|
||||
|
||||
private final UUID uuid;
|
||||
private final int entityId;
|
||||
private Vector velocity = new Vector(0, 0, 0);
|
||||
private Location location;
|
||||
private boolean alive;
|
||||
private BodyRotationController rotationController;
|
||||
private List<Entity> passengers;
|
||||
private RangeManager rangeManager;
|
||||
|
||||
protected MEGEntity(final UUID uuid, final int entityId, final Vector velocity, final Location location, final boolean alive) {
|
||||
this.uuid = uuid;
|
||||
this.entityId = entityId;
|
||||
this.velocity = velocity;
|
||||
this.location = location;
|
||||
this.alive = alive;
|
||||
this.rotationController = new DefaultBodyRotationController(this);
|
||||
this.passengers = new ArrayList<>();
|
||||
this.rangeManager = new EmptyRangeManager();
|
||||
this.rangeManager.setRenderDistance(16);
|
||||
}
|
||||
|
||||
protected MEGEntity(final UUID uuid, final int entityId) {
|
||||
this.uuid = uuid;
|
||||
this.entityId = entityId;
|
||||
this.alive = false;
|
||||
}
|
||||
|
||||
public void update(final BalloonEntity entity) {
|
||||
this.velocity = entity.getLocation().toVector();
|
||||
this.location = entity.getLocation();
|
||||
this.alive = entity.isAlive();
|
||||
}
|
||||
|
||||
public void setVelocity(final Vector velocity) {
|
||||
this.velocity = velocity;
|
||||
}
|
||||
|
||||
public void setLocation(final Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public void setAlive(final boolean alive) {
|
||||
this.alive = alive;
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return alive;
|
||||
}
|
||||
|
||||
public EntityData getEntityData() {
|
||||
return entityData;
|
||||
}
|
||||
|
||||
final EntityData entityData = new EntityData();
|
||||
|
||||
@Override
|
||||
public Object getOriginal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveController wrapMoveControl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookController wrapLookControl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyRotationController wrapBodyRotationControl() {
|
||||
return this.rotationController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapNavigation() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public RangeManager wrapRangeManager(IModel model) {
|
||||
return new ManualRangeManager(this, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RangeManager getRangeManager() {
|
||||
if (this.rangeManager == null) {
|
||||
RangeManager rangeMan = new EmptyRangeManager();
|
||||
rangeMan.setRenderDistance(16);
|
||||
return rangeMan;
|
||||
}
|
||||
return this.rangeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHurt(IDamageSource damageSource, float damage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteract(Player player, EquipmentSlot hand) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHitbox(Hitbox hitbox) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hitbox getHitbox() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStepHeight(double height) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getStepHeight() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCollidableToLiving(LivingEntity living, boolean isRemove) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastSpawnPacket() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastDespawnPacket() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityId() {
|
||||
return this.entityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return this.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return this.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return alive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGlowing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnGround() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMoving() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setYHeadRot(float rot) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getYHeadRot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getXHeadRot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setYBodyRot(float rot) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getYBodyRot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Entity> getPassengers() {
|
||||
return this.passengers;
|
||||
}
|
||||
|
||||
public Vector getVelocity() {
|
||||
return velocity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook.item;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.hook.Hook;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public interface ItemHook extends Hook {
|
||||
|
||||
String getIdentifier();
|
||||
|
||||
ItemStack getItem(final String id);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook.item;
|
||||
|
||||
import java.util.Map;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ItemHooks {
|
||||
|
||||
private final Map<String, ItemHook> itemHookMap;
|
||||
|
||||
public ItemHooks(final Map<String, ItemHook> itemHookMap) {
|
||||
this.itemHookMap = itemHookMap;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ItemStack getItemStack(final String item) {
|
||||
final String[] parts = item.split(":");
|
||||
|
||||
if (parts.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String identifier = parts[0];
|
||||
final StringBuilder itemId = new StringBuilder();
|
||||
|
||||
for (int i = 1; i < parts.length; i++) {
|
||||
itemId.append(parts[i]);
|
||||
if (i < parts.length - 1) {
|
||||
itemId.append(":");
|
||||
}
|
||||
}
|
||||
|
||||
final ItemHook hook = this.itemHookMap.get(identifier);
|
||||
|
||||
if (hook == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return hook.getItem(itemId.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook.item;
|
||||
|
||||
import dev.lone.itemsadder.api.CustomStack;
|
||||
import dev.lone.itemsadder.api.Events.ItemsAdderLoadDataEvent;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ItemsAdderHook implements ItemHook, Listener {
|
||||
|
||||
public static final String ID = "ITEM_ADDER";
|
||||
private static final String IDENTIFIER = "itemsadder";
|
||||
|
||||
@EventHandler
|
||||
public void onItemsAdderLoad(final ItemsAdderLoadDataEvent event) {
|
||||
final HMCCosmetics plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, plugin::load);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(final String id) {
|
||||
final CustomStack stack = CustomStack.getInstance(id);
|
||||
if (stack == null) {
|
||||
return null;
|
||||
}
|
||||
return stack.getItemStack().clone();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package io.github.fisher2911.hmccosmetics.hook.item;
|
||||
|
||||
import io.th0rgal.oraxen.items.ItemBuilder;
|
||||
import io.th0rgal.oraxen.items.OraxenItems;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class OraxenHook implements ItemHook {
|
||||
|
||||
public static final String ID = "ORAXEN";
|
||||
private static final String IDENTIFIER = "oraxen";
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(final String id) {
|
||||
final ItemBuilder itemBuilder = OraxenItems.getItemById(id);
|
||||
if (itemBuilder == null) {
|
||||
return null;
|
||||
}
|
||||
return itemBuilder.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package io.github.fisher2911.hmccosmetics.inventory;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PlayerArmor {
|
||||
|
||||
private final Map<ArmorItem.Type, ArmorItem> armorItems;
|
||||
|
||||
public PlayerArmor(ArmorItem hat, final ArmorItem backpack, final ArmorItem offHand) {
|
||||
this.armorItems = new EnumMap<>(ArmorItem.Type.class);
|
||||
this.armorItems.put(hat.getType(), hat);
|
||||
this.armorItems.put(backpack.getType(), hat);
|
||||
this.armorItems.put(offHand.getType(), offHand);
|
||||
}
|
||||
|
||||
public PlayerArmor(final Map<ArmorItem.Type, ArmorItem> armorItems) {
|
||||
this.armorItems = armorItems;
|
||||
}
|
||||
|
||||
public static PlayerArmor empty() {
|
||||
return new PlayerArmor(
|
||||
ArmorItem.empty(ArmorItem.Type.HAT),
|
||||
ArmorItem.empty(ArmorItem.Type.BACKPACK),
|
||||
ArmorItem.empty(ArmorItem.Type.OFF_HAND)
|
||||
);
|
||||
}
|
||||
|
||||
public ArmorItem getHat() {
|
||||
return this.getItem(ArmorItem.Type.HAT);
|
||||
}
|
||||
|
||||
// public ArmorItem getBackpack() {
|
||||
// return this.getItem(ArmorItem.Type.BACKPACK);
|
||||
// }
|
||||
|
||||
public ArmorItem getOffHand() {
|
||||
return this.getItem(ArmorItem.Type.OFF_HAND);
|
||||
}
|
||||
|
||||
public ArmorItem getItem(final ArmorItem.Type type) {
|
||||
ArmorItem armorItem = this.armorItems.get(type);
|
||||
if (armorItem == null) {
|
||||
armorItem = ArmorItem.empty(type);
|
||||
this.armorItems.put(type, armorItem);
|
||||
}
|
||||
return armorItem;
|
||||
}
|
||||
|
||||
public ArmorItem setItem(final ArmorItem armorItem) {
|
||||
if (armorItem.isEmpty() && armorItem.getType() == ArmorItem.Type.BACKPACK) {
|
||||
this.armorItems.put(ArmorItem.Type.SELF_BACKPACK, armorItem);
|
||||
}
|
||||
return this.armorItems.put(armorItem.getType(), armorItem);
|
||||
}
|
||||
|
||||
public Collection<ArmorItem> getArmorItems() {
|
||||
return this.armorItems.values();
|
||||
}
|
||||
|
||||
public PlayerArmor copy() {
|
||||
return new PlayerArmor(new HashMap<>(this.armorItems));
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for (final ArmorItem.Type type : ArmorItem.Type.values()) {
|
||||
this.setItem(ArmorItem.empty(type));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package io.github.fisher2911.hmccosmetics.listener;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.user.Equipment;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ClickListener implements Listener {
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final UserManager userManager;
|
||||
|
||||
final Map<EquipmentSlot, Set<Material>> ARMOR_ITEMS = Map.of(
|
||||
EquipmentSlot.HEAD, EnumSet.of(
|
||||
Material.LEATHER_HELMET,
|
||||
Material.CHAINMAIL_HELMET,
|
||||
Material.IRON_HELMET,
|
||||
Material.GOLDEN_HELMET,
|
||||
Material.DIAMOND_HELMET,
|
||||
Material.NETHERITE_HELMET,
|
||||
Material.TURTLE_HELMET
|
||||
),
|
||||
EquipmentSlot.CHEST, EnumSet.of(
|
||||
Material.LEATHER_CHESTPLATE,
|
||||
Material.CHAINMAIL_CHESTPLATE,
|
||||
Material.IRON_CHESTPLATE,
|
||||
Material.GOLDEN_CHESTPLATE,
|
||||
Material.DIAMOND_CHESTPLATE,
|
||||
Material.NETHERITE_CHESTPLATE,
|
||||
Material.ELYTRA
|
||||
),
|
||||
EquipmentSlot.LEGS, EnumSet.of(
|
||||
Material.LEATHER_LEGGINGS,
|
||||
Material.CHAINMAIL_LEGGINGS,
|
||||
Material.IRON_LEGGINGS,
|
||||
Material.GOLDEN_LEGGINGS,
|
||||
Material.DIAMOND_LEGGINGS,
|
||||
Material.NETHERITE_LEGGINGS
|
||||
),
|
||||
EquipmentSlot.FEET, EnumSet.of(
|
||||
Material.LEATHER_BOOTS,
|
||||
Material.CHAINMAIL_BOOTS,
|
||||
Material.IRON_BOOTS,
|
||||
Material.GOLDEN_BOOTS,
|
||||
Material.DIAMOND_BOOTS,
|
||||
Material.NETHERITE_BOOTS
|
||||
)
|
||||
);
|
||||
|
||||
public ClickListener(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.userManager = this.plugin.getUserManager();
|
||||
}
|
||||
/*
|
||||
|
||||
@EventHandler
|
||||
public void onArmorSlotClick(final InventoryClickEvent event) {
|
||||
final int slot = event.getSlot();
|
||||
if (!(event.getWhoClicked() instanceof Player)) return;
|
||||
if (slot >= 36 && slot <= 40) {
|
||||
this.fixInventory(((Player) event.getWhoClicked()).getPlayer());
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onBlockClick(final PlayerInteractEvent event) {
|
||||
// if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||
// final Player player = event.getPlayer();
|
||||
// final Block block = event.getClickedBlock();
|
||||
// if (block != null && block.getType().isInteractable() && !player.isSneaking()) return;
|
||||
// final ItemStack clickedWith = event.getItem();
|
||||
// if (clickedWith == null) return;
|
||||
// this.checkFix(player, -1, clickedWith);
|
||||
// }
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onShiftClick(final InventoryClickEvent event) {
|
||||
// if (event.getClick() != ClickType.SHIFT_LEFT &&
|
||||
// event.getClick() != ClickType.SHIFT_RIGHT) return;
|
||||
// if (!(event.getWhoClicked() instanceof final Player player)) return;
|
||||
// final ItemStack clicked = event.getCurrentItem();
|
||||
// if (clicked == null) return;
|
||||
// this.checkFix(player, -1, clicked);
|
||||
// }
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onCosmeticClick(final InventoryDragEvent event) {
|
||||
// final HumanEntity player = event.getWhoClicked();
|
||||
// if (!(player instanceof Player)) {
|
||||
// return;
|
||||
// }
|
||||
//// this.fixInventory((Player) player);
|
||||
// }
|
||||
//
|
||||
// @EventHandler
|
||||
// public void onInventoryClose(final InventoryCloseEvent event) {
|
||||
// final HumanEntity player = event.getPlayer();
|
||||
// this.userManager.get(player.getUniqueId()).ifPresent(this::doRunnable);
|
||||
// }
|
||||
//
|
||||
/*
|
||||
private void fixInventory(final Player player) {
|
||||
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
|
||||
if (optionalUser.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.doRunnable(optionalUser.get());
|
||||
}
|
||||
|
||||
private void doRunnable(final User user) {
|
||||
Equipment equip = this.userManager.getItemList(user, user.getEquipment(), Collections.emptySet());
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(
|
||||
this.plugin, () -> this.userManager.sendUpdatePacket(user, equip),
|
||||
1);
|
||||
}
|
||||
*/
|
||||
|
||||
// private void checkFix(final Player player, final int clickedSlot, final ItemStack itemStack) {
|
||||
// final EquipmentSlot slot = this.getArmorSlot(itemStack.getType());
|
||||
// if (slot == null) return;
|
||||
// final ItemStack wearing = player.getEquipment().getItem(slot);
|
||||
// if (wearing == null) return;
|
||||
// if (wearing.getType() == Material.AIR || (clickedSlot >= 39 && clickedSlot <= 40)) {
|
||||
// this.fixInventory(player);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Nullable
|
||||
// private EquipmentSlot getArmorSlot(final Material material) {
|
||||
// for (final EquipmentSlot slot : EquipmentSlot.values()) {
|
||||
// final Set<Material> armorItems = ARMOR_ITEMS.get(slot);
|
||||
// if (armorItems == null) continue;
|
||||
// if (material == null) continue;
|
||||
// if (armorItems.contains(material)) return slot;
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
package io.github.fisher2911.hmccosmetics.listener;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
|
||||
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
|
||||
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
|
||||
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
|
||||
import io.github.fisher2911.hmccosmetics.packet.wrappers.WrapperPlayClientWindowClick;
|
||||
import io.github.fisher2911.hmccosmetics.packet.wrappers.WrapperPlayServerWindowItems;
|
||||
import io.github.fisher2911.hmccosmetics.task.DelayedTask;
|
||||
import io.github.fisher2911.hmccosmetics.task.TaskManager;
|
||||
import io.github.fisher2911.hmccosmetics.user.Equipment;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import io.github.fisher2911.hmccosmetics.util.Utils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class CosmeticFixListener implements Listener {
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final UserManager userManager;
|
||||
private final CosmeticSettings settings;
|
||||
private final TaskManager taskManager;
|
||||
|
||||
public CosmeticFixListener(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.userManager = this.plugin.getUserManager();
|
||||
this.settings = this.plugin.getSettings().getCosmeticSettings();
|
||||
this.taskManager = this.plugin.getTaskManager();
|
||||
this.registerPacketListeners();
|
||||
}
|
||||
|
||||
final Map<EquipmentSlot, Set<Material>> ARMOR_ITEMS = Map.of(
|
||||
EquipmentSlot.HEAD, EnumSet.of(
|
||||
Material.LEATHER_HELMET,
|
||||
Material.CHAINMAIL_HELMET,
|
||||
Material.IRON_HELMET,
|
||||
Material.GOLDEN_HELMET,
|
||||
Material.DIAMOND_HELMET,
|
||||
Material.NETHERITE_HELMET,
|
||||
Material.TURTLE_HELMET
|
||||
),
|
||||
EquipmentSlot.CHEST, EnumSet.of(
|
||||
Material.LEATHER_CHESTPLATE,
|
||||
Material.CHAINMAIL_CHESTPLATE,
|
||||
Material.IRON_CHESTPLATE,
|
||||
Material.GOLDEN_CHESTPLATE,
|
||||
Material.DIAMOND_CHESTPLATE,
|
||||
Material.NETHERITE_CHESTPLATE,
|
||||
Material.ELYTRA
|
||||
),
|
||||
EquipmentSlot.LEGS, EnumSet.of(
|
||||
Material.LEATHER_LEGGINGS,
|
||||
Material.CHAINMAIL_LEGGINGS,
|
||||
Material.IRON_LEGGINGS,
|
||||
Material.GOLDEN_LEGGINGS,
|
||||
Material.DIAMOND_LEGGINGS,
|
||||
Material.NETHERITE_LEGGINGS
|
||||
),
|
||||
EquipmentSlot.FEET, EnumSet.of(
|
||||
Material.LEATHER_BOOTS,
|
||||
Material.CHAINMAIL_BOOTS,
|
||||
Material.IRON_BOOTS,
|
||||
Material.GOLDEN_BOOTS,
|
||||
Material.DIAMOND_BOOTS,
|
||||
Material.NETHERITE_BOOTS
|
||||
)
|
||||
);
|
||||
|
||||
public void registerPacketListeners() {
|
||||
this.registerMenuChangeListener();
|
||||
this.registerInventoryClickListener();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onHoldItem(final PlayerItemHeldEvent event) {
|
||||
this.userManager.get(event.getPlayer().getUniqueId()).ifPresent(user -> {
|
||||
if (user.isWardrobeActive()) event.setCancelled(true);
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onShiftClick(final InventoryClickEvent event) {
|
||||
if (event.getClick() != ClickType.SHIFT_LEFT && event.getClick() != ClickType.SHIFT_RIGHT) return;
|
||||
if (!(event.getWhoClicked() instanceof final Player player)) return;
|
||||
final ItemStack clicked = event.getCurrentItem();
|
||||
if (clicked == null) return;
|
||||
final EquipmentSlot slot = this.getArmorSlot(clicked.getType());
|
||||
if (slot == null) return;
|
||||
final Optional<User> user = this.userManager.get(player.getUniqueId());
|
||||
if (user.isEmpty()) return;
|
||||
final ArmorItem.Type type = ArmorItem.Type.fromWrapper(slot);
|
||||
if (type == null) return;
|
||||
|
||||
this.taskManager.submit(() -> {
|
||||
|
||||
final EntityEquipment equipment = player.getEquipment();
|
||||
final ItemStack current;
|
||||
if (equipment == null) {
|
||||
current = new ItemStack(Material.AIR);
|
||||
} else {
|
||||
current = equipment.getItem(slot);
|
||||
}
|
||||
updateOnClick(
|
||||
player,
|
||||
slot,
|
||||
user.get(),
|
||||
type,
|
||||
current
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private void registerInventoryClickListener() {
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmetics.getPlugin(HMCCosmetics.class), ListenerPriority.NORMAL, PacketType.Play.Client.WINDOW_CLICK) {
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
int invTypeClicked = event.getPacket().getIntegers().read(0);
|
||||
int slotClicked = event.getPacket().getIntegers().read(2);
|
||||
|
||||
// Must be a player inventory.
|
||||
if (invTypeClicked != 0) return;
|
||||
// -999 is when a player clicks outside their inventory. https://wiki.vg/Inventory#Player_Inventory
|
||||
if (slotClicked == -999) return;
|
||||
if (!(event.getPlayer() instanceof Player)) return;
|
||||
taskManager.submit(() -> {
|
||||
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
|
||||
if (optionalUser.isEmpty()) return;
|
||||
final User user = optionalUser.get();
|
||||
EquipmentSlot slot = getPacketArmorSlot(slotClicked);
|
||||
if (slot == null) {
|
||||
return;
|
||||
}
|
||||
final EntityEquipment entityEquipment = player.getEquipment();
|
||||
if (entityEquipment == null) return;
|
||||
final ItemStack current = Utils.replaceIfNull(entityEquipment.getItem(slot), new ItemStack(Material.AIR));
|
||||
final ArmorItem.Type type = ArmorItem.Type.fromEquipmentSlot(slot);
|
||||
if (type == null) return;
|
||||
updateOnClick(
|
||||
player,
|
||||
slot,
|
||||
user,
|
||||
type,
|
||||
current
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateOnClick(final Player player, final EquipmentSlot slot, final User user, final ArmorItem.Type type, final ItemStack current) {
|
||||
//plugin.getLogger().log(Level.INFO, "updateOnClick (171)");
|
||||
|
||||
final Location location = player.getLocation();
|
||||
final Equipment equipment = new Equipment();
|
||||
final ItemStack cosmetic = userManager.getCosmeticItem(
|
||||
user.getPlayerArmor().getItem(type),
|
||||
current,
|
||||
ArmorItem.Status.APPLIED,
|
||||
slot
|
||||
);
|
||||
//plugin.getLogger().log(Level.INFO, "Set cosmetic in " + slot + " to " + cosmetic);
|
||||
if (cosmetic != null && cosmetic.getType() != Material.AIR) equipment.setItem(slot, cosmetic);
|
||||
//plugin.getLogger().log(Level.INFO, "Set cosmetic in " + slot + " to " + cosmetic + "(done)");
|
||||
|
||||
/*
|
||||
final Equipment items = userManager.getItemList(user, equipment, Collections.emptySet());
|
||||
for (EquipmentSlot e : items.keys()) {
|
||||
//final EquipmentSlot s = e.getSlot();
|
||||
final ArmorItem.Type t = ArmorItem.Type.fromWrapper(e);
|
||||
ItemStack air = new ItemStack(Material.AIR);
|
||||
if (t == null) {
|
||||
//plugin.getLogger().log(Level.INFO, "T is null");
|
||||
equipment.setItem(e, air);
|
||||
return;
|
||||
}
|
||||
final ArmorItem armorItem = user.getPlayerArmor().getItem(t);
|
||||
final ItemStack i = equipment.getItem(e);
|
||||
if (i == null) {
|
||||
//plugin.getLogger().log(Level.INFO, "I is null");
|
||||
equipment.setItem(e, air);
|
||||
return;
|
||||
}
|
||||
Boolean remove = armorItem.isEmpty() && i.equals(equipment.getItem(t.getSlot()));
|
||||
if (remove) {
|
||||
//plugin.getLogger().log(Level.INFO, "Boolean is true");
|
||||
equipment.setItem(e, air);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
*/
|
||||
for (final Player other : Bukkit.getOnlinePlayers()) {
|
||||
if (!settings.isInViewDistance(location, other.getLocation())) continue;
|
||||
userManager.sendUpdatePacket(
|
||||
user,
|
||||
equipment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerMenuChangeListener() {
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmetics.getPlugin(HMCCosmetics.class), ListenerPriority.NORMAL, PacketType.Play.Server.WINDOW_ITEMS) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (event.getPlayer() == null) return;
|
||||
WrapperPlayServerWindowItems wrapper = new WrapperPlayServerWindowItems(event.getPacket());
|
||||
if (!(event.getPlayer() instanceof Player)) return;
|
||||
final int windowId = wrapper.getWindowId();
|
||||
|
||||
List<ItemStack> items = wrapper.getSlotData();
|
||||
taskManager.submit(() -> {
|
||||
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
|
||||
if (optionalUser.isEmpty()) return;
|
||||
final User user = optionalUser.get();
|
||||
if (windowId != 0) return;
|
||||
final int size = items.size();
|
||||
final PlayerArmor playerArmor = user.getPlayerArmor();
|
||||
final Equipment equip = userManager.getItemList(user);
|
||||
for (final ArmorItem armorItem : playerArmor.getArmorItems()) {
|
||||
final ArmorItem.Type type = armorItem.getType();
|
||||
final EquipmentSlot slot = type.getSlot();
|
||||
if (slot == null) continue;
|
||||
final int packetSlot = getPacketArmorSlot(slot);
|
||||
if (packetSlot == -1) continue;
|
||||
if (packetSlot >= size) continue;
|
||||
|
||||
final ItemStack current = (items.get(packetSlot));
|
||||
final ItemStack setTo =
|
||||
(userManager.getCosmeticItem(
|
||||
armorItem,
|
||||
current,
|
||||
ArmorItem.Status.APPLIED,
|
||||
slot
|
||||
));
|
||||
if ((current).equals(setTo)) continue;
|
||||
equip.setItem(slot, setTo);
|
||||
}
|
||||
userManager.sendUpdatePacket(
|
||||
user,
|
||||
equip
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private int getPacketArmorSlot(final EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
case HEAD -> 5;
|
||||
case CHEST -> 6;
|
||||
case LEGS -> 7;
|
||||
case FEET -> 8;
|
||||
case OFF_HAND -> 45;
|
||||
default -> -1;
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public EquipmentSlot getPacketArmorSlot(final int slot) {
|
||||
return switch (slot) {
|
||||
case 5 -> EquipmentSlot.HEAD;
|
||||
case 6 -> EquipmentSlot.CHEST;
|
||||
case 7 -> EquipmentSlot.LEGS;
|
||||
case 8 -> EquipmentSlot.FEET;
|
||||
case 45 -> EquipmentSlot.OFF_HAND;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onOffhandSwap(final PlayerSwapHandItemsEvent event) {
|
||||
final ItemStack offHand = event.getOffHandItem();
|
||||
if (offHand != null && offHand.getType() != Material.AIR) {
|
||||
return;
|
||||
}
|
||||
final Player player = event.getPlayer();
|
||||
this.fixOffHand(player, new ItemStack(Material.AIR));
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onBlockPlace(final BlockPlaceEvent event) {
|
||||
if (event.getHand() != EquipmentSlot.OFF_HAND) {
|
||||
return;
|
||||
}
|
||||
final ItemStack itemStack = event.getItemInHand();
|
||||
|
||||
if (itemStack.getAmount() > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.fixOffHand(event.getPlayer(), new ItemStack(Material.AIR));
|
||||
}
|
||||
|
||||
// @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
// public void onShiftInventoryClick(final InventoryClickEvent event) {
|
||||
// final ClickType clickType = event.getClick();
|
||||
// if (clickType != ClickType.SHIFT_LEFT && clickType != ClickType.SHIFT_RIGHT) return;
|
||||
// final ItemStack clicked = event.getCurrentItem();
|
||||
// if (clicked == null || clicked.getType() == Material.AIR) return;
|
||||
// final EquipmentSlot slot = this.getArmorSlot(clicked.getType());
|
||||
// if (slot == null) return;
|
||||
// if (!(event.getWhoClicked() instanceof final Player player)) return;
|
||||
// final EntityEquipment entityEquipment = player.getEquipment();
|
||||
// if (entityEquipment == null) return;
|
||||
// final Equipment equipment = Equipment.fromEntityEquipment(entityEquipment);
|
||||
// final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
// if (optionalUser.isEmpty()) return;
|
||||
// final User user = optionalUser.get();
|
||||
// player.sendMessage("Sent update packet in listener");
|
||||
// final var itemList = this.getItemList(user, equipment, Collections.emptySet());
|
||||
// this.taskManager.submit(() -> this.userManager.sendUpdatePacket(
|
||||
// player.getEntityId(),
|
||||
// player,
|
||||
// itemList
|
||||
// ));
|
||||
// }
|
||||
|
||||
private void fixOffHand(final Player player, final ItemStack current) {
|
||||
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
if (optionalUser.isEmpty()) return;
|
||||
final User user = optionalUser.get();
|
||||
final ArmorItem.Type type = ArmorItem.Type.OFF_HAND;
|
||||
final ArmorItem armorItem = user.getPlayerArmor().getItem(type);
|
||||
this.taskManager.submit(new DelayedTask(() -> this.userManager.sendUpdatePacket(
|
||||
user,
|
||||
armorItem,
|
||||
current,
|
||||
type
|
||||
), 1));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private EquipmentSlot getArmorSlot(final Material material) {
|
||||
for (final EquipmentSlot slot : EquipmentSlot.values()) {
|
||||
final Set<Material> armorItems = ARMOR_ITEMS.get(slot);
|
||||
if (armorItems == null) continue;
|
||||
if (material == null) continue;
|
||||
if (armorItems.contains(material)) return slot;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/*
|
||||
private void fixCosmetics(final Player player) {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(this.plugin,
|
||||
() -> this.userManager.updateCosmetics(player.getUniqueId()), 2);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package io.github.fisher2911.hmccosmetics.listener;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
|
||||
import io.github.fisher2911.hmccosmetics.database.Database;
|
||||
import io.github.fisher2911.hmccosmetics.task.TaskChain;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class JoinListener implements Listener {
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final Database database;
|
||||
private final UserManager userManager;
|
||||
|
||||
public JoinListener(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.database = this.plugin.getDatabase();
|
||||
this.userManager = this.plugin.getUserManager();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(final PlayerJoinEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
this.database.loadUser(
|
||||
player,
|
||||
user -> new TaskChain(this.plugin).chain(
|
||||
() -> this.userManager.add(user)
|
||||
).chain(() -> {
|
||||
final WardrobeSettings settings = this.plugin.getSettings().getWardrobeSettings();
|
||||
if (settings.isAlwaysDisplay() && settings.getWardrobeLocation() != null) {
|
||||
final Wardrobe wardrobe = user.getWardrobe();
|
||||
wardrobe.setCurrentLocation(settings.getWardrobeLocation());
|
||||
wardrobe.spawnFakePlayer(player);
|
||||
}
|
||||
// and finally, resend the cosmetics
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(HMCCosmetics.getPlugin(HMCCosmetics.class),
|
||||
() -> {
|
||||
this.userManager.updateCosmetics(user);
|
||||
}, 20);
|
||||
}, true).execute());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(final PlayerQuitEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
optionalUser.ifPresent(user -> {
|
||||
final Wardrobe wardrobe = user.getWardrobe();
|
||||
|
||||
user.despawnAttached();
|
||||
user.despawnBalloon();
|
||||
|
||||
if (wardrobe.isActive()) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(
|
||||
this.plugin,
|
||||
() -> wardrobe.despawnFakePlayer(player, userManager)
|
||||
);
|
||||
}
|
||||
});
|
||||
this.userManager.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package io.github.fisher2911.hmccosmetics.listener;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.message.Messages;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerToggleSneakEvent;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PlayerShiftListener implements Listener {
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final UserManager userManager;
|
||||
|
||||
public PlayerShiftListener(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.userManager = this.plugin.getUserManager();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerShift(final PlayerToggleSneakEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final Optional<User> userOptional = this.userManager.get(player.getUniqueId());
|
||||
|
||||
if (!event.isSneaking()) return;
|
||||
|
||||
if (userOptional.isEmpty()) return;
|
||||
|
||||
final User user = userOptional.get();
|
||||
final Wardrobe wardrobe = user.getWardrobe();
|
||||
|
||||
if (!wardrobe.isActive()) return;
|
||||
|
||||
wardrobe.despawnFakePlayer(player, userManager);
|
||||
this.plugin.getSettings().getWardrobeSettings().playCloseSound(player);
|
||||
this.plugin.getMessageHandler().sendMessage(
|
||||
player,
|
||||
Messages.CLOSED_WARDROBE
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,11 @@ public class RespawnListener implements Listener {
|
||||
Bukkit.getScheduler().runTaskLater(this.plugin, () -> {
|
||||
final Player player = event.getPlayer();
|
||||
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
|
||||
|
||||
optionalUser.ifPresent(user -> user.setHat(user.getPlayerArmor().getHat(), this.userManager));
|
||||
optionalUser.ifPresent(user -> {
|
||||
user.despawnAttached();
|
||||
this.userManager.updateCosmetics(user);
|
||||
});
|
||||
}, 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package io.github.fisher2911.hmccosmetics.listener;
|
||||
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.user.User;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
public class TeleportListener implements Listener {
|
||||
@@ -23,7 +23,20 @@ public class TeleportListener implements Listener {
|
||||
public void onPlayerTeleport(final PlayerTeleportEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
|
||||
this.userManager.get(player.getUniqueId()).ifPresent(User::despawnAttached);
|
||||
this.userManager.get(player.getUniqueId()).ifPresent(user -> {
|
||||
user.despawnAttached();
|
||||
user.despawnBalloon();
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onPlayerDeath(final PlayerDeathEvent event) {
|
||||
final Player player = event.getEntity();
|
||||
|
||||
this.userManager.get(player.getUniqueId()).ifPresent(user -> {
|
||||
user.despawnAttached();
|
||||
user.despawnBalloon();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package io.github.fisher2911.hmccosmetics.listener;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
|
||||
import io.github.fisher2911.hmccosmetics.user.UserManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
||||
public class WardrobeListener implements Listener {
|
||||
|
||||
private final HMCCosmetics plugin;
|
||||
private final UserManager userManager;
|
||||
|
||||
public WardrobeListener(final HMCCosmetics plugin) {
|
||||
this.plugin = plugin;
|
||||
this.userManager = this.plugin.getUserManager();
|
||||
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmetics.getPlugin(HMCCosmetics.class), ListenerPriority.NORMAL, PacketType.Play.Client.ARM_ANIMATION) {
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent event) {
|
||||
if (!(event.getPlayer() instanceof Player)) return;
|
||||
Player player = event.getPlayer();
|
||||
WardrobeListener.this.userManager.get(player.getUniqueId()).ifPresent(user -> {
|
||||
if (!user.getWardrobe().isActive()) return;
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
WardrobeListener.this.plugin.getCosmeticsMenu().openDefault(player);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDamage(final EntityDamageEvent event) {
|
||||
if (!(event.getEntity() instanceof final Player player)) return;
|
||||
this.userManager.get(player.getUniqueId()).ifPresent(user -> {
|
||||
if (user.isWardrobeActive()) event.setCancelled(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user